@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/http.js
CHANGED
|
@@ -3609,11 +3609,12 @@ var FreeformLandingConfigSchema = z21.object({
|
|
|
3609
3609
|
showVariantPicker: z21.boolean().optional(),
|
|
3610
3610
|
/**
|
|
3611
3611
|
* Suppress the native Shopify buy form (the `BUY_FORM_MARKER` block). The page
|
|
3612
|
-
* CTAs already carry `data-cl-buy-trigger` → they open the
|
|
3613
|
-
* so on
|
|
3614
|
-
*
|
|
3615
|
-
*
|
|
3616
|
-
* (backward compatible with
|
|
3612
|
+
* CTAs already carry `data-cl-buy-trigger` → they open the installed COD
|
|
3613
|
+
* provider's popup (Releasit or EasySell), so on COD-provider stores the
|
|
3614
|
+
* native add-to-cart form is a redundant second buy path (it rendered as a
|
|
3615
|
+
* bare "price + Comprar" block). When true the assembler omits the marker
|
|
3616
|
+
* entirely. Undefined/false = keep the native form (backward compatible with
|
|
3617
|
+
* already-assembled configs).
|
|
3617
3618
|
*/
|
|
3618
3619
|
hideNativeBuyForm: z21.boolean().optional()
|
|
3619
3620
|
});
|
|
@@ -5401,6 +5402,17 @@ var CodeLandingThemeSetupResponse = z28.discriminatedUnion("status", [
|
|
|
5401
5402
|
themeEditorDeepLink: z28.string().url(),
|
|
5402
5403
|
shopDomain: z28.string()
|
|
5403
5404
|
}),
|
|
5405
|
+
z28.object({
|
|
5406
|
+
/**
|
|
5407
|
+
* The block is missing and the store has NO products yet. Shopify's theme
|
|
5408
|
+
* editor cannot add an app block to a product template with nothing to
|
|
5409
|
+
* preview (it answers "there is a problem with the app block"), so there
|
|
5410
|
+
* is deliberately no deep link: the seller publishes first, and the
|
|
5411
|
+
* publish response carries the link aimed at the product it created.
|
|
5412
|
+
*/
|
|
5413
|
+
status: z28.literal("setup_after_publish"),
|
|
5414
|
+
shopDomain: z28.string()
|
|
5415
|
+
}),
|
|
5404
5416
|
z28.object({
|
|
5405
5417
|
/** Not a code-landing task — the gate does not apply. */
|
|
5406
5418
|
status: z28.literal("not_applicable"),
|
|
@@ -6903,7 +6915,10 @@ var ChatParseEstimationOptions = z34.object({}).strict();
|
|
|
6903
6915
|
var CodeLandingEditEstimationOptions = z34.object({}).strict();
|
|
6904
6916
|
var ServiceCreativeEstimationOptions = z34.object({
|
|
6905
6917
|
mediaAssetCount: z34.number().int().min(0).max(8).optional(),
|
|
6906
|
-
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional()
|
|
6918
|
+
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
|
|
6919
|
+
/** Quality the panels render at (its registry model sets the per-second
|
|
6920
|
+
* price). Absent = economy, the pre-quality service default. */
|
|
6921
|
+
videoQuality: VideoQuality.optional()
|
|
6907
6922
|
});
|
|
6908
6923
|
var ActorGridEstimationOptions = z34.object({}).strict();
|
|
6909
6924
|
var CostEstimationRequest = z34.discriminatedUnion("type", [
|
|
@@ -7673,7 +7688,18 @@ var KIE_SUBMIT_IMAGE_TASK_TARGETS = [
|
|
|
7673
7688
|
"rapid_master_anchor",
|
|
7674
7689
|
"clean_product_image",
|
|
7675
7690
|
"single_call_anchor",
|
|
7676
|
-
"product_view_reference"
|
|
7691
|
+
"product_view_reference",
|
|
7692
|
+
// Generated service-video presenter (text-to-image portrait). Task-owned, so
|
|
7693
|
+
// it lives here and not beside `actor_candidate`; it mirrors that target's
|
|
7694
|
+
// model, resolution and recovery policy. The fan-in resumes the service init
|
|
7695
|
+
// (`dispatchServiceActor`, refKey prefix `service_actor:`).
|
|
7696
|
+
"service_actor",
|
|
7697
|
+
// First frame of a generated service B-roll panel: image-to-image from the
|
|
7698
|
+
// service photo the planner cited, cleaned of overlaid text/graphics and
|
|
7699
|
+
// fitted to the shot. Mirrors `rapid_panel`'s model tier and recovery
|
|
7700
|
+
// policy. The same fan-in waits for the whole expected image set
|
|
7701
|
+
// (`dispatchServiceActor`, refKey prefix `service_broll_anchor:`).
|
|
7702
|
+
"service_broll_anchor"
|
|
7677
7703
|
];
|
|
7678
7704
|
var ACTOR_CANDIDATE_TARGET = "actor_candidate";
|
|
7679
7705
|
var ANY_KIE_SUBMIT_IMAGE_TARGETS = [
|
|
@@ -9595,6 +9621,12 @@ var DEFAULT_PRICING = {
|
|
|
9595
9621
|
ourCostCents: 0.01,
|
|
9596
9622
|
userPriceCents: 0.02
|
|
9597
9623
|
},
|
|
9624
|
+
// Service reels harvested from the business's own public profile (per second,
|
|
9625
|
+
// same Whisper-1 rate). Separate action so the ledger names the source.
|
|
9626
|
+
"openai:service-social-transcribe": {
|
|
9627
|
+
ourCostCents: 0.01,
|
|
9628
|
+
userPriceCents: 0.02
|
|
9629
|
+
},
|
|
9598
9630
|
// User-uploaded service reference/competitor analysis (per second, same Whisper-1 rate).
|
|
9599
9631
|
// This is a separate action because its ledger entries identify the analysis source.
|
|
9600
9632
|
"openai:service-reference-transcribe": {
|
|
@@ -10734,6 +10766,11 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
|
|
|
10734
10766
|
])
|
|
10735
10767
|
]);
|
|
10736
10768
|
|
|
10769
|
+
// ../../packages/types/src/seller-prohibitions.ts
|
|
10770
|
+
var MARKER = String.raw`(?:no|nunca|jam[aá]s|prohibido|evita[r]?)(?:\s*:)?\s`;
|
|
10771
|
+
var PROHIBITION_AT_START = new RegExp(String.raw`^(?:[-•*]\s*)?(${MARKER}[\s\S]*)$`, "iu");
|
|
10772
|
+
var PROHIBITION_AFTER_LABEL = new RegExp(String.raw`^(?:[-•*]\s*)?[^:.!?\n]{1,40}:\s*(${MARKER}[\s\S]*)$`, "iu");
|
|
10773
|
+
|
|
10737
10774
|
// ../../packages/types/src/task-type.ts
|
|
10738
10775
|
import { z as z50 } from "zod";
|
|
10739
10776
|
var TaskTypeSchema = z50.enum([
|
|
@@ -13315,7 +13352,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13315
13352
|
"task",
|
|
13316
13353
|
"product"
|
|
13317
13354
|
]),
|
|
13318
|
-
defineCapability("create_service_video", "
|
|
13355
|
+
defineCapability("create_service_video", "863884c1af5de3e168cbbe825ea3961901c84dae1899ca400f8f7fa01df91c0a", "credit_consuming", "creative", [
|
|
13319
13356
|
"credit_consuming",
|
|
13320
13357
|
"state_change"
|
|
13321
13358
|
], [
|
|
@@ -13339,7 +13376,11 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13339
13376
|
]),
|
|
13340
13377
|
slot("video_preset", false, [
|
|
13341
13378
|
"videoPreset"
|
|
13342
|
-
])
|
|
13379
|
+
]),
|
|
13380
|
+
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
13381
|
+
slot("video_quality", false, [
|
|
13382
|
+
"videoQuality"
|
|
13383
|
+
], [])
|
|
13343
13384
|
], [
|
|
13344
13385
|
"service_context"
|
|
13345
13386
|
], [
|
|
@@ -14133,7 +14174,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14133
14174
|
], [
|
|
14134
14175
|
"meta_upload_session"
|
|
14135
14176
|
], WHATSAPP_ONLY_CHANNEL_EXPOSURE),
|
|
14136
|
-
defineCapability("request_media_upload", "
|
|
14177
|
+
defineCapability("request_media_upload", "9a50a4647c61f97fb12bbb9b25f7660f392e3cd9825151735cd66292058882ea", "none", "creative", [
|
|
14137
14178
|
"state_change"
|
|
14138
14179
|
], [
|
|
14139
14180
|
slot("media_kind", true, [
|
|
@@ -15132,6 +15173,81 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
15132
15173
|
}
|
|
15133
15174
|
});
|
|
15134
15175
|
|
|
15176
|
+
// ../../packages/types/src/flight-recorder.ts
|
|
15177
|
+
import { z as z68 } from "zod";
|
|
15178
|
+
var FlightRecorderGenerationTypeSchema = z68.enum([
|
|
15179
|
+
"initial",
|
|
15180
|
+
"regeneration",
|
|
15181
|
+
"edit",
|
|
15182
|
+
"retry"
|
|
15183
|
+
]);
|
|
15184
|
+
var FlightRecorderProviderSchema = z68.enum([
|
|
15185
|
+
"kie",
|
|
15186
|
+
"fal"
|
|
15187
|
+
]);
|
|
15188
|
+
var FlightRecorderElementSchema = z68.object({
|
|
15189
|
+
name: z68.string().optional(),
|
|
15190
|
+
description: z68.string().optional(),
|
|
15191
|
+
frontalImageUrl: z68.string().optional(),
|
|
15192
|
+
referenceImageUrls: z68.array(z68.string()).optional(),
|
|
15193
|
+
videoUrl: z68.string().optional()
|
|
15194
|
+
});
|
|
15195
|
+
var FlightRecorderDistillationSchema = z68.object({
|
|
15196
|
+
actorGender: z68.enum([
|
|
15197
|
+
"female",
|
|
15198
|
+
"male",
|
|
15199
|
+
"mixed"
|
|
15200
|
+
]).or(z68.string()).optional(),
|
|
15201
|
+
voiceId: z68.string().optional(),
|
|
15202
|
+
cameraMotion: z68.string().optional()
|
|
15203
|
+
}).catchall(z68.unknown());
|
|
15204
|
+
var FlightRecorderEntrySchema = z68.object({
|
|
15205
|
+
schemaVersion: z68.literal(1).optional(),
|
|
15206
|
+
id: z68.string().min(1),
|
|
15207
|
+
taskId: z68.string().min(1),
|
|
15208
|
+
runId: z68.string().min(1),
|
|
15209
|
+
sequence: z68.number().int().nonnegative(),
|
|
15210
|
+
timestamp: z68.string().min(1),
|
|
15211
|
+
provider: FlightRecorderProviderSchema.or(z68.string()),
|
|
15212
|
+
model: z68.string().min(1),
|
|
15213
|
+
prompt: z68.string(),
|
|
15214
|
+
durationSeconds: z68.number().nonnegative(),
|
|
15215
|
+
aspectRatio: z68.string().optional(),
|
|
15216
|
+
resolution: z68.string().optional(),
|
|
15217
|
+
startImageUrl: z68.string().optional(),
|
|
15218
|
+
endImageUrl: z68.string().optional(),
|
|
15219
|
+
generateAudio: z68.boolean().optional(),
|
|
15220
|
+
// Correlation & pipeline metadata
|
|
15221
|
+
angleKey: z68.string().optional(),
|
|
15222
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
15223
|
+
generationType: FlightRecorderGenerationTypeSchema,
|
|
15224
|
+
operationId: z68.string().min(1).optional(),
|
|
15225
|
+
revisionId: z68.string().min(1).optional(),
|
|
15226
|
+
attemptNumber: z68.number().int().nonnegative().default(1),
|
|
15227
|
+
// Elements & Distillation
|
|
15228
|
+
elements: z68.array(FlightRecorderElementSchema).optional(),
|
|
15229
|
+
distillation: FlightRecorderDistillationSchema.optional(),
|
|
15230
|
+
// Raw payload (sanitized of secrets)
|
|
15231
|
+
rawPayload: z68.record(z68.unknown())
|
|
15232
|
+
});
|
|
15233
|
+
var FlightRecorderQuerySchema = z68.object({
|
|
15234
|
+
taskId: z68.string().min(1),
|
|
15235
|
+
runId: z68.string().optional(),
|
|
15236
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
15237
|
+
angleKey: z68.string().optional(),
|
|
15238
|
+
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15239
|
+
cursor: z68.number().int().nonnegative().optional(),
|
|
15240
|
+
limit: z68.number().int().positive().optional()
|
|
15241
|
+
});
|
|
15242
|
+
var FlightRecorderResponseSchema = z68.object({
|
|
15243
|
+
taskId: z68.string().min(1),
|
|
15244
|
+
runId: z68.string().min(1),
|
|
15245
|
+
entries: z68.array(FlightRecorderEntrySchema),
|
|
15246
|
+
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15247
|
+
count: z68.number().int().nonnegative(),
|
|
15248
|
+
nextCursor: z68.number().int().nonnegative().nullable()
|
|
15249
|
+
});
|
|
15250
|
+
|
|
15135
15251
|
// src/http.ts
|
|
15136
15252
|
import express4 from "express";
|
|
15137
15253
|
import rateLimit2 from "express-rate-limit";
|
|
@@ -15638,22 +15754,22 @@ import { InsufficientScopeError, InvalidTokenError } from "@modelcontextprotocol
|
|
|
15638
15754
|
import { createRemoteJWKSet as createRemoteJWKSet2, jwtVerify as jwtVerify2 } from "jose";
|
|
15639
15755
|
|
|
15640
15756
|
// src/auth/oauth-config.ts
|
|
15641
|
-
import { z as
|
|
15757
|
+
import { z as z69 } from "zod";
|
|
15642
15758
|
var MCP_RESOURCE = new URL("https://mcp.productmaker.app/mcp");
|
|
15643
15759
|
var MCP_SCOPE = "mcp:access";
|
|
15644
15760
|
var STATIC_CLIENT_ISSUER = new URL(MCP_RESOURCE.origin);
|
|
15645
|
-
var oauthEnvSchema =
|
|
15646
|
-
MCP_REMOTE_AUTH_MODE:
|
|
15647
|
-
MCP_AUTH0_ISSUER:
|
|
15648
|
-
MCP_AUTH0_AUDIENCE:
|
|
15761
|
+
var oauthEnvSchema = z69.object({
|
|
15762
|
+
MCP_REMOTE_AUTH_MODE: z69.literal("oauth"),
|
|
15763
|
+
MCP_AUTH0_ISSUER: z69.string().trim().min(1),
|
|
15764
|
+
MCP_AUTH0_AUDIENCE: z69.string().trim().refine((value) => value === MCP_RESOURCE.href, {
|
|
15649
15765
|
message: `must equal ${MCP_RESOURCE.href}`
|
|
15650
15766
|
}),
|
|
15651
|
-
MCP_AUTH0_CLIENT_ID:
|
|
15652
|
-
MCP_AUTH0_CLIENT_SECRET:
|
|
15653
|
-
PM_API_AUDIENCE:
|
|
15654
|
-
AUTH0_AUDIENCE:
|
|
15655
|
-
MCP_STATIC_CLIENT_ID:
|
|
15656
|
-
MCP_STATIC_CLIENT_SECRET:
|
|
15767
|
+
MCP_AUTH0_CLIENT_ID: z69.string().trim().min(1),
|
|
15768
|
+
MCP_AUTH0_CLIENT_SECRET: z69.string().trim().min(1),
|
|
15769
|
+
PM_API_AUDIENCE: z69.string().trim().min(1),
|
|
15770
|
+
AUTH0_AUDIENCE: z69.string().trim().min(1),
|
|
15771
|
+
MCP_STATIC_CLIENT_ID: z69.string().trim().min(1).optional(),
|
|
15772
|
+
MCP_STATIC_CLIENT_SECRET: z69.string().trim().min(1).optional()
|
|
15657
15773
|
});
|
|
15658
15774
|
function formatZodIssues(error) {
|
|
15659
15775
|
return error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
|
|
@@ -16760,7 +16876,7 @@ var ApiClient = class {
|
|
|
16760
16876
|
};
|
|
16761
16877
|
|
|
16762
16878
|
// src/index.ts
|
|
16763
|
-
var MCP_VERSION = "
|
|
16879
|
+
var MCP_VERSION = "8.0.0";
|
|
16764
16880
|
|
|
16765
16881
|
// src/meta-upload-app.ts
|
|
16766
16882
|
import { readFileSync } from "fs";
|
|
@@ -16832,7 +16948,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
16832
16948
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
16833
16949
|
|
|
16834
16950
|
// src/tools/tasks.ts
|
|
16835
|
-
import { z as
|
|
16951
|
+
import { z as z73 } from "zod";
|
|
16836
16952
|
|
|
16837
16953
|
// src/resolve-image.ts
|
|
16838
16954
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -17393,10 +17509,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
17393
17509
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
17394
17510
|
|
|
17395
17511
|
// src/tools/shared.ts
|
|
17396
|
-
import { z as
|
|
17397
|
-
var Lang =
|
|
17398
|
-
var Country =
|
|
17399
|
-
var LandingStrategyEnum =
|
|
17512
|
+
import { z as z70 } from "zod";
|
|
17513
|
+
var Lang = z70.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);
|
|
17514
|
+
var Country = z70.string().min(2).max(3);
|
|
17515
|
+
var LandingStrategyEnum = z70.enum([
|
|
17400
17516
|
"auto",
|
|
17401
17517
|
"classic",
|
|
17402
17518
|
"pain_solution",
|
|
@@ -17405,12 +17521,12 @@ var LandingStrategyEnum = z69.enum([
|
|
|
17405
17521
|
"offer_value",
|
|
17406
17522
|
"lifestyle_identity"
|
|
17407
17523
|
]);
|
|
17408
|
-
var LandingImageFormatEnum =
|
|
17524
|
+
var LandingImageFormatEnum = z70.enum([
|
|
17409
17525
|
"9:16",
|
|
17410
17526
|
"4:5",
|
|
17411
17527
|
"1:1"
|
|
17412
17528
|
]);
|
|
17413
|
-
var VideoPresetEnum =
|
|
17529
|
+
var VideoPresetEnum = z70.enum([
|
|
17414
17530
|
"auto",
|
|
17415
17531
|
"ugc_dynamic",
|
|
17416
17532
|
"ugc_how_to",
|
|
@@ -17423,21 +17539,21 @@ var VideoPresetEnum = z69.enum([
|
|
|
17423
17539
|
"pixar_problem",
|
|
17424
17540
|
"pixar_sassy"
|
|
17425
17541
|
]);
|
|
17426
|
-
var VideoStructureEnum =
|
|
17542
|
+
var VideoStructureEnum = z70.enum([
|
|
17427
17543
|
"single_take",
|
|
17428
17544
|
"multi_scene"
|
|
17429
17545
|
]);
|
|
17430
|
-
var VideoQualityEnum =
|
|
17546
|
+
var VideoQualityEnum = z70.enum([
|
|
17431
17547
|
"economy",
|
|
17432
17548
|
"medium",
|
|
17433
17549
|
"pro"
|
|
17434
17550
|
]);
|
|
17435
|
-
var VideoRouteIdEnum =
|
|
17551
|
+
var VideoRouteIdEnum = z70.enum([
|
|
17436
17552
|
"single_take",
|
|
17437
17553
|
"multi_scene",
|
|
17438
17554
|
"free"
|
|
17439
17555
|
]);
|
|
17440
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
17556
|
+
var TaskCreativeVariantVideoPresetEnum = z70.enum([
|
|
17441
17557
|
"auto",
|
|
17442
17558
|
"ugc_dynamic",
|
|
17443
17559
|
"ugc_how_to",
|
|
@@ -17508,7 +17624,7 @@ function resolveVideoPreset(preset) {
|
|
|
17508
17624
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
17509
17625
|
}
|
|
17510
17626
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
17511
|
-
var VideoTierEnum =
|
|
17627
|
+
var VideoTierEnum = z70.enum([
|
|
17512
17628
|
"basic"
|
|
17513
17629
|
]);
|
|
17514
17630
|
function resolveVideoTier(_tier) {
|
|
@@ -17548,22 +17664,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
17548
17664
|
}
|
|
17549
17665
|
}
|
|
17550
17666
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
17551
|
-
var VideoResolutionEnum =
|
|
17667
|
+
var VideoResolutionEnum = z70.enum([
|
|
17552
17668
|
"480p",
|
|
17553
17669
|
"720p"
|
|
17554
17670
|
]);
|
|
17555
|
-
var CreativeGenderEnum =
|
|
17671
|
+
var CreativeGenderEnum = z70.enum([
|
|
17556
17672
|
"female",
|
|
17557
17673
|
"male",
|
|
17558
17674
|
"mixed"
|
|
17559
17675
|
]);
|
|
17560
|
-
var VideoStyleEnum =
|
|
17676
|
+
var VideoStyleEnum = z70.enum([
|
|
17561
17677
|
"ugc",
|
|
17562
17678
|
"cartoon_3d",
|
|
17563
17679
|
"product_only",
|
|
17564
17680
|
"ai_dynamic"
|
|
17565
17681
|
]);
|
|
17566
|
-
var NarrativeStyleEnum =
|
|
17682
|
+
var NarrativeStyleEnum = z70.enum([
|
|
17567
17683
|
"review",
|
|
17568
17684
|
"ugc_how_to",
|
|
17569
17685
|
"problem_product_cta",
|
|
@@ -17581,7 +17697,7 @@ var NarrativeStyleEnum = z69.enum([
|
|
|
17581
17697
|
"ugc_demo_review",
|
|
17582
17698
|
"market"
|
|
17583
17699
|
]);
|
|
17584
|
-
var PublicNarrativeStyleEnum =
|
|
17700
|
+
var PublicNarrativeStyleEnum = z70.enum([
|
|
17585
17701
|
"review",
|
|
17586
17702
|
"ugc_how_to",
|
|
17587
17703
|
"ugc_unboxing_chaos",
|
|
@@ -17594,7 +17710,7 @@ var PublicNarrativeStyleEnum = z69.enum([
|
|
|
17594
17710
|
"sassy_product_pixar",
|
|
17595
17711
|
"market"
|
|
17596
17712
|
]);
|
|
17597
|
-
var VideoModelEnum =
|
|
17713
|
+
var VideoModelEnum = z70.enum([
|
|
17598
17714
|
"veo",
|
|
17599
17715
|
"wan",
|
|
17600
17716
|
"bytedance",
|
|
@@ -17602,29 +17718,29 @@ var VideoModelEnum = z69.enum([
|
|
|
17602
17718
|
"grok",
|
|
17603
17719
|
"kling"
|
|
17604
17720
|
]);
|
|
17605
|
-
var ProductReferenceUserChoiceEnum =
|
|
17721
|
+
var ProductReferenceUserChoiceEnum = z70.enum([
|
|
17606
17722
|
"same_product",
|
|
17607
17723
|
"variants",
|
|
17608
17724
|
"different_products",
|
|
17609
17725
|
"combo_distinct"
|
|
17610
17726
|
]);
|
|
17611
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
17727
|
+
var ProductReferenceCandidateGroupingEnum = z70.enum([
|
|
17612
17728
|
"same_product_same_variant",
|
|
17613
17729
|
"same_product_different_variants",
|
|
17614
17730
|
"different_products",
|
|
17615
17731
|
"unclear"
|
|
17616
17732
|
]);
|
|
17617
|
-
var ProductReferenceScopeEnum =
|
|
17733
|
+
var ProductReferenceScopeEnum = z70.enum([
|
|
17618
17734
|
"base",
|
|
17619
17735
|
"video_view_pack"
|
|
17620
17736
|
]);
|
|
17621
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
17737
|
+
var ProductReferenceResolutionDecisionEnum = z70.enum([
|
|
17622
17738
|
"approve",
|
|
17623
17739
|
"reject",
|
|
17624
17740
|
"observed_only",
|
|
17625
17741
|
"correct_view"
|
|
17626
17742
|
]);
|
|
17627
|
-
var ProductReferenceRejectionReasonEnum =
|
|
17743
|
+
var ProductReferenceRejectionReasonEnum = z70.enum([
|
|
17628
17744
|
"replacement_requested",
|
|
17629
17745
|
"wrong_product_identity",
|
|
17630
17746
|
"wrong_variant",
|
|
@@ -17635,13 +17751,13 @@ var ProductReferenceRejectionReasonEnum = z69.enum([
|
|
|
17635
17751
|
"not_a_product_photo",
|
|
17636
17752
|
"other"
|
|
17637
17753
|
]);
|
|
17638
|
-
var GapDurationChoiceMirror =
|
|
17639
|
-
angleIndex:
|
|
17640
|
-
recommendedSec:
|
|
17641
|
-
|
|
17642
|
-
|
|
17754
|
+
var GapDurationChoiceMirror = z70.object({
|
|
17755
|
+
angleIndex: z70.number().int().nonnegative(),
|
|
17756
|
+
recommendedSec: z70.union([
|
|
17757
|
+
z70.literal(15),
|
|
17758
|
+
z70.literal(30)
|
|
17643
17759
|
]),
|
|
17644
|
-
estimatedDeltaCredits:
|
|
17760
|
+
estimatedDeltaCredits: z70.number().int().nonnegative().optional()
|
|
17645
17761
|
});
|
|
17646
17762
|
function buildSelectedImageUrlsHash(urls) {
|
|
17647
17763
|
const input = [
|
|
@@ -17651,13 +17767,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
17651
17767
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
17652
17768
|
}
|
|
17653
17769
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
17654
|
-
var ImageCreativeStyleEnum =
|
|
17770
|
+
var ImageCreativeStyleEnum = z70.enum([
|
|
17655
17771
|
"studio",
|
|
17656
17772
|
"floating",
|
|
17657
17773
|
"ingredients",
|
|
17658
17774
|
"in_use"
|
|
17659
17775
|
]);
|
|
17660
|
-
var ImageCreativeArchetypeEnum =
|
|
17776
|
+
var ImageCreativeArchetypeEnum = z70.enum([
|
|
17661
17777
|
"direct_response_product_ad",
|
|
17662
17778
|
"hero_outcome",
|
|
17663
17779
|
"offer_value_prop",
|
|
@@ -17666,20 +17782,20 @@ var ImageCreativeArchetypeEnum = z69.enum([
|
|
|
17666
17782
|
"problem_solution",
|
|
17667
17783
|
"lifestyle_identity"
|
|
17668
17784
|
]);
|
|
17669
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
17785
|
+
var ImageCreativeVisualTreatmentEnum = z70.enum([
|
|
17670
17786
|
"performance_product_ad",
|
|
17671
17787
|
"premium_dtc_carousel"
|
|
17672
17788
|
]);
|
|
17673
|
-
var ImageCreativeAspectRatioEnum =
|
|
17789
|
+
var ImageCreativeAspectRatioEnum = z70.enum([
|
|
17674
17790
|
"1:1",
|
|
17675
17791
|
"4:5",
|
|
17676
17792
|
"9:16",
|
|
17677
17793
|
"16:9"
|
|
17678
17794
|
]);
|
|
17679
|
-
var ImageRefSchema =
|
|
17680
|
-
url:
|
|
17681
|
-
path:
|
|
17682
|
-
assetId:
|
|
17795
|
+
var ImageRefSchema = z70.object({
|
|
17796
|
+
url: z70.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.'),
|
|
17797
|
+
path: z70.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`.'),
|
|
17798
|
+
assetId: z70.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.")
|
|
17683
17799
|
}).refine((v) => [
|
|
17684
17800
|
v.url,
|
|
17685
17801
|
v.path,
|
|
@@ -17687,11 +17803,11 @@ var ImageRefSchema = z69.object({
|
|
|
17687
17803
|
].filter(Boolean).length === 1, {
|
|
17688
17804
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
17689
17805
|
});
|
|
17690
|
-
var ImagesInput =
|
|
17806
|
+
var ImagesInput = z70.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
17691
17807
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
17692
17808
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
17693
17809
|
ctx.addIssue({
|
|
17694
|
-
code:
|
|
17810
|
+
code: z70.ZodIssueCode.custom,
|
|
17695
17811
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
17696
17812
|
});
|
|
17697
17813
|
}
|
|
@@ -17759,14 +17875,14 @@ async function submitCreative(api, opts) {
|
|
|
17759
17875
|
});
|
|
17760
17876
|
}
|
|
17761
17877
|
__name(submitCreative, "submitCreative");
|
|
17762
|
-
var ResearchTargetCountryEnum =
|
|
17878
|
+
var ResearchTargetCountryEnum = z70.enum([
|
|
17763
17879
|
"CO",
|
|
17764
17880
|
"MX",
|
|
17765
17881
|
"PE",
|
|
17766
17882
|
"EC",
|
|
17767
17883
|
"CL"
|
|
17768
17884
|
]);
|
|
17769
|
-
var ResearchCategoryEnum =
|
|
17885
|
+
var ResearchCategoryEnum = z70.enum([
|
|
17770
17886
|
"auto",
|
|
17771
17887
|
"automotive",
|
|
17772
17888
|
"kitchen",
|
|
@@ -17791,7 +17907,7 @@ var READS_EXTERNAL = {
|
|
|
17791
17907
|
readOnlyHint: true,
|
|
17792
17908
|
destructiveHint: false,
|
|
17793
17909
|
idempotentHint: true,
|
|
17794
|
-
openWorldHint:
|
|
17910
|
+
openWorldHint: false
|
|
17795
17911
|
};
|
|
17796
17912
|
var CREATES_INTERNAL = {
|
|
17797
17913
|
readOnlyHint: false,
|
|
@@ -17800,6 +17916,24 @@ var CREATES_INTERNAL = {
|
|
|
17800
17916
|
openWorldHint: false
|
|
17801
17917
|
};
|
|
17802
17918
|
var CREATES_EXTERNAL = {
|
|
17919
|
+
readOnlyHint: false,
|
|
17920
|
+
destructiveHint: false,
|
|
17921
|
+
idempotentHint: false,
|
|
17922
|
+
openWorldHint: false
|
|
17923
|
+
};
|
|
17924
|
+
var CREATES_PAID = {
|
|
17925
|
+
readOnlyHint: false,
|
|
17926
|
+
destructiveHint: true,
|
|
17927
|
+
idempotentHint: false,
|
|
17928
|
+
openWorldHint: false
|
|
17929
|
+
};
|
|
17930
|
+
var CREATES_PAID_OPEN_WORLD = {
|
|
17931
|
+
readOnlyHint: false,
|
|
17932
|
+
destructiveHint: true,
|
|
17933
|
+
idempotentHint: false,
|
|
17934
|
+
openWorldHint: true
|
|
17935
|
+
};
|
|
17936
|
+
var CREATES_OPEN_WORLD = {
|
|
17803
17937
|
readOnlyHint: false,
|
|
17804
17938
|
destructiveHint: false,
|
|
17805
17939
|
idempotentHint: false,
|
|
@@ -17815,9 +17949,9 @@ var OVERWRITES_EXTERNAL = {
|
|
|
17815
17949
|
readOnlyHint: false,
|
|
17816
17950
|
destructiveHint: true,
|
|
17817
17951
|
idempotentHint: false,
|
|
17818
|
-
openWorldHint:
|
|
17952
|
+
openWorldHint: false
|
|
17819
17953
|
};
|
|
17820
|
-
var DailyControlStatusEnum =
|
|
17954
|
+
var DailyControlStatusEnum = z70.enum([
|
|
17821
17955
|
"ok",
|
|
17822
17956
|
"sales_unavailable",
|
|
17823
17957
|
"timezone_unavailable",
|
|
@@ -17830,19 +17964,19 @@ var DailyControlStatusEnum = z69.enum([
|
|
|
17830
17964
|
"product_missing",
|
|
17831
17965
|
"store_unreachable"
|
|
17832
17966
|
]);
|
|
17833
|
-
var DailyControlLightEnum =
|
|
17967
|
+
var DailyControlLightEnum = z70.enum([
|
|
17834
17968
|
"green",
|
|
17835
17969
|
"amber",
|
|
17836
17970
|
"red",
|
|
17837
17971
|
"none"
|
|
17838
17972
|
]);
|
|
17839
|
-
var DailyControlVerdictEnum =
|
|
17973
|
+
var DailyControlVerdictEnum = z70.enum([
|
|
17840
17974
|
"scale",
|
|
17841
17975
|
"hold",
|
|
17842
17976
|
"kill",
|
|
17843
17977
|
"insufficient_sample"
|
|
17844
17978
|
]);
|
|
17845
|
-
var DailyControlSourceEnum =
|
|
17979
|
+
var DailyControlSourceEnum = z70.enum([
|
|
17846
17980
|
"shopify",
|
|
17847
17981
|
"shopify_settling",
|
|
17848
17982
|
"user",
|
|
@@ -18930,29 +19064,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
18930
19064
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
18931
19065
|
|
|
18932
19066
|
// src/tools/media-presentation.ts
|
|
18933
|
-
import { z as
|
|
18934
|
-
var HttpsPresentationUrlSchema =
|
|
19067
|
+
import { z as z71 } from "zod";
|
|
19068
|
+
var HttpsPresentationUrlSchema = z71.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
18935
19069
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
18936
19070
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
18937
19071
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
18938
19072
|
}, "preview URL must be owned by ProductMaker");
|
|
18939
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
18940
|
-
var PresentationImageSchema =
|
|
18941
|
-
kind:
|
|
19073
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z71.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
19074
|
+
var PresentationImageSchema = z71.object({
|
|
19075
|
+
kind: z71.literal("image"),
|
|
18942
19076
|
url: HttpsPresentationUrlSchema,
|
|
18943
|
-
mimeType:
|
|
19077
|
+
mimeType: z71.enum([
|
|
18944
19078
|
"image/jpeg",
|
|
18945
19079
|
"image/png"
|
|
18946
19080
|
]),
|
|
18947
19081
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
18948
19082
|
width: positiveIntAtMost(16384),
|
|
18949
19083
|
height: positiveIntAtMost(16384),
|
|
18950
|
-
alt:
|
|
19084
|
+
alt: z71.string().trim().min(1).max(240)
|
|
18951
19085
|
}).strict();
|
|
18952
19086
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
18953
|
-
var GalleryImageSchema =
|
|
19087
|
+
var GalleryImageSchema = z71.object({
|
|
18954
19088
|
url: ProductMakerPreviewUrlSchema,
|
|
18955
|
-
alt:
|
|
19089
|
+
alt: z71.string().trim().min(1).max(240)
|
|
18956
19090
|
});
|
|
18957
19091
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
18958
19092
|
async function imageBlocks(image, transport) {
|
|
@@ -19102,10 +19236,10 @@ ${summary}`,
|
|
|
19102
19236
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
19103
19237
|
|
|
19104
19238
|
// src/tools/winning-product-image.ts
|
|
19105
|
-
import { z as
|
|
19106
|
-
var WinnerReferenceInput =
|
|
19107
|
-
runId:
|
|
19108
|
-
candidateSourceId:
|
|
19239
|
+
import { z as z72 } from "zod";
|
|
19240
|
+
var WinnerReferenceInput = z72.object({
|
|
19241
|
+
runId: z72.string().uuid(),
|
|
19242
|
+
candidateSourceId: z72.string().trim().min(1).max(160)
|
|
19109
19243
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
19110
19244
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
19111
19245
|
if (!winnerReference) return images;
|
|
@@ -19142,188 +19276,189 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
19142
19276
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
19143
19277
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
19144
19278
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
19145
|
-
var CreateProductTaskInput =
|
|
19279
|
+
var CreateProductTaskInput = z73.object({
|
|
19146
19280
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
19147
19281
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
19148
|
-
projectId:
|
|
19149
|
-
productUrl:
|
|
19282
|
+
projectId: z73.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
19283
|
+
productUrl: z73.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."),
|
|
19150
19284
|
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.'),
|
|
19151
19285
|
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.'),
|
|
19152
|
-
price:
|
|
19153
|
-
compareAtPrice:
|
|
19154
|
-
offer:
|
|
19155
|
-
paymentMethods:
|
|
19156
|
-
productContext:
|
|
19157
|
-
productLabel:
|
|
19286
|
+
price: z73.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.'),
|
|
19287
|
+
compareAtPrice: z73.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".'),
|
|
19288
|
+
offer: z73.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.'),
|
|
19289
|
+
paymentMethods: z73.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.'),
|
|
19290
|
+
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."),
|
|
19291
|
+
productLabel: z73.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.'),
|
|
19158
19292
|
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.'),
|
|
19159
|
-
durationSeconds:
|
|
19160
|
-
|
|
19161
|
-
|
|
19293
|
+
durationSeconds: z73.union([
|
|
19294
|
+
z73.literal(15),
|
|
19295
|
+
z73.literal(30)
|
|
19162
19296
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
19163
|
-
pauseForAngleReview:
|
|
19164
|
-
aiDecidesAll:
|
|
19297
|
+
pauseForAngleReview: z73.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."),
|
|
19298
|
+
aiDecidesAll: z73.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."),
|
|
19165
19299
|
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.'),
|
|
19166
19300
|
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.'),
|
|
19167
19301
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
19168
19302
|
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).'),
|
|
19169
|
-
videoAngleCount:
|
|
19303
|
+
videoAngleCount: z73.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."),
|
|
19170
19304
|
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.'),
|
|
19171
|
-
outputs:
|
|
19305
|
+
outputs: z73.array(z73.enum([
|
|
19172
19306
|
"landing",
|
|
19173
19307
|
"video",
|
|
19174
19308
|
"image"
|
|
19175
19309
|
])).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}`),
|
|
19176
|
-
competitorScanEnabled:
|
|
19177
|
-
replicateWinnerWhenFound:
|
|
19178
|
-
brandId:
|
|
19179
|
-
actorId:
|
|
19310
|
+
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). 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."),
|
|
19311
|
+
replicateWinnerWhenFound: z73.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."),
|
|
19312
|
+
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 los outputs generados."),
|
|
19313
|
+
actorId: z73.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."),
|
|
19180
19314
|
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.'),
|
|
19181
|
-
creativeDirection:
|
|
19182
|
-
headline:
|
|
19183
|
-
subheadline:
|
|
19315
|
+
creativeDirection: z73.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.'),
|
|
19316
|
+
headline: z73.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."),
|
|
19317
|
+
subheadline: z73.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."),
|
|
19184
19318
|
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".'),
|
|
19185
19319
|
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".')
|
|
19186
19320
|
}).strict();
|
|
19187
|
-
var CreateServiceVideoInput =
|
|
19188
|
-
landingUrl:
|
|
19189
|
-
additionalContext:
|
|
19321
|
+
var CreateServiceVideoInput = z73.object({
|
|
19322
|
+
landingUrl: z73.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
19323
|
+
additionalContext: z73.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
19190
19324
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
19191
|
-
voiceId:
|
|
19192
|
-
brandId:
|
|
19193
|
-
reviewMode:
|
|
19325
|
+
voiceId: z73.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.'),
|
|
19326
|
+
brandId: z73.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
19327
|
+
reviewMode: z73.enum([
|
|
19194
19328
|
"automatic",
|
|
19195
19329
|
"guided"
|
|
19196
19330
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
19197
|
-
videoPreset:
|
|
19331
|
+
videoPreset: z73.enum([
|
|
19198
19332
|
"auto",
|
|
19199
19333
|
"ugc_dynamic",
|
|
19200
19334
|
"ugc_how_to",
|
|
19201
19335
|
"cinematic",
|
|
19202
19336
|
"wild_card"
|
|
19203
|
-
]).default("auto")
|
|
19337
|
+
]).default("auto"),
|
|
19338
|
+
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
|
|
19204
19339
|
}).strict();
|
|
19205
|
-
var GetTaskStatusInput =
|
|
19206
|
-
taskId:
|
|
19207
|
-
waitSeconds:
|
|
19340
|
+
var GetTaskStatusInput = z73.object({
|
|
19341
|
+
taskId: z73.string().min(1),
|
|
19342
|
+
waitSeconds: z73.number().int().min(0).max(120).optional()
|
|
19208
19343
|
});
|
|
19209
|
-
var ListTasksInput =
|
|
19210
|
-
limit:
|
|
19211
|
-
offset:
|
|
19212
|
-
search:
|
|
19344
|
+
var ListTasksInput = z73.object({
|
|
19345
|
+
limit: z73.number().int().min(1).max(50).optional(),
|
|
19346
|
+
offset: z73.number().int().min(0).optional(),
|
|
19347
|
+
search: z73.string().optional()
|
|
19213
19348
|
});
|
|
19214
19349
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
19215
19350
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
19216
|
-
var EditTaskDraftInput =
|
|
19217
|
-
taskId:
|
|
19218
|
-
angleIndex:
|
|
19219
|
-
angle:
|
|
19220
|
-
angle:
|
|
19221
|
-
buyerPersona:
|
|
19222
|
-
actor:
|
|
19223
|
-
actorId:
|
|
19224
|
-
gender:
|
|
19351
|
+
var EditTaskDraftInput = z73.object({
|
|
19352
|
+
taskId: z73.string().min(1),
|
|
19353
|
+
angleIndex: z73.number().int().min(0),
|
|
19354
|
+
angle: z73.object({
|
|
19355
|
+
angle: z73.string().min(1).max(480),
|
|
19356
|
+
buyerPersona: z73.string().min(1).max(360),
|
|
19357
|
+
actor: z73.string().min(1).max(360).optional(),
|
|
19358
|
+
actorId: z73.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."),
|
|
19359
|
+
gender: z73.enum([
|
|
19225
19360
|
"female",
|
|
19226
19361
|
"male"
|
|
19227
19362
|
]).optional(),
|
|
19228
|
-
scriptNotes:
|
|
19363
|
+
scriptNotes: z73.string().max(2e3).optional()
|
|
19229
19364
|
})
|
|
19230
19365
|
});
|
|
19231
|
-
var PendingActionPayload =
|
|
19232
|
-
|
|
19233
|
-
kind:
|
|
19366
|
+
var PendingActionPayload = z73.discriminatedUnion("kind", [
|
|
19367
|
+
z73.object({
|
|
19368
|
+
kind: z73.literal("product_reference_set_approval"),
|
|
19234
19369
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19235
|
-
scopeKey:
|
|
19236
|
-
scopeSnapshotId:
|
|
19237
|
-
expectedScopeHash:
|
|
19370
|
+
scopeKey: z73.string().min(1).max(120).optional(),
|
|
19371
|
+
scopeSnapshotId: z73.string().uuid().optional(),
|
|
19372
|
+
expectedScopeHash: z73.string().min(1).max(128).optional(),
|
|
19238
19373
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
19239
19374
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
19240
|
-
affectedRefKeys:
|
|
19241
|
-
affectedPhotoNumbers:
|
|
19242
|
-
recoveryAction:
|
|
19375
|
+
affectedRefKeys: z73.array(z73.string().min(1).max(200)).min(1).optional(),
|
|
19376
|
+
affectedPhotoNumbers: z73.array(z73.number().int().positive()).min(1).optional(),
|
|
19377
|
+
recoveryAction: z73.enum([
|
|
19243
19378
|
"remove",
|
|
19244
19379
|
"replace",
|
|
19245
19380
|
"upload",
|
|
19246
19381
|
"return_to_selection"
|
|
19247
19382
|
]).optional()
|
|
19248
19383
|
}),
|
|
19249
|
-
|
|
19250
|
-
kind:
|
|
19251
|
-
selectedPhotoNumbers:
|
|
19384
|
+
z73.object({
|
|
19385
|
+
kind: z73.literal("product_reference_confirmation"),
|
|
19386
|
+
selectedPhotoNumbers: z73.array(z73.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."),
|
|
19252
19387
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
19253
|
-
confirmedProductNames:
|
|
19388
|
+
confirmedProductNames: z73.array(z73.string().min(1).max(120)).min(2).max(8).optional(),
|
|
19254
19389
|
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."),
|
|
19255
19390
|
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."),
|
|
19256
|
-
useMultiSceneShowcase:
|
|
19391
|
+
useMultiSceneShowcase: z73.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
19257
19392
|
}),
|
|
19258
|
-
|
|
19259
|
-
kind:
|
|
19393
|
+
z73.object({
|
|
19394
|
+
kind: z73.literal("angle_review_approval"),
|
|
19260
19395
|
// All edits are optional — empty action body just approves the
|
|
19261
19396
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
19262
19397
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
19263
19398
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
19264
|
-
customAngle:
|
|
19399
|
+
customAngle: z73.string().min(1).max(480).optional(),
|
|
19265
19400
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
19266
19401
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
19267
|
-
painPoints:
|
|
19268
|
-
benefits:
|
|
19402
|
+
painPoints: z73.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
19403
|
+
benefits: z73.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
19269
19404
|
// Same policy as the two fields above: the strictest downstream contract
|
|
19270
19405
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
19271
19406
|
// accept 300, and this single action routes to whichever the task is — so
|
|
19272
19407
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
19273
19408
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
19274
|
-
features:
|
|
19275
|
-
buyerPersona:
|
|
19409
|
+
features: z73.array(z73.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
19410
|
+
buyerPersona: z73.string().min(1).max(360).optional(),
|
|
19276
19411
|
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.'),
|
|
19277
|
-
actor:
|
|
19278
|
-
actorId:
|
|
19279
|
-
creativeDirection:
|
|
19280
|
-
selectedAngleNumbers:
|
|
19281
|
-
angleEdits:
|
|
19282
|
-
angleNumber:
|
|
19283
|
-
narrativeSelection:
|
|
19412
|
+
actor: z73.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."),
|
|
19413
|
+
actorId: z73.string().max(120).nullable().optional(),
|
|
19414
|
+
creativeDirection: z73.string().max(2e3).optional(),
|
|
19415
|
+
selectedAngleNumbers: z73.array(z73.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."),
|
|
19416
|
+
angleEdits: z73.array(z73.object({
|
|
19417
|
+
angleNumber: z73.number().int().positive(),
|
|
19418
|
+
narrativeSelection: z73.enum([
|
|
19284
19419
|
"market",
|
|
19285
19420
|
"guided"
|
|
19286
19421
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
19287
|
-
angle:
|
|
19288
|
-
buyerPersona:
|
|
19422
|
+
angle: z73.string().min(1).max(480).optional(),
|
|
19423
|
+
buyerPersona: z73.string().min(1).max(360).optional(),
|
|
19289
19424
|
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.'),
|
|
19290
|
-
actor:
|
|
19291
|
-
actorId:
|
|
19292
|
-
creativeDirection:
|
|
19425
|
+
actor: z73.string().min(1).max(360).optional(),
|
|
19426
|
+
actorId: z73.string().max(120).nullable().optional(),
|
|
19427
|
+
creativeDirection: z73.string().max(2e3).optional()
|
|
19293
19428
|
}).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)."),
|
|
19294
|
-
gapDurationSeconds:
|
|
19295
|
-
|
|
19296
|
-
|
|
19429
|
+
gapDurationSeconds: z73.union([
|
|
19430
|
+
z73.literal(15),
|
|
19431
|
+
z73.literal(30)
|
|
19297
19432
|
]).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.")
|
|
19298
19433
|
}),
|
|
19299
|
-
|
|
19300
|
-
kind:
|
|
19301
|
-
angleId:
|
|
19302
|
-
angleNumber:
|
|
19303
|
-
content:
|
|
19304
|
-
creativeDirection:
|
|
19305
|
-
actor:
|
|
19434
|
+
z73.object({
|
|
19435
|
+
kind: z73.literal("service_angle_approval"),
|
|
19436
|
+
angleId: z73.string().uuid().optional(),
|
|
19437
|
+
angleNumber: z73.number().int().positive().optional(),
|
|
19438
|
+
content: z73.string().min(1).max(480).optional(),
|
|
19439
|
+
creativeDirection: z73.string().min(1).max(1500).optional(),
|
|
19440
|
+
actor: z73.string().min(1).max(360).optional()
|
|
19306
19441
|
}),
|
|
19307
|
-
|
|
19308
|
-
kind:
|
|
19309
|
-
voiceovers:
|
|
19310
|
-
visualDirections:
|
|
19311
|
-
voiceoversByScene:
|
|
19312
|
-
visualDirectionsByScene:
|
|
19442
|
+
z73.object({
|
|
19443
|
+
kind: z73.literal("service_script_approval"),
|
|
19444
|
+
voiceovers: z73.record(z73.string(), z73.string().min(1).max(600)).optional(),
|
|
19445
|
+
visualDirections: z73.record(z73.string(), z73.string().min(1).max(1200)).optional(),
|
|
19446
|
+
voiceoversByScene: z73.record(z73.string(), z73.string().min(1).max(600)).optional(),
|
|
19447
|
+
visualDirectionsByScene: z73.record(z73.string(), z73.string().min(1).max(1200)).optional()
|
|
19313
19448
|
})
|
|
19314
19449
|
]);
|
|
19315
|
-
var ResolvePendingActionInput =
|
|
19316
|
-
taskId:
|
|
19450
|
+
var ResolvePendingActionInput = z73.object({
|
|
19451
|
+
taskId: z73.string().min(1),
|
|
19317
19452
|
action: PendingActionPayload
|
|
19318
19453
|
}).strict();
|
|
19319
19454
|
function resolveVariantConfirmVideoTier(action) {
|
|
19320
19455
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
19321
19456
|
}
|
|
19322
19457
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
19323
|
-
var StatusForResolveSchema =
|
|
19458
|
+
var StatusForResolveSchema = z73.object({
|
|
19324
19459
|
// Metadata used to select the backend resume contract. Older API responses
|
|
19325
19460
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
19326
|
-
kind:
|
|
19461
|
+
kind: z73.enum([
|
|
19327
19462
|
"autopilot",
|
|
19328
19463
|
"video",
|
|
19329
19464
|
"image",
|
|
@@ -19331,18 +19466,18 @@ var StatusForResolveSchema = z72.object({
|
|
|
19331
19466
|
"mix",
|
|
19332
19467
|
"service"
|
|
19333
19468
|
]).optional(),
|
|
19334
|
-
selectedOutputs:
|
|
19469
|
+
selectedOutputs: z73.array(z73.enum([
|
|
19335
19470
|
"landing",
|
|
19336
19471
|
"video",
|
|
19337
19472
|
"image"
|
|
19338
19473
|
])).optional(),
|
|
19339
|
-
videoAngleCount:
|
|
19340
|
-
ugcFormat:
|
|
19474
|
+
videoAngleCount: z73.number().int().min(1).max(3).optional(),
|
|
19475
|
+
ugcFormat: z73.enum([
|
|
19341
19476
|
"single_8s",
|
|
19342
19477
|
"single_15s",
|
|
19343
19478
|
"double_30s"
|
|
19344
19479
|
]).optional(),
|
|
19345
|
-
videoStyle:
|
|
19480
|
+
videoStyle: z73.enum([
|
|
19346
19481
|
"ugc",
|
|
19347
19482
|
"cartoon_3d",
|
|
19348
19483
|
"product_only",
|
|
@@ -19351,7 +19486,7 @@ var StatusForResolveSchema = z72.object({
|
|
|
19351
19486
|
videoStructure: VideoStructureEnum.optional(),
|
|
19352
19487
|
videoQuality: VideoQualityEnum.optional(),
|
|
19353
19488
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
19354
|
-
videoModel:
|
|
19489
|
+
videoModel: z73.enum([
|
|
19355
19490
|
"veo",
|
|
19356
19491
|
"wan",
|
|
19357
19492
|
"bytedance",
|
|
@@ -19359,71 +19494,71 @@ var StatusForResolveSchema = z72.object({
|
|
|
19359
19494
|
"grok",
|
|
19360
19495
|
"kling"
|
|
19361
19496
|
]).optional(),
|
|
19362
|
-
videoTier:
|
|
19497
|
+
videoTier: z73.enum([
|
|
19363
19498
|
"legacy",
|
|
19364
19499
|
"standard",
|
|
19365
19500
|
"pro",
|
|
19366
19501
|
"single_call"
|
|
19367
19502
|
]).optional(),
|
|
19368
|
-
videoResolution:
|
|
19503
|
+
videoResolution: z73.enum([
|
|
19369
19504
|
"480p",
|
|
19370
19505
|
"720p"
|
|
19371
19506
|
]).optional(),
|
|
19372
19507
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
19373
|
-
pauseForVideoScriptReview:
|
|
19374
|
-
pendingUserAction:
|
|
19375
|
-
kind:
|
|
19376
|
-
candidateGrouping:
|
|
19377
|
-
selectedImageUrls:
|
|
19378
|
-
proposedProductNames:
|
|
19508
|
+
pauseForVideoScriptReview: z73.boolean().optional(),
|
|
19509
|
+
pendingUserAction: z73.object({
|
|
19510
|
+
kind: z73.string(),
|
|
19511
|
+
candidateGrouping: z73.string().optional(),
|
|
19512
|
+
selectedImageUrls: z73.array(z73.string()).optional(),
|
|
19513
|
+
proposedProductNames: z73.array(z73.string()).optional(),
|
|
19379
19514
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
19380
19515
|
// identity and the choices shown by the current snapshot; never accept a
|
|
19381
19516
|
// client-supplied reference set as authorization.
|
|
19382
|
-
options:
|
|
19383
|
-
mode:
|
|
19517
|
+
options: z73.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
19518
|
+
mode: z73.enum([
|
|
19384
19519
|
"question",
|
|
19385
19520
|
"visual_recovery"
|
|
19386
19521
|
]).optional(),
|
|
19387
19522
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
19388
|
-
canKeepSelection:
|
|
19389
|
-
decisionKey:
|
|
19390
|
-
questionOrdinal:
|
|
19391
|
-
questionCeiling:
|
|
19392
|
-
|
|
19393
|
-
|
|
19523
|
+
canKeepSelection: z73.boolean().optional(),
|
|
19524
|
+
decisionKey: z73.string().optional(),
|
|
19525
|
+
questionOrdinal: z73.number().int().min(1).max(5).optional(),
|
|
19526
|
+
questionCeiling: z73.union([
|
|
19527
|
+
z73.literal(3),
|
|
19528
|
+
z73.literal(5)
|
|
19394
19529
|
]).optional(),
|
|
19395
|
-
referenceEvidenceVersion:
|
|
19396
|
-
expectedEvidenceHash:
|
|
19397
|
-
question:
|
|
19398
|
-
prompt:
|
|
19399
|
-
helpText:
|
|
19400
|
-
options:
|
|
19530
|
+
referenceEvidenceVersion: z73.number().int().positive().optional(),
|
|
19531
|
+
expectedEvidenceHash: z73.string().optional(),
|
|
19532
|
+
question: z73.object({
|
|
19533
|
+
prompt: z73.string().min(1).max(240),
|
|
19534
|
+
helpText: z73.string().min(1).max(300).optional(),
|
|
19535
|
+
options: z73.array(z73.object({
|
|
19401
19536
|
value: ProductReferenceUserChoiceEnum,
|
|
19402
|
-
label:
|
|
19403
|
-
description:
|
|
19537
|
+
label: z73.string().min(1).max(120),
|
|
19538
|
+
description: z73.string().min(1).max(240).optional()
|
|
19404
19539
|
})).min(2).max(4)
|
|
19405
19540
|
}).optional(),
|
|
19406
19541
|
scope: ProductReferenceScopeEnum.optional(),
|
|
19407
|
-
scopeKey:
|
|
19408
|
-
scopeSnapshotId:
|
|
19409
|
-
scopeHash:
|
|
19410
|
-
baseReferenceSetHash:
|
|
19411
|
-
phase:
|
|
19542
|
+
scopeKey: z73.string().optional(),
|
|
19543
|
+
scopeSnapshotId: z73.string().uuid().optional(),
|
|
19544
|
+
scopeHash: z73.string().optional(),
|
|
19545
|
+
baseReferenceSetHash: z73.string().optional(),
|
|
19546
|
+
phase: z73.enum([
|
|
19412
19547
|
"preparation",
|
|
19413
19548
|
"final"
|
|
19414
19549
|
]).optional(),
|
|
19415
|
-
selectedRefKeys:
|
|
19416
|
-
allowedDecisions:
|
|
19417
|
-
previews:
|
|
19418
|
-
refKey:
|
|
19550
|
+
selectedRefKeys: z73.array(z73.string().min(1).max(200)).optional(),
|
|
19551
|
+
allowedDecisions: z73.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
19552
|
+
previews: z73.array(z73.object({
|
|
19553
|
+
refKey: z73.string().min(1).max(200)
|
|
19419
19554
|
}).passthrough()).optional(),
|
|
19420
|
-
customAngleDraft:
|
|
19421
|
-
painPointsDraft:
|
|
19422
|
-
benefitsDraft:
|
|
19423
|
-
featuresDraft:
|
|
19424
|
-
angleOptions:
|
|
19425
|
-
index:
|
|
19426
|
-
angle:
|
|
19555
|
+
customAngleDraft: z73.string().optional(),
|
|
19556
|
+
painPointsDraft: z73.string().optional(),
|
|
19557
|
+
benefitsDraft: z73.string().optional(),
|
|
19558
|
+
featuresDraft: z73.array(z73.string()).optional(),
|
|
19559
|
+
angleOptions: z73.array(z73.object({
|
|
19560
|
+
index: z73.number().int().nonnegative(),
|
|
19561
|
+
angle: z73.string().min(1)
|
|
19427
19562
|
}).passthrough()).min(1).max(5).optional(),
|
|
19428
19563
|
// Recommendation consumed only when the caller explicitly sends
|
|
19429
19564
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -19433,17 +19568,17 @@ var StatusForResolveSchema = z72.object({
|
|
|
19433
19568
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
19434
19569
|
// dropped here, so the approval handler below could not echo it back on the
|
|
19435
19570
|
// PATCH — the selection looked accepted and reached no render.
|
|
19436
|
-
angles:
|
|
19437
|
-
id:
|
|
19438
|
-
content:
|
|
19439
|
-
creativeDirection:
|
|
19440
|
-
actor:
|
|
19441
|
-
actorId:
|
|
19571
|
+
angles: z73.array(z73.object({
|
|
19572
|
+
id: z73.string().uuid(),
|
|
19573
|
+
content: z73.string(),
|
|
19574
|
+
creativeDirection: z73.string(),
|
|
19575
|
+
actor: z73.string(),
|
|
19576
|
+
actorId: z73.string().nullable().optional()
|
|
19442
19577
|
}).passthrough()).optional(),
|
|
19443
|
-
panels:
|
|
19444
|
-
beatId:
|
|
19445
|
-
voiceover:
|
|
19446
|
-
visualDirection:
|
|
19578
|
+
panels: z73.array(z73.object({
|
|
19579
|
+
beatId: z73.string(),
|
|
19580
|
+
voiceover: z73.string(),
|
|
19581
|
+
visualDirection: z73.string()
|
|
19447
19582
|
}).passthrough()).optional()
|
|
19448
19583
|
}).optional()
|
|
19449
19584
|
}).passthrough();
|
|
@@ -19564,7 +19699,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
19564
19699
|
|
|
19565
19700
|
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.
|
|
19566
19701
|
|
|
19567
|
-
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,
|
|
19702
|
+
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) => {
|
|
19568
19703
|
try {
|
|
19569
19704
|
const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
|
|
19570
19705
|
const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
|
|
@@ -19655,7 +19790,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19655
19790
|
throw translateError(e);
|
|
19656
19791
|
}
|
|
19657
19792
|
});
|
|
19658
|
-
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,
|
|
19793
|
+
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) => {
|
|
19659
19794
|
try {
|
|
19660
19795
|
await requirePaidCreativeConfirmation(server, `Video de servicio en ${input.language}. Modo: ${input.reviewMode === "automatic" ? "la IA decide todo" : "reviews conversacionales"}.`);
|
|
19661
19796
|
const created = await api.postJson("/v2/ingest", {
|
|
@@ -19669,6 +19804,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19669
19804
|
voiceId: input.voiceId
|
|
19670
19805
|
} : {},
|
|
19671
19806
|
videoPreset: input.videoPreset,
|
|
19807
|
+
videoQuality: input.videoQuality,
|
|
19672
19808
|
reviewMode: input.reviewMode,
|
|
19673
19809
|
...input.brandId ? {
|
|
19674
19810
|
brandId: input.brandId
|
|
@@ -20273,7 +20409,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
20273
20409
|
|
|
20274
20410
|
// src/tools/creatives.ts
|
|
20275
20411
|
import { randomUUID } from "crypto";
|
|
20276
|
-
import { z as
|
|
20412
|
+
import { z as z74 } from "zod";
|
|
20277
20413
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
20278
20414
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
20279
20415
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -20283,70 +20419,70 @@ var CreativeRefs = {
|
|
|
20283
20419
|
images: ImagesInput,
|
|
20284
20420
|
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.'),
|
|
20285
20421
|
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.'),
|
|
20286
|
-
price:
|
|
20287
|
-
offer:
|
|
20288
|
-
compareAtPrice:
|
|
20289
|
-
productContext:
|
|
20290
|
-
productLabel:
|
|
20291
|
-
buyerPersona:
|
|
20292
|
-
isCombo:
|
|
20293
|
-
competitorScanEnabled:
|
|
20294
|
-
brandId:
|
|
20422
|
+
price: z74.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.'),
|
|
20423
|
+
offer: z74.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.'),
|
|
20424
|
+
compareAtPrice: z74.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
20425
|
+
productContext: z74.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."),
|
|
20426
|
+
productLabel: z74.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.'),
|
|
20427
|
+
buyerPersona: z74.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.'),
|
|
20428
|
+
isCombo: z74.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
20429
|
+
competitorScanEnabled: z74.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."),
|
|
20430
|
+
brandId: z74.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.")
|
|
20295
20431
|
};
|
|
20296
|
-
var VideoPresenter =
|
|
20297
|
-
|
|
20298
|
-
mode:
|
|
20432
|
+
var VideoPresenter = z74.discriminatedUnion("mode", [
|
|
20433
|
+
z74.object({
|
|
20434
|
+
mode: z74.literal("none")
|
|
20299
20435
|
}).strict(),
|
|
20300
|
-
|
|
20301
|
-
mode:
|
|
20302
|
-
actorId:
|
|
20436
|
+
z74.object({
|
|
20437
|
+
mode: z74.literal("saved_actor"),
|
|
20438
|
+
actorId: z74.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
20303
20439
|
}).strict(),
|
|
20304
|
-
|
|
20305
|
-
mode:
|
|
20306
|
-
description:
|
|
20440
|
+
z74.object({
|
|
20441
|
+
mode: z74.literal("described"),
|
|
20442
|
+
description: z74.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
20307
20443
|
}).strict()
|
|
20308
20444
|
]);
|
|
20309
|
-
var VideoCreativeSetup =
|
|
20310
|
-
|
|
20311
|
-
mode:
|
|
20445
|
+
var VideoCreativeSetup = z74.discriminatedUnion("mode", [
|
|
20446
|
+
z74.object({
|
|
20447
|
+
mode: z74.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
20312
20448
|
}).strict(),
|
|
20313
|
-
|
|
20314
|
-
mode:
|
|
20449
|
+
z74.object({
|
|
20450
|
+
mode: z74.literal("guided"),
|
|
20315
20451
|
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.'),
|
|
20316
|
-
buyerPersona:
|
|
20452
|
+
buyerPersona: z74.string().trim().min(1).max(360),
|
|
20317
20453
|
presenter: VideoPresenter,
|
|
20318
|
-
creativeDirection:
|
|
20454
|
+
creativeDirection: z74.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
20319
20455
|
}).strict()
|
|
20320
20456
|
]);
|
|
20321
|
-
var VideoInput =
|
|
20457
|
+
var VideoInput = z74.object({
|
|
20322
20458
|
images: CreativeRefs.images.optional(),
|
|
20323
20459
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20324
|
-
title:
|
|
20325
|
-
primaryAngle:
|
|
20460
|
+
title: z74.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
20461
|
+
primaryAngle: z74.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".'),
|
|
20326
20462
|
language: CreativeRefs.language,
|
|
20327
20463
|
country: CreativeRefs.country,
|
|
20328
|
-
aspectRatio:
|
|
20464
|
+
aspectRatio: z74.enum([
|
|
20329
20465
|
"9:16",
|
|
20330
20466
|
"16:9",
|
|
20331
20467
|
"Auto"
|
|
20332
20468
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
20333
|
-
durationSeconds:
|
|
20334
|
-
videoAngleCount:
|
|
20469
|
+
durationSeconds: z74.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."),
|
|
20470
|
+
videoAngleCount: z74.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."),
|
|
20335
20471
|
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.'),
|
|
20336
20472
|
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."),
|
|
20337
20473
|
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.'),
|
|
20338
20474
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
20339
20475
|
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.'),
|
|
20340
|
-
features:
|
|
20476
|
+
features: z74.array(z74.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
20341
20477
|
price: CreativeRefs.price,
|
|
20342
20478
|
offer: CreativeRefs.offer,
|
|
20343
20479
|
productContext: CreativeRefs.productContext,
|
|
20344
20480
|
productLabel: CreativeRefs.productLabel,
|
|
20345
|
-
cta:
|
|
20346
|
-
scriptNotes:
|
|
20481
|
+
cta: z74.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.'),
|
|
20482
|
+
scriptNotes: z74.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.'),
|
|
20347
20483
|
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.'),
|
|
20348
20484
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
20349
|
-
replicateWinnerWhenFound:
|
|
20485
|
+
replicateWinnerWhenFound: z74.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."),
|
|
20350
20486
|
brandId: CreativeRefs.brandId
|
|
20351
20487
|
}).strict();
|
|
20352
20488
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -20364,7 +20500,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
20364
20500
|
length: 29
|
|
20365
20501
|
}, (_, index) => index + 2)
|
|
20366
20502
|
};
|
|
20367
|
-
var FreeVideoModelIdEnum =
|
|
20503
|
+
var FreeVideoModelIdEnum = z74.enum([
|
|
20368
20504
|
"grok-imagine-video-1-5-preview",
|
|
20369
20505
|
"minimax-h3/reference-to-video",
|
|
20370
20506
|
"wan/3-0-video",
|
|
@@ -20375,70 +20511,70 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
20375
20511
|
"minimax-h3/reference-to-video",
|
|
20376
20512
|
"wan/3-0-video"
|
|
20377
20513
|
];
|
|
20378
|
-
var FreeVideoInput =
|
|
20514
|
+
var FreeVideoInput = z74.object({
|
|
20379
20515
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
20380
|
-
rawPrompt:
|
|
20516
|
+
rawPrompt: z74.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."),
|
|
20381
20517
|
language: CreativeRefs.language,
|
|
20382
20518
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
20383
20519
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
20384
20520
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
20385
20521
|
// replacement — dropping it silently would turn a caller's explicit
|
|
20386
20522
|
// Pro++ pick into a quiet fallback to Wan.
|
|
20387
|
-
freeProModel:
|
|
20523
|
+
freeProModel: z74.enum([
|
|
20388
20524
|
"wan",
|
|
20389
20525
|
"seedance"
|
|
20390
20526
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
20391
20527
|
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.'),
|
|
20392
|
-
durationSeconds:
|
|
20528
|
+
durationSeconds: z74.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."),
|
|
20393
20529
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
20394
|
-
generateAiMusic:
|
|
20395
|
-
addSubtitles:
|
|
20396
|
-
idempotencyKey:
|
|
20530
|
+
generateAiMusic: z74.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
20531
|
+
addSubtitles: z74.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
20532
|
+
idempotencyKey: z74.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.")
|
|
20397
20533
|
}).strict();
|
|
20398
20534
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
20399
|
-
var ImageCreativeSetup =
|
|
20400
|
-
|
|
20401
|
-
mode:
|
|
20535
|
+
var ImageCreativeSetup = z74.discriminatedUnion("mode", [
|
|
20536
|
+
z74.object({
|
|
20537
|
+
mode: z74.literal("automatic")
|
|
20402
20538
|
}).strict(),
|
|
20403
|
-
|
|
20404
|
-
mode:
|
|
20405
|
-
creativeArchetype:
|
|
20539
|
+
z74.object({
|
|
20540
|
+
mode: z74.literal("guided"),
|
|
20541
|
+
creativeArchetype: z74.union([
|
|
20406
20542
|
ImageCreativeArchetypeEnum,
|
|
20407
|
-
|
|
20543
|
+
z74.literal("ai_decides")
|
|
20408
20544
|
]),
|
|
20409
|
-
visualTreatment:
|
|
20545
|
+
visualTreatment: z74.union([
|
|
20410
20546
|
ImageCreativeVisualTreatmentEnum,
|
|
20411
|
-
|
|
20547
|
+
z74.literal("ai_decides")
|
|
20412
20548
|
]),
|
|
20413
20549
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
20414
|
-
nVariants:
|
|
20415
|
-
|
|
20416
|
-
|
|
20417
|
-
|
|
20418
|
-
|
|
20419
|
-
|
|
20550
|
+
nVariants: z74.union([
|
|
20551
|
+
z74.literal(1),
|
|
20552
|
+
z74.literal(2),
|
|
20553
|
+
z74.literal(3),
|
|
20554
|
+
z74.literal(4),
|
|
20555
|
+
z74.literal(6)
|
|
20420
20556
|
]),
|
|
20421
|
-
imageModel:
|
|
20557
|
+
imageModel: z74.enum([
|
|
20422
20558
|
"gpt-image-2-5:1k",
|
|
20423
20559
|
"gpt-image-2-5:2k",
|
|
20424
20560
|
"gpt-image-2:1k",
|
|
20425
20561
|
"gpt-image-2:2k"
|
|
20426
20562
|
]),
|
|
20427
|
-
styleMix:
|
|
20428
|
-
generateAdCopy:
|
|
20429
|
-
competitorScanEnabled:
|
|
20430
|
-
productContext:
|
|
20431
|
-
creativeDirection:
|
|
20432
|
-
brandColors:
|
|
20433
|
-
headline:
|
|
20434
|
-
subheadline:
|
|
20563
|
+
styleMix: z74.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
20564
|
+
generateAdCopy: z74.boolean(),
|
|
20565
|
+
competitorScanEnabled: z74.boolean(),
|
|
20566
|
+
productContext: z74.string().trim().min(1).max(3e3).nullable(),
|
|
20567
|
+
creativeDirection: z74.string().trim().min(1).max(500).nullable(),
|
|
20568
|
+
brandColors: z74.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.'),
|
|
20569
|
+
headline: z74.string().trim().min(1).max(120).nullable(),
|
|
20570
|
+
subheadline: z74.string().trim().min(1).max(160).nullable()
|
|
20435
20571
|
}).strict()
|
|
20436
20572
|
]).superRefine((setup, context) => {
|
|
20437
20573
|
if (setup.mode !== "guided") return;
|
|
20438
20574
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
20439
20575
|
if (needsStyleMix && setup.styleMix === null) {
|
|
20440
20576
|
context.addIssue({
|
|
20441
|
-
code:
|
|
20577
|
+
code: z74.ZodIssueCode.custom,
|
|
20442
20578
|
path: [
|
|
20443
20579
|
"styleMix"
|
|
20444
20580
|
],
|
|
@@ -20447,7 +20583,7 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
20447
20583
|
}
|
|
20448
20584
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
20449
20585
|
context.addIssue({
|
|
20450
|
-
code:
|
|
20586
|
+
code: z74.ZodIssueCode.custom,
|
|
20451
20587
|
path: [
|
|
20452
20588
|
"styleMix"
|
|
20453
20589
|
],
|
|
@@ -20456,7 +20592,7 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
20456
20592
|
}
|
|
20457
20593
|
if ((setup.imageModel === "gpt-image-2:2k" || setup.imageModel === "gpt-image-2-5:2k") && setup.aspectRatio === "4:5") {
|
|
20458
20594
|
context.addIssue({
|
|
20459
|
-
code:
|
|
20595
|
+
code: z74.ZodIssueCode.custom,
|
|
20460
20596
|
path: [
|
|
20461
20597
|
"aspectRatio"
|
|
20462
20598
|
],
|
|
@@ -20464,53 +20600,53 @@ var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
|
20464
20600
|
});
|
|
20465
20601
|
}
|
|
20466
20602
|
});
|
|
20467
|
-
var LandingCreativeSetup =
|
|
20468
|
-
|
|
20469
|
-
mode:
|
|
20603
|
+
var LandingCreativeSetup = z74.discriminatedUnion("mode", [
|
|
20604
|
+
z74.object({
|
|
20605
|
+
mode: z74.literal("automatic")
|
|
20470
20606
|
}).strict(),
|
|
20471
|
-
|
|
20472
|
-
mode:
|
|
20607
|
+
z74.object({
|
|
20608
|
+
mode: z74.literal("guided"),
|
|
20473
20609
|
landingStrategy: LandingStrategyEnum,
|
|
20474
20610
|
landingImageFormat: LandingImageFormatEnum,
|
|
20475
|
-
competitorScanEnabled:
|
|
20476
|
-
paymentMethods:
|
|
20477
|
-
productContext:
|
|
20478
|
-
creativeDirection:
|
|
20479
|
-
headline:
|
|
20480
|
-
subheadline:
|
|
20611
|
+
competitorScanEnabled: z74.boolean(),
|
|
20612
|
+
paymentMethods: z74.string().trim().min(1).max(240).nullable(),
|
|
20613
|
+
productContext: z74.string().trim().min(1).max(3e3).nullable(),
|
|
20614
|
+
creativeDirection: z74.string().trim().min(1).max(500).nullable(),
|
|
20615
|
+
headline: z74.string().trim().min(1).max(120).nullable(),
|
|
20616
|
+
subheadline: z74.string().trim().min(1).max(160).nullable()
|
|
20481
20617
|
}).strict()
|
|
20482
20618
|
]);
|
|
20483
|
-
var ImageInput =
|
|
20619
|
+
var ImageInput = z74.object({
|
|
20484
20620
|
images: CreativeRefs.images.optional(),
|
|
20485
20621
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20486
|
-
productTitle:
|
|
20487
|
-
primaryAngle:
|
|
20622
|
+
productTitle: z74.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
20623
|
+
primaryAngle: z74.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.'),
|
|
20488
20624
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20489
20625
|
language: CreativeRefs.language,
|
|
20490
20626
|
country: CreativeRefs.country,
|
|
20491
20627
|
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."),
|
|
20492
20628
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
20493
|
-
features:
|
|
20629
|
+
features: z74.array(z74.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
20494
20630
|
price: CreativeRefs.price,
|
|
20495
|
-
omitPrice:
|
|
20631
|
+
omitPrice: z74.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."),
|
|
20496
20632
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
20497
20633
|
offer: CreativeRefs.offer,
|
|
20498
20634
|
productLabel: CreativeRefs.productLabel,
|
|
20499
20635
|
isCombo: CreativeRefs.isCombo,
|
|
20500
20636
|
brandId: CreativeRefs.brandId
|
|
20501
20637
|
});
|
|
20502
|
-
var EditImageCreativeInput =
|
|
20503
|
-
taskId:
|
|
20504
|
-
variantIndex:
|
|
20505
|
-
instruction:
|
|
20638
|
+
var EditImageCreativeInput = z74.object({
|
|
20639
|
+
taskId: z74.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
20640
|
+
variantIndex: z74.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
20641
|
+
instruction: z74.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".')
|
|
20506
20642
|
});
|
|
20507
|
-
var LandingInput =
|
|
20643
|
+
var LandingInput = z74.object({
|
|
20508
20644
|
images: CreativeRefs.images.optional(),
|
|
20509
20645
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
20510
20646
|
language: CreativeRefs.language,
|
|
20511
20647
|
country: CreativeRefs.country,
|
|
20512
20648
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
20513
|
-
salesAngle:
|
|
20649
|
+
salesAngle: z74.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.'),
|
|
20514
20650
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
20515
20651
|
price: CreativeRefs.price,
|
|
20516
20652
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -20579,7 +20715,7 @@ function resolveLandingSetup(setup) {
|
|
|
20579
20715
|
}
|
|
20580
20716
|
__name(resolveLandingSetup, "resolveLandingSetup");
|
|
20581
20717
|
function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
20582
|
-
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,
|
|
20718
|
+
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) => {
|
|
20583
20719
|
try {
|
|
20584
20720
|
if (input.freeProModel) {
|
|
20585
20721
|
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).");
|
|
@@ -20627,7 +20763,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20627
20763
|
throw translateError(e);
|
|
20628
20764
|
}
|
|
20629
20765
|
});
|
|
20630
|
-
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,
|
|
20766
|
+
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) => {
|
|
20631
20767
|
try {
|
|
20632
20768
|
if (!input.images && !input.winnerReference) {
|
|
20633
20769
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -20691,7 +20827,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20691
20827
|
throw translateError(e);
|
|
20692
20828
|
}
|
|
20693
20829
|
});
|
|
20694
|
-
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,
|
|
20830
|
+
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) => {
|
|
20695
20831
|
try {
|
|
20696
20832
|
if (!input.images && !input.winnerReference) {
|
|
20697
20833
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -20737,7 +20873,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20737
20873
|
throw translateError(e);
|
|
20738
20874
|
}
|
|
20739
20875
|
});
|
|
20740
|
-
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,
|
|
20876
|
+
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) => {
|
|
20741
20877
|
try {
|
|
20742
20878
|
if (!input.images && !input.winnerReference) {
|
|
20743
20879
|
throw new Error("images o winnerReference es requerido.");
|
|
@@ -20772,10 +20908,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20772
20908
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
20773
20909
|
|
|
20774
20910
|
// src/tools/creative-variants.ts
|
|
20775
|
-
import { z as
|
|
20911
|
+
import { z as z75 } from "zod";
|
|
20776
20912
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
20777
20913
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
20778
|
-
var LandingSectionKeyEnum =
|
|
20914
|
+
var LandingSectionKeyEnum = z75.enum([
|
|
20779
20915
|
"problem_hook",
|
|
20780
20916
|
"problem_cost",
|
|
20781
20917
|
"solution_mechanism",
|
|
@@ -20815,24 +20951,24 @@ var LandingSectionKeyEnum = z74.enum([
|
|
|
20815
20951
|
"lifestyle_fit",
|
|
20816
20952
|
"join_lifestyle"
|
|
20817
20953
|
]);
|
|
20818
|
-
var CreativeVariantKindEnum =
|
|
20954
|
+
var CreativeVariantKindEnum = z75.enum([
|
|
20819
20955
|
"video",
|
|
20820
20956
|
"image",
|
|
20821
20957
|
"landing"
|
|
20822
20958
|
]);
|
|
20823
|
-
var EstimateCreativeVariantInputBase =
|
|
20824
|
-
sourceTaskId:
|
|
20959
|
+
var EstimateCreativeVariantInputBase = z75.object({
|
|
20960
|
+
sourceTaskId: z75.string().uuid().describe("ID de la tarea original completada."),
|
|
20825
20961
|
kind: CreativeVariantKindEnum,
|
|
20826
20962
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
20827
20963
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
20828
|
-
nVariants:
|
|
20964
|
+
nVariants: z75.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
20829
20965
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
20830
|
-
instructions:
|
|
20966
|
+
instructions: z75.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.")
|
|
20831
20967
|
}).strict();
|
|
20832
20968
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
20833
20969
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
20834
20970
|
ctx.addIssue({
|
|
20835
|
-
code:
|
|
20971
|
+
code: z75.ZodIssueCode.custom,
|
|
20836
20972
|
path: [
|
|
20837
20973
|
"nVariants"
|
|
20838
20974
|
],
|
|
@@ -20842,7 +20978,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20842
20978
|
if (input.kind !== "video") {
|
|
20843
20979
|
if (input.videoPreset !== void 0) {
|
|
20844
20980
|
ctx.addIssue({
|
|
20845
|
-
code:
|
|
20981
|
+
code: z75.ZodIssueCode.custom,
|
|
20846
20982
|
path: [
|
|
20847
20983
|
"videoPreset"
|
|
20848
20984
|
],
|
|
@@ -20851,7 +20987,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20851
20987
|
}
|
|
20852
20988
|
if (input.videoResolution !== void 0) {
|
|
20853
20989
|
ctx.addIssue({
|
|
20854
|
-
code:
|
|
20990
|
+
code: z75.ZodIssueCode.custom,
|
|
20855
20991
|
path: [
|
|
20856
20992
|
"videoResolution"
|
|
20857
20993
|
],
|
|
@@ -20861,7 +20997,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20861
20997
|
}
|
|
20862
20998
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
20863
20999
|
ctx.addIssue({
|
|
20864
|
-
code:
|
|
21000
|
+
code: z75.ZodIssueCode.custom,
|
|
20865
21001
|
path: [
|
|
20866
21002
|
"nVariants"
|
|
20867
21003
|
],
|
|
@@ -20871,7 +21007,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20871
21007
|
if (input.kind !== "landing") {
|
|
20872
21008
|
if (input.sectionKey !== void 0) {
|
|
20873
21009
|
ctx.addIssue({
|
|
20874
|
-
code:
|
|
21010
|
+
code: z75.ZodIssueCode.custom,
|
|
20875
21011
|
path: [
|
|
20876
21012
|
"sectionKey"
|
|
20877
21013
|
],
|
|
@@ -20880,7 +21016,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20880
21016
|
}
|
|
20881
21017
|
if (input.instructions !== void 0) {
|
|
20882
21018
|
ctx.addIssue({
|
|
20883
|
-
code:
|
|
21019
|
+
code: z75.ZodIssueCode.custom,
|
|
20884
21020
|
path: [
|
|
20885
21021
|
"instructions"
|
|
20886
21022
|
],
|
|
@@ -20889,31 +21025,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
20889
21025
|
}
|
|
20890
21026
|
}
|
|
20891
21027
|
});
|
|
20892
|
-
var CreateCreativeVariantInputBase =
|
|
20893
|
-
sourceTaskId:
|
|
21028
|
+
var CreateCreativeVariantInputBase = z75.object({
|
|
21029
|
+
sourceTaskId: z75.string().uuid().describe("ID de la tarea original completada."),
|
|
20894
21030
|
kind: CreativeVariantKindEnum,
|
|
20895
|
-
confirm:
|
|
20896
|
-
clientRequestId:
|
|
20897
|
-
angle:
|
|
20898
|
-
buyerPersona:
|
|
20899
|
-
scriptNotes:
|
|
20900
|
-
creativeDirection:
|
|
21031
|
+
confirm: z75.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
21032
|
+
clientRequestId: z75.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."),
|
|
21033
|
+
angle: z75.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
21034
|
+
buyerPersona: z75.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
21035
|
+
scriptNotes: z75.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
21036
|
+
creativeDirection: z75.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
20901
21037
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
20902
21038
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
20903
|
-
generateAiMusic:
|
|
20904
|
-
nVariants:
|
|
21039
|
+
generateAiMusic: z75.boolean().optional().describe("Opcional para video."),
|
|
21040
|
+
nVariants: z75.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
20905
21041
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
20906
21042
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
20907
21043
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
20908
21044
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
20909
|
-
styleMix:
|
|
21045
|
+
styleMix: z75.boolean().optional().describe("Opcional para imagen."),
|
|
20910
21046
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
20911
|
-
instructions:
|
|
21047
|
+
instructions: z75.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.")
|
|
20912
21048
|
}).strict();
|
|
20913
21049
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
20914
21050
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
20915
21051
|
ctx.addIssue({
|
|
20916
|
-
code:
|
|
21052
|
+
code: z75.ZodIssueCode.custom,
|
|
20917
21053
|
path: [
|
|
20918
21054
|
"angle"
|
|
20919
21055
|
],
|
|
@@ -20922,7 +21058,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
20922
21058
|
}
|
|
20923
21059
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
20924
21060
|
ctx.addIssue({
|
|
20925
|
-
code:
|
|
21061
|
+
code: z75.ZodIssueCode.custom,
|
|
20926
21062
|
path: [
|
|
20927
21063
|
"instructions"
|
|
20928
21064
|
],
|
|
@@ -20968,7 +21104,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
20968
21104
|
for (const field of fieldsByKind[input.kind]) {
|
|
20969
21105
|
if (input[field] !== void 0) {
|
|
20970
21106
|
ctx.addIssue({
|
|
20971
|
-
code:
|
|
21107
|
+
code: z75.ZodIssueCode.custom,
|
|
20972
21108
|
path: [
|
|
20973
21109
|
field
|
|
20974
21110
|
],
|
|
@@ -21015,7 +21151,7 @@ function registerCreativeVariantTools(server, api) {
|
|
|
21015
21151
|
throw translateError(error);
|
|
21016
21152
|
}
|
|
21017
21153
|
});
|
|
21018
|
-
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,
|
|
21154
|
+
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) => {
|
|
21019
21155
|
try {
|
|
21020
21156
|
const validatedInput = parseVariantInput(CreateCreativeVariantInput, input);
|
|
21021
21157
|
const estimateInput = EstimateCreativeVariantInput.parse({
|
|
@@ -21085,32 +21221,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
21085
21221
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
21086
21222
|
|
|
21087
21223
|
// src/tools/script-review.ts
|
|
21088
|
-
import { z as
|
|
21224
|
+
import { z as z76 } from "zod";
|
|
21089
21225
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
21090
21226
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
21091
21227
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
21092
|
-
var GetVideoScriptInput =
|
|
21093
|
-
taskId:
|
|
21094
|
-
angleKey:
|
|
21228
|
+
var GetVideoScriptInput = z76.object({
|
|
21229
|
+
taskId: z76.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
21230
|
+
angleKey: z76.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.')
|
|
21095
21231
|
}).strict();
|
|
21096
21232
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
21097
21233
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
21098
|
-
var ApproveSceneEdit =
|
|
21099
|
-
index:
|
|
21100
|
-
dialogue:
|
|
21234
|
+
var ApproveSceneEdit = z76.object({
|
|
21235
|
+
index: z76.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
21236
|
+
dialogue: z76.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
21101
21237
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
21102
21238
|
}).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.")
|
|
21103
21239
|
}).strict();
|
|
21104
|
-
var ApproveVideoScriptInput =
|
|
21105
|
-
taskId:
|
|
21106
|
-
angleKey:
|
|
21107
|
-
scenes:
|
|
21240
|
+
var ApproveVideoScriptInput = z76.object({
|
|
21241
|
+
taskId: z76.string().min(1).describe("ID de la tarea."),
|
|
21242
|
+
angleKey: z76.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.'),
|
|
21243
|
+
scenes: z76.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.")
|
|
21108
21244
|
}).strict();
|
|
21109
|
-
var RegenerateVideoScriptInput =
|
|
21110
|
-
taskId:
|
|
21111
|
-
angleKey:
|
|
21245
|
+
var RegenerateVideoScriptInput = z76.object({
|
|
21246
|
+
taskId: z76.string().min(1).describe("ID de la tarea."),
|
|
21247
|
+
angleKey: z76.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.'),
|
|
21112
21248
|
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).'),
|
|
21113
|
-
narrativeSelection:
|
|
21249
|
+
narrativeSelection: z76.enum([
|
|
21114
21250
|
"market",
|
|
21115
21251
|
"guided"
|
|
21116
21252
|
]).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.")
|
|
@@ -21170,9 +21306,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
21170
21306
|
// Not CREATES_INTERNAL: approving the script is what STARTS the render, so
|
|
21171
21307
|
// this call dispatches jobs to the video providers and burns credits. Its own
|
|
21172
21308
|
// description says so ("Tras llamarlo, el render arranca y consume créditos").
|
|
21173
|
-
//
|
|
21174
|
-
//
|
|
21175
|
-
|
|
21309
|
+
// `destructiveHint` keeps a host from treating the credit charge as a
|
|
21310
|
+
// reversible bookkeeping update.
|
|
21311
|
+
CREATES_PAID,
|
|
21176
21312
|
async (input) => {
|
|
21177
21313
|
try {
|
|
21178
21314
|
await requirePaidCreativeConfirmation(server, `Aprobar ${input.scenes.length} escena(s) y comenzar el render pagado del video.`);
|
|
@@ -21191,14 +21327,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
21191
21327
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
21192
21328
|
|
|
21193
21329
|
// src/tools/connections.ts
|
|
21194
|
-
import { z as
|
|
21330
|
+
import { z as z77 } from "zod";
|
|
21195
21331
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
21196
21332
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
21197
21333
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
21198
21334
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
21199
21335
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
21200
21336
|
function registerConnectionTools(server, api) {
|
|
21201
|
-
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.",
|
|
21337
|
+
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.", z77.object({}).shape, READS_INTERNAL, async () => {
|
|
21202
21338
|
try {
|
|
21203
21339
|
const r = await api.getJson("/v1/shopify/shops");
|
|
21204
21340
|
return asText(r);
|
|
@@ -21206,10 +21342,10 @@ function registerConnectionTools(server, api) {
|
|
|
21206
21342
|
throw translateError(e);
|
|
21207
21343
|
}
|
|
21208
21344
|
});
|
|
21209
|
-
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.',
|
|
21210
|
-
shopDomain:
|
|
21211
|
-
query:
|
|
21212
|
-
taskId:
|
|
21345
|
+
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.', z77.object({
|
|
21346
|
+
shopDomain: z77.string().min(3).max(120),
|
|
21347
|
+
query: z77.string().trim().max(120).optional(),
|
|
21348
|
+
taskId: z77.string().uuid().optional()
|
|
21213
21349
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
21214
21350
|
try {
|
|
21215
21351
|
const params = new URLSearchParams({
|
|
@@ -21223,7 +21359,7 @@ function registerConnectionTools(server, api) {
|
|
|
21223
21359
|
throw translateError(e);
|
|
21224
21360
|
}
|
|
21225
21361
|
});
|
|
21226
|
-
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.",
|
|
21362
|
+
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.", z77.object({}).shape, READS_EXTERNAL, async () => {
|
|
21227
21363
|
try {
|
|
21228
21364
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
21229
21365
|
return asText(r);
|
|
@@ -21233,7 +21369,7 @@ function registerConnectionTools(server, api) {
|
|
|
21233
21369
|
});
|
|
21234
21370
|
server.registerTool("list_meta_destinations", {
|
|
21235
21371
|
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.",
|
|
21236
|
-
inputSchema:
|
|
21372
|
+
inputSchema: z77.object({}).shape,
|
|
21237
21373
|
annotations: READS_EXTERNAL,
|
|
21238
21374
|
_meta: {
|
|
21239
21375
|
"openai/widgetAccessible": true
|
|
@@ -21246,7 +21382,7 @@ function registerConnectionTools(server, api) {
|
|
|
21246
21382
|
throw translateError(e);
|
|
21247
21383
|
}
|
|
21248
21384
|
});
|
|
21249
|
-
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
21385
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z77.object({}).shape, READS_EXTERNAL, async () => {
|
|
21250
21386
|
try {
|
|
21251
21387
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
21252
21388
|
return asText(r);
|
|
@@ -21258,10 +21394,10 @@ function registerConnectionTools(server, api) {
|
|
|
21258
21394
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
21259
21395
|
|
|
21260
21396
|
// src/tools/actors.ts
|
|
21261
|
-
import { z as
|
|
21397
|
+
import { z as z78 } from "zod";
|
|
21262
21398
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
21263
21399
|
function registerActorTools(server, api) {
|
|
21264
|
-
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.",
|
|
21400
|
+
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.", z78.object({}).shape, READS_INTERNAL, async () => {
|
|
21265
21401
|
try {
|
|
21266
21402
|
const rows = await api.getJson("/v1/actors");
|
|
21267
21403
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -21282,7 +21418,7 @@ function registerActorTools(server, api) {
|
|
|
21282
21418
|
__name(registerActorTools, "registerActorTools");
|
|
21283
21419
|
|
|
21284
21420
|
// src/tools/publish.ts
|
|
21285
|
-
import { z as
|
|
21421
|
+
import { z as z79 } from "zod";
|
|
21286
21422
|
|
|
21287
21423
|
// src/tools/stable-uuid.ts
|
|
21288
21424
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -21354,40 +21490,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
21354
21490
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
21355
21491
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
21356
21492
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
21357
|
-
var ShopifyInput =
|
|
21358
|
-
taskId:
|
|
21359
|
-
shopDomain:
|
|
21493
|
+
var ShopifyInput = z79.object({
|
|
21494
|
+
taskId: z79.string().min(1),
|
|
21495
|
+
shopDomain: z79.string().min(1),
|
|
21360
21496
|
/** Override: number of landing images to include. Default = ALL images the
|
|
21361
21497
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
21362
21498
|
* generously here; the backend validates each index against
|
|
21363
21499
|
* landing.images.length and rejects out-of-range. */
|
|
21364
|
-
numLandingImages:
|
|
21365
|
-
variantIndex:
|
|
21500
|
+
numLandingImages: z79.number().int().min(1).max(20).optional(),
|
|
21501
|
+
variantIndex: z79.number().int().min(0).optional(),
|
|
21366
21502
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
21367
21503
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
21368
21504
|
* a single-option product page. Defaults to false. */
|
|
21369
|
-
showVariantPicker:
|
|
21505
|
+
showVariantPicker: z79.boolean().optional(),
|
|
21370
21506
|
/** Default `auto` updates the product previously published for this task and
|
|
21371
21507
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
21372
21508
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
21373
|
-
publicationMode:
|
|
21509
|
+
publicationMode: z79.enum([
|
|
21374
21510
|
"auto",
|
|
21375
21511
|
"existing",
|
|
21376
21512
|
"new"
|
|
21377
21513
|
]).optional(),
|
|
21378
21514
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
21379
21515
|
* publicationMode is `existing`. */
|
|
21380
|
-
targetProductId:
|
|
21516
|
+
targetProductId: z79.string().trim().min(1).max(300).optional(),
|
|
21381
21517
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
21382
|
-
announcementBarEnabled:
|
|
21383
|
-
announcementBarText:
|
|
21518
|
+
announcementBarEnabled: z79.boolean().optional(),
|
|
21519
|
+
announcementBarText: z79.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
21384
21520
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
21385
|
-
confirmed:
|
|
21521
|
+
confirmed: z79.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
21386
21522
|
});
|
|
21387
21523
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
21388
21524
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
21389
21525
|
ctx.addIssue({
|
|
21390
|
-
code:
|
|
21526
|
+
code: z79.ZodIssueCode.custom,
|
|
21391
21527
|
path: [
|
|
21392
21528
|
"confirmed"
|
|
21393
21529
|
],
|
|
@@ -21396,7 +21532,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21396
21532
|
}
|
|
21397
21533
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
21398
21534
|
ctx.addIssue({
|
|
21399
|
-
code:
|
|
21535
|
+
code: z79.ZodIssueCode.custom,
|
|
21400
21536
|
path: [
|
|
21401
21537
|
"announcementBarText"
|
|
21402
21538
|
],
|
|
@@ -21405,7 +21541,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
21405
21541
|
}
|
|
21406
21542
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
21407
21543
|
ctx.addIssue({
|
|
21408
|
-
code:
|
|
21544
|
+
code: z79.ZodIssueCode.custom,
|
|
21409
21545
|
path: [
|
|
21410
21546
|
"announcementBarText"
|
|
21411
21547
|
],
|
|
@@ -21419,91 +21555,91 @@ function parseShopifyInput(rawInput) {
|
|
|
21419
21555
|
return parsed.data;
|
|
21420
21556
|
}
|
|
21421
21557
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
21422
|
-
var McpCampaignConfig =
|
|
21558
|
+
var McpCampaignConfig = z79.object({
|
|
21423
21559
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
21424
21560
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
21425
21561
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
21426
|
-
dailyBudgetUsd:
|
|
21562
|
+
dailyBudgetUsd: z79.number().positive().optional(),
|
|
21427
21563
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
21428
21564
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
21429
21565
|
* TikTok takes only the first entry. */
|
|
21430
|
-
targetCountries:
|
|
21431
|
-
campaignName:
|
|
21566
|
+
targetCountries: z79.array(CountryIso2Schema).max(1).optional(),
|
|
21567
|
+
campaignName: z79.string().trim().min(1).max(100).optional()
|
|
21432
21568
|
});
|
|
21433
21569
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
21434
|
-
var MetaInput =
|
|
21435
|
-
taskId:
|
|
21570
|
+
var MetaInput = z79.object({
|
|
21571
|
+
taskId: z79.string().min(1),
|
|
21436
21572
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21437
|
-
portfolioId:
|
|
21573
|
+
portfolioId: z79.string().trim().min(1),
|
|
21438
21574
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21439
|
-
pageId:
|
|
21575
|
+
pageId: z79.string().trim().min(1),
|
|
21440
21576
|
adAccountId: McpAdAccountId,
|
|
21441
|
-
pixelId:
|
|
21442
|
-
landingUrl:
|
|
21577
|
+
pixelId: z79.string().min(1).optional(),
|
|
21578
|
+
landingUrl: z79.string().url().optional(),
|
|
21443
21579
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
21444
21580
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
21445
|
-
angleIndexes:
|
|
21581
|
+
angleIndexes: z79.array(z79.number().int().nonnegative()).optional(),
|
|
21446
21582
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21447
21583
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
21448
21584
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
21449
21585
|
* (Meta's primary-text limit). */
|
|
21450
|
-
primaryText:
|
|
21586
|
+
primaryText: z79.string().trim().min(1).max(500).optional(),
|
|
21451
21587
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
21452
21588
|
* (wa.me) instead of a landing page. */
|
|
21453
|
-
phoneNumber:
|
|
21589
|
+
phoneNumber: z79.string().min(8).max(32).optional()
|
|
21454
21590
|
});
|
|
21455
|
-
var GroupedTaskSource =
|
|
21456
|
-
type:
|
|
21457
|
-
taskId:
|
|
21458
|
-
angleIndex:
|
|
21459
|
-
videoVariant:
|
|
21591
|
+
var GroupedTaskSource = z79.object({
|
|
21592
|
+
type: z79.literal("task"),
|
|
21593
|
+
taskId: z79.string().min(1),
|
|
21594
|
+
angleIndex: z79.number().int().min(0).optional(),
|
|
21595
|
+
videoVariant: z79.enum([
|
|
21460
21596
|
"with_subtitles",
|
|
21461
21597
|
"without_subtitles"
|
|
21462
21598
|
]).optional(),
|
|
21463
|
-
imageVariantIndex:
|
|
21464
|
-
});
|
|
21465
|
-
var GroupedMediaSource =
|
|
21466
|
-
type:
|
|
21467
|
-
url:
|
|
21468
|
-
path:
|
|
21469
|
-
thumbnailUrl:
|
|
21470
|
-
thumbnailPath:
|
|
21599
|
+
imageVariantIndex: z79.number().int().min(0).optional()
|
|
21600
|
+
});
|
|
21601
|
+
var GroupedMediaSource = z79.object({
|
|
21602
|
+
type: z79.literal("media"),
|
|
21603
|
+
url: z79.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
21604
|
+
path: z79.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".'),
|
|
21605
|
+
thumbnailUrl: z79.string().url().optional(),
|
|
21606
|
+
thumbnailPath: z79.string().min(1).optional()
|
|
21471
21607
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
21472
21608
|
message: "media source needs exactly one of `url` or `path`"
|
|
21473
21609
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
21474
21610
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
21475
21611
|
});
|
|
21476
|
-
var GroupedUploadedAssetSource =
|
|
21477
|
-
type:
|
|
21612
|
+
var GroupedUploadedAssetSource = z79.object({
|
|
21613
|
+
type: z79.literal("asset"),
|
|
21478
21614
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
21479
|
-
assetId:
|
|
21480
|
-
thumbnailAssetId:
|
|
21615
|
+
assetId: z79.string().uuid(),
|
|
21616
|
+
thumbnailAssetId: z79.string().uuid().optional()
|
|
21481
21617
|
});
|
|
21482
|
-
var GroupedCreative =
|
|
21483
|
-
type:
|
|
21618
|
+
var GroupedCreative = z79.object({
|
|
21619
|
+
type: z79.enum([
|
|
21484
21620
|
"image",
|
|
21485
21621
|
"video"
|
|
21486
21622
|
]),
|
|
21487
|
-
source:
|
|
21623
|
+
source: z79.union([
|
|
21488
21624
|
GroupedTaskSource,
|
|
21489
21625
|
GroupedMediaSource,
|
|
21490
21626
|
GroupedUploadedAssetSource
|
|
21491
21627
|
]),
|
|
21492
|
-
title:
|
|
21493
|
-
description:
|
|
21628
|
+
title: z79.string().max(120).optional(),
|
|
21629
|
+
description: z79.string().max(500).optional(),
|
|
21494
21630
|
cta: MetaCtaType.optional(),
|
|
21495
|
-
creativeId:
|
|
21631
|
+
creativeId: z79.string().min(1).optional()
|
|
21496
21632
|
});
|
|
21497
|
-
var GroupedCampaignConfigBase =
|
|
21633
|
+
var GroupedCampaignConfigBase = z79.object({
|
|
21498
21634
|
campaignType: MetaCampaignType.default("sales"),
|
|
21499
21635
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
21500
21636
|
budgetMode: MetaBudgetMode.optional(),
|
|
21501
|
-
campaignDailyBudget:
|
|
21502
|
-
adSets:
|
|
21503
|
-
tempId:
|
|
21504
|
-
name:
|
|
21505
|
-
dailyBudget:
|
|
21506
|
-
creativeIds:
|
|
21637
|
+
campaignDailyBudget: z79.number().int().positive().optional(),
|
|
21638
|
+
adSets: z79.array(z79.object({
|
|
21639
|
+
tempId: z79.string().min(1).max(80),
|
|
21640
|
+
name: z79.string().min(1).max(100),
|
|
21641
|
+
dailyBudget: z79.number().int().positive().optional(),
|
|
21642
|
+
creativeIds: z79.array(z79.string().min(1)).min(1)
|
|
21507
21643
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
21508
21644
|
/**
|
|
21509
21645
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -21511,17 +21647,17 @@ var GroupedCampaignConfigBase = z78.object({
|
|
|
21511
21647
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
21512
21648
|
* the API since #849 — unreachable from this tool.
|
|
21513
21649
|
*/
|
|
21514
|
-
destination:
|
|
21515
|
-
|
|
21516
|
-
type:
|
|
21517
|
-
landingUrl:
|
|
21650
|
+
destination: z79.discriminatedUnion("type", [
|
|
21651
|
+
z79.object({
|
|
21652
|
+
type: z79.literal("landing"),
|
|
21653
|
+
landingUrl: z79.string().url()
|
|
21518
21654
|
}),
|
|
21519
|
-
|
|
21520
|
-
type:
|
|
21521
|
-
phoneNumber:
|
|
21655
|
+
z79.object({
|
|
21656
|
+
type: z79.literal("whatsapp"),
|
|
21657
|
+
phoneNumber: z79.string().min(8).max(32)
|
|
21522
21658
|
})
|
|
21523
21659
|
]),
|
|
21524
|
-
saveAsDefault:
|
|
21660
|
+
saveAsDefault: z79.boolean().default(false),
|
|
21525
21661
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
21526
21662
|
});
|
|
21527
21663
|
function resolveBudgetMode(value) {
|
|
@@ -21535,7 +21671,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21535
21671
|
const budgetMode = resolveBudgetMode(value);
|
|
21536
21672
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
21537
21673
|
ctx.addIssue({
|
|
21538
|
-
code:
|
|
21674
|
+
code: z79.ZodIssueCode.custom,
|
|
21539
21675
|
path: [
|
|
21540
21676
|
"campaignDailyBudget"
|
|
21541
21677
|
],
|
|
@@ -21546,7 +21682,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21546
21682
|
value.adSets.forEach((adSet, index) => {
|
|
21547
21683
|
if (adSet.dailyBudget === void 0) {
|
|
21548
21684
|
ctx.addIssue({
|
|
21549
|
-
code:
|
|
21685
|
+
code: z79.ZodIssueCode.custom,
|
|
21550
21686
|
path: [
|
|
21551
21687
|
"adSets",
|
|
21552
21688
|
index,
|
|
@@ -21561,28 +21697,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
21561
21697
|
...value,
|
|
21562
21698
|
budgetMode: resolveBudgetMode(value)
|
|
21563
21699
|
}));
|
|
21564
|
-
var PublishCreativesToMetaInputBase =
|
|
21565
|
-
creatives:
|
|
21700
|
+
var PublishCreativesToMetaInputBase = z79.object({
|
|
21701
|
+
creatives: z79.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
21566
21702
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
21567
|
-
portfolioId:
|
|
21703
|
+
portfolioId: z79.string().trim().min(1),
|
|
21568
21704
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
21569
|
-
pageId:
|
|
21705
|
+
pageId: z79.string().trim().min(1),
|
|
21570
21706
|
adAccountId: McpAdAccountId,
|
|
21571
|
-
pixelId:
|
|
21707
|
+
pixelId: z79.string().min(1).optional(),
|
|
21572
21708
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
21573
21709
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
21574
|
-
landingUrl:
|
|
21710
|
+
landingUrl: z79.string().url().optional(),
|
|
21575
21711
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
21576
21712
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
21577
21713
|
targetCountry: CountryIso2Schema,
|
|
21578
|
-
campaignName:
|
|
21714
|
+
campaignName: z79.string().trim().min(1).max(100),
|
|
21579
21715
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
21580
21716
|
});
|
|
21581
21717
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
21582
21718
|
const destination = value.campaignConfig?.destination;
|
|
21583
21719
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
21584
21720
|
ctx.addIssue({
|
|
21585
|
-
code:
|
|
21721
|
+
code: z79.ZodIssueCode.custom,
|
|
21586
21722
|
path: [
|
|
21587
21723
|
"landingUrl"
|
|
21588
21724
|
],
|
|
@@ -21591,7 +21727,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21591
21727
|
}
|
|
21592
21728
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
21593
21729
|
ctx.addIssue({
|
|
21594
|
-
code:
|
|
21730
|
+
code: z79.ZodIssueCode.custom,
|
|
21595
21731
|
path: [
|
|
21596
21732
|
"campaignConfig",
|
|
21597
21733
|
"destination",
|
|
@@ -21610,16 +21746,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
21610
21746
|
}
|
|
21611
21747
|
return value;
|
|
21612
21748
|
});
|
|
21613
|
-
var PresignUploadResponseSchema =
|
|
21614
|
-
uploadUrl:
|
|
21749
|
+
var PresignUploadResponseSchema = z79.object({
|
|
21750
|
+
uploadUrl: z79.string().url().refine((value) => {
|
|
21615
21751
|
const url = new URL(value);
|
|
21616
21752
|
return !url.username && !url.password && url.protocol === "https:";
|
|
21617
21753
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
21618
|
-
publicUrl:
|
|
21754
|
+
publicUrl: z79.string().url().refine((value) => {
|
|
21619
21755
|
const url = new URL(value);
|
|
21620
21756
|
return !url.username && !url.password;
|
|
21621
21757
|
}, "public media URL must not contain embedded credentials"),
|
|
21622
|
-
stagingAssetId:
|
|
21758
|
+
stagingAssetId: z79.string().uuid()
|
|
21623
21759
|
});
|
|
21624
21760
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
21625
21761
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -21644,16 +21780,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
21644
21780
|
return uploadResolvedMedia(api, media, assetRole);
|
|
21645
21781
|
}
|
|
21646
21782
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
21647
|
-
var TikTokInput =
|
|
21648
|
-
taskId:
|
|
21649
|
-
advertiserId:
|
|
21650
|
-
pixelId:
|
|
21651
|
-
landingUrl:
|
|
21652
|
-
angleIndexes:
|
|
21783
|
+
var TikTokInput = z79.object({
|
|
21784
|
+
taskId: z79.string().min(1),
|
|
21785
|
+
advertiserId: z79.string().min(1),
|
|
21786
|
+
pixelId: z79.string().min(1).optional(),
|
|
21787
|
+
landingUrl: z79.string().url().optional(),
|
|
21788
|
+
angleIndexes: z79.array(z79.number().int().nonnegative()).optional(),
|
|
21653
21789
|
campaignConfig: McpCampaignConfig.optional(),
|
|
21654
21790
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
21655
21791
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
21656
|
-
primaryText:
|
|
21792
|
+
primaryText: z79.string().trim().min(1).max(500).optional()
|
|
21657
21793
|
});
|
|
21658
21794
|
function registerPublishTools(server, api, opts = {}) {
|
|
21659
21795
|
const transport = opts.transport ?? "http";
|
|
@@ -21981,39 +22117,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
21981
22117
|
|
|
21982
22118
|
// src/tools/meta-upload.ts
|
|
21983
22119
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
21984
|
-
import { z as
|
|
22120
|
+
import { z as z80 } from "zod";
|
|
21985
22121
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
21986
|
-
var UploadSessionInputBase =
|
|
21987
|
-
mediaKind:
|
|
22122
|
+
var UploadSessionInputBase = z80.object({
|
|
22123
|
+
mediaKind: z80.enum([
|
|
21988
22124
|
"image",
|
|
21989
22125
|
"video",
|
|
21990
22126
|
"mixed"
|
|
21991
22127
|
]).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."),
|
|
21992
|
-
assetRole:
|
|
22128
|
+
assetRole: z80.enum([
|
|
21993
22129
|
"media",
|
|
21994
22130
|
"thumbnail"
|
|
21995
22131
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
21996
|
-
uploadPurpose:
|
|
22132
|
+
uploadPurpose: z80.enum([
|
|
21997
22133
|
"product_reference",
|
|
21998
22134
|
"creative",
|
|
21999
22135
|
"generic"
|
|
22000
22136
|
]).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."),
|
|
22001
|
-
maxFiles:
|
|
22137
|
+
maxFiles: z80.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
22002
22138
|
});
|
|
22003
|
-
var OpenAiFileReference =
|
|
22004
|
-
download_url:
|
|
22005
|
-
file_id:
|
|
22006
|
-
mime_type:
|
|
22007
|
-
file_name:
|
|
22139
|
+
var OpenAiFileReference = z80.object({
|
|
22140
|
+
download_url: z80.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."),
|
|
22141
|
+
file_id: z80.string().min(1),
|
|
22142
|
+
mime_type: z80.string().min(1).optional(),
|
|
22143
|
+
file_name: z80.string().min(1).optional()
|
|
22008
22144
|
});
|
|
22009
22145
|
var UploadSessionToolInputShape = {
|
|
22010
22146
|
...UploadSessionInputBase.shape,
|
|
22011
|
-
files:
|
|
22147
|
+
files: z80.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.")
|
|
22012
22148
|
};
|
|
22013
|
-
var UploadSessionToolInput =
|
|
22149
|
+
var UploadSessionToolInput = z80.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
22014
22150
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
22015
22151
|
ctx.addIssue({
|
|
22016
|
-
code:
|
|
22152
|
+
code: z80.ZodIssueCode.custom,
|
|
22017
22153
|
path: [
|
|
22018
22154
|
"mediaKind"
|
|
22019
22155
|
],
|
|
@@ -22022,7 +22158,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
22022
22158
|
}
|
|
22023
22159
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
22024
22160
|
ctx.addIssue({
|
|
22025
|
-
code:
|
|
22161
|
+
code: z80.ZodIssueCode.custom,
|
|
22026
22162
|
path: [
|
|
22027
22163
|
"maxFiles"
|
|
22028
22164
|
],
|
|
@@ -22031,7 +22167,7 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
22031
22167
|
}
|
|
22032
22168
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
22033
22169
|
ctx.addIssue({
|
|
22034
|
-
code:
|
|
22170
|
+
code: z80.ZodIssueCode.custom,
|
|
22035
22171
|
path: [
|
|
22036
22172
|
"maxFiles"
|
|
22037
22173
|
],
|
|
@@ -22039,38 +22175,38 @@ var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine
|
|
|
22039
22175
|
});
|
|
22040
22176
|
}
|
|
22041
22177
|
});
|
|
22042
|
-
var UploadSessionResponse =
|
|
22043
|
-
sessionId:
|
|
22044
|
-
uploadPageUrl:
|
|
22045
|
-
mediaKind:
|
|
22178
|
+
var UploadSessionResponse = z80.object({
|
|
22179
|
+
sessionId: z80.string().uuid(),
|
|
22180
|
+
uploadPageUrl: z80.string().url(),
|
|
22181
|
+
mediaKind: z80.enum([
|
|
22046
22182
|
"image",
|
|
22047
22183
|
"video",
|
|
22048
22184
|
"mixed"
|
|
22049
22185
|
]),
|
|
22050
|
-
assetRole:
|
|
22186
|
+
assetRole: z80.enum([
|
|
22051
22187
|
"media",
|
|
22052
22188
|
"thumbnail"
|
|
22053
22189
|
]),
|
|
22054
|
-
maxFiles:
|
|
22055
|
-
expiresAt:
|
|
22190
|
+
maxFiles: z80.number().int().positive(),
|
|
22191
|
+
expiresAt: z80.string().datetime()
|
|
22056
22192
|
});
|
|
22057
|
-
var UploadStatusInput =
|
|
22058
|
-
sessionId:
|
|
22193
|
+
var UploadStatusInput = z80.object({
|
|
22194
|
+
sessionId: z80.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
22059
22195
|
});
|
|
22060
|
-
var UniversalUploadStatusResponse =
|
|
22061
|
-
|
|
22062
|
-
status:
|
|
22063
|
-
assets:
|
|
22196
|
+
var UniversalUploadStatusResponse = z80.discriminatedUnion("status", [
|
|
22197
|
+
z80.object({
|
|
22198
|
+
status: z80.literal("pending"),
|
|
22199
|
+
assets: z80.array(z80.never()).length(0)
|
|
22064
22200
|
}),
|
|
22065
|
-
|
|
22066
|
-
status:
|
|
22067
|
-
assets:
|
|
22068
|
-
assetId:
|
|
22069
|
-
mediaKind:
|
|
22201
|
+
z80.object({
|
|
22202
|
+
status: z80.literal("uploaded"),
|
|
22203
|
+
assets: z80.array(z80.object({
|
|
22204
|
+
assetId: z80.string().uuid(),
|
|
22205
|
+
mediaKind: z80.enum([
|
|
22070
22206
|
"image",
|
|
22071
22207
|
"video"
|
|
22072
22208
|
]),
|
|
22073
|
-
assetRole:
|
|
22209
|
+
assetRole: z80.enum([
|
|
22074
22210
|
"media",
|
|
22075
22211
|
"thumbnail"
|
|
22076
22212
|
])
|
|
@@ -22078,13 +22214,13 @@ var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
|
|
|
22078
22214
|
})
|
|
22079
22215
|
]);
|
|
22080
22216
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
22081
|
-
uploadPurpose:
|
|
22217
|
+
uploadPurpose: z80.enum([
|
|
22082
22218
|
"product_reference",
|
|
22083
22219
|
"creative",
|
|
22084
22220
|
"generic"
|
|
22085
22221
|
]),
|
|
22086
|
-
checkToolName:
|
|
22087
|
-
resolveEndpoint:
|
|
22222
|
+
checkToolName: z80.literal("check_media_upload"),
|
|
22223
|
+
resolveEndpoint: z80.string().url()
|
|
22088
22224
|
});
|
|
22089
22225
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
22090
22226
|
const url = new URL(uploadPageUrl);
|
|
@@ -22116,7 +22252,7 @@ __name(resolveEndpointForSession, "resolveEndpointForSession");
|
|
|
22116
22252
|
function registerMediaUploadTools(server, api) {
|
|
22117
22253
|
registerAppTool(server, "request_media_upload", {
|
|
22118
22254
|
title: "Subir archivos",
|
|
22119
|
-
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
|
|
22255
|
+
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.",
|
|
22120
22256
|
inputSchema: UploadSessionToolInputShape,
|
|
22121
22257
|
annotations: CREATES_INTERNAL,
|
|
22122
22258
|
outputSchema: UniversalUploadStructuredResponse.shape,
|
|
@@ -22175,15 +22311,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
22175
22311
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
22176
22312
|
|
|
22177
22313
|
// src/tools/campaigns.ts
|
|
22178
|
-
import { z as
|
|
22314
|
+
import { z as z81 } from "zod";
|
|
22179
22315
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
22180
22316
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
22181
|
-
var MetaStatusInput =
|
|
22182
|
-
campaignId:
|
|
22317
|
+
var MetaStatusInput = z81.object({
|
|
22318
|
+
campaignId: z81.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
22183
22319
|
});
|
|
22184
|
-
var TikTokStatusInput =
|
|
22185
|
-
campaignId:
|
|
22186
|
-
advertiserId:
|
|
22320
|
+
var TikTokStatusInput = z81.object({
|
|
22321
|
+
campaignId: z81.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
22322
|
+
advertiserId: z81.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
22187
22323
|
});
|
|
22188
22324
|
function registerCampaignTools(server, api) {
|
|
22189
22325
|
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) => {
|
|
@@ -22280,10 +22416,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
22280
22416
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
22281
22417
|
|
|
22282
22418
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22283
|
-
import { z as
|
|
22419
|
+
import { z as z83 } from "zod";
|
|
22284
22420
|
|
|
22285
22421
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22286
|
-
import { z as
|
|
22422
|
+
import { z as z82 } from "zod";
|
|
22287
22423
|
|
|
22288
22424
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
22289
22425
|
var product_costing_shipping_references_default = {
|
|
@@ -22347,21 +22483,21 @@ var product_costing_shipping_references_default = {
|
|
|
22347
22483
|
};
|
|
22348
22484
|
|
|
22349
22485
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
22350
|
-
var ShippingReferenceSchema =
|
|
22351
|
-
reference:
|
|
22352
|
-
min:
|
|
22353
|
-
max:
|
|
22354
|
-
updatedAt:
|
|
22355
|
-
confidence:
|
|
22486
|
+
var ShippingReferenceSchema = z82.object({
|
|
22487
|
+
reference: z82.number().positive(),
|
|
22488
|
+
min: z82.number().nonnegative(),
|
|
22489
|
+
max: z82.number().positive(),
|
|
22490
|
+
updatedAt: z82.string().date(),
|
|
22491
|
+
confidence: z82.enum([
|
|
22356
22492
|
"high",
|
|
22357
22493
|
"medium",
|
|
22358
22494
|
"medium-low"
|
|
22359
22495
|
]),
|
|
22360
|
-
sources:
|
|
22496
|
+
sources: z82.array(z82.string().url().startsWith("https://")).min(1).max(3)
|
|
22361
22497
|
}).superRefine(({ reference, min, max }, context) => {
|
|
22362
22498
|
if (min > reference || reference > max) {
|
|
22363
22499
|
context.addIssue({
|
|
22364
|
-
code:
|
|
22500
|
+
code: z82.ZodIssueCode.custom,
|
|
22365
22501
|
message: "shipping_reference_outside_range",
|
|
22366
22502
|
path: [
|
|
22367
22503
|
"reference"
|
|
@@ -22369,7 +22505,7 @@ var ShippingReferenceSchema = z81.object({
|
|
|
22369
22505
|
});
|
|
22370
22506
|
}
|
|
22371
22507
|
});
|
|
22372
|
-
var SHIPPING_REFERENCES =
|
|
22508
|
+
var SHIPPING_REFERENCES = z82.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
22373
22509
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
22374
22510
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
22375
22511
|
"MX",
|
|
@@ -22551,18 +22687,18 @@ function getProductCostingCountryName(country) {
|
|
|
22551
22687
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
22552
22688
|
|
|
22553
22689
|
// ../../packages/product-economics/src/product-costing.ts
|
|
22554
|
-
var ProductCostingInputSchema =
|
|
22555
|
-
country:
|
|
22556
|
-
supplierCost:
|
|
22557
|
-
shippingCost:
|
|
22558
|
-
returnRate:
|
|
22559
|
-
cancellationRate:
|
|
22560
|
-
adsManagerCpa:
|
|
22561
|
-
desiredMargin:
|
|
22690
|
+
var ProductCostingInputSchema = z83.object({
|
|
22691
|
+
country: z83.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
22692
|
+
supplierCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
22693
|
+
shippingCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
22694
|
+
returnRate: z83.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
22695
|
+
cancellationRate: z83.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
22696
|
+
adsManagerCpa: z83.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
22697
|
+
desiredMargin: z83.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
22562
22698
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
22563
22699
|
if (returnRate + cancellationRate >= 1) {
|
|
22564
22700
|
context.addIssue({
|
|
22565
|
-
code:
|
|
22701
|
+
code: z83.ZodIssueCode.custom,
|
|
22566
22702
|
message: "delivery_rate_positive",
|
|
22567
22703
|
path: [
|
|
22568
22704
|
"cancellationRate"
|
|
@@ -22659,15 +22795,15 @@ function calculateProductCosting(rawInput) {
|
|
|
22659
22795
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
22660
22796
|
|
|
22661
22797
|
// src/tools/product-costing.ts
|
|
22662
|
-
import { z as
|
|
22798
|
+
import { z as z84 } from "zod";
|
|
22663
22799
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
22664
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
22665
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
22666
|
-
var ProductCostingToolInput =
|
|
22667
|
-
country:
|
|
22800
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z84.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
22801
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z84.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
22802
|
+
var ProductCostingToolInput = z84.object({
|
|
22803
|
+
country: z84.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
22668
22804
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
22669
22805
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
22670
|
-
supplierCost:
|
|
22806
|
+
supplierCost: z84.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."),
|
|
22671
22807
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
22672
22808
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
22673
22809
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -22826,7 +22962,7 @@ function formatPercent(value) {
|
|
|
22826
22962
|
__name(formatPercent, "formatPercent");
|
|
22827
22963
|
|
|
22828
22964
|
// src/tools/product-research.ts
|
|
22829
|
-
import { z as
|
|
22965
|
+
import { z as z85 } from "zod";
|
|
22830
22966
|
|
|
22831
22967
|
// src/tools/product-research-idempotency.ts
|
|
22832
22968
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -23197,17 +23333,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
23197
23333
|
]);
|
|
23198
23334
|
var POLL_INTERVAL_MS = 5e3;
|
|
23199
23335
|
var MAX_WAIT_SECONDS = 120;
|
|
23200
|
-
var FindInput =
|
|
23336
|
+
var FindInput = z85.object({
|
|
23201
23337
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
23202
23338
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
23203
|
-
confirmed:
|
|
23204
|
-
waitSeconds:
|
|
23339
|
+
confirmed: z85.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
23340
|
+
waitSeconds: z85.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
23205
23341
|
});
|
|
23206
|
-
var GetInput =
|
|
23207
|
-
runId:
|
|
23342
|
+
var GetInput = z85.object({
|
|
23343
|
+
runId: z85.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
23208
23344
|
});
|
|
23209
|
-
var ListInput =
|
|
23210
|
-
limit:
|
|
23345
|
+
var ListInput = z85.object({
|
|
23346
|
+
limit: z85.number().int().min(1).max(20).default(10)
|
|
23211
23347
|
});
|
|
23212
23348
|
function textResult(text) {
|
|
23213
23349
|
return {
|
|
@@ -23244,7 +23380,7 @@ async function pollUntilTerminal(api, runId, waitSeconds) {
|
|
|
23244
23380
|
}
|
|
23245
23381
|
__name(pollUntilTerminal, "pollUntilTerminal");
|
|
23246
23382
|
function registerProductResearchTools(server, api) {
|
|
23247
|
-
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,
|
|
23383
|
+
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) => {
|
|
23248
23384
|
const parsed = FindInput.parse(input);
|
|
23249
23385
|
if (!parsed.confirmed) {
|
|
23250
23386
|
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.`);
|
|
@@ -23299,7 +23435,7 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
23299
23435
|
throw translateError(error);
|
|
23300
23436
|
}
|
|
23301
23437
|
});
|
|
23302
|
-
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,
|
|
23438
|
+
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) => {
|
|
23303
23439
|
const parsed = WinnerReferenceInput.parse(input);
|
|
23304
23440
|
try {
|
|
23305
23441
|
const prepared = WinningProductPreparedImageSchema.parse(await api.postJson(`/v1/product-research/runs/${encodeURIComponent(parsed.runId)}/candidates/${encodeURIComponent(parsed.candidateSourceId)}/image-asset`, {}));
|
|
@@ -23330,17 +23466,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
23330
23466
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
23331
23467
|
|
|
23332
23468
|
// src/tools/dropshipping-projects.ts
|
|
23333
|
-
import { z as
|
|
23469
|
+
import { z as z86 } from "zod";
|
|
23334
23470
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
23335
23471
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
23336
23472
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
23337
|
-
var ProjectId =
|
|
23338
|
-
var DropshippingProjectStatus =
|
|
23473
|
+
var ProjectId = z86.string().uuid();
|
|
23474
|
+
var DropshippingProjectStatus = z86.enum([
|
|
23339
23475
|
"active",
|
|
23340
23476
|
"completed",
|
|
23341
23477
|
"archived"
|
|
23342
23478
|
]);
|
|
23343
|
-
var DropshippingProjectPhase =
|
|
23479
|
+
var DropshippingProjectPhase = z86.enum([
|
|
23344
23480
|
"research",
|
|
23345
23481
|
"costing",
|
|
23346
23482
|
"media",
|
|
@@ -23349,21 +23485,21 @@ var DropshippingProjectPhase = z85.enum([
|
|
|
23349
23485
|
"advertising",
|
|
23350
23486
|
"complete"
|
|
23351
23487
|
]);
|
|
23352
|
-
var DropshippingRewardMilestone =
|
|
23488
|
+
var DropshippingRewardMilestone = z86.enum([
|
|
23353
23489
|
"product_selected",
|
|
23354
23490
|
"costing_saved",
|
|
23355
23491
|
"product_media_ready",
|
|
23356
23492
|
"creatives_completed",
|
|
23357
23493
|
"campaign_created"
|
|
23358
23494
|
]);
|
|
23359
|
-
var TargetCountry =
|
|
23495
|
+
var TargetCountry = z86.enum([
|
|
23360
23496
|
"CO",
|
|
23361
23497
|
"MX",
|
|
23362
23498
|
"PE",
|
|
23363
23499
|
"EC",
|
|
23364
23500
|
"CL"
|
|
23365
23501
|
]);
|
|
23366
|
-
var ResearchCategory =
|
|
23502
|
+
var ResearchCategory = z86.enum([
|
|
23367
23503
|
"auto",
|
|
23368
23504
|
"automotive",
|
|
23369
23505
|
"kitchen",
|
|
@@ -23378,7 +23514,7 @@ var ResearchCategory = z85.enum([
|
|
|
23378
23514
|
"garden",
|
|
23379
23515
|
"cleaning"
|
|
23380
23516
|
]);
|
|
23381
|
-
var HttpUrl3 =
|
|
23517
|
+
var HttpUrl3 = z86.string().url().max(2e3).refine((value) => {
|
|
23382
23518
|
try {
|
|
23383
23519
|
return [
|
|
23384
23520
|
"http:",
|
|
@@ -23388,45 +23524,45 @@ var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
|
|
|
23388
23524
|
return false;
|
|
23389
23525
|
}
|
|
23390
23526
|
}, "URL must use HTTP(S)");
|
|
23391
|
-
var ResearchCandidateOrigin =
|
|
23392
|
-
type:
|
|
23527
|
+
var ResearchCandidateOrigin = z86.object({
|
|
23528
|
+
type: z86.literal("research_candidate"),
|
|
23393
23529
|
runId: ProjectId,
|
|
23394
|
-
candidateSourceId:
|
|
23530
|
+
candidateSourceId: z86.string().min(1).max(160)
|
|
23395
23531
|
});
|
|
23396
|
-
var TaskOrigin =
|
|
23397
|
-
type:
|
|
23532
|
+
var TaskOrigin = z86.object({
|
|
23533
|
+
type: z86.literal("task"),
|
|
23398
23534
|
taskId: ProjectId
|
|
23399
23535
|
});
|
|
23400
|
-
var ManualOrigin =
|
|
23401
|
-
type:
|
|
23536
|
+
var ManualOrigin = z86.object({
|
|
23537
|
+
type: z86.literal("manual"),
|
|
23402
23538
|
clientRequestId: ProjectId,
|
|
23403
|
-
country:
|
|
23539
|
+
country: z86.string().min(2).max(3).optional()
|
|
23404
23540
|
});
|
|
23405
|
-
var StartProjectInput =
|
|
23406
|
-
origin:
|
|
23541
|
+
var StartProjectInput = z86.object({
|
|
23542
|
+
origin: z86.discriminatedUnion("type", [
|
|
23407
23543
|
ResearchCandidateOrigin,
|
|
23408
23544
|
TaskOrigin,
|
|
23409
23545
|
ManualOrigin
|
|
23410
23546
|
]),
|
|
23411
|
-
productName:
|
|
23547
|
+
productName: z86.string().trim().min(1).max(240).optional(),
|
|
23412
23548
|
productUrl: HttpUrl3.optional(),
|
|
23413
|
-
country:
|
|
23414
|
-
languageCode:
|
|
23549
|
+
country: z86.string().min(2).max(3).optional(),
|
|
23550
|
+
languageCode: z86.string().min(2).max(16).optional()
|
|
23415
23551
|
}).strict();
|
|
23416
|
-
var CostProjectInput =
|
|
23552
|
+
var CostProjectInput = z86.object({
|
|
23417
23553
|
projectId: ProjectId,
|
|
23418
|
-
version:
|
|
23419
|
-
country:
|
|
23554
|
+
version: z86.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
23555
|
+
country: z86.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
23420
23556
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
23421
23557
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
23422
|
-
supplierCost:
|
|
23423
|
-
shippingCost:
|
|
23424
|
-
returnRate:
|
|
23425
|
-
cancellationRate:
|
|
23426
|
-
adsManagerCpa:
|
|
23427
|
-
desiredMargin:
|
|
23428
|
-
});
|
|
23429
|
-
var GuideInput =
|
|
23558
|
+
supplierCost: z86.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."),
|
|
23559
|
+
shippingCost: z86.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
23560
|
+
returnRate: z86.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."),
|
|
23561
|
+
cancellationRate: z86.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."),
|
|
23562
|
+
adsManagerCpa: z86.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
23563
|
+
desiredMargin: z86.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
23564
|
+
});
|
|
23565
|
+
var GuideInput = z86.object({
|
|
23430
23566
|
projectId: ProjectId.optional()
|
|
23431
23567
|
}).strict();
|
|
23432
23568
|
var NEXT_ACTION_KINDS = [
|
|
@@ -23444,29 +23580,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
23444
23580
|
"repair_meta_campaign",
|
|
23445
23581
|
"review_paused_campaign"
|
|
23446
23582
|
];
|
|
23447
|
-
var DropshippingProjectNextAction =
|
|
23448
|
-
kind:
|
|
23449
|
-
href:
|
|
23583
|
+
var DropshippingProjectNextAction = z86.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z86.object({
|
|
23584
|
+
kind: z86.literal(kind),
|
|
23585
|
+
href: z86.string().min(1)
|
|
23450
23586
|
})));
|
|
23451
|
-
var CostingInputSchema =
|
|
23452
|
-
country:
|
|
23453
|
-
supplierCost:
|
|
23454
|
-
shippingCost:
|
|
23455
|
-
returnRate:
|
|
23456
|
-
cancellationRate:
|
|
23457
|
-
adsManagerCpa:
|
|
23458
|
-
desiredMargin:
|
|
23587
|
+
var CostingInputSchema = z86.object({
|
|
23588
|
+
country: z86.string().min(2).max(3),
|
|
23589
|
+
supplierCost: z86.number().finite().positive(),
|
|
23590
|
+
shippingCost: z86.number().finite().nonnegative(),
|
|
23591
|
+
returnRate: z86.number().finite().min(0).lt(1),
|
|
23592
|
+
cancellationRate: z86.number().finite().min(0).lt(1),
|
|
23593
|
+
adsManagerCpa: z86.number().finite().nonnegative(),
|
|
23594
|
+
desiredMargin: z86.number().finite().min(0).lt(1)
|
|
23459
23595
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
23460
23596
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
23461
|
-
code:
|
|
23597
|
+
code: z86.ZodIssueCode.custom,
|
|
23462
23598
|
path: [
|
|
23463
23599
|
"cancellationRate"
|
|
23464
23600
|
]
|
|
23465
23601
|
});
|
|
23466
23602
|
});
|
|
23467
|
-
var FiniteCostingNumber =
|
|
23468
|
-
var CostingResultSchema =
|
|
23469
|
-
country:
|
|
23603
|
+
var FiniteCostingNumber = z86.number().finite();
|
|
23604
|
+
var CostingResultSchema = z86.object({
|
|
23605
|
+
country: z86.string().min(2).max(3),
|
|
23470
23606
|
deliveryRate: FiniteCostingNumber,
|
|
23471
23607
|
adjustedShippingCost: FiniteCostingNumber,
|
|
23472
23608
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -23479,45 +23615,45 @@ var CostingResultSchema = z85.object({
|
|
|
23479
23615
|
estimatedProfit: FiniteCostingNumber,
|
|
23480
23616
|
actualMargin: FiniteCostingNumber,
|
|
23481
23617
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
23482
|
-
wasPriceAutoAdjusted:
|
|
23483
|
-
profitabilityStatus:
|
|
23484
|
-
});
|
|
23485
|
-
var RewardProgressSchema =
|
|
23486
|
-
campaignKey:
|
|
23487
|
-
totalCredits:
|
|
23488
|
-
earnedCredits:
|
|
23489
|
-
milestones:
|
|
23618
|
+
wasPriceAutoAdjusted: z86.boolean(),
|
|
23619
|
+
profitabilityStatus: z86.literal("healthy")
|
|
23620
|
+
});
|
|
23621
|
+
var RewardProgressSchema = z86.object({
|
|
23622
|
+
campaignKey: z86.literal("dropshipping-launch-v1"),
|
|
23623
|
+
totalCredits: z86.number().int().positive(),
|
|
23624
|
+
earnedCredits: z86.number().int().nonnegative(),
|
|
23625
|
+
milestones: z86.array(z86.object({
|
|
23490
23626
|
milestone: DropshippingRewardMilestone,
|
|
23491
|
-
credits:
|
|
23492
|
-
available:
|
|
23493
|
-
earned:
|
|
23627
|
+
credits: z86.number().int().positive(),
|
|
23628
|
+
available: z86.boolean().optional(),
|
|
23629
|
+
earned: z86.boolean(),
|
|
23494
23630
|
grantId: ProjectId.nullable(),
|
|
23495
|
-
grantedAt:
|
|
23631
|
+
grantedAt: z86.string().datetime().nullable()
|
|
23496
23632
|
})).length(DropshippingRewardMilestone.options.length)
|
|
23497
23633
|
});
|
|
23498
|
-
var ProjectResponseSchema =
|
|
23634
|
+
var ProjectResponseSchema = z86.object({
|
|
23499
23635
|
id: ProjectId,
|
|
23500
23636
|
taskId: ProjectId.nullable(),
|
|
23501
23637
|
status: DropshippingProjectStatus,
|
|
23502
|
-
originKey:
|
|
23638
|
+
originKey: z86.string().min(1),
|
|
23503
23639
|
researchRunId: ProjectId.nullable(),
|
|
23504
|
-
candidateSourceId:
|
|
23505
|
-
productName:
|
|
23640
|
+
candidateSourceId: z86.string().nullable(),
|
|
23641
|
+
productName: z86.string().nullable(),
|
|
23506
23642
|
productUrl: HttpUrl3.nullable(),
|
|
23507
23643
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
23508
|
-
targetCountry:
|
|
23509
|
-
languageCode:
|
|
23510
|
-
hasReferenceImage:
|
|
23511
|
-
hasWinnerReferenceImage:
|
|
23644
|
+
targetCountry: z86.string().nullable(),
|
|
23645
|
+
languageCode: z86.string().nullable(),
|
|
23646
|
+
hasReferenceImage: z86.boolean(),
|
|
23647
|
+
hasWinnerReferenceImage: z86.boolean(),
|
|
23512
23648
|
costingInput: CostingInputSchema.nullable(),
|
|
23513
23649
|
costingResult: CostingResultSchema.nullable(),
|
|
23514
|
-
costingVersion:
|
|
23515
|
-
version:
|
|
23650
|
+
costingVersion: z86.number().int().positive().nullable(),
|
|
23651
|
+
version: z86.number().int().positive(),
|
|
23516
23652
|
phase: DropshippingProjectPhase,
|
|
23517
23653
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
23518
23654
|
rewards: RewardProgressSchema,
|
|
23519
|
-
createdAt:
|
|
23520
|
-
updatedAt:
|
|
23655
|
+
createdAt: z86.string().datetime(),
|
|
23656
|
+
updatedAt: z86.string().datetime()
|
|
23521
23657
|
}).passthrough();
|
|
23522
23658
|
var NEXT_ACTION_GUIDANCE = {
|
|
23523
23659
|
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.",
|
|
@@ -23635,58 +23771,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
23635
23771
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
23636
23772
|
|
|
23637
23773
|
// src/tools/daily-control.ts
|
|
23638
|
-
import { z as
|
|
23774
|
+
import { z as z87 } from "zod";
|
|
23639
23775
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
23640
23776
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
23641
23777
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
23642
|
-
var ProviderCampaignIdentifier =
|
|
23643
|
-
var DateOnly =
|
|
23644
|
-
var DailyControlInput =
|
|
23778
|
+
var ProviderCampaignIdentifier = z87.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
23779
|
+
var DateOnly = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
23780
|
+
var DailyControlInput = z87.object({
|
|
23645
23781
|
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."),
|
|
23646
|
-
days:
|
|
23647
|
-
projectId:
|
|
23782
|
+
days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
23783
|
+
projectId: z87.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
23648
23784
|
}).strict();
|
|
23649
|
-
var LinkCampaignInput =
|
|
23650
|
-
projectId:
|
|
23651
|
-
provider:
|
|
23785
|
+
var LinkCampaignInput = z87.object({
|
|
23786
|
+
projectId: z87.string().uuid(),
|
|
23787
|
+
provider: z87.enum([
|
|
23652
23788
|
"meta",
|
|
23653
23789
|
"tiktok"
|
|
23654
23790
|
]),
|
|
23655
23791
|
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."),
|
|
23656
23792
|
campaignId: ProviderCampaignIdentifier
|
|
23657
23793
|
}).strict();
|
|
23658
|
-
var ReportReturnsInput =
|
|
23659
|
-
projectId:
|
|
23794
|
+
var ReportReturnsInput = z87.object({
|
|
23795
|
+
projectId: z87.string().uuid(),
|
|
23660
23796
|
date: DateOnly,
|
|
23661
|
-
returnedOrders:
|
|
23662
|
-
note:
|
|
23797
|
+
returnedOrders: z87.number().int().min(0).max(1e5),
|
|
23798
|
+
note: z87.string().trim().max(280).optional()
|
|
23663
23799
|
}).strict();
|
|
23664
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
23665
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
23666
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
23667
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
23668
|
-
var DailyControlDayMirror =
|
|
23669
|
-
date:
|
|
23670
|
-
returnedOrders:
|
|
23800
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z87.string());
|
|
23801
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z87.string());
|
|
23802
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z87.string());
|
|
23803
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z87.string());
|
|
23804
|
+
var DailyControlDayMirror = z87.object({
|
|
23805
|
+
date: z87.string(),
|
|
23806
|
+
returnedOrders: z87.number(),
|
|
23671
23807
|
returnedSource: DailyControlSourceMirror,
|
|
23672
23808
|
cancelledSource: DailyControlSourceMirror,
|
|
23673
|
-
hasEstimates:
|
|
23809
|
+
hasEstimates: z87.boolean(),
|
|
23674
23810
|
light: DailyControlLightMirror
|
|
23675
23811
|
}).passthrough();
|
|
23676
|
-
var DailyControlProductMirror =
|
|
23677
|
-
projectId:
|
|
23678
|
-
productName:
|
|
23812
|
+
var DailyControlProductMirror = z87.object({
|
|
23813
|
+
projectId: z87.string().uuid(),
|
|
23814
|
+
productName: z87.string().nullable(),
|
|
23679
23815
|
status: DailyControlStatusMirror,
|
|
23680
|
-
statusMessage:
|
|
23681
|
-
days:
|
|
23816
|
+
statusMessage: z87.string().nullable(),
|
|
23817
|
+
days: z87.array(DailyControlDayMirror),
|
|
23682
23818
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
23683
|
-
rationale:
|
|
23819
|
+
rationale: z87.string().nullable()
|
|
23684
23820
|
}).passthrough();
|
|
23685
|
-
var DailyControlResponseMirror =
|
|
23686
|
-
since:
|
|
23687
|
-
until:
|
|
23688
|
-
products:
|
|
23689
|
-
archivedProjectSpend:
|
|
23821
|
+
var DailyControlResponseMirror = z87.object({
|
|
23822
|
+
since: z87.string(),
|
|
23823
|
+
until: z87.string(),
|
|
23824
|
+
products: z87.array(DailyControlProductMirror),
|
|
23825
|
+
archivedProjectSpend: z87.array(z87.unknown())
|
|
23690
23826
|
}).passthrough();
|
|
23691
23827
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
23692
23828
|
function withWarnings(response) {
|
|
@@ -23770,42 +23906,42 @@ function registerDailyControlTools(server, api) {
|
|
|
23770
23906
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
23771
23907
|
|
|
23772
23908
|
// src/tools/product-control.ts
|
|
23773
|
-
import { z as
|
|
23909
|
+
import { z as z88 } from "zod";
|
|
23774
23910
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
23775
23911
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
23776
23912
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
23777
23913
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
23778
23914
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
23779
|
-
var DateOnly2 =
|
|
23915
|
+
var DateOnly2 = z88.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
23780
23916
|
var IMPORT_BATCH_MAX2 = 50;
|
|
23781
|
-
var ProductControlListInput =
|
|
23782
|
-
days:
|
|
23917
|
+
var ProductControlListInput = z88.object({
|
|
23918
|
+
days: z88.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
23783
23919
|
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."),
|
|
23784
|
-
shopDomain:
|
|
23920
|
+
shopDomain: z88.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
23785
23921
|
}).strict();
|
|
23786
|
-
var ImportableProductsInput =
|
|
23787
|
-
q:
|
|
23788
|
-
after:
|
|
23789
|
-
shopDomain:
|
|
23922
|
+
var ImportableProductsInput = z88.object({
|
|
23923
|
+
q: z88.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
23924
|
+
after: z88.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
23925
|
+
shopDomain: z88.string().min(1).optional()
|
|
23790
23926
|
}).strict();
|
|
23791
|
-
var ImportProductControlsInput =
|
|
23792
|
-
shopifyProductIds:
|
|
23927
|
+
var ImportProductControlsInput = z88.object({
|
|
23928
|
+
shopifyProductIds: z88.array(z88.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."),
|
|
23793
23929
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
23794
23930
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
23795
|
-
shopDomain:
|
|
23931
|
+
shopDomain: z88.string().min(1)
|
|
23796
23932
|
}).strict();
|
|
23797
|
-
var SetProductCostingInput =
|
|
23798
|
-
shopDomain:
|
|
23799
|
-
shopifyProductId:
|
|
23800
|
-
targetCountry:
|
|
23801
|
-
supplierCost:
|
|
23802
|
-
shippingCost:
|
|
23803
|
-
returnRate:
|
|
23804
|
-
cancellationRate:
|
|
23933
|
+
var SetProductCostingInput = z88.object({
|
|
23934
|
+
shopDomain: z88.string().min(1),
|
|
23935
|
+
shopifyProductId: z88.string().min(1).max(64),
|
|
23936
|
+
targetCountry: z88.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
23937
|
+
supplierCost: z88.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
23938
|
+
shippingCost: z88.number().finite().nonnegative(),
|
|
23939
|
+
returnRate: z88.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
23940
|
+
cancellationRate: z88.number().finite().min(0).lt(1)
|
|
23805
23941
|
}).strict();
|
|
23806
|
-
var Count =
|
|
23807
|
-
var ReportProductCountsInput =
|
|
23808
|
-
productControlId:
|
|
23942
|
+
var Count = z88.number().int().min(0).max(1e5).nullable().optional();
|
|
23943
|
+
var ReportProductCountsInput = z88.object({
|
|
23944
|
+
productControlId: z88.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
23809
23945
|
date: DateOnly2,
|
|
23810
23946
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
23811
23947
|
cancelledOrders: Count,
|