@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/http.js
CHANGED
|
@@ -153,7 +153,7 @@ var ApiClient = class {
|
|
|
153
153
|
};
|
|
154
154
|
|
|
155
155
|
// src/index.ts
|
|
156
|
-
var MCP_VERSION = "2.
|
|
156
|
+
var MCP_VERSION = "2.9.1";
|
|
157
157
|
|
|
158
158
|
// src/meta-upload-app.ts
|
|
159
159
|
import { readFileSync } from "fs";
|
|
@@ -206,7 +206,7 @@ function registerMetaUploadAppResource(server) {
|
|
|
206
206
|
__name(registerMetaUploadAppResource, "registerMetaUploadAppResource");
|
|
207
207
|
|
|
208
208
|
// src/tools/tasks.ts
|
|
209
|
-
import { z as
|
|
209
|
+
import { z as z46 } from "zod";
|
|
210
210
|
|
|
211
211
|
// src/resolve-image.ts
|
|
212
212
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -2306,6 +2306,25 @@ var ShopifyPublicationStatus = z19.enum([
|
|
|
2306
2306
|
"success",
|
|
2307
2307
|
"error"
|
|
2308
2308
|
]);
|
|
2309
|
+
var ShopifyTrackingSyncStatus = z19.enum([
|
|
2310
|
+
"synced",
|
|
2311
|
+
"migrated",
|
|
2312
|
+
"not_detected"
|
|
2313
|
+
]);
|
|
2314
|
+
var ShopifyTrackingSource = z19.enum([
|
|
2315
|
+
"theme",
|
|
2316
|
+
"legacy_layout",
|
|
2317
|
+
"theme_and_legacy",
|
|
2318
|
+
"none"
|
|
2319
|
+
]);
|
|
2320
|
+
var ShopifyTrackingResult = z19.object({
|
|
2321
|
+
status: ShopifyTrackingSyncStatus,
|
|
2322
|
+
manualCodeDetected: z19.boolean(),
|
|
2323
|
+
/** True when code from a prior ProductMaker layout was preserved automatically. */
|
|
2324
|
+
legacyCodeMigrated: z19.boolean().default(false),
|
|
2325
|
+
source: ShopifyTrackingSource.default("none"),
|
|
2326
|
+
syncedAt: z19.string().datetime()
|
|
2327
|
+
});
|
|
2309
2328
|
var ShopifyPublishResponse = z19.object({
|
|
2310
2329
|
publicationId: z19.string().uuid(),
|
|
2311
2330
|
taskId: z19.string().uuid(),
|
|
@@ -2321,6 +2340,8 @@ var ShopifyPublishResponse = z19.object({
|
|
|
2321
2340
|
needsThemeSetup: z19.boolean().optional(),
|
|
2322
2341
|
/** One-click theme-editor deep link to add the Code Landing block (when needsThemeSetup). */
|
|
2323
2342
|
themeEditorDeepLink: z19.string().url().optional(),
|
|
2343
|
+
/** Tracking copied from the theme or migrated from a previous ProductMaker layout. */
|
|
2344
|
+
tracking: ShopifyTrackingResult.optional(),
|
|
2324
2345
|
createdAt: z19.string().datetime().optional(),
|
|
2325
2346
|
updatedAt: z19.string().datetime().optional()
|
|
2326
2347
|
});
|
|
@@ -3219,7 +3240,9 @@ var ImageCreativeEstimationOptions = z24.object({
|
|
|
3219
3240
|
});
|
|
3220
3241
|
var RegenerateLandingRoleBody = z24.object({
|
|
3221
3242
|
comment: z24.string().max(500).optional(),
|
|
3222
|
-
sourceKey: z24.string().max(200).optional()
|
|
3243
|
+
sourceKey: z24.string().max(200).optional(),
|
|
3244
|
+
/** Client-generated key lets a lost response be retried without another charge. */
|
|
3245
|
+
clientRequestId: z24.string().uuid().optional()
|
|
3223
3246
|
}).strict();
|
|
3224
3247
|
var LandingRegenerateEstimationOptions = z24.object({
|
|
3225
3248
|
/** KIE image endpoint has non-linear pricing by nVariants; for landing we default to 2. */
|
|
@@ -6165,8 +6188,7 @@ var DEFAULT_PRICING = {
|
|
|
6165
6188
|
userPriceCents: 0.04
|
|
6166
6189
|
}
|
|
6167
6190
|
};
|
|
6168
|
-
var
|
|
6169
|
-
var REGEN_SINGLE_CALL_OUR_COST_CENTS = DEFAULT_PRICING["kie:video-generation:grok-15s-480p"].ourCostCents;
|
|
6191
|
+
var REGEN_SINGLE_CALL_OUR_COST_CENTS = DEFAULT_PRICING["kie:video-generation:grok-15s-720p"].ourCostCents;
|
|
6170
6192
|
var SC_FRAME_COMPOSE_OUR_COST_CENTS = DEFAULT_PRICING["kie:image-generation:gpt-image-2:medium"].ourCostCents;
|
|
6171
6193
|
var SC_FRAME_COMPOSE_USER_PRICE_CENTS = DEFAULT_PRICING["kie:image-generation:gpt-image-2:medium"].userPriceCents;
|
|
6172
6194
|
var MS_FRAME_COMPOSE_OUR_COST_CENTS = DEFAULT_PRICING["kie:image-generation:nano-banana-2"].ourCostCents;
|
|
@@ -7443,10 +7465,35 @@ var ListLandingEditsResponse = z37.object({
|
|
|
7443
7465
|
edits: z37.array(LandingEditDto)
|
|
7444
7466
|
});
|
|
7445
7467
|
|
|
7446
|
-
// ../../packages/types/src/
|
|
7468
|
+
// ../../packages/types/src/landing-regeneration.ts
|
|
7447
7469
|
import { z as z38 } from "zod";
|
|
7470
|
+
var LandingRegenerationStatus = z38.enum([
|
|
7471
|
+
"queued",
|
|
7472
|
+
"processing",
|
|
7473
|
+
"published",
|
|
7474
|
+
"failed"
|
|
7475
|
+
]);
|
|
7476
|
+
var RegenerateLandingRoleResponse = z38.object({
|
|
7477
|
+
ok: z38.literal(true),
|
|
7478
|
+
role: LandingRole,
|
|
7479
|
+
promptIndex: z38.number().int().nonnegative(),
|
|
7480
|
+
operationId: z38.string().min(1)
|
|
7481
|
+
});
|
|
7482
|
+
var LandingRegenerationStatusResponse = z38.object({
|
|
7483
|
+
ok: z38.literal(true),
|
|
7484
|
+
operationId: z38.string().min(1),
|
|
7485
|
+
role: LandingRole,
|
|
7486
|
+
status: LandingRegenerationStatus,
|
|
7487
|
+
refunded: z38.boolean(),
|
|
7488
|
+
failureReason: z38.string().nullable(),
|
|
7489
|
+
publishedAssetKey: z38.string().nullable(),
|
|
7490
|
+
updatedAt: z38.string().datetime()
|
|
7491
|
+
});
|
|
7492
|
+
|
|
7493
|
+
// ../../packages/types/src/video-edit.ts
|
|
7494
|
+
import { z as z39 } from "zod";
|
|
7448
7495
|
var MAX_SEGMENT_SECONDS = 3;
|
|
7449
|
-
var VideoEditStatusSchema =
|
|
7496
|
+
var VideoEditStatusSchema = z39.enum([
|
|
7450
7497
|
"pending",
|
|
7451
7498
|
"processing",
|
|
7452
7499
|
"assembling",
|
|
@@ -7455,9 +7502,9 @@ var VideoEditStatusSchema = z38.enum([
|
|
|
7455
7502
|
"discarded",
|
|
7456
7503
|
"failed"
|
|
7457
7504
|
]);
|
|
7458
|
-
var VideoEditTimeSectionSchema =
|
|
7459
|
-
startSec:
|
|
7460
|
-
endSec:
|
|
7505
|
+
var VideoEditTimeSectionSchema = z39.object({
|
|
7506
|
+
startSec: z39.number().min(0),
|
|
7507
|
+
endSec: z39.number().positive()
|
|
7461
7508
|
}).refine((v) => v.endSec > v.startSec, {
|
|
7462
7509
|
message: "endSec must be after startSec",
|
|
7463
7510
|
path: [
|
|
@@ -7469,35 +7516,35 @@ var VideoEditTimeSectionSchema = z38.object({
|
|
|
7469
7516
|
"endSec"
|
|
7470
7517
|
]
|
|
7471
7518
|
});
|
|
7472
|
-
var VideoEditRequestSchema =
|
|
7473
|
-
comment:
|
|
7474
|
-
sections:
|
|
7519
|
+
var VideoEditRequestSchema = z39.object({
|
|
7520
|
+
comment: z39.string().trim().min(1).max(2e3),
|
|
7521
|
+
sections: z39.array(VideoEditTimeSectionSchema).min(1).optional()
|
|
7475
7522
|
});
|
|
7476
|
-
var VideoEditModeSchema =
|
|
7523
|
+
var VideoEditModeSchema = z39.enum([
|
|
7477
7524
|
"wan_edit",
|
|
7478
7525
|
"regenerate"
|
|
7479
7526
|
]);
|
|
7480
|
-
var VideoRegenerationEngineSchema =
|
|
7527
|
+
var VideoRegenerationEngineSchema = z39.enum([
|
|
7481
7528
|
"free_text",
|
|
7482
7529
|
"free_image",
|
|
7483
7530
|
"single_call",
|
|
7484
7531
|
"multi_shot"
|
|
7485
7532
|
]);
|
|
7486
|
-
var VideoRegenerationRouteFingerprintSchema =
|
|
7487
|
-
var RegenerateEditRequestSchema =
|
|
7488
|
-
angleKey:
|
|
7489
|
-
comment:
|
|
7533
|
+
var VideoRegenerationRouteFingerprintSchema = z39.string().trim().min(1).max(128);
|
|
7534
|
+
var RegenerateEditRequestSchema = z39.object({
|
|
7535
|
+
angleKey: z39.string().min(1),
|
|
7536
|
+
comment: z39.string().min(1).max(2e3)
|
|
7490
7537
|
});
|
|
7491
7538
|
|
|
7492
7539
|
// ../../packages/types/src/dropshipping-project.ts
|
|
7493
|
-
import { z as
|
|
7494
|
-
var DropshippingProjectStatusSchema =
|
|
7540
|
+
import { z as z40 } from "zod";
|
|
7541
|
+
var DropshippingProjectStatusSchema = z40.enum([
|
|
7495
7542
|
"active",
|
|
7496
7543
|
"completed",
|
|
7497
7544
|
"archived"
|
|
7498
7545
|
]);
|
|
7499
7546
|
var DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN = "dropshipping-launch-v1";
|
|
7500
|
-
var DropshippingRewardMilestoneSchema =
|
|
7547
|
+
var DropshippingRewardMilestoneSchema = z40.enum([
|
|
7501
7548
|
"product_selected",
|
|
7502
7549
|
"costing_saved",
|
|
7503
7550
|
"product_media_ready",
|
|
@@ -7512,21 +7559,21 @@ var DROPSHIPPING_LAUNCH_REWARD_CREDITS = {
|
|
|
7512
7559
|
campaign_created: 200
|
|
7513
7560
|
};
|
|
7514
7561
|
var DROPSHIPPING_LAUNCH_REWARD_TOTAL_CREDITS = Object.values(DROPSHIPPING_LAUNCH_REWARD_CREDITS).reduce((sum, credits) => sum + credits, 0);
|
|
7515
|
-
var DropshippingProjectRewardMilestoneStateSchema =
|
|
7562
|
+
var DropshippingProjectRewardMilestoneStateSchema = z40.object({
|
|
7516
7563
|
milestone: DropshippingRewardMilestoneSchema,
|
|
7517
|
-
credits:
|
|
7518
|
-
available:
|
|
7519
|
-
earned:
|
|
7520
|
-
grantId:
|
|
7521
|
-
grantedAt:
|
|
7522
|
-
});
|
|
7523
|
-
var DropshippingProjectRewardProgressSchema =
|
|
7524
|
-
campaignKey:
|
|
7525
|
-
totalCredits:
|
|
7526
|
-
earnedCredits:
|
|
7527
|
-
milestones:
|
|
7528
|
-
});
|
|
7529
|
-
var DropshippingProjectPhaseSchema =
|
|
7564
|
+
credits: z40.number().int().positive(),
|
|
7565
|
+
available: z40.boolean().optional(),
|
|
7566
|
+
earned: z40.boolean(),
|
|
7567
|
+
grantId: z40.string().uuid().nullable(),
|
|
7568
|
+
grantedAt: z40.string().datetime().nullable()
|
|
7569
|
+
});
|
|
7570
|
+
var DropshippingProjectRewardProgressSchema = z40.object({
|
|
7571
|
+
campaignKey: z40.literal(DROPSHIPPING_LAUNCH_REWARD_CAMPAIGN),
|
|
7572
|
+
totalCredits: z40.number().int().positive(),
|
|
7573
|
+
earnedCredits: z40.number().int().nonnegative(),
|
|
7574
|
+
milestones: z40.array(DropshippingProjectRewardMilestoneStateSchema).length(DropshippingRewardMilestoneSchema.options.length)
|
|
7575
|
+
});
|
|
7576
|
+
var DropshippingProjectPhaseSchema = z40.enum([
|
|
7530
7577
|
"research",
|
|
7531
7578
|
"costing",
|
|
7532
7579
|
"media",
|
|
@@ -7535,18 +7582,18 @@ var DropshippingProjectPhaseSchema = z39.enum([
|
|
|
7535
7582
|
"advertising",
|
|
7536
7583
|
"complete"
|
|
7537
7584
|
]);
|
|
7538
|
-
var DropshippingProjectCostingInputSchema =
|
|
7539
|
-
country:
|
|
7540
|
-
supplierCost:
|
|
7541
|
-
shippingCost:
|
|
7542
|
-
returnRate:
|
|
7543
|
-
cancellationRate:
|
|
7544
|
-
adsManagerCpa:
|
|
7545
|
-
desiredMargin:
|
|
7585
|
+
var DropshippingProjectCostingInputSchema = z40.object({
|
|
7586
|
+
country: z40.string().min(2).max(3),
|
|
7587
|
+
supplierCost: z40.number().finite().positive(),
|
|
7588
|
+
shippingCost: z40.number().finite().nonnegative(),
|
|
7589
|
+
returnRate: z40.number().finite().min(0).lt(1),
|
|
7590
|
+
cancellationRate: z40.number().finite().min(0).lt(1),
|
|
7591
|
+
adsManagerCpa: z40.number().finite().nonnegative(),
|
|
7592
|
+
desiredMargin: z40.number().finite().min(0).lt(1)
|
|
7546
7593
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
7547
7594
|
if (returnRate + cancellationRate >= 1) {
|
|
7548
7595
|
context.addIssue({
|
|
7549
|
-
code:
|
|
7596
|
+
code: z40.ZodIssueCode.custom,
|
|
7550
7597
|
path: [
|
|
7551
7598
|
"cancellationRate"
|
|
7552
7599
|
],
|
|
@@ -7554,24 +7601,24 @@ var DropshippingProjectCostingInputSchema = z39.object({
|
|
|
7554
7601
|
});
|
|
7555
7602
|
}
|
|
7556
7603
|
});
|
|
7557
|
-
var DropshippingProjectCostingResultSchema =
|
|
7558
|
-
country:
|
|
7559
|
-
deliveryRate:
|
|
7560
|
-
adjustedShippingCost:
|
|
7561
|
-
adjustedCpa:
|
|
7562
|
-
totalCost:
|
|
7563
|
-
suggestedPrice:
|
|
7564
|
-
baseCommercialPrice:
|
|
7565
|
-
minimumSafePrice:
|
|
7566
|
-
commercialPrice:
|
|
7567
|
-
comparisonPrice:
|
|
7568
|
-
estimatedProfit:
|
|
7569
|
-
actualMargin:
|
|
7570
|
-
breakEvenAdsManagerCpa:
|
|
7571
|
-
wasPriceAutoAdjusted:
|
|
7572
|
-
profitabilityStatus:
|
|
7573
|
-
});
|
|
7574
|
-
var HttpUrlSchema =
|
|
7604
|
+
var DropshippingProjectCostingResultSchema = z40.object({
|
|
7605
|
+
country: z40.string().min(2).max(3),
|
|
7606
|
+
deliveryRate: z40.number().finite(),
|
|
7607
|
+
adjustedShippingCost: z40.number().finite(),
|
|
7608
|
+
adjustedCpa: z40.number().finite(),
|
|
7609
|
+
totalCost: z40.number().finite(),
|
|
7610
|
+
suggestedPrice: z40.number().finite(),
|
|
7611
|
+
baseCommercialPrice: z40.number().finite(),
|
|
7612
|
+
minimumSafePrice: z40.number().finite(),
|
|
7613
|
+
commercialPrice: z40.number().finite(),
|
|
7614
|
+
comparisonPrice: z40.number().finite(),
|
|
7615
|
+
estimatedProfit: z40.number().finite(),
|
|
7616
|
+
actualMargin: z40.number().finite(),
|
|
7617
|
+
breakEvenAdsManagerCpa: z40.number().finite(),
|
|
7618
|
+
wasPriceAutoAdjusted: z40.boolean(),
|
|
7619
|
+
profitabilityStatus: z40.literal("healthy")
|
|
7620
|
+
});
|
|
7621
|
+
var HttpUrlSchema = z40.string().url().max(2e3).refine((value) => {
|
|
7575
7622
|
try {
|
|
7576
7623
|
return [
|
|
7577
7624
|
"http:",
|
|
@@ -7581,124 +7628,124 @@ var HttpUrlSchema = z39.string().url().max(2e3).refine((value) => {
|
|
|
7581
7628
|
return false;
|
|
7582
7629
|
}
|
|
7583
7630
|
}, "Product URL must use HTTP(S)");
|
|
7584
|
-
var ResearchCandidateOriginSchema =
|
|
7585
|
-
type:
|
|
7586
|
-
runId:
|
|
7587
|
-
candidateSourceId:
|
|
7588
|
-
});
|
|
7589
|
-
var TaskOriginSchema =
|
|
7590
|
-
type:
|
|
7591
|
-
taskId:
|
|
7592
|
-
});
|
|
7593
|
-
var ManualOriginSchema =
|
|
7594
|
-
type:
|
|
7595
|
-
clientRequestId:
|
|
7596
|
-
country:
|
|
7597
|
-
});
|
|
7598
|
-
var CreateDropshippingProjectRequestSchema =
|
|
7599
|
-
origin:
|
|
7631
|
+
var ResearchCandidateOriginSchema = z40.object({
|
|
7632
|
+
type: z40.literal("research_candidate"),
|
|
7633
|
+
runId: z40.string().uuid(),
|
|
7634
|
+
candidateSourceId: z40.string().min(1).max(160)
|
|
7635
|
+
});
|
|
7636
|
+
var TaskOriginSchema = z40.object({
|
|
7637
|
+
type: z40.literal("task"),
|
|
7638
|
+
taskId: z40.string().uuid()
|
|
7639
|
+
});
|
|
7640
|
+
var ManualOriginSchema = z40.object({
|
|
7641
|
+
type: z40.literal("manual"),
|
|
7642
|
+
clientRequestId: z40.string().uuid(),
|
|
7643
|
+
country: z40.string().min(2).max(3).optional()
|
|
7644
|
+
});
|
|
7645
|
+
var CreateDropshippingProjectRequestSchema = z40.object({
|
|
7646
|
+
origin: z40.discriminatedUnion("type", [
|
|
7600
7647
|
ResearchCandidateOriginSchema,
|
|
7601
7648
|
TaskOriginSchema,
|
|
7602
7649
|
ManualOriginSchema
|
|
7603
7650
|
]),
|
|
7604
|
-
productName:
|
|
7651
|
+
productName: z40.string().trim().min(1).max(240).optional(),
|
|
7605
7652
|
productUrl: HttpUrlSchema.optional(),
|
|
7606
|
-
country:
|
|
7607
|
-
languageCode:
|
|
7653
|
+
country: z40.string().min(2).max(3).optional(),
|
|
7654
|
+
languageCode: z40.string().min(2).max(16).optional()
|
|
7608
7655
|
}).strict();
|
|
7609
|
-
var SaveDropshippingProjectCostingRequestSchema =
|
|
7656
|
+
var SaveDropshippingProjectCostingRequestSchema = z40.object({
|
|
7610
7657
|
input: DropshippingProjectCostingInputSchema,
|
|
7611
|
-
version:
|
|
7658
|
+
version: z40.number().int().positive()
|
|
7612
7659
|
}).strict();
|
|
7613
|
-
var DropshippingProjectNextActionSchema =
|
|
7614
|
-
|
|
7615
|
-
kind:
|
|
7616
|
-
href:
|
|
7660
|
+
var DropshippingProjectNextActionSchema = z40.discriminatedUnion("kind", [
|
|
7661
|
+
z40.object({
|
|
7662
|
+
kind: z40.literal("cost_product"),
|
|
7663
|
+
href: z40.string().min(1)
|
|
7617
7664
|
}),
|
|
7618
|
-
|
|
7619
|
-
kind:
|
|
7620
|
-
href:
|
|
7665
|
+
z40.object({
|
|
7666
|
+
kind: z40.literal("provide_product_media"),
|
|
7667
|
+
href: z40.string().min(1)
|
|
7621
7668
|
}),
|
|
7622
|
-
|
|
7623
|
-
kind:
|
|
7624
|
-
href:
|
|
7669
|
+
z40.object({
|
|
7670
|
+
kind: z40.literal("generate_creatives"),
|
|
7671
|
+
href: z40.string().min(1)
|
|
7625
7672
|
}),
|
|
7626
|
-
|
|
7627
|
-
kind:
|
|
7628
|
-
href:
|
|
7673
|
+
z40.object({
|
|
7674
|
+
kind: z40.literal("wait_for_creatives"),
|
|
7675
|
+
href: z40.string().min(1)
|
|
7629
7676
|
}),
|
|
7630
|
-
|
|
7631
|
-
kind:
|
|
7632
|
-
href:
|
|
7677
|
+
z40.object({
|
|
7678
|
+
kind: z40.literal("repair_creatives"),
|
|
7679
|
+
href: z40.string().min(1)
|
|
7633
7680
|
}),
|
|
7634
|
-
|
|
7635
|
-
kind:
|
|
7636
|
-
href:
|
|
7681
|
+
z40.object({
|
|
7682
|
+
kind: z40.literal("complete_creative_set"),
|
|
7683
|
+
href: z40.string().min(1)
|
|
7637
7684
|
}),
|
|
7638
|
-
|
|
7639
|
-
kind:
|
|
7640
|
-
href:
|
|
7685
|
+
z40.object({
|
|
7686
|
+
kind: z40.literal("connect_shopify"),
|
|
7687
|
+
href: z40.string().min(1)
|
|
7641
7688
|
}),
|
|
7642
|
-
|
|
7643
|
-
kind:
|
|
7644
|
-
href:
|
|
7689
|
+
z40.object({
|
|
7690
|
+
kind: z40.literal("publish_storefront"),
|
|
7691
|
+
href: z40.string().min(1)
|
|
7645
7692
|
}),
|
|
7646
|
-
|
|
7647
|
-
kind:
|
|
7648
|
-
href:
|
|
7693
|
+
z40.object({
|
|
7694
|
+
kind: z40.literal("wait_for_storefront"),
|
|
7695
|
+
href: z40.string().min(1)
|
|
7649
7696
|
}),
|
|
7650
|
-
|
|
7651
|
-
kind:
|
|
7652
|
-
href:
|
|
7697
|
+
z40.object({
|
|
7698
|
+
kind: z40.literal("connect_meta"),
|
|
7699
|
+
href: z40.string().min(1)
|
|
7653
7700
|
}),
|
|
7654
|
-
|
|
7655
|
-
kind:
|
|
7656
|
-
href:
|
|
7701
|
+
z40.object({
|
|
7702
|
+
kind: z40.literal("create_meta_campaign"),
|
|
7703
|
+
href: z40.string().min(1)
|
|
7657
7704
|
}),
|
|
7658
|
-
|
|
7659
|
-
kind:
|
|
7660
|
-
href:
|
|
7705
|
+
z40.object({
|
|
7706
|
+
kind: z40.literal("repair_meta_campaign"),
|
|
7707
|
+
href: z40.string().min(1)
|
|
7661
7708
|
}),
|
|
7662
|
-
|
|
7663
|
-
kind:
|
|
7664
|
-
href:
|
|
7709
|
+
z40.object({
|
|
7710
|
+
kind: z40.literal("review_paused_campaign"),
|
|
7711
|
+
href: z40.string().min(1)
|
|
7665
7712
|
})
|
|
7666
7713
|
]);
|
|
7667
|
-
var DropshippingProjectResponseSchema =
|
|
7668
|
-
id:
|
|
7669
|
-
taskId:
|
|
7714
|
+
var DropshippingProjectResponseSchema = z40.object({
|
|
7715
|
+
id: z40.string().uuid(),
|
|
7716
|
+
taskId: z40.string().uuid().nullable(),
|
|
7670
7717
|
status: DropshippingProjectStatusSchema,
|
|
7671
|
-
originKey:
|
|
7672
|
-
researchRunId:
|
|
7673
|
-
candidateSourceId:
|
|
7674
|
-
productName:
|
|
7718
|
+
originKey: z40.string().min(1),
|
|
7719
|
+
researchRunId: z40.string().uuid().nullable(),
|
|
7720
|
+
candidateSourceId: z40.string().nullable(),
|
|
7721
|
+
productName: z40.string().nullable(),
|
|
7675
7722
|
productUrl: HttpUrlSchema.nullable(),
|
|
7676
|
-
referenceImageUrl:
|
|
7677
|
-
hasReferenceImage:
|
|
7678
|
-
targetCountry:
|
|
7679
|
-
languageCode:
|
|
7723
|
+
referenceImageUrl: z40.string().url().nullable(),
|
|
7724
|
+
hasReferenceImage: z40.boolean(),
|
|
7725
|
+
targetCountry: z40.string().nullable(),
|
|
7726
|
+
languageCode: z40.string().nullable(),
|
|
7680
7727
|
costingInput: DropshippingProjectCostingInputSchema.nullable(),
|
|
7681
7728
|
costingResult: DropshippingProjectCostingResultSchema.nullable(),
|
|
7682
|
-
costingVersion:
|
|
7683
|
-
version:
|
|
7729
|
+
costingVersion: z40.number().int().positive().nullable(),
|
|
7730
|
+
version: z40.number().int().positive(),
|
|
7684
7731
|
phase: DropshippingProjectPhaseSchema,
|
|
7685
7732
|
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
7686
7733
|
rewards: DropshippingProjectRewardProgressSchema,
|
|
7687
|
-
createdAt:
|
|
7688
|
-
updatedAt:
|
|
7734
|
+
createdAt: z40.string().datetime(),
|
|
7735
|
+
updatedAt: z40.string().datetime()
|
|
7689
7736
|
});
|
|
7690
7737
|
|
|
7691
7738
|
// ../../packages/types/src/scene-subject-contract.ts
|
|
7692
|
-
import { z as
|
|
7693
|
-
var SceneSubjectContractSchema =
|
|
7694
|
-
maxPeople:
|
|
7695
|
-
minPeople:
|
|
7696
|
-
minDistinctPeople:
|
|
7697
|
-
maxHands:
|
|
7739
|
+
import { z as z41 } from "zod";
|
|
7740
|
+
var SceneSubjectContractSchema = z41.object({
|
|
7741
|
+
maxPeople: z41.number().int().min(1).max(10),
|
|
7742
|
+
minPeople: z41.number().int().min(0).max(10),
|
|
7743
|
+
minDistinctPeople: z41.number().int().min(0).max(10),
|
|
7744
|
+
maxHands: z41.number().int().min(0).max(20)
|
|
7698
7745
|
}).superRefine((value, ctx) => {
|
|
7699
7746
|
if (value.minPeople > value.maxPeople) {
|
|
7700
7747
|
ctx.addIssue({
|
|
7701
|
-
code:
|
|
7748
|
+
code: z41.ZodIssueCode.custom,
|
|
7702
7749
|
path: [
|
|
7703
7750
|
"minPeople"
|
|
7704
7751
|
],
|
|
@@ -7707,7 +7754,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7707
7754
|
}
|
|
7708
7755
|
if (value.minDistinctPeople > value.maxPeople) {
|
|
7709
7756
|
ctx.addIssue({
|
|
7710
|
-
code:
|
|
7757
|
+
code: z41.ZodIssueCode.custom,
|
|
7711
7758
|
path: [
|
|
7712
7759
|
"minDistinctPeople"
|
|
7713
7760
|
],
|
|
@@ -7716,7 +7763,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7716
7763
|
}
|
|
7717
7764
|
if (value.minDistinctPeople > value.minPeople) {
|
|
7718
7765
|
ctx.addIssue({
|
|
7719
|
-
code:
|
|
7766
|
+
code: z41.ZodIssueCode.custom,
|
|
7720
7767
|
path: [
|
|
7721
7768
|
"minDistinctPeople"
|
|
7722
7769
|
],
|
|
@@ -7726,7 +7773,7 @@ var SceneSubjectContractSchema = z40.object({
|
|
|
7726
7773
|
});
|
|
7727
7774
|
|
|
7728
7775
|
// ../../packages/types/src/service-creative.ts
|
|
7729
|
-
import { z as
|
|
7776
|
+
import { z as z42 } from "zod";
|
|
7730
7777
|
var SERVICE_CREATIVE_PUBLIC_PRESETS = [
|
|
7731
7778
|
"auto",
|
|
7732
7779
|
"ugc_dynamic",
|
|
@@ -7734,19 +7781,19 @@ var SERVICE_CREATIVE_PUBLIC_PRESETS = [
|
|
|
7734
7781
|
"cinematic",
|
|
7735
7782
|
"wild_card"
|
|
7736
7783
|
];
|
|
7737
|
-
var ServiceCreativePresetSchema =
|
|
7784
|
+
var ServiceCreativePresetSchema = z42.enum(SERVICE_CREATIVE_PUBLIC_PRESETS);
|
|
7738
7785
|
var SERVICE_REVIEW_MODES = [
|
|
7739
7786
|
"automatic",
|
|
7740
7787
|
"guided"
|
|
7741
7788
|
];
|
|
7742
|
-
var ServiceReviewModeSchema =
|
|
7789
|
+
var ServiceReviewModeSchema = z42.enum(SERVICE_REVIEW_MODES);
|
|
7743
7790
|
var SERVICE_HIGGSFIELD_MODES = [
|
|
7744
7791
|
"product_review",
|
|
7745
7792
|
"ugc_how_to",
|
|
7746
7793
|
"tv_spot",
|
|
7747
7794
|
"wild_card"
|
|
7748
7795
|
];
|
|
7749
|
-
var ServiceHiggsfieldModeSchema =
|
|
7796
|
+
var ServiceHiggsfieldModeSchema = z42.enum(SERVICE_HIGGSFIELD_MODES);
|
|
7750
7797
|
var SERVICE_MEDIA_ROLES = [
|
|
7751
7798
|
"screen_demo",
|
|
7752
7799
|
"ad_reference",
|
|
@@ -7754,20 +7801,20 @@ var SERVICE_MEDIA_ROLES = [
|
|
|
7754
7801
|
"presenter_reference",
|
|
7755
7802
|
"brand_asset"
|
|
7756
7803
|
];
|
|
7757
|
-
var ServiceMediaRoleSchema =
|
|
7758
|
-
var ServiceMediaAssetSchema =
|
|
7804
|
+
var ServiceMediaRoleSchema = z42.enum(SERVICE_MEDIA_ROLES);
|
|
7805
|
+
var ServiceMediaAssetSchema = z42.object({
|
|
7759
7806
|
role: ServiceMediaRoleSchema,
|
|
7760
|
-
s3Key:
|
|
7807
|
+
s3Key: z42.string().min(1),
|
|
7761
7808
|
/** HMAC ticket returned by the authenticated service-media presign route. */
|
|
7762
|
-
uploadToken:
|
|
7763
|
-
mimeType:
|
|
7764
|
-
durationSec:
|
|
7765
|
-
sourceName:
|
|
7809
|
+
uploadToken: z42.string().min(1).optional(),
|
|
7810
|
+
mimeType: z42.string().min(1),
|
|
7811
|
+
durationSec: z42.number().positive().max(30).optional(),
|
|
7812
|
+
sourceName: z42.string().max(255).optional()
|
|
7766
7813
|
}).superRefine((asset, ctx) => {
|
|
7767
7814
|
const isVideoRole = asset.role === "screen_demo" || asset.role === "ad_reference";
|
|
7768
7815
|
if (isVideoRole && !asset.mimeType.startsWith("video/")) {
|
|
7769
7816
|
ctx.addIssue({
|
|
7770
|
-
code:
|
|
7817
|
+
code: z42.ZodIssueCode.custom,
|
|
7771
7818
|
message: `${asset.role} requires video media`,
|
|
7772
7819
|
path: [
|
|
7773
7820
|
"mimeType"
|
|
@@ -7776,7 +7823,7 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7776
7823
|
}
|
|
7777
7824
|
if (isVideoRole && asset.durationSec === void 0) {
|
|
7778
7825
|
ctx.addIssue({
|
|
7779
|
-
code:
|
|
7826
|
+
code: z42.ZodIssueCode.custom,
|
|
7780
7827
|
message: `${asset.role} requires durationSec`,
|
|
7781
7828
|
path: [
|
|
7782
7829
|
"durationSec"
|
|
@@ -7785,7 +7832,7 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7785
7832
|
}
|
|
7786
7833
|
if (!isVideoRole && !asset.mimeType.startsWith("image/")) {
|
|
7787
7834
|
ctx.addIssue({
|
|
7788
|
-
code:
|
|
7835
|
+
code: z42.ZodIssueCode.custom,
|
|
7789
7836
|
message: `${asset.role} requires image media`,
|
|
7790
7837
|
path: [
|
|
7791
7838
|
"mimeType"
|
|
@@ -7793,13 +7840,13 @@ var ServiceMediaAssetSchema = z41.object({
|
|
|
7793
7840
|
});
|
|
7794
7841
|
}
|
|
7795
7842
|
});
|
|
7796
|
-
var ServiceMediaBundleSchema =
|
|
7797
|
-
assets:
|
|
7843
|
+
var ServiceMediaBundleSchema = z42.object({
|
|
7844
|
+
assets: z42.array(ServiceMediaAssetSchema).max(15).default([])
|
|
7798
7845
|
}).superRefine((bundle, ctx) => {
|
|
7799
7846
|
const adReferences = bundle.assets.filter((asset) => asset.role === "ad_reference");
|
|
7800
7847
|
if (adReferences.length > 5) {
|
|
7801
7848
|
ctx.addIssue({
|
|
7802
|
-
code:
|
|
7849
|
+
code: z42.ZodIssueCode.custom,
|
|
7803
7850
|
message: "A maximum of five ad_reference videos is allowed",
|
|
7804
7851
|
path: [
|
|
7805
7852
|
"assets"
|
|
@@ -7809,7 +7856,7 @@ var ServiceMediaBundleSchema = z41.object({
|
|
|
7809
7856
|
const screenDemos = bundle.assets.filter((asset) => asset.role === "screen_demo");
|
|
7810
7857
|
if (screenDemos.length > 3) {
|
|
7811
7858
|
ctx.addIssue({
|
|
7812
|
-
code:
|
|
7859
|
+
code: z42.ZodIssueCode.custom,
|
|
7813
7860
|
message: "A maximum of three screen_demo videos is allowed",
|
|
7814
7861
|
path: [
|
|
7815
7862
|
"assets"
|
|
@@ -7826,33 +7873,33 @@ var SERVICE_MEDIA_ANALYSIS_KINDS = [
|
|
|
7826
7873
|
"product",
|
|
7827
7874
|
"other"
|
|
7828
7875
|
];
|
|
7829
|
-
var ServiceMediaAnalysisKindSchema =
|
|
7830
|
-
var ServiceMediaAnalysisItemSchema =
|
|
7831
|
-
assetIndex:
|
|
7832
|
-
mediaType:
|
|
7876
|
+
var ServiceMediaAnalysisKindSchema = z42.enum(SERVICE_MEDIA_ANALYSIS_KINDS);
|
|
7877
|
+
var ServiceMediaAnalysisItemSchema = z42.object({
|
|
7878
|
+
assetIndex: z42.number().int().nonnegative(),
|
|
7879
|
+
mediaType: z42.enum([
|
|
7833
7880
|
"image",
|
|
7834
7881
|
"video"
|
|
7835
7882
|
]),
|
|
7836
7883
|
kind: ServiceMediaAnalysisKindSchema,
|
|
7837
|
-
description:
|
|
7838
|
-
tags:
|
|
7839
|
-
suggestedRoles:
|
|
7840
|
-
visiblePeople:
|
|
7841
|
-
ocrText:
|
|
7842
|
-
speechSummary:
|
|
7843
|
-
});
|
|
7844
|
-
var ServiceMediaAnalysisSchema =
|
|
7845
|
-
version:
|
|
7846
|
-
analyzedAt:
|
|
7847
|
-
pricingAction:
|
|
7848
|
-
assetFingerprint:
|
|
7884
|
+
description: z42.string().min(1).max(1200),
|
|
7885
|
+
tags: z42.array(z42.string().min(1).max(80)).max(12),
|
|
7886
|
+
suggestedRoles: z42.array(ServiceMediaRoleSchema).max(4),
|
|
7887
|
+
visiblePeople: z42.number().int().nonnegative().max(20).optional(),
|
|
7888
|
+
ocrText: z42.string().max(2e3).optional(),
|
|
7889
|
+
speechSummary: z42.string().max(2e3).optional()
|
|
7890
|
+
});
|
|
7891
|
+
var ServiceMediaAnalysisSchema = z42.object({
|
|
7892
|
+
version: z42.literal(1),
|
|
7893
|
+
analyzedAt: z42.string().datetime(),
|
|
7894
|
+
pricingAction: z42.literal("service-media-analysis"),
|
|
7895
|
+
assetFingerprint: z42.string().regex(/^[a-f0-9]{64}$/),
|
|
7849
7896
|
/** Language used for human-readable descriptions and tags. Optional for old checkpoints. */
|
|
7850
|
-
language:
|
|
7897
|
+
language: z42.enum([
|
|
7851
7898
|
"es",
|
|
7852
7899
|
"en",
|
|
7853
7900
|
"pt"
|
|
7854
7901
|
]).optional(),
|
|
7855
|
-
items:
|
|
7902
|
+
items: z42.array(ServiceMediaAnalysisItemSchema).max(15)
|
|
7856
7903
|
});
|
|
7857
7904
|
|
|
7858
7905
|
// ../../packages/types/src/productmaker-chat-capabilities.ts
|
|
@@ -8030,7 +8077,7 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
8030
8077
|
{
|
|
8031
8078
|
name: "request_meta_media_upload",
|
|
8032
8079
|
confirmation: "none",
|
|
8033
|
-
schemaHash: "
|
|
8080
|
+
schemaHash: "fad928b17b4658eb5831bb8b62d5e65bd5220ad94b04b90ace09e658e1895c74"
|
|
8034
8081
|
},
|
|
8035
8082
|
{
|
|
8036
8083
|
name: "resolve_pending_action",
|
|
@@ -8046,8 +8093,8 @@ var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
|
8046
8093
|
var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITIES.map((capability) => capability.name);
|
|
8047
8094
|
|
|
8048
8095
|
// ../../packages/types/src/actor.ts
|
|
8049
|
-
import { z as
|
|
8050
|
-
var ActorStatusSchema =
|
|
8096
|
+
import { z as z43 } from "zod";
|
|
8097
|
+
var ActorStatusSchema = z43.enum([
|
|
8051
8098
|
"draft",
|
|
8052
8099
|
"generating",
|
|
8053
8100
|
"ready",
|
|
@@ -8056,18 +8103,18 @@ var ActorStatusSchema = z42.enum([
|
|
|
8056
8103
|
var ACTOR_NAME_MAX_CHARS = 60;
|
|
8057
8104
|
var ACTOR_DESCRIPTION_MAX_CHARS = 600;
|
|
8058
8105
|
var ACTOR_CANDIDATE_COUNT = 4;
|
|
8059
|
-
var ActorGenderSchema =
|
|
8106
|
+
var ActorGenderSchema = z43.enum([
|
|
8060
8107
|
"female",
|
|
8061
8108
|
"male",
|
|
8062
8109
|
"non_binary"
|
|
8063
8110
|
]);
|
|
8064
|
-
var ActorSchema =
|
|
8065
|
-
id:
|
|
8066
|
-
name:
|
|
8067
|
-
description:
|
|
8111
|
+
var ActorSchema = z43.object({
|
|
8112
|
+
id: z43.string(),
|
|
8113
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS),
|
|
8114
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS),
|
|
8068
8115
|
gender: ActorGenderSchema,
|
|
8069
|
-
voiceId:
|
|
8070
|
-
brandId:
|
|
8116
|
+
voiceId: z43.string().nullable().optional(),
|
|
8117
|
+
brandId: z43.string().nullable().optional(),
|
|
8071
8118
|
status: ActorStatusSchema,
|
|
8072
8119
|
/**
|
|
8073
8120
|
* A candidate-grid run is in flight RIGHT NOW.
|
|
@@ -8079,36 +8126,36 @@ var ActorSchema = z42.object({
|
|
|
8079
8126
|
* timestamp with a TTL, so an orphaned run reads as `false` instead of
|
|
8080
8127
|
* pinning the personaje forever.
|
|
8081
8128
|
*/
|
|
8082
|
-
generating:
|
|
8083
|
-
photoUrl:
|
|
8084
|
-
avatarUrl:
|
|
8085
|
-
candidateUrls:
|
|
8129
|
+
generating: z43.boolean().optional(),
|
|
8130
|
+
photoUrl: z43.string().url().nullable().optional(),
|
|
8131
|
+
avatarUrl: z43.string().url().nullable().optional(),
|
|
8132
|
+
candidateUrls: z43.array(z43.string().url()).optional(),
|
|
8086
8133
|
/** Indices of candidateUrls that failed the anatomy check (Task 6). */
|
|
8087
|
-
flaggedCandidateIndices:
|
|
8134
|
+
flaggedCandidateIndices: z43.array(z43.number().int()).optional()
|
|
8088
8135
|
});
|
|
8089
|
-
var CreateActorRequest =
|
|
8090
|
-
name:
|
|
8091
|
-
description:
|
|
8136
|
+
var CreateActorRequest = z43.object({
|
|
8137
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS),
|
|
8138
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS).default(""),
|
|
8092
8139
|
gender: ActorGenderSchema,
|
|
8093
|
-
voiceId:
|
|
8094
|
-
brandId:
|
|
8095
|
-
sourcePhotoKey:
|
|
8140
|
+
voiceId: z43.string().optional(),
|
|
8141
|
+
brandId: z43.string().optional(),
|
|
8142
|
+
sourcePhotoKey: z43.string().optional()
|
|
8096
8143
|
}).refine((v) => v.description.trim().length > 0 || !!v.sourcePhotoKey, {
|
|
8097
8144
|
message: "Se necesita una descripci\xF3n o una foto"
|
|
8098
8145
|
});
|
|
8099
|
-
var UpdateActorRequest =
|
|
8100
|
-
name:
|
|
8101
|
-
description:
|
|
8146
|
+
var UpdateActorRequest = z43.object({
|
|
8147
|
+
name: z43.string().min(1).max(ACTOR_NAME_MAX_CHARS).optional(),
|
|
8148
|
+
description: z43.string().max(ACTOR_DESCRIPTION_MAX_CHARS).optional(),
|
|
8102
8149
|
gender: ActorGenderSchema.optional(),
|
|
8103
|
-
voiceId:
|
|
8104
|
-
brandId:
|
|
8150
|
+
voiceId: z43.string().nullable().optional(),
|
|
8151
|
+
brandId: z43.string().nullable().optional()
|
|
8105
8152
|
});
|
|
8106
|
-
var ApproveActorRequest =
|
|
8107
|
-
candidateIndex:
|
|
8153
|
+
var ApproveActorRequest = z43.object({
|
|
8154
|
+
candidateIndex: z43.number().int().min(0).max(ACTOR_CANDIDATE_COUNT - 1)
|
|
8108
8155
|
});
|
|
8109
8156
|
|
|
8110
8157
|
// ../../packages/types/src/referral-dashboard.ts
|
|
8111
|
-
import { z as
|
|
8158
|
+
import { z as z44 } from "zod";
|
|
8112
8159
|
var REFERRAL_DASHBOARD_RAW_STATUSES = [
|
|
8113
8160
|
"ACTIVE",
|
|
8114
8161
|
"PENDING",
|
|
@@ -8127,66 +8174,66 @@ var REFERRAL_DASHBOARD_PLAN_KINDS = [
|
|
|
8127
8174
|
"last",
|
|
8128
8175
|
"none"
|
|
8129
8176
|
];
|
|
8130
|
-
var ReferralDashboardRawStatusSchema =
|
|
8131
|
-
var ReferralDashboardStateSchema =
|
|
8132
|
-
var ReferralDashboardPlanKindSchema =
|
|
8133
|
-
var ReferralDashboardStatusSchema =
|
|
8177
|
+
var ReferralDashboardRawStatusSchema = z44.enum(REFERRAL_DASHBOARD_RAW_STATUSES);
|
|
8178
|
+
var ReferralDashboardStateSchema = z44.enum(REFERRAL_DASHBOARD_STATES);
|
|
8179
|
+
var ReferralDashboardPlanKindSchema = z44.enum(REFERRAL_DASHBOARD_PLAN_KINDS);
|
|
8180
|
+
var ReferralDashboardStatusSchema = z44.enum([
|
|
8134
8181
|
"all",
|
|
8135
8182
|
"active",
|
|
8136
8183
|
"pending",
|
|
8137
8184
|
"inactive"
|
|
8138
8185
|
]).default("all");
|
|
8139
|
-
var ReferralDashboardPlanSchema =
|
|
8140
|
-
var ReferralDashboardFiltersSchema =
|
|
8186
|
+
var ReferralDashboardPlanSchema = z44.string().trim().min(1).max(100).optional();
|
|
8187
|
+
var ReferralDashboardFiltersSchema = z44.object({
|
|
8141
8188
|
status: ReferralDashboardStatusSchema,
|
|
8142
8189
|
plan: ReferralDashboardPlanSchema
|
|
8143
8190
|
});
|
|
8144
|
-
var ReferralDashboardSubscriptionSchema =
|
|
8145
|
-
planName:
|
|
8191
|
+
var ReferralDashboardSubscriptionSchema = z44.object({
|
|
8192
|
+
planName: z44.string().nullable(),
|
|
8146
8193
|
planKind: ReferralDashboardPlanKindSchema,
|
|
8147
8194
|
rawStatus: ReferralDashboardRawStatusSchema.nullable(),
|
|
8148
8195
|
state: ReferralDashboardStateSchema,
|
|
8149
|
-
currentPeriodEnd:
|
|
8196
|
+
currentPeriodEnd: z44.string().datetime({
|
|
8150
8197
|
offset: true
|
|
8151
8198
|
}).nullable(),
|
|
8152
|
-
cancelAtPeriodEnd:
|
|
8199
|
+
cancelAtPeriodEnd: z44.boolean()
|
|
8153
8200
|
});
|
|
8154
|
-
var ReferralDashboardReferralSchema =
|
|
8155
|
-
id:
|
|
8156
|
-
registeredAt:
|
|
8201
|
+
var ReferralDashboardReferralSchema = z44.object({
|
|
8202
|
+
id: z44.string().min(1),
|
|
8203
|
+
registeredAt: z44.string().datetime({
|
|
8157
8204
|
offset: true
|
|
8158
8205
|
}),
|
|
8159
8206
|
// Kept in the response for compatibility with existing referral API clients.
|
|
8160
8207
|
// The referrer dashboard intentionally does not render these legacy fields.
|
|
8161
|
-
expiresAt:
|
|
8208
|
+
expiresAt: z44.string().datetime({
|
|
8162
8209
|
offset: true
|
|
8163
8210
|
}).nullable().optional(),
|
|
8164
|
-
status:
|
|
8165
|
-
referredUser:
|
|
8166
|
-
email:
|
|
8211
|
+
status: z44.string().min(1).optional(),
|
|
8212
|
+
referredUser: z44.object({
|
|
8213
|
+
email: z44.string().nullable()
|
|
8167
8214
|
}),
|
|
8168
8215
|
subscription: ReferralDashboardSubscriptionSchema
|
|
8169
8216
|
});
|
|
8170
|
-
var ReferralDashboardReferralsPageSchema =
|
|
8171
|
-
referrals:
|
|
8172
|
-
total:
|
|
8217
|
+
var ReferralDashboardReferralsPageSchema = z44.object({
|
|
8218
|
+
referrals: z44.array(ReferralDashboardReferralSchema),
|
|
8219
|
+
total: z44.number().int().nonnegative()
|
|
8173
8220
|
});
|
|
8174
|
-
var ReferralDashboardPlanBreakdownSchema =
|
|
8175
|
-
planName:
|
|
8176
|
-
count:
|
|
8221
|
+
var ReferralDashboardPlanBreakdownSchema = z44.object({
|
|
8222
|
+
planName: z44.string().nullable(),
|
|
8223
|
+
count: z44.number().int().nonnegative()
|
|
8177
8224
|
});
|
|
8178
|
-
var ReferralDashboardMonthlyRegistrationSchema =
|
|
8179
|
-
month:
|
|
8180
|
-
count:
|
|
8225
|
+
var ReferralDashboardMonthlyRegistrationSchema = z44.object({
|
|
8226
|
+
month: z44.string().regex(/^\d{4}-(0[1-9]|1[0-2])$/),
|
|
8227
|
+
count: z44.number().int().nonnegative()
|
|
8181
8228
|
});
|
|
8182
|
-
var ReferralDashboardOverviewSchema =
|
|
8183
|
-
totalReferredUsers:
|
|
8184
|
-
activeUsers:
|
|
8185
|
-
pendingUsers:
|
|
8186
|
-
inactiveUsers:
|
|
8187
|
-
noPlanUsers:
|
|
8188
|
-
planBreakdown:
|
|
8189
|
-
monthlyRegistrations:
|
|
8229
|
+
var ReferralDashboardOverviewSchema = z44.object({
|
|
8230
|
+
totalReferredUsers: z44.number().int().nonnegative(),
|
|
8231
|
+
activeUsers: z44.number().int().nonnegative(),
|
|
8232
|
+
pendingUsers: z44.number().int().nonnegative(),
|
|
8233
|
+
inactiveUsers: z44.number().int().nonnegative(),
|
|
8234
|
+
noPlanUsers: z44.number().int().nonnegative(),
|
|
8235
|
+
planBreakdown: z44.array(ReferralDashboardPlanBreakdownSchema),
|
|
8236
|
+
monthlyRegistrations: z44.array(ReferralDashboardMonthlyRegistrationSchema).refine((months) => months.length === 6, "Expected six monthly registration buckets")
|
|
8190
8237
|
});
|
|
8191
8238
|
|
|
8192
8239
|
// src/resolve-media.ts
|
|
@@ -8428,10 +8475,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
8428
8475
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
8429
8476
|
|
|
8430
8477
|
// src/tools/shared.ts
|
|
8431
|
-
import { z as
|
|
8432
|
-
var Lang =
|
|
8433
|
-
var Country =
|
|
8434
|
-
var LandingStrategyEnum =
|
|
8478
|
+
import { z as z45 } from "zod";
|
|
8479
|
+
var Lang = z45.string().min(2).max(10);
|
|
8480
|
+
var Country = z45.string().min(2).max(3);
|
|
8481
|
+
var LandingStrategyEnum = z45.enum([
|
|
8435
8482
|
"auto",
|
|
8436
8483
|
"classic",
|
|
8437
8484
|
"pain_solution",
|
|
@@ -8440,12 +8487,12 @@ var LandingStrategyEnum = z44.enum([
|
|
|
8440
8487
|
"offer_value",
|
|
8441
8488
|
"lifestyle_identity"
|
|
8442
8489
|
]);
|
|
8443
|
-
var LandingImageFormatEnum =
|
|
8490
|
+
var LandingImageFormatEnum = z45.enum([
|
|
8444
8491
|
"9:16",
|
|
8445
8492
|
"4:5",
|
|
8446
8493
|
"1:1"
|
|
8447
8494
|
]);
|
|
8448
|
-
var VideoPresetEnum =
|
|
8495
|
+
var VideoPresetEnum = z45.enum([
|
|
8449
8496
|
"auto",
|
|
8450
8497
|
"ugc_dynamic",
|
|
8451
8498
|
"ugc_how_to",
|
|
@@ -8458,7 +8505,7 @@ var VideoPresetEnum = z44.enum([
|
|
|
8458
8505
|
"pixar_problem",
|
|
8459
8506
|
"pixar_sassy"
|
|
8460
8507
|
]);
|
|
8461
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
8508
|
+
var TaskCreativeVariantVideoPresetEnum = z45.enum([
|
|
8462
8509
|
"auto",
|
|
8463
8510
|
"ugc_dynamic",
|
|
8464
8511
|
"ugc_how_to",
|
|
@@ -8529,7 +8576,7 @@ function resolveVideoPreset(preset) {
|
|
|
8529
8576
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
8530
8577
|
}
|
|
8531
8578
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
8532
|
-
var VideoTierEnum =
|
|
8579
|
+
var VideoTierEnum = z45.enum([
|
|
8533
8580
|
"basic"
|
|
8534
8581
|
]);
|
|
8535
8582
|
function resolveVideoTier(_tier) {
|
|
@@ -8544,17 +8591,17 @@ function resolveVideoFormatForDuration(durationSeconds) {
|
|
|
8544
8591
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
8545
8592
|
}
|
|
8546
8593
|
__name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
|
|
8547
|
-
var VideoResolutionEnum =
|
|
8594
|
+
var VideoResolutionEnum = z45.enum([
|
|
8548
8595
|
"480p",
|
|
8549
8596
|
"720p"
|
|
8550
8597
|
]);
|
|
8551
|
-
var VideoStyleEnum =
|
|
8598
|
+
var VideoStyleEnum = z45.enum([
|
|
8552
8599
|
"ugc",
|
|
8553
8600
|
"cartoon_3d",
|
|
8554
8601
|
"product_only",
|
|
8555
8602
|
"ai_dynamic"
|
|
8556
8603
|
]);
|
|
8557
|
-
var NarrativeStyleEnum =
|
|
8604
|
+
var NarrativeStyleEnum = z45.enum([
|
|
8558
8605
|
"review",
|
|
8559
8606
|
"ugc_how_to",
|
|
8560
8607
|
"problem_product_cta",
|
|
@@ -8571,7 +8618,7 @@ var NarrativeStyleEnum = z44.enum([
|
|
|
8571
8618
|
"ugc_skeptic_confession",
|
|
8572
8619
|
"ugc_demo_review"
|
|
8573
8620
|
]);
|
|
8574
|
-
var PublicNarrativeStyleEnum =
|
|
8621
|
+
var PublicNarrativeStyleEnum = z45.enum([
|
|
8575
8622
|
"review",
|
|
8576
8623
|
"ugc_how_to",
|
|
8577
8624
|
"ugc_unboxing_chaos",
|
|
@@ -8583,7 +8630,7 @@ var PublicNarrativeStyleEnum = z44.enum([
|
|
|
8583
8630
|
"animated_problem_pixar",
|
|
8584
8631
|
"sassy_product_pixar"
|
|
8585
8632
|
]);
|
|
8586
|
-
var VideoModelEnum =
|
|
8633
|
+
var VideoModelEnum = z45.enum([
|
|
8587
8634
|
"veo",
|
|
8588
8635
|
"wan",
|
|
8589
8636
|
"bytedance",
|
|
@@ -8591,25 +8638,25 @@ var VideoModelEnum = z44.enum([
|
|
|
8591
8638
|
"grok",
|
|
8592
8639
|
"kling"
|
|
8593
8640
|
]);
|
|
8594
|
-
var ProductReferenceUserChoiceEnum =
|
|
8641
|
+
var ProductReferenceUserChoiceEnum = z45.enum([
|
|
8595
8642
|
"same_product",
|
|
8596
8643
|
"variants",
|
|
8597
8644
|
"different_products",
|
|
8598
8645
|
"combo_distinct"
|
|
8599
8646
|
]);
|
|
8600
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
8647
|
+
var ProductReferenceCandidateGroupingEnum = z45.enum([
|
|
8601
8648
|
"same_product_same_variant",
|
|
8602
8649
|
"same_product_different_variants",
|
|
8603
8650
|
"different_products",
|
|
8604
8651
|
"unclear"
|
|
8605
8652
|
]);
|
|
8606
|
-
var GapDurationChoiceMirror =
|
|
8607
|
-
angleIndex:
|
|
8608
|
-
recommendedSec:
|
|
8609
|
-
|
|
8610
|
-
|
|
8653
|
+
var GapDurationChoiceMirror = z45.object({
|
|
8654
|
+
angleIndex: z45.number().int().nonnegative(),
|
|
8655
|
+
recommendedSec: z45.union([
|
|
8656
|
+
z45.literal(15),
|
|
8657
|
+
z45.literal(30)
|
|
8611
8658
|
]),
|
|
8612
|
-
estimatedDeltaCredits:
|
|
8659
|
+
estimatedDeltaCredits: z45.number().int().nonnegative().optional()
|
|
8613
8660
|
});
|
|
8614
8661
|
function buildSelectedImageUrlsHash(urls) {
|
|
8615
8662
|
const input = [
|
|
@@ -8623,13 +8670,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
8623
8670
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
8624
8671
|
}
|
|
8625
8672
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
8626
|
-
var ImageCreativeStyleEnum =
|
|
8673
|
+
var ImageCreativeStyleEnum = z45.enum([
|
|
8627
8674
|
"studio",
|
|
8628
8675
|
"floating",
|
|
8629
8676
|
"ingredients",
|
|
8630
8677
|
"in_use"
|
|
8631
8678
|
]);
|
|
8632
|
-
var ImageCreativeArchetypeEnum =
|
|
8679
|
+
var ImageCreativeArchetypeEnum = z45.enum([
|
|
8633
8680
|
"direct_response_product_ad",
|
|
8634
8681
|
"hero_outcome",
|
|
8635
8682
|
"offer_value_prop",
|
|
@@ -8638,23 +8685,23 @@ var ImageCreativeArchetypeEnum = z44.enum([
|
|
|
8638
8685
|
"problem_solution",
|
|
8639
8686
|
"lifestyle_identity"
|
|
8640
8687
|
]);
|
|
8641
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
8688
|
+
var ImageCreativeVisualTreatmentEnum = z45.enum([
|
|
8642
8689
|
"performance_product_ad",
|
|
8643
8690
|
"premium_dtc_carousel"
|
|
8644
8691
|
]);
|
|
8645
|
-
var ImageCreativeAspectRatioEnum =
|
|
8692
|
+
var ImageCreativeAspectRatioEnum = z45.enum([
|
|
8646
8693
|
"1:1",
|
|
8647
8694
|
"4:5",
|
|
8648
8695
|
"9:16",
|
|
8649
8696
|
"16:9"
|
|
8650
8697
|
]);
|
|
8651
|
-
var ImageRefSchema =
|
|
8652
|
-
url:
|
|
8653
|
-
path:
|
|
8698
|
+
var ImageRefSchema = z45.object({
|
|
8699
|
+
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.'),
|
|
8700
|
+
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`.')
|
|
8654
8701
|
}).refine((v) => Boolean(v.url) !== Boolean(v.path), {
|
|
8655
8702
|
message: "each image entry must have exactly one of `url` or `path`"
|
|
8656
8703
|
});
|
|
8657
|
-
var ImagesInput =
|
|
8704
|
+
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.');
|
|
8658
8705
|
function asText(value) {
|
|
8659
8706
|
return {
|
|
8660
8707
|
content: [
|
|
@@ -8707,14 +8754,14 @@ async function submitCreative(api, opts) {
|
|
|
8707
8754
|
});
|
|
8708
8755
|
}
|
|
8709
8756
|
__name(submitCreative, "submitCreative");
|
|
8710
|
-
var ResearchTargetCountryEnum =
|
|
8757
|
+
var ResearchTargetCountryEnum = z45.enum([
|
|
8711
8758
|
"CO",
|
|
8712
8759
|
"MX",
|
|
8713
8760
|
"PE",
|
|
8714
8761
|
"EC",
|
|
8715
8762
|
"CL"
|
|
8716
8763
|
]);
|
|
8717
|
-
var ResearchCategoryEnum =
|
|
8764
|
+
var ResearchCategoryEnum = z45.enum([
|
|
8718
8765
|
"auto",
|
|
8719
8766
|
"automotive",
|
|
8720
8767
|
"kitchen",
|
|
@@ -9400,53 +9447,53 @@ function renderOutputsMarkdown(outputs) {
|
|
|
9400
9447
|
__name(renderOutputsMarkdown, "renderOutputsMarkdown");
|
|
9401
9448
|
|
|
9402
9449
|
// src/tools/tasks.ts
|
|
9403
|
-
var CreateProductTaskInput =
|
|
9450
|
+
var CreateProductTaskInput = z46.object({
|
|
9404
9451
|
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
9405
|
-
projectId:
|
|
9406
|
-
productUrl:
|
|
9452
|
+
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."),
|
|
9453
|
+
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."),
|
|
9407
9454
|
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.'),
|
|
9408
9455
|
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.'),
|
|
9409
|
-
price:
|
|
9410
|
-
compareAtPrice:
|
|
9411
|
-
offer:
|
|
9412
|
-
paymentMethods:
|
|
9413
|
-
productContext:
|
|
9414
|
-
productLabel:
|
|
9456
|
+
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.'),
|
|
9457
|
+
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".'),
|
|
9458
|
+
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.'),
|
|
9459
|
+
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.'),
|
|
9460
|
+
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."),
|
|
9461
|
+
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.'),
|
|
9415
9462
|
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.'),
|
|
9416
|
-
durationSeconds:
|
|
9417
|
-
|
|
9418
|
-
|
|
9463
|
+
durationSeconds: z46.union([
|
|
9464
|
+
z46.literal(15),
|
|
9465
|
+
z46.literal(30)
|
|
9419
9466
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
9420
|
-
pauseForAngleReview:
|
|
9467
|
+
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."),
|
|
9421
9468
|
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.'),
|
|
9422
9469
|
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).'),
|
|
9423
|
-
multiAngleVideos:
|
|
9470
|
+
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."),
|
|
9424
9471
|
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.'),
|
|
9425
|
-
outputs:
|
|
9472
|
+
outputs: z46.array(z46.enum([
|
|
9426
9473
|
"landing",
|
|
9427
9474
|
"video",
|
|
9428
9475
|
"image"
|
|
9429
9476
|
])).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.'),
|
|
9430
|
-
competitorScanEnabled:
|
|
9431
|
-
brandId:
|
|
9432
|
-
actorId:
|
|
9433
|
-
creativeDirection:
|
|
9434
|
-
headline:
|
|
9435
|
-
subheadline:
|
|
9477
|
+
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."),
|
|
9478
|
+
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."),
|
|
9479
|
+
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."),
|
|
9480
|
+
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.'),
|
|
9481
|
+
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."),
|
|
9482
|
+
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."),
|
|
9436
9483
|
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".'),
|
|
9437
9484
|
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".')
|
|
9438
9485
|
}).strict();
|
|
9439
|
-
var CreateServiceVideoInput =
|
|
9440
|
-
landingUrl:
|
|
9441
|
-
additionalContext:
|
|
9486
|
+
var CreateServiceVideoInput = z46.object({
|
|
9487
|
+
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."),
|
|
9488
|
+
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.'),
|
|
9442
9489
|
language: Lang.describe("Idioma del video: es, en o pt."),
|
|
9443
|
-
voiceId:
|
|
9444
|
-
brandId:
|
|
9445
|
-
reviewMode:
|
|
9490
|
+
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.'),
|
|
9491
|
+
brandId: z46.string().uuid().optional().describe("Marca guardada del usuario. Aplica voz, mensajes, paleta y persona predeterminada."),
|
|
9492
|
+
reviewMode: z46.enum([
|
|
9446
9493
|
"automatic",
|
|
9447
9494
|
"guided"
|
|
9448
9495
|
]).default("automatic").describe("automatic = la IA elige concepto y guion sin pausas; guided = el usuario aprueba concepto y storyboard."),
|
|
9449
|
-
videoPreset:
|
|
9496
|
+
videoPreset: z46.enum([
|
|
9450
9497
|
"auto",
|
|
9451
9498
|
"ugc_dynamic",
|
|
9452
9499
|
"ugc_how_to",
|
|
@@ -9454,35 +9501,35 @@ var CreateServiceVideoInput = z45.object({
|
|
|
9454
9501
|
"wild_card"
|
|
9455
9502
|
]).default("auto")
|
|
9456
9503
|
}).strict();
|
|
9457
|
-
var GetTaskStatusInput =
|
|
9458
|
-
taskId:
|
|
9459
|
-
waitSeconds:
|
|
9460
|
-
});
|
|
9461
|
-
var ListTasksInput =
|
|
9462
|
-
limit:
|
|
9463
|
-
offset:
|
|
9464
|
-
search:
|
|
9465
|
-
});
|
|
9466
|
-
var EditTaskDraftInput =
|
|
9467
|
-
taskId:
|
|
9468
|
-
angleIndex:
|
|
9469
|
-
angle:
|
|
9470
|
-
angle:
|
|
9471
|
-
buyerPersona:
|
|
9472
|
-
actor:
|
|
9473
|
-
actorId:
|
|
9474
|
-
gender:
|
|
9504
|
+
var GetTaskStatusInput = z46.object({
|
|
9505
|
+
taskId: z46.string().min(1),
|
|
9506
|
+
waitSeconds: z46.number().int().min(0).max(120).optional()
|
|
9507
|
+
});
|
|
9508
|
+
var ListTasksInput = z46.object({
|
|
9509
|
+
limit: z46.number().int().min(1).max(50).optional(),
|
|
9510
|
+
offset: z46.number().int().min(0).optional(),
|
|
9511
|
+
search: z46.string().optional()
|
|
9512
|
+
});
|
|
9513
|
+
var EditTaskDraftInput = z46.object({
|
|
9514
|
+
taskId: z46.string().min(1),
|
|
9515
|
+
angleIndex: z46.number().int().min(0),
|
|
9516
|
+
angle: z46.object({
|
|
9517
|
+
angle: z46.string().min(1).max(480),
|
|
9518
|
+
buyerPersona: z46.string().min(1).max(360),
|
|
9519
|
+
actor: z46.string().min(1).max(360).optional(),
|
|
9520
|
+
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."),
|
|
9521
|
+
gender: z46.enum([
|
|
9475
9522
|
"female",
|
|
9476
9523
|
"male"
|
|
9477
9524
|
]).optional(),
|
|
9478
|
-
scriptNotes:
|
|
9525
|
+
scriptNotes: z46.string().max(2e3).optional()
|
|
9479
9526
|
})
|
|
9480
9527
|
});
|
|
9481
|
-
var PendingActionPayload =
|
|
9482
|
-
|
|
9483
|
-
kind:
|
|
9528
|
+
var PendingActionPayload = z46.discriminatedUnion("kind", [
|
|
9529
|
+
z46.object({
|
|
9530
|
+
kind: z46.literal("product_reference_confirmation"),
|
|
9484
9531
|
userChoice: ProductReferenceUserChoiceEnum,
|
|
9485
|
-
confirmedProductNames:
|
|
9532
|
+
confirmedProductNames: z46.array(z46.string().min(1).max(120)).min(2).max(8).optional(),
|
|
9486
9533
|
// SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
|
|
9487
9534
|
// reachable via MCP. Valid ONLY together with userChoice='variants' (same
|
|
9488
9535
|
// product in several colors): renders one shot per color and stitches them,
|
|
@@ -9493,50 +9540,50 @@ var PendingActionPayload = z45.discriminatedUnion("kind", [
|
|
|
9493
9540
|
// safe because multi-scene IS the intended render for a color variant set,
|
|
9494
9541
|
// not a blind quality upsell. Maps to `videoTier: 'standard'` on the
|
|
9495
9542
|
// confirm call; the backend re-gates it (variants + variant_set only).
|
|
9496
|
-
useMultiSceneShowcase:
|
|
9543
|
+
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".')
|
|
9497
9544
|
}),
|
|
9498
|
-
|
|
9499
|
-
kind:
|
|
9545
|
+
z46.object({
|
|
9546
|
+
kind: z46.literal("angle_review_approval"),
|
|
9500
9547
|
// All edits are optional — empty action body just approves the
|
|
9501
9548
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
9502
9549
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
9503
9550
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
9504
|
-
customAngle:
|
|
9551
|
+
customAngle: z46.string().min(1).max(480).optional(),
|
|
9505
9552
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
9506
9553
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
9507
|
-
painPoints:
|
|
9508
|
-
benefits:
|
|
9509
|
-
features:
|
|
9510
|
-
gapDurationSeconds:
|
|
9511
|
-
|
|
9512
|
-
|
|
9554
|
+
painPoints: z46.string().max(1500).optional(),
|
|
9555
|
+
benefits: z46.string().max(1500).optional(),
|
|
9556
|
+
features: z46.array(z46.string().min(1).max(300)).max(10).optional(),
|
|
9557
|
+
gapDurationSeconds: z46.union([
|
|
9558
|
+
z46.literal(15),
|
|
9559
|
+
z46.literal(30)
|
|
9513
9560
|
]).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.")
|
|
9514
9561
|
}),
|
|
9515
|
-
|
|
9516
|
-
kind:
|
|
9517
|
-
angleId:
|
|
9518
|
-
content:
|
|
9519
|
-
creativeDirection:
|
|
9520
|
-
actor:
|
|
9562
|
+
z46.object({
|
|
9563
|
+
kind: z46.literal("service_angle_approval"),
|
|
9564
|
+
angleId: z46.string().uuid(),
|
|
9565
|
+
content: z46.string().min(1).max(480).optional(),
|
|
9566
|
+
creativeDirection: z46.string().min(1).max(1500).optional(),
|
|
9567
|
+
actor: z46.string().min(1).max(360).optional()
|
|
9521
9568
|
}),
|
|
9522
|
-
|
|
9523
|
-
kind:
|
|
9524
|
-
voiceovers:
|
|
9525
|
-
visualDirections:
|
|
9569
|
+
z46.object({
|
|
9570
|
+
kind: z46.literal("service_script_approval"),
|
|
9571
|
+
voiceovers: z46.record(z46.string(), z46.string().min(1).max(600)).optional(),
|
|
9572
|
+
visualDirections: z46.record(z46.string(), z46.string().min(1).max(1200)).optional()
|
|
9526
9573
|
})
|
|
9527
9574
|
]);
|
|
9528
|
-
var ResolvePendingActionInput =
|
|
9529
|
-
taskId:
|
|
9575
|
+
var ResolvePendingActionInput = z46.object({
|
|
9576
|
+
taskId: z46.string().min(1),
|
|
9530
9577
|
action: PendingActionPayload
|
|
9531
9578
|
}).strict();
|
|
9532
9579
|
function resolveVariantConfirmVideoTier(action) {
|
|
9533
9580
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
9534
9581
|
}
|
|
9535
9582
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
9536
|
-
var StatusForResolveSchema =
|
|
9583
|
+
var StatusForResolveSchema = z46.object({
|
|
9537
9584
|
// Metadata used to select the backend resume contract. Older API responses
|
|
9538
9585
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
9539
|
-
kind:
|
|
9586
|
+
kind: z46.enum([
|
|
9540
9587
|
"autopilot",
|
|
9541
9588
|
"video",
|
|
9542
9589
|
"image",
|
|
@@ -9544,24 +9591,24 @@ var StatusForResolveSchema = z45.object({
|
|
|
9544
9591
|
"mix",
|
|
9545
9592
|
"service"
|
|
9546
9593
|
]).optional(),
|
|
9547
|
-
selectedOutputs:
|
|
9594
|
+
selectedOutputs: z46.array(z46.enum([
|
|
9548
9595
|
"landing",
|
|
9549
9596
|
"video",
|
|
9550
9597
|
"image"
|
|
9551
9598
|
])).optional(),
|
|
9552
|
-
videoAngleCount:
|
|
9553
|
-
ugcFormat:
|
|
9599
|
+
videoAngleCount: z46.number().int().min(1).max(3).optional(),
|
|
9600
|
+
ugcFormat: z46.enum([
|
|
9554
9601
|
"single_8s",
|
|
9555
9602
|
"single_15s",
|
|
9556
9603
|
"double_30s"
|
|
9557
9604
|
]).optional(),
|
|
9558
|
-
videoStyle:
|
|
9605
|
+
videoStyle: z46.enum([
|
|
9559
9606
|
"ugc",
|
|
9560
9607
|
"cartoon_3d",
|
|
9561
9608
|
"product_only",
|
|
9562
9609
|
"ai_dynamic"
|
|
9563
9610
|
]).optional(),
|
|
9564
|
-
videoModel:
|
|
9611
|
+
videoModel: z46.enum([
|
|
9565
9612
|
"veo",
|
|
9566
9613
|
"wan",
|
|
9567
9614
|
"bytedance",
|
|
@@ -9569,26 +9616,26 @@ var StatusForResolveSchema = z45.object({
|
|
|
9569
9616
|
"grok",
|
|
9570
9617
|
"kling"
|
|
9571
9618
|
]).optional(),
|
|
9572
|
-
videoTier:
|
|
9619
|
+
videoTier: z46.enum([
|
|
9573
9620
|
"legacy",
|
|
9574
9621
|
"standard",
|
|
9575
9622
|
"pro",
|
|
9576
9623
|
"single_call"
|
|
9577
9624
|
]).optional(),
|
|
9578
|
-
videoResolution:
|
|
9625
|
+
videoResolution: z46.enum([
|
|
9579
9626
|
"480p",
|
|
9580
9627
|
"720p"
|
|
9581
9628
|
]).optional(),
|
|
9582
9629
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
9583
|
-
pendingUserAction:
|
|
9584
|
-
kind:
|
|
9585
|
-
candidateGrouping:
|
|
9586
|
-
selectedImageUrls:
|
|
9587
|
-
proposedProductNames:
|
|
9588
|
-
customAngleDraft:
|
|
9589
|
-
painPointsDraft:
|
|
9590
|
-
benefitsDraft:
|
|
9591
|
-
featuresDraft:
|
|
9630
|
+
pendingUserAction: z46.object({
|
|
9631
|
+
kind: z46.string(),
|
|
9632
|
+
candidateGrouping: z46.string().optional(),
|
|
9633
|
+
selectedImageUrls: z46.array(z46.string()).optional(),
|
|
9634
|
+
proposedProductNames: z46.array(z46.string()).optional(),
|
|
9635
|
+
customAngleDraft: z46.string().optional(),
|
|
9636
|
+
painPointsDraft: z46.string().optional(),
|
|
9637
|
+
benefitsDraft: z46.string().optional(),
|
|
9638
|
+
featuresDraft: z46.array(z46.string()).optional(),
|
|
9592
9639
|
// Recommendation consumed only when the caller explicitly sends
|
|
9593
9640
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
9594
9641
|
gapDurationChoice: GapDurationChoiceMirror.optional(),
|
|
@@ -9597,17 +9644,17 @@ var StatusForResolveSchema = z45.object({
|
|
|
9597
9644
|
// keys. `actorId` (the saved custom actor the picker stored) was silently
|
|
9598
9645
|
// dropped here, so the approval handler below could not echo it back on the
|
|
9599
9646
|
// PATCH — the selection looked accepted and reached no render.
|
|
9600
|
-
angles:
|
|
9601
|
-
id:
|
|
9602
|
-
content:
|
|
9603
|
-
creativeDirection:
|
|
9604
|
-
actor:
|
|
9605
|
-
actorId:
|
|
9647
|
+
angles: z46.array(z46.object({
|
|
9648
|
+
id: z46.string().uuid(),
|
|
9649
|
+
content: z46.string(),
|
|
9650
|
+
creativeDirection: z46.string(),
|
|
9651
|
+
actor: z46.string(),
|
|
9652
|
+
actorId: z46.string().nullable().optional()
|
|
9606
9653
|
}).passthrough()).optional(),
|
|
9607
|
-
panels:
|
|
9608
|
-
beatId:
|
|
9609
|
-
voiceover:
|
|
9610
|
-
visualDirection:
|
|
9654
|
+
panels: z46.array(z46.object({
|
|
9655
|
+
beatId: z46.string(),
|
|
9656
|
+
voiceover: z46.string(),
|
|
9657
|
+
visualDirection: z46.string()
|
|
9611
9658
|
}).passthrough()).optional()
|
|
9612
9659
|
}).optional()
|
|
9613
9660
|
}).passthrough();
|
|
@@ -10047,58 +10094,58 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
10047
10094
|
|
|
10048
10095
|
// src/tools/creatives.ts
|
|
10049
10096
|
import { randomUUID } from "crypto";
|
|
10050
|
-
import { z as
|
|
10097
|
+
import { z as z47 } from "zod";
|
|
10051
10098
|
var CreativeRefs = {
|
|
10052
10099
|
images: ImagesInput,
|
|
10053
10100
|
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.'),
|
|
10054
10101
|
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.'),
|
|
10055
|
-
price:
|
|
10056
|
-
offer:
|
|
10057
|
-
compareAtPrice:
|
|
10058
|
-
paymentMethods:
|
|
10059
|
-
productContext:
|
|
10060
|
-
productLabel:
|
|
10061
|
-
buyerPersona:
|
|
10062
|
-
isCombo:
|
|
10063
|
-
competitorScanEnabled:
|
|
10064
|
-
brandId:
|
|
10065
|
-
projectId:
|
|
10066
|
-
creativeDirection:
|
|
10067
|
-
headline:
|
|
10068
|
-
subheadline:
|
|
10102
|
+
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.'),
|
|
10103
|
+
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.'),
|
|
10104
|
+
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".'),
|
|
10105
|
+
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.'),
|
|
10106
|
+
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."),
|
|
10107
|
+
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.'),
|
|
10108
|
+
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.'),
|
|
10109
|
+
isCombo: z47.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
10110
|
+
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."),
|
|
10111
|
+
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."),
|
|
10112
|
+
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."),
|
|
10113
|
+
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.'),
|
|
10114
|
+
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."),
|
|
10115
|
+
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.")
|
|
10069
10116
|
};
|
|
10070
|
-
var VideoInput =
|
|
10117
|
+
var VideoInput = z47.object({
|
|
10071
10118
|
images: CreativeRefs.images,
|
|
10072
|
-
title:
|
|
10073
|
-
primaryAngle:
|
|
10119
|
+
title: z47.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
10120
|
+
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".'),
|
|
10074
10121
|
language: CreativeRefs.language,
|
|
10075
10122
|
country: CreativeRefs.country,
|
|
10076
|
-
aspectRatio:
|
|
10123
|
+
aspectRatio: z47.enum([
|
|
10077
10124
|
"9:16",
|
|
10078
10125
|
"16:9",
|
|
10079
10126
|
"Auto"
|
|
10080
10127
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
10081
|
-
durationSeconds:
|
|
10082
|
-
|
|
10083
|
-
|
|
10128
|
+
durationSeconds: z47.union([
|
|
10129
|
+
z47.literal(15),
|
|
10130
|
+
z47.literal(30)
|
|
10084
10131
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
10085
10132
|
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).'),
|
|
10086
10133
|
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.'),
|
|
10087
10134
|
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).'),
|
|
10088
|
-
features:
|
|
10135
|
+
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"].'),
|
|
10089
10136
|
price: CreativeRefs.price,
|
|
10090
10137
|
offer: CreativeRefs.offer,
|
|
10091
10138
|
productContext: CreativeRefs.productContext,
|
|
10092
10139
|
productLabel: CreativeRefs.productLabel,
|
|
10093
|
-
cta:
|
|
10094
|
-
scriptNotes:
|
|
10095
|
-
pauseForVideoScriptReview:
|
|
10096
|
-
pauseForAngleReview:
|
|
10140
|
+
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.'),
|
|
10141
|
+
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.'),
|
|
10142
|
+
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."),
|
|
10143
|
+
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."),
|
|
10097
10144
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
10098
10145
|
brandId: CreativeRefs.brandId,
|
|
10099
10146
|
projectId: CreativeRefs.projectId
|
|
10100
10147
|
}).strict();
|
|
10101
|
-
var FreeVideoQualityEnum =
|
|
10148
|
+
var FreeVideoQualityEnum = z47.enum([
|
|
10102
10149
|
"economical",
|
|
10103
10150
|
"high_detail"
|
|
10104
10151
|
]);
|
|
@@ -10120,38 +10167,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
10120
10167
|
15
|
|
10121
10168
|
]
|
|
10122
10169
|
};
|
|
10123
|
-
var FreeVideoInput =
|
|
10170
|
+
var FreeVideoInput = z47.object({
|
|
10124
10171
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
10125
|
-
rawPrompt:
|
|
10172
|
+
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."),
|
|
10126
10173
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
|
|
10127
|
-
durationSeconds:
|
|
10174
|
+
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."),
|
|
10128
10175
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
10129
|
-
generateAiMusic:
|
|
10130
|
-
addSubtitles:
|
|
10131
|
-
idempotencyKey:
|
|
10176
|
+
generateAiMusic: z47.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
10177
|
+
addSubtitles: z47.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
10178
|
+
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.")
|
|
10132
10179
|
}).strict();
|
|
10133
10180
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
10134
10181
|
var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
|
|
10135
10182
|
var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
|
|
10136
10183
|
var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
|
|
10137
|
-
var ImageInput =
|
|
10184
|
+
var ImageInput = z47.object({
|
|
10138
10185
|
images: CreativeRefs.images,
|
|
10139
|
-
productTitle:
|
|
10140
|
-
primaryAngle:
|
|
10186
|
+
productTitle: z47.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
10187
|
+
primaryAngle: z47.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
|
|
10141
10188
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
10142
10189
|
language: CreativeRefs.language,
|
|
10143
10190
|
country: CreativeRefs.country,
|
|
10144
|
-
nVariants:
|
|
10145
|
-
imageModel:
|
|
10191
|
+
nVariants: z47.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
|
|
10192
|
+
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.'),
|
|
10146
10193
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
10147
10194
|
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).`),
|
|
10148
10195
|
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.`),
|
|
10149
|
-
styleMix:
|
|
10196
|
+
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."),
|
|
10150
10197
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
|
|
10151
|
-
generateAdCopy:
|
|
10152
|
-
pauseForAngleReview:
|
|
10153
|
-
features:
|
|
10154
|
-
brandColors:
|
|
10198
|
+
generateAdCopy: z47.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
|
|
10199
|
+
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."),
|
|
10200
|
+
features: z47.array(z47.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
10201
|
+
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.'),
|
|
10155
10202
|
price: CreativeRefs.price,
|
|
10156
10203
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
10157
10204
|
offer: CreativeRefs.offer,
|
|
@@ -10165,16 +10212,16 @@ var ImageInput = z46.object({
|
|
|
10165
10212
|
headline: CreativeRefs.headline,
|
|
10166
10213
|
subheadline: CreativeRefs.subheadline
|
|
10167
10214
|
});
|
|
10168
|
-
var EditImageCreativeInput =
|
|
10169
|
-
taskId:
|
|
10170
|
-
variantIndex:
|
|
10171
|
-
instruction:
|
|
10215
|
+
var EditImageCreativeInput = z47.object({
|
|
10216
|
+
taskId: z47.string().uuid().describe("ID de la tarea de imagen ya finalizada."),
|
|
10217
|
+
variantIndex: z47.number().int().min(0).max(10).describe("\xCDndice de la variante a corregir (0 = primera imagen)."),
|
|
10218
|
+
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".')
|
|
10172
10219
|
});
|
|
10173
|
-
var LandingInput =
|
|
10220
|
+
var LandingInput = z47.object({
|
|
10174
10221
|
images: CreativeRefs.images,
|
|
10175
10222
|
language: CreativeRefs.language,
|
|
10176
10223
|
country: CreativeRefs.country,
|
|
10177
|
-
salesAngle:
|
|
10224
|
+
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.'),
|
|
10178
10225
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
10179
10226
|
price: CreativeRefs.price,
|
|
10180
10227
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -10299,8 +10346,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
10299
10346
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
10300
10347
|
|
|
10301
10348
|
// src/tools/creative-variants.ts
|
|
10302
|
-
import { z as
|
|
10303
|
-
var LandingSectionKeyEnum =
|
|
10349
|
+
import { z as z48 } from "zod";
|
|
10350
|
+
var LandingSectionKeyEnum = z48.enum([
|
|
10304
10351
|
"problem_hook",
|
|
10305
10352
|
"problem_cost",
|
|
10306
10353
|
"solution_mechanism",
|
|
@@ -10340,24 +10387,24 @@ var LandingSectionKeyEnum = z47.enum([
|
|
|
10340
10387
|
"lifestyle_fit",
|
|
10341
10388
|
"join_lifestyle"
|
|
10342
10389
|
]);
|
|
10343
|
-
var CreativeVariantKindEnum =
|
|
10390
|
+
var CreativeVariantKindEnum = z48.enum([
|
|
10344
10391
|
"video",
|
|
10345
10392
|
"image",
|
|
10346
10393
|
"landing"
|
|
10347
10394
|
]);
|
|
10348
|
-
var EstimateCreativeVariantInputBase =
|
|
10349
|
-
sourceTaskId:
|
|
10395
|
+
var EstimateCreativeVariantInputBase = z48.object({
|
|
10396
|
+
sourceTaskId: z48.string().uuid().describe("ID de la tarea original completada."),
|
|
10350
10397
|
kind: CreativeVariantKindEnum,
|
|
10351
10398
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
10352
10399
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
10353
|
-
nVariants:
|
|
10400
|
+
nVariants: z48.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
10354
10401
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
10355
|
-
instructions:
|
|
10402
|
+
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.")
|
|
10356
10403
|
}).strict();
|
|
10357
10404
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
10358
10405
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
10359
10406
|
ctx.addIssue({
|
|
10360
|
-
code:
|
|
10407
|
+
code: z48.ZodIssueCode.custom,
|
|
10361
10408
|
path: [
|
|
10362
10409
|
"nVariants"
|
|
10363
10410
|
],
|
|
@@ -10367,7 +10414,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10367
10414
|
if (input.kind !== "video") {
|
|
10368
10415
|
if (input.videoPreset !== void 0) {
|
|
10369
10416
|
ctx.addIssue({
|
|
10370
|
-
code:
|
|
10417
|
+
code: z48.ZodIssueCode.custom,
|
|
10371
10418
|
path: [
|
|
10372
10419
|
"videoPreset"
|
|
10373
10420
|
],
|
|
@@ -10376,7 +10423,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10376
10423
|
}
|
|
10377
10424
|
if (input.videoResolution !== void 0) {
|
|
10378
10425
|
ctx.addIssue({
|
|
10379
|
-
code:
|
|
10426
|
+
code: z48.ZodIssueCode.custom,
|
|
10380
10427
|
path: [
|
|
10381
10428
|
"videoResolution"
|
|
10382
10429
|
],
|
|
@@ -10386,7 +10433,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10386
10433
|
}
|
|
10387
10434
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
10388
10435
|
ctx.addIssue({
|
|
10389
|
-
code:
|
|
10436
|
+
code: z48.ZodIssueCode.custom,
|
|
10390
10437
|
path: [
|
|
10391
10438
|
"nVariants"
|
|
10392
10439
|
],
|
|
@@ -10396,7 +10443,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10396
10443
|
if (input.kind !== "landing") {
|
|
10397
10444
|
if (input.sectionKey !== void 0) {
|
|
10398
10445
|
ctx.addIssue({
|
|
10399
|
-
code:
|
|
10446
|
+
code: z48.ZodIssueCode.custom,
|
|
10400
10447
|
path: [
|
|
10401
10448
|
"sectionKey"
|
|
10402
10449
|
],
|
|
@@ -10405,7 +10452,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10405
10452
|
}
|
|
10406
10453
|
if (input.instructions !== void 0) {
|
|
10407
10454
|
ctx.addIssue({
|
|
10408
|
-
code:
|
|
10455
|
+
code: z48.ZodIssueCode.custom,
|
|
10409
10456
|
path: [
|
|
10410
10457
|
"instructions"
|
|
10411
10458
|
],
|
|
@@ -10414,31 +10461,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
10414
10461
|
}
|
|
10415
10462
|
}
|
|
10416
10463
|
});
|
|
10417
|
-
var CreateCreativeVariantInputBase =
|
|
10418
|
-
sourceTaskId:
|
|
10464
|
+
var CreateCreativeVariantInputBase = z48.object({
|
|
10465
|
+
sourceTaskId: z48.string().uuid().describe("ID de la tarea original completada."),
|
|
10419
10466
|
kind: CreativeVariantKindEnum,
|
|
10420
|
-
confirm:
|
|
10421
|
-
clientRequestId:
|
|
10422
|
-
angle:
|
|
10423
|
-
buyerPersona:
|
|
10424
|
-
scriptNotes:
|
|
10425
|
-
creativeDirection:
|
|
10467
|
+
confirm: z48.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
10468
|
+
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."),
|
|
10469
|
+
angle: z48.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
10470
|
+
buyerPersona: z48.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
10471
|
+
scriptNotes: z48.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
10472
|
+
creativeDirection: z48.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
10426
10473
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
10427
10474
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
10428
|
-
generateAiMusic:
|
|
10429
|
-
nVariants:
|
|
10475
|
+
generateAiMusic: z48.boolean().optional().describe("Opcional para video."),
|
|
10476
|
+
nVariants: z48.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
10430
10477
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
10431
10478
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
10432
10479
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
10433
10480
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
10434
|
-
styleMix:
|
|
10481
|
+
styleMix: z48.boolean().optional().describe("Opcional para imagen."),
|
|
10435
10482
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
10436
|
-
instructions:
|
|
10483
|
+
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.")
|
|
10437
10484
|
}).strict();
|
|
10438
10485
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
10439
10486
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
10440
10487
|
ctx.addIssue({
|
|
10441
|
-
code:
|
|
10488
|
+
code: z48.ZodIssueCode.custom,
|
|
10442
10489
|
path: [
|
|
10443
10490
|
"angle"
|
|
10444
10491
|
],
|
|
@@ -10447,7 +10494,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
10447
10494
|
}
|
|
10448
10495
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
10449
10496
|
ctx.addIssue({
|
|
10450
|
-
code:
|
|
10497
|
+
code: z48.ZodIssueCode.custom,
|
|
10451
10498
|
path: [
|
|
10452
10499
|
"instructions"
|
|
10453
10500
|
],
|
|
@@ -10493,7 +10540,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
10493
10540
|
for (const field of fieldsByKind[input.kind]) {
|
|
10494
10541
|
if (input[field] !== void 0) {
|
|
10495
10542
|
ctx.addIssue({
|
|
10496
|
-
code:
|
|
10543
|
+
code: z48.ZodIssueCode.custom,
|
|
10497
10544
|
path: [
|
|
10498
10545
|
field
|
|
10499
10546
|
],
|
|
@@ -10610,27 +10657,27 @@ function registerCreativeVariantTools(server, api) {
|
|
|
10610
10657
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
10611
10658
|
|
|
10612
10659
|
// src/tools/script-review.ts
|
|
10613
|
-
import { z as
|
|
10614
|
-
var GetVideoScriptInput =
|
|
10615
|
-
taskId:
|
|
10616
|
-
angleKey:
|
|
10660
|
+
import { z as z49 } from "zod";
|
|
10661
|
+
var GetVideoScriptInput = z49.object({
|
|
10662
|
+
taskId: z49.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
10663
|
+
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.')
|
|
10617
10664
|
}).strict();
|
|
10618
10665
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
10619
10666
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
10620
|
-
var ApproveSceneEdit =
|
|
10621
|
-
index:
|
|
10622
|
-
dialogue:
|
|
10667
|
+
var ApproveSceneEdit = z49.object({
|
|
10668
|
+
index: z49.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
10669
|
+
dialogue: z49.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
10623
10670
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
10624
10671
|
}).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.")
|
|
10625
10672
|
}).strict();
|
|
10626
|
-
var ApproveVideoScriptInput =
|
|
10627
|
-
taskId:
|
|
10628
|
-
angleKey:
|
|
10629
|
-
scenes:
|
|
10673
|
+
var ApproveVideoScriptInput = z49.object({
|
|
10674
|
+
taskId: z49.string().min(1).describe("ID de la tarea."),
|
|
10675
|
+
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.'),
|
|
10676
|
+
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.")
|
|
10630
10677
|
}).strict();
|
|
10631
|
-
var RegenerateVideoScriptInput =
|
|
10632
|
-
taskId:
|
|
10633
|
-
angleKey:
|
|
10678
|
+
var RegenerateVideoScriptInput = z49.object({
|
|
10679
|
+
taskId: z49.string().min(1).describe("ID de la tarea."),
|
|
10680
|
+
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.'),
|
|
10634
10681
|
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).')
|
|
10635
10682
|
}).strict();
|
|
10636
10683
|
function registerScriptReviewTools(server, api) {
|
|
@@ -10670,9 +10717,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
10670
10717
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
10671
10718
|
|
|
10672
10719
|
// src/tools/connections.ts
|
|
10673
|
-
import { z as
|
|
10720
|
+
import { z as z50 } from "zod";
|
|
10674
10721
|
function registerConnectionTools(server, api) {
|
|
10675
|
-
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.",
|
|
10722
|
+
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 () => {
|
|
10676
10723
|
try {
|
|
10677
10724
|
const r = await api.getJson("/v1/shopify/shops");
|
|
10678
10725
|
return asText(r);
|
|
@@ -10680,10 +10727,10 @@ function registerConnectionTools(server, api) {
|
|
|
10680
10727
|
throw translateError(e);
|
|
10681
10728
|
}
|
|
10682
10729
|
});
|
|
10683
|
-
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.',
|
|
10684
|
-
shopDomain:
|
|
10685
|
-
query:
|
|
10686
|
-
taskId:
|
|
10730
|
+
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({
|
|
10731
|
+
shopDomain: z50.string().min(3).max(120),
|
|
10732
|
+
query: z50.string().trim().max(120).optional(),
|
|
10733
|
+
taskId: z50.string().uuid().optional()
|
|
10687
10734
|
}).shape, async ({ shopDomain, query, taskId }) => {
|
|
10688
10735
|
try {
|
|
10689
10736
|
const params = new URLSearchParams({
|
|
@@ -10697,7 +10744,7 @@ function registerConnectionTools(server, api) {
|
|
|
10697
10744
|
throw translateError(e);
|
|
10698
10745
|
}
|
|
10699
10746
|
});
|
|
10700
|
-
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.",
|
|
10747
|
+
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 () => {
|
|
10701
10748
|
try {
|
|
10702
10749
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
10703
10750
|
return asText(r);
|
|
@@ -10705,7 +10752,13 @@ function registerConnectionTools(server, api) {
|
|
|
10705
10752
|
throw translateError(e);
|
|
10706
10753
|
}
|
|
10707
10754
|
});
|
|
10708
|
-
server.
|
|
10755
|
+
server.registerTool("list_meta_destinations", {
|
|
10756
|
+
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.",
|
|
10757
|
+
inputSchema: z50.object({}).shape,
|
|
10758
|
+
_meta: {
|
|
10759
|
+
"openai/widgetAccessible": true
|
|
10760
|
+
}
|
|
10761
|
+
}, async () => {
|
|
10709
10762
|
try {
|
|
10710
10763
|
const r = await api.getJson("/v1/facebook/destinations");
|
|
10711
10764
|
return asText(r);
|
|
@@ -10713,7 +10766,7 @@ function registerConnectionTools(server, api) {
|
|
|
10713
10766
|
throw translateError(e);
|
|
10714
10767
|
}
|
|
10715
10768
|
});
|
|
10716
|
-
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.",
|
|
10769
|
+
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 () => {
|
|
10717
10770
|
try {
|
|
10718
10771
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
10719
10772
|
return asText(r);
|
|
@@ -10725,9 +10778,9 @@ function registerConnectionTools(server, api) {
|
|
|
10725
10778
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
10726
10779
|
|
|
10727
10780
|
// src/tools/actors.ts
|
|
10728
|
-
import { z as
|
|
10781
|
+
import { z as z51 } from "zod";
|
|
10729
10782
|
function registerActorTools(server, api) {
|
|
10730
|
-
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.",
|
|
10783
|
+
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 () => {
|
|
10731
10784
|
try {
|
|
10732
10785
|
const rows = await api.getJson("/v1/actors");
|
|
10733
10786
|
const actors = (Array.isArray(rows) ? rows : []).filter((actor) => actor.status === "ready").map(({ id, name, description, gender, voiceId }) => ({
|
|
@@ -10748,116 +10801,116 @@ function registerActorTools(server, api) {
|
|
|
10748
10801
|
__name(registerActorTools, "registerActorTools");
|
|
10749
10802
|
|
|
10750
10803
|
// src/tools/publish.ts
|
|
10751
|
-
import { z as
|
|
10752
|
-
var ShopifyInput =
|
|
10753
|
-
taskId:
|
|
10754
|
-
shopDomain:
|
|
10804
|
+
import { z as z52 } from "zod";
|
|
10805
|
+
var ShopifyInput = z52.object({
|
|
10806
|
+
taskId: z52.string().min(1),
|
|
10807
|
+
shopDomain: z52.string().min(1),
|
|
10755
10808
|
/** Override: number of landing images to include. Default = ALL images the
|
|
10756
10809
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
10757
10810
|
* generously here; the backend validates each index against
|
|
10758
10811
|
* landing.images.length and rejects out-of-range. */
|
|
10759
|
-
numLandingImages:
|
|
10760
|
-
variantIndex:
|
|
10812
|
+
numLandingImages: z52.number().int().min(1).max(20).optional(),
|
|
10813
|
+
variantIndex: z52.number().int().min(0).optional(),
|
|
10761
10814
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
10762
10815
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
10763
10816
|
* a single-option product page. Defaults to false. */
|
|
10764
|
-
showVariantPicker:
|
|
10817
|
+
showVariantPicker: z52.boolean().optional(),
|
|
10765
10818
|
/** Default `auto` updates the product previously published for this task and
|
|
10766
10819
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
10767
10820
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
10768
|
-
publicationMode:
|
|
10821
|
+
publicationMode: z52.enum([
|
|
10769
10822
|
"auto",
|
|
10770
10823
|
"existing",
|
|
10771
10824
|
"new"
|
|
10772
10825
|
]).optional(),
|
|
10773
10826
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
10774
10827
|
* publicationMode is `existing`. */
|
|
10775
|
-
targetProductId:
|
|
10828
|
+
targetProductId: z52.string().trim().min(1).max(300).optional()
|
|
10776
10829
|
});
|
|
10777
|
-
var McpCampaignConfig =
|
|
10830
|
+
var McpCampaignConfig = z52.object({
|
|
10778
10831
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
10779
10832
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
10780
10833
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
10781
|
-
dailyBudgetUsd:
|
|
10834
|
+
dailyBudgetUsd: z52.number().positive().optional(),
|
|
10782
10835
|
/** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
|
|
10783
10836
|
* ad set). TikTok takes only the first entry. */
|
|
10784
|
-
targetCountries:
|
|
10785
|
-
campaignName:
|
|
10837
|
+
targetCountries: z52.array(z52.string().length(2)).max(1).optional(),
|
|
10838
|
+
campaignName: z52.string().trim().min(1).max(100).optional()
|
|
10786
10839
|
});
|
|
10787
10840
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
10788
|
-
var MetaInput =
|
|
10789
|
-
taskId:
|
|
10841
|
+
var MetaInput = z52.object({
|
|
10842
|
+
taskId: z52.string().min(1),
|
|
10790
10843
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
10791
|
-
portfolioId:
|
|
10844
|
+
portfolioId: z52.string().trim().min(1),
|
|
10792
10845
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
10793
|
-
pageId:
|
|
10846
|
+
pageId: z52.string().trim().min(1),
|
|
10794
10847
|
adAccountId: McpAdAccountId,
|
|
10795
|
-
pixelId:
|
|
10796
|
-
landingUrl:
|
|
10848
|
+
pixelId: z52.string().min(1).optional(),
|
|
10849
|
+
landingUrl: z52.string().url().optional(),
|
|
10797
10850
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
10798
10851
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
10799
|
-
angleIndexes:
|
|
10852
|
+
angleIndexes: z52.array(z52.number().int().nonnegative()).optional(),
|
|
10800
10853
|
campaignConfig: McpCampaignConfig.optional(),
|
|
10801
10854
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
10802
10855
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
10803
10856
|
* (Meta's primary-text limit). */
|
|
10804
|
-
primaryText:
|
|
10857
|
+
primaryText: z52.string().trim().min(1).max(500).optional(),
|
|
10805
10858
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
10806
10859
|
* (wa.me) instead of a landing page. */
|
|
10807
|
-
phoneNumber:
|
|
10860
|
+
phoneNumber: z52.string().min(8).max(32).optional()
|
|
10808
10861
|
});
|
|
10809
|
-
var GroupedTaskSource =
|
|
10810
|
-
type:
|
|
10811
|
-
taskId:
|
|
10812
|
-
angleIndex:
|
|
10813
|
-
videoVariant:
|
|
10862
|
+
var GroupedTaskSource = z52.object({
|
|
10863
|
+
type: z52.literal("task"),
|
|
10864
|
+
taskId: z52.string().min(1),
|
|
10865
|
+
angleIndex: z52.number().int().min(0).optional(),
|
|
10866
|
+
videoVariant: z52.enum([
|
|
10814
10867
|
"with_subtitles",
|
|
10815
10868
|
"without_subtitles"
|
|
10816
10869
|
]).optional(),
|
|
10817
|
-
imageVariantIndex:
|
|
10818
|
-
});
|
|
10819
|
-
var GroupedMediaSource =
|
|
10820
|
-
type:
|
|
10821
|
-
url:
|
|
10822
|
-
path:
|
|
10823
|
-
thumbnailUrl:
|
|
10824
|
-
thumbnailPath:
|
|
10870
|
+
imageVariantIndex: z52.number().int().min(0).optional()
|
|
10871
|
+
});
|
|
10872
|
+
var GroupedMediaSource = z52.object({
|
|
10873
|
+
type: z52.literal("media"),
|
|
10874
|
+
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."),
|
|
10875
|
+
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".'),
|
|
10876
|
+
thumbnailUrl: z52.string().url().optional(),
|
|
10877
|
+
thumbnailPath: z52.string().min(1).optional()
|
|
10825
10878
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
10826
10879
|
message: "media source needs exactly one of `url` or `path`"
|
|
10827
10880
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
10828
10881
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
10829
10882
|
});
|
|
10830
|
-
var GroupedStagedMediaSource =
|
|
10831
|
-
type:
|
|
10883
|
+
var GroupedStagedMediaSource = z52.object({
|
|
10884
|
+
type: z52.literal("staged"),
|
|
10832
10885
|
/** Returned by check_meta_media_upload after the user selects a local file. */
|
|
10833
|
-
stagingAssetId:
|
|
10834
|
-
thumbnailAssetId:
|
|
10886
|
+
stagingAssetId: z52.string().uuid(),
|
|
10887
|
+
thumbnailAssetId: z52.string().uuid().optional()
|
|
10835
10888
|
});
|
|
10836
|
-
var GroupedCreative =
|
|
10837
|
-
type:
|
|
10889
|
+
var GroupedCreative = z52.object({
|
|
10890
|
+
type: z52.enum([
|
|
10838
10891
|
"image",
|
|
10839
10892
|
"video"
|
|
10840
10893
|
]),
|
|
10841
|
-
source:
|
|
10894
|
+
source: z52.union([
|
|
10842
10895
|
GroupedTaskSource,
|
|
10843
10896
|
GroupedMediaSource,
|
|
10844
10897
|
GroupedStagedMediaSource
|
|
10845
10898
|
]),
|
|
10846
|
-
title:
|
|
10847
|
-
description:
|
|
10899
|
+
title: z52.string().max(120).optional(),
|
|
10900
|
+
description: z52.string().max(500).optional(),
|
|
10848
10901
|
cta: MetaCtaType.optional(),
|
|
10849
|
-
creativeId:
|
|
10902
|
+
creativeId: z52.string().min(1).optional()
|
|
10850
10903
|
});
|
|
10851
|
-
var GroupedCampaignConfig =
|
|
10904
|
+
var GroupedCampaignConfig = z52.object({
|
|
10852
10905
|
campaignType: MetaCampaignType.default("sales"),
|
|
10853
10906
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
10854
10907
|
budgetMode: MetaBudgetMode.default("campaign"),
|
|
10855
|
-
campaignDailyBudget:
|
|
10856
|
-
adSets:
|
|
10857
|
-
tempId:
|
|
10858
|
-
name:
|
|
10859
|
-
dailyBudget:
|
|
10860
|
-
creativeIds:
|
|
10908
|
+
campaignDailyBudget: z52.number().int().positive().optional(),
|
|
10909
|
+
adSets: z52.array(z52.object({
|
|
10910
|
+
tempId: z52.string().min(1).max(80),
|
|
10911
|
+
name: z52.string().min(1).max(100),
|
|
10912
|
+
dailyBudget: z52.number().int().positive().optional(),
|
|
10913
|
+
creativeIds: z52.array(z52.string().min(1)).min(1)
|
|
10861
10914
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
10862
10915
|
/**
|
|
10863
10916
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -10865,22 +10918,22 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10865
10918
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
10866
10919
|
* the API since #849 — unreachable from this tool.
|
|
10867
10920
|
*/
|
|
10868
|
-
destination:
|
|
10869
|
-
|
|
10870
|
-
type:
|
|
10871
|
-
landingUrl:
|
|
10921
|
+
destination: z52.discriminatedUnion("type", [
|
|
10922
|
+
z52.object({
|
|
10923
|
+
type: z52.literal("landing"),
|
|
10924
|
+
landingUrl: z52.string().url()
|
|
10872
10925
|
}),
|
|
10873
|
-
|
|
10874
|
-
type:
|
|
10875
|
-
phoneNumber:
|
|
10926
|
+
z52.object({
|
|
10927
|
+
type: z52.literal("whatsapp"),
|
|
10928
|
+
phoneNumber: z52.string().min(8).max(32)
|
|
10876
10929
|
})
|
|
10877
10930
|
]),
|
|
10878
|
-
saveAsDefault:
|
|
10931
|
+
saveAsDefault: z52.boolean().default(false),
|
|
10879
10932
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
10880
10933
|
}).superRefine((value, ctx) => {
|
|
10881
10934
|
if (value.budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
10882
10935
|
ctx.addIssue({
|
|
10883
|
-
code:
|
|
10936
|
+
code: z52.ZodIssueCode.custom,
|
|
10884
10937
|
path: [
|
|
10885
10938
|
"campaignDailyBudget"
|
|
10886
10939
|
],
|
|
@@ -10891,7 +10944,7 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10891
10944
|
value.adSets.forEach((adSet, index) => {
|
|
10892
10945
|
if (adSet.dailyBudget === void 0) {
|
|
10893
10946
|
ctx.addIssue({
|
|
10894
|
-
code:
|
|
10947
|
+
code: z52.ZodIssueCode.custom,
|
|
10895
10948
|
path: [
|
|
10896
10949
|
"adSets",
|
|
10897
10950
|
index,
|
|
@@ -10903,26 +10956,26 @@ var GroupedCampaignConfig = z51.object({
|
|
|
10903
10956
|
});
|
|
10904
10957
|
}
|
|
10905
10958
|
});
|
|
10906
|
-
var PublishCreativesToMetaInputBase =
|
|
10907
|
-
creatives:
|
|
10959
|
+
var PublishCreativesToMetaInputBase = z52.object({
|
|
10960
|
+
creatives: z52.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
10908
10961
|
/** Exact Meta Business portfolio selected from `list_meta_destinations`. */
|
|
10909
|
-
portfolioId:
|
|
10962
|
+
portfolioId: z52.string().trim().min(1),
|
|
10910
10963
|
/** Exact Facebook Page selected from `list_meta_destinations`. */
|
|
10911
|
-
pageId:
|
|
10964
|
+
pageId: z52.string().trim().min(1),
|
|
10912
10965
|
adAccountId: McpAdAccountId,
|
|
10913
|
-
pixelId:
|
|
10966
|
+
pixelId: z52.string().min(1).optional(),
|
|
10914
10967
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
10915
10968
|
* superRefine below. Mirrors the API's `UploadToMetaRequest`. */
|
|
10916
|
-
landingUrl:
|
|
10917
|
-
targetCountry:
|
|
10918
|
-
campaignName:
|
|
10969
|
+
landingUrl: z52.string().url().optional(),
|
|
10970
|
+
targetCountry: z52.string().length(2),
|
|
10971
|
+
campaignName: z52.string().trim().min(1).max(100),
|
|
10919
10972
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
10920
10973
|
});
|
|
10921
10974
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
10922
10975
|
const destination = value.campaignConfig?.destination;
|
|
10923
10976
|
if (destination?.type !== "whatsapp" && !value.landingUrl) {
|
|
10924
10977
|
ctx.addIssue({
|
|
10925
|
-
code:
|
|
10978
|
+
code: z52.ZodIssueCode.custom,
|
|
10926
10979
|
path: [
|
|
10927
10980
|
"landingUrl"
|
|
10928
10981
|
],
|
|
@@ -10931,7 +10984,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
10931
10984
|
}
|
|
10932
10985
|
if (destination?.type === "landing" && destination.landingUrl !== value.landingUrl) {
|
|
10933
10986
|
ctx.addIssue({
|
|
10934
|
-
code:
|
|
10987
|
+
code: z52.ZodIssueCode.custom,
|
|
10935
10988
|
path: [
|
|
10936
10989
|
"campaignConfig",
|
|
10937
10990
|
"destination",
|
|
@@ -10941,16 +10994,16 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
10941
10994
|
});
|
|
10942
10995
|
}
|
|
10943
10996
|
});
|
|
10944
|
-
var PresignUploadResponseSchema =
|
|
10945
|
-
uploadUrl:
|
|
10997
|
+
var PresignUploadResponseSchema = z52.object({
|
|
10998
|
+
uploadUrl: z52.string().url().refine((value) => {
|
|
10946
10999
|
const url = new URL(value);
|
|
10947
11000
|
return !url.username && !url.password && url.protocol === "https:";
|
|
10948
11001
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
10949
|
-
publicUrl:
|
|
11002
|
+
publicUrl: z52.string().url().refine((value) => {
|
|
10950
11003
|
const url = new URL(value);
|
|
10951
11004
|
return !url.username && !url.password;
|
|
10952
11005
|
}, "public media URL must not contain embedded credentials"),
|
|
10953
|
-
stagingAssetId:
|
|
11006
|
+
stagingAssetId: z52.string().uuid()
|
|
10954
11007
|
});
|
|
10955
11008
|
async function uploadResolvedMedia(api, media, assetRole) {
|
|
10956
11009
|
if (!media.buffer) throw new ResolveMediaError("INVALID_INPUT", "resolved media has no bytes");
|
|
@@ -10975,16 +11028,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, assetRole, transpor
|
|
|
10975
11028
|
return uploadResolvedMedia(api, media, assetRole);
|
|
10976
11029
|
}
|
|
10977
11030
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
10978
|
-
var TikTokInput =
|
|
10979
|
-
taskId:
|
|
10980
|
-
advertiserId:
|
|
10981
|
-
pixelId:
|
|
10982
|
-
landingUrl:
|
|
10983
|
-
angleIndexes:
|
|
11031
|
+
var TikTokInput = z52.object({
|
|
11032
|
+
taskId: z52.string().min(1),
|
|
11033
|
+
advertiserId: z52.string().min(1),
|
|
11034
|
+
pixelId: z52.string().min(1).optional(),
|
|
11035
|
+
landingUrl: z52.string().url().optional(),
|
|
11036
|
+
angleIndexes: z52.array(z52.number().int().nonnegative()).optional(),
|
|
10984
11037
|
campaignConfig: McpCampaignConfig.optional(),
|
|
10985
11038
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
10986
11039
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
10987
|
-
primaryText:
|
|
11040
|
+
primaryText: z52.string().trim().min(1).max(500).optional()
|
|
10988
11041
|
});
|
|
10989
11042
|
function registerPublishTools(server, api, opts = {}) {
|
|
10990
11043
|
const transport = opts.transport ?? "http";
|
|
@@ -11172,6 +11225,17 @@ function renderShopifyPublishMarkdown(r) {
|
|
|
11172
11225
|
if (r.productUrl) lines.push(`
|
|
11173
11226
|
### Producto
|
|
11174
11227
|
[Ver producto](${r.productUrl})`);
|
|
11228
|
+
if (r.needsThemeSetup) {
|
|
11229
|
+
lines.push(r.themeEditorDeepLink ? `
|
|
11230
|
+
\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.");
|
|
11231
|
+
}
|
|
11232
|
+
if (r.tracking?.status === "migrated") {
|
|
11233
|
+
lines.push("\nTracking: \u2705 configuraci\xF3n anterior migrada autom\xE1ticamente. No necesitas editar el tema.");
|
|
11234
|
+
} else if (r.tracking?.status === "synced") {
|
|
11235
|
+
lines.push("\nTracking: \u2705 c\xF3digo manual sincronizado desde `theme.liquid` al layout de ProductMaker.");
|
|
11236
|
+
} else if (r.tracking?.status === "not_detected") {
|
|
11237
|
+
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.");
|
|
11238
|
+
}
|
|
11175
11239
|
if (!r.pageUrl && !r.productUrl && r.status !== "success") {
|
|
11176
11240
|
lines.push("\n_La publicaci\xF3n a\xFAn est\xE1 proces\xE1ndose. Usa `get_task_status` para verificar progreso._");
|
|
11177
11241
|
}
|
|
@@ -11216,71 +11280,81 @@ function toTikTokCampaignConfig(cfg) {
|
|
|
11216
11280
|
__name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
11217
11281
|
|
|
11218
11282
|
// src/tools/meta-upload.ts
|
|
11219
|
-
import { z as
|
|
11220
|
-
var MetaUploadSessionInputBase =
|
|
11221
|
-
mediaKind:
|
|
11283
|
+
import { z as z53 } from "zod";
|
|
11284
|
+
var MetaUploadSessionInputBase = z53.object({
|
|
11285
|
+
mediaKind: z53.enum([
|
|
11222
11286
|
"image",
|
|
11223
11287
|
"video",
|
|
11224
11288
|
"mixed"
|
|
11225
11289
|
]).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."),
|
|
11226
|
-
assetRole:
|
|
11290
|
+
assetRole: z53.enum([
|
|
11227
11291
|
"media",
|
|
11228
11292
|
"thumbnail"
|
|
11229
|
-
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail.")
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11293
|
+
]).default("media").describe("Use media for the creative itself; thumbnail only for an image thumbnail."),
|
|
11294
|
+
maxFiles: z53.number().int().min(1).max(10).optional().describe("Optional batch limit. Use 1 for a single creative; mixed media defaults to 10.")
|
|
11295
|
+
});
|
|
11296
|
+
var OpenAiFileReference = z53.object({
|
|
11297
|
+
download_url: z53.string().url(),
|
|
11298
|
+
file_id: z53.string().min(1),
|
|
11299
|
+
mime_type: z53.string().min(1).optional(),
|
|
11300
|
+
file_name: z53.string().min(1).optional()
|
|
11236
11301
|
}).strict();
|
|
11237
11302
|
var MetaUploadSessionToolInputShape = {
|
|
11238
11303
|
...MetaUploadSessionInputBase.shape,
|
|
11239
|
-
files:
|
|
11304
|
+
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.")
|
|
11240
11305
|
};
|
|
11241
|
-
var MetaUploadSessionToolInput =
|
|
11306
|
+
var MetaUploadSessionToolInput = z53.object(MetaUploadSessionToolInputShape).superRefine((value, ctx) => {
|
|
11242
11307
|
if (value.assetRole === "thumbnail" && value.mediaKind !== "image") {
|
|
11243
11308
|
ctx.addIssue({
|
|
11244
|
-
code:
|
|
11309
|
+
code: z53.ZodIssueCode.custom,
|
|
11245
11310
|
path: [
|
|
11246
11311
|
"mediaKind"
|
|
11247
11312
|
],
|
|
11248
11313
|
message: "Meta thumbnails must be images"
|
|
11249
11314
|
});
|
|
11250
11315
|
}
|
|
11316
|
+
if (value.mediaKind !== "mixed" && value.maxFiles !== void 0 && value.maxFiles !== 1) {
|
|
11317
|
+
ctx.addIssue({
|
|
11318
|
+
code: z53.ZodIssueCode.custom,
|
|
11319
|
+
path: [
|
|
11320
|
+
"maxFiles"
|
|
11321
|
+
],
|
|
11322
|
+
message: "Image and video sessions accept exactly one file"
|
|
11323
|
+
});
|
|
11324
|
+
}
|
|
11251
11325
|
});
|
|
11252
|
-
var MetaUploadSessionResponse2 =
|
|
11253
|
-
sessionId:
|
|
11254
|
-
uploadPageUrl:
|
|
11255
|
-
mediaKind:
|
|
11326
|
+
var MetaUploadSessionResponse2 = z53.object({
|
|
11327
|
+
sessionId: z53.string().uuid(),
|
|
11328
|
+
uploadPageUrl: z53.string().url(),
|
|
11329
|
+
mediaKind: z53.enum([
|
|
11256
11330
|
"image",
|
|
11257
11331
|
"video",
|
|
11258
11332
|
"mixed"
|
|
11259
11333
|
]),
|
|
11260
|
-
assetRole:
|
|
11334
|
+
assetRole: z53.enum([
|
|
11261
11335
|
"media",
|
|
11262
11336
|
"thumbnail"
|
|
11263
11337
|
]),
|
|
11264
|
-
maxFiles:
|
|
11265
|
-
expiresAt:
|
|
11338
|
+
maxFiles: z53.number().int().positive(),
|
|
11339
|
+
expiresAt: z53.string().datetime()
|
|
11266
11340
|
});
|
|
11267
|
-
var MetaUploadStatusInput =
|
|
11268
|
-
sessionId:
|
|
11341
|
+
var MetaUploadStatusInput = z53.object({
|
|
11342
|
+
sessionId: z53.string().uuid().describe("The sessionId returned by request_meta_media_upload.")
|
|
11269
11343
|
});
|
|
11270
|
-
var MetaUploadStatusResponse =
|
|
11271
|
-
sessionId:
|
|
11272
|
-
status:
|
|
11344
|
+
var MetaUploadStatusResponse = z53.object({
|
|
11345
|
+
sessionId: z53.string().uuid(),
|
|
11346
|
+
status: z53.enum([
|
|
11273
11347
|
"pending",
|
|
11274
11348
|
"uploaded"
|
|
11275
11349
|
]),
|
|
11276
|
-
assets:
|
|
11277
|
-
stagingAssetId:
|
|
11278
|
-
mediaKind:
|
|
11350
|
+
assets: z53.array(z53.object({
|
|
11351
|
+
stagingAssetId: z53.string().uuid(),
|
|
11352
|
+
mediaKind: z53.enum([
|
|
11279
11353
|
"image",
|
|
11280
11354
|
"video"
|
|
11281
11355
|
])
|
|
11282
11356
|
})).max(10).default([]),
|
|
11283
|
-
stagingAssetId:
|
|
11357
|
+
stagingAssetId: z53.string().uuid().optional()
|
|
11284
11358
|
});
|
|
11285
11359
|
function uploadSessionText(result) {
|
|
11286
11360
|
const mediaLabel = result.mediaKind === "mixed" ? "archivos" : result.mediaKind === "video" ? "video" : "imagen";
|
|
@@ -11289,8 +11363,8 @@ function uploadSessionText(result) {
|
|
|
11289
11363
|
{
|
|
11290
11364
|
type: "text",
|
|
11291
11365
|
text: [
|
|
11292
|
-
`###
|
|
11293
|
-
`[Abrir carga segura](${result.uploadPageUrl})`,
|
|
11366
|
+
`### Prepara tu ${mediaLabel} en ProductMaker`,
|
|
11367
|
+
`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})`,
|
|
11294
11368
|
`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.`,
|
|
11295
11369
|
`sessionId: \`${result.sessionId}\``,
|
|
11296
11370
|
`Este enlace expira: ${result.expiresAt}`
|
|
@@ -11303,7 +11377,7 @@ __name(uploadSessionText, "uploadSessionText");
|
|
|
11303
11377
|
function registerMetaUploadTools(server, api) {
|
|
11304
11378
|
server.registerTool("request_meta_media_upload", {
|
|
11305
11379
|
title: "Solicitar carga segura de Meta",
|
|
11306
|
-
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.
|
|
11380
|
+
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.",
|
|
11307
11381
|
inputSchema: MetaUploadSessionToolInputShape,
|
|
11308
11382
|
outputSchema: MetaUploadSessionResponse2,
|
|
11309
11383
|
_meta: {
|
|
@@ -11335,7 +11409,13 @@ function registerMetaUploadTools(server, api) {
|
|
|
11335
11409
|
throw translateError(error);
|
|
11336
11410
|
}
|
|
11337
11411
|
});
|
|
11338
|
-
server.
|
|
11412
|
+
server.registerTool("check_meta_media_upload", {
|
|
11413
|
+
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.',
|
|
11414
|
+
inputSchema: MetaUploadStatusInput.shape,
|
|
11415
|
+
_meta: {
|
|
11416
|
+
"openai/widgetAccessible": true
|
|
11417
|
+
}
|
|
11418
|
+
}, async (rawInput) => {
|
|
11339
11419
|
try {
|
|
11340
11420
|
const input = MetaUploadStatusInput.parse(rawInput);
|
|
11341
11421
|
const result = MetaUploadStatusResponse.parse(await api.getJson(`/v1/ads/meta-upload-sessions/${encodeURIComponent(input.sessionId)}`));
|
|
@@ -11348,13 +11428,13 @@ function registerMetaUploadTools(server, api) {
|
|
|
11348
11428
|
__name(registerMetaUploadTools, "registerMetaUploadTools");
|
|
11349
11429
|
|
|
11350
11430
|
// src/tools/campaigns.ts
|
|
11351
|
-
import { z as
|
|
11352
|
-
var MetaStatusInput =
|
|
11353
|
-
campaignId:
|
|
11431
|
+
import { z as z54 } from "zod";
|
|
11432
|
+
var MetaStatusInput = z54.object({
|
|
11433
|
+
campaignId: z54.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
11354
11434
|
});
|
|
11355
|
-
var TikTokStatusInput =
|
|
11356
|
-
campaignId:
|
|
11357
|
-
advertiserId:
|
|
11435
|
+
var TikTokStatusInput = z54.object({
|
|
11436
|
+
campaignId: z54.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
11437
|
+
advertiserId: z54.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
11358
11438
|
});
|
|
11359
11439
|
function registerCampaignTools(server, api) {
|
|
11360
11440
|
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) => {
|
|
@@ -11451,10 +11531,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
11451
11531
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
11452
11532
|
|
|
11453
11533
|
// ../../packages/product-economics/src/product-costing.ts
|
|
11454
|
-
import { z as
|
|
11534
|
+
import { z as z56 } from "zod";
|
|
11455
11535
|
|
|
11456
11536
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
11457
|
-
import { z as
|
|
11537
|
+
import { z as z55 } from "zod";
|
|
11458
11538
|
|
|
11459
11539
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
11460
11540
|
var product_costing_shipping_references_default = {
|
|
@@ -11518,21 +11598,21 @@ var product_costing_shipping_references_default = {
|
|
|
11518
11598
|
};
|
|
11519
11599
|
|
|
11520
11600
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
11521
|
-
var ShippingReferenceSchema =
|
|
11522
|
-
reference:
|
|
11523
|
-
min:
|
|
11524
|
-
max:
|
|
11525
|
-
updatedAt:
|
|
11526
|
-
confidence:
|
|
11601
|
+
var ShippingReferenceSchema = z55.object({
|
|
11602
|
+
reference: z55.number().positive(),
|
|
11603
|
+
min: z55.number().nonnegative(),
|
|
11604
|
+
max: z55.number().positive(),
|
|
11605
|
+
updatedAt: z55.string().date(),
|
|
11606
|
+
confidence: z55.enum([
|
|
11527
11607
|
"high",
|
|
11528
11608
|
"medium",
|
|
11529
11609
|
"medium-low"
|
|
11530
11610
|
]),
|
|
11531
|
-
sources:
|
|
11611
|
+
sources: z55.array(z55.string().url().startsWith("https://")).min(1).max(3)
|
|
11532
11612
|
}).superRefine(({ reference, min, max }, context) => {
|
|
11533
11613
|
if (min > reference || reference > max) {
|
|
11534
11614
|
context.addIssue({
|
|
11535
|
-
code:
|
|
11615
|
+
code: z55.ZodIssueCode.custom,
|
|
11536
11616
|
message: "shipping_reference_outside_range",
|
|
11537
11617
|
path: [
|
|
11538
11618
|
"reference"
|
|
@@ -11540,7 +11620,7 @@ var ShippingReferenceSchema = z54.object({
|
|
|
11540
11620
|
});
|
|
11541
11621
|
}
|
|
11542
11622
|
});
|
|
11543
|
-
var SHIPPING_REFERENCES =
|
|
11623
|
+
var SHIPPING_REFERENCES = z55.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
11544
11624
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
11545
11625
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
11546
11626
|
"MX",
|
|
@@ -11722,18 +11802,18 @@ function getProductCostingCountryName(country) {
|
|
|
11722
11802
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
11723
11803
|
|
|
11724
11804
|
// ../../packages/product-economics/src/product-costing.ts
|
|
11725
|
-
var ProductCostingInputSchema =
|
|
11726
|
-
country:
|
|
11727
|
-
supplierCost:
|
|
11728
|
-
shippingCost:
|
|
11729
|
-
returnRate:
|
|
11730
|
-
cancellationRate:
|
|
11731
|
-
adsManagerCpa:
|
|
11732
|
-
desiredMargin:
|
|
11805
|
+
var ProductCostingInputSchema = z56.object({
|
|
11806
|
+
country: z56.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
11807
|
+
supplierCost: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
11808
|
+
shippingCost: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
11809
|
+
returnRate: z56.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
11810
|
+
cancellationRate: z56.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
11811
|
+
adsManagerCpa: z56.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
11812
|
+
desiredMargin: z56.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
11733
11813
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
11734
11814
|
if (returnRate + cancellationRate >= 1) {
|
|
11735
11815
|
context.addIssue({
|
|
11736
|
-
code:
|
|
11816
|
+
code: z56.ZodIssueCode.custom,
|
|
11737
11817
|
message: "delivery_rate_positive",
|
|
11738
11818
|
path: [
|
|
11739
11819
|
"cancellationRate"
|
|
@@ -11800,14 +11880,14 @@ function calculateProductCosting(rawInput) {
|
|
|
11800
11880
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
11801
11881
|
|
|
11802
11882
|
// src/tools/product-costing.ts
|
|
11803
|
-
import { z as
|
|
11804
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
11805
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
11806
|
-
var ProductCostingToolInput =
|
|
11807
|
-
country:
|
|
11883
|
+
import { z as z57 } from "zod";
|
|
11884
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z57.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
11885
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z57.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
11886
|
+
var ProductCostingToolInput = z57.object({
|
|
11887
|
+
country: z57.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
11808
11888
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
11809
11889
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
11810
|
-
supplierCost:
|
|
11890
|
+
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."),
|
|
11811
11891
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
11812
11892
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
11813
11893
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -11939,7 +12019,7 @@ function formatPercent(value) {
|
|
|
11939
12019
|
__name(formatPercent, "formatPercent");
|
|
11940
12020
|
|
|
11941
12021
|
// src/tools/product-research.ts
|
|
11942
|
-
import { z as
|
|
12022
|
+
import { z as z58 } from "zod";
|
|
11943
12023
|
|
|
11944
12024
|
// src/tools/product-research-idempotency.ts
|
|
11945
12025
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -12055,17 +12135,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
12055
12135
|
]);
|
|
12056
12136
|
var POLL_INTERVAL_MS = 5e3;
|
|
12057
12137
|
var MAX_WAIT_SECONDS = 120;
|
|
12058
|
-
var FindInput =
|
|
12138
|
+
var FindInput = z58.object({
|
|
12059
12139
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
12060
12140
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
12061
|
-
confirmed:
|
|
12062
|
-
waitSeconds:
|
|
12141
|
+
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.`),
|
|
12142
|
+
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.")
|
|
12063
12143
|
});
|
|
12064
|
-
var GetInput =
|
|
12065
|
-
runId:
|
|
12144
|
+
var GetInput = z58.object({
|
|
12145
|
+
runId: z58.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
12066
12146
|
});
|
|
12067
|
-
var ListInput =
|
|
12068
|
-
limit:
|
|
12147
|
+
var ListInput = z58.object({
|
|
12148
|
+
limit: z58.number().int().min(1).max(20).default(10)
|
|
12069
12149
|
});
|
|
12070
12150
|
function textResult(text) {
|
|
12071
12151
|
return {
|
|
@@ -12157,14 +12237,14 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
12157
12237
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
12158
12238
|
|
|
12159
12239
|
// src/tools/dropshipping-projects.ts
|
|
12160
|
-
import { z as
|
|
12161
|
-
var ProjectId =
|
|
12162
|
-
var DropshippingProjectStatus =
|
|
12240
|
+
import { z as z59 } from "zod";
|
|
12241
|
+
var ProjectId = z59.string().uuid();
|
|
12242
|
+
var DropshippingProjectStatus = z59.enum([
|
|
12163
12243
|
"active",
|
|
12164
12244
|
"completed",
|
|
12165
12245
|
"archived"
|
|
12166
12246
|
]);
|
|
12167
|
-
var DropshippingProjectPhase =
|
|
12247
|
+
var DropshippingProjectPhase = z59.enum([
|
|
12168
12248
|
"research",
|
|
12169
12249
|
"costing",
|
|
12170
12250
|
"media",
|
|
@@ -12173,21 +12253,21 @@ var DropshippingProjectPhase = z58.enum([
|
|
|
12173
12253
|
"advertising",
|
|
12174
12254
|
"complete"
|
|
12175
12255
|
]);
|
|
12176
|
-
var DropshippingRewardMilestone =
|
|
12256
|
+
var DropshippingRewardMilestone = z59.enum([
|
|
12177
12257
|
"product_selected",
|
|
12178
12258
|
"costing_saved",
|
|
12179
12259
|
"product_media_ready",
|
|
12180
12260
|
"creatives_completed",
|
|
12181
12261
|
"campaign_created"
|
|
12182
12262
|
]);
|
|
12183
|
-
var TargetCountry =
|
|
12263
|
+
var TargetCountry = z59.enum([
|
|
12184
12264
|
"CO",
|
|
12185
12265
|
"MX",
|
|
12186
12266
|
"PE",
|
|
12187
12267
|
"EC",
|
|
12188
12268
|
"CL"
|
|
12189
12269
|
]);
|
|
12190
|
-
var ResearchCategory =
|
|
12270
|
+
var ResearchCategory = z59.enum([
|
|
12191
12271
|
"auto",
|
|
12192
12272
|
"automotive",
|
|
12193
12273
|
"kitchen",
|
|
@@ -12202,7 +12282,7 @@ var ResearchCategory = z58.enum([
|
|
|
12202
12282
|
"garden",
|
|
12203
12283
|
"cleaning"
|
|
12204
12284
|
]);
|
|
12205
|
-
var HttpUrl3 =
|
|
12285
|
+
var HttpUrl3 = z59.string().url().max(2e3).refine((value) => {
|
|
12206
12286
|
try {
|
|
12207
12287
|
return [
|
|
12208
12288
|
"http:",
|
|
@@ -12212,46 +12292,46 @@ var HttpUrl3 = z58.string().url().max(2e3).refine((value) => {
|
|
|
12212
12292
|
return false;
|
|
12213
12293
|
}
|
|
12214
12294
|
}, "URL must use HTTP(S)");
|
|
12215
|
-
var ResearchCandidateOrigin =
|
|
12216
|
-
type:
|
|
12295
|
+
var ResearchCandidateOrigin = z59.object({
|
|
12296
|
+
type: z59.literal("research_candidate"),
|
|
12217
12297
|
runId: ProjectId,
|
|
12218
|
-
candidateSourceId:
|
|
12298
|
+
candidateSourceId: z59.string().min(1).max(160)
|
|
12219
12299
|
});
|
|
12220
|
-
var TaskOrigin =
|
|
12221
|
-
type:
|
|
12300
|
+
var TaskOrigin = z59.object({
|
|
12301
|
+
type: z59.literal("task"),
|
|
12222
12302
|
taskId: ProjectId
|
|
12223
12303
|
});
|
|
12224
|
-
var ManualOrigin =
|
|
12225
|
-
type:
|
|
12304
|
+
var ManualOrigin = z59.object({
|
|
12305
|
+
type: z59.literal("manual"),
|
|
12226
12306
|
clientRequestId: ProjectId,
|
|
12227
|
-
country:
|
|
12307
|
+
country: z59.string().min(2).max(3).optional()
|
|
12228
12308
|
});
|
|
12229
|
-
var StartProjectInput =
|
|
12230
|
-
origin:
|
|
12309
|
+
var StartProjectInput = z59.object({
|
|
12310
|
+
origin: z59.discriminatedUnion("type", [
|
|
12231
12311
|
ResearchCandidateOrigin,
|
|
12232
12312
|
TaskOrigin,
|
|
12233
12313
|
ManualOrigin
|
|
12234
12314
|
]),
|
|
12235
|
-
productName:
|
|
12315
|
+
productName: z59.string().trim().min(1).max(240).optional(),
|
|
12236
12316
|
productUrl: HttpUrl3.optional(),
|
|
12237
|
-
country:
|
|
12238
|
-
languageCode:
|
|
12317
|
+
country: z59.string().min(2).max(3).optional(),
|
|
12318
|
+
languageCode: z59.string().min(2).max(16).optional()
|
|
12239
12319
|
}).strict();
|
|
12240
|
-
var CostProjectInput =
|
|
12320
|
+
var CostProjectInput = z59.object({
|
|
12241
12321
|
projectId: ProjectId,
|
|
12242
|
-
version:
|
|
12243
|
-
country:
|
|
12244
|
-
supplierCost:
|
|
12245
|
-
shippingCost:
|
|
12246
|
-
returnRate:
|
|
12247
|
-
cancellationRate:
|
|
12248
|
-
adsManagerCpa:
|
|
12249
|
-
desiredMargin:
|
|
12250
|
-
});
|
|
12251
|
-
var GuideInput =
|
|
12322
|
+
version: z59.number().int().positive(),
|
|
12323
|
+
country: z59.string().trim().min(2).max(3),
|
|
12324
|
+
supplierCost: z59.number().finite().positive(),
|
|
12325
|
+
shippingCost: z59.number().finite().nonnegative(),
|
|
12326
|
+
returnRate: z59.number().finite().min(0).lt(1),
|
|
12327
|
+
cancellationRate: z59.number().finite().min(0).lt(1),
|
|
12328
|
+
adsManagerCpa: z59.number().finite().nonnegative(),
|
|
12329
|
+
desiredMargin: z59.number().finite().min(0).lt(1)
|
|
12330
|
+
});
|
|
12331
|
+
var GuideInput = z59.object({
|
|
12252
12332
|
projectId: ProjectId.optional()
|
|
12253
12333
|
}).strict();
|
|
12254
|
-
var DropshippingProjectNextAction =
|
|
12334
|
+
var DropshippingProjectNextAction = z59.discriminatedUnion("kind", [
|
|
12255
12335
|
"cost_product",
|
|
12256
12336
|
"provide_product_media",
|
|
12257
12337
|
"generate_creatives",
|
|
@@ -12265,78 +12345,78 @@ var DropshippingProjectNextAction = z58.discriminatedUnion("kind", [
|
|
|
12265
12345
|
"create_meta_campaign",
|
|
12266
12346
|
"repair_meta_campaign",
|
|
12267
12347
|
"review_paused_campaign"
|
|
12268
|
-
].map((kind) =>
|
|
12269
|
-
kind:
|
|
12270
|
-
href:
|
|
12348
|
+
].map((kind) => z59.object({
|
|
12349
|
+
kind: z59.literal(kind),
|
|
12350
|
+
href: z59.string().min(1)
|
|
12271
12351
|
})));
|
|
12272
|
-
var CostingInputSchema =
|
|
12273
|
-
country:
|
|
12274
|
-
supplierCost:
|
|
12275
|
-
shippingCost:
|
|
12276
|
-
returnRate:
|
|
12277
|
-
cancellationRate:
|
|
12278
|
-
adsManagerCpa:
|
|
12279
|
-
desiredMargin:
|
|
12352
|
+
var CostingInputSchema = z59.object({
|
|
12353
|
+
country: z59.string().min(2).max(3),
|
|
12354
|
+
supplierCost: z59.number().finite().positive(),
|
|
12355
|
+
shippingCost: z59.number().finite().nonnegative(),
|
|
12356
|
+
returnRate: z59.number().finite().min(0).lt(1),
|
|
12357
|
+
cancellationRate: z59.number().finite().min(0).lt(1),
|
|
12358
|
+
adsManagerCpa: z59.number().finite().nonnegative(),
|
|
12359
|
+
desiredMargin: z59.number().finite().min(0).lt(1)
|
|
12280
12360
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
12281
12361
|
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
12282
|
-
code:
|
|
12362
|
+
code: z59.ZodIssueCode.custom,
|
|
12283
12363
|
path: [
|
|
12284
12364
|
"cancellationRate"
|
|
12285
12365
|
]
|
|
12286
12366
|
});
|
|
12287
12367
|
});
|
|
12288
|
-
var CostingResultSchema =
|
|
12289
|
-
country:
|
|
12290
|
-
deliveryRate:
|
|
12291
|
-
adjustedShippingCost:
|
|
12292
|
-
adjustedCpa:
|
|
12293
|
-
totalCost:
|
|
12294
|
-
suggestedPrice:
|
|
12295
|
-
baseCommercialPrice:
|
|
12296
|
-
minimumSafePrice:
|
|
12297
|
-
commercialPrice:
|
|
12298
|
-
comparisonPrice:
|
|
12299
|
-
estimatedProfit:
|
|
12300
|
-
actualMargin:
|
|
12301
|
-
breakEvenAdsManagerCpa:
|
|
12302
|
-
wasPriceAutoAdjusted:
|
|
12303
|
-
profitabilityStatus:
|
|
12304
|
-
});
|
|
12305
|
-
var RewardProgressSchema =
|
|
12306
|
-
campaignKey:
|
|
12307
|
-
totalCredits:
|
|
12308
|
-
earnedCredits:
|
|
12309
|
-
milestones:
|
|
12368
|
+
var CostingResultSchema = z59.object({
|
|
12369
|
+
country: z59.string().min(2).max(3),
|
|
12370
|
+
deliveryRate: z59.number().finite(),
|
|
12371
|
+
adjustedShippingCost: z59.number().finite(),
|
|
12372
|
+
adjustedCpa: z59.number().finite(),
|
|
12373
|
+
totalCost: z59.number().finite(),
|
|
12374
|
+
suggestedPrice: z59.number().finite(),
|
|
12375
|
+
baseCommercialPrice: z59.number().finite(),
|
|
12376
|
+
minimumSafePrice: z59.number().finite(),
|
|
12377
|
+
commercialPrice: z59.number().finite(),
|
|
12378
|
+
comparisonPrice: z59.number().finite(),
|
|
12379
|
+
estimatedProfit: z59.number().finite(),
|
|
12380
|
+
actualMargin: z59.number().finite(),
|
|
12381
|
+
breakEvenAdsManagerCpa: z59.number().finite(),
|
|
12382
|
+
wasPriceAutoAdjusted: z59.boolean(),
|
|
12383
|
+
profitabilityStatus: z59.literal("healthy")
|
|
12384
|
+
});
|
|
12385
|
+
var RewardProgressSchema = z59.object({
|
|
12386
|
+
campaignKey: z59.literal("dropshipping-launch-v1"),
|
|
12387
|
+
totalCredits: z59.number().int().positive(),
|
|
12388
|
+
earnedCredits: z59.number().int().nonnegative(),
|
|
12389
|
+
milestones: z59.array(z59.object({
|
|
12310
12390
|
milestone: DropshippingRewardMilestone,
|
|
12311
|
-
credits:
|
|
12312
|
-
available:
|
|
12313
|
-
earned:
|
|
12391
|
+
credits: z59.number().int().positive(),
|
|
12392
|
+
available: z59.boolean().optional(),
|
|
12393
|
+
earned: z59.boolean(),
|
|
12314
12394
|
grantId: ProjectId.nullable(),
|
|
12315
|
-
grantedAt:
|
|
12395
|
+
grantedAt: z59.string().datetime().nullable()
|
|
12316
12396
|
})).length(DropshippingRewardMilestone.options.length)
|
|
12317
12397
|
});
|
|
12318
|
-
var ProjectResponseSchema =
|
|
12398
|
+
var ProjectResponseSchema = z59.object({
|
|
12319
12399
|
id: ProjectId,
|
|
12320
12400
|
taskId: ProjectId.nullable(),
|
|
12321
12401
|
status: DropshippingProjectStatus,
|
|
12322
|
-
originKey:
|
|
12402
|
+
originKey: z59.string().min(1),
|
|
12323
12403
|
researchRunId: ProjectId.nullable(),
|
|
12324
|
-
candidateSourceId:
|
|
12325
|
-
productName:
|
|
12404
|
+
candidateSourceId: z59.string().nullable(),
|
|
12405
|
+
productName: z59.string().nullable(),
|
|
12326
12406
|
productUrl: HttpUrl3.nullable(),
|
|
12327
12407
|
referenceImageUrl: HttpUrl3.nullable(),
|
|
12328
|
-
targetCountry:
|
|
12329
|
-
languageCode:
|
|
12330
|
-
hasReferenceImage:
|
|
12408
|
+
targetCountry: z59.string().nullable(),
|
|
12409
|
+
languageCode: z59.string().nullable(),
|
|
12410
|
+
hasReferenceImage: z59.boolean(),
|
|
12331
12411
|
costingInput: CostingInputSchema.nullable(),
|
|
12332
12412
|
costingResult: CostingResultSchema.nullable(),
|
|
12333
|
-
costingVersion:
|
|
12334
|
-
version:
|
|
12413
|
+
costingVersion: z59.number().int().positive().nullable(),
|
|
12414
|
+
version: z59.number().int().positive(),
|
|
12335
12415
|
phase: DropshippingProjectPhase,
|
|
12336
12416
|
nextAction: DropshippingProjectNextAction.nullable(),
|
|
12337
12417
|
rewards: RewardProgressSchema,
|
|
12338
|
-
createdAt:
|
|
12339
|
-
updatedAt:
|
|
12418
|
+
createdAt: z59.string().datetime(),
|
|
12419
|
+
updatedAt: z59.string().datetime()
|
|
12340
12420
|
}).passthrough();
|
|
12341
12421
|
function projectText(raw) {
|
|
12342
12422
|
const project = ProjectResponseSchema.parse(raw);
|