@productmaker/mcp 7.1.0 → 7.3.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/dist/http.js +864 -684
- package/dist/stdio.js +853 -673
- package/package.json +1 -1
package/dist/stdio.js
CHANGED
|
@@ -1497,9 +1497,23 @@ var LandingSectionPlanSchema = z11.array(LandingSectionPlanEntrySchema).superRef
|
|
|
1497
1497
|
|
|
1498
1498
|
// ../../packages/types/src/landing.ts
|
|
1499
1499
|
var LandingImageReadable = z12.object({
|
|
1500
|
+
/**
|
|
1501
|
+
* Display position in the AGGREGATED gallery (parent images + every `done`
|
|
1502
|
+
* variant's images, concatenated). Recalculated on every read from
|
|
1503
|
+
* `creativeVariants` order (createdAt asc), so it DRIFTS for a given image
|
|
1504
|
+
* when a sibling variant finishes out of creation order — it is NOT a
|
|
1505
|
+
* stable identity. Use `sourceIndex` for that.
|
|
1506
|
+
*/
|
|
1500
1507
|
index: z12.number().int().min(1).max(20),
|
|
1501
1508
|
/** Child task that owns this image when variants are rendered alongside the root task. */
|
|
1502
1509
|
variantTaskId: z12.string().uuid().optional(),
|
|
1510
|
+
/**
|
|
1511
|
+
* The image's own `indexNum` within its OWN task (root or variant) — set
|
|
1512
|
+
* once at render time and never recomputed. Unlike `index`, this is stable
|
|
1513
|
+
* across reads and is the correct key for identity/selection tracking.
|
|
1514
|
+
* Optional only for legacy rows persisted before this field existed.
|
|
1515
|
+
*/
|
|
1516
|
+
sourceIndex: z12.number().int().min(1).optional(),
|
|
1503
1517
|
role: LandingRoleLegacy,
|
|
1504
1518
|
/** Strategy-specific display identity; absent on legacy tasks. */
|
|
1505
1519
|
sectionKey: LandingSectionKeySchema.optional(),
|
|
@@ -3617,11 +3631,12 @@ var FreeformLandingConfigSchema = z21.object({
|
|
|
3617
3631
|
showVariantPicker: z21.boolean().optional(),
|
|
3618
3632
|
/**
|
|
3619
3633
|
* Suppress the native Shopify buy form (the `BUY_FORM_MARKER` block). The page
|
|
3620
|
-
* CTAs already carry `data-cl-buy-trigger` → they open the
|
|
3621
|
-
* so on
|
|
3622
|
-
*
|
|
3623
|
-
*
|
|
3624
|
-
* (backward compatible with
|
|
3634
|
+
* CTAs already carry `data-cl-buy-trigger` → they open the installed COD
|
|
3635
|
+
* provider's popup (Releasit or EasySell), so on COD-provider stores the
|
|
3636
|
+
* native add-to-cart form is a redundant second buy path (it rendered as a
|
|
3637
|
+
* bare "price + Comprar" block). When true the assembler omits the marker
|
|
3638
|
+
* entirely. Undefined/false = keep the native form (backward compatible with
|
|
3639
|
+
* already-assembled configs).
|
|
3625
3640
|
*/
|
|
3626
3641
|
hideNativeBuyForm: z21.boolean().optional()
|
|
3627
3642
|
});
|
|
@@ -5124,6 +5139,7 @@ var SelectedLandingImage = z28.object({
|
|
|
5124
5139
|
/** 0-based index of the selected variant (from img.notes JSON array) */
|
|
5125
5140
|
variantIndex: z28.number().int().nonnegative()
|
|
5126
5141
|
});
|
|
5142
|
+
var SHOPIFY_MAX_LANDING_IMAGES = 20;
|
|
5127
5143
|
var ShopifyPublicationMode = z28.enum([
|
|
5128
5144
|
"auto",
|
|
5129
5145
|
"existing",
|
|
@@ -5138,9 +5154,9 @@ var ShopifyPublishRequest = z28.object({
|
|
|
5138
5154
|
* Landing images to include in the Shopify page with their selected variants.
|
|
5139
5155
|
* Required (≥1) for CLASSIC image landings — the classic publish branch enforces
|
|
5140
5156
|
* that itself. CODE landings have no images and send an empty array, so the schema
|
|
5141
|
-
* allows empty;
|
|
5157
|
+
* allows empty; at most SHOPIFY_MAX_LANDING_IMAGES.
|
|
5142
5158
|
*/
|
|
5143
|
-
selectedLandingImages: z28.array(SelectedLandingImage).max(
|
|
5159
|
+
selectedLandingImages: z28.array(SelectedLandingImage).max(SHOPIFY_MAX_LANDING_IMAGES).default([]),
|
|
5144
5160
|
/** Show variant picker pills in the landing when the product has multiple variants. */
|
|
5145
5161
|
showVariantPicker: z28.boolean().optional(),
|
|
5146
5162
|
/**
|
|
@@ -5326,7 +5342,13 @@ var ShopifyPublishErrorResponse = z28.discriminatedUnion("code", [
|
|
|
5326
5342
|
"SHOPIFY_PUBLISH_FAILED",
|
|
5327
5343
|
"SHOPIFY_NO_PUBLISHED_THEME",
|
|
5328
5344
|
"SHOPIFY_THEME_STRUCTURE_UNSUPPORTED",
|
|
5329
|
-
"SHOPIFY_PUBLISH_CONTEXT_CHANGED"
|
|
5345
|
+
"SHOPIFY_PUBLISH_CONTEXT_CHANGED",
|
|
5346
|
+
/**
|
|
5347
|
+
* A publish failure we understand (Shopify did not keep the offer's
|
|
5348
|
+
* variants, another app rewrote the product, landing too large).
|
|
5349
|
+
* `message` carries the seller's next step; never a 500.
|
|
5350
|
+
*/
|
|
5351
|
+
"SHOPIFY_PUBLISH_VERIFICATION_FAILED"
|
|
5330
5352
|
]),
|
|
5331
5353
|
message: z28.string().optional(),
|
|
5332
5354
|
authUrl: z28.string().url().optional(),
|
|
@@ -5336,13 +5358,31 @@ var ShopifyPublishErrorResponse = z28.discriminatedUnion("code", [
|
|
|
5336
5358
|
z28.object({
|
|
5337
5359
|
code: z28.literal("SHOPIFY_PUBLISH_INPUT_REQUIRED"),
|
|
5338
5360
|
message: z28.string().optional(),
|
|
5339
|
-
recovery: PublishPreparationSchema.options[1]
|
|
5361
|
+
recovery: PublishPreparationSchema.options[1],
|
|
5362
|
+
/**
|
|
5363
|
+
* Present when this answers a confirmed correction: the seller already
|
|
5364
|
+
* submitted the form and these issue codes are WHY it was refused. Every
|
|
5365
|
+
* surface must say so instead of re-opening the same form mute (C1).
|
|
5366
|
+
*/
|
|
5367
|
+
correctionRejected: z28.literal(true).optional(),
|
|
5368
|
+
rejectedIssueCodes: z28.array(PublishRecoveryCodeSchema).max(6).optional()
|
|
5340
5369
|
}),
|
|
5341
5370
|
z28.object({
|
|
5342
5371
|
code: z28.literal("SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR"),
|
|
5343
5372
|
action: z28.literal("open_editor"),
|
|
5344
5373
|
message: z28.string().optional()
|
|
5345
5374
|
}),
|
|
5375
|
+
z28.object({
|
|
5376
|
+
/**
|
|
5377
|
+
* The seller confirmed exactly what we suggested and the offer still
|
|
5378
|
+
* cannot publish: another pass of the recovery form cannot converge, so
|
|
5379
|
+
* the only exit is the landing editor. `message` names the reason.
|
|
5380
|
+
*/
|
|
5381
|
+
code: z28.literal("SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED"),
|
|
5382
|
+
action: z28.literal("open_editor"),
|
|
5383
|
+
message: z28.string().optional(),
|
|
5384
|
+
commerceCorrectionSaved: z28.literal(true).optional()
|
|
5385
|
+
}),
|
|
5346
5386
|
z28.object({
|
|
5347
5387
|
/**
|
|
5348
5388
|
* The chosen existing product cannot express the confirmed offer's
|
|
@@ -5384,6 +5424,17 @@ var CodeLandingThemeSetupResponse = z28.discriminatedUnion("status", [
|
|
|
5384
5424
|
themeEditorDeepLink: z28.string().url(),
|
|
5385
5425
|
shopDomain: z28.string()
|
|
5386
5426
|
}),
|
|
5427
|
+
z28.object({
|
|
5428
|
+
/**
|
|
5429
|
+
* The block is missing and the store has NO products yet. Shopify's theme
|
|
5430
|
+
* editor cannot add an app block to a product template with nothing to
|
|
5431
|
+
* preview (it answers "there is a problem with the app block"), so there
|
|
5432
|
+
* is deliberately no deep link: the seller publishes first, and the
|
|
5433
|
+
* publish response carries the link aimed at the product it created.
|
|
5434
|
+
*/
|
|
5435
|
+
status: z28.literal("setup_after_publish"),
|
|
5436
|
+
shopDomain: z28.string()
|
|
5437
|
+
}),
|
|
5387
5438
|
z28.object({
|
|
5388
5439
|
/** Not a code-landing task — the gate does not apply. */
|
|
5389
5440
|
status: z28.literal("not_applicable"),
|
|
@@ -6886,7 +6937,10 @@ var ChatParseEstimationOptions = z34.object({}).strict();
|
|
|
6886
6937
|
var CodeLandingEditEstimationOptions = z34.object({}).strict();
|
|
6887
6938
|
var ServiceCreativeEstimationOptions = z34.object({
|
|
6888
6939
|
mediaAssetCount: z34.number().int().min(0).max(8).optional(),
|
|
6889
|
-
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional()
|
|
6940
|
+
uploadedVideoDurationSeconds: z34.number().min(0).max(240).optional(),
|
|
6941
|
+
/** Quality the panels render at (its registry model sets the per-second
|
|
6942
|
+
* price). Absent = economy, the pre-quality service default. */
|
|
6943
|
+
videoQuality: VideoQuality.optional()
|
|
6890
6944
|
});
|
|
6891
6945
|
var ActorGridEstimationOptions = z34.object({}).strict();
|
|
6892
6946
|
var CostEstimationRequest = z34.discriminatedUnion("type", [
|
|
@@ -7251,7 +7305,13 @@ var ImageQaGateEntry = z36.object({
|
|
|
7251
7305
|
"passed",
|
|
7252
7306
|
"failed",
|
|
7253
7307
|
"unavailable"
|
|
7254
|
-
]).optional()
|
|
7308
|
+
]).optional(),
|
|
7309
|
+
// Paid edit QA telemetry (plan t2-j9): whether the edit could be checked at all,
|
|
7310
|
+
// whether a previous image was actually available to compare against, and the
|
|
7311
|
+
// measured pixel-delta between the two images.
|
|
7312
|
+
requestedEditVerifiable: z36.boolean().optional(),
|
|
7313
|
+
previousImageUsed: z36.boolean().optional(),
|
|
7314
|
+
editPixelDelta: z36.number().min(0).max(1).optional()
|
|
7255
7315
|
}).passthrough();
|
|
7256
7316
|
var ImageQaAssessmentState = z36.enum([
|
|
7257
7317
|
"approved",
|
|
@@ -7650,7 +7710,18 @@ var KIE_SUBMIT_IMAGE_TASK_TARGETS = [
|
|
|
7650
7710
|
"rapid_master_anchor",
|
|
7651
7711
|
"clean_product_image",
|
|
7652
7712
|
"single_call_anchor",
|
|
7653
|
-
"product_view_reference"
|
|
7713
|
+
"product_view_reference",
|
|
7714
|
+
// Generated service-video presenter (text-to-image portrait). Task-owned, so
|
|
7715
|
+
// it lives here and not beside `actor_candidate`; it mirrors that target's
|
|
7716
|
+
// model, resolution and recovery policy. The fan-in resumes the service init
|
|
7717
|
+
// (`dispatchServiceActor`, refKey prefix `service_actor:`).
|
|
7718
|
+
"service_actor",
|
|
7719
|
+
// First frame of a generated service B-roll panel: image-to-image from the
|
|
7720
|
+
// service photo the planner cited, cleaned of overlaid text/graphics and
|
|
7721
|
+
// fitted to the shot. Mirrors `rapid_panel`'s model tier and recovery
|
|
7722
|
+
// policy. The same fan-in waits for the whole expected image set
|
|
7723
|
+
// (`dispatchServiceActor`, refKey prefix `service_broll_anchor:`).
|
|
7724
|
+
"service_broll_anchor"
|
|
7654
7725
|
];
|
|
7655
7726
|
var ACTOR_CANDIDATE_TARGET = "actor_candidate";
|
|
7656
7727
|
var ANY_KIE_SUBMIT_IMAGE_TARGETS = [
|
|
@@ -9572,6 +9643,12 @@ var DEFAULT_PRICING = {
|
|
|
9572
9643
|
ourCostCents: 0.01,
|
|
9573
9644
|
userPriceCents: 0.02
|
|
9574
9645
|
},
|
|
9646
|
+
// Service reels harvested from the business's own public profile (per second,
|
|
9647
|
+
// same Whisper-1 rate). Separate action so the ledger names the source.
|
|
9648
|
+
"openai:service-social-transcribe": {
|
|
9649
|
+
ourCostCents: 0.01,
|
|
9650
|
+
userPriceCents: 0.02
|
|
9651
|
+
},
|
|
9575
9652
|
// User-uploaded service reference/competitor analysis (per second, same Whisper-1 rate).
|
|
9576
9653
|
// This is a separate action because its ledger entries identify the analysis source.
|
|
9577
9654
|
"openai:service-reference-transcribe": {
|
|
@@ -10711,6 +10788,11 @@ var DECLARATION = DELIVERY_FAMILIES.map((family) => [
|
|
|
10711
10788
|
])
|
|
10712
10789
|
]);
|
|
10713
10790
|
|
|
10791
|
+
// ../../packages/types/src/seller-prohibitions.ts
|
|
10792
|
+
var MARKER = String.raw`(?:no|nunca|jam[aá]s|prohibido|evita[r]?)(?:\s*:)?\s`;
|
|
10793
|
+
var PROHIBITION_AT_START = new RegExp(String.raw`^(?:[-•*]\s*)?(${MARKER}[\s\S]*)$`, "iu");
|
|
10794
|
+
var PROHIBITION_AFTER_LABEL = new RegExp(String.raw`^(?:[-•*]\s*)?[^:.!?\n]{1,40}:\s*(${MARKER}[\s\S]*)$`, "iu");
|
|
10795
|
+
|
|
10714
10796
|
// ../../packages/types/src/task-type.ts
|
|
10715
10797
|
import { z as z50 } from "zod";
|
|
10716
10798
|
var TaskTypeSchema = z50.enum([
|
|
@@ -13292,7 +13374,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13292
13374
|
"task",
|
|
13293
13375
|
"product"
|
|
13294
13376
|
]),
|
|
13295
|
-
defineCapability("create_service_video", "
|
|
13377
|
+
defineCapability("create_service_video", "863884c1af5de3e168cbbe825ea3961901c84dae1899ca400f8f7fa01df91c0a", "credit_consuming", "creative", [
|
|
13296
13378
|
"credit_consuming",
|
|
13297
13379
|
"state_change"
|
|
13298
13380
|
], [
|
|
@@ -13316,7 +13398,11 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13316
13398
|
]),
|
|
13317
13399
|
slot("video_preset", false, [
|
|
13318
13400
|
"videoPreset"
|
|
13319
|
-
])
|
|
13401
|
+
]),
|
|
13402
|
+
// MCP-only for now: WhatsApp's service flow keeps the economy default.
|
|
13403
|
+
slot("video_quality", false, [
|
|
13404
|
+
"videoQuality"
|
|
13405
|
+
], [])
|
|
13320
13406
|
], [
|
|
13321
13407
|
"service_context"
|
|
13322
13408
|
], [
|
|
@@ -14855,6 +14941,81 @@ var WhatsAppPresentationManifestSchema = z67.object({
|
|
|
14855
14941
|
}
|
|
14856
14942
|
});
|
|
14857
14943
|
|
|
14944
|
+
// ../../packages/types/src/flight-recorder.ts
|
|
14945
|
+
import { z as z68 } from "zod";
|
|
14946
|
+
var FlightRecorderGenerationTypeSchema = z68.enum([
|
|
14947
|
+
"initial",
|
|
14948
|
+
"regeneration",
|
|
14949
|
+
"edit",
|
|
14950
|
+
"retry"
|
|
14951
|
+
]);
|
|
14952
|
+
var FlightRecorderProviderSchema = z68.enum([
|
|
14953
|
+
"kie",
|
|
14954
|
+
"fal"
|
|
14955
|
+
]);
|
|
14956
|
+
var FlightRecorderElementSchema = z68.object({
|
|
14957
|
+
name: z68.string().optional(),
|
|
14958
|
+
description: z68.string().optional(),
|
|
14959
|
+
frontalImageUrl: z68.string().optional(),
|
|
14960
|
+
referenceImageUrls: z68.array(z68.string()).optional(),
|
|
14961
|
+
videoUrl: z68.string().optional()
|
|
14962
|
+
});
|
|
14963
|
+
var FlightRecorderDistillationSchema = z68.object({
|
|
14964
|
+
actorGender: z68.enum([
|
|
14965
|
+
"female",
|
|
14966
|
+
"male",
|
|
14967
|
+
"mixed"
|
|
14968
|
+
]).or(z68.string()).optional(),
|
|
14969
|
+
voiceId: z68.string().optional(),
|
|
14970
|
+
cameraMotion: z68.string().optional()
|
|
14971
|
+
}).catchall(z68.unknown());
|
|
14972
|
+
var FlightRecorderEntrySchema = z68.object({
|
|
14973
|
+
schemaVersion: z68.literal(1).optional(),
|
|
14974
|
+
id: z68.string().min(1),
|
|
14975
|
+
taskId: z68.string().min(1),
|
|
14976
|
+
runId: z68.string().min(1),
|
|
14977
|
+
sequence: z68.number().int().nonnegative(),
|
|
14978
|
+
timestamp: z68.string().min(1),
|
|
14979
|
+
provider: FlightRecorderProviderSchema.or(z68.string()),
|
|
14980
|
+
model: z68.string().min(1),
|
|
14981
|
+
prompt: z68.string(),
|
|
14982
|
+
durationSeconds: z68.number().nonnegative(),
|
|
14983
|
+
aspectRatio: z68.string().optional(),
|
|
14984
|
+
resolution: z68.string().optional(),
|
|
14985
|
+
startImageUrl: z68.string().optional(),
|
|
14986
|
+
endImageUrl: z68.string().optional(),
|
|
14987
|
+
generateAudio: z68.boolean().optional(),
|
|
14988
|
+
// Correlation & pipeline metadata
|
|
14989
|
+
angleKey: z68.string().optional(),
|
|
14990
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
14991
|
+
generationType: FlightRecorderGenerationTypeSchema,
|
|
14992
|
+
operationId: z68.string().min(1).optional(),
|
|
14993
|
+
revisionId: z68.string().min(1).optional(),
|
|
14994
|
+
attemptNumber: z68.number().int().nonnegative().default(1),
|
|
14995
|
+
// Elements & Distillation
|
|
14996
|
+
elements: z68.array(FlightRecorderElementSchema).optional(),
|
|
14997
|
+
distillation: FlightRecorderDistillationSchema.optional(),
|
|
14998
|
+
// Raw payload (sanitized of secrets)
|
|
14999
|
+
rawPayload: z68.record(z68.unknown())
|
|
15000
|
+
});
|
|
15001
|
+
var FlightRecorderQuerySchema = z68.object({
|
|
15002
|
+
taskId: z68.string().min(1),
|
|
15003
|
+
runId: z68.string().optional(),
|
|
15004
|
+
sceneIndex: z68.number().int().nonnegative().optional(),
|
|
15005
|
+
angleKey: z68.string().optional(),
|
|
15006
|
+
generationType: FlightRecorderGenerationTypeSchema.optional(),
|
|
15007
|
+
cursor: z68.number().int().nonnegative().optional(),
|
|
15008
|
+
limit: z68.number().int().positive().optional()
|
|
15009
|
+
});
|
|
15010
|
+
var FlightRecorderResponseSchema = z68.object({
|
|
15011
|
+
taskId: z68.string().min(1),
|
|
15012
|
+
runId: z68.string().min(1),
|
|
15013
|
+
entries: z68.array(FlightRecorderEntrySchema),
|
|
15014
|
+
lastCall: FlightRecorderEntrySchema.nullable(),
|
|
15015
|
+
count: z68.number().int().nonnegative(),
|
|
15016
|
+
nextCursor: z68.number().int().nonnegative().nullable()
|
|
15017
|
+
});
|
|
15018
|
+
|
|
14858
15019
|
// src/response-body.ts
|
|
14859
15020
|
var ResponseBodyTooLargeError = class extends Error {
|
|
14860
15021
|
static {
|
|
@@ -15094,7 +15255,7 @@ var ApiClient = class {
|
|
|
15094
15255
|
};
|
|
15095
15256
|
|
|
15096
15257
|
// src/index.ts
|
|
15097
|
-
var MCP_VERSION = "7.
|
|
15258
|
+
var MCP_VERSION = "7.3.0";
|
|
15098
15259
|
|
|
15099
15260
|
// src/meta-upload-app.ts
|
|
15100
15261
|
import { readFileSync } from "fs";
|
|
@@ -15166,7 +15327,7 @@ function registerMediaUploadAppResource(server, resolveEndpoint) {
|
|
|
15166
15327
|
__name(registerMediaUploadAppResource, "registerMediaUploadAppResource");
|
|
15167
15328
|
|
|
15168
15329
|
// src/tools/tasks.ts
|
|
15169
|
-
import { z as
|
|
15330
|
+
import { z as z72 } from "zod";
|
|
15170
15331
|
|
|
15171
15332
|
// src/resolve-image.ts
|
|
15172
15333
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -15727,10 +15888,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
15727
15888
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
15728
15889
|
|
|
15729
15890
|
// src/tools/shared.ts
|
|
15730
|
-
import { z as
|
|
15731
|
-
var Lang =
|
|
15732
|
-
var Country =
|
|
15733
|
-
var LandingStrategyEnum =
|
|
15891
|
+
import { z as z69 } from "zod";
|
|
15892
|
+
var Lang = z69.string().regex(/^[a-z]{2}(?:[-_][a-zA-Z]{2})?$/, "Usa un c\xF3digo de idioma BCP-47, por ejemplo es, en-US o pt-BR").max(10);
|
|
15893
|
+
var Country = z69.string().min(2).max(3);
|
|
15894
|
+
var LandingStrategyEnum = z69.enum([
|
|
15734
15895
|
"auto",
|
|
15735
15896
|
"classic",
|
|
15736
15897
|
"pain_solution",
|
|
@@ -15739,12 +15900,12 @@ var LandingStrategyEnum = z68.enum([
|
|
|
15739
15900
|
"offer_value",
|
|
15740
15901
|
"lifestyle_identity"
|
|
15741
15902
|
]);
|
|
15742
|
-
var LandingImageFormatEnum =
|
|
15903
|
+
var LandingImageFormatEnum = z69.enum([
|
|
15743
15904
|
"9:16",
|
|
15744
15905
|
"4:5",
|
|
15745
15906
|
"1:1"
|
|
15746
15907
|
]);
|
|
15747
|
-
var VideoPresetEnum =
|
|
15908
|
+
var VideoPresetEnum = z69.enum([
|
|
15748
15909
|
"auto",
|
|
15749
15910
|
"ugc_dynamic",
|
|
15750
15911
|
"ugc_how_to",
|
|
@@ -15757,21 +15918,21 @@ var VideoPresetEnum = z68.enum([
|
|
|
15757
15918
|
"pixar_problem",
|
|
15758
15919
|
"pixar_sassy"
|
|
15759
15920
|
]);
|
|
15760
|
-
var VideoStructureEnum =
|
|
15921
|
+
var VideoStructureEnum = z69.enum([
|
|
15761
15922
|
"single_take",
|
|
15762
15923
|
"multi_scene"
|
|
15763
15924
|
]);
|
|
15764
|
-
var VideoQualityEnum =
|
|
15925
|
+
var VideoQualityEnum = z69.enum([
|
|
15765
15926
|
"economy",
|
|
15766
15927
|
"medium",
|
|
15767
15928
|
"pro"
|
|
15768
15929
|
]);
|
|
15769
|
-
var VideoRouteIdEnum =
|
|
15930
|
+
var VideoRouteIdEnum = z69.enum([
|
|
15770
15931
|
"single_take",
|
|
15771
15932
|
"multi_scene",
|
|
15772
15933
|
"free"
|
|
15773
15934
|
]);
|
|
15774
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
15935
|
+
var TaskCreativeVariantVideoPresetEnum = z69.enum([
|
|
15775
15936
|
"auto",
|
|
15776
15937
|
"ugc_dynamic",
|
|
15777
15938
|
"ugc_how_to",
|
|
@@ -15842,7 +16003,7 @@ function resolveVideoPreset(preset) {
|
|
|
15842
16003
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
15843
16004
|
}
|
|
15844
16005
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
15845
|
-
var VideoTierEnum =
|
|
16006
|
+
var VideoTierEnum = z69.enum([
|
|
15846
16007
|
"basic"
|
|
15847
16008
|
]);
|
|
15848
16009
|
function resolveVideoTier(_tier) {
|
|
@@ -15882,22 +16043,22 @@ function assertSemanticVideoDurationCompatibility(structure, quality, durationSe
|
|
|
15882
16043
|
}
|
|
15883
16044
|
}
|
|
15884
16045
|
__name(assertSemanticVideoDurationCompatibility, "assertSemanticVideoDurationCompatibility");
|
|
15885
|
-
var VideoResolutionEnum =
|
|
16046
|
+
var VideoResolutionEnum = z69.enum([
|
|
15886
16047
|
"480p",
|
|
15887
16048
|
"720p"
|
|
15888
16049
|
]);
|
|
15889
|
-
var CreativeGenderEnum =
|
|
16050
|
+
var CreativeGenderEnum = z69.enum([
|
|
15890
16051
|
"female",
|
|
15891
16052
|
"male",
|
|
15892
16053
|
"mixed"
|
|
15893
16054
|
]);
|
|
15894
|
-
var VideoStyleEnum =
|
|
16055
|
+
var VideoStyleEnum = z69.enum([
|
|
15895
16056
|
"ugc",
|
|
15896
16057
|
"cartoon_3d",
|
|
15897
16058
|
"product_only",
|
|
15898
16059
|
"ai_dynamic"
|
|
15899
16060
|
]);
|
|
15900
|
-
var NarrativeStyleEnum =
|
|
16061
|
+
var NarrativeStyleEnum = z69.enum([
|
|
15901
16062
|
"review",
|
|
15902
16063
|
"ugc_how_to",
|
|
15903
16064
|
"problem_product_cta",
|
|
@@ -15915,7 +16076,7 @@ var NarrativeStyleEnum = z68.enum([
|
|
|
15915
16076
|
"ugc_demo_review",
|
|
15916
16077
|
"market"
|
|
15917
16078
|
]);
|
|
15918
|
-
var PublicNarrativeStyleEnum =
|
|
16079
|
+
var PublicNarrativeStyleEnum = z69.enum([
|
|
15919
16080
|
"review",
|
|
15920
16081
|
"ugc_how_to",
|
|
15921
16082
|
"ugc_unboxing_chaos",
|
|
@@ -15928,7 +16089,7 @@ var PublicNarrativeStyleEnum = z68.enum([
|
|
|
15928
16089
|
"sassy_product_pixar",
|
|
15929
16090
|
"market"
|
|
15930
16091
|
]);
|
|
15931
|
-
var VideoModelEnum =
|
|
16092
|
+
var VideoModelEnum = z69.enum([
|
|
15932
16093
|
"veo",
|
|
15933
16094
|
"wan",
|
|
15934
16095
|
"bytedance",
|
|
@@ -15936,29 +16097,29 @@ var VideoModelEnum = z68.enum([
|
|
|
15936
16097
|
"grok",
|
|
15937
16098
|
"kling"
|
|
15938
16099
|
]);
|
|
15939
|
-
var ProductReferenceUserChoiceEnum =
|
|
16100
|
+
var ProductReferenceUserChoiceEnum = z69.enum([
|
|
15940
16101
|
"same_product",
|
|
15941
16102
|
"variants",
|
|
15942
16103
|
"different_products",
|
|
15943
16104
|
"combo_distinct"
|
|
15944
16105
|
]);
|
|
15945
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
16106
|
+
var ProductReferenceCandidateGroupingEnum = z69.enum([
|
|
15946
16107
|
"same_product_same_variant",
|
|
15947
16108
|
"same_product_different_variants",
|
|
15948
16109
|
"different_products",
|
|
15949
16110
|
"unclear"
|
|
15950
16111
|
]);
|
|
15951
|
-
var ProductReferenceScopeEnum =
|
|
16112
|
+
var ProductReferenceScopeEnum = z69.enum([
|
|
15952
16113
|
"base",
|
|
15953
16114
|
"video_view_pack"
|
|
15954
16115
|
]);
|
|
15955
|
-
var ProductReferenceResolutionDecisionEnum =
|
|
16116
|
+
var ProductReferenceResolutionDecisionEnum = z69.enum([
|
|
15956
16117
|
"approve",
|
|
15957
16118
|
"reject",
|
|
15958
16119
|
"observed_only",
|
|
15959
16120
|
"correct_view"
|
|
15960
16121
|
]);
|
|
15961
|
-
var ProductReferenceRejectionReasonEnum =
|
|
16122
|
+
var ProductReferenceRejectionReasonEnum = z69.enum([
|
|
15962
16123
|
"replacement_requested",
|
|
15963
16124
|
"wrong_product_identity",
|
|
15964
16125
|
"wrong_variant",
|
|
@@ -15969,13 +16130,13 @@ var ProductReferenceRejectionReasonEnum = z68.enum([
|
|
|
15969
16130
|
"not_a_product_photo",
|
|
15970
16131
|
"other"
|
|
15971
16132
|
]);
|
|
15972
|
-
var GapDurationChoiceMirror =
|
|
15973
|
-
angleIndex:
|
|
15974
|
-
recommendedSec:
|
|
15975
|
-
|
|
15976
|
-
|
|
16133
|
+
var GapDurationChoiceMirror = z69.object({
|
|
16134
|
+
angleIndex: z69.number().int().nonnegative(),
|
|
16135
|
+
recommendedSec: z69.union([
|
|
16136
|
+
z69.literal(15),
|
|
16137
|
+
z69.literal(30)
|
|
15977
16138
|
]),
|
|
15978
|
-
estimatedDeltaCredits:
|
|
16139
|
+
estimatedDeltaCredits: z69.number().int().nonnegative().optional()
|
|
15979
16140
|
});
|
|
15980
16141
|
function buildSelectedImageUrlsHash(urls) {
|
|
15981
16142
|
const input = [
|
|
@@ -15985,13 +16146,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
15985
16146
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
15986
16147
|
}
|
|
15987
16148
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
15988
|
-
var ImageCreativeStyleEnum =
|
|
16149
|
+
var ImageCreativeStyleEnum = z69.enum([
|
|
15989
16150
|
"studio",
|
|
15990
16151
|
"floating",
|
|
15991
16152
|
"ingredients",
|
|
15992
16153
|
"in_use"
|
|
15993
16154
|
]);
|
|
15994
|
-
var ImageCreativeArchetypeEnum =
|
|
16155
|
+
var ImageCreativeArchetypeEnum = z69.enum([
|
|
15995
16156
|
"direct_response_product_ad",
|
|
15996
16157
|
"hero_outcome",
|
|
15997
16158
|
"offer_value_prop",
|
|
@@ -16000,20 +16161,20 @@ var ImageCreativeArchetypeEnum = z68.enum([
|
|
|
16000
16161
|
"problem_solution",
|
|
16001
16162
|
"lifestyle_identity"
|
|
16002
16163
|
]);
|
|
16003
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
16164
|
+
var ImageCreativeVisualTreatmentEnum = z69.enum([
|
|
16004
16165
|
"performance_product_ad",
|
|
16005
16166
|
"premium_dtc_carousel"
|
|
16006
16167
|
]);
|
|
16007
|
-
var ImageCreativeAspectRatioEnum =
|
|
16168
|
+
var ImageCreativeAspectRatioEnum = z69.enum([
|
|
16008
16169
|
"1:1",
|
|
16009
16170
|
"4:5",
|
|
16010
16171
|
"9:16",
|
|
16011
16172
|
"16:9"
|
|
16012
16173
|
]);
|
|
16013
|
-
var ImageRefSchema =
|
|
16014
|
-
url:
|
|
16015
|
-
path:
|
|
16016
|
-
assetId:
|
|
16174
|
+
var ImageRefSchema = z69.object({
|
|
16175
|
+
url: z69.string().url().optional().describe('URL p\xFAblica HTTPS de la foto. Ej: una URL de Shopify CDN, Cloudinary, Imgur. \xDAsala cuando el usuario te diga "est\xE1 en X.com/foto.jpg" o cuando la foto ya est\xE9 hospedada.'),
|
|
16176
|
+
path: z69.string().min(1).optional().describe('Ruta del archivo en el computador del usuario. Ej: "/Users/maria/Desktop/foto.jpg", "~/Pictures/camiseta.png", "C:\\Users\\Maria\\Desktop\\foto.jpg". El MCP local la lee del disco y la sube. SOLO funciona cuando el MCP corre local (stdio). NO funciona en mcp.productmaker.app (HTTP) \u2014 ah\xED usa `url`.'),
|
|
16177
|
+
assetId: z69.string().uuid().optional().describe("ID opaco devuelto por check_media_upload. \xDAsalo para una imagen subida desde el MCP App; ProductMaker adopta el archivo directamente y el MCP nunca descarga sus bytes.")
|
|
16017
16178
|
}).refine((v) => [
|
|
16018
16179
|
v.url,
|
|
16019
16180
|
v.path,
|
|
@@ -16021,11 +16182,11 @@ var ImageRefSchema = z68.object({
|
|
|
16021
16182
|
].filter(Boolean).length === 1, {
|
|
16022
16183
|
message: "each image entry must have exactly one of `url`, `path`, or `assetId`"
|
|
16023
16184
|
});
|
|
16024
|
-
var ImagesInput =
|
|
16185
|
+
var ImagesInput = z69.array(ImageRefSchema).min(1).max(5).superRefine((images, ctx) => {
|
|
16025
16186
|
const assetCount = images.filter((image) => Boolean(image.assetId)).length;
|
|
16026
16187
|
if (assetCount > 0 && assetCount !== images.length) {
|
|
16027
16188
|
ctx.addIssue({
|
|
16028
|
-
code:
|
|
16189
|
+
code: z69.ZodIssueCode.custom,
|
|
16029
16190
|
message: "all image entries must use assetId, or all must use URL/path sources"
|
|
16030
16191
|
});
|
|
16031
16192
|
}
|
|
@@ -16093,14 +16254,14 @@ async function submitCreative(api, opts) {
|
|
|
16093
16254
|
});
|
|
16094
16255
|
}
|
|
16095
16256
|
__name(submitCreative, "submitCreative");
|
|
16096
|
-
var ResearchTargetCountryEnum =
|
|
16257
|
+
var ResearchTargetCountryEnum = z69.enum([
|
|
16097
16258
|
"CO",
|
|
16098
16259
|
"MX",
|
|
16099
16260
|
"PE",
|
|
16100
16261
|
"EC",
|
|
16101
16262
|
"CL"
|
|
16102
16263
|
]);
|
|
16103
|
-
var ResearchCategoryEnum =
|
|
16264
|
+
var ResearchCategoryEnum = z69.enum([
|
|
16104
16265
|
"auto",
|
|
16105
16266
|
"automotive",
|
|
16106
16267
|
"kitchen",
|
|
@@ -16151,7 +16312,7 @@ var OVERWRITES_EXTERNAL = {
|
|
|
16151
16312
|
idempotentHint: false,
|
|
16152
16313
|
openWorldHint: true
|
|
16153
16314
|
};
|
|
16154
|
-
var DailyControlStatusEnum =
|
|
16315
|
+
var DailyControlStatusEnum = z69.enum([
|
|
16155
16316
|
"ok",
|
|
16156
16317
|
"sales_unavailable",
|
|
16157
16318
|
"timezone_unavailable",
|
|
@@ -16164,19 +16325,19 @@ var DailyControlStatusEnum = z68.enum([
|
|
|
16164
16325
|
"product_missing",
|
|
16165
16326
|
"store_unreachable"
|
|
16166
16327
|
]);
|
|
16167
|
-
var DailyControlLightEnum =
|
|
16328
|
+
var DailyControlLightEnum = z69.enum([
|
|
16168
16329
|
"green",
|
|
16169
16330
|
"amber",
|
|
16170
16331
|
"red",
|
|
16171
16332
|
"none"
|
|
16172
16333
|
]);
|
|
16173
|
-
var DailyControlVerdictEnum =
|
|
16334
|
+
var DailyControlVerdictEnum = z69.enum([
|
|
16174
16335
|
"scale",
|
|
16175
16336
|
"hold",
|
|
16176
16337
|
"kill",
|
|
16177
16338
|
"insufficient_sample"
|
|
16178
16339
|
]);
|
|
16179
|
-
var DailyControlSourceEnum =
|
|
16340
|
+
var DailyControlSourceEnum = z69.enum([
|
|
16180
16341
|
"shopify",
|
|
16181
16342
|
"shopify_settling",
|
|
16182
16343
|
"user",
|
|
@@ -16248,6 +16409,8 @@ var McpErrorCode = {
|
|
|
16248
16409
|
SHOPIFY_PUBLISH_INPUT_REQUIRED: "SHOPIFY_PUBLISH_INPUT_REQUIRED",
|
|
16249
16410
|
SHOPIFY_PUBLISH_CONTEXT_CHANGED: "SHOPIFY_PUBLISH_CONTEXT_CHANGED",
|
|
16250
16411
|
SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR: "SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR",
|
|
16412
|
+
SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED: "SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED",
|
|
16413
|
+
SHOPIFY_PUBLISH_VERIFICATION_FAILED: "SHOPIFY_PUBLISH_VERIFICATION_FAILED",
|
|
16251
16414
|
SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE: "SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE",
|
|
16252
16415
|
SHOPIFY_THEME_SETUP_REQUIRED: "SHOPIFY_THEME_SETUP_REQUIRED",
|
|
16253
16416
|
// Meta / Facebook Ads
|
|
@@ -16320,6 +16483,8 @@ var CODE_MESSAGES = {
|
|
|
16320
16483
|
SHOPIFY_PUBLISH_INPUT_REQUIRED: "Review every recovery issue with the seller. Ask for missing prices and confirm the exact currency, unit price and pack totals before resending commerceCorrection with confirmed:true. Never invent amounts, convert currency or remove an offer.",
|
|
16321
16484
|
SHOPIFY_PUBLISH_CONTEXT_CHANGED: "The publication context changed. Reopen the task in ProductMaker, review the current store, product and landing revision, and obtain fresh confirmation. Do not reuse this correction.",
|
|
16322
16485
|
SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR: "Open the landing editor in ProductMaker to reconcile the visible offer with checkout prices. The correction was not saved; do not retry it automatically or regenerate the landing without approval.",
|
|
16486
|
+
SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED: "The seller confirmed exactly the suggested values and the offer still cannot publish \u2014 resending the same correction will loop. Read the error's reason to the user and send them to the landing editor in ProductMaker to adjust the offer, then publish again. Do not resend commerceCorrection.",
|
|
16487
|
+
SHOPIFY_PUBLISH_VERIFICATION_FAILED: "Shopify did not keep what the publish wrote (offer variants, template or inventory), or the landing is too large. Read the error's reason to the user; retry the publish once, and if it repeats follow the step in the reason (map packs to existing variants, check apps that edit products, or trim the landing in the editor).",
|
|
16323
16488
|
SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE: "The selected Shopify product cannot carry the confirmed offer (missing quantity options/prices) or no longer exists. Read the error's message to the user, then retry with publicationMode:'new' to create a fresh product, or ask the user to pick a different existing product.",
|
|
16324
16489
|
SHOPIFY_THEME_SETUP_REQUIRED: "The store's Shopify theme is missing the ProductMaker 'Code Landing' app block \u2014 publishing now would create a product whose page renders blank. Send the user the themeEditorDeepLink (in error data) to open the Shopify theme editor, have them confirm the Code Landing block is added and press Save, then retry publishing. This is a one-time step per store; nothing was published.",
|
|
16325
16490
|
SHOPIFY_NO_PUBLISHED_THEME: "The Shopify store has no published theme, so there is nowhere to place the landing. Ask the user to publish a theme (Online Store > Themes > Publish) and retry.",
|
|
@@ -16515,6 +16680,8 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
16515
16680
|
McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED,
|
|
16516
16681
|
McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED,
|
|
16517
16682
|
McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR,
|
|
16683
|
+
McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED,
|
|
16684
|
+
McpErrorCode.SHOPIFY_PUBLISH_VERIFICATION_FAILED,
|
|
16518
16685
|
McpErrorCode.SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE,
|
|
16519
16686
|
McpErrorCode.SHOPIFY_THEME_SETUP_REQUIRED,
|
|
16520
16687
|
McpErrorCode.TIKTOK_NOT_CONNECTED,
|
|
@@ -16542,6 +16709,8 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
16542
16709
|
McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED,
|
|
16543
16710
|
McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED,
|
|
16544
16711
|
McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR,
|
|
16712
|
+
McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED,
|
|
16713
|
+
McpErrorCode.SHOPIFY_PUBLISH_VERIFICATION_FAILED,
|
|
16545
16714
|
McpErrorCode.SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE,
|
|
16546
16715
|
McpErrorCode.SHOPIFY_NOT_CONNECTED,
|
|
16547
16716
|
McpErrorCode.SHOPIFY_TOKEN_EXPIRED,
|
|
@@ -16665,13 +16834,20 @@ function translateError(err) {
|
|
|
16665
16834
|
}
|
|
16666
16835
|
if (err instanceof ApiHttpError) {
|
|
16667
16836
|
const body = isRecord2(err.body) ? err.body : {};
|
|
16668
|
-
if (body.code === McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED || body.code === McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED || body.code === McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR || body.code === McpErrorCode.SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE || body.code === McpErrorCode.SHOPIFY_THEME_SETUP_REQUIRED || body.code === McpErrorCode.SHOPIFY_PUBLISH_FAILED) {
|
|
16837
|
+
if (body.code === McpErrorCode.SHOPIFY_PUBLISH_INPUT_REQUIRED || body.code === McpErrorCode.SHOPIFY_PUBLISH_CONTEXT_CHANGED || body.code === McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR || body.code === McpErrorCode.SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED || body.code === McpErrorCode.SHOPIFY_PUBLISH_VERIFICATION_FAILED || body.code === McpErrorCode.SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE || body.code === McpErrorCode.SHOPIFY_THEME_SETUP_REQUIRED || body.code === McpErrorCode.SHOPIFY_PUBLISH_FAILED) {
|
|
16669
16838
|
const parsed = ShopifyPublishErrorResponse.safeParse(body);
|
|
16670
16839
|
if (!parsed.success) return mcp(McpErrorCode.INTERNAL, resolveMessage(McpErrorCode.INTERNAL, void 0));
|
|
16671
16840
|
const details = parsed.data;
|
|
16672
16841
|
const extra = {};
|
|
16673
|
-
if (details.code === "SHOPIFY_PUBLISH_INPUT_REQUIRED")
|
|
16674
|
-
|
|
16842
|
+
if (details.code === "SHOPIFY_PUBLISH_INPUT_REQUIRED") {
|
|
16843
|
+
extra.recovery = details.recovery;
|
|
16844
|
+
if (details.correctionRejected) {
|
|
16845
|
+
extra.correctionRejected = true;
|
|
16846
|
+
if (details.rejectedIssueCodes) extra.rejectedIssueCodes = details.rejectedIssueCodes;
|
|
16847
|
+
}
|
|
16848
|
+
}
|
|
16849
|
+
if (details.code === "SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR" || details.code === "SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED") extra.action = details.action;
|
|
16850
|
+
if ((details.code === "SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED" || details.code === "SHOPIFY_PUBLISH_VERIFICATION_FAILED" || details.code === "SHOPIFY_PUBLISH_INPUT_REQUIRED" && details.correctionRejected) && details.message) extra.reason = details.message.slice(0, 500);
|
|
16675
16851
|
if (details.code === "SHOPIFY_THEME_SETUP_REQUIRED") extra.themeEditorDeepLink = details.themeEditorDeepLink;
|
|
16676
16852
|
const saved = "commerceCorrectionSaved" in details && details.commerceCorrectionSaved === true;
|
|
16677
16853
|
if (saved) extra.commerceCorrectionSaved = true;
|
|
@@ -17302,29 +17478,29 @@ ${parsed.data.error ? `${escapeMarkdownText(parsed.data.error)}
|
|
|
17302
17478
|
__name(renderVideoScriptMarkdown, "renderVideoScriptMarkdown");
|
|
17303
17479
|
|
|
17304
17480
|
// src/tools/media-presentation.ts
|
|
17305
|
-
import { z as
|
|
17306
|
-
var HttpsPresentationUrlSchema =
|
|
17481
|
+
import { z as z70 } from "zod";
|
|
17482
|
+
var HttpsPresentationUrlSchema = z70.string().url().max(2048).refine((value) => new URL(value).protocol === "https:");
|
|
17307
17483
|
var ProductMakerPreviewUrlSchema = HttpsPresentationUrlSchema.refine((value) => {
|
|
17308
17484
|
const hostname = new URL(value).hostname.toLowerCase();
|
|
17309
17485
|
return hostname === "productmaker.app" || hostname.endsWith(".productmaker.app");
|
|
17310
17486
|
}, "preview URL must be owned by ProductMaker");
|
|
17311
|
-
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) =>
|
|
17312
|
-
var PresentationImageSchema =
|
|
17313
|
-
kind:
|
|
17487
|
+
var positiveIntAtMost = /* @__PURE__ */ __name((maximum) => z70.number().int().positive().max(maximum), "positiveIntAtMost");
|
|
17488
|
+
var PresentationImageSchema = z70.object({
|
|
17489
|
+
kind: z70.literal("image"),
|
|
17314
17490
|
url: HttpsPresentationUrlSchema,
|
|
17315
|
-
mimeType:
|
|
17491
|
+
mimeType: z70.enum([
|
|
17316
17492
|
"image/jpeg",
|
|
17317
17493
|
"image/png"
|
|
17318
17494
|
]),
|
|
17319
17495
|
byteSize: positiveIntAtMost(5 * 1024 * 1024),
|
|
17320
17496
|
width: positiveIntAtMost(16384),
|
|
17321
17497
|
height: positiveIntAtMost(16384),
|
|
17322
|
-
alt:
|
|
17498
|
+
alt: z70.string().trim().min(1).max(240)
|
|
17323
17499
|
}).strict();
|
|
17324
17500
|
var McpMediaPresentationSchema = PresentationImageSchema;
|
|
17325
|
-
var GalleryImageSchema =
|
|
17501
|
+
var GalleryImageSchema = z70.object({
|
|
17326
17502
|
url: ProductMakerPreviewUrlSchema,
|
|
17327
|
-
alt:
|
|
17503
|
+
alt: z70.string().trim().min(1).max(240)
|
|
17328
17504
|
});
|
|
17329
17505
|
var MCP_GALLERY_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
|
|
17330
17506
|
async function imageBlocks(image, transport) {
|
|
@@ -17474,10 +17650,10 @@ ${summary}`,
|
|
|
17474
17650
|
__name(requirePaidCreativeConfirmation, "requirePaidCreativeConfirmation");
|
|
17475
17651
|
|
|
17476
17652
|
// src/tools/winning-product-image.ts
|
|
17477
|
-
import { z as
|
|
17478
|
-
var WinnerReferenceInput =
|
|
17479
|
-
runId:
|
|
17480
|
-
candidateSourceId:
|
|
17653
|
+
import { z as z71 } from "zod";
|
|
17654
|
+
var WinnerReferenceInput = z71.object({
|
|
17655
|
+
runId: z71.string().uuid(),
|
|
17656
|
+
candidateSourceId: z71.string().trim().min(1).max(160)
|
|
17481
17657
|
}).strict().describe("Referencia opaca de un producto devuelto por find_winning_products/get_product_research_run.");
|
|
17482
17658
|
async function resolveWinnerImages(api, winnerReference, images) {
|
|
17483
17659
|
if (!winnerReference) return images;
|
|
@@ -17514,188 +17690,189 @@ var createProductTaskSingleOutputDescription = renderCreateProductTaskAvoidWhenF
|
|
|
17514
17690
|
var createServiceVideoGuidance = getProductMakerCapabilityModelGuidance("create_service_video");
|
|
17515
17691
|
var listTasksGuidance = getProductMakerCapabilityModelGuidance("list_tasks");
|
|
17516
17692
|
var editTaskDraftGuidance = getProductMakerCapabilityModelGuidance("edit_task_draft");
|
|
17517
|
-
var CreateProductTaskInput =
|
|
17693
|
+
var CreateProductTaskInput = z72.object({
|
|
17518
17694
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
17519
17695
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
17520
|
-
projectId:
|
|
17521
|
-
productUrl:
|
|
17696
|
+
projectId: z72.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
17697
|
+
productUrl: z72.string().url().optional().describe("Opcional. URL de la p\xE1gina del producto (Shopify, AliExpress, Amazon, etc.) para enriquecer el contexto. Si se omite, la IA infiere todo desde la imagen."),
|
|
17522
17698
|
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.'),
|
|
17523
17699
|
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.'),
|
|
17524
|
-
price:
|
|
17525
|
-
compareAtPrice:
|
|
17526
|
-
offer:
|
|
17527
|
-
paymentMethods:
|
|
17528
|
-
productContext:
|
|
17529
|
-
productLabel:
|
|
17700
|
+
price: z72.string().min(1).max(120).optional().describe('Precio que se mostrar\xE1 en la landing y video. Formato libre \u2014 ej. "$89.900", "USD 29.99", "MXN 599". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si te dice "t\xFA elige", om\xEDtelo y el backend sugiere uno.'),
|
|
17701
|
+
compareAtPrice: z72.string().min(1).max(120).optional().describe('Opcional. Precio anterior para comunicar un descuento real en landing e im\xE1genes. Ej. "$129.000" cuando price="$89.900".'),
|
|
17702
|
+
offer: z72.string().min(1).max(240).optional().describe('Oferta o promoci\xF3n a destacar. Ej. "2x1", "Env\xEDo gratis hoy", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si te dice "t\xFA elige", om\xEDtelo.'),
|
|
17703
|
+
paymentMethods: z72.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago que puede mostrar la landing. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
|
|
17704
|
+
productContext: z72.string().max(3e3).optional().describe("Opcional. Informacion adicional del producto que la IA debe usar como contexto prioritario: uso real, comprador, restricciones, diferenciadores o direccion creativa. No reemplaza la investigacion de competencia; si hay competencia, guia el primer angulo y los outputs no deben contradecirlo."),
|
|
17705
|
+
productLabel: z72.string().trim().max(80).optional().describe('Opcional. Qu\xE9 es el producto, en pocas palabras (ej. "quita pelusas para ropa"). Es AUTORITATIVO: si lo env\xEDas, la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA detecta el producto desde la imagen.'),
|
|
17530
17706
|
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.'),
|
|
17531
|
-
durationSeconds:
|
|
17532
|
-
|
|
17533
|
-
|
|
17707
|
+
durationSeconds: z72.union([
|
|
17708
|
+
z72.literal(15),
|
|
17709
|
+
z72.literal(30)
|
|
17534
17710
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
17535
|
-
pauseForAngleReview:
|
|
17536
|
-
aiDecidesAll:
|
|
17711
|
+
pauseForAngleReview: z72.boolean().optional().describe("Compatibilidad heredada. MCP deriva esta pausa de aiDecidesAll: manual siempre pausa y autom\xE1tico siempre la omite. No uses este campo para saltar reviews."),
|
|
17712
|
+
aiDecidesAll: z72.boolean().optional().describe("Mapea el toggle web \u201CDejar que la IA decida todo\u201D. Si true, ProductMaker omite reviews. Act\xEDvalo \xFAnicamente cuando el usuario lo pida expl\xEDcitamente. Omitido/false = reviews conversacionales."),
|
|
17537
17713
|
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.'),
|
|
17538
17714
|
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.'),
|
|
17539
17715
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
17540
17716
|
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).'),
|
|
17541
|
-
videoAngleCount:
|
|
17717
|
+
videoAngleCount: z72.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
|
|
17542
17718
|
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.'),
|
|
17543
|
-
outputs:
|
|
17719
|
+
outputs: z72.array(z72.enum([
|
|
17544
17720
|
"landing",
|
|
17545
17721
|
"video",
|
|
17546
17722
|
"image"
|
|
17547
17723
|
])).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}`),
|
|
17548
|
-
competitorScanEnabled:
|
|
17549
|
-
replicateWinnerWhenFound:
|
|
17550
|
-
brandId:
|
|
17551
|
-
actorId:
|
|
17724
|
+
competitorScanEnabled: z72.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). Si la tarea incluye video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
|
|
17725
|
+
replicateWinnerWhenFound: z72.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false estudia el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1ade una pregunta obligatoria."),
|
|
17726
|
+
brandId: z72.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer los outputs generados."),
|
|
17727
|
+
actorId: z72.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
|
|
17552
17728
|
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.'),
|
|
17553
|
-
creativeDirection:
|
|
17554
|
-
headline:
|
|
17555
|
-
subheadline:
|
|
17729
|
+
creativeDirection: z72.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo) que aplica a los outputs de IMAGEN y LANDING (no al video \u2014 el estilo/ambiente del video se dirige con scriptNotes). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Ej. "amarillo y azul, minimalista". M\xE1x 500 caracteres.'),
|
|
17730
|
+
headline: z72.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar. Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. Se aplica a las IM\xC1GENES y a la portada de la landing de esta task (el video no lo usa; para el video usa scriptNotes). \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
|
|
17731
|
+
subheadline: z72.string().max(160).optional().describe("Opcional. Subt\xEDtulo EXACTO a renderizar, misma regla que headline. Independiente: puedes fijar solo el subt\xEDtulo. M\xE1x 160 caracteres."),
|
|
17556
17732
|
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".'),
|
|
17557
17733
|
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".')
|
|
17558
17734
|
}).strict();
|
|
17559
|
-
var CreateServiceVideoInput =
|
|
17560
|
-
landingUrl:
|
|
17561
|
-
additionalContext:
|
|
17735
|
+
var CreateServiceVideoInput = z72.object({
|
|
17736
|
+
landingUrl: z72.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
17737
|
+
additionalContext: z72.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
17562
17738
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
17563
|
-
voiceId:
|
|
17564
|
-
brandId:
|
|
17565
|
-
reviewMode:
|
|
17739
|
+
voiceId: z72.string().trim().min(1).optional().describe('Opcional. Voz de ElevenLabs para toda la narraci\xF3n. Usa "auto" para que la IA la alinee con el presentador o env\xEDa un ID concreto de la lista de voces de la web.'),
|
|
17740
|
+
brandId: z72.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
17741
|
+
reviewMode: z72.enum([
|
|
17566
17742
|
"automatic",
|
|
17567
17743
|
"guided"
|
|
17568
17744
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
17569
|
-
videoPreset:
|
|
17745
|
+
videoPreset: z72.enum([
|
|
17570
17746
|
"auto",
|
|
17571
17747
|
"ugc_dynamic",
|
|
17572
17748
|
"ugc_how_to",
|
|
17573
17749
|
"cinematic",
|
|
17574
17750
|
"wild_card"
|
|
17575
|
-
]).default("auto")
|
|
17751
|
+
]).default("auto"),
|
|
17752
|
+
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.')
|
|
17576
17753
|
}).strict();
|
|
17577
|
-
var GetTaskStatusInput =
|
|
17578
|
-
taskId:
|
|
17579
|
-
waitSeconds:
|
|
17754
|
+
var GetTaskStatusInput = z72.object({
|
|
17755
|
+
taskId: z72.string().min(1),
|
|
17756
|
+
waitSeconds: z72.number().int().min(0).max(120).optional()
|
|
17580
17757
|
});
|
|
17581
|
-
var ListTasksInput =
|
|
17582
|
-
limit:
|
|
17583
|
-
offset:
|
|
17584
|
-
search:
|
|
17758
|
+
var ListTasksInput = z72.object({
|
|
17759
|
+
limit: z72.number().int().min(1).max(50).optional(),
|
|
17760
|
+
offset: z72.number().int().min(0).optional(),
|
|
17761
|
+
search: z72.string().optional()
|
|
17585
17762
|
});
|
|
17586
17763
|
var MCP_REVIEW_LIST_FIELD_MAX = 1500;
|
|
17587
17764
|
var MCP_REVIEW_FEATURE_ITEM_MAX = 240;
|
|
17588
|
-
var EditTaskDraftInput =
|
|
17589
|
-
taskId:
|
|
17590
|
-
angleIndex:
|
|
17591
|
-
angle:
|
|
17592
|
-
angle:
|
|
17593
|
-
buyerPersona:
|
|
17594
|
-
actor:
|
|
17595
|
-
actorId:
|
|
17596
|
-
gender:
|
|
17765
|
+
var EditTaskDraftInput = z72.object({
|
|
17766
|
+
taskId: z72.string().min(1),
|
|
17767
|
+
angleIndex: z72.number().int().min(0),
|
|
17768
|
+
angle: z72.object({
|
|
17769
|
+
angle: z72.string().min(1).max(480),
|
|
17770
|
+
buyerPersona: z72.string().min(1).max(360),
|
|
17771
|
+
actor: z72.string().min(1).max(360).optional(),
|
|
17772
|
+
actorId: z72.string().trim().min(1).optional().describe("Opcional. ID de un personaje guardado (usa list_actors para verlos). Si lo env\xEDas, su foto y su voz mandan sobre la descripci\xF3n de texto."),
|
|
17773
|
+
gender: z72.enum([
|
|
17597
17774
|
"female",
|
|
17598
17775
|
"male"
|
|
17599
17776
|
]).optional(),
|
|
17600
|
-
scriptNotes:
|
|
17777
|
+
scriptNotes: z72.string().max(2e3).optional()
|
|
17601
17778
|
})
|
|
17602
17779
|
});
|
|
17603
|
-
var PendingActionPayload =
|
|
17604
|
-
|
|
17605
|
-
kind:
|
|
17780
|
+
var PendingActionPayload = z72.discriminatedUnion("kind", [
|
|
17781
|
+
z72.object({
|
|
17782
|
+
kind: z72.literal("product_reference_set_approval"),
|
|
17606
17783
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17607
|
-
scopeKey:
|
|
17608
|
-
scopeSnapshotId:
|
|
17609
|
-
expectedScopeHash:
|
|
17784
|
+
scopeKey: z72.string().min(1).max(120).optional(),
|
|
17785
|
+
scopeSnapshotId: z72.string().uuid().optional(),
|
|
17786
|
+
expectedScopeHash: z72.string().min(1).max(128).optional(),
|
|
17610
17787
|
decision: ProductReferenceResolutionDecisionEnum,
|
|
17611
17788
|
reason: ProductReferenceRejectionReasonEnum.optional(),
|
|
17612
|
-
affectedRefKeys:
|
|
17613
|
-
affectedPhotoNumbers:
|
|
17614
|
-
recoveryAction:
|
|
17789
|
+
affectedRefKeys: z72.array(z72.string().min(1).max(200)).min(1).optional(),
|
|
17790
|
+
affectedPhotoNumbers: z72.array(z72.number().int().positive()).min(1).optional(),
|
|
17791
|
+
recoveryAction: z72.enum([
|
|
17615
17792
|
"remove",
|
|
17616
17793
|
"replace",
|
|
17617
17794
|
"upload",
|
|
17618
17795
|
"return_to_selection"
|
|
17619
17796
|
]).optional()
|
|
17620
17797
|
}),
|
|
17621
|
-
|
|
17622
|
-
kind:
|
|
17623
|
-
selectedPhotoNumbers:
|
|
17798
|
+
z72.object({
|
|
17799
|
+
kind: z72.literal("product_reference_confirmation"),
|
|
17800
|
+
selectedPhotoNumbers: z72.array(z72.number().int().positive().max(5)).min(1).max(5).optional().describe("Opcional. N\xFAmeros visibles de las fotos que el usuario quiere conservar; las dem\xE1s se deseleccionan. Debe quedar al menos una."),
|
|
17624
17801
|
userChoice: ProductReferenceUserChoiceEnum.optional(),
|
|
17625
|
-
confirmedProductNames:
|
|
17802
|
+
confirmedProductNames: z72.array(z72.string().min(1).max(120)).min(2).max(8).optional(),
|
|
17626
17803
|
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."),
|
|
17627
17804
|
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."),
|
|
17628
|
-
useMultiSceneShowcase:
|
|
17805
|
+
useMultiSceneShowcase: z72.boolean().optional().describe("Compatibilidad con confirmaciones antiguas: si es true junto con userChoice=variants, conserva el showcase multiescena.")
|
|
17629
17806
|
}),
|
|
17630
|
-
|
|
17631
|
-
kind:
|
|
17807
|
+
z72.object({
|
|
17808
|
+
kind: z72.literal("angle_review_approval"),
|
|
17632
17809
|
// All edits are optional — empty action body just approves the
|
|
17633
17810
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
17634
17811
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
17635
17812
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
17636
|
-
customAngle:
|
|
17813
|
+
customAngle: z72.string().min(1).max(480).optional(),
|
|
17637
17814
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
17638
17815
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
17639
|
-
painPoints:
|
|
17640
|
-
benefits:
|
|
17816
|
+
painPoints: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17817
|
+
benefits: z72.string().max(MCP_REVIEW_LIST_FIELD_MAX).optional(),
|
|
17641
17818
|
// Same policy as the two fields above: the strictest downstream contract
|
|
17642
17819
|
// wins. The image endpoint caps each feature at 240 while landing/video
|
|
17643
17820
|
// accept 300, and this single action routes to whichever the task is — so
|
|
17644
17821
|
// accepting 300 here turns a 250-character feature on an image task into
|
|
17645
17822
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
17646
|
-
features:
|
|
17647
|
-
buyerPersona:
|
|
17823
|
+
features: z72.array(z72.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
17824
|
+
buyerPersona: z72.string().min(1).max(360).optional(),
|
|
17648
17825
|
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.'),
|
|
17649
|
-
actor:
|
|
17650
|
-
actorId:
|
|
17651
|
-
creativeDirection:
|
|
17652
|
-
selectedAngleNumbers:
|
|
17653
|
-
angleEdits:
|
|
17654
|
-
angleNumber:
|
|
17655
|
-
narrativeSelection:
|
|
17826
|
+
actor: z72.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
|
|
17827
|
+
actorId: z72.string().max(120).nullable().optional(),
|
|
17828
|
+
creativeDirection: z72.string().max(2e3).optional(),
|
|
17829
|
+
selectedAngleNumbers: z72.array(z72.number().int().positive()).min(1).max(3).optional().describe("N\xFAmeros visibles (1-based) de los \xE1ngulos que el usuario quiere renderizar. Deben ser \xFAnicos, existir en la review y no superar el videoAngleCount autorizado."),
|
|
17830
|
+
angleEdits: z72.array(z72.object({
|
|
17831
|
+
angleNumber: z72.number().int().positive(),
|
|
17832
|
+
narrativeSelection: z72.enum([
|
|
17656
17833
|
"market",
|
|
17657
17834
|
"guided"
|
|
17658
17835
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
17659
|
-
angle:
|
|
17660
|
-
buyerPersona:
|
|
17836
|
+
angle: z72.string().min(1).max(480).optional(),
|
|
17837
|
+
buyerPersona: z72.string().min(1).max(360).optional(),
|
|
17661
17838
|
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.'),
|
|
17662
|
-
actor:
|
|
17663
|
-
actorId:
|
|
17664
|
-
creativeDirection:
|
|
17839
|
+
actor: z72.string().min(1).max(360).optional(),
|
|
17840
|
+
actorId: z72.string().max(120).nullable().optional(),
|
|
17841
|
+
creativeDirection: z72.string().max(2e3).optional()
|
|
17665
17842
|
}).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)."),
|
|
17666
|
-
gapDurationSeconds:
|
|
17667
|
-
|
|
17668
|
-
|
|
17843
|
+
gapDurationSeconds: z72.union([
|
|
17844
|
+
z72.literal(15),
|
|
17845
|
+
z72.literal(30)
|
|
17669
17846
|
]).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.")
|
|
17670
17847
|
}),
|
|
17671
|
-
|
|
17672
|
-
kind:
|
|
17673
|
-
angleId:
|
|
17674
|
-
angleNumber:
|
|
17675
|
-
content:
|
|
17676
|
-
creativeDirection:
|
|
17677
|
-
actor:
|
|
17848
|
+
z72.object({
|
|
17849
|
+
kind: z72.literal("service_angle_approval"),
|
|
17850
|
+
angleId: z72.string().uuid().optional(),
|
|
17851
|
+
angleNumber: z72.number().int().positive().optional(),
|
|
17852
|
+
content: z72.string().min(1).max(480).optional(),
|
|
17853
|
+
creativeDirection: z72.string().min(1).max(1500).optional(),
|
|
17854
|
+
actor: z72.string().min(1).max(360).optional()
|
|
17678
17855
|
}),
|
|
17679
|
-
|
|
17680
|
-
kind:
|
|
17681
|
-
voiceovers:
|
|
17682
|
-
visualDirections:
|
|
17683
|
-
voiceoversByScene:
|
|
17684
|
-
visualDirectionsByScene:
|
|
17856
|
+
z72.object({
|
|
17857
|
+
kind: z72.literal("service_script_approval"),
|
|
17858
|
+
voiceovers: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
|
|
17859
|
+
visualDirections: z72.record(z72.string(), z72.string().min(1).max(1200)).optional(),
|
|
17860
|
+
voiceoversByScene: z72.record(z72.string(), z72.string().min(1).max(600)).optional(),
|
|
17861
|
+
visualDirectionsByScene: z72.record(z72.string(), z72.string().min(1).max(1200)).optional()
|
|
17685
17862
|
})
|
|
17686
17863
|
]);
|
|
17687
|
-
var ResolvePendingActionInput =
|
|
17688
|
-
taskId:
|
|
17864
|
+
var ResolvePendingActionInput = z72.object({
|
|
17865
|
+
taskId: z72.string().min(1),
|
|
17689
17866
|
action: PendingActionPayload
|
|
17690
17867
|
}).strict();
|
|
17691
17868
|
function resolveVariantConfirmVideoTier(action) {
|
|
17692
17869
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
17693
17870
|
}
|
|
17694
17871
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
17695
|
-
var StatusForResolveSchema =
|
|
17872
|
+
var StatusForResolveSchema = z72.object({
|
|
17696
17873
|
// Metadata used to select the backend resume contract. Older API responses
|
|
17697
17874
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
17698
|
-
kind:
|
|
17875
|
+
kind: z72.enum([
|
|
17699
17876
|
"autopilot",
|
|
17700
17877
|
"video",
|
|
17701
17878
|
"image",
|
|
@@ -17703,18 +17880,18 @@ var StatusForResolveSchema = z71.object({
|
|
|
17703
17880
|
"mix",
|
|
17704
17881
|
"service"
|
|
17705
17882
|
]).optional(),
|
|
17706
|
-
selectedOutputs:
|
|
17883
|
+
selectedOutputs: z72.array(z72.enum([
|
|
17707
17884
|
"landing",
|
|
17708
17885
|
"video",
|
|
17709
17886
|
"image"
|
|
17710
17887
|
])).optional(),
|
|
17711
|
-
videoAngleCount:
|
|
17712
|
-
ugcFormat:
|
|
17888
|
+
videoAngleCount: z72.number().int().min(1).max(3).optional(),
|
|
17889
|
+
ugcFormat: z72.enum([
|
|
17713
17890
|
"single_8s",
|
|
17714
17891
|
"single_15s",
|
|
17715
17892
|
"double_30s"
|
|
17716
17893
|
]).optional(),
|
|
17717
|
-
videoStyle:
|
|
17894
|
+
videoStyle: z72.enum([
|
|
17718
17895
|
"ugc",
|
|
17719
17896
|
"cartoon_3d",
|
|
17720
17897
|
"product_only",
|
|
@@ -17723,7 +17900,7 @@ var StatusForResolveSchema = z71.object({
|
|
|
17723
17900
|
videoStructure: VideoStructureEnum.optional(),
|
|
17724
17901
|
videoQuality: VideoQualityEnum.optional(),
|
|
17725
17902
|
videoRouteId: VideoRouteIdEnum.optional(),
|
|
17726
|
-
videoModel:
|
|
17903
|
+
videoModel: z72.enum([
|
|
17727
17904
|
"veo",
|
|
17728
17905
|
"wan",
|
|
17729
17906
|
"bytedance",
|
|
@@ -17731,71 +17908,71 @@ var StatusForResolveSchema = z71.object({
|
|
|
17731
17908
|
"grok",
|
|
17732
17909
|
"kling"
|
|
17733
17910
|
]).optional(),
|
|
17734
|
-
videoTier:
|
|
17911
|
+
videoTier: z72.enum([
|
|
17735
17912
|
"legacy",
|
|
17736
17913
|
"standard",
|
|
17737
17914
|
"pro",
|
|
17738
17915
|
"single_call"
|
|
17739
17916
|
]).optional(),
|
|
17740
|
-
videoResolution:
|
|
17917
|
+
videoResolution: z72.enum([
|
|
17741
17918
|
"480p",
|
|
17742
17919
|
"720p"
|
|
17743
17920
|
]).optional(),
|
|
17744
17921
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
17745
|
-
pauseForVideoScriptReview:
|
|
17746
|
-
pendingUserAction:
|
|
17747
|
-
kind:
|
|
17748
|
-
candidateGrouping:
|
|
17749
|
-
selectedImageUrls:
|
|
17750
|
-
proposedProductNames:
|
|
17922
|
+
pauseForVideoScriptReview: z72.boolean().optional(),
|
|
17923
|
+
pendingUserAction: z72.object({
|
|
17924
|
+
kind: z72.string(),
|
|
17925
|
+
candidateGrouping: z72.string().optional(),
|
|
17926
|
+
selectedImageUrls: z72.array(z72.string()).optional(),
|
|
17927
|
+
proposedProductNames: z72.array(z72.string()).optional(),
|
|
17751
17928
|
// Adaptive reference questions are server-owned. Echo only the evidence
|
|
17752
17929
|
// identity and the choices shown by the current snapshot; never accept a
|
|
17753
17930
|
// client-supplied reference set as authorization.
|
|
17754
|
-
options:
|
|
17755
|
-
mode:
|
|
17931
|
+
options: z72.array(ProductReferenceUserChoiceEnum).max(4).optional(),
|
|
17932
|
+
mode: z72.enum([
|
|
17756
17933
|
"question",
|
|
17757
17934
|
"visual_recovery"
|
|
17758
17935
|
]).optional(),
|
|
17759
17936
|
/** Hand-mirrored from packages/types result.ts — see CLAUDE.md § MCP Server Sync. */
|
|
17760
|
-
canKeepSelection:
|
|
17761
|
-
decisionKey:
|
|
17762
|
-
questionOrdinal:
|
|
17763
|
-
questionCeiling:
|
|
17764
|
-
|
|
17765
|
-
|
|
17937
|
+
canKeepSelection: z72.boolean().optional(),
|
|
17938
|
+
decisionKey: z72.string().optional(),
|
|
17939
|
+
questionOrdinal: z72.number().int().min(1).max(5).optional(),
|
|
17940
|
+
questionCeiling: z72.union([
|
|
17941
|
+
z72.literal(3),
|
|
17942
|
+
z72.literal(5)
|
|
17766
17943
|
]).optional(),
|
|
17767
|
-
referenceEvidenceVersion:
|
|
17768
|
-
expectedEvidenceHash:
|
|
17769
|
-
question:
|
|
17770
|
-
prompt:
|
|
17771
|
-
helpText:
|
|
17772
|
-
options:
|
|
17944
|
+
referenceEvidenceVersion: z72.number().int().positive().optional(),
|
|
17945
|
+
expectedEvidenceHash: z72.string().optional(),
|
|
17946
|
+
question: z72.object({
|
|
17947
|
+
prompt: z72.string().min(1).max(240),
|
|
17948
|
+
helpText: z72.string().min(1).max(300).optional(),
|
|
17949
|
+
options: z72.array(z72.object({
|
|
17773
17950
|
value: ProductReferenceUserChoiceEnum,
|
|
17774
|
-
label:
|
|
17775
|
-
description:
|
|
17951
|
+
label: z72.string().min(1).max(120),
|
|
17952
|
+
description: z72.string().min(1).max(240).optional()
|
|
17776
17953
|
})).min(2).max(4)
|
|
17777
17954
|
}).optional(),
|
|
17778
17955
|
scope: ProductReferenceScopeEnum.optional(),
|
|
17779
|
-
scopeKey:
|
|
17780
|
-
scopeSnapshotId:
|
|
17781
|
-
scopeHash:
|
|
17782
|
-
baseReferenceSetHash:
|
|
17783
|
-
phase:
|
|
17956
|
+
scopeKey: z72.string().optional(),
|
|
17957
|
+
scopeSnapshotId: z72.string().uuid().optional(),
|
|
17958
|
+
scopeHash: z72.string().optional(),
|
|
17959
|
+
baseReferenceSetHash: z72.string().optional(),
|
|
17960
|
+
phase: z72.enum([
|
|
17784
17961
|
"preparation",
|
|
17785
17962
|
"final"
|
|
17786
17963
|
]).optional(),
|
|
17787
|
-
selectedRefKeys:
|
|
17788
|
-
allowedDecisions:
|
|
17789
|
-
previews:
|
|
17790
|
-
refKey:
|
|
17964
|
+
selectedRefKeys: z72.array(z72.string().min(1).max(200)).optional(),
|
|
17965
|
+
allowedDecisions: z72.array(ProductReferenceResolutionDecisionEnum).optional(),
|
|
17966
|
+
previews: z72.array(z72.object({
|
|
17967
|
+
refKey: z72.string().min(1).max(200)
|
|
17791
17968
|
}).passthrough()).optional(),
|
|
17792
|
-
customAngleDraft:
|
|
17793
|
-
painPointsDraft:
|
|
17794
|
-
benefitsDraft:
|
|
17795
|
-
featuresDraft:
|
|
17796
|
-
angleOptions:
|
|
17797
|
-
index:
|
|
17798
|
-
angle:
|
|
17969
|
+
customAngleDraft: z72.string().optional(),
|
|
17970
|
+
painPointsDraft: z72.string().optional(),
|
|
17971
|
+
benefitsDraft: z72.string().optional(),
|
|
17972
|
+
featuresDraft: z72.array(z72.string()).optional(),
|
|
17973
|
+
angleOptions: z72.array(z72.object({
|
|
17974
|
+
index: z72.number().int().nonnegative(),
|
|
17975
|
+
angle: z72.string().min(1)
|
|
17799
17976
|
}).passthrough()).min(1).max(5).optional(),
|
|
17800
17977
|
// Recommendation consumed only when the caller explicitly sends
|
|
17801
17978
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
@@ -17805,17 +17982,17 @@ var StatusForResolveSchema = z71.object({
|
|
|
17805
17982
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
17806
17983
|
// dropped here, so the approval handler below could not echo it back on the
|
|
17807
17984
|
// PATCH — the selection looked accepted and reached no render.
|
|
17808
|
-
angles:
|
|
17809
|
-
id:
|
|
17810
|
-
content:
|
|
17811
|
-
creativeDirection:
|
|
17812
|
-
actor:
|
|
17813
|
-
actorId:
|
|
17985
|
+
angles: z72.array(z72.object({
|
|
17986
|
+
id: z72.string().uuid(),
|
|
17987
|
+
content: z72.string(),
|
|
17988
|
+
creativeDirection: z72.string(),
|
|
17989
|
+
actor: z72.string(),
|
|
17990
|
+
actorId: z72.string().nullable().optional()
|
|
17814
17991
|
}).passthrough()).optional(),
|
|
17815
|
-
panels:
|
|
17816
|
-
beatId:
|
|
17817
|
-
voiceover:
|
|
17818
|
-
visualDirection:
|
|
17992
|
+
panels: z72.array(z72.object({
|
|
17993
|
+
beatId: z72.string(),
|
|
17994
|
+
voiceover: z72.string(),
|
|
17995
|
+
visualDirection: z72.string()
|
|
17819
17996
|
}).passthrough()).optional()
|
|
17820
17997
|
}).optional()
|
|
17821
17998
|
}).passthrough();
|
|
@@ -18041,6 +18218,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
18041
18218
|
voiceId: input.voiceId
|
|
18042
18219
|
} : {},
|
|
18043
18220
|
videoPreset: input.videoPreset,
|
|
18221
|
+
videoQuality: input.videoQuality,
|
|
18044
18222
|
reviewMode: input.reviewMode,
|
|
18045
18223
|
...input.brandId ? {
|
|
18046
18224
|
brandId: input.brandId
|
|
@@ -18645,7 +18823,7 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
18645
18823
|
|
|
18646
18824
|
// src/tools/creatives.ts
|
|
18647
18825
|
import { randomUUID } from "crypto";
|
|
18648
|
-
import { z as
|
|
18826
|
+
import { z as z73 } from "zod";
|
|
18649
18827
|
var generateFreeVideoGuidance = getProductMakerCapabilityModelGuidance("generate_free_video");
|
|
18650
18828
|
var generateVideoCreativeGuidance = getProductMakerCapabilityModelGuidance("generate_video_creative");
|
|
18651
18829
|
var generateImageCreativesGuidance = getProductMakerCapabilityModelGuidance("generate_image_creatives");
|
|
@@ -18655,70 +18833,70 @@ var CreativeRefs = {
|
|
|
18655
18833
|
images: ImagesInput,
|
|
18656
18834
|
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.'),
|
|
18657
18835
|
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.'),
|
|
18658
|
-
price:
|
|
18659
|
-
offer:
|
|
18660
|
-
compareAtPrice:
|
|
18661
|
-
productContext:
|
|
18662
|
-
productLabel:
|
|
18663
|
-
buyerPersona:
|
|
18664
|
-
isCombo:
|
|
18665
|
-
competitorScanEnabled:
|
|
18666
|
-
brandId:
|
|
18836
|
+
price: z73.string().min(1).max(120).optional().describe('Precio en formato libre \u2014 ej. "$89.900", "USD 29.99". Opcional pero MUY IMPACTANTE para conversi\xF3n: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar. Si el usuario te dice "t\xFA elige", omite el campo y la IA del backend sugiere uno.'),
|
|
18837
|
+
offer: z73.string().min(1).max(240).optional().describe('Oferta a destacar \u2014 ej. "2x1", "Env\xEDo gratis", "50% OFF". Opcional pero MUY IMPACTANTE: si el usuario no lo mencion\xF3, PREG\xDANTALE antes de invocar (es v\xE1lido que diga "sin oferta"). Si el usuario te dice "t\xFA elige", omite el campo.'),
|
|
18838
|
+
compareAtPrice: z73.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
18839
|
+
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."),
|
|
18840
|
+
productLabel: z73.string().trim().max(80).optional().describe('Opcional. Nombre o tipo del producto en pocas palabras (ej. "collar de oro", "quita pelusas para ropa"). Es AUTORITATIVO: la IA usa esta identidad y no la reemplaza por otra categor\xEDa. Si lo omites, la IA lo detecta desde la imagen. NO salta la extracci\xF3n.'),
|
|
18841
|
+
buyerPersona: z73.string().optional().describe('Opcional. Descripci\xF3n del comprador objetivo. Ej. "Mujeres 35-50, profesionales urbanas". Si se omite, la IA infiere desde el \xE1ngulo y producto.'),
|
|
18842
|
+
isCombo: z73.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
18843
|
+
competitorScanEnabled: z73.boolean().optional().describe("Opcional. Debe enviarse true solo despu\xE9s de que el usuario acepte estudiar la competencia (o si solicita la narrativa an\xE1lisis de mercado). En video, true analiza anuncios de la competencia y desbloquea la narrativa an\xE1lisis de mercado; si el estudio no encuentra datos suficientes, degrada al planner cl\xE1sico. Omitir no autoriza el estudio profundo."),
|
|
18844
|
+
brandId: z73.string().uuid().optional().describe("Opcional. ID de una marca del usuario; si se env\xEDa, el sistema usa su voz, colores y persona para enriquecer el creativo.")
|
|
18667
18845
|
};
|
|
18668
|
-
var VideoPresenter =
|
|
18669
|
-
|
|
18670
|
-
mode:
|
|
18846
|
+
var VideoPresenter = z73.discriminatedUnion("mode", [
|
|
18847
|
+
z73.object({
|
|
18848
|
+
mode: z73.literal("none")
|
|
18671
18849
|
}).strict(),
|
|
18672
|
-
|
|
18673
|
-
mode:
|
|
18674
|
-
actorId:
|
|
18850
|
+
z73.object({
|
|
18851
|
+
mode: z73.literal("saved_actor"),
|
|
18852
|
+
actorId: z73.string().trim().min(1).max(120).describe("ID devuelto por list_actors para un actor guardado del usuario.")
|
|
18675
18853
|
}).strict(),
|
|
18676
|
-
|
|
18677
|
-
mode:
|
|
18678
|
-
description:
|
|
18854
|
+
z73.object({
|
|
18855
|
+
mode: z73.literal("described"),
|
|
18856
|
+
description: z73.string().trim().min(1).max(500).describe("Descripci\xF3n concreta de la persona que presenta el producto.")
|
|
18679
18857
|
}).strict()
|
|
18680
18858
|
]);
|
|
18681
|
-
var VideoCreativeSetup =
|
|
18682
|
-
|
|
18683
|
-
mode:
|
|
18859
|
+
var VideoCreativeSetup = z73.discriminatedUnion("mode", [
|
|
18860
|
+
z73.object({
|
|
18861
|
+
mode: z73.literal("automatic").describe('S\xF3lo cuando el usuario pidi\xF3 expl\xEDcitamente "decide todo".')
|
|
18684
18862
|
}).strict(),
|
|
18685
|
-
|
|
18686
|
-
mode:
|
|
18863
|
+
z73.object({
|
|
18864
|
+
mode: z73.literal("guided"),
|
|
18687
18865
|
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.'),
|
|
18688
|
-
buyerPersona:
|
|
18866
|
+
buyerPersona: z73.string().trim().min(1).max(360),
|
|
18689
18867
|
presenter: VideoPresenter,
|
|
18690
|
-
creativeDirection:
|
|
18868
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
18691
18869
|
}).strict()
|
|
18692
18870
|
]);
|
|
18693
|
-
var VideoInput =
|
|
18871
|
+
var VideoInput = z73.object({
|
|
18694
18872
|
images: CreativeRefs.images.optional(),
|
|
18695
18873
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18696
|
-
title:
|
|
18697
|
-
primaryAngle:
|
|
18874
|
+
title: z73.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
18875
|
+
primaryAngle: z73.string().min(1).describe('\xC1ngulo de venta principal (frase del beneficio). Ej. "Reduce arrugas en 14 d\xEDas" o "Para quienes odian las cremas grasosas".'),
|
|
18698
18876
|
language: CreativeRefs.language,
|
|
18699
18877
|
country: CreativeRefs.country,
|
|
18700
|
-
aspectRatio:
|
|
18878
|
+
aspectRatio: z73.enum([
|
|
18701
18879
|
"9:16",
|
|
18702
18880
|
"16:9",
|
|
18703
18881
|
"Auto"
|
|
18704
18882
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
18705
|
-
durationSeconds:
|
|
18706
|
-
videoAngleCount:
|
|
18883
|
+
durationSeconds: z73.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
|
|
18884
|
+
videoAngleCount: z73.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
|
|
18707
18885
|
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.'),
|
|
18708
18886
|
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."),
|
|
18709
18887
|
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.'),
|
|
18710
18888
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
18711
18889
|
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.'),
|
|
18712
|
-
features:
|
|
18890
|
+
features: z73.array(z73.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
18713
18891
|
price: CreativeRefs.price,
|
|
18714
18892
|
offer: CreativeRefs.offer,
|
|
18715
18893
|
productContext: CreativeRefs.productContext,
|
|
18716
18894
|
productLabel: CreativeRefs.productLabel,
|
|
18717
|
-
cta:
|
|
18718
|
-
scriptNotes:
|
|
18895
|
+
cta: z73.string().optional().describe('Opcional. Call-to-action final del video. Ej. "Compra ahora", "Pide el tuyo hoy", "Link en bio". Si se omite, la IA escribe uno.'),
|
|
18896
|
+
scriptNotes: z73.string().optional().describe('Opcional. Notas/restricciones para el guion (la IA las usa al redactar). Ej. "No mencionar la marca X", "Tono divertido, no cl\xEDnico", "Mencionar 2x1". NO es el guion literal: creativeSetup.mode=guided activa siempre la revisi\xF3n palabra-por-palabra con get_video_script / approve_video_script.'),
|
|
18719
18897
|
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.'),
|
|
18720
18898
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
18721
|
-
replicateWinnerWhenFound:
|
|
18899
|
+
replicateWinnerWhenFound: z73.boolean().optional().describe("Conserva la preferencia de copiar un ganador si existe. false permite estudiar el mercado sin reemplazar un \xE1ngulo por el anuncio ganador. No a\xF1adas una pregunta obligatoria para este campo."),
|
|
18722
18900
|
brandId: CreativeRefs.brandId
|
|
18723
18901
|
}).strict();
|
|
18724
18902
|
var FreeVideoQualityEnum = VideoQualityEnum;
|
|
@@ -18736,7 +18914,7 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
18736
18914
|
length: 29
|
|
18737
18915
|
}, (_, index) => index + 2)
|
|
18738
18916
|
};
|
|
18739
|
-
var FreeVideoModelIdEnum =
|
|
18917
|
+
var FreeVideoModelIdEnum = z73.enum([
|
|
18740
18918
|
"grok-imagine-video-1-5-preview",
|
|
18741
18919
|
"minimax-h3/reference-to-video",
|
|
18742
18920
|
"wan/3-0-video",
|
|
@@ -18747,70 +18925,70 @@ var FREE_SELECTABLE_MODEL_IDS = [
|
|
|
18747
18925
|
"minimax-h3/reference-to-video",
|
|
18748
18926
|
"wan/3-0-video"
|
|
18749
18927
|
];
|
|
18750
|
-
var FreeVideoInput =
|
|
18928
|
+
var FreeVideoInput = z73.object({
|
|
18751
18929
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
18752
|
-
rawPrompt:
|
|
18930
|
+
rawPrompt: z73.string().trim().min(1).max(2e3).describe("Prompt o guion exacto del video. Si activas subt\xEDtulos, este mismo texto se usa como guion de subt\xEDtulos."),
|
|
18753
18931
|
language: CreativeRefs.language,
|
|
18754
18932
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro (Wan).'),
|
|
18755
18933
|
// Retired in MCP 7.0.0 (Task 11): kept in the schema, accepted, and
|
|
18756
18934
|
// parsed ONLY so the handler can reject it with a message naming its
|
|
18757
18935
|
// replacement — dropping it silently would turn a caller's explicit
|
|
18758
18936
|
// Pro++ pick into a quiet fallback to Wan.
|
|
18759
|
-
freeProModel:
|
|
18937
|
+
freeProModel: z73.enum([
|
|
18760
18938
|
"wan",
|
|
18761
18939
|
"seedance"
|
|
18762
18940
|
]).optional().describe("ELIMINADO en MCP 7.0.0 \u2014 usa `modelId`. Enviar este campo produce un error."),
|
|
18763
18941
|
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.'),
|
|
18764
|
-
durationSeconds:
|
|
18942
|
+
durationSeconds: z73.number().int().min(2).max(30).describe("Duraci\xF3n exacta. Econ\xF3mico: 6, 8, 10 o 15s; Medio: enteros de 4 a 15s; Pro Wan: 2 a 30s; Pro++ Seedance: 4 a 30s."),
|
|
18765
18943
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
18766
|
-
generateAiMusic:
|
|
18767
|
-
addSubtitles:
|
|
18768
|
-
idempotencyKey:
|
|
18944
|
+
generateAiMusic: z73.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
18945
|
+
addSubtitles: z73.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
18946
|
+
idempotencyKey: z73.string().uuid().optional().describe("Opcional. UUID para reintentar exactamente esta misma solicitud sin crear ni cobrar otro video. Reutiliza el mismo valor si el cliente no recibi\xF3 la respuesta.")
|
|
18769
18947
|
}).strict();
|
|
18770
18948
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
18771
|
-
var ImageCreativeSetup =
|
|
18772
|
-
|
|
18773
|
-
mode:
|
|
18949
|
+
var ImageCreativeSetup = z73.discriminatedUnion("mode", [
|
|
18950
|
+
z73.object({
|
|
18951
|
+
mode: z73.literal("automatic")
|
|
18774
18952
|
}).strict(),
|
|
18775
|
-
|
|
18776
|
-
mode:
|
|
18777
|
-
creativeArchetype:
|
|
18953
|
+
z73.object({
|
|
18954
|
+
mode: z73.literal("guided"),
|
|
18955
|
+
creativeArchetype: z73.union([
|
|
18778
18956
|
ImageCreativeArchetypeEnum,
|
|
18779
|
-
|
|
18957
|
+
z73.literal("ai_decides")
|
|
18780
18958
|
]),
|
|
18781
|
-
visualTreatment:
|
|
18959
|
+
visualTreatment: z73.union([
|
|
18782
18960
|
ImageCreativeVisualTreatmentEnum,
|
|
18783
|
-
|
|
18961
|
+
z73.literal("ai_decides")
|
|
18784
18962
|
]),
|
|
18785
18963
|
aspectRatio: ImageCreativeAspectRatioEnum,
|
|
18786
|
-
nVariants:
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18964
|
+
nVariants: z73.union([
|
|
18965
|
+
z73.literal(1),
|
|
18966
|
+
z73.literal(2),
|
|
18967
|
+
z73.literal(3),
|
|
18968
|
+
z73.literal(4),
|
|
18969
|
+
z73.literal(6)
|
|
18792
18970
|
]),
|
|
18793
|
-
imageModel:
|
|
18971
|
+
imageModel: z73.enum([
|
|
18794
18972
|
"gpt-image-2-5:1k",
|
|
18795
18973
|
"gpt-image-2-5:2k",
|
|
18796
18974
|
"gpt-image-2:1k",
|
|
18797
18975
|
"gpt-image-2:2k"
|
|
18798
18976
|
]),
|
|
18799
|
-
styleMix:
|
|
18800
|
-
generateAdCopy:
|
|
18801
|
-
competitorScanEnabled:
|
|
18802
|
-
productContext:
|
|
18803
|
-
creativeDirection:
|
|
18804
|
-
brandColors:
|
|
18805
|
-
headline:
|
|
18806
|
-
subheadline:
|
|
18977
|
+
styleMix: z73.boolean().nullable().describe("Decisi\xF3n s\xF3lo para 2\u20134 variantes. Usa null para 1 o 6, cuando la UI no hace esta pregunta."),
|
|
18978
|
+
generateAdCopy: z73.boolean(),
|
|
18979
|
+
competitorScanEnabled: z73.boolean(),
|
|
18980
|
+
productContext: z73.string().trim().min(1).max(3e3).nullable(),
|
|
18981
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable(),
|
|
18982
|
+
brandColors: z73.string().trim().min(1).max(240).nullable().describe('Colores en lenguaje natural, igual que en el chat web. Ej. "Azul y Dorado". null significa sin colores espec\xEDficos.'),
|
|
18983
|
+
headline: z73.string().trim().min(1).max(120).nullable(),
|
|
18984
|
+
subheadline: z73.string().trim().min(1).max(160).nullable()
|
|
18807
18985
|
}).strict()
|
|
18808
18986
|
]).superRefine((setup, context) => {
|
|
18809
18987
|
if (setup.mode !== "guided") return;
|
|
18810
18988
|
const needsStyleMix = setup.nVariants >= 2 && setup.nVariants <= 4;
|
|
18811
18989
|
if (needsStyleMix && setup.styleMix === null) {
|
|
18812
18990
|
context.addIssue({
|
|
18813
|
-
code:
|
|
18991
|
+
code: z73.ZodIssueCode.custom,
|
|
18814
18992
|
path: [
|
|
18815
18993
|
"styleMix"
|
|
18816
18994
|
],
|
|
@@ -18819,7 +18997,7 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18819
18997
|
}
|
|
18820
18998
|
if (!needsStyleMix && setup.styleMix !== null) {
|
|
18821
18999
|
context.addIssue({
|
|
18822
|
-
code:
|
|
19000
|
+
code: z73.ZodIssueCode.custom,
|
|
18823
19001
|
path: [
|
|
18824
19002
|
"styleMix"
|
|
18825
19003
|
],
|
|
@@ -18828,7 +19006,7 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18828
19006
|
}
|
|
18829
19007
|
if ((setup.imageModel === "gpt-image-2:2k" || setup.imageModel === "gpt-image-2-5:2k") && setup.aspectRatio === "4:5") {
|
|
18830
19008
|
context.addIssue({
|
|
18831
|
-
code:
|
|
19009
|
+
code: z73.ZodIssueCode.custom,
|
|
18832
19010
|
path: [
|
|
18833
19011
|
"aspectRatio"
|
|
18834
19012
|
],
|
|
@@ -18836,53 +19014,53 @@ var ImageCreativeSetup = z72.discriminatedUnion("mode", [
|
|
|
18836
19014
|
});
|
|
18837
19015
|
}
|
|
18838
19016
|
});
|
|
18839
|
-
var LandingCreativeSetup =
|
|
18840
|
-
|
|
18841
|
-
mode:
|
|
19017
|
+
var LandingCreativeSetup = z73.discriminatedUnion("mode", [
|
|
19018
|
+
z73.object({
|
|
19019
|
+
mode: z73.literal("automatic")
|
|
18842
19020
|
}).strict(),
|
|
18843
|
-
|
|
18844
|
-
mode:
|
|
19021
|
+
z73.object({
|
|
19022
|
+
mode: z73.literal("guided"),
|
|
18845
19023
|
landingStrategy: LandingStrategyEnum,
|
|
18846
19024
|
landingImageFormat: LandingImageFormatEnum,
|
|
18847
|
-
competitorScanEnabled:
|
|
18848
|
-
paymentMethods:
|
|
18849
|
-
productContext:
|
|
18850
|
-
creativeDirection:
|
|
18851
|
-
headline:
|
|
18852
|
-
subheadline:
|
|
19025
|
+
competitorScanEnabled: z73.boolean(),
|
|
19026
|
+
paymentMethods: z73.string().trim().min(1).max(240).nullable(),
|
|
19027
|
+
productContext: z73.string().trim().min(1).max(3e3).nullable(),
|
|
19028
|
+
creativeDirection: z73.string().trim().min(1).max(500).nullable(),
|
|
19029
|
+
headline: z73.string().trim().min(1).max(120).nullable(),
|
|
19030
|
+
subheadline: z73.string().trim().min(1).max(160).nullable()
|
|
18853
19031
|
}).strict()
|
|
18854
19032
|
]);
|
|
18855
|
-
var ImageInput =
|
|
19033
|
+
var ImageInput = z73.object({
|
|
18856
19034
|
images: CreativeRefs.images.optional(),
|
|
18857
19035
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18858
|
-
productTitle:
|
|
18859
|
-
primaryAngle:
|
|
19036
|
+
productTitle: z73.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
19037
|
+
primaryAngle: z73.string().min(1).optional().describe('Opcional. \xC1ngulo de venta principal. Si se omite, ProductMaker lo genera y creativeSetup.mode="guided" lo muestra para revisi\xF3n antes de crear las im\xE1genes.'),
|
|
18860
19038
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
18861
19039
|
language: CreativeRefs.language,
|
|
18862
19040
|
country: CreativeRefs.country,
|
|
18863
19041
|
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."),
|
|
18864
19042
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
18865
|
-
features:
|
|
19043
|
+
features: z73.array(z73.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
18866
19044
|
price: CreativeRefs.price,
|
|
18867
|
-
omitPrice:
|
|
19045
|
+
omitPrice: z73.boolean().optional().describe("Pon true \xFAnicamente cuando el usuario pida expl\xEDcitamente una imagen sin precio. Evita que el backend reutilice un precio extra\xEDdo del producto. No lo combines con price ni compareAtPrice."),
|
|
18868
19046
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
18869
19047
|
offer: CreativeRefs.offer,
|
|
18870
19048
|
productLabel: CreativeRefs.productLabel,
|
|
18871
19049
|
isCombo: CreativeRefs.isCombo,
|
|
18872
19050
|
brandId: CreativeRefs.brandId
|
|
18873
19051
|
});
|
|
18874
|
-
var EditImageCreativeInput =
|
|
18875
|
-
taskId:
|
|
18876
|
-
variantIndex:
|
|
18877
|
-
instruction:
|
|
19052
|
+
var EditImageCreativeInput = z73.object({
|
|
19053
|
+
taskId: z73.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
19054
|
+
variantIndex: z73.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
19055
|
+
instruction: z73.string().min(1).max(1e3).describe('Qu\xE9 cambiar en esa imagen. Ej. "quita el badge de env\xEDo gratis", "cambia el fondo a blanco".')
|
|
18878
19056
|
});
|
|
18879
|
-
var LandingInput =
|
|
19057
|
+
var LandingInput = z73.object({
|
|
18880
19058
|
images: CreativeRefs.images.optional(),
|
|
18881
19059
|
winnerReference: WinnerReferenceInput.optional().describe(WINNER_IMAGE_CHOICE_GUIDANCE),
|
|
18882
19060
|
language: CreativeRefs.language,
|
|
18883
19061
|
country: CreativeRefs.country,
|
|
18884
19062
|
creativeSetup: LandingCreativeSetup.describe("Configuraci\xF3n obligatoria de landing cl\xE1sica equivalente al wizard web. No expone landing editable/code mientras siga siendo admin-only."),
|
|
18885
|
-
salesAngle:
|
|
19063
|
+
salesAngle: z73.string().optional().describe('Opcional. \xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas". Si se omite, la IA lo deduce de la imagen.'),
|
|
18886
19064
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
18887
19065
|
price: CreativeRefs.price,
|
|
18888
19066
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -19144,10 +19322,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
19144
19322
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
19145
19323
|
|
|
19146
19324
|
// src/tools/creative-variants.ts
|
|
19147
|
-
import { z as
|
|
19325
|
+
import { z as z74 } from "zod";
|
|
19148
19326
|
var estimateCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("estimate_creative_variant");
|
|
19149
19327
|
var createCreativeVariantGuidance = getProductMakerCapabilityModelGuidance("create_creative_variant");
|
|
19150
|
-
var LandingSectionKeyEnum =
|
|
19328
|
+
var LandingSectionKeyEnum = z74.enum([
|
|
19151
19329
|
"problem_hook",
|
|
19152
19330
|
"problem_cost",
|
|
19153
19331
|
"solution_mechanism",
|
|
@@ -19187,24 +19365,24 @@ var LandingSectionKeyEnum = z73.enum([
|
|
|
19187
19365
|
"lifestyle_fit",
|
|
19188
19366
|
"join_lifestyle"
|
|
19189
19367
|
]);
|
|
19190
|
-
var CreativeVariantKindEnum =
|
|
19368
|
+
var CreativeVariantKindEnum = z74.enum([
|
|
19191
19369
|
"video",
|
|
19192
19370
|
"image",
|
|
19193
19371
|
"landing"
|
|
19194
19372
|
]);
|
|
19195
|
-
var EstimateCreativeVariantInputBase =
|
|
19196
|
-
sourceTaskId:
|
|
19373
|
+
var EstimateCreativeVariantInputBase = z74.object({
|
|
19374
|
+
sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
|
|
19197
19375
|
kind: CreativeVariantKindEnum,
|
|
19198
19376
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
19199
19377
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
19200
|
-
nVariants:
|
|
19378
|
+
nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19201
19379
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
19202
|
-
instructions:
|
|
19380
|
+
instructions: z74.string().trim().min(1).max(2e3).optional().describe("Opcional para landing. Si se env\xEDa sin sectionKey, el estimado suma la clasificaci\xF3n pagada con IA.")
|
|
19203
19381
|
}).strict();
|
|
19204
19382
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19205
19383
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
19206
19384
|
ctx.addIssue({
|
|
19207
|
-
code:
|
|
19385
|
+
code: z74.ZodIssueCode.custom,
|
|
19208
19386
|
path: [
|
|
19209
19387
|
"nVariants"
|
|
19210
19388
|
],
|
|
@@ -19214,7 +19392,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19214
19392
|
if (input.kind !== "video") {
|
|
19215
19393
|
if (input.videoPreset !== void 0) {
|
|
19216
19394
|
ctx.addIssue({
|
|
19217
|
-
code:
|
|
19395
|
+
code: z74.ZodIssueCode.custom,
|
|
19218
19396
|
path: [
|
|
19219
19397
|
"videoPreset"
|
|
19220
19398
|
],
|
|
@@ -19223,7 +19401,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19223
19401
|
}
|
|
19224
19402
|
if (input.videoResolution !== void 0) {
|
|
19225
19403
|
ctx.addIssue({
|
|
19226
|
-
code:
|
|
19404
|
+
code: z74.ZodIssueCode.custom,
|
|
19227
19405
|
path: [
|
|
19228
19406
|
"videoResolution"
|
|
19229
19407
|
],
|
|
@@ -19233,7 +19411,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19233
19411
|
}
|
|
19234
19412
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
19235
19413
|
ctx.addIssue({
|
|
19236
|
-
code:
|
|
19414
|
+
code: z74.ZodIssueCode.custom,
|
|
19237
19415
|
path: [
|
|
19238
19416
|
"nVariants"
|
|
19239
19417
|
],
|
|
@@ -19243,7 +19421,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19243
19421
|
if (input.kind !== "landing") {
|
|
19244
19422
|
if (input.sectionKey !== void 0) {
|
|
19245
19423
|
ctx.addIssue({
|
|
19246
|
-
code:
|
|
19424
|
+
code: z74.ZodIssueCode.custom,
|
|
19247
19425
|
path: [
|
|
19248
19426
|
"sectionKey"
|
|
19249
19427
|
],
|
|
@@ -19252,7 +19430,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19252
19430
|
}
|
|
19253
19431
|
if (input.instructions !== void 0) {
|
|
19254
19432
|
ctx.addIssue({
|
|
19255
|
-
code:
|
|
19433
|
+
code: z74.ZodIssueCode.custom,
|
|
19256
19434
|
path: [
|
|
19257
19435
|
"instructions"
|
|
19258
19436
|
],
|
|
@@ -19261,31 +19439,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
19261
19439
|
}
|
|
19262
19440
|
}
|
|
19263
19441
|
});
|
|
19264
|
-
var CreateCreativeVariantInputBase =
|
|
19265
|
-
sourceTaskId:
|
|
19442
|
+
var CreateCreativeVariantInputBase = z74.object({
|
|
19443
|
+
sourceTaskId: z74.string().uuid().describe("ID de la tarea original completada."),
|
|
19266
19444
|
kind: CreativeVariantKindEnum,
|
|
19267
|
-
confirm:
|
|
19268
|
-
clientRequestId:
|
|
19269
|
-
angle:
|
|
19270
|
-
buyerPersona:
|
|
19271
|
-
scriptNotes:
|
|
19272
|
-
creativeDirection:
|
|
19445
|
+
confirm: z74.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
19446
|
+
clientRequestId: z74.string().uuid().describe("UUID estable y obligatorio para esta intenci\xF3n. Reutil\xEDzalo ante timeouts o transporte ambiguo. Si la API devuelve status=error, una nueva generaci\xF3n exige otra confirmaci\xF3n y un UUID nuevo."),
|
|
19447
|
+
angle: z74.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
19448
|
+
buyerPersona: z74.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
19449
|
+
scriptNotes: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
19450
|
+
creativeDirection: z74.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
19273
19451
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
19274
19452
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
19275
|
-
generateAiMusic:
|
|
19276
|
-
nVariants:
|
|
19453
|
+
generateAiMusic: z74.boolean().optional().describe("Opcional para video."),
|
|
19454
|
+
nVariants: z74.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
19277
19455
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
19278
19456
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
19279
19457
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
19280
19458
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
19281
|
-
styleMix:
|
|
19459
|
+
styleMix: z74.boolean().optional().describe("Opcional para imagen."),
|
|
19282
19460
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
19283
|
-
instructions:
|
|
19461
|
+
instructions: z74.string().trim().min(1).max(2e3).optional().describe("Solicitud libre para una nueva secci\xF3n de landing. La IA la clasifica si no env\xEDas sectionKey.")
|
|
19284
19462
|
}).strict();
|
|
19285
19463
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
19286
19464
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
19287
19465
|
ctx.addIssue({
|
|
19288
|
-
code:
|
|
19466
|
+
code: z74.ZodIssueCode.custom,
|
|
19289
19467
|
path: [
|
|
19290
19468
|
"angle"
|
|
19291
19469
|
],
|
|
@@ -19294,7 +19472,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19294
19472
|
}
|
|
19295
19473
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
19296
19474
|
ctx.addIssue({
|
|
19297
|
-
code:
|
|
19475
|
+
code: z74.ZodIssueCode.custom,
|
|
19298
19476
|
path: [
|
|
19299
19477
|
"instructions"
|
|
19300
19478
|
],
|
|
@@ -19340,7 +19518,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
19340
19518
|
for (const field of fieldsByKind[input.kind]) {
|
|
19341
19519
|
if (input[field] !== void 0) {
|
|
19342
19520
|
ctx.addIssue({
|
|
19343
|
-
code:
|
|
19521
|
+
code: z74.ZodIssueCode.custom,
|
|
19344
19522
|
path: [
|
|
19345
19523
|
field
|
|
19346
19524
|
],
|
|
@@ -19457,32 +19635,32 @@ function registerCreativeVariantTools(server, api) {
|
|
|
19457
19635
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
19458
19636
|
|
|
19459
19637
|
// src/tools/script-review.ts
|
|
19460
|
-
import { z as
|
|
19638
|
+
import { z as z75 } from "zod";
|
|
19461
19639
|
var getVideoScriptGuidance = getProductMakerCapabilityModelGuidance("get_video_script");
|
|
19462
19640
|
var regenerateVideoScriptGuidance = getProductMakerCapabilityModelGuidance("regenerate_video_script");
|
|
19463
19641
|
var approveVideoScriptGuidance = getProductMakerCapabilityModelGuidance("approve_video_script");
|
|
19464
|
-
var GetVideoScriptInput =
|
|
19465
|
-
taskId:
|
|
19466
|
-
angleKey:
|
|
19642
|
+
var GetVideoScriptInput = z75.object({
|
|
19643
|
+
taskId: z75.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
19644
|
+
angleKey: z75.string().min(1).optional().describe('Clave del \xE1ngulo cuyo guion se quiere leer (formato "angle_0", "angle_1", ...). REQUERIDO para tareas multi-angle: si se omite, el backend resuelve a "angle_0" LITERAL (no "el primer pendiente"), as\xED que en multi-angle donde angle_0 ya est\xE9 aprobado/saltado obtendr\xEDas status="approved" y nunca alcanzar\xEDas el \xE1ngulo realmente pendiente. Para single-angle puede omitirse.')
|
|
19467
19645
|
}).strict();
|
|
19468
19646
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
19469
19647
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
19470
|
-
var ApproveSceneEdit =
|
|
19471
|
-
index:
|
|
19472
|
-
dialogue:
|
|
19648
|
+
var ApproveSceneEdit = z75.object({
|
|
19649
|
+
index: z75.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
19650
|
+
dialogue: z75.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
19473
19651
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
19474
19652
|
}).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.")
|
|
19475
19653
|
}).strict();
|
|
19476
|
-
var ApproveVideoScriptInput =
|
|
19477
|
-
taskId:
|
|
19478
|
-
angleKey:
|
|
19479
|
-
scenes:
|
|
19654
|
+
var ApproveVideoScriptInput = z75.object({
|
|
19655
|
+
taskId: z75.string().min(1).describe("ID de la tarea."),
|
|
19656
|
+
angleKey: z75.string().trim().min(1).max(120).optional().describe('Mismo angleKey usado en get_video_script. REQUERIDO en multi-angle (si se omite el backend resuelve a "angle_0" literal). En single-angle puede omitirse.'),
|
|
19657
|
+
scenes: z75.array(ApproveSceneEdit).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES2).describe("Escenas con los di\xE1logos finales. El backend mergea por `index` \u2014 las escenas NO incluidas conservan el di\xE1logo original. Debe haber entre 1 y 50 entradas. Para cada entrada que mandes con un dialogue distinto del original, el backend valida minWords \u2264 words \u2264 maxWords y rechaza con 400 si te sales del rango.")
|
|
19480
19658
|
}).strict();
|
|
19481
|
-
var RegenerateVideoScriptInput =
|
|
19482
|
-
taskId:
|
|
19483
|
-
angleKey:
|
|
19659
|
+
var RegenerateVideoScriptInput = z75.object({
|
|
19660
|
+
taskId: z75.string().min(1).describe("ID de la tarea."),
|
|
19661
|
+
angleKey: z75.string().min(1).describe('Clave del \xE1ngulo a regenerar. Single-angle: pasa "angle_0". Multi-angle: el mismo que devuelve get_video_script. NO se puede omitir \u2014 el backend lo exige siempre.'),
|
|
19484
19662
|
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).'),
|
|
19485
|
-
narrativeSelection:
|
|
19663
|
+
narrativeSelection: z75.enum([
|
|
19486
19664
|
"market",
|
|
19487
19665
|
"guided"
|
|
19488
19666
|
]).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.")
|
|
@@ -19563,14 +19741,14 @@ function registerScriptReviewTools(server, api) {
|
|
|
19563
19741
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
19564
19742
|
|
|
19565
19743
|
// src/tools/connections.ts
|
|
19566
|
-
import { z as
|
|
19744
|
+
import { z as z76 } from "zod";
|
|
19567
19745
|
var listShopifyShopsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_shops");
|
|
19568
19746
|
var listShopifyProductsGuidance = getProductMakerCapabilityModelGuidance("list_shopify_products");
|
|
19569
19747
|
var listMetaAdAccountsGuidance = getProductMakerCapabilityModelGuidance("list_meta_ad_accounts");
|
|
19570
19748
|
var listMetaDestinationsGuidance = getProductMakerCapabilityModelGuidance("list_meta_destinations");
|
|
19571
19749
|
var listTikTokAdvertisersGuidance = getProductMakerCapabilityModelGuidance("list_tiktok_advertisers");
|
|
19572
19750
|
function registerConnectionTools(server, api) {
|
|
19573
|
-
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.",
|
|
19751
|
+
server.tool("list_shopify_shops", listShopifyShopsGuidance.summary + " Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z76.object({}).shape, READS_INTERNAL, async () => {
|
|
19574
19752
|
try {
|
|
19575
19753
|
const r = await api.getJson("/v1/shopify/shops");
|
|
19576
19754
|
return asText(r);
|
|
@@ -19578,10 +19756,10 @@ function registerConnectionTools(server, api) {
|
|
|
19578
19756
|
throw translateError(e);
|
|
19579
19757
|
}
|
|
19580
19758
|
});
|
|
19581
|
-
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.',
|
|
19582
|
-
shopDomain:
|
|
19583
|
-
query:
|
|
19584
|
-
taskId:
|
|
19759
|
+
server.tool("list_shopify_products", listShopifyProductsGuidance.summary + ' Usa el `id` devuelto junto con `publicationMode="existing"` en `publish_to_shopify`. Si `taskId` se proporciona, la respuesta tambi\xE9n indica el producto publicado actualmente para esa tarea y tienda. No modifica Shopify.', z76.object({
|
|
19760
|
+
shopDomain: z76.string().min(3).max(120),
|
|
19761
|
+
query: z76.string().trim().max(120).optional(),
|
|
19762
|
+
taskId: z76.string().uuid().optional()
|
|
19585
19763
|
}).shape, READS_EXTERNAL, async ({ shopDomain, query, taskId }) => {
|
|
19586
19764
|
try {
|
|
19587
19765
|
const params = new URLSearchParams({
|
|
@@ -19595,7 +19773,7 @@ function registerConnectionTools(server, api) {
|
|
|
19595
19773
|
throw translateError(e);
|
|
19596
19774
|
}
|
|
19597
19775
|
});
|
|
19598
|
-
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.",
|
|
19776
|
+
server.tool("list_meta_ad_accounts", listMetaAdAccountsGuidance.summary + " Para publicar, prefiere `list_meta_destinations`, que tambi\xE9n devuelve el portfolio y las p\xE1ginas disponibles. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
|
|
19599
19777
|
try {
|
|
19600
19778
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
19601
19779
|
return asText(r);
|
|
@@ -19605,7 +19783,7 @@ function registerConnectionTools(server, api) {
|
|
|
19605
19783
|
});
|
|
19606
19784
|
server.registerTool("list_meta_destinations", {
|
|
19607
19785
|
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.",
|
|
19608
|
-
inputSchema:
|
|
19786
|
+
inputSchema: z76.object({}).shape,
|
|
19609
19787
|
annotations: READS_EXTERNAL,
|
|
19610
19788
|
_meta: {
|
|
19611
19789
|
"openai/widgetAccessible": true
|
|
@@ -19618,7 +19796,7 @@ function registerConnectionTools(server, api) {
|
|
|
19618
19796
|
throw translateError(e);
|
|
19619
19797
|
}
|
|
19620
19798
|
});
|
|
19621
|
-
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
19799
|
+
server.tool("list_tiktok_advertisers", listTikTokAdvertisersGuidance.summary + " Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z76.object({}).shape, READS_EXTERNAL, async () => {
|
|
19622
19800
|
try {
|
|
19623
19801
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
19624
19802
|
return asText(r);
|
|
@@ -19630,10 +19808,10 @@ function registerConnectionTools(server, api) {
|
|
|
19630
19808
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
19631
19809
|
|
|
19632
19810
|
// src/tools/actors.ts
|
|
19633
|
-
import { z as
|
|
19811
|
+
import { z as z77 } from "zod";
|
|
19634
19812
|
var listActorsGuidance = getProductMakerCapabilityModelGuidance("list_actors");
|
|
19635
19813
|
function registerActorTools(server, api) {
|
|
19636
|
-
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.",
|
|
19814
|
+
server.tool("list_actors", listActorsGuidance.summary + " Devuelve id, nombre, descripci\xF3n, g\xE9nero y voz. Usa el `id` como `actorId` al crear o editar una tarea. Solo aparecen los personajes listos para usar; si la lista est\xE1 vac\xEDa, dile al usuario que cree uno en productmaker.app antes de intentar asignarlo. No modifica nada.", z77.object({}).shape, READS_INTERNAL, async () => {
|
|
19637
19815
|
try {
|
|
19638
19816
|
const rows = await api.getJson("/v1/actors");
|
|
19639
19817
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -19654,7 +19832,7 @@ function registerActorTools(server, api) {
|
|
|
19654
19832
|
__name(registerActorTools, "registerActorTools");
|
|
19655
19833
|
|
|
19656
19834
|
// src/tools/publish.ts
|
|
19657
|
-
import { z as
|
|
19835
|
+
import { z as z78 } from "zod";
|
|
19658
19836
|
|
|
19659
19837
|
// src/tools/stable-uuid.ts
|
|
19660
19838
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -19726,40 +19904,40 @@ var publishToShopifyGuidance = getProductMakerCapabilityModelGuidance("publish_t
|
|
|
19726
19904
|
var publishToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_to_meta");
|
|
19727
19905
|
var publishCreativesToMetaGuidance = getProductMakerCapabilityModelGuidance("publish_creatives_to_meta");
|
|
19728
19906
|
var publishToTikTokGuidance = getProductMakerCapabilityModelGuidance("publish_to_tiktok");
|
|
19729
|
-
var ShopifyInput =
|
|
19730
|
-
taskId:
|
|
19731
|
-
shopDomain:
|
|
19907
|
+
var ShopifyInput = z78.object({
|
|
19908
|
+
taskId: z78.string().min(1),
|
|
19909
|
+
shopDomain: z78.string().min(1),
|
|
19732
19910
|
/** Override: number of landing images to include. Default = ALL images the
|
|
19733
19911
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
19734
19912
|
* generously here; the backend validates each index against
|
|
19735
19913
|
* landing.images.length and rejects out-of-range. */
|
|
19736
|
-
numLandingImages:
|
|
19737
|
-
variantIndex:
|
|
19914
|
+
numLandingImages: z78.number().int().min(1).max(20).optional(),
|
|
19915
|
+
variantIndex: z78.number().int().min(0).optional(),
|
|
19738
19916
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
19739
19917
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
19740
19918
|
* a single-option product page. Defaults to false. */
|
|
19741
|
-
showVariantPicker:
|
|
19919
|
+
showVariantPicker: z78.boolean().optional(),
|
|
19742
19920
|
/** Default `auto` updates the product previously published for this task and
|
|
19743
19921
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
19744
19922
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
19745
|
-
publicationMode:
|
|
19923
|
+
publicationMode: z78.enum([
|
|
19746
19924
|
"auto",
|
|
19747
19925
|
"existing",
|
|
19748
19926
|
"new"
|
|
19749
19927
|
]).optional(),
|
|
19750
19928
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
19751
19929
|
* publicationMode is `existing`. */
|
|
19752
|
-
targetProductId:
|
|
19930
|
+
targetProductId: z78.string().trim().min(1).max(300).optional(),
|
|
19753
19931
|
/** Add an announcement bar text above add-to-cart (optional). */
|
|
19754
|
-
announcementBarEnabled:
|
|
19755
|
-
announcementBarText:
|
|
19932
|
+
announcementBarEnabled: z78.boolean().optional(),
|
|
19933
|
+
announcementBarText: z78.string().trim().min(1).max(SHOPIFY_ANNOUNCEMENT_BAR_MAX_LENGTH).optional(),
|
|
19756
19934
|
commerceCorrection: PublishCommerceCorrectionSchema.optional().describe("Complete seller-confirmed commerce values, with the revision and fingerprint returned in recovery. Never invent missing prices or convert currency."),
|
|
19757
|
-
confirmed:
|
|
19935
|
+
confirmed: z78.boolean().optional().describe("Required as true only when submitting commerceCorrection, after showing its values and obtaining explicit seller confirmation.")
|
|
19758
19936
|
});
|
|
19759
19937
|
var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value, ctx) => {
|
|
19760
19938
|
if (value.commerceCorrection && value.confirmed !== true) {
|
|
19761
19939
|
ctx.addIssue({
|
|
19762
|
-
code:
|
|
19940
|
+
code: z78.ZodIssueCode.custom,
|
|
19763
19941
|
path: [
|
|
19764
19942
|
"confirmed"
|
|
19765
19943
|
],
|
|
@@ -19768,7 +19946,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19768
19946
|
}
|
|
19769
19947
|
if (value.announcementBarEnabled && !value.announcementBarText) {
|
|
19770
19948
|
ctx.addIssue({
|
|
19771
|
-
code:
|
|
19949
|
+
code: z78.ZodIssueCode.custom,
|
|
19772
19950
|
path: [
|
|
19773
19951
|
"announcementBarText"
|
|
19774
19952
|
],
|
|
@@ -19777,7 +19955,7 @@ var ShopifyInputWithAnnouncementBarValidation = ShopifyInput.superRefine((value,
|
|
|
19777
19955
|
}
|
|
19778
19956
|
if (!value.announcementBarEnabled && value.announcementBarText) {
|
|
19779
19957
|
ctx.addIssue({
|
|
19780
|
-
code:
|
|
19958
|
+
code: z78.ZodIssueCode.custom,
|
|
19781
19959
|
path: [
|
|
19782
19960
|
"announcementBarText"
|
|
19783
19961
|
],
|
|
@@ -19791,91 +19969,91 @@ function parseShopifyInput(rawInput) {
|
|
|
19791
19969
|
return parsed.data;
|
|
19792
19970
|
}
|
|
19793
19971
|
__name(parseShopifyInput, "parseShopifyInput");
|
|
19794
|
-
var McpCampaignConfig =
|
|
19972
|
+
var McpCampaignConfig = z78.object({
|
|
19795
19973
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
19796
19974
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
19797
19975
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
19798
|
-
dailyBudgetUsd:
|
|
19976
|
+
dailyBudgetUsd: z78.number().positive().optional(),
|
|
19799
19977
|
/** ISO-3166-1 alpha-2 country codes or resolvable names (CountryIso2Schema
|
|
19800
19978
|
* normalizes at validation). Meta accepts max 1 (single-country ad set).
|
|
19801
19979
|
* TikTok takes only the first entry. */
|
|
19802
|
-
targetCountries:
|
|
19803
|
-
campaignName:
|
|
19980
|
+
targetCountries: z78.array(CountryIso2Schema).max(1).optional(),
|
|
19981
|
+
campaignName: z78.string().trim().min(1).max(100).optional()
|
|
19804
19982
|
});
|
|
19805
19983
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
19806
|
-
var MetaInput =
|
|
19807
|
-
taskId:
|
|
19984
|
+
var MetaInput = z78.object({
|
|
19985
|
+
taskId: z78.string().min(1),
|
|
19808
19986
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
19809
|
-
portfolioId:
|
|
19987
|
+
portfolioId: z78.string().trim().min(1),
|
|
19810
19988
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
19811
|
-
pageId:
|
|
19989
|
+
pageId: z78.string().trim().min(1),
|
|
19812
19990
|
adAccountId: McpAdAccountId,
|
|
19813
|
-
pixelId:
|
|
19814
|
-
landingUrl:
|
|
19991
|
+
pixelId: z78.string().min(1).optional(),
|
|
19992
|
+
landingUrl: z78.string().url().optional(),
|
|
19815
19993
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
19816
19994
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
19817
|
-
angleIndexes:
|
|
19995
|
+
angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
|
|
19818
19996
|
campaignConfig: McpCampaignConfig.optional(),
|
|
19819
19997
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
19820
19998
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
19821
19999
|
* (Meta's primary-text limit). */
|
|
19822
|
-
primaryText:
|
|
20000
|
+
primaryText: z78.string().trim().min(1).max(500).optional(),
|
|
19823
20001
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
19824
20002
|
* (wa.me) instead of a landing page. */
|
|
19825
|
-
phoneNumber:
|
|
20003
|
+
phoneNumber: z78.string().min(8).max(32).optional()
|
|
19826
20004
|
});
|
|
19827
|
-
var GroupedTaskSource =
|
|
19828
|
-
type:
|
|
19829
|
-
taskId:
|
|
19830
|
-
angleIndex:
|
|
19831
|
-
videoVariant:
|
|
20005
|
+
var GroupedTaskSource = z78.object({
|
|
20006
|
+
type: z78.literal("task"),
|
|
20007
|
+
taskId: z78.string().min(1),
|
|
20008
|
+
angleIndex: z78.number().int().min(0).optional(),
|
|
20009
|
+
videoVariant: z78.enum([
|
|
19832
20010
|
"with_subtitles",
|
|
19833
20011
|
"without_subtitles"
|
|
19834
20012
|
]).optional(),
|
|
19835
|
-
imageVariantIndex:
|
|
19836
|
-
});
|
|
19837
|
-
var GroupedMediaSource =
|
|
19838
|
-
type:
|
|
19839
|
-
url:
|
|
19840
|
-
path:
|
|
19841
|
-
thumbnailUrl:
|
|
19842
|
-
thumbnailPath:
|
|
20013
|
+
imageVariantIndex: z78.number().int().min(0).optional()
|
|
20014
|
+
});
|
|
20015
|
+
var GroupedMediaSource = z78.object({
|
|
20016
|
+
type: z78.literal("media"),
|
|
20017
|
+
url: z78.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_media_upload on the hosted MCP instead."),
|
|
20018
|
+
path: z78.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_media_upload and then use source.type="asset".'),
|
|
20019
|
+
thumbnailUrl: z78.string().url().optional(),
|
|
20020
|
+
thumbnailPath: z78.string().min(1).optional()
|
|
19843
20021
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
19844
20022
|
message: "media source needs exactly one of `url` or `path`"
|
|
19845
20023
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
19846
20024
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
19847
20025
|
});
|
|
19848
|
-
var GroupedUploadedAssetSource =
|
|
19849
|
-
type:
|
|
20026
|
+
var GroupedUploadedAssetSource = z78.object({
|
|
20027
|
+
type: z78.literal("asset"),
|
|
19850
20028
|
/** Returned by check_media_upload. ProductMaker resolves ownership server-side. */
|
|
19851
|
-
assetId:
|
|
19852
|
-
thumbnailAssetId:
|
|
20029
|
+
assetId: z78.string().uuid(),
|
|
20030
|
+
thumbnailAssetId: z78.string().uuid().optional()
|
|
19853
20031
|
});
|
|
19854
|
-
var GroupedCreative =
|
|
19855
|
-
type:
|
|
20032
|
+
var GroupedCreative = z78.object({
|
|
20033
|
+
type: z78.enum([
|
|
19856
20034
|
"image",
|
|
19857
20035
|
"video"
|
|
19858
20036
|
]),
|
|
19859
|
-
source:
|
|
20037
|
+
source: z78.union([
|
|
19860
20038
|
GroupedTaskSource,
|
|
19861
20039
|
GroupedMediaSource,
|
|
19862
20040
|
GroupedUploadedAssetSource
|
|
19863
20041
|
]),
|
|
19864
|
-
title:
|
|
19865
|
-
description:
|
|
20042
|
+
title: z78.string().max(120).optional(),
|
|
20043
|
+
description: z78.string().max(500).optional(),
|
|
19866
20044
|
cta: MetaCtaType.optional(),
|
|
19867
|
-
creativeId:
|
|
20045
|
+
creativeId: z78.string().min(1).optional()
|
|
19868
20046
|
});
|
|
19869
|
-
var GroupedCampaignConfigBase =
|
|
20047
|
+
var GroupedCampaignConfigBase = z78.object({
|
|
19870
20048
|
campaignType: MetaCampaignType.default("sales"),
|
|
19871
20049
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
19872
20050
|
budgetMode: MetaBudgetMode.optional(),
|
|
19873
|
-
campaignDailyBudget:
|
|
19874
|
-
adSets:
|
|
19875
|
-
tempId:
|
|
19876
|
-
name:
|
|
19877
|
-
dailyBudget:
|
|
19878
|
-
creativeIds:
|
|
20051
|
+
campaignDailyBudget: z78.number().int().positive().optional(),
|
|
20052
|
+
adSets: z78.array(z78.object({
|
|
20053
|
+
tempId: z78.string().min(1).max(80),
|
|
20054
|
+
name: z78.string().min(1).max(100),
|
|
20055
|
+
dailyBudget: z78.number().int().positive().optional(),
|
|
20056
|
+
creativeIds: z78.array(z78.string().min(1)).min(1)
|
|
19879
20057
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
19880
20058
|
/**
|
|
19881
20059
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -19883,17 +20061,17 @@ var GroupedCampaignConfigBase = z77.object({
|
|
|
19883
20061
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
19884
20062
|
* the API since #849 — unreachable from this tool.
|
|
19885
20063
|
*/
|
|
19886
|
-
destination:
|
|
19887
|
-
|
|
19888
|
-
type:
|
|
19889
|
-
landingUrl:
|
|
20064
|
+
destination: z78.discriminatedUnion("type", [
|
|
20065
|
+
z78.object({
|
|
20066
|
+
type: z78.literal("landing"),
|
|
20067
|
+
landingUrl: z78.string().url()
|
|
19890
20068
|
}),
|
|
19891
|
-
|
|
19892
|
-
type:
|
|
19893
|
-
phoneNumber:
|
|
20069
|
+
z78.object({
|
|
20070
|
+
type: z78.literal("whatsapp"),
|
|
20071
|
+
phoneNumber: z78.string().min(8).max(32)
|
|
19894
20072
|
})
|
|
19895
20073
|
]),
|
|
19896
|
-
saveAsDefault:
|
|
20074
|
+
saveAsDefault: z78.boolean().default(false),
|
|
19897
20075
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
19898
20076
|
});
|
|
19899
20077
|
function resolveBudgetMode(value) {
|
|
@@ -19907,7 +20085,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19907
20085
|
const budgetMode = resolveBudgetMode(value);
|
|
19908
20086
|
if (budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
19909
20087
|
ctx.addIssue({
|
|
19910
|
-
code:
|
|
20088
|
+
code: z78.ZodIssueCode.custom,
|
|
19911
20089
|
path: [
|
|
19912
20090
|
"campaignDailyBudget"
|
|
19913
20091
|
],
|
|
@@ -19918,7 +20096,7 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19918
20096
|
value.adSets.forEach((adSet, index) => {
|
|
19919
20097
|
if (adSet.dailyBudget === void 0) {
|
|
19920
20098
|
ctx.addIssue({
|
|
19921
|
-
code:
|
|
20099
|
+
code: z78.ZodIssueCode.custom,
|
|
19922
20100
|
path: [
|
|
19923
20101
|
"adSets",
|
|
19924
20102
|
index,
|
|
@@ -19933,28 +20111,28 @@ var GroupedCampaignConfig = GroupedCampaignConfigBase.superRefine((value, ctx) =
|
|
|
19933
20111
|
...value,
|
|
19934
20112
|
budgetMode: resolveBudgetMode(value)
|
|
19935
20113
|
}));
|
|
19936
|
-
var PublishCreativesToMetaInputBase =
|
|
19937
|
-
creatives:
|
|
20114
|
+
var PublishCreativesToMetaInputBase = z78.object({
|
|
20115
|
+
creatives: z78.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
19938
20116
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
19939
|
-
portfolioId:
|
|
20117
|
+
portfolioId: z78.string().trim().min(1),
|
|
19940
20118
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
19941
|
-
pageId:
|
|
20119
|
+
pageId: z78.string().trim().min(1),
|
|
19942
20120
|
adAccountId: McpAdAccountId,
|
|
19943
|
-
pixelId:
|
|
20121
|
+
pixelId: z78.string().min(1).optional(),
|
|
19944
20122
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
19945
20123
|
* superRefine below. Mirrors the API's `FacebookCreateCampaignFromTasksBodySchema`. */
|
|
19946
|
-
landingUrl:
|
|
20124
|
+
landingUrl: z78.string().url().optional(),
|
|
19947
20125
|
/** ISO-2 code or resolvable country name — mirrors the API contract
|
|
19948
20126
|
* (CountryIso2Schema), which normalizes names to alpha-2 at validation. */
|
|
19949
20127
|
targetCountry: CountryIso2Schema,
|
|
19950
|
-
campaignName:
|
|
20128
|
+
campaignName: z78.string().trim().min(1).max(100),
|
|
19951
20129
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
19952
20130
|
});
|
|
19953
20131
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
19954
20132
|
const destination = value.campaignConfig?.destination;
|
|
19955
20133
|
if (destination?.type !== "whatsapp" && destination?.type !== "landing" && !value.landingUrl) {
|
|
19956
20134
|
ctx.addIssue({
|
|
19957
|
-
code:
|
|
20135
|
+
code: z78.ZodIssueCode.custom,
|
|
19958
20136
|
path: [
|
|
19959
20137
|
"landingUrl"
|
|
19960
20138
|
],
|
|
@@ -19963,7 +20141,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
19963
20141
|
}
|
|
19964
20142
|
if (destination?.type === "landing" && value.landingUrl && destination.landingUrl !== value.landingUrl) {
|
|
19965
20143
|
ctx.addIssue({
|
|
19966
|
-
code:
|
|
20144
|
+
code: z78.ZodIssueCode.custom,
|
|
19967
20145
|
path: [
|
|
19968
20146
|
"campaignConfig",
|
|
19969
20147
|
"destination",
|
|
@@ -19982,16 +20160,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
19982
20160
|
}
|
|
19983
20161
|
return value;
|
|
19984
20162
|
});
|
|
19985
|
-
var PresignUploadResponseSchema =
|
|
19986
|
-
uploadUrl:
|
|
20163
|
+
var PresignUploadResponseSchema = z78.object({
|
|
20164
|
+
uploadUrl: z78.string().url().refine((value) => {
|
|
19987
20165
|
const url = new URL(value);
|
|
19988
20166
|
return !url.username && !url.password && url.protocol === "https:";
|
|
19989
20167
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
19990
|
-
publicUrl:
|
|
20168
|
+
publicUrl: z78.string().url().refine((value) => {
|
|
19991
20169
|
const url = new URL(value);
|
|
19992
20170
|
return !url.username && !url.password;
|
|
19993
20171
|
}, "public media URL must not contain embedded credentials"),
|
|
19994
|
-
stagingAssetId:
|
|
20172
|
+
stagingAssetId: z78.string().uuid()
|
|
19995
20173
|
});
|
|
19996
20174
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
19997
20175
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -20016,20 +20194,20 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
20016
20194
|
return uploadResolvedMedia(api, media, assetRole);
|
|
20017
20195
|
}
|
|
20018
20196
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
20019
|
-
var TikTokInput =
|
|
20020
|
-
taskId:
|
|
20021
|
-
advertiserId:
|
|
20022
|
-
pixelId:
|
|
20023
|
-
landingUrl:
|
|
20024
|
-
angleIndexes:
|
|
20197
|
+
var TikTokInput = z78.object({
|
|
20198
|
+
taskId: z78.string().min(1),
|
|
20199
|
+
advertiserId: z78.string().min(1),
|
|
20200
|
+
pixelId: z78.string().min(1).optional(),
|
|
20201
|
+
landingUrl: z78.string().url().optional(),
|
|
20202
|
+
angleIndexes: z78.array(z78.number().int().nonnegative()).optional(),
|
|
20025
20203
|
campaignConfig: McpCampaignConfig.optional(),
|
|
20026
20204
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
20027
20205
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
20028
|
-
primaryText:
|
|
20206
|
+
primaryText: z78.string().trim().min(1).max(500).optional()
|
|
20029
20207
|
});
|
|
20030
20208
|
function registerPublishTools(server, api, opts = {}) {
|
|
20031
20209
|
const transport = opts.transport ?? "http";
|
|
20032
|
-
server.tool("publish_to_shopify", publishToShopifyGuidance.summary + " Precondici\xF3n: la tarea debe estar en status='complete' \u2014 usa `get_task_status` antes. Por defecto `publicationMode=auto`: si esta tarea ya fue publicada en esa tienda, actualiza ESE MISMO producto y conserva URL, precio, variantes, inventario y SKU; si no, crea uno. Usa `existing` + `targetProductId` cuando el usuario elija otro producto y `new` s\xF3lo si pide crear uno nuevo. ANTES de llamar preg\xFAntale \"\xBFTu producto tiene variantes (talla, color, etc.)?\" y pasa `showVariantPicker: true` si responde que s\xED. Por defecto publica TODAS las im\xE1genes generadas; pasa `numLandingImages` s\xF3lo si el usuario pide menos. En code landings con una oferta expl\xEDcita de packs, ProductMaker s\xF3lo publica el selector si variantes reales de Shopify cobran los totales exactos; la respuesta explica si las cre\xF3, verific\xF3 o descart\xF3 por no existir ahorro. Si devuelve SHOPIFY_PUBLISH_INPUT_REQUIRED, muestra todos los problemas de recovery y solicita los importes faltantes. Solo env\xEDa commerceCorrection con su revisi\xF3n/huella y confirmed:true despu\xE9s de confirmar los valores exactos; nunca inventes importes, conviertas moneda ni elimines ofertas. Un contexto obsoleto requiere volver a revisar; open_editor requiere el editor de ProductMaker. Si devuelve SHOPIFY_THEME_SETUP_REQUIRED, el tema de la tienda no tiene el bloque Code Landing y nada se public\xF3: env\xEDa al usuario el themeEditorDeepLink del error para abrir el editor del tema de Shopify, p\xEDdele que agregue el bloque y pulse Guardar (una sola vez por tienda), y reintenta s\xF3lo despu\xE9s. Ante resultado incierto, verifica la tarea/tienda antes de volver a publicar, especialmente con new; commerceCorrectionSaved no prueba publicaci\xF3n. La respuesta es markdown con el link a la landing y al producto.", ShopifyInput.shape, OVERWRITES_EXTERNAL, async (input, extra) => {
|
|
20210
|
+
server.tool("publish_to_shopify", publishToShopifyGuidance.summary + " Precondici\xF3n: la tarea debe estar en status='complete' \u2014 usa `get_task_status` antes. Por defecto `publicationMode=auto`: si esta tarea ya fue publicada en esa tienda, actualiza ESE MISMO producto y conserva URL, precio, variantes, inventario y SKU; si no, crea uno. Usa `existing` + `targetProductId` cuando el usuario elija otro producto y `new` s\xF3lo si pide crear uno nuevo. ANTES de llamar preg\xFAntale \"\xBFTu producto tiene variantes (talla, color, etc.)?\" y pasa `showVariantPicker: true` si responde que s\xED. Por defecto publica TODAS las im\xE1genes generadas; pasa `numLandingImages` s\xF3lo si el usuario pide menos. En code landings con una oferta expl\xEDcita de packs, ProductMaker s\xF3lo publica el selector si variantes reales de Shopify cobran los totales exactos; la respuesta explica si las cre\xF3, verific\xF3 o descart\xF3 por no existir ahorro. Si devuelve SHOPIFY_PUBLISH_INPUT_REQUIRED, muestra todos los problemas de recovery y solicita los importes faltantes. Solo env\xEDa commerceCorrection con su revisi\xF3n/huella y confirmed:true despu\xE9s de confirmar los valores exactos; nunca inventes importes, conviertas moneda ni elimines ofertas. Si adem\xE1s trae correctionRejected, lo que el vendedor confirm\xF3 fue rechazado: l\xE9ele `reason` ANTES de volver a pedir datos. Un contexto obsoleto requiere volver a revisar; open_editor (incluido SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED) requiere el editor de ProductMaker y NO se reenv\xEDa la misma correcci\xF3n. SHOPIFY_PUBLISH_VERIFICATION_FAILED trae en `reason` el siguiente paso: reintenta una vez y si se repite sigue ese paso. Si devuelve SHOPIFY_THEME_SETUP_REQUIRED, el tema de la tienda no tiene el bloque Code Landing y nada se public\xF3: env\xEDa al usuario el themeEditorDeepLink del error para abrir el editor del tema de Shopify, p\xEDdele que agregue el bloque y pulse Guardar (una sola vez por tienda), y reintenta s\xF3lo despu\xE9s. Ante resultado incierto, verifica la tarea/tienda antes de volver a publicar, especialmente con new; commerceCorrectionSaved no prueba publicaci\xF3n. La respuesta es markdown con el link a la landing y al producto.", ShopifyInput.shape, OVERWRITES_EXTERNAL, async (input, extra) => {
|
|
20033
20211
|
try {
|
|
20034
20212
|
const parsed = parseShopifyInput(input);
|
|
20035
20213
|
if (parsed.publicationMode === "existing" && !parsed.targetProductId) {
|
|
@@ -20046,7 +20224,7 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
20046
20224
|
const variantIndex = parsed.variantIndex ?? 0;
|
|
20047
20225
|
const availableImages = await fetchLandingImageCount(api, parsed.taskId);
|
|
20048
20226
|
const effectiveAvailable = availableImages > 0 ? availableImages : 3;
|
|
20049
|
-
const numImages = Math.min(parsed.numLandingImages ?? effectiveAvailable, effectiveAvailable);
|
|
20227
|
+
const numImages = Math.min(parsed.numLandingImages ?? effectiveAvailable, effectiveAvailable, SHOPIFY_MAX_LANDING_IMAGES);
|
|
20050
20228
|
const selectedLandingImages = Array.from({
|
|
20051
20229
|
length: numImages
|
|
20052
20230
|
}, (_, i) => ({
|
|
@@ -20077,6 +20255,8 @@ function registerPublishTools(server, api, opts = {}) {
|
|
|
20077
20255
|
"SHOPIFY_PUBLISH_INPUT_REQUIRED",
|
|
20078
20256
|
"SHOPIFY_PUBLISH_CONTEXT_CHANGED",
|
|
20079
20257
|
"SHOPIFY_PUBLISH_CORRECTION_REQUIRES_EDITOR",
|
|
20258
|
+
"SHOPIFY_PUBLISH_CORRECTION_NOT_CONVERGED",
|
|
20259
|
+
"SHOPIFY_PUBLISH_VERIFICATION_FAILED",
|
|
20080
20260
|
"SHOPIFY_PUBLISH_TARGET_INCOMPATIBLE",
|
|
20081
20261
|
"SHOPIFY_THEME_SETUP_REQUIRED",
|
|
20082
20262
|
"SHOPIFY_PUBLISH_FAILED"
|
|
@@ -20351,39 +20531,39 @@ __name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
|
20351
20531
|
|
|
20352
20532
|
// src/tools/meta-upload.ts
|
|
20353
20533
|
import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
|
|
20354
|
-
import { z as
|
|
20534
|
+
import { z as z79 } from "zod";
|
|
20355
20535
|
var requestMediaUploadGuidance = getProductMakerCapabilityModelGuidance("request_media_upload");
|
|
20356
|
-
var UploadSessionInputBase =
|
|
20357
|
-
mediaKind:
|
|
20536
|
+
var UploadSessionInputBase = z79.object({
|
|
20537
|
+
mediaKind: z79.enum([
|
|
20358
20538
|
"image",
|
|
20359
20539
|
"video",
|
|
20360
20540
|
"mixed"
|
|
20361
20541
|
]).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."),
|
|
20362
|
-
assetRole:
|
|
20542
|
+
assetRole: z79.enum([
|
|
20363
20543
|
"media",
|
|
20364
20544
|
"thumbnail"
|
|
20365
20545
|
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
20366
|
-
uploadPurpose:
|
|
20546
|
+
uploadPurpose: z79.enum([
|
|
20367
20547
|
"product_reference",
|
|
20368
20548
|
"creative",
|
|
20369
20549
|
"generic"
|
|
20370
20550
|
]).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."),
|
|
20371
|
-
maxFiles:
|
|
20551
|
+
maxFiles: z79.number().int().min(1).max(10).optional().describe("Optional batch limit: image accepts 1-5, video exactly 1, and mixed 1-10.")
|
|
20372
20552
|
});
|
|
20373
|
-
var OpenAiFileReference =
|
|
20374
|
-
download_url:
|
|
20375
|
-
file_id:
|
|
20376
|
-
mime_type:
|
|
20377
|
-
file_name:
|
|
20553
|
+
var OpenAiFileReference = z79.object({
|
|
20554
|
+
download_url: z79.string().url().optional().describe("Optional host-provided download URL. The App prefers getFileDownloadUrl(file_id) and the server never fetches this URL."),
|
|
20555
|
+
file_id: z79.string().min(1),
|
|
20556
|
+
mime_type: z79.string().min(1).optional(),
|
|
20557
|
+
file_name: z79.string().min(1).optional()
|
|
20378
20558
|
});
|
|
20379
20559
|
var UploadSessionToolInputShape = {
|
|
20380
20560
|
...UploadSessionInputBase.shape,
|
|
20381
|
-
files:
|
|
20561
|
+
files: z79.array(OpenAiFileReference).max(10).optional().describe("Optional OpenAI-hosted file references provided by ChatGPT. They are only metadata for the UI bridge and are never forwarded to ProductMaker.")
|
|
20382
20562
|
};
|
|
20383
|
-
var UploadSessionToolInput =
|
|
20563
|
+
var UploadSessionToolInput = z79.object(UploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
20384
20564
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
20385
20565
|
ctx.addIssue({
|
|
20386
|
-
code:
|
|
20566
|
+
code: z79.ZodIssueCode.custom,
|
|
20387
20567
|
path: [
|
|
20388
20568
|
"mediaKind"
|
|
20389
20569
|
],
|
|
@@ -20392,7 +20572,7 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20392
20572
|
}
|
|
20393
20573
|
if (value.mediaKind === "video" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
20394
20574
|
ctx.addIssue({
|
|
20395
|
-
code:
|
|
20575
|
+
code: z79.ZodIssueCode.custom,
|
|
20396
20576
|
path: [
|
|
20397
20577
|
"maxFiles"
|
|
20398
20578
|
],
|
|
@@ -20401,7 +20581,7 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20401
20581
|
}
|
|
20402
20582
|
if (value.mediaKind === "image" && (value.maxFiles ?? 1) > 5) {
|
|
20403
20583
|
ctx.addIssue({
|
|
20404
|
-
code:
|
|
20584
|
+
code: z79.ZodIssueCode.custom,
|
|
20405
20585
|
path: [
|
|
20406
20586
|
"maxFiles"
|
|
20407
20587
|
],
|
|
@@ -20409,38 +20589,38 @@ var UploadSessionToolInput = z78.object(UploadSessionToolInputShape).superRefine
|
|
|
20409
20589
|
});
|
|
20410
20590
|
}
|
|
20411
20591
|
});
|
|
20412
|
-
var UploadSessionResponse =
|
|
20413
|
-
sessionId:
|
|
20414
|
-
uploadPageUrl:
|
|
20415
|
-
mediaKind:
|
|
20592
|
+
var UploadSessionResponse = z79.object({
|
|
20593
|
+
sessionId: z79.string().uuid(),
|
|
20594
|
+
uploadPageUrl: z79.string().url(),
|
|
20595
|
+
mediaKind: z79.enum([
|
|
20416
20596
|
"image",
|
|
20417
20597
|
"video",
|
|
20418
20598
|
"mixed"
|
|
20419
20599
|
]),
|
|
20420
|
-
assetRole:
|
|
20600
|
+
assetRole: z79.enum([
|
|
20421
20601
|
"media",
|
|
20422
20602
|
"thumbnail"
|
|
20423
20603
|
]),
|
|
20424
|
-
maxFiles:
|
|
20425
|
-
expiresAt:
|
|
20604
|
+
maxFiles: z79.number().int().positive(),
|
|
20605
|
+
expiresAt: z79.string().datetime()
|
|
20426
20606
|
});
|
|
20427
|
-
var UploadStatusInput =
|
|
20428
|
-
sessionId:
|
|
20607
|
+
var UploadStatusInput = z79.object({
|
|
20608
|
+
sessionId: z79.string().uuid().describe("The sessionId returned by request_media_upload.")
|
|
20429
20609
|
});
|
|
20430
|
-
var UniversalUploadStatusResponse =
|
|
20431
|
-
|
|
20432
|
-
status:
|
|
20433
|
-
assets:
|
|
20610
|
+
var UniversalUploadStatusResponse = z79.discriminatedUnion("status", [
|
|
20611
|
+
z79.object({
|
|
20612
|
+
status: z79.literal("pending"),
|
|
20613
|
+
assets: z79.array(z79.never()).length(0)
|
|
20434
20614
|
}),
|
|
20435
|
-
|
|
20436
|
-
status:
|
|
20437
|
-
assets:
|
|
20438
|
-
assetId:
|
|
20439
|
-
mediaKind:
|
|
20615
|
+
z79.object({
|
|
20616
|
+
status: z79.literal("uploaded"),
|
|
20617
|
+
assets: z79.array(z79.object({
|
|
20618
|
+
assetId: z79.string().uuid(),
|
|
20619
|
+
mediaKind: z79.enum([
|
|
20440
20620
|
"image",
|
|
20441
20621
|
"video"
|
|
20442
20622
|
]),
|
|
20443
|
-
assetRole:
|
|
20623
|
+
assetRole: z79.enum([
|
|
20444
20624
|
"media",
|
|
20445
20625
|
"thumbnail"
|
|
20446
20626
|
])
|
|
@@ -20448,13 +20628,13 @@ var UniversalUploadStatusResponse = z78.discriminatedUnion("status", [
|
|
|
20448
20628
|
})
|
|
20449
20629
|
]);
|
|
20450
20630
|
var UniversalUploadStructuredResponse = UploadSessionResponse.extend({
|
|
20451
|
-
uploadPurpose:
|
|
20631
|
+
uploadPurpose: z79.enum([
|
|
20452
20632
|
"product_reference",
|
|
20453
20633
|
"creative",
|
|
20454
20634
|
"generic"
|
|
20455
20635
|
]),
|
|
20456
|
-
checkToolName:
|
|
20457
|
-
resolveEndpoint:
|
|
20636
|
+
checkToolName: z79.literal("check_media_upload"),
|
|
20637
|
+
resolveEndpoint: z79.string().url()
|
|
20458
20638
|
});
|
|
20459
20639
|
function contextualizeUploadPageUrl(uploadPageUrl, uploadPurpose) {
|
|
20460
20640
|
const url = new URL(uploadPageUrl);
|
|
@@ -20545,15 +20725,15 @@ function registerMediaUploadTools(server, api) {
|
|
|
20545
20725
|
__name(registerMediaUploadTools, "registerMediaUploadTools");
|
|
20546
20726
|
|
|
20547
20727
|
// src/tools/campaigns.ts
|
|
20548
|
-
import { z as
|
|
20728
|
+
import { z as z80 } from "zod";
|
|
20549
20729
|
var getMetaCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_meta_campaign_status");
|
|
20550
20730
|
var getTikTokCampaignStatusGuidance = getProductMakerCapabilityModelGuidance("get_tiktok_campaign_status");
|
|
20551
|
-
var MetaStatusInput =
|
|
20552
|
-
campaignId:
|
|
20731
|
+
var MetaStatusInput = z80.object({
|
|
20732
|
+
campaignId: z80.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
20553
20733
|
});
|
|
20554
|
-
var TikTokStatusInput =
|
|
20555
|
-
campaignId:
|
|
20556
|
-
advertiserId:
|
|
20734
|
+
var TikTokStatusInput = z80.object({
|
|
20735
|
+
campaignId: z80.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
20736
|
+
advertiserId: z80.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
20557
20737
|
});
|
|
20558
20738
|
function registerCampaignTools(server, api) {
|
|
20559
20739
|
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) => {
|
|
@@ -20650,10 +20830,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
20650
20830
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
20651
20831
|
|
|
20652
20832
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20653
|
-
import { z as
|
|
20833
|
+
import { z as z82 } from "zod";
|
|
20654
20834
|
|
|
20655
20835
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20656
|
-
import { z as
|
|
20836
|
+
import { z as z81 } from "zod";
|
|
20657
20837
|
|
|
20658
20838
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
20659
20839
|
var product_costing_shipping_references_default = {
|
|
@@ -20717,21 +20897,21 @@ var product_costing_shipping_references_default = {
|
|
|
20717
20897
|
};
|
|
20718
20898
|
|
|
20719
20899
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
20720
|
-
var ShippingReferenceSchema =
|
|
20721
|
-
reference:
|
|
20722
|
-
min:
|
|
20723
|
-
max:
|
|
20724
|
-
updatedAt:
|
|
20725
|
-
confidence:
|
|
20900
|
+
var ShippingReferenceSchema = z81.object({
|
|
20901
|
+
reference: z81.number().positive(),
|
|
20902
|
+
min: z81.number().nonnegative(),
|
|
20903
|
+
max: z81.number().positive(),
|
|
20904
|
+
updatedAt: z81.string().date(),
|
|
20905
|
+
confidence: z81.enum([
|
|
20726
20906
|
"high",
|
|
20727
20907
|
"medium",
|
|
20728
20908
|
"medium-low"
|
|
20729
20909
|
]),
|
|
20730
|
-
sources:
|
|
20910
|
+
sources: z81.array(z81.string().url().startsWith("https://")).min(1).max(3)
|
|
20731
20911
|
}).superRefine(({ reference, min, max }, context) => {
|
|
20732
20912
|
if (min > reference || reference > max) {
|
|
20733
20913
|
context.addIssue({
|
|
20734
|
-
code:
|
|
20914
|
+
code: z81.ZodIssueCode.custom,
|
|
20735
20915
|
message: "shipping_reference_outside_range",
|
|
20736
20916
|
path: [
|
|
20737
20917
|
"reference"
|
|
@@ -20739,7 +20919,7 @@ var ShippingReferenceSchema = z80.object({
|
|
|
20739
20919
|
});
|
|
20740
20920
|
}
|
|
20741
20921
|
});
|
|
20742
|
-
var SHIPPING_REFERENCES =
|
|
20922
|
+
var SHIPPING_REFERENCES = z81.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
20743
20923
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
20744
20924
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
20745
20925
|
"MX",
|
|
@@ -20921,18 +21101,18 @@ function getProductCostingCountryName(country) {
|
|
|
20921
21101
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
20922
21102
|
|
|
20923
21103
|
// ../../packages/product-economics/src/product-costing.ts
|
|
20924
|
-
var ProductCostingInputSchema =
|
|
20925
|
-
country:
|
|
20926
|
-
supplierCost:
|
|
20927
|
-
shippingCost:
|
|
20928
|
-
returnRate:
|
|
20929
|
-
cancellationRate:
|
|
20930
|
-
adsManagerCpa:
|
|
20931
|
-
desiredMargin:
|
|
21104
|
+
var ProductCostingInputSchema = z82.object({
|
|
21105
|
+
country: z82.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
21106
|
+
supplierCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
21107
|
+
shippingCost: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
21108
|
+
returnRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21109
|
+
cancellationRate: z82.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
21110
|
+
adsManagerCpa: z82.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
21111
|
+
desiredMargin: z82.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
20932
21112
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
20933
21113
|
if (returnRate + cancellationRate >= 1) {
|
|
20934
21114
|
context.addIssue({
|
|
20935
|
-
code:
|
|
21115
|
+
code: z82.ZodIssueCode.custom,
|
|
20936
21116
|
message: "delivery_rate_positive",
|
|
20937
21117
|
path: [
|
|
20938
21118
|
"cancellationRate"
|
|
@@ -21029,15 +21209,15 @@ function calculateProductCosting(rawInput) {
|
|
|
21029
21209
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
21030
21210
|
|
|
21031
21211
|
// src/tools/product-costing.ts
|
|
21032
|
-
import { z as
|
|
21212
|
+
import { z as z83 } from "zod";
|
|
21033
21213
|
var costProductGuidance = getProductMakerCapabilityModelGuidance("cost_product");
|
|
21034
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
21035
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
21036
|
-
var ProductCostingToolInput =
|
|
21037
|
-
country:
|
|
21214
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z83.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
21215
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z83.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
21216
|
+
var ProductCostingToolInput = z83.object({
|
|
21217
|
+
country: z83.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21038
21218
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21039
21219
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
21040
|
-
supplierCost:
|
|
21220
|
+
supplierCost: z83.number().finite().max(Number.MAX_SAFE_INTEGER).positive().optional().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. Requerido salvo que uses supplierCostCop para Colombia."),
|
|
21041
21221
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
21042
21222
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
21043
21223
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -21196,7 +21376,7 @@ function formatPercent(value) {
|
|
|
21196
21376
|
__name(formatPercent, "formatPercent");
|
|
21197
21377
|
|
|
21198
21378
|
// src/tools/product-research.ts
|
|
21199
|
-
import { z as
|
|
21379
|
+
import { z as z84 } from "zod";
|
|
21200
21380
|
|
|
21201
21381
|
// src/tools/product-research-idempotency.ts
|
|
21202
21382
|
var RESEARCH_IDEMPOTENCY_WINDOW_MS = 2 * 60 * 60 * 1e3;
|
|
@@ -21567,17 +21747,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
21567
21747
|
]);
|
|
21568
21748
|
var POLL_INTERVAL_MS = 5e3;
|
|
21569
21749
|
var MAX_WAIT_SECONDS = 120;
|
|
21570
|
-
var FindInput =
|
|
21750
|
+
var FindInput = z84.object({
|
|
21571
21751
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
21572
21752
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
21573
|
-
confirmed:
|
|
21574
|
-
waitSeconds:
|
|
21753
|
+
confirmed: z84.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
21754
|
+
waitSeconds: z84.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
21575
21755
|
});
|
|
21576
|
-
var GetInput =
|
|
21577
|
-
runId:
|
|
21756
|
+
var GetInput = z84.object({
|
|
21757
|
+
runId: z84.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
21578
21758
|
});
|
|
21579
|
-
var ListInput =
|
|
21580
|
-
limit:
|
|
21759
|
+
var ListInput = z84.object({
|
|
21760
|
+
limit: z84.number().int().min(1).max(20).default(10)
|
|
21581
21761
|
});
|
|
21582
21762
|
function textResult(text) {
|
|
21583
21763
|
return {
|
|
@@ -21700,17 +21880,17 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
21700
21880
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
21701
21881
|
|
|
21702
21882
|
// src/tools/dropshipping-projects.ts
|
|
21703
|
-
import { z as
|
|
21883
|
+
import { z as z85 } from "zod";
|
|
21704
21884
|
var startDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("start_dropshipping_project");
|
|
21705
21885
|
var costDropshippingProjectGuidance = getProductMakerCapabilityModelGuidance("cost_dropshipping_project");
|
|
21706
21886
|
var guideDropshippingLaunchGuidance = getProductMakerCapabilityModelGuidance("guide_dropshipping_launch");
|
|
21707
|
-
var ProjectId =
|
|
21708
|
-
var DropshippingProjectStatus =
|
|
21887
|
+
var ProjectId = z85.string().uuid();
|
|
21888
|
+
var DropshippingProjectStatus = z85.enum([
|
|
21709
21889
|
"active",
|
|
21710
21890
|
"completed",
|
|
21711
21891
|
"archived"
|
|
21712
21892
|
]);
|
|
21713
|
-
var DropshippingProjectPhase =
|
|
21893
|
+
var DropshippingProjectPhase = z85.enum([
|
|
21714
21894
|
"research",
|
|
21715
21895
|
"costing",
|
|
21716
21896
|
"media",
|
|
@@ -21719,21 +21899,21 @@ var DropshippingProjectPhase = z84.enum([
|
|
|
21719
21899
|
"advertising",
|
|
21720
21900
|
"complete"
|
|
21721
21901
|
]);
|
|
21722
|
-
var DropshippingRewardMilestone =
|
|
21902
|
+
var DropshippingRewardMilestone = z85.enum([
|
|
21723
21903
|
"product_selected",
|
|
21724
21904
|
"costing_saved",
|
|
21725
21905
|
"product_media_ready",
|
|
21726
21906
|
"creatives_completed",
|
|
21727
21907
|
"campaign_created"
|
|
21728
21908
|
]);
|
|
21729
|
-
var TargetCountry =
|
|
21909
|
+
var TargetCountry = z85.enum([
|
|
21730
21910
|
"CO",
|
|
21731
21911
|
"MX",
|
|
21732
21912
|
"PE",
|
|
21733
21913
|
"EC",
|
|
21734
21914
|
"CL"
|
|
21735
21915
|
]);
|
|
21736
|
-
var ResearchCategory =
|
|
21916
|
+
var ResearchCategory = z85.enum([
|
|
21737
21917
|
"auto",
|
|
21738
21918
|
"automotive",
|
|
21739
21919
|
"kitchen",
|
|
@@ -21748,7 +21928,7 @@ var ResearchCategory = z84.enum([
|
|
|
21748
21928
|
"garden",
|
|
21749
21929
|
"cleaning"
|
|
21750
21930
|
]);
|
|
21751
|
-
var HttpUrl3 =
|
|
21931
|
+
var HttpUrl3 = z85.string().url().max(2e3).refine((value) => {
|
|
21752
21932
|
try {
|
|
21753
21933
|
return [
|
|
21754
21934
|
"http:",
|
|
@@ -21758,45 +21938,45 @@ var HttpUrl3 = z84.string().url().max(2e3).refine((value) => {
|
|
|
21758
21938
|
return false;
|
|
21759
21939
|
}
|
|
21760
21940
|
}, "URL must use HTTP(S)");
|
|
21761
|
-
var ResearchCandidateOrigin =
|
|
21762
|
-
type:
|
|
21941
|
+
var ResearchCandidateOrigin = z85.object({
|
|
21942
|
+
type: z85.literal("research_candidate"),
|
|
21763
21943
|
runId: ProjectId,
|
|
21764
|
-
candidateSourceId:
|
|
21944
|
+
candidateSourceId: z85.string().min(1).max(160)
|
|
21765
21945
|
});
|
|
21766
|
-
var TaskOrigin =
|
|
21767
|
-
type:
|
|
21946
|
+
var TaskOrigin = z85.object({
|
|
21947
|
+
type: z85.literal("task"),
|
|
21768
21948
|
taskId: ProjectId
|
|
21769
21949
|
});
|
|
21770
|
-
var ManualOrigin =
|
|
21771
|
-
type:
|
|
21950
|
+
var ManualOrigin = z85.object({
|
|
21951
|
+
type: z85.literal("manual"),
|
|
21772
21952
|
clientRequestId: ProjectId,
|
|
21773
|
-
country:
|
|
21953
|
+
country: z85.string().min(2).max(3).optional()
|
|
21774
21954
|
});
|
|
21775
|
-
var StartProjectInput =
|
|
21776
|
-
origin:
|
|
21955
|
+
var StartProjectInput = z85.object({
|
|
21956
|
+
origin: z85.discriminatedUnion("type", [
|
|
21777
21957
|
ResearchCandidateOrigin,
|
|
21778
21958
|
TaskOrigin,
|
|
21779
21959
|
ManualOrigin
|
|
21780
21960
|
]),
|
|
21781
|
-
productName:
|
|
21961
|
+
productName: z85.string().trim().min(1).max(240).optional(),
|
|
21782
21962
|
productUrl: HttpUrl3.optional(),
|
|
21783
|
-
country:
|
|
21784
|
-
languageCode:
|
|
21963
|
+
country: z85.string().min(2).max(3).optional(),
|
|
21964
|
+
languageCode: z85.string().min(2).max(16).optional()
|
|
21785
21965
|
}).strict();
|
|
21786
|
-
var CostProjectInput =
|
|
21966
|
+
var CostProjectInput = z85.object({
|
|
21787
21967
|
projectId: ProjectId,
|
|
21788
|
-
version:
|
|
21789
|
-
country:
|
|
21968
|
+
version: z85.number().int().positive().describe("Version le\xEDda del proyecto. Copia la \xFAltima que viste; no se la pidas al usuario."),
|
|
21969
|
+
country: z85.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
21790
21970
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
21791
21971
|
}).describe("C\xF3digo ISO-2 del pa\xEDs del proyecto. Usa el `targetCountry` que devuelve el proyecto."),
|
|
21792
|
-
supplierCost:
|
|
21793
|
-
shippingCost:
|
|
21794
|
-
returnRate:
|
|
21795
|
-
cancellationRate:
|
|
21796
|
-
adsManagerCpa:
|
|
21797
|
-
desiredMargin:
|
|
21798
|
-
});
|
|
21799
|
-
var GuideInput =
|
|
21972
|
+
supplierCost: z85.number().finite().positive().describe("Costo real de una unidad con el proveedor, en la moneda del pa\xEDs. \xDANICO dato que debes pedirle al usuario: nunca lo inventes."),
|
|
21973
|
+
shippingCost: z85.number().finite().nonnegative().optional().describe("Costo de un env\xEDo. Omite para usar el valor gu\xEDa del pa\xEDs en vez de inventarlo."),
|
|
21974
|
+
returnRate: z85.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos devueltos (0.25 = 25%). Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
21975
|
+
cancellationRate: z85.number().finite().min(0).lt(1).optional().describe("Fracci\xF3n de pedidos cancelados (0.15 = 15%). Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
21976
|
+
adsManagerCpa: z85.number().finite().nonnegative().optional().describe("Costo por compra de Ads Manager. Omite para usar el valor gu\xEDa del pa\xEDs."),
|
|
21977
|
+
desiredMargin: z85.number().finite().min(0).lt(1).optional().describe("Margen deseado (0.1 = 10%). Omite para usar el valor gu\xEDa del pa\xEDs.")
|
|
21978
|
+
});
|
|
21979
|
+
var GuideInput = z85.object({
|
|
21800
21980
|
projectId: ProjectId.optional()
|
|
21801
21981
|
}).strict();
|
|
21802
21982
|
var NEXT_ACTION_KINDS = [
|
|
@@ -21814,29 +21994,29 @@ var NEXT_ACTION_KINDS = [
|
|
|
21814
21994
|
"repair_meta_campaign",
|
|
21815
21995
|
"review_paused_campaign"
|
|
21816
21996
|
];
|
|
21817
|
-
var DropshippingProjectNextAction =
|
|
21818
|
-
kind:
|
|
21819
|
-
href:
|
|
21997
|
+
var DropshippingProjectNextAction = z85.discriminatedUnion("kind", NEXT_ACTION_KINDS.map((kind) => z85.object({
|
|
21998
|
+
kind: z85.literal(kind),
|
|
21999
|
+
href: z85.string().min(1)
|
|
21820
22000
|
})));
|
|
21821
|
-
var CostingInputSchema =
|
|
21822
|
-
country:
|
|
21823
|
-
supplierCost:
|
|
21824
|
-
shippingCost:
|
|
21825
|
-
returnRate:
|
|
21826
|
-
cancellationRate:
|
|
21827
|
-
adsManagerCpa:
|
|
21828
|
-
desiredMargin:
|
|
22001
|
+
var CostingInputSchema = z85.object({
|
|
22002
|
+
country: z85.string().min(2).max(3),
|
|
22003
|
+
supplierCost: z85.number().finite().positive(),
|
|
22004
|
+
shippingCost: z85.number().finite().nonnegative(),
|
|
22005
|
+
returnRate: z85.number().finite().min(0).lt(1),
|
|
22006
|
+
cancellationRate: z85.number().finite().min(0).lt(1),
|
|
22007
|
+
adsManagerCpa: z85.number().finite().nonnegative(),
|
|
22008
|
+
desiredMargin: z85.number().finite().min(0).lt(1)
|
|
21829
22009
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
21830
22010
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
21831
|
-
code:
|
|
22011
|
+
code: z85.ZodIssueCode.custom,
|
|
21832
22012
|
path: [
|
|
21833
22013
|
"cancellationRate"
|
|
21834
22014
|
]
|
|
21835
22015
|
});
|
|
21836
22016
|
});
|
|
21837
|
-
var FiniteCostingNumber =
|
|
21838
|
-
var CostingResultSchema =
|
|
21839
|
-
country:
|
|
22017
|
+
var FiniteCostingNumber = z85.number().finite();
|
|
22018
|
+
var CostingResultSchema = z85.object({
|
|
22019
|
+
country: z85.string().min(2).max(3),
|
|
21840
22020
|
deliveryRate: FiniteCostingNumber,
|
|
21841
22021
|
adjustedShippingCost: FiniteCostingNumber,
|
|
21842
22022
|
adjustedCpa: FiniteCostingNumber,
|
|
@@ -21849,45 +22029,45 @@ var CostingResultSchema = z84.object({
|
|
|
21849
22029
|
estimatedProfit: FiniteCostingNumber,
|
|
21850
22030
|
actualMargin: FiniteCostingNumber,
|
|
21851
22031
|
breakEvenAdsManagerCpa: FiniteCostingNumber,
|
|
21852
|
-
wasPriceAutoAdjusted:
|
|
21853
|
-
profitabilityStatus:
|
|
21854
|
-
});
|
|
21855
|
-
var RewardProgressSchema =
|
|
21856
|
-
campaignKey:
|
|
21857
|
-
totalCredits:
|
|
21858
|
-
earnedCredits:
|
|
21859
|
-
milestones:
|
|
22032
|
+
wasPriceAutoAdjusted: z85.boolean(),
|
|
22033
|
+
profitabilityStatus: z85.literal("healthy")
|
|
22034
|
+
});
|
|
22035
|
+
var RewardProgressSchema = z85.object({
|
|
22036
|
+
campaignKey: z85.literal("dropshipping-launch-v1"),
|
|
22037
|
+
totalCredits: z85.number().int().positive(),
|
|
22038
|
+
earnedCredits: z85.number().int().nonnegative(),
|
|
22039
|
+
milestones: z85.array(z85.object({
|
|
21860
22040
|
milestone: DropshippingRewardMilestone,
|
|
21861
|
-
credits:
|
|
21862
|
-
available:
|
|
21863
|
-
earned:
|
|
22041
|
+
credits: z85.number().int().positive(),
|
|
22042
|
+
available: z85.boolean().optional(),
|
|
22043
|
+
earned: z85.boolean(),
|
|
21864
22044
|
grantId: ProjectId.nullable(),
|
|
21865
|
-
grantedAt:
|
|
22045
|
+
grantedAt: z85.string().datetime().nullable()
|
|
21866
22046
|
})).length(DropshippingRewardMilestone.options.length)
|
|
21867
22047
|
});
|
|
21868
|
-
var ProjectResponseSchema =
|
|
22048
|
+
var ProjectResponseSchema = z85.object({
|
|
21869
22049
|
id: ProjectId,
|
|
21870
22050
|
taskId: ProjectId.nullable(),
|
|
21871
22051
|
status: DropshippingProjectStatus,
|
|
21872
|
-
originKey:
|
|
22052
|
+
originKey: z85.string().min(1),
|
|
21873
22053
|
researchRunId: ProjectId.nullable(),
|
|
21874
|
-
candidateSourceId:
|
|
21875
|
-
productName:
|
|
22054
|
+
candidateSourceId: z85.string().nullable(),
|
|
22055
|
+
productName: z85.string().nullable(),
|
|
21876
22056
|
productUrl: HttpUrl3.nullable(),
|
|
21877
22057
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
21878
|
-
targetCountry:
|
|
21879
|
-
languageCode:
|
|
21880
|
-
hasReferenceImage:
|
|
21881
|
-
hasWinnerReferenceImage:
|
|
22058
|
+
targetCountry: z85.string().nullable(),
|
|
22059
|
+
languageCode: z85.string().nullable(),
|
|
22060
|
+
hasReferenceImage: z85.boolean(),
|
|
22061
|
+
hasWinnerReferenceImage: z85.boolean(),
|
|
21882
22062
|
costingInput: CostingInputSchema.nullable(),
|
|
21883
22063
|
costingResult: CostingResultSchema.nullable(),
|
|
21884
|
-
costingVersion:
|
|
21885
|
-
version:
|
|
22064
|
+
costingVersion: z85.number().int().positive().nullable(),
|
|
22065
|
+
version: z85.number().int().positive(),
|
|
21886
22066
|
phase: DropshippingProjectPhase,
|
|
21887
22067
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
21888
22068
|
rewards: RewardProgressSchema,
|
|
21889
|
-
createdAt:
|
|
21890
|
-
updatedAt:
|
|
22069
|
+
createdAt: z85.string().datetime(),
|
|
22070
|
+
updatedAt: z85.string().datetime()
|
|
21891
22071
|
}).passthrough();
|
|
21892
22072
|
var NEXT_ACTION_GUIDANCE = {
|
|
21893
22073
|
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.",
|
|
@@ -22005,58 +22185,58 @@ function registerDropshippingProjectTools(server, api) {
|
|
|
22005
22185
|
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
22006
22186
|
|
|
22007
22187
|
// src/tools/daily-control.ts
|
|
22008
|
-
import { z as
|
|
22188
|
+
import { z as z86 } from "zod";
|
|
22009
22189
|
var getDailyControlGuidance = getProductMakerCapabilityModelGuidance("get_daily_control");
|
|
22010
22190
|
var linkCampaignToProjectGuidance = getProductMakerCapabilityModelGuidance("link_campaign_to_project");
|
|
22011
22191
|
var reportDailyReturnsGuidance = getProductMakerCapabilityModelGuidance("report_daily_returns");
|
|
22012
|
-
var ProviderCampaignIdentifier =
|
|
22013
|
-
var DateOnly =
|
|
22014
|
-
var DailyControlInput =
|
|
22192
|
+
var ProviderCampaignIdentifier = z86.string().min(1).max(64).regex(/^[A-Za-z0-9_-]+$/);
|
|
22193
|
+
var DateOnly = z86.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22194
|
+
var DailyControlInput = z86.object({
|
|
22015
22195
|
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."),
|
|
22016
|
-
days:
|
|
22017
|
-
projectId:
|
|
22196
|
+
days: z86.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
22197
|
+
projectId: z86.string().uuid().optional().describe("Opcional: limita el reporte a un solo proyecto en vez de todos los productos activos.")
|
|
22018
22198
|
}).strict();
|
|
22019
|
-
var LinkCampaignInput =
|
|
22020
|
-
projectId:
|
|
22021
|
-
provider:
|
|
22199
|
+
var LinkCampaignInput = z86.object({
|
|
22200
|
+
projectId: z86.string().uuid(),
|
|
22201
|
+
provider: z86.enum([
|
|
22022
22202
|
"meta",
|
|
22023
22203
|
"tiktok"
|
|
22024
22204
|
]),
|
|
22025
22205
|
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."),
|
|
22026
22206
|
campaignId: ProviderCampaignIdentifier
|
|
22027
22207
|
}).strict();
|
|
22028
|
-
var ReportReturnsInput =
|
|
22029
|
-
projectId:
|
|
22208
|
+
var ReportReturnsInput = z86.object({
|
|
22209
|
+
projectId: z86.string().uuid(),
|
|
22030
22210
|
date: DateOnly,
|
|
22031
|
-
returnedOrders:
|
|
22032
|
-
note:
|
|
22211
|
+
returnedOrders: z86.number().int().min(0).max(1e5),
|
|
22212
|
+
note: z86.string().trim().max(280).optional()
|
|
22033
22213
|
}).strict();
|
|
22034
|
-
var DailyControlStatusMirror = DailyControlStatusEnum.or(
|
|
22035
|
-
var DailyControlLightMirror = DailyControlLightEnum.or(
|
|
22036
|
-
var DailyControlSourceMirror = DailyControlSourceEnum.or(
|
|
22037
|
-
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(
|
|
22038
|
-
var DailyControlDayMirror =
|
|
22039
|
-
date:
|
|
22040
|
-
returnedOrders:
|
|
22214
|
+
var DailyControlStatusMirror = DailyControlStatusEnum.or(z86.string());
|
|
22215
|
+
var DailyControlLightMirror = DailyControlLightEnum.or(z86.string());
|
|
22216
|
+
var DailyControlSourceMirror = DailyControlSourceEnum.or(z86.string());
|
|
22217
|
+
var DailyControlVerdictMirror = DailyControlVerdictEnum.or(z86.string());
|
|
22218
|
+
var DailyControlDayMirror = z86.object({
|
|
22219
|
+
date: z86.string(),
|
|
22220
|
+
returnedOrders: z86.number(),
|
|
22041
22221
|
returnedSource: DailyControlSourceMirror,
|
|
22042
22222
|
cancelledSource: DailyControlSourceMirror,
|
|
22043
|
-
hasEstimates:
|
|
22223
|
+
hasEstimates: z86.boolean(),
|
|
22044
22224
|
light: DailyControlLightMirror
|
|
22045
22225
|
}).passthrough();
|
|
22046
|
-
var DailyControlProductMirror =
|
|
22047
|
-
projectId:
|
|
22048
|
-
productName:
|
|
22226
|
+
var DailyControlProductMirror = z86.object({
|
|
22227
|
+
projectId: z86.string().uuid(),
|
|
22228
|
+
productName: z86.string().nullable(),
|
|
22049
22229
|
status: DailyControlStatusMirror,
|
|
22050
|
-
statusMessage:
|
|
22051
|
-
days:
|
|
22230
|
+
statusMessage: z86.string().nullable(),
|
|
22231
|
+
days: z86.array(DailyControlDayMirror),
|
|
22052
22232
|
verdict: DailyControlVerdictMirror.nullable(),
|
|
22053
|
-
rationale:
|
|
22233
|
+
rationale: z86.string().nullable()
|
|
22054
22234
|
}).passthrough();
|
|
22055
|
-
var DailyControlResponseMirror =
|
|
22056
|
-
since:
|
|
22057
|
-
until:
|
|
22058
|
-
products:
|
|
22059
|
-
archivedProjectSpend:
|
|
22235
|
+
var DailyControlResponseMirror = z86.object({
|
|
22236
|
+
since: z86.string(),
|
|
22237
|
+
until: z86.string(),
|
|
22238
|
+
products: z86.array(DailyControlProductMirror),
|
|
22239
|
+
archivedProjectSpend: z86.array(z86.unknown())
|
|
22060
22240
|
}).passthrough();
|
|
22061
22241
|
var MCP_WARNINGS_KEY = "_mcpDailyControlWarnings";
|
|
22062
22242
|
function withWarnings(response) {
|
|
@@ -22140,42 +22320,42 @@ function registerDailyControlTools(server, api) {
|
|
|
22140
22320
|
__name(registerDailyControlTools, "registerDailyControlTools");
|
|
22141
22321
|
|
|
22142
22322
|
// src/tools/product-control.ts
|
|
22143
|
-
import { z as
|
|
22323
|
+
import { z as z87 } from "zod";
|
|
22144
22324
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
22145
22325
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
22146
22326
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
22147
22327
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
22148
22328
|
var reportProductCountsGuidance = getProductMakerCapabilityModelGuidance("report_product_counts");
|
|
22149
|
-
var DateOnly2 =
|
|
22329
|
+
var DateOnly2 = z87.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
22150
22330
|
var IMPORT_BATCH_MAX2 = 50;
|
|
22151
|
-
var ProductControlListInput =
|
|
22152
|
-
days:
|
|
22331
|
+
var ProductControlListInput = z87.object({
|
|
22332
|
+
days: z87.number().int().min(1).max(14).default(3).describe("Tama\xF1o de la ventana, 1 a 14 d\xEDas."),
|
|
22153
22333
|
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."),
|
|
22154
|
-
shopDomain:
|
|
22334
|
+
shopDomain: z87.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
22155
22335
|
}).strict();
|
|
22156
|
-
var ImportableProductsInput =
|
|
22157
|
-
q:
|
|
22158
|
-
after:
|
|
22159
|
-
shopDomain:
|
|
22336
|
+
var ImportableProductsInput = z87.object({
|
|
22337
|
+
q: z87.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
22338
|
+
after: z87.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
22339
|
+
shopDomain: z87.string().min(1).optional()
|
|
22160
22340
|
}).strict();
|
|
22161
|
-
var ImportProductControlsInput =
|
|
22162
|
-
shopifyProductIds:
|
|
22341
|
+
var ImportProductControlsInput = z87.object({
|
|
22342
|
+
shopifyProductIds: z87.array(z87.string().min(1).max(64)).min(1).max(IMPORT_BATCH_MAX2).describe("Identificadores tal como vinieron de list_importable_products. NO los inventes ni los deduzcas del t\xEDtulo."),
|
|
22163
22343
|
// Obligatorio, como en el endpoint: con dos tiendas conectadas, importar
|
|
22164
22344
|
// sin decir a cuál archivaría el producto bajo la tienda equivocada.
|
|
22165
|
-
shopDomain:
|
|
22345
|
+
shopDomain: z87.string().min(1)
|
|
22166
22346
|
}).strict();
|
|
22167
|
-
var SetProductCostingInput =
|
|
22168
|
-
shopDomain:
|
|
22169
|
-
shopifyProductId:
|
|
22170
|
-
targetCountry:
|
|
22171
|
-
supplierCost:
|
|
22172
|
-
shippingCost:
|
|
22173
|
-
returnRate:
|
|
22174
|
-
cancellationRate:
|
|
22347
|
+
var SetProductCostingInput = z87.object({
|
|
22348
|
+
shopDomain: z87.string().min(1),
|
|
22349
|
+
shopifyProductId: z87.string().min(1).max(64),
|
|
22350
|
+
targetCountry: z87.string().length(2).describe("Pa\xEDs de venta en ISO-2, que fija moneda y referencia de flete."),
|
|
22351
|
+
supplierCost: z87.number().finite().positive().describe("Lo que le cuesta el producto al proveedor. Nunca cero."),
|
|
22352
|
+
shippingCost: z87.number().finite().nonnegative(),
|
|
22353
|
+
returnRate: z87.number().finite().min(0).lt(1).describe("Proporci\xF3n 0\u20131, no porcentaje: 0.15 es quince por ciento."),
|
|
22354
|
+
cancellationRate: z87.number().finite().min(0).lt(1)
|
|
22175
22355
|
}).strict();
|
|
22176
|
-
var Count =
|
|
22177
|
-
var ReportProductCountsInput =
|
|
22178
|
-
productControlId:
|
|
22356
|
+
var Count = z87.number().int().min(0).max(1e5).nullable().optional();
|
|
22357
|
+
var ReportProductCountsInput = z87.object({
|
|
22358
|
+
productControlId: z87.string().uuid().describe("El identificador que devuelve get_product_control."),
|
|
22179
22359
|
date: DateOnly2,
|
|
22180
22360
|
orders: Count.describe("Pedidos que entraron ese d\xEDa."),
|
|
22181
22361
|
cancelledOrders: Count,
|