@productmaker/mcp 7.2.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/http.js +826 -690
- package/dist/stdio.js +815 -679
- package/package.json +3 -3
package/dist/stdio.js
CHANGED
|
@@ -3631,11 +3631,12 @@ var FreeformLandingConfigSchema = z21.object({
|
|
|
3631
3631
|
showVariantPicker: z21.boolean().optional(),
|
|
3632
3632
|
/**
|
|
3633
3633
|
* Suppress the native Shopify buy form (the `BUY_FORM_MARKER` block). The page
|
|
3634
|
-
* CTAs already carry `data-cl-buy-trigger` → they open the
|
|
3635
|
-
* so on
|
|
3636
|
-
*
|
|
3637
|
-
*
|
|
3638
|
-
* (backward compatible with
|
|
3634
|
+
* CTAs already carry `data-cl-buy-trigger` → they open the installed COD
|
|
3635
|
+
* provider's popup (Releasit or EasySell), so on COD-provider stores the
|
|
3636
|
+
* native add-to-cart form is a redundant second buy path (it rendered as a
|
|
3637
|
+
* bare "price + Comprar" block). When true the assembler omits the marker
|
|
3638
|
+
* entirely. Undefined/false = keep the native form (backward compatible with
|
|
3639
|
+
* already-assembled configs).
|
|
3639
3640
|
*/
|
|
3640
3641
|
hideNativeBuyForm: z21.boolean().optional()
|
|
3641
3642
|
});
|
|
@@ -5423,6 +5424,17 @@ var CodeLandingThemeSetupResponse = z28.discriminatedUnion("status", [
|
|
|
5423
5424
|
themeEditorDeepLink: z28.string().url(),
|
|
5424
5425
|
shopDomain: z28.string()
|
|
5425
5426
|
}),
|
|
5427
|
+
z28.object({
|
|
5428
|
+
/**
|
|
5429
|
+
* The block is missing and the store has NO products yet. Shopify's theme
|
|
5430
|
+
* editor cannot add an app block to a product template with nothing to
|
|
5431
|
+
* preview (it answers "there is a problem with the app block"), so there
|
|
5432
|
+
* is deliberately no deep link: the seller publishes first, and the
|
|
5433
|
+
* publish response carries the link aimed at the product it created.
|
|
5434
|
+
*/
|
|
5435
|
+
status: z28.literal("setup_after_publish"),
|
|
5436
|
+
shopDomain: z28.string()
|
|
5437
|
+
}),
|
|
5426
5438
|
z28.object({
|
|
5427
5439
|
/** Not a code-landing task — the gate does not apply. */
|
|
5428
5440
|
status: z28.literal("not_applicable"),
|
|
@@ -6925,7 +6937,10 @@ var ChatParseEstimationOptions = z34.object({}).strict();
|
|
|
6925
6937
|
var CodeLandingEditEstimationOptions = z34.object({}).strict();
|
|
6926
6938
|
var ServiceCreativeEstimationOptions = z34.object({
|
|
6927
6939
|
mediaAssetCount: z34.number().int().min(0).max(8).optional(),
|
|
6928
|
-
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional()
|
|
6940
|
+
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
|
|
6941
|
+
/** Quality the panels render at (its registry model sets the per-second
|
|
6942
|
+
* price). Absent = economy, the pre-quality service default. */
|
|
6943
|
+
videoQuality: VideoQuality.optional()
|
|
6929
6944
|
});
|
|
6930
6945
|
var ActorGridEstimationOptions = z34.object({}).strict();
|
|
6931
6946
|
var CostEstimationRequest = z34.discriminatedUnion("type", [
|
|
@@ -7695,7 +7710,18 @@ var KIE_SUBMIT_IMAGE_TASK_TARGETS = [
|
|
|
7695
7710
|
"rapid_master_anchor",
|
|
7696
7711
|
"clean_product_image",
|
|
7697
7712
|
"single_call_anchor",
|
|
7698
|
-
"product_view_reference"
|
|
7713
|
+
"product_view_reference",
|
|
7714
|
+
// Generated service-video presenter (text-to-image portrait). Task-owned, so
|
|
7715
|
+
// it lives here and not beside `actor_candidate`; it mirrors that target's
|
|
7716
|
+
// model, resolution and recovery policy. The fan-in resumes the service init
|
|
7717
|
+
// (`dispatchServiceActor`, refKey prefix `service_actor:`).
|
|
7718
|
+
"service_actor",
|
|
7719
|
+
// First frame of a generated service B-roll panel: image-to-image from the
|
|
7720
|
+
// service photo the planner cited, cleaned of overlaid text/graphics and
|
|
7721
|
+
// fitted to the shot. Mirrors `rapid_panel`'s model tier and recovery
|
|
7722
|
+
// policy. The same fan-in waits for the whole expected image set
|
|
7723
|
+
// (`dispatchServiceActor`, refKey prefix `service_broll_anchor:`).
|
|
7724
|
+
"service_broll_anchor"
|
|
7699
7725
|
];
|
|
7700
7726
|
var ACTOR_CANDIDATE_TARGET = "actor_candidate";
|
|
7701
7727
|
var ANY_KIE_SUBMIT_IMAGE_TARGETS = [
|
|
@@ -9617,6 +9643,12 @@ var DEFAULT_PRICING = {
|
|
|
9617
9643
|
ourCostCents: 0.01,
|
|
9618
9644
|
userPriceCents: 0.02
|
|
9619
9645
|
},
|
|
9646
|
+
// Service reels harvested from the business's own public profile (per second,
|
|
9647
|
+
// same Whisper-1 rate). Separate action so the ledger names the source.
|
|
9648
|
+
"openai:service-social-transcribe": {
|
|
9649
|
+
ourCostCents: 0.01,
|
|
9650
|
+
userPriceCents: 0.02
|
|
9651
|
+
},
|
|
9620
9652
|
// User-uploaded service reference/competitor analysis (per second, same Whisper-1 rate).
|
|
9621
9653
|
// This is a separate action because its ledger entries identify the analysis source.
|
|
9622
9654
|
"openai:service-reference-transcribe": {
|
|
@@ -10756,6 +10788,11 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
|
|
|
10756
10788
|
])
|
|
10757
10789
|
]);
|
|
10758
10790
|
|
|
10791
|
+
// ../../packages/types/src/seller-prohibitions.ts
|
|
10792
|
+
var MARKER = String.raw`(?:no|nunca|jam[aá]s|prohibido|evita[r]?)(?:\s*:)?\s`;
|
|
10793
|
+
var PROHIBITION_AT_START = new RegExp(String.raw`^(?:[-•*]\s*)?(${MARKER}[\s\S]*)$`, "iu");
|
|
10794
|
+
var PROHIBITION_AFTER_LABEL = new RegExp(String.raw`^(?:[-•*]\s*)?[^:.!?\n]{1,40}:\s*(${MARKER}[\s\S]*)$`, "iu");
|
|
10795
|
+
|
|
10759
10796
|
// ../../packages/types/src/task-type.ts
|
|
10760
10797
|
import { z as z50 } from "zod";
|
|
10761
10798
|
var TaskTypeSchema = z50.enum([
|
|
@@ -13337,7 +13374,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13337
13374
|
"task",
|
|
13338
13375
|
"product"
|
|
13339
13376
|
]),
|
|
13340
|
-
defineCapability("create_service_video", "
|
|
13377
|
+
defineCapability("create_service_video", "863884c1af5de3e168cbbe825ea3961901c84dae1899ca400f8f7fa01df91c0a", "credit_consuming", "creative", [
|
|
13341
13378
|
"credit_consuming",
|
|
13342
13379
|
"state_change"
|
|
13343
13380
|
], [
|
|
@@ -13361,7 +13398,11 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13361
13398
|
]),
|
|
13362
13399
|
slot("video_preset", false, [
|
|
13363
13400
|
"videoPreset"
|
|
13364
|
-
])
|
|
13401
|
+
]),
|
|
13402
|
+
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
13403
|
+
slot("video_quality", false, [
|
|
13404
|
+
"videoQuality"
|
|
13405
|
+
], [])
|
|
13365
13406
|
], [
|
|
13366
13407
|
"service_context"
|
|
13367
13408
|
], [
|
|
@@ -14155,7 +14196,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14155
14196
|
], [
|
|
14156
14197
|
"meta_upload_session"
|
|
14157
14198
|
], WHATSAPP_ONLY_CHANNEL_EXPOSURE),
|
|
14158
|
-
defineCapability("request_media_upload", "
|
|
14199
|
+
defineCapability("request_media_upload", "9a50a4647c61f97fb12bbb9b25f7660f392e3cd9825151735cd66292058882ea", "none", "creative", [
|
|
14159
14200
|
"state_change"
|
|
14160
14201
|
], [
|
|
14161
14202
|
slot("media_kind", true, [
|
|
@@ -14900,6 +14941,81 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
14900
14941
|
}
|
|
14901
14942
|
});
|
|
14902
14943
|
|
|
14944
|
+
// ../../packages/types/src/flight-recorder.ts
|
|
14945
|
+
import { z as z68 } from "zod";
|
|
14946
|
+
var FlightRecorderGenerationTypeSchema = z68.enum([
|
|
14947
|
+
"initial",
|
|
14948
|
+
"regeneration",
|
|
14949
|
+
"edit",
|
|
14950
|
+
"retry"
|
|
14951
|
+
]);
|
|
14952
|
+
var FlightRecorderProviderSchema = z68.enum([
|
|
14953
|
+
"kie",
|
|
14954
|
+
"fal"
|
|
14955
|
+
]);
|
|
14956
|
+
var FlightRecorderElementSchema = z68.object({
|
|
14957
|
+
name: z68.string().optional(),
|
|
14958
|
+
description: z68.string().optional(),
|
|
14959
|
+
frontalImageUrl: z68.string().optional(),
|
|
14960
|
+
referenceImageUrls: z68.array(z68.string()).optional(),
|
|
14961
|
+
videoUrl: z68.string().optional()
|
|
14962
|
+
});
|
|
14963
|
+
var FlightRecorderDistillationSchema = z68.object({
|
|
14964
|
+
actorGender: z68.enum([
|
|
14965
|
+
"female",
|
|
14966
|
+
"male",
|
|
14967
|
+
"mixed"
|
|
14968
|
+
]).or(z68.string()).optional(),
|
|
14969
|
+
voiceId: z68.string().optional(),
|
|
14970
|
+
cameraMotion: z68.string().optional()
|
|
14971
|
+
}).catchall(z68.unknown());
|
|
14972
|
+
var FlightRecorderEntrySchema = z68.object({
|
|
14973
|
+
schemaVersion: z68.literal(1).optional(),
|
|
14974
|
+
id: z68.string().min(1),
|
|
14975
|
+
taskId: z68.string().min(1),
|
|
14976
|
+
runId: z68.string().min(1),
|
|
14977
|
+
sequence: z68.number().int().nonnegative(),
|
|
14978
|
+
timestamp: z68.string().min(1),
|
|
14979
|
+
provider: FlightRecorderProviderSchema.or(z68.string()),
|
|
14980
|
+
model: z68.string().min(1),
|
|
14981
|
+
prompt: z68.string(),
|
|
14982
|
+
durationSeconds: z68.number().nonnegative(),
|
|
14983
|
+
aspectRatio: z68.string().optional(),
|
|
14984
|
+
resolution: z68.string().optional(),
|
|
14985
|
+
startImageUrl: z68.string().optional(),
|
|
14986
|
+
endImageUrl: z68.string().optional(),
|
|
14987
|
+
generateAudio: z68.boolean().optional(),
|
|
14988
|
+
// Correlation & pipeline metadata
|
|
14989
|
+
angleKey: z68.string().optional(),
|
|
14990
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
14991
|
+
generationType: FlightRecorderGenerationTypeSchema,
|
|
14992
|
+
operationId: z68.string().min(1).optional(),
|
|
14993
|
+
revisionId: z68.string().min(1).optional(),
|
|
14994
|
+
attemptNumber: z68.number().int().nonnegative().default(1),
|
|
14995
|
+
// Elements & Distillation
|
|
14996
|
+
elements: z68.array(FlightRecorderElementSchema).optional(),
|
|
14997
|
+
distillation: FlightRecorderDistillationSchema.optional(),
|
|
14998
|
+
// Raw payload (sanitized of secrets)
|
|
14999
|
+
rawPayload: z68.record(z68.unknown())
|
|
15000
|
+
});
|
|
15001
|
+
var FlightRecorderQuerySchema = z68.object({
|
|
15002
|
+
taskId: z68.string().min(1),
|
|
15003
|
+
runId: z68.string().optional(),
|
|
15004
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
15005
|
+
angleKey: z68.string().optional(),
|
|
15006
|
+
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15007
|
+
cursor: z68.number().int().nonnegative().optional(),
|
|
15008
|
+
limit: z68.number().int().positive().optional()
|
|
15009
|
+
});
|
|
15010
|
+
var FlightRecorderResponseSchema = z68.object({
|
|
15011
|
+
taskId: z68.string().min(1),
|
|
15012
|
+
runId: z68.string().min(1),
|
|
15013
|
+
entries: z68.array(FlightRecorderEntrySchema),
|
|
15014
|
+
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15015
|
+
count: z68.number().int().nonnegative(),
|
|
15016
|
+
nextCursor: z68.number().int().nonnegative().nullable()
|
|
15017
|
+
});
|
|
15018
|
+
|
|
14903
15019
|
// src/response-body.ts
|
|
14904
15020
|
var ResponseBodyTooLargeError = class extends Error {
|
|
14905
15021
|
static {
|
|
@@ -15139,7 +15255,7 @@ var ApiClient = class {
|
|
|
15139
15255
|
};
|
|
15140
15256
|
|
|
15141
15257
|
// src/index.ts
|
|
15142
|
-
var MCP_VERSION = "
|
|
15258
|
+
var MCP_VERSION = "8.0.0";
|
|
15143
15259
|
|
|
15144
15260
|
// src/meta-upload-app.ts
|
|
15145
15261
|
import { readFileSync } from "fs";
|
|
@@ -15211,7 +15327,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
15211
15327
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
15212
15328
|
|
|
15213
15329
|
// src/tools/tasks.ts
|
|
15214
|
-
import { z as
|
|
15330
|
+
import { z as z72 } from "zod";
|
|
15215
15331
|
|
|
15216
15332
|
// src/resolve-image.ts
|
|
15217
15333
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -15772,10 +15888,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
15772
15888
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
15773
15889
|
|
|
15774
15890
|
// src/tools/shared.ts
|
|
15775
|
-
import { z as
|
|
15776
|
-
var Lang =
|
|
15777
|
-
var Country =
|
|
15778
|
-
var LandingStrategyEnum =
|
|
15891
|
+
import { z as z69 } from "zod";
|
|
15892
|
+
var Lang = z69.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);
|
|
15893
|
+
var Country = z69.string().min(2).max(3);
|
|
15894
|
+
var LandingStrategyEnum = z69.enum([
|
|
15779
15895
|
"auto",
|
|
15780
15896
|
"classic",
|
|
15781
15897
|
"pain_solution",
|
|
@@ -15784,12 +15900,12 @@ var LandingStrategyEnum = z68.enum([
|
|
|
15784
15900
|
"offer_value",
|
|
15785
15901
|
"lifestyle_identity"
|
|
15786
15902
|
]);
|
|
15787
|
-
var LandingImageFormatEnum =
|
|
15903
|
+
var LandingImageFormatEnum = z69.enum([
|
|
15788
15904
|
"9:16",
|
|
15789
15905
|
"4:5",
|
|
15790
15906
|
"1:1"
|
|
15791
15907
|
]);
|
|
15792
|
-
var VideoPresetEnum =
|
|
15908
|
+
var VideoPresetEnum = z69.enum([
|
|
15793
15909
|
"auto",
|
|
15794
15910
|
"ugc_dynamic",
|
|
15795
15911
|
"ugc_how_to",
|
|
@@ -15802,21 +15918,21 @@ var VideoPresetEnum = z68.enum([
|
|
|
15802
15918
|
"pixar_problem",
|
|
15803
15919
|
"pixar_sassy"
|
|
15804
15920
|
]);
|
|
15805
|
-
var VideoStructureEnum =
|
|
15921
|
+
var VideoStructureEnum = z69.enum([
|
|
15806
15922
|
"single_take",
|
|
15807
15923
|
"multi_scene"
|
|
15808
15924
|
]);
|
|
15809
|
-
var VideoQualityEnum =
|
|
15925
|
+
var VideoQualityEnum = z69.enum([
|
|
15810
15926
|
"economy",
|
|
15811
15927
|
"medium",
|
|
15812
15928
|
"pro"
|
|
15813
15929
|
]);
|
|
15814
|
-
var VideoRouteIdEnum =
|
|
15930
|
+
var VideoRouteIdEnum = z69.enum([
|
|
15815
15931
|
"single_take",
|
|
15816
15932
|
"multi_scene",
|
|
15817
15933
|
"free"
|
|
15818
15934
|
]);
|
|
15819
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
15935
|
+
var TaskCreativeVariantVideoPresetEnum = z69.enum([
|
|
15820
15936
|
"auto",
|
|
15821
15937
|
"ugc_dynamic",
|
|
15822
15938
|
"ugc_how_to",
|
|
@@ -15887,7 +16003,7 @@ function resolveVideoPreset(preset) {
|
|
|
15887
16003
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
15888
16004
|
}
|
|
15889
16005
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
15890
|
-
var VideoTierEnum =
|
|
16006
|
+
var VideoTierEnum = z69.enum([
|
|
15891
16007
|
"basic"
|
|
15892
16008
|
]);
|
|
15893
16009
|
function resolveVideoTier(_tier) {
|
|
@@ -15927,22 +16043,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
15927
16043
|
}
|
|
15928
16044
|
}
|
|
15929
16045
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
15930
|
-
var VideoResolutionEnum =
|
|
16046
|
+
var VideoResolutionEnum = z69.enum([
|
|
15931
16047
|
"480p",
|
|
15932
16048
|
"720p"
|
|
15933
16049
|
]);
|
|
15934
|
-
var CreativeGenderEnum =
|
|
16050
|
+
var CreativeGenderEnum = z69.enum([
|
|
15935
16051
|
"female",
|
|
15936
16052
|
"male",
|
|
15937
16053
|
"mixed"
|
|
15938
16054
|
]);
|
|
15939
|
-
var VideoStyleEnum =
|
|
16055
|
+
var VideoStyleEnum = z69.enum([
|
|
15940
16056
|
"ugc",
|
|
15941
16057
|
"cartoon_3d",
|
|
15942
16058
|
"product_only",
|
|
15943
16059
|
"ai_dynamic"
|
|
15944
16060
|
]);
|
|
15945
|
-
var NarrativeStyleEnum =
|
|
16061
|
+
var NarrativeStyleEnum = z69.enum([
|
|
15946
16062
|
"review",
|
|
15947
16063
|
"ugc_how_to",
|
|
15948
16064
|
"problem_product_cta",
|
|
@@ -15960,7 +16076,7 @@ var NarrativeStyleEnum = z68.enum([
|
|
|
15960
16076
|
"ugc_demo_review",
|
|
15961
16077
|
"market"
|
|
15962
16078
|
]);
|
|
15963
|
-
var PublicNarrativeStyleEnum =
|
|
16079
|
+
var PublicNarrativeStyleEnum = z69.enum([
|
|
15964
16080
|
"review",
|
|
15965
16081
|
"ugc_how_to",
|
|
15966
16082
|
"ugc_unboxing_chaos",
|
|
@@ -15973,7 +16089,7 @@ var PublicNarrativeStyleEnum = z68.enum([
|
|
|
15973
16089
|
"sassy_product_pixar",
|
|
15974
16090
|
"market"
|
|
15975
16091
|
]);
|
|
15976
|
-
var VideoModelEnum =
|
|
16092
|
+
var VideoModelEnum = z69.enum([
|
|
15977
16093
|
"veo",
|
|
15978
16094
|
"wan",
|
|
15979
16095
|
"bytedance",
|
|
@@ -15981,29 +16097,29 @@ var VideoModelEnum = z68.enum([
|
|
|
15981
16097
|
"grok",
|
|
15982
16098
|
"kling"
|
|
15983
16099
|
]);
|
|
15984
|
-
var ProductReferenceUserChoiceEnum =
|
|
16100
|
+
var ProductReferenceUserChoiceEnum = z69.enum([
|
|
15985
16101
|
"same_product",
|
|
15986
16102
|
"variants",
|
|
15987
16103
|
"different_products",
|
|
15988
16104
|
"combo_distinct"
|
|
15989
16105
|
]);
|
|
15990
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
16106
|
+
var ProductReferenceCandidateGroupingEnum = z69.enum([
|
|
15991
16107
|
"same_product_same_variant",
|
|
15992
16108
|
"same_product_different_variants",
|
|
15993
16109
|
"different_products",
|
|
15994
16110
|
"unclear"
|
|
15995
16111
|
]);
|
|
15996
|
-
var ProductReferenceScopeEnum =
|
|
16112
|
+
var ProductReferenceScopeEnum = z69.enum([
|
|
15997
16113
|
"base",
|
|
15998
16114
|
"video_view_pack"
|
|
15999
16115
|
]);
|
|
16000
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
16116
|
+
var ProductReferenceResolutionDecisionEnum = z69.enum([
|
|
16001
16117
|
"approve",
|
|
16002
16118
|
"reject",
|
|
16003
16119
|
"observed_only",
|
|
16004
16120
|
"correct_view"
|
|
16005
16121
|
]);
|
|
16006
|
-
var ProductReferenceRejectionReasonEnum =
|
|
16122
|
+
var ProductReferenceRejectionReasonEnum = z69.enum([
|
|
16007
16123
|
"replacement_requested",
|
|
16008
16124
|
"wrong_product_identity",
|
|
16009
16125
|
"wrong_variant",
|
|
@@ -16014,13 +16130,13 @@ var ProductReferenceRejectionReasonEnum = z68.enum([
|
|
|
16014
16130
|
"not_a_product_photo",
|
|
16015
16131
|
"other"
|
|
16016
16132
|
]);
|
|
16017
|
-
var GapDurationChoiceMirror =
|
|
16018
|
-
angleIndex:
|
|
16019
|
-
recommendedSec:
|
|
16020
|
-
|
|
16021
|
-
|
|
16133
|
+
var GapDurationChoiceMirror = z69.object({
|
|
16134
|
+
angleIndex: z69.number().int().nonnegative(),
|
|
16135
|
+
recommendedSec: z69.union([
|
|
16136
|
+
z69.literal(15),
|
|
16137
|
+
z69.literal(30)
|
|
16022
16138
|
]),
|
|
16023
|
-
estimatedDeltaCredits:
|
|
16139
|
+
estimatedDeltaCredits: z69.number().int().nonnegative().optional()
|
|
16024
16140
|
});
|
|
16025
16141
|
function buildSelectedImageUrlsHash(urls) {
|
|
16026
16142
|
const input = [
|
|
@@ -16030,13 +16146,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
16030
16146
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
16031
16147
|
}
|
|
16032
16148
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
16033
|
-
var ImageCreativeStyleEnum =
|
|
16149
|
+
var ImageCreativeStyleEnum = z69.enum([
|
|
16034
16150
|
"studio",
|
|
16035
16151
|
"floating",
|
|
16036
16152
|
"ingredients",
|
|
16037
16153
|
"in_use"
|
|
16038
16154
|
]);
|
|
16039
|
-
var ImageCreativeArchetypeEnum =
|
|
16155
|
+
var ImageCreativeArchetypeEnum = z69.enum([
|
|
16040
16156
|
"direct_response_product_ad",
|
|
16041
16157
|
"hero_outcome",
|
|
16042
16158
|
"offer_value_prop",
|
|
@@ -16045,20 +16161,20 @@ var ImageCreativeArchetypeEnum = z68.enum([
|
|
|
16045
16161
|
"problem_solution",
|
|
16046
16162
|
"lifestyle_identity"
|
|
16047
16163
|
]);
|
|
16048
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
16164
|
+
var ImageCreativeVisualTreatmentEnum = z69.enum([
|
|
16049
16165
|
"performance_product_ad",
|
|
16050
16166
|
"premium_dtc_carousel"
|
|
16051
16167
|
]);
|
|
16052
|
-
var ImageCreativeAspectRatioEnum =
|
|
16168
|
+
var ImageCreativeAspectRatioEnum = z69.enum([
|
|
16053
16169
|
"1:1",
|
|
16054
16170
|
"4:5",
|
|
16055
16171
|
"9:16",
|
|
16056
16172
|
"16:9"
|
|
16057
16173
|
]);
|
|
16058
|
-
var ImageRefSchema =
|
|
16059
|
-
url:
|
|
16060
|
-
path:
|
|
16061
|
-
assetId:
|
|
16174
|
+
var ImageRefSchema = z69.object({
|
|
16175
|
+
url: z69.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.'),
|
|
16176
|
+
path: z69.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`.'),
|
|
16177
|
+
assetId: z69.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.")
|
|
16062
16178
|
}).refine((v) => [
|
|
16063
16179
|
v.url,
|
|
16064
16180
|
v.path,
|
|
@@ -16066,11 +16182,11 @@ var ImageRefSchema = z68.object({
|
|
|
16066
16182
|
].filter(Boolean).length === 1, {
|
|
16067
16183
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
16068
16184
|
});
|
|
16069
|
-
var ImagesInput =
|
|
16185
|
+
var ImagesInput = z69.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
16070
16186
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
16071
16187
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
16072
16188
|
ctx.addIssue({
|
|
16073
|
-
code:
|
|
16189
|
+
code: z69.ZodIssueCode.custom,
|
|
16074
16190
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
16075
16191
|
});
|
|
16076
16192
|
}
|
|
@@ -16138,14 +16254,14 @@ async function submitCreative(api, opts) {
|
|
|
16138
16254
|
});
|
|
16139
16255
|
}
|
|
16140
16256
|
__name(submitCreative, "submitCreative");
|
|
16141
|
-
var ResearchTargetCountryEnum =
|
|
16257
|
+
var ResearchTargetCountryEnum = z69.enum([
|
|
16142
16258
|
"CO",
|
|
16143
16259
|
"MX",
|
|
16144
16260
|
"PE",
|
|
16145
16261
|
"EC",
|
|
16146
16262
|
"CL"
|
|
16147
16263
|
]);
|
|
16148
|
-
var ResearchCategoryEnum =
|
|
16264
|
+
var ResearchCategoryEnum = z69.enum([
|
|
16149
16265
|
"auto",
|
|
16150
16266
|
"automotive",
|
|
16151
16267
|
"kitchen",
|
|
@@ -16170,7 +16286,7 @@ var READS_EXTERNAL = {
|
|
|
16170
16286
|
readOnlyHint: true,
|
|
16171
16287
|
destructiveHint: false,
|
|
16172
16288
|
idempotentHint: true,
|
|
16173
|
-
openWorldHint:
|
|
16289
|
+
openWorldHint: false
|
|
16174
16290
|
};
|
|
16175
16291
|
var CREATES_INTERNAL = {
|
|
16176
16292
|
readOnlyHint: false,
|
|
@@ -16179,6 +16295,24 @@ var CREATES_INTERNAL = {
|
|
|
16179
16295
|
openWorldHint: false
|
|
16180
16296
|
};
|
|
16181
16297
|
var CREATES_EXTERNAL = {
|
|
16298
|
+
readOnlyHint: false,
|
|
16299
|
+
destructiveHint: false,
|
|
16300
|
+
idempotentHint: false,
|
|
16301
|
+
openWorldHint: false
|
|
16302
|
+
};
|
|
16303
|
+
var CREATES_PAID = {
|
|
16304
|
+
readOnlyHint: false,
|
|
16305
|
+
destructiveHint: true,
|
|
16306
|
+
idempotentHint: false,
|
|
16307
|
+
openWorldHint: false
|
|
16308
|
+
};
|
|
16309
|
+
var CREATES_PAID_OPEN_WORLD = {
|
|
16310
|
+
readOnlyHint: false,
|
|
16311
|
+
destructiveHint: true,
|
|
16312
|
+
idempotentHint: false,
|
|
16313
|
+
openWorldHint: true
|
|
16314
|
+
};
|
|
16315
|
+
var CREATES_OPEN_WORLD = {
|
|
16182
16316
|
readOnlyHint: false,
|
|
16183
16317
|
destructiveHint: false,
|
|
16184
16318
|
idempotentHint: false,
|
|
@@ -16194,9 +16328,9 @@ var OVERWRITES_EXTERNAL = {
|
|
|
16194
16328
|
readOnlyHint: false,
|
|
16195
16329
|
destructiveHint: true,
|
|
16196
16330
|
idempotentHint: false,
|
|
16197
|
-
openWorldHint:
|
|
16331
|
+
openWorldHint: false
|
|
16198
16332
|
};
|
|
16199
|
-
var DailyControlStatusEnum =
|
|
16333
|
+
var DailyControlStatusEnum = z69.enum([
|
|
16200
16334
|
"ok",
|
|
16201
16335
|
"sales_unavailable",
|
|
16202
16336
|
"timezone_unavailable",
|
|
@@ -16209,19 +16343,19 @@ var DailyControlStatusEnum = z68.enum([
|
|
|
16209
16343
|
"product_missing",
|
|
16210
16344
|
"store_unreachable"
|
|
16211
16345
|
]);
|
|
16212
|
-
var DailyControlLightEnum =
|
|
16346
|
+
var DailyControlLightEnum = z69.enum([
|
|
16213
16347
|
"green",
|
|
16214
16348
|
"amber",
|
|
16215
16349
|
"red",
|
|
16216
16350
|
"none"
|
|
16217
16351
|
]);
|
|
16218
|
-
var DailyControlVerdictEnum =
|
|
16352
|
+
var DailyControlVerdictEnum = z69.enum([
|
|
16219
16353
|
"scale",
|
|
16220
16354
|
"hold",
|
|
16221
16355
|
"kill",
|
|
16222
16356
|
"insufficient_sample"
|
|
16223
16357
|
]);
|
|
16224
|
-
var DailyControlSourceEnum =
|
|
16358
|
+
var DailyControlSourceEnum = z69.enum([
|
|
16225
16359
|
"shopify",
|
|
16226
16360
|
"shopify_settling",
|
|
16227
16361
|
"user",
|
|
@@ -17362,29 +17496,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
17362
17496
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
17363
17497
|
|
|
17364
17498
|
// src/tools/media-presentation.ts
|
|
17365
|
-
import { z as
|
|
17366
|
-
var HttpsPresentationUrlSchema =
|
|
17499
|
+
import { z as z70 } from "zod";
|
|
17500
|
+
var HttpsPresentationUrlSchema = z70.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
17367
17501
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
17368
17502
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
17369
17503
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
17370
17504
|
}, "preview URL must be owned by ProductMaker");
|
|
17371
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
17372
|
-
var PresentationImageSchema =
|
|
17373
|
-
kind:
|
|
17505
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z70.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
17506
|
+
var PresentationImageSchema = z70.object({
|
|
17507
|
+
kind: z70.literal("image"),
|
|
17374
17508
|
url: HttpsPresentationUrlSchema,
|
|
17375
|
-
mimeType:
|
|
17509
|
+
mimeType: z70.enum([
|
|
17376
17510
|
"image/jpeg",
|
|
17377
17511
|
"image/png"
|
|
17378
17512
|
]),
|
|
17379
17513
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
17380
17514
|
width: positiveIntAtMost(16384),
|
|
17381
17515
|
height: positiveIntAtMost(16384),
|
|
17382
|
-
alt:
|
|
17516
|
+
alt: z70.string().trim().min(1).max(240)
|
|
17383
17517
|
}).strict();
|
|
17384
17518
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
17385
|
-
var GalleryImageSchema =
|
|
17519
|
+
var GalleryImageSchema = z70.object({
|
|
17386
17520
|
url: ProductMakerPreviewUrlSchema,
|
|
17387
|
-
alt:
|
|
17521
|
+
alt: z70.string().trim().min(1).max(240)
|
|
17388
17522
|
});
|
|
17389
17523
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
17390
17524
|
async function imageBlocks(image, transport) {
|
|
@@ -17534,10 +17668,10 @@ ${summary}`,
|
|
|
17534
17668
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
17535
17669
|
|
|
17536
17670
|
// src/tools/winning-product-image.ts
|
|
17537
|
-
import { z as
|
|
17538
|
-
var WinnerReferenceInput =
|
|
17539
|
-
runId:
|
|
17540
|
-
candidateSourceId:
|
|
17671
|
+
import { z as z71 } from "zod";
|
|
17672
|
+
var WinnerReferenceInput = z71.object({
|
|
17673
|
+
runId: z71.string().uuid(),
|
|
17674
|
+
candidateSourceId: z71.string().trim().min(1).max(160)
|
|
17541
17675
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
17542
17676
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
17543
17677
|
if (!winnerReference) return images;
|
|
@@ -17574,188 +17708,189 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
17574
17708
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
17575
17709
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
17576
17710
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
17577
|
-
var CreateProductTaskInput =
|
|
17711
|
+
var CreateProductTaskInput = z72.object({
|
|
17578
17712
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
17579
17713
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
17580
|
-
projectId:
|
|
17581
|
-
productUrl:
|
|
17714
|
+
projectId: z72.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
17715
|
+
productUrl: z72.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."),
|
|
17582
17716
|
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.'),
|
|
17583
17717
|
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.'),
|
|
17584
|
-
price:
|
|
17585
|
-
compareAtPrice:
|
|
17586
|
-
offer:
|
|
17587
|
-
paymentMethods:
|
|
17588
|
-
productContext:
|
|
17589
|
-
productLabel:
|
|
17718
|
+
price: z72.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.'),
|
|
17719
|
+
compareAtPrice: z72.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".'),
|
|
17720
|
+
offer: z72.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.'),
|
|
17721
|
+
paymentMethods: z72.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.'),
|
|
17722
|
+
productContext: z72.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."),
|
|
17723
|
+
productLabel: z72.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.'),
|
|
17590
17724
|
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena), excepto "problem_solution", que requiere 30s Multiescena. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
|
|
17591
|
-
durationSeconds:
|
|
17592
|
-
|
|
17593
|
-
|
|
17725
|
+
durationSeconds: z72.union([
|
|
17726
|
+
z72.literal(15),
|
|
17727
|
+
z72.literal(30)
|
|
17594
17728
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
17595
|
-
pauseForAngleReview:
|
|
17596
|
-
aiDecidesAll:
|
|
17729
|
+
pauseForAngleReview: z72.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."),
|
|
17730
|
+
aiDecidesAll: z72.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."),
|
|
17597
17731
|
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.'),
|
|
17598
17732
|
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.'),
|
|
17599
17733
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
17600
17734
|
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).'),
|
|
17601
|
-
videoAngleCount:
|
|
17735
|
+
videoAngleCount: z72.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."),
|
|
17602
17736
|
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.'),
|
|
17603
|
-
outputs:
|
|
17737
|
+
outputs: z72.array(z72.enum([
|
|
17604
17738
|
"landing",
|
|
17605
17739
|
"video",
|
|
17606
17740
|
"image"
|
|
17607
17741
|
])).min(2).max(3).optional().describe(`Opcional. Qu\xE9 outputs generar. Default: todos ["landing","video","image"]. Para 2 outputs: ["landing","image"] (sin video), ["video","image"] (sin landing), ["landing","video"] (sin imagen). ${createProductTaskSingleOutputDescription}`),
|
|
17608
|
-
competitorScanEnabled:
|
|
17609
|
-
replicateWinnerWhenFound:
|
|
17610
|
-
brandId:
|
|
17611
|
-
actorId:
|
|
17742
|
+
competitorScanEnabled: z72.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
|
|
17743
|
+
replicateWinnerWhenFound: z72.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."),
|
|
17744
|
+
brandId: z72.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."),
|
|
17745
|
+
actorId: z72.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."),
|
|
17612
17746
|
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.'),
|
|
17613
|
-
creativeDirection:
|
|
17614
|
-
headline:
|
|
17615
|
-
subheadline:
|
|
17747
|
+
creativeDirection: z72.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.'),
|
|
17748
|
+
headline: z72.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."),
|
|
17749
|
+
subheadline: z72.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."),
|
|
17616
17750
|
landingStrategy: LandingStrategyEnum.default("classic").describe('Opcional. Estructura de la landing cl\xE1sica cuando landing est\xE1 entre outputs: "classic" (estructura original probada y recomendada; default del primer rollout), "auto" (la IA decide; experimental), "pain_solution", "social_proof" (Landing Viral: UGC, WhatsApp, Instagram y evidencia social), "benefits_clarity", "offer_value" o "lifestyle_identity". Default "classic".'),
|
|
17617
17751
|
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".')
|
|
17618
17752
|
}).strict();
|
|
17619
|
-
var CreateServiceVideoInput =
|
|
17620
|
-
landingUrl:
|
|
17621
|
-
additionalContext:
|
|
17753
|
+
var CreateServiceVideoInput = z72.object({
|
|
17754
|
+
landingUrl: z72.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
17755
|
+
additionalContext: z72.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
17622
17756
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
17623
|
-
voiceId:
|
|
17624
|
-
brandId:
|
|
17625
|
-
reviewMode:
|
|
17757
|
+
voiceId: z72.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
|
|
17758
|
+
brandId: z72.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
17759
|
+
reviewMode: z72.enum([
|
|
17626
17760
|
"automatic",
|
|
17627
17761
|
"guided"
|
|
17628
17762
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
17629
|
-
videoPreset:
|
|
17763
|
+
videoPreset: z72.enum([
|
|
17630
17764
|
"auto",
|
|
17631
17765
|
"ugc_dynamic",
|
|
17632
17766
|
"ugc_how_to",
|
|
17633
17767
|
"cinematic",
|
|
17634
17768
|
"wild_card"
|
|
17635
|
-
]).default("auto")
|
|
17769
|
+
]).default("auto"),
|
|
17770
|
+
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
|
|
17636
17771
|
}).strict();
|
|
17637
|
-
var GetTaskStatusInput =
|
|
17638
|
-
taskId:
|
|
17639
|
-
waitSeconds:
|
|
17772
|
+
var GetTaskStatusInput = z72.object({
|
|
17773
|
+
taskId: z72.string().min(1),
|
|
17774
|
+
waitSeconds: z72.number().int().min(0).max(120).optional()
|
|
17640
17775
|
});
|
|
17641
|
-
var ListTasksInput =
|
|
17642
|
-
limit:
|
|
17643
|
-
offset:
|
|
17644
|
-
search:
|
|
17776
|
+
var ListTasksInput = z72.object({
|
|
17777
|
+
limit: z72.number().int().min(1).max(50).optional(),
|
|
17778
|
+
offset: z72.number().int().min(0).optional(),
|
|
17779
|
+
search: z72.string().optional()
|
|
17645
17780
|
});
|
|
17646
17781
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
17647
17782
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
17648
|
-
var EditTaskDraftInput =
|
|
17649
|
-
taskId:
|
|
17650
|
-
angleIndex:
|
|
17651
|
-
angle:
|
|
17652
|
-
angle:
|
|
17653
|
-
buyerPersona:
|
|
17654
|
-
actor:
|
|
17655
|
-
actorId:
|
|
17656
|
-
gender:
|
|
17783
|
+
var EditTaskDraftInput = z72.object({
|
|
17784
|
+
taskId: z72.string().min(1),
|
|
17785
|
+
angleIndex: z72.number().int().min(0),
|
|
17786
|
+
angle: z72.object({
|
|
17787
|
+
angle: z72.string().min(1).max(480),
|
|
17788
|
+
buyerPersona: z72.string().min(1).max(360),
|
|
17789
|
+
actor: z72.string().min(1).max(360).optional(),
|
|
17790
|
+
actorId: z72.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."),
|
|
17791
|
+
gender: z72.enum([
|
|
17657
17792
|
"female",
|
|
17658
17793
|
"male"
|
|
17659
17794
|
]).optional(),
|
|
17660
|
-
scriptNotes:
|
|
17795
|
+
scriptNotes: z72.string().max(2e3).optional()
|
|
17661
17796
|
})
|
|
17662
17797
|
});
|
|
17663
|
-
var PendingActionPayload =
|
|
17664
|
-
|
|
17665
|
-
kind:
|
|
17798
|
+
var PendingActionPayload = z72.discriminatedUnion("kind", [
|
|
17799
|
+
z72.object({
|
|
17800
|
+
kind: z72.literal("product_reference_set_approval"),
|
|
17666
17801
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17667
|
-
scopeKey:
|
|
17668
|
-
scopeSnapshotId:
|
|
17669
|
-
expectedScopeHash:
|
|
17802
|
+
scopeKey: z72.string().min(1).max(120).optional(),
|
|
17803
|
+
scopeSnapshotId: z72.string().uuid().optional(),
|
|
17804
|
+
expectedScopeHash: z72.string().min(1).max(128).optional(),
|
|
17670
17805
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
17671
17806
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
17672
|
-
affectedRefKeys:
|
|
17673
|
-
affectedPhotoNumbers:
|
|
17674
|
-
recoveryAction:
|
|
17807
|
+
affectedRefKeys: z72.array(z72.string().min(1).max(200)).min(1).optional(),
|
|
17808
|
+
affectedPhotoNumbers: z72.array(z72.number().int().positive()).min(1).optional(),
|
|
17809
|
+
recoveryAction: z72.enum([
|
|
17675
17810
|
"remove",
|
|
17676
17811
|
"replace",
|
|
17677
17812
|
"upload",
|
|
17678
17813
|
"return_to_selection"
|
|
17679
17814
|
]).optional()
|
|
17680
17815
|
}),
|
|
17681
|
-
|
|
17682
|
-
kind:
|
|
17683
|
-
selectedPhotoNumbers:
|
|
17816
|
+
z72.object({
|
|
17817
|
+
kind: z72.literal("product_reference_confirmation"),
|
|
17818
|
+
selectedPhotoNumbers: z72.array(z72.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."),
|
|
17684
17819
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
17685
|
-
confirmedProductNames:
|
|
17820
|
+
confirmedProductNames: z72.array(z72.string().min(1).max(120)).min(2).max(8).optional(),
|
|
17686
17821
|
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."),
|
|
17687
17822
|
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."),
|
|
17688
|
-
useMultiSceneShowcase:
|
|
17823
|
+
useMultiSceneShowcase: z72.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
17689
17824
|
}),
|
|
17690
|
-
|
|
17691
|
-
kind:
|
|
17825
|
+
z72.object({
|
|
17826
|
+
kind: z72.literal("angle_review_approval"),
|
|
17692
17827
|
// All edits are optional — empty action body just approves the
|
|
17693
17828
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
17694
17829
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
17695
17830
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
17696
|
-
customAngle:
|
|
17831
|
+
customAngle: z72.string().min(1).max(480).optional(),
|
|
17697
17832
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
17698
17833
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
17699
|
-
painPoints:
|
|
17700
|
-
benefits:
|
|
17834
|
+
painPoints: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17835
|
+
benefits: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17701
17836
|
// Same policy as the two fields above: the strictest downstream contract
|
|
17702
17837
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
17703
17838
|
// accept 300, and this single action routes to whichever the task is — so
|
|
17704
17839
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
17705
17840
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
17706
|
-
features:
|
|
17707
|
-
buyerPersona:
|
|
17841
|
+
features: z72.array(z72.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
17842
|
+
buyerPersona: z72.string().min(1).max(360).optional(),
|
|
17708
17843
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
|
|
17709
|
-
actor:
|
|
17710
|
-
actorId:
|
|
17711
|
-
creativeDirection:
|
|
17712
|
-
selectedAngleNumbers:
|
|
17713
|
-
angleEdits:
|
|
17714
|
-
angleNumber:
|
|
17715
|
-
narrativeSelection:
|
|
17844
|
+
actor: z72.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."),
|
|
17845
|
+
actorId: z72.string().max(120).nullable().optional(),
|
|
17846
|
+
creativeDirection: z72.string().max(2e3).optional(),
|
|
17847
|
+
selectedAngleNumbers: z72.array(z72.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."),
|
|
17848
|
+
angleEdits: z72.array(z72.object({
|
|
17849
|
+
angleNumber: z72.number().int().positive(),
|
|
17850
|
+
narrativeSelection: z72.enum([
|
|
17716
17851
|
"market",
|
|
17717
17852
|
"guided"
|
|
17718
17853
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
17719
|
-
angle:
|
|
17720
|
-
buyerPersona:
|
|
17854
|
+
angle: z72.string().min(1).max(480).optional(),
|
|
17855
|
+
buyerPersona: z72.string().min(1).max(360).optional(),
|
|
17721
17856
|
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) requiere Multiescena de 30s: en un video de 15s en formato Un solo clip el servidor la rechaza.'),
|
|
17722
|
-
actor:
|
|
17723
|
-
actorId:
|
|
17724
|
-
creativeDirection:
|
|
17857
|
+
actor: z72.string().min(1).max(360).optional(),
|
|
17858
|
+
actorId: z72.string().max(120).nullable().optional(),
|
|
17859
|
+
creativeDirection: z72.string().max(2e3).optional()
|
|
17725
17860
|
}).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)."),
|
|
17726
|
-
gapDurationSeconds:
|
|
17727
|
-
|
|
17728
|
-
|
|
17861
|
+
gapDurationSeconds: z72.union([
|
|
17862
|
+
z72.literal(15),
|
|
17863
|
+
z72.literal(30)
|
|
17729
17864
|
]).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.")
|
|
17730
17865
|
}),
|
|
17731
|
-
|
|
17732
|
-
kind:
|
|
17733
|
-
angleId:
|
|
17734
|
-
angleNumber:
|
|
17735
|
-
content:
|
|
17736
|
-
creativeDirection:
|
|
17737
|
-
actor:
|
|
17866
|
+
z72.object({
|
|
17867
|
+
kind: z72.literal("service_angle_approval"),
|
|
17868
|
+
angleId: z72.string().uuid().optional(),
|
|
17869
|
+
angleNumber: z72.number().int().positive().optional(),
|
|
17870
|
+
content: z72.string().min(1).max(480).optional(),
|
|
17871
|
+
creativeDirection: z72.string().min(1).max(1500).optional(),
|
|
17872
|
+
actor: z72.string().min(1).max(360).optional()
|
|
17738
17873
|
}),
|
|
17739
|
-
|
|
17740
|
-
kind:
|
|
17741
|
-
voiceovers:
|
|
17742
|
-
visualDirections:
|
|
17743
|
-
voiceoversByScene:
|
|
17744
|
-
visualDirectionsByScene:
|
|
17874
|
+
z72.object({
|
|
17875
|
+
kind: z72.literal("service_script_approval"),
|
|
17876
|
+
voiceovers: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
|
|
17877
|
+
visualDirections: z72.record(z72.string(), z72.string().min(1).max(1200)).optional(),
|
|
17878
|
+
voiceoversByScene: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
|
|
17879
|
+
visualDirectionsByScene: z72.record(z72.string(), z72.string().min(1).max(1200)).optional()
|
|
17745
17880
|
})
|
|
17746
17881
|
]);
|
|
17747
|
-
var ResolvePendingActionInput =
|
|
17748
|
-
taskId:
|
|
17882
|
+
var ResolvePendingActionInput = z72.object({
|
|
17883
|
+
taskId: z72.string().min(1),
|
|
17749
17884
|
action: PendingActionPayload
|
|
17750
17885
|
}).strict();
|
|
17751
17886
|
function resolveVariantConfirmVideoTier(action) {
|
|
17752
17887
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
17753
17888
|
}
|
|
17754
17889
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
17755
|
-
var StatusForResolveSchema =
|
|
17890
|
+
var StatusForResolveSchema = z72.object({
|
|
17756
17891
|
// Metadata used to select the backend resume contract. Older API responses
|
|
17757
17892
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
17758
|
-
kind:
|
|
17893
|
+
kind: z72.enum([
|
|
17759
17894
|
"autopilot",
|
|
17760
17895
|
"video",
|
|
17761
17896
|
"image",
|
|
@@ -17763,18 +17898,18 @@ var StatusForResolveSchema = z71.object({
|
|
|
17763
17898
|
"mix",
|
|
17764
17899
|
"service"
|
|
17765
17900
|
]).optional(),
|
|
17766
|
-
selectedOutputs:
|
|
17901
|
+
selectedOutputs: z72.array(z72.enum([
|
|
17767
17902
|
"landing",
|
|
17768
17903
|
"video",
|
|
17769
17904
|
"image"
|
|
17770
17905
|
])).optional(),
|
|
17771
|
-
videoAngleCount:
|
|
17772
|
-
ugcFormat:
|
|
17906
|
+
videoAngleCount: z72.number().int().min(1).max(3).optional(),
|
|
17907
|
+
ugcFormat: z72.enum([
|
|
17773
17908
|
"single_8s",
|
|
17774
17909
|
"single_15s",
|
|
17775
17910
|
"double_30s"
|
|
17776
17911
|
]).optional(),
|
|
17777
|
-
videoStyle:
|
|
17912
|
+
videoStyle: z72.enum([
|
|
17778
17913
|
"ugc",
|
|
17779
17914
|
"cartoon_3d",
|
|
17780
17915
|
"product_only",
|
|
@@ -17783,7 +17918,7 @@ var StatusForResolveSchema = z71.object({
|
|
|
17783
17918
|
videoStructure: VideoStructureEnum.optional(),
|
|
17784
17919
|
videoQuality: VideoQualityEnum.optional(),
|
|
17785
17920
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
17786
|
-
videoModel:
|
|
17921
|
+
videoModel: z72.enum([
|
|
17787
17922
|
"veo",
|
|
17788
17923
|
"wan",
|
|
17789
17924
|
"bytedance",
|
|
@@ -17791,71 +17926,71 @@ var StatusForResolveSchema = z71.object({
|
|
|
17791
17926
|
"grok",
|
|
17792
17927
|
"kling"
|
|
17793
17928
|
]).optional(),
|
|
17794
|
-
videoTier:
|
|
17929
|
+
videoTier: z72.enum([
|
|
17795
17930
|
"legacy",
|
|
17796
17931
|
"standard",
|
|
17797
17932
|
"pro",
|
|
17798
17933
|
"single_call"
|
|
17799
17934
|
]).optional(),
|
|
17800
|
-
videoResolution:
|
|
17935
|
+
videoResolution: z72.enum([
|
|
17801
17936
|
"480p",
|
|
17802
17937
|
"720p"
|
|
17803
17938
|
]).optional(),
|
|
17804
17939
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
17805
|
-
pauseForVideoScriptReview:
|
|
17806
|
-
pendingUserAction:
|
|
17807
|
-
kind:
|
|
17808
|
-
candidateGrouping:
|
|
17809
|
-
selectedImageUrls:
|
|
17810
|
-
proposedProductNames:
|
|
17940
|
+
pauseForVideoScriptReview: z72.boolean().optional(),
|
|
17941
|
+
pendingUserAction: z72.object({
|
|
17942
|
+
kind: z72.string(),
|
|
17943
|
+
candidateGrouping: z72.string().optional(),
|
|
17944
|
+
selectedImageUrls: z72.array(z72.string()).optional(),
|
|
17945
|
+
proposedProductNames: z72.array(z72.string()).optional(),
|
|
17811
17946
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
17812
17947
|
// identity and the choices shown by the current snapshot; never accept a
|
|
17813
17948
|
// client-supplied reference set as authorization.
|
|
17814
|
-
options:
|
|
17815
|
-
mode:
|
|
17949
|
+
options: z72.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
17950
|
+
mode: z72.enum([
|
|
17816
17951
|
"question",
|
|
17817
17952
|
"visual_recovery"
|
|
17818
17953
|
]).optional(),
|
|
17819
17954
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
17820
|
-
canKeepSelection:
|
|
17821
|
-
decisionKey:
|
|
17822
|
-
questionOrdinal:
|
|
17823
|
-
questionCeiling:
|
|
17824
|
-
|
|
17825
|
-
|
|
17955
|
+
canKeepSelection: z72.boolean().optional(),
|
|
17956
|
+
decisionKey: z72.string().optional(),
|
|
17957
|
+
questionOrdinal: z72.number().int().min(1).max(5).optional(),
|
|
17958
|
+
questionCeiling: z72.union([
|
|
17959
|
+
z72.literal(3),
|
|
17960
|
+
z72.literal(5)
|
|
17826
17961
|
]).optional(),
|
|
17827
|
-
referenceEvidenceVersion:
|
|
17828
|
-
expectedEvidenceHash:
|
|
17829
|
-
question:
|
|
17830
|
-
prompt:
|
|
17831
|
-
helpText:
|
|
17832
|
-
options:
|
|
17962
|
+
referenceEvidenceVersion: z72.number().int().positive().optional(),
|
|
17963
|
+
expectedEvidenceHash: z72.string().optional(),
|
|
17964
|
+
question: z72.object({
|
|
17965
|
+
prompt: z72.string().min(1).max(240),
|
|
17966
|
+
helpText: z72.string().min(1).max(300).optional(),
|
|
17967
|
+
options: z72.array(z72.object({
|
|
17833
17968
|
value: ProductReferenceUserChoiceEnum,
|
|
17834
|
-
label:
|
|
17835
|
-
description:
|
|
17969
|
+
label: z72.string().min(1).max(120),
|
|
17970
|
+
description: z72.string().min(1).max(240).optional()
|
|
17836
17971
|
})).min(2).max(4)
|
|
17837
17972
|
}).optional(),
|
|
17838
17973
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17839
|
-
scopeKey:
|
|
17840
|
-
scopeSnapshotId:
|
|
17841
|
-
scopeHash:
|
|
17842
|
-
baseReferenceSetHash:
|
|
17843
|
-
phase:
|
|
17974
|
+
scopeKey: z72.string().optional(),
|
|
17975
|
+
scopeSnapshotId: z72.string().uuid().optional(),
|
|
17976
|
+
scopeHash: z72.string().optional(),
|
|
17977
|
+
baseReferenceSetHash: z72.string().optional(),
|
|
17978
|
+
phase: z72.enum([
|
|
17844
17979
|
"preparation",
|
|
17845
17980
|
"final"
|
|
17846
17981
|
]).optional(),
|
|
17847
|
-
selectedRefKeys:
|
|
17848
|
-
allowedDecisions:
|
|
17849
|
-
previews:
|
|
17850
|
-
refKey:
|
|
17982
|
+
selectedRefKeys: z72.array(z72.string().min(1).max(200)).optional(),
|
|
17983
|
+
allowedDecisions: z72.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
17984
|
+
previews: z72.array(z72.object({
|
|
17985
|
+
refKey: z72.string().min(1).max(200)
|
|
17851
17986
|
}).passthrough()).optional(),
|
|
17852
|
-
customAngleDraft:
|
|
17853
|
-
painPointsDraft:
|
|
17854
|
-
benefitsDraft:
|
|
17855
|
-
featuresDraft:
|
|
17856
|
-
angleOptions:
|
|
17857
|
-
index:
|
|
17858
|
-
angle:
|
|
17987
|
+
customAngleDraft: z72.string().optional(),
|
|
17988
|
+
painPointsDraft: z72.string().optional(),
|
|
17989
|
+
benefitsDraft: z72.string().optional(),
|
|
17990
|
+
featuresDraft: z72.array(z72.string()).optional(),
|
|
17991
|
+
angleOptions: z72.array(z72.object({
|
|
17992
|
+
index: z72.number().int().nonnegative(),
|
|
17993
|
+
angle: z72.string().min(1)
|
|
17859
17994
|
}).passthrough()).min(1).max(5).optional(),
|
|
17860
17995
|
// Recommendation consumed only when the caller explicitly sends
|
|
17861
17996
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -17865,17 +18000,17 @@ var StatusForResolveSchema = z71.object({
|
|
|
17865
18000
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
17866
18001
|
// dropped here, so the approval handler below could not echo it back on the
|
|
17867
18002
|
// PATCH — the selection looked accepted and reached no render.
|
|
17868
|
-
angles:
|
|
17869
|
-
id:
|
|
17870
|
-
content:
|
|
17871
|
-
creativeDirection:
|
|
17872
|
-
actor:
|
|
17873
|
-
actorId:
|
|
18003
|
+
angles: z72.array(z72.object({
|
|
18004
|
+
id: z72.string().uuid(),
|
|
18005
|
+
content: z72.string(),
|
|
18006
|
+
creativeDirection: z72.string(),
|
|
18007
|
+
actor: z72.string(),
|
|
18008
|
+
actorId: z72.string().nullable().optional()
|
|
17874
18009
|
}).passthrough()).optional(),
|
|
17875
|
-
panels:
|
|
17876
|
-
beatId:
|
|
17877
|
-
voiceover:
|
|
17878
|
-
visualDirection:
|
|
18010
|
+
panels: z72.array(z72.object({
|
|
18011
|
+
beatId: z72.string(),
|
|
18012
|
+
voiceover: z72.string(),
|
|
18013
|
+
visualDirection: z72.string()
|
|
17879
18014
|
}).passthrough()).optional()
|
|
17880
18015
|
}).optional()
|
|
17881
18016
|
}).passthrough();
|
|
@@ -17996,7 +18131,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
17996
18131
|
|
|
17997
18132
|
REQUERIDOS: images o projectId expl\xEDcito, language y country. Cuando los outputs incluyen video (tambi\xE9n por default), pregunta SIEMPRE videoAngleCount: 1, 2 o 3; es una decisi\xF3n de costo incluso con aiDecidesAll. Si falta una foto local, llama primero \`request_media_upload\`. Pregunta price, offer, paymentMethods y compareAtPrice cuando aplique; nunca asumas country/language.
|
|
17998
18133
|
|
|
17999
|
-
ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape,
|
|
18134
|
+
ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explica que inicia trabajo pagado y espera confirmaci\xF3n expl\xEDcita. aiDecidesAll omitido/false pausa para reviews conversacionales; muestra todos los \xE1ngulos candidatos y permite escoger/editar hasta el m\xE1ximo autorizado. Usa aiDecidesAll=true s\xF3lo si el usuario pidi\xF3 \u201Cdecide todo\u201D o \u201Cno me preguntes\u201D.`, CreateProductTaskInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
18000
18135
|
try {
|
|
18001
18136
|
const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
|
|
18002
18137
|
const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
|
|
@@ -18087,7 +18222,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
18087
18222
|
throw translateError(e);
|
|
18088
18223
|
}
|
|
18089
18224
|
});
|
|
18090
|
-
server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape,
|
|
18225
|
+
server.tool("create_service_video", createServiceVideoGuidance.summary + " Esta acci\xF3n consume cr\xE9ditos: confirma la intenci\xF3n del usuario antes de llamarla. `automatic` genera directamente; `guided` devuelve conceptos para que el usuario apruebe uno mediante `resolve_pending_action`. La web tambi\xE9n acepta demos y anuncios de referencia; el transporte MCP de video adjunto todav\xEDa falla cerrado hasta poder subir bytes de forma segura.", CreateServiceVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
18091
18226
|
try {
|
|
18092
18227
|
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
18093
18228
|
const created = await api.postJson("/v2/ingest", {
|
|
@@ -18101,6 +18236,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
18101
18236
|
voiceId: input.voiceId
|
|
18102
18237
|
} : {},
|
|
18103
18238
|
videoPreset: input.videoPreset,
|
|
18239
|
+
videoQuality: input.videoQuality,
|
|
18104
18240
|
reviewMode: input.reviewMode,
|
|
18105
18241
|
...input.brandId ? {
|
|
18106
18242
|
brandId: input.brandId
|
|
@@ -18705,7 +18841,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
18705
18841
|
|
|
18706
18842
|
// src/tools/creatives.ts
|
|
18707
18843
|
import { randomUUID } from "crypto";
|
|
18708
|
-
import { z as
|
|
18844
|
+
import { z as z73 } from "zod";
|
|
18709
18845
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
18710
18846
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
18711
18847
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -18715,70 +18851,70 @@ var CreativeRefs = {
|
|
|
18715
18851
|
images: ImagesInput,
|
|
18716
18852
|
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.'),
|
|
18717
18853
|
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.'),
|
|
18718
|
-
price:
|
|
18719
|
-
offer:
|
|
18720
|
-
compareAtPrice:
|
|
18721
|
-
productContext:
|
|
18722
|
-
productLabel:
|
|
18723
|
-
buyerPersona:
|
|
18724
|
-
isCombo:
|
|
18725
|
-
competitorScanEnabled:
|
|
18726
|
-
brandId:
|
|
18854
|
+
price: z73.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.'),
|
|
18855
|
+
offer: z73.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.'),
|
|
18856
|
+
compareAtPrice: z73.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
18857
|
+
productContext: z73.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."),
|
|
18858
|
+
productLabel: z73.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.'),
|
|
18859
|
+
buyerPersona: z73.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.'),
|
|
18860
|
+
isCombo: z73.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
18861
|
+
competitorScanEnabled: z73.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
|
|
18862
|
+
brandId: z73.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.")
|
|
18727
18863
|
};
|
|
18728
|
-
var VideoPresenter =
|
|
18729
|
-
|
|
18730
|
-
mode:
|
|
18864
|
+
var VideoPresenter = z73.discriminatedUnion("mode", [
|
|
18865
|
+
z73.object({
|
|
18866
|
+
mode: z73.literal("none")
|
|
18731
18867
|
}).strict(),
|
|
18732
|
-
|
|
18733
|
-
mode:
|
|
18734
|
-
actorId:
|
|
18868
|
+
z73.object({
|
|
18869
|
+
mode: z73.literal("saved_actor"),
|
|
18870
|
+
actorId: z73.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
18735
18871
|
}).strict(),
|
|
18736
|
-
|
|
18737
|
-
mode:
|
|
18738
|
-
description:
|
|
18872
|
+
z73.object({
|
|
18873
|
+
mode: z73.literal("described"),
|
|
18874
|
+
description: z73.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
18739
18875
|
}).strict()
|
|
18740
18876
|
]);
|
|
18741
|
-
var VideoCreativeSetup =
|
|
18742
|
-
|
|
18743
|
-
mode:
|
|
18877
|
+
var VideoCreativeSetup = z73.discriminatedUnion("mode", [
|
|
18878
|
+
z73.object({
|
|
18879
|
+
mode: z73.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
18744
18880
|
}).strict(),
|
|
18745
|
-
|
|
18746
|
-
mode:
|
|
18881
|
+
z73.object({
|
|
18882
|
+
mode: z73.literal("guided"),
|
|
18747
18883
|
videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. "problem_solution" requiere 30s.'),
|
|
18748
|
-
buyerPersona:
|
|
18884
|
+
buyerPersona: z73.string().trim().min(1).max(360),
|
|
18749
18885
|
presenter: VideoPresenter,
|
|
18750
|
-
creativeDirection:
|
|
18886
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
18751
18887
|
}).strict()
|
|
18752
18888
|
]);
|
|
18753
|
-
var VideoInput =
|
|
18889
|
+
var VideoInput = z73.object({
|
|
18754
18890
|
images: CreativeRefs.images.optional(),
|
|
18755
18891
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18756
|
-
title:
|
|
18757
|
-
primaryAngle:
|
|
18892
|
+
title: z73.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
18893
|
+
primaryAngle: z73.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".'),
|
|
18758
18894
|
language: CreativeRefs.language,
|
|
18759
18895
|
country: CreativeRefs.country,
|
|
18760
|
-
aspectRatio:
|
|
18896
|
+
aspectRatio: z73.enum([
|
|
18761
18897
|
"9:16",
|
|
18762
18898
|
"16:9",
|
|
18763
18899
|
"Auto"
|
|
18764
18900
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
18765
|
-
durationSeconds:
|
|
18766
|
-
videoAngleCount:
|
|
18901
|
+
durationSeconds: z73.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."),
|
|
18902
|
+
videoAngleCount: z73.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."),
|
|
18767
18903
|
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.'),
|
|
18768
18904
|
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."),
|
|
18769
18905
|
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.'),
|
|
18770
18906
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
18771
18907
|
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.'),
|
|
18772
|
-
features:
|
|
18908
|
+
features: z73.array(z73.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
18773
18909
|
price: CreativeRefs.price,
|
|
18774
18910
|
offer: CreativeRefs.offer,
|
|
18775
18911
|
productContext: CreativeRefs.productContext,
|
|
18776
18912
|
productLabel: CreativeRefs.productLabel,
|
|
18777
|
-
cta:
|
|
18778
|
-
scriptNotes:
|
|
18913
|
+
cta: z73.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.'),
|
|
18914
|
+
scriptNotes: z73.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.'),
|
|
18779
18915
|
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.'),
|
|
18780
18916
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
18781
|
-
replicateWinnerWhenFound:
|
|
18917
|
+
replicateWinnerWhenFound: z73.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."),
|
|
18782
18918
|
brandId: CreativeRefs.brandId
|
|
18783
18919
|
}).strict();
|
|
18784
18920
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -18796,7 +18932,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
18796
18932
|
length: 29
|
|
18797
18933
|
}, (_, index) => index + 2)
|
|
18798
18934
|
};
|
|
18799
|
-
var FreeVideoModelIdEnum =
|
|
18935
|
+
var FreeVideoModelIdEnum = z73.enum([
|
|
18800
18936
|
"grok-imagine-video-1-5-preview",
|
|
18801
18937
|
"minimax-h3/reference-to-video",
|
|
18802
18938
|
"wan/3-0-video",
|
|
@@ -18807,70 +18943,70 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
18807
18943
|
"minimax-h3/reference-to-video",
|
|
18808
18944
|
"wan/3-0-video"
|
|
18809
18945
|
];
|
|
18810
|
-
var FreeVideoInput =
|
|
18946
|
+
var FreeVideoInput = z73.object({
|
|
18811
18947
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
18812
|
-
rawPrompt:
|
|
18948
|
+
rawPrompt: z73.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."),
|
|
18813
18949
|
language: CreativeRefs.language,
|
|
18814
18950
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
18815
18951
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
18816
18952
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
18817
18953
|
// replacement — dropping it silently would turn a caller's explicit
|
|
18818
18954
|
// Pro++ pick into a quiet fallback to Wan.
|
|
18819
|
-
freeProModel:
|
|
18955
|
+
freeProModel: z73.enum([
|
|
18820
18956
|
"wan",
|
|
18821
18957
|
"seedance"
|
|
18822
18958
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
18823
18959
|
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.'),
|
|
18824
|
-
durationSeconds:
|
|
18960
|
+
durationSeconds: z73.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."),
|
|
18825
18961
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
18826
|
-
generateAiMusic:
|
|
18827
|
-
addSubtitles:
|
|
18828
|
-
idempotencyKey:
|
|
18962
|
+
generateAiMusic: z73.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
18963
|
+
addSubtitles: z73.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
18964
|
+
idempotencyKey: z73.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
|
|
18829
18965
|
}).strict();
|
|
18830
18966
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
18831
|
-
var ImageCreativeSetup =
|
|
18832
|
-
|
|
18833
|
-
mode:
|
|
18967
|
+
var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
18968
|
+
z73.object({
|
|
18969
|
+
mode: z73.literal("automatic")
|
|
18834
18970
|
}).strict(),
|
|
18835
|
-
|
|
18836
|
-
mode:
|
|
18837
|
-
creativeArchetype:
|
|
18971
|
+
z73.object({
|
|
18972
|
+
mode: z73.literal("guided"),
|
|
18973
|
+
creativeArchetype: z73.union([
|
|
18838
18974
|
ImageCreativeArchetypeEnum,
|
|
18839
|
-
|
|
18975
|
+
z73.literal("ai_decides")
|
|
18840
18976
|
]),
|
|
18841
|
-
visualTreatment:
|
|
18977
|
+
visualTreatment: z73.union([
|
|
18842
18978
|
ImageCreativeVisualTreatmentEnum,
|
|
18843
|
-
|
|
18979
|
+
z73.literal("ai_decides")
|
|
18844
18980
|
]),
|
|
18845
18981
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
18846
|
-
nVariants:
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
|
|
18982
|
+
nVariants: z73.union([
|
|
18983
|
+
z73.literal(1),
|
|
18984
|
+
z73.literal(2),
|
|
18985
|
+
z73.literal(3),
|
|
18986
|
+
z73.literal(4),
|
|
18987
|
+
z73.literal(6)
|
|
18852
18988
|
]),
|
|
18853
|
-
imageModel:
|
|
18989
|
+
imageModel: z73.enum([
|
|
18854
18990
|
"gpt-image-2-5:1k",
|
|
18855
18991
|
"gpt-image-2-5:2k",
|
|
18856
18992
|
"gpt-image-2:1k",
|
|
18857
18993
|
"gpt-image-2:2k"
|
|
18858
18994
|
]),
|
|
18859
|
-
styleMix:
|
|
18860
|
-
generateAdCopy:
|
|
18861
|
-
competitorScanEnabled:
|
|
18862
|
-
productContext:
|
|
18863
|
-
creativeDirection:
|
|
18864
|
-
brandColors:
|
|
18865
|
-
headline:
|
|
18866
|
-
subheadline:
|
|
18995
|
+
styleMix: z73.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
18996
|
+
generateAdCopy: z73.boolean(),
|
|
18997
|
+
competitorScanEnabled: z73.boolean(),
|
|
18998
|
+
productContext: z73.string().trim().min(1).max(3e3).nullable(),
|
|
18999
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable(),
|
|
19000
|
+
brandColors: z73.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.'),
|
|
19001
|
+
headline: z73.string().trim().min(1).max(120).nullable(),
|
|
19002
|
+
subheadline: z73.string().trim().min(1).max(160).nullable()
|
|
18867
19003
|
}).strict()
|
|
18868
19004
|
]).superRefine((setup, context) => {
|
|
18869
19005
|
if (setup.mode !== "guided") return;
|
|
18870
19006
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
18871
19007
|
if (needsStyleMix && setup.styleMix === null) {
|
|
18872
19008
|
context.addIssue({
|
|
18873
|
-
code:
|
|
19009
|
+
code: z73.ZodIssueCode.custom,
|
|
18874
19010
|
path: [
|
|
18875
19011
|
"styleMix"
|
|
18876
19012
|
],
|
|
@@ -18879,7 +19015,7 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18879
19015
|
}
|
|
18880
19016
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
18881
19017
|
context.addIssue({
|
|
18882
|
-
code:
|
|
19018
|
+
code: z73.ZodIssueCode.custom,
|
|
18883
19019
|
path: [
|
|
18884
19020
|
"styleMix"
|
|
18885
19021
|
],
|
|
@@ -18888,7 +19024,7 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18888
19024
|
}
|
|
18889
19025
|
if ((setup.imageModel === "gpt-image-2:2k" || setup.imageModel === "gpt-image-2-5:2k") && setup.aspectRatio === "4:5") {
|
|
18890
19026
|
context.addIssue({
|
|
18891
|
-
code:
|
|
19027
|
+
code: z73.ZodIssueCode.custom,
|
|
18892
19028
|
path: [
|
|
18893
19029
|
"aspectRatio"
|
|
18894
19030
|
],
|
|
@@ -18896,53 +19032,53 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18896
19032
|
});
|
|
18897
19033
|
}
|
|
18898
19034
|
});
|
|
18899
|
-
var LandingCreativeSetup =
|
|
18900
|
-
|
|
18901
|
-
mode:
|
|
19035
|
+
var LandingCreativeSetup = z73.discriminatedUnion("mode", [
|
|
19036
|
+
z73.object({
|
|
19037
|
+
mode: z73.literal("automatic")
|
|
18902
19038
|
}).strict(),
|
|
18903
|
-
|
|
18904
|
-
mode:
|
|
19039
|
+
z73.object({
|
|
19040
|
+
mode: z73.literal("guided"),
|
|
18905
19041
|
landingStrategy: LandingStrategyEnum,
|
|
18906
19042
|
landingImageFormat: LandingImageFormatEnum,
|
|
18907
|
-
competitorScanEnabled:
|
|
18908
|
-
paymentMethods:
|
|
18909
|
-
productContext:
|
|
18910
|
-
creativeDirection:
|
|
18911
|
-
headline:
|
|
18912
|
-
subheadline:
|
|
19043
|
+
competitorScanEnabled: z73.boolean(),
|
|
19044
|
+
paymentMethods: z73.string().trim().min(1).max(240).nullable(),
|
|
19045
|
+
productContext: z73.string().trim().min(1).max(3e3).nullable(),
|
|
19046
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable(),
|
|
19047
|
+
headline: z73.string().trim().min(1).max(120).nullable(),
|
|
19048
|
+
subheadline: z73.string().trim().min(1).max(160).nullable()
|
|
18913
19049
|
}).strict()
|
|
18914
19050
|
]);
|
|
18915
|
-
var ImageInput =
|
|
19051
|
+
var ImageInput = z73.object({
|
|
18916
19052
|
images: CreativeRefs.images.optional(),
|
|
18917
19053
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18918
|
-
productTitle:
|
|
18919
|
-
primaryAngle:
|
|
19054
|
+
productTitle: z73.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
19055
|
+
primaryAngle: z73.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.'),
|
|
18920
19056
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
18921
19057
|
language: CreativeRefs.language,
|
|
18922
19058
|
country: CreativeRefs.country,
|
|
18923
19059
|
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."),
|
|
18924
19060
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
18925
|
-
features:
|
|
19061
|
+
features: z73.array(z73.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
18926
19062
|
price: CreativeRefs.price,
|
|
18927
|
-
omitPrice:
|
|
19063
|
+
omitPrice: z73.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."),
|
|
18928
19064
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
18929
19065
|
offer: CreativeRefs.offer,
|
|
18930
19066
|
productLabel: CreativeRefs.productLabel,
|
|
18931
19067
|
isCombo: CreativeRefs.isCombo,
|
|
18932
19068
|
brandId: CreativeRefs.brandId
|
|
18933
19069
|
});
|
|
18934
|
-
var EditImageCreativeInput =
|
|
18935
|
-
taskId:
|
|
18936
|
-
variantIndex:
|
|
18937
|
-
instruction:
|
|
19070
|
+
var EditImageCreativeInput = z73.object({
|
|
19071
|
+
taskId: z73.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
19072
|
+
variantIndex: z73.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
19073
|
+
instruction: z73.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".')
|
|
18938
19074
|
});
|
|
18939
|
-
var LandingInput =
|
|
19075
|
+
var LandingInput = z73.object({
|
|
18940
19076
|
images: CreativeRefs.images.optional(),
|
|
18941
19077
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18942
19078
|
language: CreativeRefs.language,
|
|
18943
19079
|
country: CreativeRefs.country,
|
|
18944
19080
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
18945
|
-
salesAngle:
|
|
19081
|
+
salesAngle: z73.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.'),
|
|
18946
19082
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
18947
19083
|
price: CreativeRefs.price,
|
|
18948
19084
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -19011,7 +19147,7 @@ function resolveLandingSetup(setup) {
|
|
|
19011
19147
|
}
|
|
19012
19148
|
__name(resolveLandingSetup, "resolveLandingSetup");
|
|
19013
19149
|
function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
19014
|
-
server.tool("generate_free_video", generateFreeVideoGuidance.summary + ' Si el usuario adjunta o menciona una imagen local, llama primero request_media_upload con mediaKind=image y usa el assetId devuelto; no pidas path ni URL. Devuelve un taskId y procesa el job de forma as\xEDncrona.\n\nREQUERIDOS: rawPrompt, quality, durationSeconds y videoResolution.\n\nCALIDAD: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan). Economy admite 6/8/10/15s; Medium admite cualquier duraci\xF3n entera de 4 a 15s; Pro admite enteros de 2 a 30s y audio natural. `freeProModel` se elimin\xF3 \u2014 usa `modelId` (ver su descripci\xF3n); Seedance 2.5 est\xE1 inactivo y se rechaza con un error claro.\n\nSUBT\xCDTULOS: si addSubtitles=true, el rawPrompt completo se usa como texto exacto de subt\xEDtulos y debe tener m\xE1ximo 500 caracteres; no existe una pregunta adicional de transcripci\xF3n.\n\nPara videos normales con narrativa/\xE1ngulo usa generate_video_creative. Para tareas combinadas de producto usa create_product_task.', FreeVideoInput.shape,
|
|
19150
|
+
server.tool("generate_free_video", generateFreeVideoGuidance.summary + ' Si el usuario adjunta o menciona una imagen local, llama primero request_media_upload con mediaKind=image y usa el assetId devuelto; no pidas path ni URL. Devuelve un taskId y procesa el job de forma as\xEDncrona.\n\nREQUERIDOS: rawPrompt, quality, durationSeconds y videoResolution.\n\nCALIDAD: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan). Economy admite 6/8/10/15s; Medium admite cualquier duraci\xF3n entera de 4 a 15s; Pro admite enteros de 2 a 30s y audio natural. `freeProModel` se elimin\xF3 \u2014 usa `modelId` (ver su descripci\xF3n); Seedance 2.5 est\xE1 inactivo y se rechaza con un error claro.\n\nSUBT\xCDTULOS: si addSubtitles=true, el rawPrompt completo se usa como texto exacto de subt\xEDtulos y debe tener m\xE1ximo 500 caracteres; no existe una pregunta adicional de transcripci\xF3n.\n\nPara videos normales con narrativa/\xE1ngulo usa generate_video_creative. Para tareas combinadas de producto usa create_product_task.', FreeVideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
19015
19151
|
try {
|
|
19016
19152
|
if (input.freeProModel) {
|
|
19017
19153
|
throw new Error("freeProModel se elimin\xF3 en MCP 7.0.0. Usa `modelId` para elegir el modelo expl\xEDcitamente (ver la descripci\xF3n del par\xE1metro).");
|
|
@@ -19059,7 +19195,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19059
19195
|
throw translateError(e);
|
|
19060
19196
|
}
|
|
19061
19197
|
});
|
|
19062
|
-
server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape,
|
|
19198
|
+
server.tool("generate_video_creative", generateVideoCreativeGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), title, primaryAngle, language, country, aspectRatio, videoAngleCount y creativeSetup. Pregunta SIEMPRE cu\xE1ntos videos quiere (1, 2 o 3): la cantidad cambia el costo y no forma parte de \u2018la IA decide todo\u2019. Si falta una foto local, llama primero `request_media_upload` y usa los assetId; no pidas path ni URL. PREGUNTA price y offer si faltan; no asumas country/language.\n\nFORMATO Y CALIDAD: pregunta videoStructure (Un solo clip o Multiescena) y videoQuality (Econ\xF3mico, Medio o Pro). Un solo clip se genera completo y puede incluir cambios de plano. El sistema elige el proveedor internamente.\n\nCONFIGURACI\xD3N: salvo que el usuario diga expl\xEDcitamente que la IA decida todo, usa creativeSetup.mode=guided y pregunta narrativa solo si no hay estudio de mercado; recoge p\xFAblico comprador, presentador (actor guardado, descripci\xF3n o ninguno) y direcci\xF3n creativa. Si el usuario dice qui\xE9n debe aparecer (mujer, hombre o ambos), env\xEDa creativeGender; no lo preguntes si no lo menciona. creativeDirection=null s\xF3lo despu\xE9s de que el usuario delegue esa decisi\xF3n concreta. No inventes valores de setup.\n\nANTES de invocar, muestra un resumen compacto que incluya cantidad, planificaci\xF3n (estudio de mercado o narrativa), p\xFAblico, presentador y direcci\xF3n y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. Multiescena se factura por escena, as\xED que avisa ese mayor costo. Advierte tambi\xE9n que, si luego el usuario confirma que las fotos son de varios productos (combo), el pipeline r\xE1pido actualmente omite la pausa de guion aunque mantiene las dem\xE1s revisiones.\n\nREVIEWS: guided muestra los \xE1ngulos candidatos y permite escoger hasta videoAngleCount, editar cada \xE1ngulo y revisar sus guiones. automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite ambas reviews. scriptNotes agrega restricciones al guion; get_video_script y approve_video_script manejan la review palabra por palabra.", VideoInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
19063
19199
|
try {
|
|
19064
19200
|
if (!input.images && !input.winnerReference) {
|
|
19065
19201
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -19123,7 +19259,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19123
19259
|
throw translateError(e);
|
|
19124
19260
|
}
|
|
19125
19261
|
});
|
|
19126
|
-
server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape,
|
|
19262
|
+
server.tool("generate_image_creatives", generateImageCreativesGuidance.summary + " Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), productTitle, language, country y creativeSetup. Si falta una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language. primaryAngle es opcional: si falta, ProductMaker lo genera y guided lo muestra para revisi\xF3n.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. No hagas un interrogatorio campo por campo: presenta UN checklist compacto con arquetipo, tratamiento visual, formato, cantidad, calidad, mezcla condicional, copy, competencia, contexto, direcci\xF3n, colores y copy exacto; propone los defaults recomendados y permite que el usuario delegue los campos con ai_decides o null donde el schema lo admite. La UI ofrece 1, 2, 3, 4 o 6 variantes: para 2\u20134 pregunta styleMix; para 1 o 6 usa null, y 6 activa autom\xE1ticamente una imagen de cada estilo. Premium 2K no admite 4:5.\n\nANTES de invocar, muestra el resumen de esas decisiones y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", ImageInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
19127
19263
|
try {
|
|
19128
19264
|
if (!input.images && !input.winnerReference) {
|
|
19129
19265
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -19169,7 +19305,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19169
19305
|
throw translateError(e);
|
|
19170
19306
|
}
|
|
19171
19307
|
});
|
|
19172
|
-
server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape,
|
|
19308
|
+
server.tool("generate_landing", generateLandingGuidance.summary + " No expone landing editable/code mientras siga siendo admin-only. Devuelve un taskId. Esta solicitud es directa: nunca busques, reutilices ni menciones un DropshippingProject.\n\nREQUERIDOS: images (1-5 fotos), language, country y creativeSetup. Ante \u201Ccrea una landing con este producto\u201D y una foto local, llama primero `request_media_upload` y usa los assetId. Pregunta price, offer y compareAtPrice cuando aplique; no asumas country/language.\n\nCONFIGURACI\xD3N: usa guided salvo delegaci\xF3n total expl\xEDcita. Presenta UN checklist compacto \u2014no preguntas seriales\u2014 con estrategia, formato, competencia, m\xE9todos de pago, contexto, direcci\xF3n creativa y headline/subheadline exactos opcionales. Prop\xF3n defaults recomendados; null significa que el usuario deleg\xF3 esa decisi\xF3n concreta, nunca que el agente la olvid\xF3.\n\nANTES de invocar, muestra el resumen y espera confirmaci\xF3n expl\xEDcita porque inicia trabajo pagado. guided pausa para revisar el \xE1ngulo; automatic equivale al toggle web \u201CDejar que la IA decida todo\u201D y omite la review.", LandingInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
19173
19309
|
try {
|
|
19174
19310
|
if (!input.images && !input.winnerReference) {
|
|
19175
19311
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -19204,10 +19340,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19204
19340
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
19205
19341
|
|
|
19206
19342
|
// src/tools/creative-variants.ts
|
|
19207
|
-
import { z as
|
|
19343
|
+
import { z as z74 } from "zod";
|
|
19208
19344
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
19209
19345
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
19210
|
-
var LandingSectionKeyEnum =
|
|
19346
|
+
var LandingSectionKeyEnum = z74.enum([
|
|
19211
19347
|
"problem_hook",
|
|
19212
19348
|
"problem_cost",
|
|
19213
19349
|
"solution_mechanism",
|
|
@@ -19247,24 +19383,24 @@ var LandingSectionKeyEnum = z73.enum([
|
|
|
19247
19383
|
"lifestyle_fit",
|
|
19248
19384
|
"join_lifestyle"
|
|
19249
19385
|
]);
|
|
19250
|
-
var CreativeVariantKindEnum =
|
|
19386
|
+
var CreativeVariantKindEnum = z74.enum([
|
|
19251
19387
|
"video",
|
|
19252
19388
|
"image",
|
|
19253
19389
|
"landing"
|
|
19254
19390
|
]);
|
|
19255
|
-
var EstimateCreativeVariantInputBase =
|
|
19256
|
-
sourceTaskId:
|
|
19391
|
+
var EstimateCreativeVariantInputBase = z74.object({
|
|
19392
|
+
sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
|
|
19257
19393
|
kind: CreativeVariantKindEnum,
|
|
19258
19394
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
19259
19395
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
19260
|
-
nVariants:
|
|
19396
|
+
nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19261
19397
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
19262
|
-
instructions:
|
|
19398
|
+
instructions: z74.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.")
|
|
19263
19399
|
}).strict();
|
|
19264
19400
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19265
19401
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
19266
19402
|
ctx.addIssue({
|
|
19267
|
-
code:
|
|
19403
|
+
code: z74.ZodIssueCode.custom,
|
|
19268
19404
|
path: [
|
|
19269
19405
|
"nVariants"
|
|
19270
19406
|
],
|
|
@@ -19274,7 +19410,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19274
19410
|
if (input.kind !== "video") {
|
|
19275
19411
|
if (input.videoPreset !== void 0) {
|
|
19276
19412
|
ctx.addIssue({
|
|
19277
|
-
code:
|
|
19413
|
+
code: z74.ZodIssueCode.custom,
|
|
19278
19414
|
path: [
|
|
19279
19415
|
"videoPreset"
|
|
19280
19416
|
],
|
|
@@ -19283,7 +19419,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19283
19419
|
}
|
|
19284
19420
|
if (input.videoResolution !== void 0) {
|
|
19285
19421
|
ctx.addIssue({
|
|
19286
|
-
code:
|
|
19422
|
+
code: z74.ZodIssueCode.custom,
|
|
19287
19423
|
path: [
|
|
19288
19424
|
"videoResolution"
|
|
19289
19425
|
],
|
|
@@ -19293,7 +19429,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19293
19429
|
}
|
|
19294
19430
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
19295
19431
|
ctx.addIssue({
|
|
19296
|
-
code:
|
|
19432
|
+
code: z74.ZodIssueCode.custom,
|
|
19297
19433
|
path: [
|
|
19298
19434
|
"nVariants"
|
|
19299
19435
|
],
|
|
@@ -19303,7 +19439,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19303
19439
|
if (input.kind !== "landing") {
|
|
19304
19440
|
if (input.sectionKey !== void 0) {
|
|
19305
19441
|
ctx.addIssue({
|
|
19306
|
-
code:
|
|
19442
|
+
code: z74.ZodIssueCode.custom,
|
|
19307
19443
|
path: [
|
|
19308
19444
|
"sectionKey"
|
|
19309
19445
|
],
|
|
@@ -19312,7 +19448,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19312
19448
|
}
|
|
19313
19449
|
if (input.instructions !== void 0) {
|
|
19314
19450
|
ctx.addIssue({
|
|
19315
|
-
code:
|
|
19451
|
+
code: z74.ZodIssueCode.custom,
|
|
19316
19452
|
path: [
|
|
19317
19453
|
"instructions"
|
|
19318
19454
|
],
|
|
@@ -19321,31 +19457,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19321
19457
|
}
|
|
19322
19458
|
}
|
|
19323
19459
|
});
|
|
19324
|
-
var CreateCreativeVariantInputBase =
|
|
19325
|
-
sourceTaskId:
|
|
19460
|
+
var CreateCreativeVariantInputBase = z74.object({
|
|
19461
|
+
sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
|
|
19326
19462
|
kind: CreativeVariantKindEnum,
|
|
19327
|
-
confirm:
|
|
19328
|
-
clientRequestId:
|
|
19329
|
-
angle:
|
|
19330
|
-
buyerPersona:
|
|
19331
|
-
scriptNotes:
|
|
19332
|
-
creativeDirection:
|
|
19463
|
+
confirm: z74.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
19464
|
+
clientRequestId: z74.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
|
|
19465
|
+
angle: z74.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
19466
|
+
buyerPersona: z74.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
19467
|
+
scriptNotes: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
19468
|
+
creativeDirection: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
19333
19469
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
19334
19470
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
19335
|
-
generateAiMusic:
|
|
19336
|
-
nVariants:
|
|
19471
|
+
generateAiMusic: z74.boolean().optional().describe("Opcional para video."),
|
|
19472
|
+
nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19337
19473
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
19338
19474
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
19339
19475
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
19340
19476
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
19341
|
-
styleMix:
|
|
19477
|
+
styleMix: z74.boolean().optional().describe("Opcional para imagen."),
|
|
19342
19478
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
19343
|
-
instructions:
|
|
19479
|
+
instructions: z74.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.")
|
|
19344
19480
|
}).strict();
|
|
19345
19481
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19346
19482
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
19347
19483
|
ctx.addIssue({
|
|
19348
|
-
code:
|
|
19484
|
+
code: z74.ZodIssueCode.custom,
|
|
19349
19485
|
path: [
|
|
19350
19486
|
"angle"
|
|
19351
19487
|
],
|
|
@@ -19354,7 +19490,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19354
19490
|
}
|
|
19355
19491
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
19356
19492
|
ctx.addIssue({
|
|
19357
|
-
code:
|
|
19493
|
+
code: z74.ZodIssueCode.custom,
|
|
19358
19494
|
path: [
|
|
19359
19495
|
"instructions"
|
|
19360
19496
|
],
|
|
@@ -19400,7 +19536,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19400
19536
|
for (const field of fieldsByKind[input.kind]) {
|
|
19401
19537
|
if (input[field] !== void 0) {
|
|
19402
19538
|
ctx.addIssue({
|
|
19403
|
-
code:
|
|
19539
|
+
code: z74.ZodIssueCode.custom,
|
|
19404
19540
|
path: [
|
|
19405
19541
|
field
|
|
19406
19542
|
],
|
|
@@ -19447,7 +19583,7 @@ function registerCreativeVariantTools(server, api) {
|
|
|
19447
19583
|
throw translateError(error);
|
|
19448
19584
|
}
|
|
19449
19585
|
});
|
|
19450
|
-
server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape,
|
|
19586
|
+
server.tool("create_creative_variant", createCreativeVariantGuidance.summary + " ES UNA ACCI\xD3N DE PAGO: primero llama estimate_creative_variant, muestra el rango de cr\xE9ditos al usuario y solo despu\xE9s invoca este tool con confirm=true. Las recomendaciones IA tambi\xE9n son acciones pagas a 2x del costo real. clientRequestId es obligatorio: genera un UUID por intenci\xF3n y reutiliza el mismo ante timeouts o transporte ambiguo. Si recibes status=error, pide confirmaci\xF3n para un intento nuevo y usa otro UUID. Reutiliza el producto y referencias del task origen; crea un child task independiente y devuelve variantTaskId. Para landing puedes enviar instructions en texto libre y omitir sectionKey: el backend lo clasifica con IA. No expone ni permite cambiar videoModel, videoTier, videoStyle o narrativeStyle; esos valores se heredan del task origen.", CreateCreativeVariantInputBase.shape, CREATES_PAID, async (input) => {
|
|
19451
19587
|
try {
|
|
19452
19588
|
const validatedInput = parseVariantInput(CreateCreativeVariantInput, input);
|
|
19453
19589
|
const estimateInput = EstimateCreativeVariantInput.parse({
|
|
@@ -19517,32 +19653,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
19517
19653
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
19518
19654
|
|
|
19519
19655
|
// src/tools/script-review.ts
|
|
19520
|
-
import { z as
|
|
19656
|
+
import { z as z75 } from "zod";
|
|
19521
19657
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
19522
19658
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
19523
19659
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
19524
|
-
var GetVideoScriptInput =
|
|
19525
|
-
taskId:
|
|
19526
|
-
angleKey:
|
|
19660
|
+
var GetVideoScriptInput = z75.object({
|
|
19661
|
+
taskId: z75.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
19662
|
+
angleKey: z75.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.')
|
|
19527
19663
|
}).strict();
|
|
19528
19664
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
19529
19665
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
19530
|
-
var ApproveSceneEdit =
|
|
19531
|
-
index:
|
|
19532
|
-
dialogue:
|
|
19666
|
+
var ApproveSceneEdit = z75.object({
|
|
19667
|
+
index: z75.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
19668
|
+
dialogue: z75.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
19533
19669
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
19534
19670
|
}).describe("Di\xE1logo final de la escena. NO puede estar vac\xEDo ni ser s\xF3lo espacios. Puede ser el original sin cambios o la edici\xF3n del usuario.")
|
|
19535
19671
|
}).strict();
|
|
19536
|
-
var ApproveVideoScriptInput =
|
|
19537
|
-
taskId:
|
|
19538
|
-
angleKey:
|
|
19539
|
-
scenes:
|
|
19672
|
+
var ApproveVideoScriptInput = z75.object({
|
|
19673
|
+
taskId: z75.string().min(1).describe("ID de la tarea."),
|
|
19674
|
+
angleKey: z75.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
|
|
19675
|
+
scenes: z75.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
|
|
19540
19676
|
}).strict();
|
|
19541
|
-
var RegenerateVideoScriptInput =
|
|
19542
|
-
taskId:
|
|
19543
|
-
angleKey:
|
|
19677
|
+
var RegenerateVideoScriptInput = z75.object({
|
|
19678
|
+
taskId: z75.string().min(1).describe("ID de la tarea."),
|
|
19679
|
+
angleKey: z75.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
|
|
19544
19680
|
narrativeStyle: NarrativeStyleEnum.describe('Narrativa para el nuevo guion. Incluye valores hist\xF3ricos porque esta herramienta tambi\xE9n regenera tareas antiguas. REQUERIDO \u2014 el backend NO acepta "mantener la actual"; siempre tienes que elegir una. Si el usuario quiere re-rolear con la misma narrativa, pasa la que ya tiene el \xE1ngulo (la ves en get_video_script o en get_task_status).'),
|
|
19545
|
-
narrativeSelection:
|
|
19681
|
+
narrativeSelection: z75.enum([
|
|
19546
19682
|
"market",
|
|
19547
19683
|
"guided"
|
|
19548
19684
|
]).optional().describe("Elecci\xF3n expl\xEDcita del usuario: market usa el estudio de mercado disponible; guided usa la narrativa elegida. Omitir conserva el comportamiento existente.")
|
|
@@ -19602,9 +19738,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
19602
19738
|
// Not CREATES_INTERNAL: approving the script is what STARTS the render, so
|
|
19603
19739
|
// this call dispatches jobs to the video providers and burns credits. Its own
|
|
19604
19740
|
// description says so ("Tras llamarlo, el render arranca y consume créditos").
|
|
19605
|
-
//
|
|
19606
|
-
//
|
|
19607
|
-
|
|
19741
|
+
// `destructiveHint` keeps a host from treating the credit charge as a
|
|
19742
|
+
// reversible bookkeeping update.
|
|
19743
|
+
CREATES_PAID,
|
|
19608
19744
|
async (input) => {
|
|
19609
19745
|
try {
|
|
19610
19746
|
await requirePaidCreativeConfirmation(server, `Aprobar ${input.scenes.length} escena(s) y comenzar el render pagado del video.`);
|
|
@@ -19623,14 +19759,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
19623
19759
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
19624
19760
|
|
|
19625
19761
|
// src/tools/connections.ts
|
|
19626
|
-
import { z as
|
|
19762
|
+
import { z as z76 } from "zod";
|
|
19627
19763
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
19628
19764
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
19629
19765
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
19630
19766
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
19631
19767
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
19632
19768
|
function registerConnectionTools(server, api) {
|
|
19633
|
-
server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
|
|
19769
|
+
server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z76.object({}).shape, READS_INTERNAL, async () => {
|
|
19634
19770
|
try {
|
|
19635
19771
|
const r = await api.getJson("/v1/shopify/shops");
|
|
19636
19772
|
return asText(r);
|
|
@@ -19638,10 +19774,10 @@ function registerConnectionTools(server, api) {
|
|
|
19638
19774
|
throw translateError(e);
|
|
19639
19775
|
}
|
|
19640
19776
|
});
|
|
19641
|
-
server.tool("list_shopify_products", listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.',
|
|
19642
|
-
shopDomain:
|
|
19643
|
-
query:
|
|
19644
|
-
taskId:
|
|
19777
|
+
server.tool("list_shopify_products", listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.', z76.object({
|
|
19778
|
+
shopDomain: z76.string().min(3).max(120),
|
|
19779
|
+
query: z76.string().trim().max(120).optional(),
|
|
19780
|
+
taskId: z76.string().uuid().optional()
|
|
19645
19781
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
19646
19782
|
try {
|
|
19647
19783
|
const params = new URLSearchParams({
|
|
@@ -19655,7 +19791,7 @@ function registerConnectionTools(server, api) {
|
|
|
19655
19791
|
throw translateError(e);
|
|
19656
19792
|
}
|
|
19657
19793
|
});
|
|
19658
|
-
server.tool("list_meta_ad_accounts", listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.",
|
|
19794
|
+
server.tool("list_meta_ad_accounts", listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
|
|
19659
19795
|
try {
|
|
19660
19796
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
19661
19797
|
return asText(r);
|
|
@@ -19665,7 +19801,7 @@ function registerConnectionTools(server, api) {
|
|
|
19665
19801
|
});
|
|
19666
19802
|
server.registerTool("list_meta_destinations", {
|
|
19667
19803
|
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.",
|
|
19668
|
-
inputSchema:
|
|
19804
|
+
inputSchema: z76.object({}).shape,
|
|
19669
19805
|
annotations: READS_EXTERNAL,
|
|
19670
19806
|
_meta: {
|
|
19671
19807
|
"openai/widgetAccessible": true
|
|
@@ -19678,7 +19814,7 @@ function registerConnectionTools(server, api) {
|
|
|
19678
19814
|
throw translateError(e);
|
|
19679
19815
|
}
|
|
19680
19816
|
});
|
|
19681
|
-
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
19817
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
|
|
19682
19818
|
try {
|
|
19683
19819
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
19684
19820
|
return asText(r);
|
|
@@ -19690,10 +19826,10 @@ function registerConnectionTools(server, api) {
|
|
|
19690
19826
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
19691
19827
|
|
|
19692
19828
|
// src/tools/actors.ts
|
|
19693
|
-
import { z as
|
|
19829
|
+
import { z as z77 } from "zod";
|
|
19694
19830
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
19695
19831
|
function registerActorTools(server, api) {
|
|
19696
|
-
server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.",
|
|
19832
|
+
server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z77.object({}).shape, READS_INTERNAL, async () => {
|
|
19697
19833
|
try {
|
|
19698
19834
|
const rows = await api.getJson("/v1/actors");
|
|
19699
19835
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -19714,7 +19850,7 @@ function registerActorTools(server, api) {
|
|
|
19714
19850
|
__name(registerActorTools, "registerActorTools");
|
|
19715
19851
|
|
|
19716
19852
|
// src/tools/publish.ts
|
|
19717
|
-
import { z as
|
|
19853
|
+
import { z as z78 } from "zod";
|
|
19718
19854
|
|
|
19719
19855
|
// src/tools/stable-uuid.ts
|
|
19720
19856
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -19786,40 +19922,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
19786
19922
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
19787
19923
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
19788
19924
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
19789
|
-
var ShopifyInput =
|
|
19790
|
-
taskId:
|
|
19791
|
-
shopDomain:
|
|
19925
|
+
var ShopifyInput = z78.object({
|
|
19926
|
+
taskId: z78.string().min(1),
|
|
19927
|
+
shopDomain: z78.string().min(1),
|
|
19792
19928
|
/** Override: number of landing images to include. Default = ALL images the
|
|
19793
19929
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
19794
19930
|
* generously here; the backend validates each index against
|
|
19795
19931
|
* landing.images.length and rejects out-of-range. */
|
|
19796
|
-
numLandingImages:
|
|
19797
|
-
variantIndex:
|
|
19932
|
+
numLandingImages: z78.number().int().min(1).max(20).optional(),
|
|
19933
|
+
variantIndex: z78.number().int().min(0).optional(),
|
|
19798
19934
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
19799
19935
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
19800
19936
|
* a single-option product page. Defaults to false. */
|
|
19801
|
-
showVariantPicker:
|
|
19937
|
+
showVariantPicker: z78.boolean().optional(),
|
|
19802
19938
|
/** Default `auto` updates the product previously published for this task and
|
|
19803
19939
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
19804
19940
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
19805
|
-
publicationMode:
|
|
19941
|
+
publicationMode: z78.enum([
|
|
19806
19942
|
"auto",
|
|
19807
19943
|
"existing",
|
|
19808
19944
|
"new"
|
|
19809
19945
|
]).optional(),
|
|
19810
19946
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
19811
19947
|
* publicationMode is `existing`. */
|
|
19812
|
-
targetProductId:
|
|
19948
|
+
targetProductId: z78.string().trim().min(1).max(300).optional(),
|
|
19813
19949
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
19814
|
-
announcementBarEnabled:
|
|
19815
|
-
announcementBarText:
|
|
19950
|
+
announcementBarEnabled: z78.boolean().optional(),
|
|
19951
|
+
announcementBarText: z78.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
19816
19952
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
19817
|
-
confirmed:
|
|
19953
|
+
confirmed: z78.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
19818
19954
|
});
|
|
19819
19955
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
19820
19956
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
19821
19957
|
ctx.addIssue({
|
|
19822
|
-
code:
|
|
19958
|
+
code: z78.ZodIssueCode.custom,
|
|
19823
19959
|
path: [
|
|
19824
19960
|
"confirmed"
|
|
19825
19961
|
],
|
|
@@ -19828,7 +19964,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19828
19964
|
}
|
|
19829
19965
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
19830
19966
|
ctx.addIssue({
|
|
19831
|
-
code:
|
|
19967
|
+
code: z78.ZodIssueCode.custom,
|
|
19832
19968
|
path: [
|
|
19833
19969
|
"announcementBarText"
|
|
19834
19970
|
],
|
|
@@ -19837,7 +19973,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19837
19973
|
}
|
|
19838
19974
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
19839
19975
|
ctx.addIssue({
|
|
19840
|
-
code:
|
|
19976
|
+
code: z78.ZodIssueCode.custom,
|
|
19841
19977
|
path: [
|
|
19842
19978
|
"announcementBarText"
|
|
19843
19979
|
],
|
|
@@ -19851,91 +19987,91 @@ function parseShopifyInput(rawInput) {
|
|
|
19851
19987
|
return parsed.data;
|
|
19852
19988
|
}
|
|
19853
19989
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
19854
|
-
var McpCampaignConfig =
|
|
19990
|
+
var McpCampaignConfig = z78.object({
|
|
19855
19991
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
19856
19992
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
19857
19993
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
19858
|
-
dailyBudgetUsd:
|
|
19994
|
+
dailyBudgetUsd: z78.number().positive().optional(),
|
|
19859
19995
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
19860
19996
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
19861
19997
|
* TikTok takes only the first entry. */
|
|
19862
|
-
targetCountries:
|
|
19863
|
-
campaignName:
|
|
19998
|
+
targetCountries: z78.array(CountryIso2Schema).max(1).optional(),
|
|
19999
|
+
campaignName: z78.string().trim().min(1).max(100).optional()
|
|
19864
20000
|
});
|
|
19865
20001
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
19866
|
-
var MetaInput =
|
|
19867
|
-
taskId:
|
|
20002
|
+
var MetaInput = z78.object({
|
|
20003
|
+
taskId: z78.string().min(1),
|
|
19868
20004
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
19869
|
-
portfolioId:
|
|
20005
|
+
portfolioId: z78.string().trim().min(1),
|
|
19870
20006
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
19871
|
-
pageId:
|
|
20007
|
+
pageId: z78.string().trim().min(1),
|
|
19872
20008
|
adAccountId: McpAdAccountId,
|
|
19873
|
-
pixelId:
|
|
19874
|
-
landingUrl:
|
|
20009
|
+
pixelId: z78.string().min(1).optional(),
|
|
20010
|
+
landingUrl: z78.string().url().optional(),
|
|
19875
20011
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
19876
20012
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
19877
|
-
angleIndexes:
|
|
20013
|
+
angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
|
|
19878
20014
|
campaignConfig: McpCampaignConfig.optional(),
|
|
19879
20015
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
19880
20016
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
19881
20017
|
* (Meta's primary-text limit). */
|
|
19882
|
-
primaryText:
|
|
20018
|
+
primaryText: z78.string().trim().min(1).max(500).optional(),
|
|
19883
20019
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
19884
20020
|
* (wa.me) instead of a landing page. */
|
|
19885
|
-
phoneNumber:
|
|
20021
|
+
phoneNumber: z78.string().min(8).max(32).optional()
|
|
19886
20022
|
});
|
|
19887
|
-
var GroupedTaskSource =
|
|
19888
|
-
type:
|
|
19889
|
-
taskId:
|
|
19890
|
-
angleIndex:
|
|
19891
|
-
videoVariant:
|
|
20023
|
+
var GroupedTaskSource = z78.object({
|
|
20024
|
+
type: z78.literal("task"),
|
|
20025
|
+
taskId: z78.string().min(1),
|
|
20026
|
+
angleIndex: z78.number().int().min(0).optional(),
|
|
20027
|
+
videoVariant: z78.enum([
|
|
19892
20028
|
"with_subtitles",
|
|
19893
20029
|
"without_subtitles"
|
|
19894
20030
|
]).optional(),
|
|
19895
|
-
imageVariantIndex:
|
|
19896
|
-
});
|
|
19897
|
-
var GroupedMediaSource =
|
|
19898
|
-
type:
|
|
19899
|
-
url:
|
|
19900
|
-
path:
|
|
19901
|
-
thumbnailUrl:
|
|
19902
|
-
thumbnailPath:
|
|
20031
|
+
imageVariantIndex: z78.number().int().min(0).optional()
|
|
20032
|
+
});
|
|
20033
|
+
var GroupedMediaSource = z78.object({
|
|
20034
|
+
type: z78.literal("media"),
|
|
20035
|
+
url: z78.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
20036
|
+
path: z78.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".'),
|
|
20037
|
+
thumbnailUrl: z78.string().url().optional(),
|
|
20038
|
+
thumbnailPath: z78.string().min(1).optional()
|
|
19903
20039
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
19904
20040
|
message: "media source needs exactly one of `url` or `path`"
|
|
19905
20041
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
19906
20042
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
19907
20043
|
});
|
|
19908
|
-
var GroupedUploadedAssetSource =
|
|
19909
|
-
type:
|
|
20044
|
+
var GroupedUploadedAssetSource = z78.object({
|
|
20045
|
+
type: z78.literal("asset"),
|
|
19910
20046
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
19911
|
-
assetId:
|
|
19912
|
-
thumbnailAssetId:
|
|
20047
|
+
assetId: z78.string().uuid(),
|
|
20048
|
+
thumbnailAssetId: z78.string().uuid().optional()
|
|
19913
20049
|
});
|
|
19914
|
-
var GroupedCreative =
|
|
19915
|
-
type:
|
|
20050
|
+
var GroupedCreative = z78.object({
|
|
20051
|
+
type: z78.enum([
|
|
19916
20052
|
"image",
|
|
19917
20053
|
"video"
|
|
19918
20054
|
]),
|
|
19919
|
-
source:
|
|
20055
|
+
source: z78.union([
|
|
19920
20056
|
GroupedTaskSource,
|
|
19921
20057
|
GroupedMediaSource,
|
|
19922
20058
|
GroupedUploadedAssetSource
|
|
19923
20059
|
]),
|
|
19924
|
-
title:
|
|
19925
|
-
description:
|
|
20060
|
+
title: z78.string().max(120).optional(),
|
|
20061
|
+
description: z78.string().max(500).optional(),
|
|
19926
20062
|
cta: MetaCtaType.optional(),
|
|
19927
|
-
creativeId:
|
|
20063
|
+
creativeId: z78.string().min(1).optional()
|
|
19928
20064
|
});
|
|
19929
|
-
var GroupedCampaignConfigBase =
|
|
20065
|
+
var GroupedCampaignConfigBase = z78.object({
|
|
19930
20066
|
campaignType: MetaCampaignType.default("sales"),
|
|
19931
20067
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
19932
20068
|
budgetMode: MetaBudgetMode.optional(),
|
|
19933
|
-
campaignDailyBudget:
|
|
19934
|
-
adSets:
|
|
19935
|
-
tempId:
|
|
19936
|
-
name:
|
|
19937
|
-
dailyBudget:
|
|
19938
|
-
creativeIds:
|
|
20069
|
+
campaignDailyBudget: z78.number().int().positive().optional(),
|
|
20070
|
+
adSets: z78.array(z78.object({
|
|
20071
|
+
tempId: z78.string().min(1).max(80),
|
|
20072
|
+
name: z78.string().min(1).max(100),
|
|
20073
|
+
dailyBudget: z78.number().int().positive().optional(),
|
|
20074
|
+
creativeIds: z78.array(z78.string().min(1)).min(1)
|
|
19939
20075
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
19940
20076
|
/**
|
|
19941
20077
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -19943,17 +20079,17 @@ var GroupedCampaignConfigBase = z77.object({
|
|
|
19943
20079
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
19944
20080
|
* the API since #849 — unreachable from this tool.
|
|
19945
20081
|
*/
|
|
19946
|
-
destination:
|
|
19947
|
-
|
|
19948
|
-
type:
|
|
19949
|
-
landingUrl:
|
|
20082
|
+
destination: z78.discriminatedUnion("type", [
|
|
20083
|
+
z78.object({
|
|
20084
|
+
type: z78.literal("landing"),
|
|
20085
|
+
landingUrl: z78.string().url()
|
|
19950
20086
|
}),
|
|
19951
|
-
|
|
19952
|
-
type:
|
|
19953
|
-
phoneNumber:
|
|
20087
|
+
z78.object({
|
|
20088
|
+
type: z78.literal("whatsapp"),
|
|
20089
|
+
phoneNumber: z78.string().min(8).max(32)
|
|
19954
20090
|
})
|
|
19955
20091
|
]),
|
|
19956
|
-
saveAsDefault:
|
|
20092
|
+
saveAsDefault: z78.boolean().default(false),
|
|
19957
20093
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
19958
20094
|
});
|
|
19959
20095
|
function resolveBudgetMode(value) {
|
|
@@ -19967,7 +20103,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19967
20103
|
const budgetMode = resolveBudgetMode(value);
|
|
19968
20104
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
19969
20105
|
ctx.addIssue({
|
|
19970
|
-
code:
|
|
20106
|
+
code: z78.ZodIssueCode.custom,
|
|
19971
20107
|
path: [
|
|
19972
20108
|
"campaignDailyBudget"
|
|
19973
20109
|
],
|
|
@@ -19978,7 +20114,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19978
20114
|
value.adSets.forEach((adSet, index) => {
|
|
19979
20115
|
if (adSet.dailyBudget === void 0) {
|
|
19980
20116
|
ctx.addIssue({
|
|
19981
|
-
code:
|
|
20117
|
+
code: z78.ZodIssueCode.custom,
|
|
19982
20118
|
path: [
|
|
19983
20119
|
"adSets",
|
|
19984
20120
|
index,
|
|
@@ -19993,28 +20129,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19993
20129
|
...value,
|
|
19994
20130
|
budgetMode: resolveBudgetMode(value)
|
|
19995
20131
|
}));
|
|
19996
|
-
var PublishCreativesToMetaInputBase =
|
|
19997
|
-
creatives:
|
|
20132
|
+
var PublishCreativesToMetaInputBase = z78.object({
|
|
20133
|
+
creatives: z78.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
19998
20134
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
19999
|
-
portfolioId:
|
|
20135
|
+
portfolioId: z78.string().trim().min(1),
|
|
20000
20136
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
20001
|
-
pageId:
|
|
20137
|
+
pageId: z78.string().trim().min(1),
|
|
20002
20138
|
adAccountId: McpAdAccountId,
|
|
20003
|
-
pixelId:
|
|
20139
|
+
pixelId: z78.string().min(1).optional(),
|
|
20004
20140
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
20005
20141
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
20006
|
-
landingUrl:
|
|
20142
|
+
landingUrl: z78.string().url().optional(),
|
|
20007
20143
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
20008
20144
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
20009
20145
|
targetCountry: CountryIso2Schema,
|
|
20010
|
-
campaignName:
|
|
20146
|
+
campaignName: z78.string().trim().min(1).max(100),
|
|
20011
20147
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
20012
20148
|
});
|
|
20013
20149
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
20014
20150
|
const destination = value.campaignConfig?.destination;
|
|
20015
20151
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
20016
20152
|
ctx.addIssue({
|
|
20017
|
-
code:
|
|
20153
|
+
code: z78.ZodIssueCode.custom,
|
|
20018
20154
|
path: [
|
|
20019
20155
|
"landingUrl"
|
|
20020
20156
|
],
|
|
@@ -20023,7 +20159,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20023
20159
|
}
|
|
20024
20160
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
20025
20161
|
ctx.addIssue({
|
|
20026
|
-
code:
|
|
20162
|
+
code: z78.ZodIssueCode.custom,
|
|
20027
20163
|
path: [
|
|
20028
20164
|
"campaignConfig",
|
|
20029
20165
|
"destination",
|
|
@@ -20042,16 +20178,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
20042
20178
|
}
|
|
20043
20179
|
return value;
|
|
20044
20180
|
});
|
|
20045
|
-
var PresignUploadResponseSchema =
|
|
20046
|
-
uploadUrl:
|
|
20181
|
+
var PresignUploadResponseSchema = z78.object({
|
|
20182
|
+
uploadUrl: z78.string().url().refine((value) => {
|
|
20047
20183
|
const url = new URL(value);
|
|
20048
20184
|
return !url.username && !url.password && url.protocol === "https:";
|
|
20049
20185
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
20050
|
-
publicUrl:
|
|
20186
|
+
publicUrl: z78.string().url().refine((value) => {
|
|
20051
20187
|
const url = new URL(value);
|
|
20052
20188
|
return !url.username && !url.password;
|
|
20053
20189
|
}, "public media URL must not contain embedded credentials"),
|
|
20054
|
-
stagingAssetId:
|
|
20190
|
+
stagingAssetId: z78.string().uuid()
|
|
20055
20191
|
});
|
|
20056
20192
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
20057
20193
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -20076,16 +20212,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
20076
20212
|
return uploadResolvedMedia(api, media, assetRole);
|
|
20077
20213
|
}
|
|
20078
20214
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
20079
|
-
var TikTokInput =
|
|
20080
|
-
taskId:
|
|
20081
|
-
advertiserId:
|
|
20082
|
-
pixelId:
|
|
20083
|
-
landingUrl:
|
|
20084
|
-
angleIndexes:
|
|
20215
|
+
var TikTokInput = z78.object({
|
|
20216
|
+
taskId: z78.string().min(1),
|
|
20217
|
+
advertiserId: z78.string().min(1),
|
|
20218
|
+
pixelId: z78.string().min(1).optional(),
|
|
20219
|
+
landingUrl: z78.string().url().optional(),
|
|
20220
|
+
angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
|
|
20085
20221
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20086
20222
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
20087
20223
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
20088
|
-
primaryText:
|
|
20224
|
+
primaryText: z78.string().trim().min(1).max(500).optional()
|
|
20089
20225
|
});
|
|
20090
20226
|
function registerPublishTools(server, api, opts = {}) {
|
|
20091
20227
|
const transport = opts.transport ?? "http";
|
|
@@ -20413,39 +20549,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
20413
20549
|
|
|
20414
20550
|
// src/tools/meta-upload.ts
|
|
20415
20551
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
20416
|
-
import { z as
|
|
20552
|
+
import { z as z79 } from "zod";
|
|
20417
20553
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
20418
|
-
var UploadSessionInputBase =
|
|
20419
|
-
mediaKind:
|
|
20554
|
+
var UploadSessionInputBase = z79.object({
|
|
20555
|
+
mediaKind: z79.enum([
|
|
20420
20556
|
"image",
|
|
20421
20557
|
"video",
|
|
20422
20558
|
"mixed"
|
|
20423
20559
|
]).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."),
|
|
20424
|
-
assetRole:
|
|
20560
|
+
assetRole: z79.enum([
|
|
20425
20561
|
"media",
|
|
20426
20562
|
"thumbnail"
|
|
20427
20563
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
20428
|
-
uploadPurpose:
|
|
20564
|
+
uploadPurpose: z79.enum([
|
|
20429
20565
|
"product_reference",
|
|
20430
20566
|
"creative",
|
|
20431
20567
|
"generic"
|
|
20432
20568
|
]).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."),
|
|
20433
|
-
maxFiles:
|
|
20569
|
+
maxFiles: z79.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
20434
20570
|
});
|
|
20435
|
-
var OpenAiFileReference =
|
|
20436
|
-
download_url:
|
|
20437
|
-
file_id:
|
|
20438
|
-
mime_type:
|
|
20439
|
-
file_name:
|
|
20571
|
+
var OpenAiFileReference = z79.object({
|
|
20572
|
+
download_url: z79.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."),
|
|
20573
|
+
file_id: z79.string().min(1),
|
|
20574
|
+
mime_type: z79.string().min(1).optional(),
|
|
20575
|
+
file_name: z79.string().min(1).optional()
|
|
20440
20576
|
});
|
|
20441
20577
|
var UploadSessionToolInputShape = {
|
|
20442
20578
|
...UploadSessionInputBase.shape,
|
|
20443
|
-
files:
|
|
20579
|
+
files: z79.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.")
|
|
20444
20580
|
};
|
|
20445
|
-
var UploadSessionToolInput =
|
|
20581
|
+
var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
20446
20582
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
20447
20583
|
ctx.addIssue({
|
|
20448
|
-
code:
|
|
20584
|
+
code: z79.ZodIssueCode.custom,
|
|
20449
20585
|
path: [
|
|
20450
20586
|
"mediaKind"
|
|
20451
20587
|
],
|
|
@@ -20454,7 +20590,7 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20454
20590
|
}
|
|
20455
20591
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
20456
20592
|
ctx.addIssue({
|
|
20457
|
-
code:
|
|
20593
|
+
code: z79.ZodIssueCode.custom,
|
|
20458
20594
|
path: [
|
|
20459
20595
|
"maxFiles"
|
|
20460
20596
|
],
|
|
@@ -20463,7 +20599,7 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20463
20599
|
}
|
|
20464
20600
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
20465
20601
|
ctx.addIssue({
|
|
20466
|
-
code:
|
|
20602
|
+
code: z79.ZodIssueCode.custom,
|
|
20467
20603
|
path: [
|
|
20468
20604
|
"maxFiles"
|
|
20469
20605
|
],
|
|
@@ -20471,38 +20607,38 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20471
20607
|
});
|
|
20472
20608
|
}
|
|
20473
20609
|
});
|
|
20474
|
-
var UploadSessionResponse =
|
|
20475
|
-
sessionId:
|
|
20476
|
-
uploadPageUrl:
|
|
20477
|
-
mediaKind:
|
|
20610
|
+
var UploadSessionResponse = z79.object({
|
|
20611
|
+
sessionId: z79.string().uuid(),
|
|
20612
|
+
uploadPageUrl: z79.string().url(),
|
|
20613
|
+
mediaKind: z79.enum([
|
|
20478
20614
|
"image",
|
|
20479
20615
|
"video",
|
|
20480
20616
|
"mixed"
|
|
20481
20617
|
]),
|
|
20482
|
-
assetRole:
|
|
20618
|
+
assetRole: z79.enum([
|
|
20483
20619
|
"media",
|
|
20484
20620
|
"thumbnail"
|
|
20485
20621
|
]),
|
|
20486
|
-
maxFiles:
|
|
20487
|
-
expiresAt:
|
|
20622
|
+
maxFiles: z79.number().int().positive(),
|
|
20623
|
+
expiresAt: z79.string().datetime()
|
|
20488
20624
|
});
|
|
20489
|
-
var UploadStatusInput =
|
|
20490
|
-
sessionId:
|
|
20625
|
+
var UploadStatusInput = z79.object({
|
|
20626
|
+
sessionId: z79.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
20491
20627
|
});
|
|
20492
|
-
var UniversalUploadStatusResponse =
|
|
20493
|
-
|
|
20494
|
-
status:
|
|
20495
|
-
assets:
|
|
20628
|
+
var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
|
|
20629
|
+
z79.object({
|
|
20630
|
+
status: z79.literal("pending"),
|
|
20631
|
+
assets: z79.array(z79.never()).length(0)
|
|
20496
20632
|
}),
|
|
20497
|
-
|
|
20498
|
-
status:
|
|
20499
|
-
assets:
|
|
20500
|
-
assetId:
|
|
20501
|
-
mediaKind:
|
|
20633
|
+
z79.object({
|
|
20634
|
+
status: z79.literal("uploaded"),
|
|
20635
|
+
assets: z79.array(z79.object({
|
|
20636
|
+
assetId: z79.string().uuid(),
|
|
20637
|
+
mediaKind: z79.enum([
|
|
20502
20638
|
"image",
|
|
20503
20639
|
"video"
|
|
20504
20640
|
]),
|
|
20505
|
-
assetRole:
|
|
20641
|
+
assetRole: z79.enum([
|
|
20506
20642
|
"media",
|
|
20507
20643
|
"thumbnail"
|
|
20508
20644
|
])
|
|
@@ -20510,13 +20646,13 @@ var UniversalUploadStatusResponse = z78.discriminatedUnion("status", [
|
|
|
20510
20646
|
})
|
|
20511
20647
|
]);
|
|
20512
20648
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
20513
|
-
uploadPurpose:
|
|
20649
|
+
uploadPurpose: z79.enum([
|
|
20514
20650
|
"product_reference",
|
|
20515
20651
|
"creative",
|
|
20516
20652
|
"generic"
|
|
20517
20653
|
]),
|
|
20518
|
-
checkToolName:
|
|
20519
|
-
resolveEndpoint:
|
|
20654
|
+
checkToolName: z79.literal("check_media_upload"),
|
|
20655
|
+
resolveEndpoint: z79.string().url()
|
|
20520
20656
|
});
|
|
20521
20657
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
20522
20658
|
const url = new URL(uploadPageUrl);
|
|
@@ -20548,7 +20684,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
|
|
|
20548
20684
|
function registerMediaUploadTools(server, api) {
|
|
20549
20685
|
registerAppTool(server, "request_media_upload", {
|
|
20550
20686
|
title: "Subir archivos",
|
|
20551
|
-
description: requestMediaUploadGuidance.summary + " Cuando la foto o el video sea el siguiente dato faltante, ll\xE1malo en esa misma respuesta: no te limites a pedir que lo adjunte en el chat y esperar otro turno. Ll\xE1malo tambi\xE9n autom\xE1ticamente y antes de preguntar por campos faltantes adicionales cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias
|
|
20687
|
+
description: requestMediaUploadGuidance.summary + " Cuando la foto o el video sea el siguiente dato faltante, ll\xE1malo en esa misma respuesta: no te limites a pedir que lo adjunte en el chat y esperar otro turno. Ll\xE1malo tambi\xE9n autom\xE1ticamente y antes de preguntar por campos faltantes adicionales cuando una petici\xF3n natural adjunte o mencione un archivo local, por ejemplo \u2018crea una landing con este producto\u2019, \u2018haz creativos con esta foto\u2019 o \u2018sube este video a Meta\u2019; hazlo aunque el usuario diga que todav\xEDa no generes ni publiques, porque esta herramienta solo prepara el archivo y no consume cr\xE9ditos, salvo que proh\xEDba expl\xEDcitamente subir, compartir o almacenar el archivo; no pidas una ruta local ni URL. Es la \xFAnica ruta de carga para create_product_task, generate_image_creatives, generate_video_creative, generate_free_video, generate_landing y publish_creatives_to_meta. Pasa las referencias de ChatGPT en files con download_url y file_id. Si otro host no puede proporcionar ambos, omite files para que el App abra el selector inline o el enlace de carga. Usa uploadPurpose=product_reference para fotos de producto y landings, creative para creativos o anuncios, y generic solo cuando ninguno aplique. Usa mediaKind=image para referencias de producto y landings; mixed solo cuando el consumidor acepte ambos tipos. El App NO te avisa cuando termina: en cuanto el usuario diga que ya subi\xF3 el archivo o que sigas, llama `check_media_upload` con este sessionId para obtener los assetId, y reanuda la intenci\xF3n original usando \xFAnicamente assetId y mediaKind, sin pedir que vuelva a subir ni mostrar datos t\xE9cnicos. El enlace externo es fallback solo si el App inline falla. Esta herramienta no genera, publica ni consume cr\xE9ditos.",
|
|
20552
20688
|
inputSchema: UploadSessionToolInputShape,
|
|
20553
20689
|
annotations: CREATES_INTERNAL,
|
|
20554
20690
|
outputSchema: UniversalUploadStructuredResponse.shape,
|
|
@@ -20607,15 +20743,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
20607
20743
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
20608
20744
|
|
|
20609
20745
|
// src/tools/campaigns.ts
|
|
20610
|
-
import { z as
|
|
20746
|
+
import { z as z80 } from "zod";
|
|
20611
20747
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
20612
20748
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
20613
|
-
var MetaStatusInput =
|
|
20614
|
-
campaignId:
|
|
20749
|
+
var MetaStatusInput = z80.object({
|
|
20750
|
+
campaignId: z80.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
20615
20751
|
});
|
|
20616
|
-
var TikTokStatusInput =
|
|
20617
|
-
campaignId:
|
|
20618
|
-
advertiserId:
|
|
20752
|
+
var TikTokStatusInput = z80.object({
|
|
20753
|
+
campaignId: z80.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
20754
|
+
advertiserId: z80.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
20619
20755
|
});
|
|
20620
20756
|
function registerCampaignTools(server, api) {
|
|
20621
20757
|
server.tool("get_meta_campaign_status", getMetaCampaignStatusGuidance.summary + " Llama esto DESPU\xC9S de `publish_to_meta` para confirmar que la campa\xF1a se cre\xF3 correctamente y para reportar performance al usuario. Es read-only \u2014 no modifica nada en Meta Ads Manager.", MetaStatusInput.shape, READS_EXTERNAL, async (input) => {
|
|
@@ -20712,10 +20848,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
20712
20848
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
20713
20849
|
|
|
20714
20850
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20715
|
-
import { z as
|
|
20851
|
+
import { z as z82 } from "zod";
|
|
20716
20852
|
|
|
20717
20853
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20718
|
-
import { z as
|
|
20854
|
+
import { z as z81 } from "zod";
|
|
20719
20855
|
|
|
20720
20856
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
20721
20857
|
var product_costing_shipping_references_default = {
|
|
@@ -20779,21 +20915,21 @@ var product_costing_shipping_references_default = {
|
|
|
20779
20915
|
};
|
|
20780
20916
|
|
|
20781
20917
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20782
|
-
var ShippingReferenceSchema =
|
|
20783
|
-
reference:
|
|
20784
|
-
min:
|
|
20785
|
-
max:
|
|
20786
|
-
updatedAt:
|
|
20787
|
-
confidence:
|
|
20918
|
+
var ShippingReferenceSchema = z81.object({
|
|
20919
|
+
reference: z81.number().positive(),
|
|
20920
|
+
min: z81.number().nonnegative(),
|
|
20921
|
+
max: z81.number().positive(),
|
|
20922
|
+
updatedAt: z81.string().date(),
|
|
20923
|
+
confidence: z81.enum([
|
|
20788
20924
|
"high",
|
|
20789
20925
|
"medium",
|
|
20790
20926
|
"medium-low"
|
|
20791
20927
|
]),
|
|
20792
|
-
sources:
|
|
20928
|
+
sources: z81.array(z81.string().url().startsWith("https://")).min(1).max(3)
|
|
20793
20929
|
}).superRefine(({ reference, min, max }, context) => {
|
|
20794
20930
|
if (min > reference || reference > max) {
|
|
20795
20931
|
context.addIssue({
|
|
20796
|
-
code:
|
|
20932
|
+
code: z81.ZodIssueCode.custom,
|
|
20797
20933
|
message: "shipping_reference_outside_range",
|
|
20798
20934
|
path: [
|
|
20799
20935
|
"reference"
|
|
@@ -20801,7 +20937,7 @@ var ShippingReferenceSchema = z80.object({
|
|
|
20801
20937
|
});
|
|
20802
20938
|
}
|
|
20803
20939
|
});
|
|
20804
|
-
var SHIPPING_REFERENCES =
|
|
20940
|
+
var SHIPPING_REFERENCES = z81.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
20805
20941
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
20806
20942
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
20807
20943
|
"MX",
|
|
@@ -20983,18 +21119,18 @@ function getProductCostingCountryName(country) {
|
|
|
20983
21119
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
20984
21120
|
|
|
20985
21121
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20986
|
-
var ProductCostingInputSchema =
|
|
20987
|
-
country:
|
|
20988
|
-
supplierCost:
|
|
20989
|
-
shippingCost:
|
|
20990
|
-
returnRate:
|
|
20991
|
-
cancellationRate:
|
|
20992
|
-
adsManagerCpa:
|
|
20993
|
-
desiredMargin:
|
|
21122
|
+
var ProductCostingInputSchema = z82.object({
|
|
21123
|
+
country: z82.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
21124
|
+
supplierCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
21125
|
+
shippingCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
21126
|
+
returnRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21127
|
+
cancellationRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21128
|
+
adsManagerCpa: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
21129
|
+
desiredMargin: z82.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
20994
21130
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
20995
21131
|
if (returnRate + cancellationRate >= 1) {
|
|
20996
21132
|
context.addIssue({
|
|
20997
|
-
code:
|
|
21133
|
+
code: z82.ZodIssueCode.custom,
|
|
20998
21134
|
message: "delivery_rate_positive",
|
|
20999
21135
|
path: [
|
|
21000
21136
|
"cancellationRate"
|
|
@@ -21091,15 +21227,15 @@ function calculateProductCosting(rawInput) {
|
|
|
21091
21227
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
21092
21228
|
|
|
21093
21229
|
// src/tools/product-costing.ts
|
|
21094
|
-
import { z as
|
|
21230
|
+
import { z as z83 } from "zod";
|
|
21095
21231
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
21096
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
21097
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
21098
|
-
var ProductCostingToolInput =
|
|
21099
|
-
country:
|
|
21232
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z83.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
21233
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z83.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
21234
|
+
var ProductCostingToolInput = z83.object({
|
|
21235
|
+
country: z83.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21100
21236
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21101
21237
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
21102
|
-
supplierCost:
|
|
21238
|
+
supplierCost: z83.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."),
|
|
21103
21239
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
21104
21240
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
21105
21241
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -21258,7 +21394,7 @@ function formatPercent(value) {
|
|
|
21258
21394
|
__name(formatPercent, "formatPercent");
|
|
21259
21395
|
|
|
21260
21396
|
// src/tools/product-research.ts
|
|
21261
|
-
import { z as
|
|
21397
|
+
import { z as z84 } from "zod";
|
|
21262
21398
|
|
|
21263
21399
|
// src/tools/product-research-idempotency.ts
|
|
21264
21400
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -21629,17 +21765,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
21629
21765
|
]);
|
|
21630
21766
|
var POLL_INTERVAL_MS = 5e3;
|
|
21631
21767
|
var MAX_WAIT_SECONDS = 120;
|
|
21632
|
-
var FindInput =
|
|
21768
|
+
var FindInput = z84.object({
|
|
21633
21769
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
21634
21770
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
21635
|
-
confirmed:
|
|
21636
|
-
waitSeconds:
|
|
21771
|
+
confirmed: z84.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
21772
|
+
waitSeconds: z84.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
21637
21773
|
});
|
|
21638
|
-
var GetInput =
|
|
21639
|
-
runId:
|
|
21774
|
+
var GetInput = z84.object({
|
|
21775
|
+
runId: z84.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
21640
21776
|
});
|
|
21641
|
-
var ListInput =
|
|
21642
|
-
limit:
|
|
21777
|
+
var ListInput = z84.object({
|
|
21778
|
+
limit: z84.number().int().min(1).max(20).default(10)
|
|
21643
21779
|
});
|
|
21644
21780
|
function textResult(text) {
|
|
21645
21781
|
return {
|
|
@@ -21676,7 +21812,7 @@ async function pollUntilTerminal(api, runId, waitSeconds) {
|
|
|
21676
21812
|
}
|
|
21677
21813
|
__name(pollUntilTerminal, "pollUntilTerminal");
|
|
21678
21814
|
function registerProductResearchTools(server, api) {
|
|
21679
|
-
server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape,
|
|
21815
|
+
server.tool("find_winning_products", `${findWinningProductsGuidance.summary} CUESTA ${PRICE_CREDITS} CR\xC9DITOS por ejecuci\xF3n. ANTES de invocar, dile al usuario el costo y espera su aceptaci\xF3n expl\xEDcita; s\xF3lo entonces pasa confirmed: true. Consulta primero list_product_research_runs (GRATIS) \u2014 puede que el usuario ya tenga un reporte pagado para ese pa\xEDs/categor\xEDa y no necesites cobrar de nuevo. Pa\xEDses disponibles: CO, MX, PE, EC, CL. Tarda varios minutos: usa waitSeconds para esperar, y si expira consulta el resultado con get_product_research_run \u2014 el reporte NO se pierde.`, FindInput.shape, CREATES_PAID_OPEN_WORLD, async (input) => {
|
|
21680
21816
|
const parsed = FindInput.parse(input);
|
|
21681
21817
|
if (!parsed.confirmed) {
|
|
21682
21818
|
throw mcp(McpErrorCode.INVALID_INPUT, `This research run costs ${PRICE_CREDITS} credits. Tell the user the cost, get an explicit yes, then call again with confirmed: true.`);
|
|
@@ -21731,7 +21867,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
21731
21867
|
throw translateError(error);
|
|
21732
21868
|
}
|
|
21733
21869
|
});
|
|
21734
|
-
server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape,
|
|
21870
|
+
server.tool("prepare_winning_product_image", prepareWinningProductImageGuidance.summary + " GRATIS. \xDAsalo s\xF3lo despu\xE9s de que el usuario elija un candidato del reporte. Importa de forma segura la foto exacta a ProductMaker, la muestra y luego pide elegir: usarla, usarla y agregar m\xE1s, o subir s\xF3lo fotos propias.", WinnerReferenceInput.shape, CREATES_OPEN_WORLD, async (input) => {
|
|
21735
21871
|
const parsed = WinnerReferenceInput.parse(input);
|
|
21736
21872
|
try {
|
|
21737
21873
|
const prepared = WinningProductPreparedImageSchema.parse(await api.postJson(`/v1/product-research/runs/${encodeURIComponent(parsed.runId)}/candidates/${encodeURIComponent(parsed.candidateSourceId)}/image-asset`, {}));
|
|
@@ -21762,17 +21898,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
21762
21898
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
21763
21899
|
|
|
21764
21900
|
// src/tools/dropshipping-projects.ts
|
|
21765
|
-
import { z as
|
|
21901
|
+
import { z as z85 } from "zod";
|
|
21766
21902
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
21767
21903
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
21768
21904
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
21769
|
-
var ProjectId =
|
|
21770
|
-
var DropshippingProjectStatus =
|
|
21905
|
+
var ProjectId = z85.string().uuid();
|
|
21906
|
+
var DropshippingProjectStatus = z85.enum([
|
|
21771
21907
|
"active",
|
|
21772
21908
|
"completed",
|
|
21773
21909
|
"archived"
|
|
21774
21910
|
]);
|
|
21775
|
-
var DropshippingProjectPhase =
|
|
21911
|
+
var DropshippingProjectPhase = z85.enum([
|
|
21776
21912
|
"research",
|
|
21777
21913
|
"costing",
|
|
21778
21914
|
"media",
|
|
@@ -21781,21 +21917,21 @@ var DropshippingProjectPhase = z84.enum([
|
|
|
21781
21917
|
"advertising",
|
|
21782
21918
|
"complete"
|
|
21783
21919
|
]);
|
|
21784
|
-
var DropshippingRewardMilestone =
|
|
21920
|
+
var DropshippingRewardMilestone = z85.enum([
|
|
21785
21921
|
"product_selected",
|
|
21786
21922
|
"costing_saved",
|
|
21787
21923
|
"product_media_ready",
|
|
21788
21924
|
"creatives_completed",
|
|
21789
21925
|
"campaign_created"
|
|
21790
21926
|
]);
|
|
21791
|
-
var TargetCountry =
|
|
21927
|
+
var TargetCountry = z85.enum([
|
|
21792
21928
|
"CO",
|
|
21793
21929
|
"MX",
|
|
21794
21930
|
"PE",
|
|
21795
21931
|
"EC",
|
|
21796
21932
|
"CL"
|
|
21797
21933
|
]);
|
|
21798
|
-
var ResearchCategory =
|
|
21934
|
+
var ResearchCategory = z85.enum([
|
|
21799
21935
|
"auto",
|
|
21800
21936
|
"automotive",
|
|
21801
21937
|
"kitchen",
|
|
@@ -21810,7 +21946,7 @@ var ResearchCategory = z84.enum([
|
|
|
21810
21946
|
"garden",
|
|
21811
21947
|
"cleaning"
|
|
21812
21948
|
]);
|
|
21813
|
-
var HttpUrl3 =
|
|
21949
|
+
var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
|
|
21814
21950
|
try {
|
|
21815
21951
|
return [
|
|
21816
21952
|
"http:",
|
|
@@ -21820,45 +21956,45 @@ var HttpUrl3 = z84.string().url().max(2e3).refine((value) => {
|
|
|
21820
21956
|
return false;
|
|
21821
21957
|
}
|
|
21822
21958
|
}, "URL must use HTTP(S)");
|
|
21823
|
-
var ResearchCandidateOrigin =
|
|
21824
|
-
type:
|
|
21959
|
+
var ResearchCandidateOrigin = z85.object({
|
|
21960
|
+
type: z85.literal("research_candidate"),
|
|
21825
21961
|
runId: ProjectId,
|
|
21826
|
-
candidateSourceId:
|
|
21962
|
+
candidateSourceId: z85.string().min(1).max(160)
|
|
21827
21963
|
});
|
|
21828
|
-
var TaskOrigin =
|
|
21829
|
-
type:
|
|
21964
|
+
var TaskOrigin = z85.object({
|
|
21965
|
+
type: z85.literal("task"),
|
|
21830
21966
|
taskId: ProjectId
|
|
21831
21967
|
});
|
|
21832
|
-
var ManualOrigin =
|
|
21833
|
-
type:
|
|
21968
|
+
var ManualOrigin = z85.object({
|
|
21969
|
+
type: z85.literal("manual"),
|
|
21834
21970
|
clientRequestId: ProjectId,
|
|
21835
|
-
country:
|
|
21971
|
+
country: z85.string().min(2).max(3).optional()
|
|
21836
21972
|
});
|
|
21837
|
-
var StartProjectInput =
|
|
21838
|
-
origin:
|
|
21973
|
+
var StartProjectInput = z85.object({
|
|
21974
|
+
origin: z85.discriminatedUnion("type", [
|
|
21839
21975
|
ResearchCandidateOrigin,
|
|
21840
21976
|
TaskOrigin,
|
|
21841
21977
|
ManualOrigin
|
|
21842
21978
|
]),
|
|
21843
|
-
productName:
|
|
21979
|
+
productName: z85.string().trim().min(1).max(240).optional(),
|
|
21844
21980
|
productUrl: HttpUrl3.optional(),
|
|
21845
|
-
country:
|
|
21846
|
-
languageCode:
|
|
21981
|
+
country: z85.string().min(2).max(3).optional(),
|
|
21982
|
+
languageCode: z85.string().min(2).max(16).optional()
|
|
21847
21983
|
}).strict();
|
|
21848
|
-
var CostProjectInput =
|
|
21984
|
+
var CostProjectInput = z85.object({
|
|
21849
21985
|
projectId: ProjectId,
|
|
21850
|
-
version:
|
|
21851
|
-
country:
|
|
21986
|
+
version: z85.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
21987
|
+
country: z85.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21852
21988
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21853
21989
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
21854
|
-
supplierCost:
|
|
21855
|
-
shippingCost:
|
|
21856
|
-
returnRate:
|
|
21857
|
-
cancellationRate:
|
|
21858
|
-
adsManagerCpa:
|
|
21859
|
-
desiredMargin:
|
|
21860
|
-
});
|
|
21861
|
-
var GuideInput =
|
|
21990
|
+
supplierCost: z85.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."),
|
|
21991
|
+
shippingCost: z85.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
21992
|
+
returnRate: z85.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."),
|
|
21993
|
+
cancellationRate: z85.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."),
|
|
21994
|
+
adsManagerCpa: z85.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
21995
|
+
desiredMargin: z85.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
21996
|
+
});
|
|
21997
|
+
var GuideInput = z85.object({
|
|
21862
21998
|
projectId: ProjectId.optional()
|
|
21863
21999
|
}).strict();
|
|
21864
22000
|
var NEXT_ACTION_KINDS = [
|
|
@@ -21876,29 +22012,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
21876
22012
|
"repair_meta_campaign",
|
|
21877
22013
|
"review_paused_campaign"
|
|
21878
22014
|
];
|
|
21879
|
-
var DropshippingProjectNextAction =
|
|
21880
|
-
kind:
|
|
21881
|
-
href:
|
|
22015
|
+
var DropshippingProjectNextAction = z85.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z85.object({
|
|
22016
|
+
kind: z85.literal(kind),
|
|
22017
|
+
href: z85.string().min(1)
|
|
21882
22018
|
})));
|
|
21883
|
-
var CostingInputSchema =
|
|
21884
|
-
country:
|
|
21885
|
-
supplierCost:
|
|
21886
|
-
shippingCost:
|
|
21887
|
-
returnRate:
|
|
21888
|
-
cancellationRate:
|
|
21889
|
-
adsManagerCpa:
|
|
21890
|
-
desiredMargin:
|
|
22019
|
+
var CostingInputSchema = z85.object({
|
|
22020
|
+
country: z85.string().min(2).max(3),
|
|
22021
|
+
supplierCost: z85.number().finite().positive(),
|
|
22022
|
+
shippingCost: z85.number().finite().nonnegative(),
|
|
22023
|
+
returnRate: z85.number().finite().min(0).lt(1),
|
|
22024
|
+
cancellationRate: z85.number().finite().min(0).lt(1),
|
|
22025
|
+
adsManagerCpa: z85.number().finite().nonnegative(),
|
|
22026
|
+
desiredMargin: z85.number().finite().min(0).lt(1)
|
|
21891
22027
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
21892
22028
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
21893
|
-
code:
|
|
22029
|
+
code: z85.ZodIssueCode.custom,
|
|
21894
22030
|
path: [
|
|
21895
22031
|
"cancellationRate"
|
|
21896
22032
|
]
|
|
21897
22033
|
});
|
|
21898
22034
|
});
|
|
21899
|
-
var FiniteCostingNumber =
|
|
21900
|
-
var CostingResultSchema =
|
|
21901
|
-
country:
|
|
22035
|
+
var FiniteCostingNumber = z85.number().finite();
|
|
22036
|
+
var CostingResultSchema = z85.object({
|
|
22037
|
+
country: z85.string().min(2).max(3),
|
|
21902
22038
|
deliveryRate: FiniteCostingNumber,
|
|
21903
22039
|
adjustedShippingCost: FiniteCostingNumber,
|
|
21904
22040
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -21911,45 +22047,45 @@ var CostingResultSchema = z84.object({
|
|
|
21911
22047
|
estimatedProfit: FiniteCostingNumber,
|
|
21912
22048
|
actualMargin: FiniteCostingNumber,
|
|
21913
22049
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
21914
|
-
wasPriceAutoAdjusted:
|
|
21915
|
-
profitabilityStatus:
|
|
21916
|
-
});
|
|
21917
|
-
var RewardProgressSchema =
|
|
21918
|
-
campaignKey:
|
|
21919
|
-
totalCredits:
|
|
21920
|
-
earnedCredits:
|
|
21921
|
-
milestones:
|
|
22050
|
+
wasPriceAutoAdjusted: z85.boolean(),
|
|
22051
|
+
profitabilityStatus: z85.literal("healthy")
|
|
22052
|
+
});
|
|
22053
|
+
var RewardProgressSchema = z85.object({
|
|
22054
|
+
campaignKey: z85.literal("dropshipping-launch-v1"),
|
|
22055
|
+
totalCredits: z85.number().int().positive(),
|
|
22056
|
+
earnedCredits: z85.number().int().nonnegative(),
|
|
22057
|
+
milestones: z85.array(z85.object({
|
|
21922
22058
|
milestone: DropshippingRewardMilestone,
|
|
21923
|
-
credits:
|
|
21924
|
-
available:
|
|
21925
|
-
earned:
|
|
22059
|
+
credits: z85.number().int().positive(),
|
|
22060
|
+
available: z85.boolean().optional(),
|
|
22061
|
+
earned: z85.boolean(),
|
|
21926
22062
|
grantId: ProjectId.nullable(),
|
|
21927
|
-
grantedAt:
|
|
22063
|
+
grantedAt: z85.string().datetime().nullable()
|
|
21928
22064
|
})).length(DropshippingRewardMilestone.options.length)
|
|
21929
22065
|
});
|
|
21930
|
-
var ProjectResponseSchema =
|
|
22066
|
+
var ProjectResponseSchema = z85.object({
|
|
21931
22067
|
id: ProjectId,
|
|
21932
22068
|
taskId: ProjectId.nullable(),
|
|
21933
22069
|
status: DropshippingProjectStatus,
|
|
21934
|
-
originKey:
|
|
22070
|
+
originKey: z85.string().min(1),
|
|
21935
22071
|
researchRunId: ProjectId.nullable(),
|
|
21936
|
-
candidateSourceId:
|
|
21937
|
-
productName:
|
|
22072
|
+
candidateSourceId: z85.string().nullable(),
|
|
22073
|
+
productName: z85.string().nullable(),
|
|
21938
22074
|
productUrl: HttpUrl3.nullable(),
|
|
21939
22075
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
21940
|
-
targetCountry:
|
|
21941
|
-
languageCode:
|
|
21942
|
-
hasReferenceImage:
|
|
21943
|
-
hasWinnerReferenceImage:
|
|
22076
|
+
targetCountry: z85.string().nullable(),
|
|
22077
|
+
languageCode: z85.string().nullable(),
|
|
22078
|
+
hasReferenceImage: z85.boolean(),
|
|
22079
|
+
hasWinnerReferenceImage: z85.boolean(),
|
|
21944
22080
|
costingInput: CostingInputSchema.nullable(),
|
|
21945
22081
|
costingResult: CostingResultSchema.nullable(),
|
|
21946
|
-
costingVersion:
|
|
21947
|
-
version:
|
|
22082
|
+
costingVersion: z85.number().int().positive().nullable(),
|
|
22083
|
+
version: z85.number().int().positive(),
|
|
21948
22084
|
phase: DropshippingProjectPhase,
|
|
21949
22085
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
21950
22086
|
rewards: RewardProgressSchema,
|
|
21951
|
-
createdAt:
|
|
21952
|
-
updatedAt:
|
|
22087
|
+
createdAt: z85.string().datetime(),
|
|
22088
|
+
updatedAt: z85.string().datetime()
|
|
21953
22089
|
}).passthrough();
|
|
21954
22090
|
var NEXT_ACTION_GUIDANCE = {
|
|
21955
22091
|
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.",
|
|
@@ -22067,58 +22203,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
22067
22203
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
22068
22204
|
|
|
22069
22205
|
// src/tools/daily-control.ts
|
|
22070
|
-
import { z as
|
|
22206
|
+
import { z as z86 } from "zod";
|
|
22071
22207
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
22072
22208
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
22073
22209
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
22074
|
-
var ProviderCampaignIdentifier =
|
|
22075
|
-
var DateOnly =
|
|
22076
|
-
var DailyControlInput =
|
|
22210
|
+
var ProviderCampaignIdentifier = z86.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
22211
|
+
var DateOnly = z86.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22212
|
+
var DailyControlInput = z86.object({
|
|
22077
22213
|
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."),
|
|
22078
|
-
days:
|
|
22079
|
-
projectId:
|
|
22214
|
+
days: z86.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
22215
|
+
projectId: z86.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
22080
22216
|
}).strict();
|
|
22081
|
-
var LinkCampaignInput =
|
|
22082
|
-
projectId:
|
|
22083
|
-
provider:
|
|
22217
|
+
var LinkCampaignInput = z86.object({
|
|
22218
|
+
projectId: z86.string().uuid(),
|
|
22219
|
+
provider: z86.enum([
|
|
22084
22220
|
"meta",
|
|
22085
22221
|
"tiktok"
|
|
22086
22222
|
]),
|
|
22087
22223
|
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."),
|
|
22088
22224
|
campaignId: ProviderCampaignIdentifier
|
|
22089
22225
|
}).strict();
|
|
22090
|
-
var ReportReturnsInput =
|
|
22091
|
-
projectId:
|
|
22226
|
+
var ReportReturnsInput = z86.object({
|
|
22227
|
+
projectId: z86.string().uuid(),
|
|
22092
22228
|
date: DateOnly,
|
|
22093
|
-
returnedOrders:
|
|
22094
|
-
note:
|
|
22229
|
+
returnedOrders: z86.number().int().min(0).max(1e5),
|
|
22230
|
+
note: z86.string().trim().max(280).optional()
|
|
22095
22231
|
}).strict();
|
|
22096
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
22097
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
22098
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
22099
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
22100
|
-
var DailyControlDayMirror =
|
|
22101
|
-
date:
|
|
22102
|
-
returnedOrders:
|
|
22232
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z86.string());
|
|
22233
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z86.string());
|
|
22234
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z86.string());
|
|
22235
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z86.string());
|
|
22236
|
+
var DailyControlDayMirror = z86.object({
|
|
22237
|
+
date: z86.string(),
|
|
22238
|
+
returnedOrders: z86.number(),
|
|
22103
22239
|
returnedSource: DailyControlSourceMirror,
|
|
22104
22240
|
cancelledSource: DailyControlSourceMirror,
|
|
22105
|
-
hasEstimates:
|
|
22241
|
+
hasEstimates: z86.boolean(),
|
|
22106
22242
|
light: DailyControlLightMirror
|
|
22107
22243
|
}).passthrough();
|
|
22108
|
-
var DailyControlProductMirror =
|
|
22109
|
-
projectId:
|
|
22110
|
-
productName:
|
|
22244
|
+
var DailyControlProductMirror = z86.object({
|
|
22245
|
+
projectId: z86.string().uuid(),
|
|
22246
|
+
productName: z86.string().nullable(),
|
|
22111
22247
|
status: DailyControlStatusMirror,
|
|
22112
|
-
statusMessage:
|
|
22113
|
-
days:
|
|
22248
|
+
statusMessage: z86.string().nullable(),
|
|
22249
|
+
days: z86.array(DailyControlDayMirror),
|
|
22114
22250
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
22115
|
-
rationale:
|
|
22251
|
+
rationale: z86.string().nullable()
|
|
22116
22252
|
}).passthrough();
|
|
22117
|
-
var DailyControlResponseMirror =
|
|
22118
|
-
since:
|
|
22119
|
-
until:
|
|
22120
|
-
products:
|
|
22121
|
-
archivedProjectSpend:
|
|
22253
|
+
var DailyControlResponseMirror = z86.object({
|
|
22254
|
+
since: z86.string(),
|
|
22255
|
+
until: z86.string(),
|
|
22256
|
+
products: z86.array(DailyControlProductMirror),
|
|
22257
|
+
archivedProjectSpend: z86.array(z86.unknown())
|
|
22122
22258
|
}).passthrough();
|
|
22123
22259
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
22124
22260
|
function withWarnings(response) {
|
|
@@ -22202,42 +22338,42 @@ function registerDailyControlTools(server, api) {
|
|
|
22202
22338
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
22203
22339
|
|
|
22204
22340
|
// src/tools/product-control.ts
|
|
22205
|
-
import { z as
|
|
22341
|
+
import { z as z87 } from "zod";
|
|
22206
22342
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
22207
22343
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
22208
22344
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
22209
22345
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
22210
22346
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
22211
|
-
var DateOnly2 =
|
|
22347
|
+
var DateOnly2 = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22212
22348
|
var IMPORT_BATCH_MAX2 = 50;
|
|
22213
|
-
var ProductControlListInput =
|
|
22214
|
-
days:
|
|
22349
|
+
var ProductControlListInput = z87.object({
|
|
22350
|
+
days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
22215
22351
|
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."),
|
|
22216
|
-
shopDomain:
|
|
22352
|
+
shopDomain: z87.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
22217
22353
|
}).strict();
|
|
22218
|
-
var ImportableProductsInput =
|
|
22219
|
-
q:
|
|
22220
|
-
after:
|
|
22221
|
-
shopDomain:
|
|
22354
|
+
var ImportableProductsInput = z87.object({
|
|
22355
|
+
q: z87.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
22356
|
+
after: z87.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
22357
|
+
shopDomain: z87.string().min(1).optional()
|
|
22222
22358
|
}).strict();
|
|
22223
|
-
var ImportProductControlsInput =
|
|
22224
|
-
shopifyProductIds:
|
|
22359
|
+
var ImportProductControlsInput = z87.object({
|
|
22360
|
+
shopifyProductIds: z87.array(z87.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."),
|
|
22225
22361
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
22226
22362
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
22227
|
-
shopDomain:
|
|
22363
|
+
shopDomain: z87.string().min(1)
|
|
22228
22364
|
}).strict();
|
|
22229
|
-
var SetProductCostingInput =
|
|
22230
|
-
shopDomain:
|
|
22231
|
-
shopifyProductId:
|
|
22232
|
-
targetCountry:
|
|
22233
|
-
supplierCost:
|
|
22234
|
-
shippingCost:
|
|
22235
|
-
returnRate:
|
|
22236
|
-
cancellationRate:
|
|
22365
|
+
var SetProductCostingInput = z87.object({
|
|
22366
|
+
shopDomain: z87.string().min(1),
|
|
22367
|
+
shopifyProductId: z87.string().min(1).max(64),
|
|
22368
|
+
targetCountry: z87.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
22369
|
+
supplierCost: z87.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
22370
|
+
shippingCost: z87.number().finite().nonnegative(),
|
|
22371
|
+
returnRate: z87.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
22372
|
+
cancellationRate: z87.number().finite().min(0).lt(1)
|
|
22237
22373
|
}).strict();
|
|
22238
|
-
var Count =
|
|
22239
|
-
var ReportProductCountsInput =
|
|
22240
|
-
productControlId:
|
|
22374
|
+
var Count = z87.number().int().min(0).max(1e5).nullable().optional();
|
|
22375
|
+
var ReportProductCountsInput = z87.object({
|
|
22376
|
+
productControlId: z87.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
22241
22377
|
date: DateOnly2,
|
|
22242
22378
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
22243
22379
|
cancelledOrders: Count,
|