@productmaker/mcp 2.8.3 → 2.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -8
- package/dist/http.js +801 -721
- package/dist/stdio.js +801 -721
- package/dist/ui/meta-upload-app.html +973 -436
- package/package.json +3 -3
package/dist/stdio.js
CHANGED
|
@@ -150,7 +150,7 @@ var ApiClient = class {
|
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
// src/index.ts
|
|
153
|
-
var MCP_VERSION = "2.
|
|
153
|
+
var MCP_VERSION = "2.9.1";
|
|
154
154
|
|
|
155
155
|
// src/meta-upload-app.ts
|
|
156
156
|
import { readFileSync } from "fs";
|
|
@@ -203,7 +203,7 @@ function registerMetaUploadAppResource(server) {
|
|
|
203
203
|
__name(registerMetaUploadAppResource, "registerMetaUploadAppResource");
|
|
204
204
|
|
|
205
205
|
// src/tools/tasks.ts
|
|
206
|
-
import { z as
|
|
206
|
+
import { z as z46 } from "zod";
|
|
207
207
|
|
|
208
208
|
// src/resolve-image.ts
|
|
209
209
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -2303,6 +2303,25 @@ var ShopifyPublicationStatus = z19.enum([
|
|
|
2303
2303
|
"success",
|
|
2304
2304
|
"error"
|
|
2305
2305
|
]);
|
|
2306
|
+
var ShopifyTrackingSyncStatus = z19.enum([
|
|
2307
|
+
"synced",
|
|
2308
|
+
"migrated",
|
|
2309
|
+
"not_detected"
|
|
2310
|
+
]);
|
|
2311
|
+
var ShopifyTrackingSource = z19.enum([
|
|
2312
|
+
"theme",
|
|
2313
|
+
"legacy_layout",
|
|
2314
|
+
"theme_and_legacy",
|
|
2315
|
+
"none"
|
|
2316
|
+
]);
|
|
2317
|
+
var ShopifyTrackingResult = z19.object({
|
|
2318
|
+
status: ShopifyTrackingSyncStatus,
|
|
2319
|
+
manualCodeDetected: z19.boolean(),
|
|
2320
|
+
/** True when code from a prior ProductMaker layout was preserved automatically. */
|
|
2321
|
+
legacyCodeMigrated: z19.boolean().default(false),
|
|
2322
|
+
source: ShopifyTrackingSource.default("none"),
|
|
2323
|
+
syncedAt: z19.string().datetime()
|
|
2324
|
+
});
|
|
2306
2325
|
var ShopifyPublishResponse = z19.object({
|
|
2307
2326
|
publicationId: z19.string().uuid(),
|
|
2308
2327
|
taskId: z19.string().uuid(),
|
|
@@ -2318,6 +2337,8 @@ var ShopifyPublishResponse = z19.object({
|
|
|
2318
2337
|
needsThemeSetup: z19.boolean().optional(),
|
|
2319
2338
|
/** One-click theme-editor deep link to add the Code Landing block (when needsThemeSetup). */
|
|
2320
2339
|
themeEditorDeepLink: z19.string().url().optional(),
|
|
2340
|
+
/** Tracking copied from the theme or migrated from a previous ProductMaker layout. */
|
|
2341
|
+
tracking: ShopifyTrackingResult.optional(),
|
|
2321
2342
|
createdAt: z19.string().datetime().optional(),
|
|
2322
2343
|
updatedAt: z19.string().datetime().optional()
|
|
2323
2344
|
});
|
|
@@ -3216,7 +3237,9 @@ var ImageCreativeEstimationOptions = z24.object({
|
|
|
3216
3237
|
});
|
|
3217
3238
|
var RegenerateLandingRoleBody = z24.object({
|
|
3218
3239
|
comment: z24.string().max(500).optional(),
|
|
3219
|
-
sourceKey: z24.string().max(200).optional()
|
|
3240
|
+
sourceKey: z24.string().max(200).optional(),
|
|
3241
|
+
/** Client-generated key lets a lost response be retried without another charge. */
|
|
3242
|
+
clientRequestId: z24.string().uuid().optional()
|
|
3220
3243
|
}).strict();
|
|
3221
3244
|
var LandingRegenerateEstimationOptions = z24.object({
|
|
3222
3245
|
/** KIE image endpoint has non-linear pricing by nVariants; for landing we default to 2. */
|
|
@@ -6162,8 +6185,7 @@ var DEFAULT_PRICING = {
|
|
|
6162
6185
|
userPriceCents: 0.04
|
|
6163
6186
|
}
|
|
6164
6187
|
};
|
|
6165
|
-
var
|
|
6166
|
-
var REGEN_SINGLE_CALL_OUR_COST_CENTS = DEFAULT_PRICING["kie:video-generation:grok-15s-480p"].ourCostCents;
|
|
6188
|
+
var REGEN_SINGLE_CALL_OUR_COST_CENTS = DEFAULT_PRICING["kie:video-generation:grok-15s-720p"].ourCostCents;
|
|
6167
6189
|
var SC_FRAME_COMPOSE_OUR_COST_CENTS = DEFAULT_PRICING["kie:image-generation:gpt-image-2:medium"].ourCostCents;
|
|
6168
6190
|
var SC_FRAME_COMPOSE_USER_PRICE_CENTS = DEFAULT_PRICING["kie:image-generation:gpt-image-2:medium"].userPriceCents;
|
|
6169
6191
|
var MS_FRAME_COMPOSE_OUR_COST_CENTS = DEFAULT_PRICING["kie:image-generation:nano-banana-2"].ourCostCents;
|
|
@@ -7440,10 +7462,35 @@ var ListLandingEditsResponse = z37.object({
|
|
|
7440
7462
|
edits: z37.array(LandingEditDto)
|
|
7441
7463
|
});
|
|
7442
7464
|
|
|
7443
|
-
// ../../packages/types/src/
|
|
7465
|
+
// ../../packages/types/src/landing-regeneration.ts
|
|
7444
7466
|
import { z as z38 } from "zod";
|
|
7467
|
+
var LandingRegenerationStatus = z38.enum([
|
|
7468
|
+
"queued",
|
|
7469
|
+
"processing",
|
|
7470
|
+
"published",
|
|
7471
|
+
"failed"
|
|
7472
|
+
]);
|
|
7473
|
+
var RegenerateLandingRoleResponse = z38.object({
|
|
7474
|
+
ok: z38.literal(true),
|
|
7475
|
+
role: LandingRole,
|
|
7476
|
+
promptIndex: z38.number().int().nonnegative(),
|
|
7477
|
+
operationId: z38.string().min(1)
|
|
7478
|
+
});
|
|
7479
|
+
var LandingRegenerationStatusResponse = z38.object({
|
|
7480
|
+
ok: z38.literal(true),
|
|
7481
|
+
operationId: z38.string().min(1),
|
|
7482
|
+
role: LandingRole,
|
|
7483
|
+
status: LandingRegenerationStatus,
|
|
7484
|
+
refunded: z38.boolean(),
|
|
7485
|
+
failureReason: z38.string().nullable(),
|
|
7486
|
+
publishedAssetKey: z38.string().nullable(),
|
|
7487
|
+
updatedAt: z38.string().datetime()
|
|
7488
|
+
});
|
|
7489
|
+
|
|
7490
|
+
// ../../packages/types/src/video-edit.ts
|
|
7491
|
+
import { z as z39 } from "zod";
|
|
7445
7492
|
var MAX_SEGMENT_SECONDS = 3;
|
|
7446
|
-
var VideoEditStatusSchema =
|
|
7493
|
+
var VideoEditStatusSchema = z39.enum([
|
|
7447
7494
|
"pending",
|
|
7448
7495
|
"processing",
|
|
7449
7496
|
"assembling",
|
|
@@ -7452,9 +7499,9 @@ var VideoEditStatusSchema = z38.enum([
|
|
|
7452
7499
|
"discarded",
|
|
7453
7500
|
"failed"
|
|
7454
7501
|
]);
|
|
7455
|
-
var VideoEditTimeSectionSchema =
|
|
7456
|
-
startSec:
|
|
7457
|
-
endSec:
|
|
7502
|
+
var VideoEditTimeSectionSchema = z39.object({
|
|
7503
|
+
startSec: z39.number().min(0),
|
|
7504
|
+
endSec: z39.number().positive()
|
|
7458
7505
|
}).refine((v) => v.endSec > v.startSec, {
|
|
7459
7506
|
message: "endSec must be after startSec",
|
|
7460
7507
|
path: [
|
|
@@ -7466,35 +7513,35 @@ var VideoEditTimeSectionSchema = z38.object({
|
|
|
7466
7513
|
"endSec"
|
|
7467
7514
|
]
|
|
7468
7515
|
});
|
|
7469
|
-
var VideoEditRequestSchema =
|
|
7470
|
-
comment:
|
|
7471
|
-
sections:
|
|
7516
|
+
var VideoEditRequestSchema = z39.object({
|
|
7517
|
+
comment: z39.string().trim().min(1).max(2e3),
|
|
7518
|
+
sections: z39.array(VideoEditTimeSectionSchema).min(1).optional()
|
|
7472
7519
|
});
|
|
7473
|
-
var VideoEditModeSchema =
|
|
7520
|
+
var VideoEditModeSchema = z39.enum([
|
|
7474
7521
|
"wan_edit",
|
|
7475
7522
|
"regenerate"
|
|
7476
7523
|
]);
|
|
7477
|
-
var VideoRegenerationEngineSchema =
|
|
7524
|
+
var VideoRegenerationEngineSchema = z39.enum([
|
|
7478
7525
|
"free_text",
|
|
7479
7526
|
"free_image",
|
|
7480
7527
|
"single_call",
|
|
7481
7528
|
"multi_shot"
|
|
7482
7529
|
]);
|
|
7483
|
-
var VideoRegenerationRouteFingerprintSchema =
|
|
7484
|
-
var RegenerateEditRequestSchema =
|
|
7485
|
-
angleKey:
|
|
7486
|
-
comment:
|
|
7530
|
+
var VideoRegenerationRouteFingerprintSchema = z39.string().trim().min(1).max(128);
|
|
7531
|
+
var RegenerateEditRequestSchema = z39.object({
|
|
7532
|
+
angleKey: z39.string().min(1),
|
|
7533
|
+
comment: z39.string().min(1).max(2e3)
|
|
7487
7534
|
});
|
|
7488
7535
|
|
|
7489
7536
|
// ../../packages/types/src/dropshipping-project.ts
|
|
7490
|
-
import { z as
|
|
7491
|
-
var DropshippingProjectStatusSchema =
|
|
7537
|
+
import { z as z40 } from "zod";
|
|
7538
|
+
var DropshippingProjectStatusSchema = z40.enum([
|
|
7492
7539
|
"active",
|
|
7493
7540
|
"completed",
|
|
7494
7541
|
"archived"
|
|
7495
7542
|
]);
|
|
7496
7543
|
var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
|
|
7497
|
-
var DropshippingRewardMilestoneSchema =
|
|
7544
|
+
var DropshippingRewardMilestoneSchema = z40.enum([
|
|
7498
7545
|
"product_selected",
|
|
7499
7546
|
"costing_saved",
|
|
7500
7547
|
"product_media_ready",
|
|
@@ -7509,21 +7556,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
|
|
|
7509
7556
|
campaign_created: 200
|
|
7510
7557
|
};
|
|
7511
7558
|
var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
|
|
7512
|
-
var DropshippingProjectRewardMilestoneStateSchema =
|
|
7559
|
+
var DropshippingProjectRewardMilestoneStateSchema = z40.object({
|
|
7513
7560
|
milestone: DropshippingRewardMilestoneSchema,
|
|
7514
|
-
credits:
|
|
7515
|
-
available:
|
|
7516
|
-
earned:
|
|
7517
|
-
grantId:
|
|
7518
|
-
grantedAt:
|
|
7519
|
-
});
|
|
7520
|
-
var DropshippingProjectRewardProgressSchema =
|
|
7521
|
-
campaignKey:
|
|
7522
|
-
totalCredits:
|
|
7523
|
-
earnedCredits:
|
|
7524
|
-
milestones:
|
|
7525
|
-
});
|
|
7526
|
-
var DropshippingProjectPhaseSchema =
|
|
7561
|
+
credits: z40.number().int().positive(),
|
|
7562
|
+
available: z40.boolean().optional(),
|
|
7563
|
+
earned: z40.boolean(),
|
|
7564
|
+
grantId: z40.string().uuid().nullable(),
|
|
7565
|
+
grantedAt: z40.string().datetime().nullable()
|
|
7566
|
+
});
|
|
7567
|
+
var DropshippingProjectRewardProgressSchema = z40.object({
|
|
7568
|
+
campaignKey: z40.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
|
|
7569
|
+
totalCredits: z40.number().int().positive(),
|
|
7570
|
+
earnedCredits: z40.number().int().nonnegative(),
|
|
7571
|
+
milestones: z40.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
|
|
7572
|
+
});
|
|
7573
|
+
var DropshippingProjectPhaseSchema = z40.enum([
|
|
7527
7574
|
"research",
|
|
7528
7575
|
"costing",
|
|
7529
7576
|
"media",
|
|
@@ -7532,18 +7579,18 @@ var DropshippingProjectPhaseSchema = z39.enum([
|
|
|
7532
7579
|
"advertising",
|
|
7533
7580
|
"complete"
|
|
7534
7581
|
]);
|
|
7535
|
-
var DropshippingProjectCostingInputSchema =
|
|
7536
|
-
country:
|
|
7537
|
-
supplierCost:
|
|
7538
|
-
shippingCost:
|
|
7539
|
-
returnRate:
|
|
7540
|
-
cancellationRate:
|
|
7541
|
-
adsManagerCpa:
|
|
7542
|
-
desiredMargin:
|
|
7582
|
+
var DropshippingProjectCostingInputSchema = z40.object({
|
|
7583
|
+
country: z40.string().min(2).max(3),
|
|
7584
|
+
supplierCost: z40.number().finite().positive(),
|
|
7585
|
+
shippingCost: z40.number().finite().nonnegative(),
|
|
7586
|
+
returnRate: z40.number().finite().min(0).lt(1),
|
|
7587
|
+
cancellationRate: z40.number().finite().min(0).lt(1),
|
|
7588
|
+
adsManagerCpa: z40.number().finite().nonnegative(),
|
|
7589
|
+
desiredMargin: z40.number().finite().min(0).lt(1)
|
|
7543
7590
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
7544
7591
|
if (returnRate + cancellationRate >= 1) {
|
|
7545
7592
|
context.addIssue({
|
|
7546
|
-
code:
|
|
7593
|
+
code: z40.ZodIssueCode.custom,
|
|
7547
7594
|
path: [
|
|
7548
7595
|
"cancellationRate"
|
|
7549
7596
|
],
|
|
@@ -7551,24 +7598,24 @@ var DropshippingProjectCostingInputSchema = z39.object({
|
|
|
7551
7598
|
});
|
|
7552
7599
|
}
|
|
7553
7600
|
});
|
|
7554
|
-
var DropshippingProjectCostingResultSchema =
|
|
7555
|
-
country:
|
|
7556
|
-
deliveryRate:
|
|
7557
|
-
adjustedShippingCost:
|
|
7558
|
-
adjustedCpa:
|
|
7559
|
-
totalCost:
|
|
7560
|
-
suggestedPrice:
|
|
7561
|
-
baseCommercialPrice:
|
|
7562
|
-
minimumSafePrice:
|
|
7563
|
-
commercialPrice:
|
|
7564
|
-
comparisonPrice:
|
|
7565
|
-
estimatedProfit:
|
|
7566
|
-
actualMargin:
|
|
7567
|
-
breakEvenAdsManagerCpa:
|
|
7568
|
-
wasPriceAutoAdjusted:
|
|
7569
|
-
profitabilityStatus:
|
|
7570
|
-
});
|
|
7571
|
-
var HttpUrlSchema =
|
|
7601
|
+
var DropshippingProjectCostingResultSchema = z40.object({
|
|
7602
|
+
country: z40.string().min(2).max(3),
|
|
7603
|
+
deliveryRate: z40.number().finite(),
|
|
7604
|
+
adjustedShippingCost: z40.number().finite(),
|
|
7605
|
+
adjustedCpa: z40.number().finite(),
|
|
7606
|
+
totalCost: z40.number().finite(),
|
|
7607
|
+
suggestedPrice: z40.number().finite(),
|
|
7608
|
+
baseCommercialPrice: z40.number().finite(),
|
|
7609
|
+
minimumSafePrice: z40.number().finite(),
|
|
7610
|
+
commercialPrice: z40.number().finite(),
|
|
7611
|
+
comparisonPrice: z40.number().finite(),
|
|
7612
|
+
estimatedProfit: z40.number().finite(),
|
|
7613
|
+
actualMargin: z40.number().finite(),
|
|
7614
|
+
breakEvenAdsManagerCpa: z40.number().finite(),
|
|
7615
|
+
wasPriceAutoAdjusted: z40.boolean(),
|
|
7616
|
+
profitabilityStatus: z40.literal("healthy")
|
|
7617
|
+
});
|
|
7618
|
+
var HttpUrlSchema = z40.string().url().max(2e3).refine((value) => {
|
|
7572
7619
|
try {
|
|
7573
7620
|
return [
|
|
7574
7621
|
"http:",
|
|
@@ -7578,124 +7625,124 @@ var HttpUrlSchema = z39.string().url().max(2e3).refine((value) => {
|
|
|
7578
7625
|
return false;
|
|
7579
7626
|
}
|
|
7580
7627
|
}, "Product URL must use HTTP(S)");
|
|
7581
|
-
var ResearchCandidateOriginSchema =
|
|
7582
|
-
type:
|
|
7583
|
-
runId:
|
|
7584
|
-
candidateSourceId:
|
|
7585
|
-
});
|
|
7586
|
-
var TaskOriginSchema =
|
|
7587
|
-
type:
|
|
7588
|
-
taskId:
|
|
7589
|
-
});
|
|
7590
|
-
var ManualOriginSchema =
|
|
7591
|
-
type:
|
|
7592
|
-
clientRequestId:
|
|
7593
|
-
country:
|
|
7594
|
-
});
|
|
7595
|
-
var CreateDropshippingProjectRequestSchema =
|
|
7596
|
-
origin:
|
|
7628
|
+
var ResearchCandidateOriginSchema = z40.object({
|
|
7629
|
+
type: z40.literal("research_candidate"),
|
|
7630
|
+
runId: z40.string().uuid(),
|
|
7631
|
+
candidateSourceId: z40.string().min(1).max(160)
|
|
7632
|
+
});
|
|
7633
|
+
var TaskOriginSchema = z40.object({
|
|
7634
|
+
type: z40.literal("task"),
|
|
7635
|
+
taskId: z40.string().uuid()
|
|
7636
|
+
});
|
|
7637
|
+
var ManualOriginSchema = z40.object({
|
|
7638
|
+
type: z40.literal("manual"),
|
|
7639
|
+
clientRequestId: z40.string().uuid(),
|
|
7640
|
+
country: z40.string().min(2).max(3).optional()
|
|
7641
|
+
});
|
|
7642
|
+
var CreateDropshippingProjectRequestSchema = z40.object({
|
|
7643
|
+
origin: z40.discriminatedUnion("type", [
|
|
7597
7644
|
ResearchCandidateOriginSchema,
|
|
7598
7645
|
TaskOriginSchema,
|
|
7599
7646
|
ManualOriginSchema
|
|
7600
7647
|
]),
|
|
7601
|
-
productName:
|
|
7648
|
+
productName: z40.string().trim().min(1).max(240).optional(),
|
|
7602
7649
|
productUrl: HttpUrlSchema.optional(),
|
|
7603
|
-
country:
|
|
7604
|
-
languageCode:
|
|
7650
|
+
country: z40.string().min(2).max(3).optional(),
|
|
7651
|
+
languageCode: z40.string().min(2).max(16).optional()
|
|
7605
7652
|
}).strict();
|
|
7606
|
-
var SaveDropshippingProjectCostingRequestSchema =
|
|
7653
|
+
var SaveDropshippingProjectCostingRequestSchema = z40.object({
|
|
7607
7654
|
input: DropshippingProjectCostingInputSchema,
|
|
7608
|
-
version:
|
|
7655
|
+
version: z40.number().int().positive()
|
|
7609
7656
|
}).strict();
|
|
7610
|
-
var DropshippingProjectNextActionSchema =
|
|
7611
|
-
|
|
7612
|
-
kind:
|
|
7613
|
-
href:
|
|
7657
|
+
var DropshippingProjectNextActionSchema = z40.discriminatedUnion("kind", [
|
|
7658
|
+
z40.object({
|
|
7659
|
+
kind: z40.literal("cost_product"),
|
|
7660
|
+
href: z40.string().min(1)
|
|
7614
7661
|
}),
|
|
7615
|
-
|
|
7616
|
-
kind:
|
|
7617
|
-
href:
|
|
7662
|
+
z40.object({
|
|
7663
|
+
kind: z40.literal("provide_product_media"),
|
|
7664
|
+
href: z40.string().min(1)
|
|
7618
7665
|
}),
|
|
7619
|
-
|
|
7620
|
-
kind:
|
|
7621
|
-
href:
|
|
7666
|
+
z40.object({
|
|
7667
|
+
kind: z40.literal("generate_creatives"),
|
|
7668
|
+
href: z40.string().min(1)
|
|
7622
7669
|
}),
|
|
7623
|
-
|
|
7624
|
-
kind:
|
|
7625
|
-
href:
|
|
7670
|
+
z40.object({
|
|
7671
|
+
kind: z40.literal("wait_for_creatives"),
|
|
7672
|
+
href: z40.string().min(1)
|
|
7626
7673
|
}),
|
|
7627
|
-
|
|
7628
|
-
kind:
|
|
7629
|
-
href:
|
|
7674
|
+
z40.object({
|
|
7675
|
+
kind: z40.literal("repair_creatives"),
|
|
7676
|
+
href: z40.string().min(1)
|
|
7630
7677
|
}),
|
|
7631
|
-
|
|
7632
|
-
kind:
|
|
7633
|
-
href:
|
|
7678
|
+
z40.object({
|
|
7679
|
+
kind: z40.literal("complete_creative_set"),
|
|
7680
|
+
href: z40.string().min(1)
|
|
7634
7681
|
}),
|
|
7635
|
-
|
|
7636
|
-
kind:
|
|
7637
|
-
href:
|
|
7682
|
+
z40.object({
|
|
7683
|
+
kind: z40.literal("connect_shopify"),
|
|
7684
|
+
href: z40.string().min(1)
|
|
7638
7685
|
}),
|
|
7639
|
-
|
|
7640
|
-
kind:
|
|
7641
|
-
href:
|
|
7686
|
+
z40.object({
|
|
7687
|
+
kind: z40.literal("publish_storefront"),
|
|
7688
|
+
href: z40.string().min(1)
|
|
7642
7689
|
}),
|
|
7643
|
-
|
|
7644
|
-
kind:
|
|
7645
|
-
href:
|
|
7690
|
+
z40.object({
|
|
7691
|
+
kind: z40.literal("wait_for_storefront"),
|
|
7692
|
+
href: z40.string().min(1)
|
|
7646
7693
|
}),
|
|
7647
|
-
|
|
7648
|
-
kind:
|
|
7649
|
-
href:
|
|
7694
|
+
z40.object({
|
|
7695
|
+
kind: z40.literal("connect_meta"),
|
|
7696
|
+
href: z40.string().min(1)
|
|
7650
7697
|
}),
|
|
7651
|
-
|
|
7652
|
-
kind:
|
|
7653
|
-
href:
|
|
7698
|
+
z40.object({
|
|
7699
|
+
kind: z40.literal("create_meta_campaign"),
|
|
7700
|
+
href: z40.string().min(1)
|
|
7654
7701
|
}),
|
|
7655
|
-
|
|
7656
|
-
kind:
|
|
7657
|
-
href:
|
|
7702
|
+
z40.object({
|
|
7703
|
+
kind: z40.literal("repair_meta_campaign"),
|
|
7704
|
+
href: z40.string().min(1)
|
|
7658
7705
|
}),
|
|
7659
|
-
|
|
7660
|
-
kind:
|
|
7661
|
-
href:
|
|
7706
|
+
z40.object({
|
|
7707
|
+
kind: z40.literal("review_paused_campaign"),
|
|
7708
|
+
href: z40.string().min(1)
|
|
7662
7709
|
})
|
|
7663
7710
|
]);
|
|
7664
|
-
var DropshippingProjectResponseSchema =
|
|
7665
|
-
id:
|
|
7666
|
-
taskId:
|
|
7711
|
+
var DropshippingProjectResponseSchema = z40.object({
|
|
7712
|
+
id: z40.string().uuid(),
|
|
7713
|
+
taskId: z40.string().uuid().nullable(),
|
|
7667
7714
|
status: DropshippingProjectStatusSchema,
|
|
7668
|
-
originKey:
|
|
7669
|
-
researchRunId:
|
|
7670
|
-
candidateSourceId:
|
|
7671
|
-
productName:
|
|
7715
|
+
originKey: z40.string().min(1),
|
|
7716
|
+
researchRunId: z40.string().uuid().nullable(),
|
|
7717
|
+
candidateSourceId: z40.string().nullable(),
|
|
7718
|
+
productName: z40.string().nullable(),
|
|
7672
7719
|
productUrl: HttpUrlSchema.nullable(),
|
|
7673
|
-
referenceImageUrl:
|
|
7674
|
-
hasReferenceImage:
|
|
7675
|
-
targetCountry:
|
|
7676
|
-
languageCode:
|
|
7720
|
+
referenceImageUrl: z40.string().url().nullable(),
|
|
7721
|
+
hasReferenceImage: z40.boolean(),
|
|
7722
|
+
targetCountry: z40.string().nullable(),
|
|
7723
|
+
languageCode: z40.string().nullable(),
|
|
7677
7724
|
costingInput: DropshippingProjectCostingInputSchema.nullable(),
|
|
7678
7725
|
costingResult: DropshippingProjectCostingResultSchema.nullable(),
|
|
7679
|
-
costingVersion:
|
|
7680
|
-
version:
|
|
7726
|
+
costingVersion: z40.number().int().positive().nullable(),
|
|
7727
|
+
version: z40.number().int().positive(),
|
|
7681
7728
|
phase: DropshippingProjectPhaseSchema,
|
|
7682
7729
|
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
7683
7730
|
rewards: DropshippingProjectRewardProgressSchema,
|
|
7684
|
-
createdAt:
|
|
7685
|
-
updatedAt:
|
|
7731
|
+
createdAt: z40.string().datetime(),
|
|
7732
|
+
updatedAt: z40.string().datetime()
|
|
7686
7733
|
});
|
|
7687
7734
|
|
|
7688
7735
|
// ../../packages/types/src/scene-subject-contract.ts
|
|
7689
|
-
import { z as
|
|
7690
|
-
var SceneSubjectContractSchema =
|
|
7691
|
-
maxPeople:
|
|
7692
|
-
minPeople:
|
|
7693
|
-
minDistinctPeople:
|
|
7694
|
-
maxHands:
|
|
7736
|
+
import { z as z41 } from "zod";
|
|
7737
|
+
var SceneSubjectContractSchema = z41.object({
|
|
7738
|
+
maxPeople: z41.number().int().min(1).max(10),
|
|
7739
|
+
minPeople: z41.number().int().min(0).max(10),
|
|
7740
|
+
minDistinctPeople: z41.number().int().min(0).max(10),
|
|
7741
|
+
maxHands: z41.number().int().min(0).max(20)
|
|
7695
7742
|
}).superRefine((value, ctx) => {
|
|
7696
7743
|
if (value.minPeople > value.maxPeople) {
|
|
7697
7744
|
ctx.addIssue({
|
|
7698
|
-
code:
|
|
7745
|
+
code: z41.ZodIssueCode.custom,
|
|
7699
7746
|
path: [
|
|
7700
7747
|
"minPeople"
|
|
7701
7748
|
],
|
|
@@ -7704,7 +7751,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7704
7751
|
}
|
|
7705
7752
|
if (value.minDistinctPeople > value.maxPeople) {
|
|
7706
7753
|
ctx.addIssue({
|
|
7707
|
-
code:
|
|
7754
|
+
code: z41.ZodIssueCode.custom,
|
|
7708
7755
|
path: [
|
|
7709
7756
|
"minDistinctPeople"
|
|
7710
7757
|
],
|
|
@@ -7713,7 +7760,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7713
7760
|
}
|
|
7714
7761
|
if (value.minDistinctPeople > value.minPeople) {
|
|
7715
7762
|
ctx.addIssue({
|
|
7716
|
-
code:
|
|
7763
|
+
code: z41.ZodIssueCode.custom,
|
|
7717
7764
|
path: [
|
|
7718
7765
|
"minDistinctPeople"
|
|
7719
7766
|
],
|
|
@@ -7723,7 +7770,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7723
7770
|
});
|
|
7724
7771
|
|
|
7725
7772
|
// ../../packages/types/src/service-creative.ts
|
|
7726
|
-
import { z as
|
|
7773
|
+
import { z as z42 } from "zod";
|
|
7727
7774
|
var SERVICE_CREATIVE_PUBLIC_PRESETS = [
|
|
7728
7775
|
"auto",
|
|
7729
7776
|
"ugc_dynamic",
|
|
@@ -7731,19 +7778,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
|
|
|
7731
7778
|
"cinematic",
|
|
7732
7779
|
"wild_card"
|
|
7733
7780
|
];
|
|
7734
|
-
var ServiceCreativePresetSchema =
|
|
7781
|
+
var ServiceCreativePresetSchema = z42.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
|
|
7735
7782
|
var SERVICE_REVIEW_MODES = [
|
|
7736
7783
|
"automatic",
|
|
7737
7784
|
"guided"
|
|
7738
7785
|
];
|
|
7739
|
-
var ServiceReviewModeSchema =
|
|
7786
|
+
var ServiceReviewModeSchema = z42.enum(SERVICE_REVIEW_MODES);
|
|
7740
7787
|
var SERVICE_HIGGSFIELD_MODES = [
|
|
7741
7788
|
"product_review",
|
|
7742
7789
|
"ugc_how_to",
|
|
7743
7790
|
"tv_spot",
|
|
7744
7791
|
"wild_card"
|
|
7745
7792
|
];
|
|
7746
|
-
var ServiceHiggsfieldModeSchema =
|
|
7793
|
+
var ServiceHiggsfieldModeSchema = z42.enum(SERVICE_HIGGSFIELD_MODES);
|
|
7747
7794
|
var SERVICE_MEDIA_ROLES = [
|
|
7748
7795
|
"screen_demo",
|
|
7749
7796
|
"ad_reference",
|
|
@@ -7751,20 +7798,20 @@ var SERVICE_MEDIA_ROLES = [
|
|
|
7751
7798
|
"presenter_reference",
|
|
7752
7799
|
"brand_asset"
|
|
7753
7800
|
];
|
|
7754
|
-
var ServiceMediaRoleSchema =
|
|
7755
|
-
var ServiceMediaAssetSchema =
|
|
7801
|
+
var ServiceMediaRoleSchema = z42.enum(SERVICE_MEDIA_ROLES);
|
|
7802
|
+
var ServiceMediaAssetSchema = z42.object({
|
|
7756
7803
|
role: ServiceMediaRoleSchema,
|
|
7757
|
-
s3Key:
|
|
7804
|
+
s3Key: z42.string().min(1),
|
|
7758
7805
|
/** HMAC ticket returned by the authenticated service-media presign route. */
|
|
7759
|
-
uploadToken:
|
|
7760
|
-
mimeType:
|
|
7761
|
-
durationSec:
|
|
7762
|
-
sourceName:
|
|
7806
|
+
uploadToken: z42.string().min(1).optional(),
|
|
7807
|
+
mimeType: z42.string().min(1),
|
|
7808
|
+
durationSec: z42.number().positive().max(30).optional(),
|
|
7809
|
+
sourceName: z42.string().max(255).optional()
|
|
7763
7810
|
}).superRefine((asset, ctx) => {
|
|
7764
7811
|
const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
|
|
7765
7812
|
if (isVideoRole && !asset.mimeType.startsWith("video/")) {
|
|
7766
7813
|
ctx.addIssue({
|
|
7767
|
-
code:
|
|
7814
|
+
code: z42.ZodIssueCode.custom,
|
|
7768
7815
|
message: `${asset.role} requires video media`,
|
|
7769
7816
|
path: [
|
|
7770
7817
|
"mimeType"
|
|
@@ -7773,7 +7820,7 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7773
7820
|
}
|
|
7774
7821
|
if (isVideoRole && asset.durationSec === void 0) {
|
|
7775
7822
|
ctx.addIssue({
|
|
7776
|
-
code:
|
|
7823
|
+
code: z42.ZodIssueCode.custom,
|
|
7777
7824
|
message: `${asset.role} requires durationSec`,
|
|
7778
7825
|
path: [
|
|
7779
7826
|
"durationSec"
|
|
@@ -7782,7 +7829,7 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7782
7829
|
}
|
|
7783
7830
|
if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
|
|
7784
7831
|
ctx.addIssue({
|
|
7785
|
-
code:
|
|
7832
|
+
code: z42.ZodIssueCode.custom,
|
|
7786
7833
|
message: `${asset.role} requires image media`,
|
|
7787
7834
|
path: [
|
|
7788
7835
|
"mimeType"
|
|
@@ -7790,13 +7837,13 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7790
7837
|
});
|
|
7791
7838
|
}
|
|
7792
7839
|
});
|
|
7793
|
-
var ServiceMediaBundleSchema =
|
|
7794
|
-
assets:
|
|
7840
|
+
var ServiceMediaBundleSchema = z42.object({
|
|
7841
|
+
assets: z42.array(ServiceMediaAssetSchema).max(15).default([])
|
|
7795
7842
|
}).superRefine((bundle, ctx) => {
|
|
7796
7843
|
const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
|
|
7797
7844
|
if (adReferences.length > 5) {
|
|
7798
7845
|
ctx.addIssue({
|
|
7799
|
-
code:
|
|
7846
|
+
code: z42.ZodIssueCode.custom,
|
|
7800
7847
|
message: "A maximum of five ad_reference videos is allowed",
|
|
7801
7848
|
path: [
|
|
7802
7849
|
"assets"
|
|
@@ -7806,7 +7853,7 @@ var ServiceMediaBundleSchema = z41.object({
|
|
|
7806
7853
|
const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
|
|
7807
7854
|
if (screenDemos.length > 3) {
|
|
7808
7855
|
ctx.addIssue({
|
|
7809
|
-
code:
|
|
7856
|
+
code: z42.ZodIssueCode.custom,
|
|
7810
7857
|
message: "A maximum of three screen_demo videos is allowed",
|
|
7811
7858
|
path: [
|
|
7812
7859
|
"assets"
|
|
@@ -7823,33 +7870,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
|
|
|
7823
7870
|
"product",
|
|
7824
7871
|
"other"
|
|
7825
7872
|
];
|
|
7826
|
-
var ServiceMediaAnalysisKindSchema =
|
|
7827
|
-
var ServiceMediaAnalysisItemSchema =
|
|
7828
|
-
assetIndex:
|
|
7829
|
-
mediaType:
|
|
7873
|
+
var ServiceMediaAnalysisKindSchema = z42.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
|
|
7874
|
+
var ServiceMediaAnalysisItemSchema = z42.object({
|
|
7875
|
+
assetIndex: z42.number().int().nonnegative(),
|
|
7876
|
+
mediaType: z42.enum([
|
|
7830
7877
|
"image",
|
|
7831
7878
|
"video"
|
|
7832
7879
|
]),
|
|
7833
7880
|
kind: ServiceMediaAnalysisKindSchema,
|
|
7834
|
-
description:
|
|
7835
|
-
tags:
|
|
7836
|
-
suggestedRoles:
|
|
7837
|
-
visiblePeople:
|
|
7838
|
-
ocrText:
|
|
7839
|
-
speechSummary:
|
|
7840
|
-
});
|
|
7841
|
-
var ServiceMediaAnalysisSchema =
|
|
7842
|
-
version:
|
|
7843
|
-
analyzedAt:
|
|
7844
|
-
pricingAction:
|
|
7845
|
-
assetFingerprint:
|
|
7881
|
+
description: z42.string().min(1).max(1200),
|
|
7882
|
+
tags: z42.array(z42.string().min(1).max(80)).max(12),
|
|
7883
|
+
suggestedRoles: z42.array(ServiceMediaRoleSchema).max(4),
|
|
7884
|
+
visiblePeople: z42.number().int().nonnegative().max(20).optional(),
|
|
7885
|
+
ocrText: z42.string().max(2e3).optional(),
|
|
7886
|
+
speechSummary: z42.string().max(2e3).optional()
|
|
7887
|
+
});
|
|
7888
|
+
var ServiceMediaAnalysisSchema = z42.object({
|
|
7889
|
+
version: z42.literal(1),
|
|
7890
|
+
analyzedAt: z42.string().datetime(),
|
|
7891
|
+
pricingAction: z42.literal("service-media-analysis"),
|
|
7892
|
+
assetFingerprint: z42.string().regex(/^[a-f0-9]{64}$/),
|
|
7846
7893
|
/** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
|
|
7847
|
-
language:
|
|
7894
|
+
language: z42.enum([
|
|
7848
7895
|
"es",
|
|
7849
7896
|
"en",
|
|
7850
7897
|
"pt"
|
|
7851
7898
|
]).optional(),
|
|
7852
|
-
items:
|
|
7899
|
+
items: z42.array(ServiceMediaAnalysisItemSchema).max(15)
|
|
7853
7900
|
});
|
|
7854
7901
|
|
|
7855
7902
|
// ../../packages/types/src/productmaker-chat-capabilities.ts
|
|
@@ -8027,7 +8074,7 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
8027
8074
|
{
|
|
8028
8075
|
name: "request_meta_media_upload",
|
|
8029
8076
|
confirmation: "none",
|
|
8030
|
-
schemaHash: "
|
|
8077
|
+
schemaHash: "fad928b17b4658eb5831bb8b62d5e65bd5220ad94b04b90ace09e658e1895c74"
|
|
8031
8078
|
},
|
|
8032
8079
|
{
|
|
8033
8080
|
name: "resolve_pending_action",
|
|
@@ -8043,8 +8090,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
8043
8090
|
var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITIES.map((capability) => capability.name);
|
|
8044
8091
|
|
|
8045
8092
|
// ../../packages/types/src/actor.ts
|
|
8046
|
-
import { z as
|
|
8047
|
-
var ActorStatusSchema =
|
|
8093
|
+
import { z as z43 } from "zod";
|
|
8094
|
+
var ActorStatusSchema = z43.enum([
|
|
8048
8095
|
"draft",
|
|
8049
8096
|
"generating",
|
|
8050
8097
|
"ready",
|
|
@@ -8053,18 +8100,18 @@ var ActorStatusSchema = z42.enum([
|
|
|
8053
8100
|
var ACTOR_NAME_MAX_CHARS = 60;
|
|
8054
8101
|
var ACTOR_DESCRIPTION_MAX_CHARS = 600;
|
|
8055
8102
|
var ACTOR_CANDIDATE_COUNT = 4;
|
|
8056
|
-
var ActorGenderSchema =
|
|
8103
|
+
var ActorGenderSchema = z43.enum([
|
|
8057
8104
|
"female",
|
|
8058
8105
|
"male",
|
|
8059
8106
|
"non_binary"
|
|
8060
8107
|
]);
|
|
8061
|
-
var ActorSchema =
|
|
8062
|
-
id:
|
|
8063
|
-
name:
|
|
8064
|
-
description:
|
|
8108
|
+
var ActorSchema = z43.object({
|
|
8109
|
+
id: z43.string(),
|
|
8110
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS),
|
|
8111
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
|
|
8065
8112
|
gender: ActorGenderSchema,
|
|
8066
|
-
voiceId:
|
|
8067
|
-
brandId:
|
|
8113
|
+
voiceId: z43.string().nullable().optional(),
|
|
8114
|
+
brandId: z43.string().nullable().optional(),
|
|
8068
8115
|
status: ActorStatusSchema,
|
|
8069
8116
|
/**
|
|
8070
8117
|
* A candidate-grid run is in flight RIGHT NOW.
|
|
@@ -8076,36 +8123,36 @@ var ActorSchema = z42.object({
|
|
|
8076
8123
|
* timestamp with a TTL, so an orphaned run reads as `false` instead of
|
|
8077
8124
|
* pinning the personaje forever.
|
|
8078
8125
|
*/
|
|
8079
|
-
generating:
|
|
8080
|
-
photoUrl:
|
|
8081
|
-
avatarUrl:
|
|
8082
|
-
candidateUrls:
|
|
8126
|
+
generating: z43.boolean().optional(),
|
|
8127
|
+
photoUrl: z43.string().url().nullable().optional(),
|
|
8128
|
+
avatarUrl: z43.string().url().nullable().optional(),
|
|
8129
|
+
candidateUrls: z43.array(z43.string().url()).optional(),
|
|
8083
8130
|
/** Indices of candidateUrls that failed the anatomy check (Task 6). */
|
|
8084
|
-
flaggedCandidateIndices:
|
|
8131
|
+
flaggedCandidateIndices: z43.array(z43.number().int()).optional()
|
|
8085
8132
|
});
|
|
8086
|
-
var CreateActorRequest =
|
|
8087
|
-
name:
|
|
8088
|
-
description:
|
|
8133
|
+
var CreateActorRequest = z43.object({
|
|
8134
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS),
|
|
8135
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
|
|
8089
8136
|
gender: ActorGenderSchema,
|
|
8090
|
-
voiceId:
|
|
8091
|
-
brandId:
|
|
8092
|
-
sourcePhotoKey:
|
|
8137
|
+
voiceId: z43.string().optional(),
|
|
8138
|
+
brandId: z43.string().optional(),
|
|
8139
|
+
sourcePhotoKey: z43.string().optional()
|
|
8093
8140
|
}).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
|
|
8094
8141
|
message: "Se necesita una descripci\xF3n o una foto"
|
|
8095
8142
|
});
|
|
8096
|
-
var UpdateActorRequest =
|
|
8097
|
-
name:
|
|
8098
|
-
description:
|
|
8143
|
+
var UpdateActorRequest = z43.object({
|
|
8144
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
|
|
8145
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
|
|
8099
8146
|
gender: ActorGenderSchema.optional(),
|
|
8100
|
-
voiceId:
|
|
8101
|
-
brandId:
|
|
8147
|
+
voiceId: z43.string().nullable().optional(),
|
|
8148
|
+
brandId: z43.string().nullable().optional()
|
|
8102
8149
|
});
|
|
8103
|
-
var ApproveActorRequest =
|
|
8104
|
-
candidateIndex:
|
|
8150
|
+
var ApproveActorRequest = z43.object({
|
|
8151
|
+
candidateIndex: z43.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
|
|
8105
8152
|
});
|
|
8106
8153
|
|
|
8107
8154
|
// ../../packages/types/src/referral-dashboard.ts
|
|
8108
|
-
import { z as
|
|
8155
|
+
import { z as z44 } from "zod";
|
|
8109
8156
|
var REFERRAL_DASHBOARD_RAW_STATUSES = [
|
|
8110
8157
|
"ACTIVE",
|
|
8111
8158
|
"PENDING",
|
|
@@ -8124,66 +8171,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
|
|
|
8124
8171
|
"last",
|
|
8125
8172
|
"none"
|
|
8126
8173
|
];
|
|
8127
|
-
var ReferralDashboardRawStatusSchema =
|
|
8128
|
-
var ReferralDashboardStateSchema =
|
|
8129
|
-
var ReferralDashboardPlanKindSchema =
|
|
8130
|
-
var ReferralDashboardStatusSchema =
|
|
8174
|
+
var ReferralDashboardRawStatusSchema = z44.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
|
|
8175
|
+
var ReferralDashboardStateSchema = z44.enum(REFERRAL_DASHBOARD_STATES);
|
|
8176
|
+
var ReferralDashboardPlanKindSchema = z44.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
|
|
8177
|
+
var ReferralDashboardStatusSchema = z44.enum([
|
|
8131
8178
|
"all",
|
|
8132
8179
|
"active",
|
|
8133
8180
|
"pending",
|
|
8134
8181
|
"inactive"
|
|
8135
8182
|
]).default("all");
|
|
8136
|
-
var ReferralDashboardPlanSchema =
|
|
8137
|
-
var ReferralDashboardFiltersSchema =
|
|
8183
|
+
var ReferralDashboardPlanSchema = z44.string().trim().min(1).max(100).optional();
|
|
8184
|
+
var ReferralDashboardFiltersSchema = z44.object({
|
|
8138
8185
|
status: ReferralDashboardStatusSchema,
|
|
8139
8186
|
plan: ReferralDashboardPlanSchema
|
|
8140
8187
|
});
|
|
8141
|
-
var ReferralDashboardSubscriptionSchema =
|
|
8142
|
-
planName:
|
|
8188
|
+
var ReferralDashboardSubscriptionSchema = z44.object({
|
|
8189
|
+
planName: z44.string().nullable(),
|
|
8143
8190
|
planKind: ReferralDashboardPlanKindSchema,
|
|
8144
8191
|
rawStatus: ReferralDashboardRawStatusSchema.nullable(),
|
|
8145
8192
|
state: ReferralDashboardStateSchema,
|
|
8146
|
-
currentPeriodEnd:
|
|
8193
|
+
currentPeriodEnd: z44.string().datetime({
|
|
8147
8194
|
offset: true
|
|
8148
8195
|
}).nullable(),
|
|
8149
|
-
cancelAtPeriodEnd:
|
|
8196
|
+
cancelAtPeriodEnd: z44.boolean()
|
|
8150
8197
|
});
|
|
8151
|
-
var ReferralDashboardReferralSchema =
|
|
8152
|
-
id:
|
|
8153
|
-
registeredAt:
|
|
8198
|
+
var ReferralDashboardReferralSchema = z44.object({
|
|
8199
|
+
id: z44.string().min(1),
|
|
8200
|
+
registeredAt: z44.string().datetime({
|
|
8154
8201
|
offset: true
|
|
8155
8202
|
}),
|
|
8156
8203
|
// Kept in the response for compatibility with existing referral API clients.
|
|
8157
8204
|
// The referrer dashboard intentionally does not render these legacy fields.
|
|
8158
|
-
expiresAt:
|
|
8205
|
+
expiresAt: z44.string().datetime({
|
|
8159
8206
|
offset: true
|
|
8160
8207
|
}).nullable().optional(),
|
|
8161
|
-
status:
|
|
8162
|
-
referredUser:
|
|
8163
|
-
email:
|
|
8208
|
+
status: z44.string().min(1).optional(),
|
|
8209
|
+
referredUser: z44.object({
|
|
8210
|
+
email: z44.string().nullable()
|
|
8164
8211
|
}),
|
|
8165
8212
|
subscription: ReferralDashboardSubscriptionSchema
|
|
8166
8213
|
});
|
|
8167
|
-
var ReferralDashboardReferralsPageSchema =
|
|
8168
|
-
referrals:
|
|
8169
|
-
total:
|
|
8214
|
+
var ReferralDashboardReferralsPageSchema = z44.object({
|
|
8215
|
+
referrals: z44.array(ReferralDashboardReferralSchema),
|
|
8216
|
+
total: z44.number().int().nonnegative()
|
|
8170
8217
|
});
|
|
8171
|
-
var ReferralDashboardPlanBreakdownSchema =
|
|
8172
|
-
planName:
|
|
8173
|
-
count:
|
|
8218
|
+
var ReferralDashboardPlanBreakdownSchema = z44.object({
|
|
8219
|
+
planName: z44.string().nullable(),
|
|
8220
|
+
count: z44.number().int().nonnegative()
|
|
8174
8221
|
});
|
|
8175
|
-
var ReferralDashboardMonthlyRegistrationSchema =
|
|
8176
|
-
month:
|
|
8177
|
-
count:
|
|
8222
|
+
var ReferralDashboardMonthlyRegistrationSchema = z44.object({
|
|
8223
|
+
month: z44.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
|
|
8224
|
+
count: z44.number().int().nonnegative()
|
|
8178
8225
|
});
|
|
8179
|
-
var ReferralDashboardOverviewSchema =
|
|
8180
|
-
totalReferredUsers:
|
|
8181
|
-
activeUsers:
|
|
8182
|
-
pendingUsers:
|
|
8183
|
-
inactiveUsers:
|
|
8184
|
-
noPlanUsers:
|
|
8185
|
-
planBreakdown:
|
|
8186
|
-
monthlyRegistrations:
|
|
8226
|
+
var ReferralDashboardOverviewSchema = z44.object({
|
|
8227
|
+
totalReferredUsers: z44.number().int().nonnegative(),
|
|
8228
|
+
activeUsers: z44.number().int().nonnegative(),
|
|
8229
|
+
pendingUsers: z44.number().int().nonnegative(),
|
|
8230
|
+
inactiveUsers: z44.number().int().nonnegative(),
|
|
8231
|
+
noPlanUsers: z44.number().int().nonnegative(),
|
|
8232
|
+
planBreakdown: z44.array(ReferralDashboardPlanBreakdownSchema),
|
|
8233
|
+
monthlyRegistrations: z44.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
|
|
8187
8234
|
});
|
|
8188
8235
|
|
|
8189
8236
|
// src/resolve-media.ts
|
|
@@ -8425,10 +8472,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
8425
8472
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
8426
8473
|
|
|
8427
8474
|
// src/tools/shared.ts
|
|
8428
|
-
import { z as
|
|
8429
|
-
var Lang =
|
|
8430
|
-
var Country =
|
|
8431
|
-
var LandingStrategyEnum =
|
|
8475
|
+
import { z as z45 } from "zod";
|
|
8476
|
+
var Lang = z45.string().min(2).max(10);
|
|
8477
|
+
var Country = z45.string().min(2).max(3);
|
|
8478
|
+
var LandingStrategyEnum = z45.enum([
|
|
8432
8479
|
"auto",
|
|
8433
8480
|
"classic",
|
|
8434
8481
|
"pain_solution",
|
|
@@ -8437,12 +8484,12 @@ var LandingStrategyEnum = z44.enum([
|
|
|
8437
8484
|
"offer_value",
|
|
8438
8485
|
"lifestyle_identity"
|
|
8439
8486
|
]);
|
|
8440
|
-
var LandingImageFormatEnum =
|
|
8487
|
+
var LandingImageFormatEnum = z45.enum([
|
|
8441
8488
|
"9:16",
|
|
8442
8489
|
"4:5",
|
|
8443
8490
|
"1:1"
|
|
8444
8491
|
]);
|
|
8445
|
-
var VideoPresetEnum =
|
|
8492
|
+
var VideoPresetEnum = z45.enum([
|
|
8446
8493
|
"auto",
|
|
8447
8494
|
"ugc_dynamic",
|
|
8448
8495
|
"ugc_how_to",
|
|
@@ -8455,7 +8502,7 @@ var VideoPresetEnum = z44.enum([
|
|
|
8455
8502
|
"pixar_problem",
|
|
8456
8503
|
"pixar_sassy"
|
|
8457
8504
|
]);
|
|
8458
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
8505
|
+
var TaskCreativeVariantVideoPresetEnum = z45.enum([
|
|
8459
8506
|
"auto",
|
|
8460
8507
|
"ugc_dynamic",
|
|
8461
8508
|
"ugc_how_to",
|
|
@@ -8526,7 +8573,7 @@ function resolveVideoPreset(preset) {
|
|
|
8526
8573
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
8527
8574
|
}
|
|
8528
8575
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
8529
|
-
var VideoTierEnum =
|
|
8576
|
+
var VideoTierEnum = z45.enum([
|
|
8530
8577
|
"basic"
|
|
8531
8578
|
]);
|
|
8532
8579
|
function resolveVideoTier(_tier) {
|
|
@@ -8541,17 +8588,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
|
|
|
8541
8588
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
8542
8589
|
}
|
|
8543
8590
|
__name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
|
|
8544
|
-
var VideoResolutionEnum =
|
|
8591
|
+
var VideoResolutionEnum = z45.enum([
|
|
8545
8592
|
"480p",
|
|
8546
8593
|
"720p"
|
|
8547
8594
|
]);
|
|
8548
|
-
var VideoStyleEnum =
|
|
8595
|
+
var VideoStyleEnum = z45.enum([
|
|
8549
8596
|
"ugc",
|
|
8550
8597
|
"cartoon_3d",
|
|
8551
8598
|
"product_only",
|
|
8552
8599
|
"ai_dynamic"
|
|
8553
8600
|
]);
|
|
8554
|
-
var NarrativeStyleEnum =
|
|
8601
|
+
var NarrativeStyleEnum = z45.enum([
|
|
8555
8602
|
"review",
|
|
8556
8603
|
"ugc_how_to",
|
|
8557
8604
|
"problem_product_cta",
|
|
@@ -8568,7 +8615,7 @@ var NarrativeStyleEnum = z44.enum([
|
|
|
8568
8615
|
"ugc_skeptic_confession",
|
|
8569
8616
|
"ugc_demo_review"
|
|
8570
8617
|
]);
|
|
8571
|
-
var PublicNarrativeStyleEnum =
|
|
8618
|
+
var PublicNarrativeStyleEnum = z45.enum([
|
|
8572
8619
|
"review",
|
|
8573
8620
|
"ugc_how_to",
|
|
8574
8621
|
"ugc_unboxing_chaos",
|
|
@@ -8580,7 +8627,7 @@ var PublicNarrativeStyleEnum = z44.enum([
|
|
|
8580
8627
|
"animated_problem_pixar",
|
|
8581
8628
|
"sassy_product_pixar"
|
|
8582
8629
|
]);
|
|
8583
|
-
var VideoModelEnum =
|
|
8630
|
+
var VideoModelEnum = z45.enum([
|
|
8584
8631
|
"veo",
|
|
8585
8632
|
"wan",
|
|
8586
8633
|
"bytedance",
|
|
@@ -8588,25 +8635,25 @@ var VideoModelEnum = z44.enum([
|
|
|
8588
8635
|
"grok",
|
|
8589
8636
|
"kling"
|
|
8590
8637
|
]);
|
|
8591
|
-
var ProductReferenceUserChoiceEnum =
|
|
8638
|
+
var ProductReferenceUserChoiceEnum = z45.enum([
|
|
8592
8639
|
"same_product",
|
|
8593
8640
|
"variants",
|
|
8594
8641
|
"different_products",
|
|
8595
8642
|
"combo_distinct"
|
|
8596
8643
|
]);
|
|
8597
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
8644
|
+
var ProductReferenceCandidateGroupingEnum = z45.enum([
|
|
8598
8645
|
"same_product_same_variant",
|
|
8599
8646
|
"same_product_different_variants",
|
|
8600
8647
|
"different_products",
|
|
8601
8648
|
"unclear"
|
|
8602
8649
|
]);
|
|
8603
|
-
var GapDurationChoiceMirror =
|
|
8604
|
-
angleIndex:
|
|
8605
|
-
recommendedSec:
|
|
8606
|
-
|
|
8607
|
-
|
|
8650
|
+
var GapDurationChoiceMirror = z45.object({
|
|
8651
|
+
angleIndex: z45.number().int().nonnegative(),
|
|
8652
|
+
recommendedSec: z45.union([
|
|
8653
|
+
z45.literal(15),
|
|
8654
|
+
z45.literal(30)
|
|
8608
8655
|
]),
|
|
8609
|
-
estimatedDeltaCredits:
|
|
8656
|
+
estimatedDeltaCredits: z45.number().int().nonnegative().optional()
|
|
8610
8657
|
});
|
|
8611
8658
|
function buildSelectedImageUrlsHash(urls) {
|
|
8612
8659
|
const input = [
|
|
@@ -8620,13 +8667,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
8620
8667
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
8621
8668
|
}
|
|
8622
8669
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
8623
|
-
var ImageCreativeStyleEnum =
|
|
8670
|
+
var ImageCreativeStyleEnum = z45.enum([
|
|
8624
8671
|
"studio",
|
|
8625
8672
|
"floating",
|
|
8626
8673
|
"ingredients",
|
|
8627
8674
|
"in_use"
|
|
8628
8675
|
]);
|
|
8629
|
-
var ImageCreativeArchetypeEnum =
|
|
8676
|
+
var ImageCreativeArchetypeEnum = z45.enum([
|
|
8630
8677
|
"direct_response_product_ad",
|
|
8631
8678
|
"hero_outcome",
|
|
8632
8679
|
"offer_value_prop",
|
|
@@ -8635,23 +8682,23 @@ var ImageCreativeArchetypeEnum = z44.enum([
|
|
|
8635
8682
|
"problem_solution",
|
|
8636
8683
|
"lifestyle_identity"
|
|
8637
8684
|
]);
|
|
8638
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
8685
|
+
var ImageCreativeVisualTreatmentEnum = z45.enum([
|
|
8639
8686
|
"performance_product_ad",
|
|
8640
8687
|
"premium_dtc_carousel"
|
|
8641
8688
|
]);
|
|
8642
|
-
var ImageCreativeAspectRatioEnum =
|
|
8689
|
+
var ImageCreativeAspectRatioEnum = z45.enum([
|
|
8643
8690
|
"1:1",
|
|
8644
8691
|
"4:5",
|
|
8645
8692
|
"9:16",
|
|
8646
8693
|
"16:9"
|
|
8647
8694
|
]);
|
|
8648
|
-
var ImageRefSchema =
|
|
8649
|
-
url:
|
|
8650
|
-
path:
|
|
8695
|
+
var ImageRefSchema = z45.object({
|
|
8696
|
+
url: z45.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.'),
|
|
8697
|
+
path: z45.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`.')
|
|
8651
8698
|
}).refine((v) => Boolean(v.url) !== Boolean(v.path), {
|
|
8652
8699
|
message: "each image entry must have exactly one of `url` or `path`"
|
|
8653
8700
|
});
|
|
8654
|
-
var ImagesInput =
|
|
8701
|
+
var ImagesInput = z45.array(ImageRefSchema).min(1).max(5).describe('1 a 5 fotos del MISMO producto. La PRIMERA es la principal (hero); las dem\xE1s son \xE1ngulos adicionales. NO mezcles productos distintos en una sola llamada.\n\nCada entrada tiene EXACTAMENTE uno de:\n\u2022 `url` \u2014 URL p\xFAblica HTTPS (Shopify CDN, Cloudinary). Prefi\xE9rela si la foto ya est\xE1 hospedada.\n\u2022 `path` \u2014 Ruta del archivo en el computador del usuario (ej. "/Users/maria/Desktop/foto.jpg", "~/Downloads/camiseta.png"). \xDAsala cuando el usuario te dijo d\xF3nde guard\xF3 la foto. Solo MCP local \u2014 el cliente web rechaza paths.\n\nSi el usuario te peg\xF3 la foto en el chat pero no te dio ni URL ni ruta: PREG\xDANTALE d\xF3nde la tiene guardada (Escritorio, Descargas, etc.). Si el `path` falla con IMAGE_PATH_NOT_FOUND, prueba 1-2 ubicaciones obvias alternativas (~/Desktop, ~/Downloads) antes de molestar al usuario. Tras 3 intentos fallidos, p\xEDdele la ruta completa.');
|
|
8655
8702
|
function asText(value) {
|
|
8656
8703
|
return {
|
|
8657
8704
|
content: [
|
|
@@ -8704,14 +8751,14 @@ async function submitCreative(api, opts) {
|
|
|
8704
8751
|
});
|
|
8705
8752
|
}
|
|
8706
8753
|
__name(submitCreative, "submitCreative");
|
|
8707
|
-
var ResearchTargetCountryEnum =
|
|
8754
|
+
var ResearchTargetCountryEnum = z45.enum([
|
|
8708
8755
|
"CO",
|
|
8709
8756
|
"MX",
|
|
8710
8757
|
"PE",
|
|
8711
8758
|
"EC",
|
|
8712
8759
|
"CL"
|
|
8713
8760
|
]);
|
|
8714
|
-
var ResearchCategoryEnum =
|
|
8761
|
+
var ResearchCategoryEnum = z45.enum([
|
|
8715
8762
|
"auto",
|
|
8716
8763
|
"automotive",
|
|
8717
8764
|
"kitchen",
|
|
@@ -9356,53 +9403,53 @@ function renderOutputsMarkdown(outputs) {
|
|
|
9356
9403
|
__name(renderOutputsMarkdown, "renderOutputsMarkdown");
|
|
9357
9404
|
|
|
9358
9405
|
// src/tools/tasks.ts
|
|
9359
|
-
var CreateProductTaskInput =
|
|
9406
|
+
var CreateProductTaskInput = z46.object({
|
|
9360
9407
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
9361
|
-
projectId:
|
|
9362
|
-
productUrl:
|
|
9408
|
+
projectId: z46.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
9409
|
+
productUrl: z46.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."),
|
|
9363
9410
|
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.'),
|
|
9364
9411
|
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.'),
|
|
9365
|
-
price:
|
|
9366
|
-
compareAtPrice:
|
|
9367
|
-
offer:
|
|
9368
|
-
paymentMethods:
|
|
9369
|
-
productContext:
|
|
9370
|
-
productLabel:
|
|
9412
|
+
price: z46.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.'),
|
|
9413
|
+
compareAtPrice: z46.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".'),
|
|
9414
|
+
offer: z46.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.'),
|
|
9415
|
+
paymentMethods: z46.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.'),
|
|
9416
|
+
productContext: z46.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."),
|
|
9417
|
+
productLabel: z46.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.'),
|
|
9371
9418
|
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). 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" (una regla visual experimental original), "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.'),
|
|
9372
|
-
durationSeconds:
|
|
9373
|
-
|
|
9374
|
-
|
|
9419
|
+
durationSeconds: z46.union([
|
|
9420
|
+
z46.literal(15),
|
|
9421
|
+
z46.literal(30)
|
|
9375
9422
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
9376
|
-
pauseForAngleReview:
|
|
9423
|
+
pauseForAngleReview: z46.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. \xDAsalo si quiere decidir 15/30s cuando aparezca un winner. Default false."),
|
|
9377
9424
|
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.'),
|
|
9378
9425
|
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).'),
|
|
9379
|
-
multiAngleVideos:
|
|
9426
|
+
multiAngleVideos: z46.boolean().optional().describe("Opcional. Si true, genera m\xFAltiples \xE1ngulos de venta en paralelo (3-5 videos). Si false/omitido, genera 1 video del \xE1ngulo principal. Default false."),
|
|
9380
9427
|
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". angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. Requiere multiAngleVideos:true para varios \xE1ngulos.'),
|
|
9381
|
-
outputs:
|
|
9428
|
+
outputs: z46.array(z46.enum([
|
|
9382
9429
|
"landing",
|
|
9383
9430
|
"video",
|
|
9384
9431
|
"image"
|
|
9385
9432
|
])).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). Para 1 solo output, usa generate_landing / generate_video_creative / generate_image_creatives.'),
|
|
9386
|
-
competitorScanEnabled:
|
|
9387
|
-
brandId:
|
|
9388
|
-
actorId:
|
|
9389
|
-
creativeDirection:
|
|
9390
|
-
headline:
|
|
9391
|
-
subheadline:
|
|
9433
|
+
competitorScanEnabled: z46.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
|
|
9434
|
+
brandId: z46.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."),
|
|
9435
|
+
actorId: z46.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."),
|
|
9436
|
+
creativeDirection: z46.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.'),
|
|
9437
|
+
headline: z46.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."),
|
|
9438
|
+
subheadline: z46.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."),
|
|
9392
9439
|
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".'),
|
|
9393
9440
|
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".')
|
|
9394
9441
|
}).strict();
|
|
9395
|
-
var CreateServiceVideoInput =
|
|
9396
|
-
landingUrl:
|
|
9397
|
-
additionalContext:
|
|
9442
|
+
var CreateServiceVideoInput = z46.object({
|
|
9443
|
+
landingUrl: z46.string().url().describe("URL p\xFAblica de la landing del servicio. Es suficiente para generar el video; los medios son opcionales en la web."),
|
|
9444
|
+
additionalContext: z46.string().max(3e3).optional().describe('Instrucci\xF3n natural prioritaria. Ej.: "adapta el ritmo de estos competidores", "enfatiza reservas de demos" o restricciones de claims.'),
|
|
9398
9445
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
9399
|
-
voiceId:
|
|
9400
|
-
brandId:
|
|
9401
|
-
reviewMode:
|
|
9446
|
+
voiceId: z46.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.'),
|
|
9447
|
+
brandId: z46.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
9448
|
+
reviewMode: z46.enum([
|
|
9402
9449
|
"automatic",
|
|
9403
9450
|
"guided"
|
|
9404
9451
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
9405
|
-
videoPreset:
|
|
9452
|
+
videoPreset: z46.enum([
|
|
9406
9453
|
"auto",
|
|
9407
9454
|
"ugc_dynamic",
|
|
9408
9455
|
"ugc_how_to",
|
|
@@ -9410,35 +9457,35 @@ var CreateServiceVideoInput = z45.object({
|
|
|
9410
9457
|
"wild_card"
|
|
9411
9458
|
]).default("auto")
|
|
9412
9459
|
}).strict();
|
|
9413
|
-
var GetTaskStatusInput =
|
|
9414
|
-
taskId:
|
|
9415
|
-
waitSeconds:
|
|
9416
|
-
});
|
|
9417
|
-
var ListTasksInput =
|
|
9418
|
-
limit:
|
|
9419
|
-
offset:
|
|
9420
|
-
search:
|
|
9421
|
-
});
|
|
9422
|
-
var EditTaskDraftInput =
|
|
9423
|
-
taskId:
|
|
9424
|
-
angleIndex:
|
|
9425
|
-
angle:
|
|
9426
|
-
angle:
|
|
9427
|
-
buyerPersona:
|
|
9428
|
-
actor:
|
|
9429
|
-
actorId:
|
|
9430
|
-
gender:
|
|
9460
|
+
var GetTaskStatusInput = z46.object({
|
|
9461
|
+
taskId: z46.string().min(1),
|
|
9462
|
+
waitSeconds: z46.number().int().min(0).max(120).optional()
|
|
9463
|
+
});
|
|
9464
|
+
var ListTasksInput = z46.object({
|
|
9465
|
+
limit: z46.number().int().min(1).max(50).optional(),
|
|
9466
|
+
offset: z46.number().int().min(0).optional(),
|
|
9467
|
+
search: z46.string().optional()
|
|
9468
|
+
});
|
|
9469
|
+
var EditTaskDraftInput = z46.object({
|
|
9470
|
+
taskId: z46.string().min(1),
|
|
9471
|
+
angleIndex: z46.number().int().min(0),
|
|
9472
|
+
angle: z46.object({
|
|
9473
|
+
angle: z46.string().min(1).max(480),
|
|
9474
|
+
buyerPersona: z46.string().min(1).max(360),
|
|
9475
|
+
actor: z46.string().min(1).max(360).optional(),
|
|
9476
|
+
actorId: z46.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."),
|
|
9477
|
+
gender: z46.enum([
|
|
9431
9478
|
"female",
|
|
9432
9479
|
"male"
|
|
9433
9480
|
]).optional(),
|
|
9434
|
-
scriptNotes:
|
|
9481
|
+
scriptNotes: z46.string().max(2e3).optional()
|
|
9435
9482
|
})
|
|
9436
9483
|
});
|
|
9437
|
-
var PendingActionPayload =
|
|
9438
|
-
|
|
9439
|
-
kind:
|
|
9484
|
+
var PendingActionPayload = z46.discriminatedUnion("kind", [
|
|
9485
|
+
z46.object({
|
|
9486
|
+
kind: z46.literal("product_reference_confirmation"),
|
|
9440
9487
|
userChoice: ProductReferenceUserChoiceEnum,
|
|
9441
|
-
confirmedProductNames:
|
|
9488
|
+
confirmedProductNames: z46.array(z46.string().min(1).max(120)).min(2).max(8).optional(),
|
|
9442
9489
|
// SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
|
|
9443
9490
|
// reachable via MCP. Valid ONLY together with userChoice='variants' (same
|
|
9444
9491
|
// product in several colors): renders one shot per color and stitches them,
|
|
@@ -9449,50 +9496,50 @@ var PendingActionPayload = z45.discriminatedUnion("kind", [
|
|
|
9449
9496
|
// safe because multi-scene IS the intended render for a color variant set,
|
|
9450
9497
|
// not a blind quality upsell. Maps to `videoTier: 'standard'` on the
|
|
9451
9498
|
// confirm call; the backend re-gates it (variants + variant_set only).
|
|
9452
|
-
useMultiSceneShowcase:
|
|
9499
|
+
useMultiSceneShowcase: z46.boolean().optional().describe('Opcional (SOLO con userChoice="variants"). true = render Multiescena: una toma por color, mostrando todas las variantes, hasta 30s. Se factura POR ESCENA (m\xE1s caro que el render normal de una sola toma) \u2014 AV\xCDSALE del mayor costo al usuario antes de activarlo. Omitir = render est\xE1ndar de una sola toma. Se ignora si userChoice no es "variants".')
|
|
9453
9500
|
}),
|
|
9454
|
-
|
|
9455
|
-
kind:
|
|
9501
|
+
z46.object({
|
|
9502
|
+
kind: z46.literal("angle_review_approval"),
|
|
9456
9503
|
// All edits are optional — empty action body just approves the
|
|
9457
9504
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
9458
9505
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
9459
9506
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
9460
|
-
customAngle:
|
|
9507
|
+
customAngle: z46.string().min(1).max(480).optional(),
|
|
9461
9508
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
9462
9509
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
9463
|
-
painPoints:
|
|
9464
|
-
benefits:
|
|
9465
|
-
features:
|
|
9466
|
-
gapDurationSeconds:
|
|
9467
|
-
|
|
9468
|
-
|
|
9510
|
+
painPoints: z46.string().max(1500).optional(),
|
|
9511
|
+
benefits: z46.string().max(1500).optional(),
|
|
9512
|
+
features: z46.array(z46.string().min(1).max(300)).max(10).optional(),
|
|
9513
|
+
gapDurationSeconds: z46.union([
|
|
9514
|
+
z46.literal(15),
|
|
9515
|
+
z46.literal(30)
|
|
9469
9516
|
]).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.")
|
|
9470
9517
|
}),
|
|
9471
|
-
|
|
9472
|
-
kind:
|
|
9473
|
-
angleId:
|
|
9474
|
-
content:
|
|
9475
|
-
creativeDirection:
|
|
9476
|
-
actor:
|
|
9518
|
+
z46.object({
|
|
9519
|
+
kind: z46.literal("service_angle_approval"),
|
|
9520
|
+
angleId: z46.string().uuid(),
|
|
9521
|
+
content: z46.string().min(1).max(480).optional(),
|
|
9522
|
+
creativeDirection: z46.string().min(1).max(1500).optional(),
|
|
9523
|
+
actor: z46.string().min(1).max(360).optional()
|
|
9477
9524
|
}),
|
|
9478
|
-
|
|
9479
|
-
kind:
|
|
9480
|
-
voiceovers:
|
|
9481
|
-
visualDirections:
|
|
9525
|
+
z46.object({
|
|
9526
|
+
kind: z46.literal("service_script_approval"),
|
|
9527
|
+
voiceovers: z46.record(z46.string(), z46.string().min(1).max(600)).optional(),
|
|
9528
|
+
visualDirections: z46.record(z46.string(), z46.string().min(1).max(1200)).optional()
|
|
9482
9529
|
})
|
|
9483
9530
|
]);
|
|
9484
|
-
var ResolvePendingActionInput =
|
|
9485
|
-
taskId:
|
|
9531
|
+
var ResolvePendingActionInput = z46.object({
|
|
9532
|
+
taskId: z46.string().min(1),
|
|
9486
9533
|
action: PendingActionPayload
|
|
9487
9534
|
}).strict();
|
|
9488
9535
|
function resolveVariantConfirmVideoTier(action) {
|
|
9489
9536
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
9490
9537
|
}
|
|
9491
9538
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
9492
|
-
var StatusForResolveSchema =
|
|
9539
|
+
var StatusForResolveSchema = z46.object({
|
|
9493
9540
|
// Metadata used to select the backend resume contract. Older API responses
|
|
9494
9541
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
9495
|
-
kind:
|
|
9542
|
+
kind: z46.enum([
|
|
9496
9543
|
"autopilot",
|
|
9497
9544
|
"video",
|
|
9498
9545
|
"image",
|
|
@@ -9500,24 +9547,24 @@ var StatusForResolveSchema = z45.object({
|
|
|
9500
9547
|
"mix",
|
|
9501
9548
|
"service"
|
|
9502
9549
|
]).optional(),
|
|
9503
|
-
selectedOutputs:
|
|
9550
|
+
selectedOutputs: z46.array(z46.enum([
|
|
9504
9551
|
"landing",
|
|
9505
9552
|
"video",
|
|
9506
9553
|
"image"
|
|
9507
9554
|
])).optional(),
|
|
9508
|
-
videoAngleCount:
|
|
9509
|
-
ugcFormat:
|
|
9555
|
+
videoAngleCount: z46.number().int().min(1).max(3).optional(),
|
|
9556
|
+
ugcFormat: z46.enum([
|
|
9510
9557
|
"single_8s",
|
|
9511
9558
|
"single_15s",
|
|
9512
9559
|
"double_30s"
|
|
9513
9560
|
]).optional(),
|
|
9514
|
-
videoStyle:
|
|
9561
|
+
videoStyle: z46.enum([
|
|
9515
9562
|
"ugc",
|
|
9516
9563
|
"cartoon_3d",
|
|
9517
9564
|
"product_only",
|
|
9518
9565
|
"ai_dynamic"
|
|
9519
9566
|
]).optional(),
|
|
9520
|
-
videoModel:
|
|
9567
|
+
videoModel: z46.enum([
|
|
9521
9568
|
"veo",
|
|
9522
9569
|
"wan",
|
|
9523
9570
|
"bytedance",
|
|
@@ -9525,26 +9572,26 @@ var StatusForResolveSchema = z45.object({
|
|
|
9525
9572
|
"grok",
|
|
9526
9573
|
"kling"
|
|
9527
9574
|
]).optional(),
|
|
9528
|
-
videoTier:
|
|
9575
|
+
videoTier: z46.enum([
|
|
9529
9576
|
"legacy",
|
|
9530
9577
|
"standard",
|
|
9531
9578
|
"pro",
|
|
9532
9579
|
"single_call"
|
|
9533
9580
|
]).optional(),
|
|
9534
|
-
videoResolution:
|
|
9581
|
+
videoResolution: z46.enum([
|
|
9535
9582
|
"480p",
|
|
9536
9583
|
"720p"
|
|
9537
9584
|
]).optional(),
|
|
9538
9585
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
9539
|
-
pendingUserAction:
|
|
9540
|
-
kind:
|
|
9541
|
-
candidateGrouping:
|
|
9542
|
-
selectedImageUrls:
|
|
9543
|
-
proposedProductNames:
|
|
9544
|
-
customAngleDraft:
|
|
9545
|
-
painPointsDraft:
|
|
9546
|
-
benefitsDraft:
|
|
9547
|
-
featuresDraft:
|
|
9586
|
+
pendingUserAction: z46.object({
|
|
9587
|
+
kind: z46.string(),
|
|
9588
|
+
candidateGrouping: z46.string().optional(),
|
|
9589
|
+
selectedImageUrls: z46.array(z46.string()).optional(),
|
|
9590
|
+
proposedProductNames: z46.array(z46.string()).optional(),
|
|
9591
|
+
customAngleDraft: z46.string().optional(),
|
|
9592
|
+
painPointsDraft: z46.string().optional(),
|
|
9593
|
+
benefitsDraft: z46.string().optional(),
|
|
9594
|
+
featuresDraft: z46.array(z46.string()).optional(),
|
|
9548
9595
|
// Recommendation consumed only when the caller explicitly sends
|
|
9549
9596
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
9550
9597
|
gapDurationChoice: GapDurationChoiceMirror.optional(),
|
|
@@ -9553,17 +9600,17 @@ var StatusForResolveSchema = z45.object({
|
|
|
9553
9600
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
9554
9601
|
// dropped here, so the approval handler below could not echo it back on the
|
|
9555
9602
|
// PATCH — the selection looked accepted and reached no render.
|
|
9556
|
-
angles:
|
|
9557
|
-
id:
|
|
9558
|
-
content:
|
|
9559
|
-
creativeDirection:
|
|
9560
|
-
actor:
|
|
9561
|
-
actorId:
|
|
9603
|
+
angles: z46.array(z46.object({
|
|
9604
|
+
id: z46.string().uuid(),
|
|
9605
|
+
content: z46.string(),
|
|
9606
|
+
creativeDirection: z46.string(),
|
|
9607
|
+
actor: z46.string(),
|
|
9608
|
+
actorId: z46.string().nullable().optional()
|
|
9562
9609
|
}).passthrough()).optional(),
|
|
9563
|
-
panels:
|
|
9564
|
-
beatId:
|
|
9565
|
-
voiceover:
|
|
9566
|
-
visualDirection:
|
|
9610
|
+
panels: z46.array(z46.object({
|
|
9611
|
+
beatId: z46.string(),
|
|
9612
|
+
voiceover: z46.string(),
|
|
9613
|
+
visualDirection: z46.string()
|
|
9567
9614
|
}).passthrough()).optional()
|
|
9568
9615
|
}).optional()
|
|
9569
9616
|
}).passthrough();
|
|
@@ -10003,58 +10050,58 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
10003
10050
|
|
|
10004
10051
|
// src/tools/creatives.ts
|
|
10005
10052
|
import { randomUUID } from "crypto";
|
|
10006
|
-
import { z as
|
|
10053
|
+
import { z as z47 } from "zod";
|
|
10007
10054
|
var CreativeRefs = {
|
|
10008
10055
|
images: ImagesInput,
|
|
10009
10056
|
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.'),
|
|
10010
10057
|
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.'),
|
|
10011
|
-
price:
|
|
10012
|
-
offer:
|
|
10013
|
-
compareAtPrice:
|
|
10014
|
-
paymentMethods:
|
|
10015
|
-
productContext:
|
|
10016
|
-
productLabel:
|
|
10017
|
-
buyerPersona:
|
|
10018
|
-
isCombo:
|
|
10019
|
-
competitorScanEnabled:
|
|
10020
|
-
brandId:
|
|
10021
|
-
projectId:
|
|
10022
|
-
creativeDirection:
|
|
10023
|
-
headline:
|
|
10024
|
-
subheadline:
|
|
10058
|
+
price: z47.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.'),
|
|
10059
|
+
offer: z47.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.'),
|
|
10060
|
+
compareAtPrice: z47.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
10061
|
+
paymentMethods: z47.string().min(1).max(240).optional().describe('Opcional. M\xE9todos de pago a mostrar. Ej. "Tarjeta, PSE, Nequi, Contraentrega". Si se omite, la landing no muestra m\xE9todos de pago.'),
|
|
10062
|
+
productContext: z47.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."),
|
|
10063
|
+
productLabel: z47.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.'),
|
|
10064
|
+
buyerPersona: z47.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.'),
|
|
10065
|
+
isCombo: z47.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
10066
|
+
competitorScanEnabled: z47.boolean().optional().describe("Opcional. Si true (default), el sistema analiza ads de competencia en Meta Ad Library y enriquece los \xE1ngulos generados con hooks y painPoints validados por el mercado (\u2248$0.20-0.48 extra por task \u2014 var\xEDa con cu\xE1ntas transcripciones de video se capturen). Si false, el pipeline genera \xE1ngulos sin esa se\xF1al \u2014 usa esto SOLO si el usuario ya tiene su propia investigaci\xF3n de mercado o quiere ahorrar costos en productos muy nicho sin presencia en Meta. Default true."),
|
|
10067
|
+
brandId: z47.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."),
|
|
10068
|
+
projectId: z47.string().uuid().optional().describe("Opcional. ID de un proyecto guiado de dropshipping activo del usuario. Enlaza esta generaci\xF3n con su progreso y recompensas."),
|
|
10069
|
+
creativeDirection: z47.string().max(500).optional().describe('Opcional. Direcci\xF3n creativa en texto libre (colores, mood, estilo). M\xC1XIMA PRIORIDAD: anula marca, colores y estilo por defecto. Aplica SOLO a im\xE1genes y landing. Ej. im\xE1genes: "amarillo, azul y rojo, minimalista"; landing: "elegante, paleta fr\xEDa". Para video usa scriptNotes (ambiente/escenario). M\xE1x 500 caracteres.'),
|
|
10070
|
+
headline: z47.string().max(120).optional().describe("Opcional. Titular EXACTO a renderizar en la imagen (o en la portada de la landing). Se imprime tal cual: la IA no lo reescribe, no lo acorta y no lo traduce. \xDAsalo cuando el copy es de marca y no es negociable. M\xE1x 120 caracteres. Si lo omites, la IA escribe el titular."),
|
|
10071
|
+
subheadline: z47.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.")
|
|
10025
10072
|
};
|
|
10026
|
-
var VideoInput =
|
|
10073
|
+
var VideoInput = z47.object({
|
|
10027
10074
|
images: CreativeRefs.images,
|
|
10028
|
-
title:
|
|
10029
|
-
primaryAngle:
|
|
10075
|
+
title: z47.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
10076
|
+
primaryAngle: z47.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".'),
|
|
10030
10077
|
language: CreativeRefs.language,
|
|
10031
10078
|
country: CreativeRefs.country,
|
|
10032
|
-
aspectRatio:
|
|
10079
|
+
aspectRatio: z47.enum([
|
|
10033
10080
|
"9:16",
|
|
10034
10081
|
"16:9",
|
|
10035
10082
|
"Auto"
|
|
10036
10083
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
10037
|
-
durationSeconds:
|
|
10038
|
-
|
|
10039
|
-
|
|
10084
|
+
durationSeconds: z47.union([
|
|
10085
|
+
z47.literal(15),
|
|
10086
|
+
z47.literal(30)
|
|
10040
10087
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
10041
10088
|
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). 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" (una regla visual experimental original), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla).'),
|
|
10042
10089
|
videoTier: VideoTierEnum.optional().describe('Opcional. Estilo del video. "basic" = "Realista"; para durationSeconds=30 el sistema selecciona internamente Multiescena. No se expone el tier interno directamente.'),
|
|
10043
10090
|
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).'),
|
|
10044
|
-
features:
|
|
10091
|
+
features: z47.array(z47.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
10045
10092
|
price: CreativeRefs.price,
|
|
10046
10093
|
offer: CreativeRefs.offer,
|
|
10047
10094
|
productContext: CreativeRefs.productContext,
|
|
10048
10095
|
productLabel: CreativeRefs.productLabel,
|
|
10049
|
-
cta:
|
|
10050
|
-
scriptNotes:
|
|
10051
|
-
pauseForVideoScriptReview:
|
|
10052
|
-
pauseForAngleReview:
|
|
10096
|
+
cta: z47.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.'),
|
|
10097
|
+
scriptNotes: z47.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 \u2014 para editar el guion palabra-por-palabra, pasa `pauseForVideoScriptReview: true` y usa get_video_script / approve_video_script tras la pausa.'),
|
|
10098
|
+
pauseForVideoScriptReview: z47.boolean().optional().describe("Opcional. Si true, la tarea pausa despu\xE9s de generar el guion y antes de renderizar. \xDAsalo cuando el usuario quiera editar el guion antes de gastar cr\xE9ditos en el video. Tras la pausa: get_video_script para leerlo, approve_video_script para aprobar (con o sin ediciones). Default false."),
|
|
10099
|
+
pauseForAngleReview: z47.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo para que el usuario lo confirme o edite antes del render. Default false."),
|
|
10053
10100
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
10054
10101
|
brandId: CreativeRefs.brandId,
|
|
10055
10102
|
projectId: CreativeRefs.projectId
|
|
10056
10103
|
}).strict();
|
|
10057
|
-
var FreeVideoQualityEnum =
|
|
10104
|
+
var FreeVideoQualityEnum = z47.enum([
|
|
10058
10105
|
"economical",
|
|
10059
10106
|
"high_detail"
|
|
10060
10107
|
]);
|
|
@@ -10076,38 +10123,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
10076
10123
|
15
|
|
10077
10124
|
]
|
|
10078
10125
|
};
|
|
10079
|
-
var FreeVideoInput =
|
|
10126
|
+
var FreeVideoInput = z47.object({
|
|
10080
10127
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
10081
|
-
rawPrompt:
|
|
10128
|
+
rawPrompt: z47.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."),
|
|
10082
10129
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
|
|
10083
|
-
durationSeconds:
|
|
10130
|
+
durationSeconds: z47.number().int().min(1).max(15).describe("Duraci\xF3n exacta. Econ\xF3mico permite 6, 8, 10 o 15s; Alto detalle permite 4, 8, 12 o 15s."),
|
|
10084
10131
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
10085
|
-
generateAiMusic:
|
|
10086
|
-
addSubtitles:
|
|
10087
|
-
idempotencyKey:
|
|
10132
|
+
generateAiMusic: z47.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
10133
|
+
addSubtitles: z47.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
10134
|
+
idempotencyKey: z47.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.")
|
|
10088
10135
|
}).strict();
|
|
10089
10136
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
10090
10137
|
var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
|
|
10091
10138
|
var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
|
|
10092
10139
|
var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
|
|
10093
|
-
var ImageInput =
|
|
10140
|
+
var ImageInput = z47.object({
|
|
10094
10141
|
images: CreativeRefs.images,
|
|
10095
|
-
productTitle:
|
|
10096
|
-
primaryAngle:
|
|
10142
|
+
productTitle: z47.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
10143
|
+
primaryAngle: z47.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
|
|
10097
10144
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
10098
10145
|
language: CreativeRefs.language,
|
|
10099
10146
|
country: CreativeRefs.country,
|
|
10100
|
-
nVariants:
|
|
10101
|
-
imageModel:
|
|
10147
|
+
nVariants: z47.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
|
|
10148
|
+
imageModel: z47.string().optional().describe('Opcional. Modelo de imagen. Ej. "gpt-image-2", "nano-banana-2". Om\xEDtelo para usar el default optimizado por costo/calidad.'),
|
|
10102
10149
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
10103
10150
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe(`Opcional. Arquetipo CRO de la composici\xF3n. Valores: ${archetypeList}. Si se omite, la IA escoge seg\xFAn \xE1ngulo+oferta (ej. "offer_value_prop" cuando hay descuento, "social_proof_trust" cuando el \xE1ngulo es testimonial).`),
|
|
10104
10151
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe(`Opcional. Tratamiento gr\xE1fico. Valores: ${visualTreatmentList} ("performance_product_ad" = dealer-style alto CTR para Meta/TikTok ads; "premium_dtc_carousel" = fotograf\xEDa limpia estilo Allbirds/Glossier). Si se omite, la IA escoge.`),
|
|
10105
|
-
styleMix:
|
|
10152
|
+
styleMix: z47.boolean().optional().describe("Opcional. Si true, las N variantes mezclan distintos imageStyle para A/B test. Si false/omitido, todas comparten estilo. Default false."),
|
|
10106
10153
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
|
|
10107
|
-
generateAdCopy:
|
|
10108
|
-
pauseForAngleReview:
|
|
10109
|
-
features:
|
|
10110
|
-
brandColors:
|
|
10154
|
+
generateAdCopy: z47.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
|
|
10155
|
+
pauseForAngleReview: z47.boolean().optional().describe("Opcional. Si true, pausa despu\xE9s de generar el \xE1ngulo y antes de las im\xE1genes para que el usuario edite v\xEDa edit_task_draft. Default false."),
|
|
10156
|
+
features: z47.array(z47.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
10157
|
+
brandColors: z47.array(z47.string()).optional().describe('Opcional. Paleta de marca en hex. Ej. ["#FF6B35", "#004E89"]. Si se omite, la IA elige seg\xFAn el producto.'),
|
|
10111
10158
|
price: CreativeRefs.price,
|
|
10112
10159
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
10113
10160
|
offer: CreativeRefs.offer,
|
|
@@ -10121,16 +10168,16 @@ var ImageInput = z46.object({
|
|
|
10121
10168
|
headline: CreativeRefs.headline,
|
|
10122
10169
|
subheadline: CreativeRefs.subheadline
|
|
10123
10170
|
});
|
|
10124
|
-
var EditImageCreativeInput =
|
|
10125
|
-
taskId:
|
|
10126
|
-
variantIndex:
|
|
10127
|
-
instruction:
|
|
10171
|
+
var EditImageCreativeInput = z47.object({
|
|
10172
|
+
taskId: z47.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
10173
|
+
variantIndex: z47.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
10174
|
+
instruction: z47.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".')
|
|
10128
10175
|
});
|
|
10129
|
-
var LandingInput =
|
|
10176
|
+
var LandingInput = z47.object({
|
|
10130
10177
|
images: CreativeRefs.images,
|
|
10131
10178
|
language: CreativeRefs.language,
|
|
10132
10179
|
country: CreativeRefs.country,
|
|
10133
|
-
salesAngle:
|
|
10180
|
+
salesAngle: z47.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.'),
|
|
10134
10181
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
10135
10182
|
price: CreativeRefs.price,
|
|
10136
10183
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -10255,8 +10302,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
10255
10302
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
10256
10303
|
|
|
10257
10304
|
// src/tools/creative-variants.ts
|
|
10258
|
-
import { z as
|
|
10259
|
-
var LandingSectionKeyEnum =
|
|
10305
|
+
import { z as z48 } from "zod";
|
|
10306
|
+
var LandingSectionKeyEnum = z48.enum([
|
|
10260
10307
|
"problem_hook",
|
|
10261
10308
|
"problem_cost",
|
|
10262
10309
|
"solution_mechanism",
|
|
@@ -10296,24 +10343,24 @@ var LandingSectionKeyEnum = z47.enum([
|
|
|
10296
10343
|
"lifestyle_fit",
|
|
10297
10344
|
"join_lifestyle"
|
|
10298
10345
|
]);
|
|
10299
|
-
var CreativeVariantKindEnum =
|
|
10346
|
+
var CreativeVariantKindEnum = z48.enum([
|
|
10300
10347
|
"video",
|
|
10301
10348
|
"image",
|
|
10302
10349
|
"landing"
|
|
10303
10350
|
]);
|
|
10304
|
-
var EstimateCreativeVariantInputBase =
|
|
10305
|
-
sourceTaskId:
|
|
10351
|
+
var EstimateCreativeVariantInputBase = z48.object({
|
|
10352
|
+
sourceTaskId: z48.string().uuid().describe("ID de la tarea original completada."),
|
|
10306
10353
|
kind: CreativeVariantKindEnum,
|
|
10307
10354
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
10308
10355
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
10309
|
-
nVariants:
|
|
10356
|
+
nVariants: z48.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
10310
10357
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
10311
|
-
instructions:
|
|
10358
|
+
instructions: z48.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.")
|
|
10312
10359
|
}).strict();
|
|
10313
10360
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
10314
10361
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
10315
10362
|
ctx.addIssue({
|
|
10316
|
-
code:
|
|
10363
|
+
code: z48.ZodIssueCode.custom,
|
|
10317
10364
|
path: [
|
|
10318
10365
|
"nVariants"
|
|
10319
10366
|
],
|
|
@@ -10323,7 +10370,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10323
10370
|
if (input.kind !== "video") {
|
|
10324
10371
|
if (input.videoPreset !== void 0) {
|
|
10325
10372
|
ctx.addIssue({
|
|
10326
|
-
code:
|
|
10373
|
+
code: z48.ZodIssueCode.custom,
|
|
10327
10374
|
path: [
|
|
10328
10375
|
"videoPreset"
|
|
10329
10376
|
],
|
|
@@ -10332,7 +10379,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10332
10379
|
}
|
|
10333
10380
|
if (input.videoResolution !== void 0) {
|
|
10334
10381
|
ctx.addIssue({
|
|
10335
|
-
code:
|
|
10382
|
+
code: z48.ZodIssueCode.custom,
|
|
10336
10383
|
path: [
|
|
10337
10384
|
"videoResolution"
|
|
10338
10385
|
],
|
|
@@ -10342,7 +10389,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10342
10389
|
}
|
|
10343
10390
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
10344
10391
|
ctx.addIssue({
|
|
10345
|
-
code:
|
|
10392
|
+
code: z48.ZodIssueCode.custom,
|
|
10346
10393
|
path: [
|
|
10347
10394
|
"nVariants"
|
|
10348
10395
|
],
|
|
@@ -10352,7 +10399,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10352
10399
|
if (input.kind !== "landing") {
|
|
10353
10400
|
if (input.sectionKey !== void 0) {
|
|
10354
10401
|
ctx.addIssue({
|
|
10355
|
-
code:
|
|
10402
|
+
code: z48.ZodIssueCode.custom,
|
|
10356
10403
|
path: [
|
|
10357
10404
|
"sectionKey"
|
|
10358
10405
|
],
|
|
@@ -10361,7 +10408,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10361
10408
|
}
|
|
10362
10409
|
if (input.instructions !== void 0) {
|
|
10363
10410
|
ctx.addIssue({
|
|
10364
|
-
code:
|
|
10411
|
+
code: z48.ZodIssueCode.custom,
|
|
10365
10412
|
path: [
|
|
10366
10413
|
"instructions"
|
|
10367
10414
|
],
|
|
@@ -10370,31 +10417,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10370
10417
|
}
|
|
10371
10418
|
}
|
|
10372
10419
|
});
|
|
10373
|
-
var CreateCreativeVariantInputBase =
|
|
10374
|
-
sourceTaskId:
|
|
10420
|
+
var CreateCreativeVariantInputBase = z48.object({
|
|
10421
|
+
sourceTaskId: z48.string().uuid().describe("ID de la tarea original completada."),
|
|
10375
10422
|
kind: CreativeVariantKindEnum,
|
|
10376
|
-
confirm:
|
|
10377
|
-
clientRequestId:
|
|
10378
|
-
angle:
|
|
10379
|
-
buyerPersona:
|
|
10380
|
-
scriptNotes:
|
|
10381
|
-
creativeDirection:
|
|
10423
|
+
confirm: z48.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
10424
|
+
clientRequestId: z48.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."),
|
|
10425
|
+
angle: z48.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
10426
|
+
buyerPersona: z48.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
10427
|
+
scriptNotes: z48.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
10428
|
+
creativeDirection: z48.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
10382
10429
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
10383
10430
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
10384
|
-
generateAiMusic:
|
|
10385
|
-
nVariants:
|
|
10431
|
+
generateAiMusic: z48.boolean().optional().describe("Opcional para video."),
|
|
10432
|
+
nVariants: z48.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
10386
10433
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
10387
10434
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
10388
10435
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
10389
10436
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
10390
|
-
styleMix:
|
|
10437
|
+
styleMix: z48.boolean().optional().describe("Opcional para imagen."),
|
|
10391
10438
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
10392
|
-
instructions:
|
|
10439
|
+
instructions: z48.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.")
|
|
10393
10440
|
}).strict();
|
|
10394
10441
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
10395
10442
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
10396
10443
|
ctx.addIssue({
|
|
10397
|
-
code:
|
|
10444
|
+
code: z48.ZodIssueCode.custom,
|
|
10398
10445
|
path: [
|
|
10399
10446
|
"angle"
|
|
10400
10447
|
],
|
|
@@ -10403,7 +10450,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
10403
10450
|
}
|
|
10404
10451
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
10405
10452
|
ctx.addIssue({
|
|
10406
|
-
code:
|
|
10453
|
+
code: z48.ZodIssueCode.custom,
|
|
10407
10454
|
path: [
|
|
10408
10455
|
"instructions"
|
|
10409
10456
|
],
|
|
@@ -10449,7 +10496,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
10449
10496
|
for (const field of fieldsByKind[input.kind]) {
|
|
10450
10497
|
if (input[field] !== void 0) {
|
|
10451
10498
|
ctx.addIssue({
|
|
10452
|
-
code:
|
|
10499
|
+
code: z48.ZodIssueCode.custom,
|
|
10453
10500
|
path: [
|
|
10454
10501
|
field
|
|
10455
10502
|
],
|
|
@@ -10566,27 +10613,27 @@ function registerCreativeVariantTools(server, api) {
|
|
|
10566
10613
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
10567
10614
|
|
|
10568
10615
|
// src/tools/script-review.ts
|
|
10569
|
-
import { z as
|
|
10570
|
-
var GetVideoScriptInput =
|
|
10571
|
-
taskId:
|
|
10572
|
-
angleKey:
|
|
10616
|
+
import { z as z49 } from "zod";
|
|
10617
|
+
var GetVideoScriptInput = z49.object({
|
|
10618
|
+
taskId: z49.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
10619
|
+
angleKey: z49.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.')
|
|
10573
10620
|
}).strict();
|
|
10574
10621
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
10575
10622
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
10576
|
-
var ApproveSceneEdit =
|
|
10577
|
-
index:
|
|
10578
|
-
dialogue:
|
|
10623
|
+
var ApproveSceneEdit = z49.object({
|
|
10624
|
+
index: z49.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
10625
|
+
dialogue: z49.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
10579
10626
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
10580
10627
|
}).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.")
|
|
10581
10628
|
}).strict();
|
|
10582
|
-
var ApproveVideoScriptInput =
|
|
10583
|
-
taskId:
|
|
10584
|
-
angleKey:
|
|
10585
|
-
scenes:
|
|
10629
|
+
var ApproveVideoScriptInput = z49.object({
|
|
10630
|
+
taskId: z49.string().min(1).describe("ID de la tarea."),
|
|
10631
|
+
angleKey: z49.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.'),
|
|
10632
|
+
scenes: z49.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.")
|
|
10586
10633
|
}).strict();
|
|
10587
|
-
var RegenerateVideoScriptInput =
|
|
10588
|
-
taskId:
|
|
10589
|
-
angleKey:
|
|
10634
|
+
var RegenerateVideoScriptInput = z49.object({
|
|
10635
|
+
taskId: z49.string().min(1).describe("ID de la tarea."),
|
|
10636
|
+
angleKey: z49.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.'),
|
|
10590
10637
|
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).')
|
|
10591
10638
|
}).strict();
|
|
10592
10639
|
function registerScriptReviewTools(server, api) {
|
|
@@ -10626,9 +10673,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
10626
10673
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
10627
10674
|
|
|
10628
10675
|
// src/tools/connections.ts
|
|
10629
|
-
import { z as
|
|
10676
|
+
import { z as z50 } from "zod";
|
|
10630
10677
|
function registerConnectionTools(server, api) {
|
|
10631
|
-
server.tool("list_shopify_shops", "Lista las tiendas Shopify conectadas por este usuario. Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.",
|
|
10678
|
+
server.tool("list_shopify_shops", "Lista las tiendas Shopify conectadas por este usuario. Si la lista est\xE1 vac\xEDa, dile al usuario que conecte una tienda en productmaker.app/integrations antes de intentar publicar.", z50.object({}).shape, async () => {
|
|
10632
10679
|
try {
|
|
10633
10680
|
const r = await api.getJson("/v1/shopify/shops");
|
|
10634
10681
|
return asText(r);
|
|
@@ -10636,10 +10683,10 @@ function registerConnectionTools(server, api) {
|
|
|
10636
10683
|
throw translateError(e);
|
|
10637
10684
|
}
|
|
10638
10685
|
});
|
|
10639
|
-
server.tool("list_shopify_products", 'Busca productos en una tienda Shopify conectada para elegir el target de una republicaci\xF3n. 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.',
|
|
10640
|
-
shopDomain:
|
|
10641
|
-
query:
|
|
10642
|
-
taskId:
|
|
10686
|
+
server.tool("list_shopify_products", 'Busca productos en una tienda Shopify conectada para elegir el target de una republicaci\xF3n. 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.', z50.object({
|
|
10687
|
+
shopDomain: z50.string().min(3).max(120),
|
|
10688
|
+
query: z50.string().trim().max(120).optional(),
|
|
10689
|
+
taskId: z50.string().uuid().optional()
|
|
10643
10690
|
}).shape, async ({ shopDomain, query, taskId }) => {
|
|
10644
10691
|
try {
|
|
10645
10692
|
const params = new URLSearchParams({
|
|
@@ -10653,7 +10700,7 @@ function registerConnectionTools(server, api) {
|
|
|
10653
10700
|
throw translateError(e);
|
|
10654
10701
|
}
|
|
10655
10702
|
});
|
|
10656
|
-
server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. 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.",
|
|
10703
|
+
server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. 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.", z50.object({}).shape, async () => {
|
|
10657
10704
|
try {
|
|
10658
10705
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
10659
10706
|
return asText(r);
|
|
@@ -10661,7 +10708,13 @@ function registerConnectionTools(server, api) {
|
|
|
10661
10708
|
throw translateError(e);
|
|
10662
10709
|
}
|
|
10663
10710
|
});
|
|
10664
|
-
server.
|
|
10711
|
+
server.registerTool("list_meta_destinations", {
|
|
10712
|
+
description: "Lista los destinos de publicaci\xF3n de Meta del usuario: Business portfolios, cuentas publicitarias dentro de cada portfolio y Facebook Pages disponibles. 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.",
|
|
10713
|
+
inputSchema: z50.object({}).shape,
|
|
10714
|
+
_meta: {
|
|
10715
|
+
"openai/widgetAccessible": true
|
|
10716
|
+
}
|
|
10717
|
+
}, async () => {
|
|
10665
10718
|
try {
|
|
10666
10719
|
const r = await api.getJson("/v1/facebook/destinations");
|
|
10667
10720
|
return asText(r);
|
|
@@ -10669,7 +10722,7 @@ function registerConnectionTools(server, api) {
|
|
|
10669
10722
|
throw translateError(e);
|
|
10670
10723
|
}
|
|
10671
10724
|
});
|
|
10672
|
-
server.tool("list_tiktok_advertisers", "Lista las cuentas de TikTok Ads conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.",
|
|
10725
|
+
server.tool("list_tiktok_advertisers", "Lista las cuentas de TikTok Ads conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar TikTok en productmaker.app/integrations.", z50.object({}).shape, async () => {
|
|
10673
10726
|
try {
|
|
10674
10727
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
10675
10728
|
return asText(r);
|
|
@@ -10681,9 +10734,9 @@ function registerConnectionTools(server, api) {
|
|
|
10681
10734
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
10682
10735
|
|
|
10683
10736
|
// src/tools/actors.ts
|
|
10684
|
-
import { z as
|
|
10737
|
+
import { z as z51 } from "zod";
|
|
10685
10738
|
function registerActorTools(server, api) {
|
|
10686
|
-
server.tool("list_actors", "Lista los personajes guardados del usuario (personas creadas con IA que pueden protagonizar los videos e im\xE1genes). 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.",
|
|
10739
|
+
server.tool("list_actors", "Lista los personajes guardados del usuario (personas creadas con IA que pueden protagonizar los videos e im\xE1genes). 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.", z51.object({}).shape, async () => {
|
|
10687
10740
|
try {
|
|
10688
10741
|
const rows = await api.getJson("/v1/actors");
|
|
10689
10742
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -10704,116 +10757,116 @@ function registerActorTools(server, api) {
|
|
|
10704
10757
|
__name(registerActorTools, "registerActorTools");
|
|
10705
10758
|
|
|
10706
10759
|
// src/tools/publish.ts
|
|
10707
|
-
import { z as
|
|
10708
|
-
var ShopifyInput =
|
|
10709
|
-
taskId:
|
|
10710
|
-
shopDomain:
|
|
10760
|
+
import { z as z52 } from "zod";
|
|
10761
|
+
var ShopifyInput = z52.object({
|
|
10762
|
+
taskId: z52.string().min(1),
|
|
10763
|
+
shopDomain: z52.string().min(1),
|
|
10711
10764
|
/** Override: number of landing images to include. Default = ALL images the
|
|
10712
10765
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
10713
10766
|
* generously here; the backend validates each index against
|
|
10714
10767
|
* landing.images.length and rejects out-of-range. */
|
|
10715
|
-
numLandingImages:
|
|
10716
|
-
variantIndex:
|
|
10768
|
+
numLandingImages: z52.number().int().min(1).max(20).optional(),
|
|
10769
|
+
variantIndex: z52.number().int().min(0).optional(),
|
|
10717
10770
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
10718
10771
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
10719
10772
|
* a single-option product page. Defaults to false. */
|
|
10720
|
-
showVariantPicker:
|
|
10773
|
+
showVariantPicker: z52.boolean().optional(),
|
|
10721
10774
|
/** Default `auto` updates the product previously published for this task and
|
|
10722
10775
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
10723
10776
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
10724
|
-
publicationMode:
|
|
10777
|
+
publicationMode: z52.enum([
|
|
10725
10778
|
"auto",
|
|
10726
10779
|
"existing",
|
|
10727
10780
|
"new"
|
|
10728
10781
|
]).optional(),
|
|
10729
10782
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
10730
10783
|
* publicationMode is `existing`. */
|
|
10731
|
-
targetProductId:
|
|
10784
|
+
targetProductId: z52.string().trim().min(1).max(300).optional()
|
|
10732
10785
|
});
|
|
10733
|
-
var McpCampaignConfig =
|
|
10786
|
+
var McpCampaignConfig = z52.object({
|
|
10734
10787
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
10735
10788
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
10736
10789
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
10737
|
-
dailyBudgetUsd:
|
|
10790
|
+
dailyBudgetUsd: z52.number().positive().optional(),
|
|
10738
10791
|
/** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
|
|
10739
10792
|
* ad set). TikTok takes only the first entry. */
|
|
10740
|
-
targetCountries:
|
|
10741
|
-
campaignName:
|
|
10793
|
+
targetCountries: z52.array(z52.string().length(2)).max(1).optional(),
|
|
10794
|
+
campaignName: z52.string().trim().min(1).max(100).optional()
|
|
10742
10795
|
});
|
|
10743
10796
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
10744
|
-
var MetaInput =
|
|
10745
|
-
taskId:
|
|
10797
|
+
var MetaInput = z52.object({
|
|
10798
|
+
taskId: z52.string().min(1),
|
|
10746
10799
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
10747
|
-
portfolioId:
|
|
10800
|
+
portfolioId: z52.string().trim().min(1),
|
|
10748
10801
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
10749
|
-
pageId:
|
|
10802
|
+
pageId: z52.string().trim().min(1),
|
|
10750
10803
|
adAccountId: McpAdAccountId,
|
|
10751
|
-
pixelId:
|
|
10752
|
-
landingUrl:
|
|
10804
|
+
pixelId: z52.string().min(1).optional(),
|
|
10805
|
+
landingUrl: z52.string().url().optional(),
|
|
10753
10806
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
10754
10807
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
10755
|
-
angleIndexes:
|
|
10808
|
+
angleIndexes: z52.array(z52.number().int().nonnegative()).optional(),
|
|
10756
10809
|
campaignConfig: McpCampaignConfig.optional(),
|
|
10757
10810
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
10758
10811
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
10759
10812
|
* (Meta's primary-text limit). */
|
|
10760
|
-
primaryText:
|
|
10813
|
+
primaryText: z52.string().trim().min(1).max(500).optional(),
|
|
10761
10814
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
10762
10815
|
* (wa.me) instead of a landing page. */
|
|
10763
|
-
phoneNumber:
|
|
10816
|
+
phoneNumber: z52.string().min(8).max(32).optional()
|
|
10764
10817
|
});
|
|
10765
|
-
var GroupedTaskSource =
|
|
10766
|
-
type:
|
|
10767
|
-
taskId:
|
|
10768
|
-
angleIndex:
|
|
10769
|
-
videoVariant:
|
|
10818
|
+
var GroupedTaskSource = z52.object({
|
|
10819
|
+
type: z52.literal("task"),
|
|
10820
|
+
taskId: z52.string().min(1),
|
|
10821
|
+
angleIndex: z52.number().int().min(0).optional(),
|
|
10822
|
+
videoVariant: z52.enum([
|
|
10770
10823
|
"with_subtitles",
|
|
10771
10824
|
"without_subtitles"
|
|
10772
10825
|
]).optional(),
|
|
10773
|
-
imageVariantIndex:
|
|
10774
|
-
});
|
|
10775
|
-
var GroupedMediaSource =
|
|
10776
|
-
type:
|
|
10777
|
-
url:
|
|
10778
|
-
path:
|
|
10779
|
-
thumbnailUrl:
|
|
10780
|
-
thumbnailPath:
|
|
10826
|
+
imageVariantIndex: z52.number().int().min(0).optional()
|
|
10827
|
+
});
|
|
10828
|
+
var GroupedMediaSource = z52.object({
|
|
10829
|
+
type: z52.literal("media"),
|
|
10830
|
+
url: z52.string().url().optional().describe("Public HTTPS media URL. For a file on the user laptop, use request_meta_media_upload on the hosted MCP instead."),
|
|
10831
|
+
path: z52.string().min(1).optional().describe('Local file path only when this MCP runs over stdio. On the hosted MCP, call request_meta_media_upload and then use source.type="staged".'),
|
|
10832
|
+
thumbnailUrl: z52.string().url().optional(),
|
|
10833
|
+
thumbnailPath: z52.string().min(1).optional()
|
|
10781
10834
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
10782
10835
|
message: "media source needs exactly one of `url` or `path`"
|
|
10783
10836
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
10784
10837
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
10785
10838
|
});
|
|
10786
|
-
var GroupedStagedMediaSource =
|
|
10787
|
-
type:
|
|
10839
|
+
var GroupedStagedMediaSource = z52.object({
|
|
10840
|
+
type: z52.literal("staged"),
|
|
10788
10841
|
/** Returned by check_meta_media_upload after the user selects a local file. */
|
|
10789
|
-
stagingAssetId:
|
|
10790
|
-
thumbnailAssetId:
|
|
10842
|
+
stagingAssetId: z52.string().uuid(),
|
|
10843
|
+
thumbnailAssetId: z52.string().uuid().optional()
|
|
10791
10844
|
});
|
|
10792
|
-
var GroupedCreative =
|
|
10793
|
-
type:
|
|
10845
|
+
var GroupedCreative = z52.object({
|
|
10846
|
+
type: z52.enum([
|
|
10794
10847
|
"image",
|
|
10795
10848
|
"video"
|
|
10796
10849
|
]),
|
|
10797
|
-
source:
|
|
10850
|
+
source: z52.union([
|
|
10798
10851
|
GroupedTaskSource,
|
|
10799
10852
|
GroupedMediaSource,
|
|
10800
10853
|
GroupedStagedMediaSource
|
|
10801
10854
|
]),
|
|
10802
|
-
title:
|
|
10803
|
-
description:
|
|
10855
|
+
title: z52.string().max(120).optional(),
|
|
10856
|
+
description: z52.string().max(500).optional(),
|
|
10804
10857
|
cta: MetaCtaType.optional(),
|
|
10805
|
-
creativeId:
|
|
10858
|
+
creativeId: z52.string().min(1).optional()
|
|
10806
10859
|
});
|
|
10807
|
-
var GroupedCampaignConfig =
|
|
10860
|
+
var GroupedCampaignConfig = z52.object({
|
|
10808
10861
|
campaignType: MetaCampaignType.default("sales"),
|
|
10809
10862
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
10810
10863
|
budgetMode: MetaBudgetMode.default("campaign"),
|
|
10811
|
-
campaignDailyBudget:
|
|
10812
|
-
adSets:
|
|
10813
|
-
tempId:
|
|
10814
|
-
name:
|
|
10815
|
-
dailyBudget:
|
|
10816
|
-
creativeIds:
|
|
10864
|
+
campaignDailyBudget: z52.number().int().positive().optional(),
|
|
10865
|
+
adSets: z52.array(z52.object({
|
|
10866
|
+
tempId: z52.string().min(1).max(80),
|
|
10867
|
+
name: z52.string().min(1).max(100),
|
|
10868
|
+
dailyBudget: z52.number().int().positive().optional(),
|
|
10869
|
+
creativeIds: z52.array(z52.string().min(1)).min(1)
|
|
10817
10870
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
10818
10871
|
/**
|
|
10819
10872
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -10821,22 +10874,22 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10821
10874
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
10822
10875
|
* the API since #849 — unreachable from this tool.
|
|
10823
10876
|
*/
|
|
10824
|
-
destination:
|
|
10825
|
-
|
|
10826
|
-
type:
|
|
10827
|
-
landingUrl:
|
|
10877
|
+
destination: z52.discriminatedUnion("type", [
|
|
10878
|
+
z52.object({
|
|
10879
|
+
type: z52.literal("landing"),
|
|
10880
|
+
landingUrl: z52.string().url()
|
|
10828
10881
|
}),
|
|
10829
|
-
|
|
10830
|
-
type:
|
|
10831
|
-
phoneNumber:
|
|
10882
|
+
z52.object({
|
|
10883
|
+
type: z52.literal("whatsapp"),
|
|
10884
|
+
phoneNumber: z52.string().min(8).max(32)
|
|
10832
10885
|
})
|
|
10833
10886
|
]),
|
|
10834
|
-
saveAsDefault:
|
|
10887
|
+
saveAsDefault: z52.boolean().default(false),
|
|
10835
10888
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
10836
10889
|
}).superRefine((value, ctx) => {
|
|
10837
10890
|
if (value.budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
10838
10891
|
ctx.addIssue({
|
|
10839
|
-
code:
|
|
10892
|
+
code: z52.ZodIssueCode.custom,
|
|
10840
10893
|
path: [
|
|
10841
10894
|
"campaignDailyBudget"
|
|
10842
10895
|
],
|
|
@@ -10847,7 +10900,7 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10847
10900
|
value.adSets.forEach((adSet, index) => {
|
|
10848
10901
|
if (adSet.dailyBudget === void 0) {
|
|
10849
10902
|
ctx.addIssue({
|
|
10850
|
-
code:
|
|
10903
|
+
code: z52.ZodIssueCode.custom,
|
|
10851
10904
|
path: [
|
|
10852
10905
|
"adSets",
|
|
10853
10906
|
index,
|
|
@@ -10859,26 +10912,26 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10859
10912
|
});
|
|
10860
10913
|
}
|
|
10861
10914
|
});
|
|
10862
|
-
var PublishCreativesToMetaInputBase =
|
|
10863
|
-
creatives:
|
|
10915
|
+
var PublishCreativesToMetaInputBase = z52.object({
|
|
10916
|
+
creatives: z52.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
10864
10917
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
10865
|
-
portfolioId:
|
|
10918
|
+
portfolioId: z52.string().trim().min(1),
|
|
10866
10919
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
10867
|
-
pageId:
|
|
10920
|
+
pageId: z52.string().trim().min(1),
|
|
10868
10921
|
adAccountId: McpAdAccountId,
|
|
10869
|
-
pixelId:
|
|
10922
|
+
pixelId: z52.string().min(1).optional(),
|
|
10870
10923
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
10871
10924
|
* superRefine below. Mirrors the API's `UploadToMetaRequest`. */
|
|
10872
|
-
landingUrl:
|
|
10873
|
-
targetCountry:
|
|
10874
|
-
campaignName:
|
|
10925
|
+
landingUrl: z52.string().url().optional(),
|
|
10926
|
+
targetCountry: z52.string().length(2),
|
|
10927
|
+
campaignName: z52.string().trim().min(1).max(100),
|
|
10875
10928
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
10876
10929
|
});
|
|
10877
10930
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
10878
10931
|
const destination = value.campaignConfig?.destination;
|
|
10879
10932
|
if (destination?.type !== "whatsapp" && !value.landingUrl) {
|
|
10880
10933
|
ctx.addIssue({
|
|
10881
|
-
code:
|
|
10934
|
+
code: z52.ZodIssueCode.custom,
|
|
10882
10935
|
path: [
|
|
10883
10936
|
"landingUrl"
|
|
10884
10937
|
],
|
|
@@ -10887,7 +10940,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
10887
10940
|
}
|
|
10888
10941
|
if (destination?.type === "landing" && destination.landingUrl !== value.landingUrl) {
|
|
10889
10942
|
ctx.addIssue({
|
|
10890
|
-
code:
|
|
10943
|
+
code: z52.ZodIssueCode.custom,
|
|
10891
10944
|
path: [
|
|
10892
10945
|
"campaignConfig",
|
|
10893
10946
|
"destination",
|
|
@@ -10897,16 +10950,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
10897
10950
|
});
|
|
10898
10951
|
}
|
|
10899
10952
|
});
|
|
10900
|
-
var PresignUploadResponseSchema =
|
|
10901
|
-
uploadUrl:
|
|
10953
|
+
var PresignUploadResponseSchema = z52.object({
|
|
10954
|
+
uploadUrl: z52.string().url().refine((value) => {
|
|
10902
10955
|
const url = new URL(value);
|
|
10903
10956
|
return !url.username && !url.password && url.protocol === "https:";
|
|
10904
10957
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
10905
|
-
publicUrl:
|
|
10958
|
+
publicUrl: z52.string().url().refine((value) => {
|
|
10906
10959
|
const url = new URL(value);
|
|
10907
10960
|
return !url.username && !url.password;
|
|
10908
10961
|
}, "public media URL must not contain embedded credentials"),
|
|
10909
|
-
stagingAssetId:
|
|
10962
|
+
stagingAssetId: z52.string().uuid()
|
|
10910
10963
|
});
|
|
10911
10964
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
10912
10965
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -10931,16 +10984,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
10931
10984
|
return uploadResolvedMedia(api, media, assetRole);
|
|
10932
10985
|
}
|
|
10933
10986
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
10934
|
-
var TikTokInput =
|
|
10935
|
-
taskId:
|
|
10936
|
-
advertiserId:
|
|
10937
|
-
pixelId:
|
|
10938
|
-
landingUrl:
|
|
10939
|
-
angleIndexes:
|
|
10987
|
+
var TikTokInput = z52.object({
|
|
10988
|
+
taskId: z52.string().min(1),
|
|
10989
|
+
advertiserId: z52.string().min(1),
|
|
10990
|
+
pixelId: z52.string().min(1).optional(),
|
|
10991
|
+
landingUrl: z52.string().url().optional(),
|
|
10992
|
+
angleIndexes: z52.array(z52.number().int().nonnegative()).optional(),
|
|
10940
10993
|
campaignConfig: McpCampaignConfig.optional(),
|
|
10941
10994
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
10942
10995
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
10943
|
-
primaryText:
|
|
10996
|
+
primaryText: z52.string().trim().min(1).max(500).optional()
|
|
10944
10997
|
});
|
|
10945
10998
|
function registerPublishTools(server, api, opts = {}) {
|
|
10946
10999
|
const transport = opts.transport ?? "http";
|
|
@@ -11128,6 +11181,17 @@ function renderShopifyPublishMarkdown(r) {
|
|
|
11128
11181
|
if (r.productUrl) lines.push(`
|
|
11129
11182
|
### Producto
|
|
11130
11183
|
[Ver producto](${r.productUrl})`);
|
|
11184
|
+
if (r.needsThemeSetup) {
|
|
11185
|
+
lines.push(r.themeEditorDeepLink ? `
|
|
11186
|
+
\u26A0\uFE0F La landing est\xE1 publicada, pero falta activar el bloque Code Landing en el tema. [Abrir editor de Shopify](${r.themeEditorDeepLink}) y guardar una vez.` : "\n\u26A0\uFE0F La landing est\xE1 publicada, pero falta activar el bloque Code Landing en el tema. Abre el editor de Shopify, agrega el bloque y guarda una vez.");
|
|
11187
|
+
}
|
|
11188
|
+
if (r.tracking?.status === "migrated") {
|
|
11189
|
+
lines.push("\nTracking: \u2705 configuraci\xF3n anterior migrada autom\xE1ticamente. No necesitas editar el tema.");
|
|
11190
|
+
} else if (r.tracking?.status === "synced") {
|
|
11191
|
+
lines.push("\nTracking: \u2705 c\xF3digo manual sincronizado desde `theme.liquid` al layout de ProductMaker.");
|
|
11192
|
+
} else if (r.tracking?.status === "not_detected") {
|
|
11193
|
+
lines.push("\nTracking: \u2705 ProductMaker dej\xF3 la landing compatible con el tracking nativo de Shopify; no se encontr\xF3 c\xF3digo manual para migrar.");
|
|
11194
|
+
}
|
|
11131
11195
|
if (!r.pageUrl && !r.productUrl && r.status !== "success") {
|
|
11132
11196
|
lines.push("\n_La publicaci\xF3n a\xFAn est\xE1 proces\xE1ndose. Usa `get_task_status` para verificar progreso._");
|
|
11133
11197
|
}
|
|
@@ -11172,71 +11236,81 @@ function toTikTokCampaignConfig(cfg) {
|
|
|
11172
11236
|
__name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
11173
11237
|
|
|
11174
11238
|
// src/tools/meta-upload.ts
|
|
11175
|
-
import { z as
|
|
11176
|
-
var MetaUploadSessionInputBase =
|
|
11177
|
-
mediaKind:
|
|
11239
|
+
import { z as z53 } from "zod";
|
|
11240
|
+
var MetaUploadSessionInputBase = z53.object({
|
|
11241
|
+
mediaKind: z53.enum([
|
|
11178
11242
|
"image",
|
|
11179
11243
|
"video",
|
|
11180
11244
|
"mixed"
|
|
11181
11245
|
]).default("mixed").describe("The kind of file the user will select in the upload page. Use mixed for a normal batch of image and video creatives."),
|
|
11182
|
-
assetRole:
|
|
11246
|
+
assetRole: z53.enum([
|
|
11183
11247
|
"media",
|
|
11184
11248
|
"thumbnail"
|
|
11185
|
-
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail.")
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
|
|
11249
|
+
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
11250
|
+
maxFiles: z53.number().int().min(1).max(10).optional().describe("Optional batch limit. Use 1 for a single creative; mixed media defaults to 10.")
|
|
11251
|
+
});
|
|
11252
|
+
var OpenAiFileReference = z53.object({
|
|
11253
|
+
download_url: z53.string().url(),
|
|
11254
|
+
file_id: z53.string().min(1),
|
|
11255
|
+
mime_type: z53.string().min(1).optional(),
|
|
11256
|
+
file_name: z53.string().min(1).optional()
|
|
11192
11257
|
}).strict();
|
|
11193
11258
|
var MetaUploadSessionToolInputShape = {
|
|
11194
11259
|
...MetaUploadSessionInputBase.shape,
|
|
11195
|
-
files:
|
|
11260
|
+
files: z53.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.")
|
|
11196
11261
|
};
|
|
11197
|
-
var MetaUploadSessionToolInput =
|
|
11262
|
+
var MetaUploadSessionToolInput = z53.object(MetaUploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
11198
11263
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
11199
11264
|
ctx.addIssue({
|
|
11200
|
-
code:
|
|
11265
|
+
code: z53.ZodIssueCode.custom,
|
|
11201
11266
|
path: [
|
|
11202
11267
|
"mediaKind"
|
|
11203
11268
|
],
|
|
11204
11269
|
message: "Meta thumbnails must be images"
|
|
11205
11270
|
});
|
|
11206
11271
|
}
|
|
11272
|
+
if (value.mediaKind !== "mixed" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
11273
|
+
ctx.addIssue({
|
|
11274
|
+
code: z53.ZodIssueCode.custom,
|
|
11275
|
+
path: [
|
|
11276
|
+
"maxFiles"
|
|
11277
|
+
],
|
|
11278
|
+
message: "Image and video sessions accept exactly one file"
|
|
11279
|
+
});
|
|
11280
|
+
}
|
|
11207
11281
|
});
|
|
11208
|
-
var MetaUploadSessionResponse2 =
|
|
11209
|
-
sessionId:
|
|
11210
|
-
uploadPageUrl:
|
|
11211
|
-
mediaKind:
|
|
11282
|
+
var MetaUploadSessionResponse2 = z53.object({
|
|
11283
|
+
sessionId: z53.string().uuid(),
|
|
11284
|
+
uploadPageUrl: z53.string().url(),
|
|
11285
|
+
mediaKind: z53.enum([
|
|
11212
11286
|
"image",
|
|
11213
11287
|
"video",
|
|
11214
11288
|
"mixed"
|
|
11215
11289
|
]),
|
|
11216
|
-
assetRole:
|
|
11290
|
+
assetRole: z53.enum([
|
|
11217
11291
|
"media",
|
|
11218
11292
|
"thumbnail"
|
|
11219
11293
|
]),
|
|
11220
|
-
maxFiles:
|
|
11221
|
-
expiresAt:
|
|
11294
|
+
maxFiles: z53.number().int().positive(),
|
|
11295
|
+
expiresAt: z53.string().datetime()
|
|
11222
11296
|
});
|
|
11223
|
-
var MetaUploadStatusInput =
|
|
11224
|
-
sessionId:
|
|
11297
|
+
var MetaUploadStatusInput = z53.object({
|
|
11298
|
+
sessionId: z53.string().uuid().describe("The sessionId returned by request_meta_media_upload.")
|
|
11225
11299
|
});
|
|
11226
|
-
var MetaUploadStatusResponse =
|
|
11227
|
-
sessionId:
|
|
11228
|
-
status:
|
|
11300
|
+
var MetaUploadStatusResponse = z53.object({
|
|
11301
|
+
sessionId: z53.string().uuid(),
|
|
11302
|
+
status: z53.enum([
|
|
11229
11303
|
"pending",
|
|
11230
11304
|
"uploaded"
|
|
11231
11305
|
]),
|
|
11232
|
-
assets:
|
|
11233
|
-
stagingAssetId:
|
|
11234
|
-
mediaKind:
|
|
11306
|
+
assets: z53.array(z53.object({
|
|
11307
|
+
stagingAssetId: z53.string().uuid(),
|
|
11308
|
+
mediaKind: z53.enum([
|
|
11235
11309
|
"image",
|
|
11236
11310
|
"video"
|
|
11237
11311
|
])
|
|
11238
11312
|
})).max(10).default([]),
|
|
11239
|
-
stagingAssetId:
|
|
11313
|
+
stagingAssetId: z53.string().uuid().optional()
|
|
11240
11314
|
});
|
|
11241
11315
|
function uploadSessionText(result) {
|
|
11242
11316
|
const mediaLabel = result.mediaKind === "mixed" ? "archivos" : result.mediaKind === "video" ? "video" : "imagen";
|
|
@@ -11245,8 +11319,8 @@ function uploadSessionText(result) {
|
|
|
11245
11319
|
{
|
|
11246
11320
|
type: "text",
|
|
11247
11321
|
text: [
|
|
11248
|
-
`###
|
|
11249
|
-
`[Abrir carga segura](${result.uploadPageUrl})`,
|
|
11322
|
+
`### Prepara tu ${mediaLabel} en ProductMaker`,
|
|
11323
|
+
`Usa primero el App inline de este chat. Si tu host no soporta el bridge de archivos, usa este fallback: [Abrir carga segura](${result.uploadPageUrl})`,
|
|
11250
11324
|
`Puedes seleccionar hasta ${result.maxFiles} ${result.mediaKind === "mixed" ? "archivos" : "archivo"}. Cuando termine, escribe **\u201Clisto\u201D** en este chat para que ProductMaker contin\xFAe con Meta.`,
|
|
11251
11325
|
`sessionId: \`${result.sessionId}\``,
|
|
11252
11326
|
`Este enlace expira: ${result.expiresAt}`
|
|
@@ -11259,7 +11333,7 @@ __name(uploadSessionText, "uploadSessionText");
|
|
|
11259
11333
|
function registerMetaUploadTools(server, api) {
|
|
11260
11334
|
server.registerTool("request_meta_media_upload", {
|
|
11261
11335
|
title: "Solicitar carga segura de Meta",
|
|
11262
|
-
description: "Inicia una carga segura desde la laptop del usuario para creativos propios de Meta. Por defecto crea una sesi\xF3n `mixed` de hasta diez archivos; tambi\xE9n admite una sola imagen o video.
|
|
11336
|
+
description: "Inicia una carga segura desde la laptop del usuario para creativos propios de Meta. Por defecto crea una sesi\xF3n `mixed` de hasta diez archivos; tambi\xE9n admite una sola imagen o video. Si el usuario adjunta una foto o video en el mismo mensaje de ChatGPT, pasa esas referencias opcionales en `files` para que el MCP App inline las consuma dentro del chat. ProductMaker conserva `files` solo como metadata del UI bridge: NO los descarga y NO los reenv\xEDa. No pidas URL CDN, ruta local, bytes ni base64. El flujo principal es el MCP App inline; el enlace externo de ProductMaker queda como fallback para hosts sin bridge de archivos. Despu\xE9s conserva el `sessionId` y llama `check_meta_media_upload`. Esta herramienta no publica ni consume cr\xE9ditos.",
|
|
11263
11337
|
inputSchema: MetaUploadSessionToolInputShape,
|
|
11264
11338
|
outputSchema: MetaUploadSessionResponse2,
|
|
11265
11339
|
_meta: {
|
|
@@ -11291,7 +11365,13 @@ function registerMetaUploadTools(server, api) {
|
|
|
11291
11365
|
throw translateError(error);
|
|
11292
11366
|
}
|
|
11293
11367
|
});
|
|
11294
|
-
server.
|
|
11368
|
+
server.registerTool("check_meta_media_upload", {
|
|
11369
|
+
description: 'Comprueba si el usuario ya termin\xF3 de subir desde el enlace de ProductMaker. Si status=uploaded, devuelve `assets[]`; crea un creativo `source.type="staged"` por cada asset, usando su `mediaKind` como el tipo del creativo, hasta diez en el batch. Si la carga fue parcial, publica \xFAnicamente los assets que `assets[]` reporta como subidos. Conserva el `stagingAssetId` legado si aparece. Si status=pending, pide al usuario que termine; no publiques todav\xEDa.',
|
|
11370
|
+
inputSchema: MetaUploadStatusInput.shape,
|
|
11371
|
+
_meta: {
|
|
11372
|
+
"openai/widgetAccessible": true
|
|
11373
|
+
}
|
|
11374
|
+
}, async (rawInput) => {
|
|
11295
11375
|
try {
|
|
11296
11376
|
const input = MetaUploadStatusInput.parse(rawInput);
|
|
11297
11377
|
const result = MetaUploadStatusResponse.parse(await api.getJson(`/v1/ads/meta-upload-sessions/${encodeURIComponent(input.sessionId)}`));
|
|
@@ -11304,13 +11384,13 @@ function registerMetaUploadTools(server, api) {
|
|
|
11304
11384
|
__name(registerMetaUploadTools, "registerMetaUploadTools");
|
|
11305
11385
|
|
|
11306
11386
|
// src/tools/campaigns.ts
|
|
11307
|
-
import { z as
|
|
11308
|
-
var MetaStatusInput =
|
|
11309
|
-
campaignId:
|
|
11387
|
+
import { z as z54 } from "zod";
|
|
11388
|
+
var MetaStatusInput = z54.object({
|
|
11389
|
+
campaignId: z54.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
11310
11390
|
});
|
|
11311
|
-
var TikTokStatusInput =
|
|
11312
|
-
campaignId:
|
|
11313
|
-
advertiserId:
|
|
11391
|
+
var TikTokStatusInput = z54.object({
|
|
11392
|
+
campaignId: z54.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
11393
|
+
advertiserId: z54.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
11314
11394
|
});
|
|
11315
11395
|
function registerCampaignTools(server, api) {
|
|
11316
11396
|
server.tool("get_meta_campaign_status", "Consulta el estado actual + m\xE9tricas lifetime (spend, impressions, clicks, reach) de una campa\xF1a Meta publicada. 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, async (input) => {
|
|
@@ -11407,10 +11487,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
11407
11487
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
11408
11488
|
|
|
11409
11489
|
// ../../packages/product-economics/src/product-costing.ts
|
|
11410
|
-
import { z as
|
|
11490
|
+
import { z as z56 } from "zod";
|
|
11411
11491
|
|
|
11412
11492
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
11413
|
-
import { z as
|
|
11493
|
+
import { z as z55 } from "zod";
|
|
11414
11494
|
|
|
11415
11495
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
11416
11496
|
var product_costing_shipping_references_default = {
|
|
@@ -11474,21 +11554,21 @@ var product_costing_shipping_references_default = {
|
|
|
11474
11554
|
};
|
|
11475
11555
|
|
|
11476
11556
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
11477
|
-
var ShippingReferenceSchema =
|
|
11478
|
-
reference:
|
|
11479
|
-
min:
|
|
11480
|
-
max:
|
|
11481
|
-
updatedAt:
|
|
11482
|
-
confidence:
|
|
11557
|
+
var ShippingReferenceSchema = z55.object({
|
|
11558
|
+
reference: z55.number().positive(),
|
|
11559
|
+
min: z55.number().nonnegative(),
|
|
11560
|
+
max: z55.number().positive(),
|
|
11561
|
+
updatedAt: z55.string().date(),
|
|
11562
|
+
confidence: z55.enum([
|
|
11483
11563
|
"high",
|
|
11484
11564
|
"medium",
|
|
11485
11565
|
"medium-low"
|
|
11486
11566
|
]),
|
|
11487
|
-
sources:
|
|
11567
|
+
sources: z55.array(z55.string().url().startsWith("https://")).min(1).max(3)
|
|
11488
11568
|
}).superRefine(({ reference, min, max }, context) => {
|
|
11489
11569
|
if (min > reference || reference > max) {
|
|
11490
11570
|
context.addIssue({
|
|
11491
|
-
code:
|
|
11571
|
+
code: z55.ZodIssueCode.custom,
|
|
11492
11572
|
message: "shipping_reference_outside_range",
|
|
11493
11573
|
path: [
|
|
11494
11574
|
"reference"
|
|
@@ -11496,7 +11576,7 @@ var ShippingReferenceSchema = z54.object({
|
|
|
11496
11576
|
});
|
|
11497
11577
|
}
|
|
11498
11578
|
});
|
|
11499
|
-
var SHIPPING_REFERENCES =
|
|
11579
|
+
var SHIPPING_REFERENCES = z55.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
11500
11580
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
11501
11581
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
11502
11582
|
"MX",
|
|
@@ -11678,18 +11758,18 @@ function getProductCostingCountryName(country) {
|
|
|
11678
11758
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
11679
11759
|
|
|
11680
11760
|
// ../../packages/product-economics/src/product-costing.ts
|
|
11681
|
-
var ProductCostingInputSchema =
|
|
11682
|
-
country:
|
|
11683
|
-
supplierCost:
|
|
11684
|
-
shippingCost:
|
|
11685
|
-
returnRate:
|
|
11686
|
-
cancellationRate:
|
|
11687
|
-
adsManagerCpa:
|
|
11688
|
-
desiredMargin:
|
|
11761
|
+
var ProductCostingInputSchema = z56.object({
|
|
11762
|
+
country: z56.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
11763
|
+
supplierCost: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
11764
|
+
shippingCost: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
11765
|
+
returnRate: z56.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
11766
|
+
cancellationRate: z56.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
11767
|
+
adsManagerCpa: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
11768
|
+
desiredMargin: z56.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
11689
11769
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
11690
11770
|
if (returnRate + cancellationRate >= 1) {
|
|
11691
11771
|
context.addIssue({
|
|
11692
|
-
code:
|
|
11772
|
+
code: z56.ZodIssueCode.custom,
|
|
11693
11773
|
message: "delivery_rate_positive",
|
|
11694
11774
|
path: [
|
|
11695
11775
|
"cancellationRate"
|
|
@@ -11756,14 +11836,14 @@ function calculateProductCosting(rawInput) {
|
|
|
11756
11836
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
11757
11837
|
|
|
11758
11838
|
// src/tools/product-costing.ts
|
|
11759
|
-
import { z as
|
|
11760
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
11761
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
11762
|
-
var ProductCostingToolInput =
|
|
11763
|
-
country:
|
|
11839
|
+
import { z as z57 } from "zod";
|
|
11840
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z57.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
11841
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z57.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
11842
|
+
var ProductCostingToolInput = z57.object({
|
|
11843
|
+
country: z57.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
11764
11844
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
11765
11845
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
11766
|
-
supplierCost:
|
|
11846
|
+
supplierCost: z57.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."),
|
|
11767
11847
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
11768
11848
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
11769
11849
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -11895,7 +11975,7 @@ function formatPercent(value) {
|
|
|
11895
11975
|
__name(formatPercent, "formatPercent");
|
|
11896
11976
|
|
|
11897
11977
|
// src/tools/product-research.ts
|
|
11898
|
-
import { z as
|
|
11978
|
+
import { z as z58 } from "zod";
|
|
11899
11979
|
|
|
11900
11980
|
// src/tools/product-research-idempotency.ts
|
|
11901
11981
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -12011,17 +12091,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
12011
12091
|
]);
|
|
12012
12092
|
var POLL_INTERVAL_MS = 5e3;
|
|
12013
12093
|
var MAX_WAIT_SECONDS = 120;
|
|
12014
|
-
var FindInput =
|
|
12094
|
+
var FindInput = z58.object({
|
|
12015
12095
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
12016
12096
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
12017
|
-
confirmed:
|
|
12018
|
-
waitSeconds:
|
|
12097
|
+
confirmed: z58.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
12098
|
+
waitSeconds: z58.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
12019
12099
|
});
|
|
12020
|
-
var GetInput =
|
|
12021
|
-
runId:
|
|
12100
|
+
var GetInput = z58.object({
|
|
12101
|
+
runId: z58.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
12022
12102
|
});
|
|
12023
|
-
var ListInput =
|
|
12024
|
-
limit:
|
|
12103
|
+
var ListInput = z58.object({
|
|
12104
|
+
limit: z58.number().int().min(1).max(20).default(10)
|
|
12025
12105
|
});
|
|
12026
12106
|
function textResult(text) {
|
|
12027
12107
|
return {
|
|
@@ -12113,14 +12193,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
12113
12193
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
12114
12194
|
|
|
12115
12195
|
// src/tools/dropshipping-projects.ts
|
|
12116
|
-
import { z as
|
|
12117
|
-
var ProjectId =
|
|
12118
|
-
var DropshippingProjectStatus =
|
|
12196
|
+
import { z as z59 } from "zod";
|
|
12197
|
+
var ProjectId = z59.string().uuid();
|
|
12198
|
+
var DropshippingProjectStatus = z59.enum([
|
|
12119
12199
|
"active",
|
|
12120
12200
|
"completed",
|
|
12121
12201
|
"archived"
|
|
12122
12202
|
]);
|
|
12123
|
-
var DropshippingProjectPhase =
|
|
12203
|
+
var DropshippingProjectPhase = z59.enum([
|
|
12124
12204
|
"research",
|
|
12125
12205
|
"costing",
|
|
12126
12206
|
"media",
|
|
@@ -12129,21 +12209,21 @@ var DropshippingProjectPhase = z58.enum([
|
|
|
12129
12209
|
"advertising",
|
|
12130
12210
|
"complete"
|
|
12131
12211
|
]);
|
|
12132
|
-
var DropshippingRewardMilestone =
|
|
12212
|
+
var DropshippingRewardMilestone = z59.enum([
|
|
12133
12213
|
"product_selected",
|
|
12134
12214
|
"costing_saved",
|
|
12135
12215
|
"product_media_ready",
|
|
12136
12216
|
"creatives_completed",
|
|
12137
12217
|
"campaign_created"
|
|
12138
12218
|
]);
|
|
12139
|
-
var TargetCountry =
|
|
12219
|
+
var TargetCountry = z59.enum([
|
|
12140
12220
|
"CO",
|
|
12141
12221
|
"MX",
|
|
12142
12222
|
"PE",
|
|
12143
12223
|
"EC",
|
|
12144
12224
|
"CL"
|
|
12145
12225
|
]);
|
|
12146
|
-
var ResearchCategory =
|
|
12226
|
+
var ResearchCategory = z59.enum([
|
|
12147
12227
|
"auto",
|
|
12148
12228
|
"automotive",
|
|
12149
12229
|
"kitchen",
|
|
@@ -12158,7 +12238,7 @@ var ResearchCategory = z58.enum([
|
|
|
12158
12238
|
"garden",
|
|
12159
12239
|
"cleaning"
|
|
12160
12240
|
]);
|
|
12161
|
-
var HttpUrl3 =
|
|
12241
|
+
var HttpUrl3 = z59.string().url().max(2e3).refine((value) => {
|
|
12162
12242
|
try {
|
|
12163
12243
|
return [
|
|
12164
12244
|
"http:",
|
|
@@ -12168,46 +12248,46 @@ var HttpUrl3 = z58.string().url().max(2e3).refine((value) => {
|
|
|
12168
12248
|
return false;
|
|
12169
12249
|
}
|
|
12170
12250
|
}, "URL must use HTTP(S)");
|
|
12171
|
-
var ResearchCandidateOrigin =
|
|
12172
|
-
type:
|
|
12251
|
+
var ResearchCandidateOrigin = z59.object({
|
|
12252
|
+
type: z59.literal("research_candidate"),
|
|
12173
12253
|
runId: ProjectId,
|
|
12174
|
-
candidateSourceId:
|
|
12254
|
+
candidateSourceId: z59.string().min(1).max(160)
|
|
12175
12255
|
});
|
|
12176
|
-
var TaskOrigin =
|
|
12177
|
-
type:
|
|
12256
|
+
var TaskOrigin = z59.object({
|
|
12257
|
+
type: z59.literal("task"),
|
|
12178
12258
|
taskId: ProjectId
|
|
12179
12259
|
});
|
|
12180
|
-
var ManualOrigin =
|
|
12181
|
-
type:
|
|
12260
|
+
var ManualOrigin = z59.object({
|
|
12261
|
+
type: z59.literal("manual"),
|
|
12182
12262
|
clientRequestId: ProjectId,
|
|
12183
|
-
country:
|
|
12263
|
+
country: z59.string().min(2).max(3).optional()
|
|
12184
12264
|
});
|
|
12185
|
-
var StartProjectInput =
|
|
12186
|
-
origin:
|
|
12265
|
+
var StartProjectInput = z59.object({
|
|
12266
|
+
origin: z59.discriminatedUnion("type", [
|
|
12187
12267
|
ResearchCandidateOrigin,
|
|
12188
12268
|
TaskOrigin,
|
|
12189
12269
|
ManualOrigin
|
|
12190
12270
|
]),
|
|
12191
|
-
productName:
|
|
12271
|
+
productName: z59.string().trim().min(1).max(240).optional(),
|
|
12192
12272
|
productUrl: HttpUrl3.optional(),
|
|
12193
|
-
country:
|
|
12194
|
-
languageCode:
|
|
12273
|
+
country: z59.string().min(2).max(3).optional(),
|
|
12274
|
+
languageCode: z59.string().min(2).max(16).optional()
|
|
12195
12275
|
}).strict();
|
|
12196
|
-
var CostProjectInput =
|
|
12276
|
+
var CostProjectInput = z59.object({
|
|
12197
12277
|
projectId: ProjectId,
|
|
12198
|
-
version:
|
|
12199
|
-
country:
|
|
12200
|
-
supplierCost:
|
|
12201
|
-
shippingCost:
|
|
12202
|
-
returnRate:
|
|
12203
|
-
cancellationRate:
|
|
12204
|
-
adsManagerCpa:
|
|
12205
|
-
desiredMargin:
|
|
12206
|
-
});
|
|
12207
|
-
var GuideInput =
|
|
12278
|
+
version: z59.number().int().positive(),
|
|
12279
|
+
country: z59.string().trim().min(2).max(3),
|
|
12280
|
+
supplierCost: z59.number().finite().positive(),
|
|
12281
|
+
shippingCost: z59.number().finite().nonnegative(),
|
|
12282
|
+
returnRate: z59.number().finite().min(0).lt(1),
|
|
12283
|
+
cancellationRate: z59.number().finite().min(0).lt(1),
|
|
12284
|
+
adsManagerCpa: z59.number().finite().nonnegative(),
|
|
12285
|
+
desiredMargin: z59.number().finite().min(0).lt(1)
|
|
12286
|
+
});
|
|
12287
|
+
var GuideInput = z59.object({
|
|
12208
12288
|
projectId: ProjectId.optional()
|
|
12209
12289
|
}).strict();
|
|
12210
|
-
var DropshippingProjectNextAction =
|
|
12290
|
+
var DropshippingProjectNextAction = z59.discriminatedUnion("kind", [
|
|
12211
12291
|
"cost_product",
|
|
12212
12292
|
"provide_product_media",
|
|
12213
12293
|
"generate_creatives",
|
|
@@ -12221,78 +12301,78 @@ var DropshippingProjectNextAction = z58.discriminatedUnion("kind", [
|
|
|
12221
12301
|
"create_meta_campaign",
|
|
12222
12302
|
"repair_meta_campaign",
|
|
12223
12303
|
"review_paused_campaign"
|
|
12224
|
-
].map((kind) =>
|
|
12225
|
-
kind:
|
|
12226
|
-
href:
|
|
12304
|
+
].map((kind) => z59.object({
|
|
12305
|
+
kind: z59.literal(kind),
|
|
12306
|
+
href: z59.string().min(1)
|
|
12227
12307
|
})));
|
|
12228
|
-
var CostingInputSchema =
|
|
12229
|
-
country:
|
|
12230
|
-
supplierCost:
|
|
12231
|
-
shippingCost:
|
|
12232
|
-
returnRate:
|
|
12233
|
-
cancellationRate:
|
|
12234
|
-
adsManagerCpa:
|
|
12235
|
-
desiredMargin:
|
|
12308
|
+
var CostingInputSchema = z59.object({
|
|
12309
|
+
country: z59.string().min(2).max(3),
|
|
12310
|
+
supplierCost: z59.number().finite().positive(),
|
|
12311
|
+
shippingCost: z59.number().finite().nonnegative(),
|
|
12312
|
+
returnRate: z59.number().finite().min(0).lt(1),
|
|
12313
|
+
cancellationRate: z59.number().finite().min(0).lt(1),
|
|
12314
|
+
adsManagerCpa: z59.number().finite().nonnegative(),
|
|
12315
|
+
desiredMargin: z59.number().finite().min(0).lt(1)
|
|
12236
12316
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
12237
12317
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
12238
|
-
code:
|
|
12318
|
+
code: z59.ZodIssueCode.custom,
|
|
12239
12319
|
path: [
|
|
12240
12320
|
"cancellationRate"
|
|
12241
12321
|
]
|
|
12242
12322
|
});
|
|
12243
12323
|
});
|
|
12244
|
-
var CostingResultSchema =
|
|
12245
|
-
country:
|
|
12246
|
-
deliveryRate:
|
|
12247
|
-
adjustedShippingCost:
|
|
12248
|
-
adjustedCpa:
|
|
12249
|
-
totalCost:
|
|
12250
|
-
suggestedPrice:
|
|
12251
|
-
baseCommercialPrice:
|
|
12252
|
-
minimumSafePrice:
|
|
12253
|
-
commercialPrice:
|
|
12254
|
-
comparisonPrice:
|
|
12255
|
-
estimatedProfit:
|
|
12256
|
-
actualMargin:
|
|
12257
|
-
breakEvenAdsManagerCpa:
|
|
12258
|
-
wasPriceAutoAdjusted:
|
|
12259
|
-
profitabilityStatus:
|
|
12260
|
-
});
|
|
12261
|
-
var RewardProgressSchema =
|
|
12262
|
-
campaignKey:
|
|
12263
|
-
totalCredits:
|
|
12264
|
-
earnedCredits:
|
|
12265
|
-
milestones:
|
|
12324
|
+
var CostingResultSchema = z59.object({
|
|
12325
|
+
country: z59.string().min(2).max(3),
|
|
12326
|
+
deliveryRate: z59.number().finite(),
|
|
12327
|
+
adjustedShippingCost: z59.number().finite(),
|
|
12328
|
+
adjustedCpa: z59.number().finite(),
|
|
12329
|
+
totalCost: z59.number().finite(),
|
|
12330
|
+
suggestedPrice: z59.number().finite(),
|
|
12331
|
+
baseCommercialPrice: z59.number().finite(),
|
|
12332
|
+
minimumSafePrice: z59.number().finite(),
|
|
12333
|
+
commercialPrice: z59.number().finite(),
|
|
12334
|
+
comparisonPrice: z59.number().finite(),
|
|
12335
|
+
estimatedProfit: z59.number().finite(),
|
|
12336
|
+
actualMargin: z59.number().finite(),
|
|
12337
|
+
breakEvenAdsManagerCpa: z59.number().finite(),
|
|
12338
|
+
wasPriceAutoAdjusted: z59.boolean(),
|
|
12339
|
+
profitabilityStatus: z59.literal("healthy")
|
|
12340
|
+
});
|
|
12341
|
+
var RewardProgressSchema = z59.object({
|
|
12342
|
+
campaignKey: z59.literal("dropshipping-launch-v1"),
|
|
12343
|
+
totalCredits: z59.number().int().positive(),
|
|
12344
|
+
earnedCredits: z59.number().int().nonnegative(),
|
|
12345
|
+
milestones: z59.array(z59.object({
|
|
12266
12346
|
milestone: DropshippingRewardMilestone,
|
|
12267
|
-
credits:
|
|
12268
|
-
available:
|
|
12269
|
-
earned:
|
|
12347
|
+
credits: z59.number().int().positive(),
|
|
12348
|
+
available: z59.boolean().optional(),
|
|
12349
|
+
earned: z59.boolean(),
|
|
12270
12350
|
grantId: ProjectId.nullable(),
|
|
12271
|
-
grantedAt:
|
|
12351
|
+
grantedAt: z59.string().datetime().nullable()
|
|
12272
12352
|
})).length(DropshippingRewardMilestone.options.length)
|
|
12273
12353
|
});
|
|
12274
|
-
var ProjectResponseSchema =
|
|
12354
|
+
var ProjectResponseSchema = z59.object({
|
|
12275
12355
|
id: ProjectId,
|
|
12276
12356
|
taskId: ProjectId.nullable(),
|
|
12277
12357
|
status: DropshippingProjectStatus,
|
|
12278
|
-
originKey:
|
|
12358
|
+
originKey: z59.string().min(1),
|
|
12279
12359
|
researchRunId: ProjectId.nullable(),
|
|
12280
|
-
candidateSourceId:
|
|
12281
|
-
productName:
|
|
12360
|
+
candidateSourceId: z59.string().nullable(),
|
|
12361
|
+
productName: z59.string().nullable(),
|
|
12282
12362
|
productUrl: HttpUrl3.nullable(),
|
|
12283
12363
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
12284
|
-
targetCountry:
|
|
12285
|
-
languageCode:
|
|
12286
|
-
hasReferenceImage:
|
|
12364
|
+
targetCountry: z59.string().nullable(),
|
|
12365
|
+
languageCode: z59.string().nullable(),
|
|
12366
|
+
hasReferenceImage: z59.boolean(),
|
|
12287
12367
|
costingInput: CostingInputSchema.nullable(),
|
|
12288
12368
|
costingResult: CostingResultSchema.nullable(),
|
|
12289
|
-
costingVersion:
|
|
12290
|
-
version:
|
|
12369
|
+
costingVersion: z59.number().int().positive().nullable(),
|
|
12370
|
+
version: z59.number().int().positive(),
|
|
12291
12371
|
phase: DropshippingProjectPhase,
|
|
12292
12372
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
12293
12373
|
rewards: RewardProgressSchema,
|
|
12294
|
-
createdAt:
|
|
12295
|
-
updatedAt:
|
|
12374
|
+
createdAt: z59.string().datetime(),
|
|
12375
|
+
updatedAt: z59.string().datetime()
|
|
12296
12376
|
}).passthrough();
|
|
12297
12377
|
function projectText(raw) {
|
|
12298
12378
|
const project = ProjectResponseSchema.parse(raw);
|