@productmaker/mcp 1.17.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +955 -333
- package/dist/stdio.js +955 -333
- package/package.json +2 -2
package/dist/http.js
CHANGED
|
@@ -76,6 +76,17 @@ var ApiClient = class {
|
|
|
76
76
|
});
|
|
77
77
|
return this.parse(res);
|
|
78
78
|
}
|
|
79
|
+
async putJson(path3, body) {
|
|
80
|
+
const res = await fetch(`${this.baseUrl}${path3}`, {
|
|
81
|
+
method: "PUT",
|
|
82
|
+
headers: {
|
|
83
|
+
...this.authHeaders(),
|
|
84
|
+
"Content-Type": "application/json"
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify(body)
|
|
87
|
+
});
|
|
88
|
+
return this.parse(res);
|
|
89
|
+
}
|
|
79
90
|
async deleteJson(path3) {
|
|
80
91
|
const res = await fetch(`${this.baseUrl}${path3}`, {
|
|
81
92
|
method: "DELETE",
|
|
@@ -142,10 +153,10 @@ var ApiClient = class {
|
|
|
142
153
|
};
|
|
143
154
|
|
|
144
155
|
// src/index.ts
|
|
145
|
-
var MCP_VERSION = "1.
|
|
156
|
+
var MCP_VERSION = "2.1.0";
|
|
146
157
|
|
|
147
158
|
// src/tools/tasks.ts
|
|
148
|
-
import { z as
|
|
159
|
+
import { z as z40 } from "zod";
|
|
149
160
|
|
|
150
161
|
// src/resolve-image.ts
|
|
151
162
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -450,9 +461,11 @@ var VideoModel = z.enum([
|
|
|
450
461
|
]);
|
|
451
462
|
var NarrativeStyle = z.enum([
|
|
452
463
|
"review",
|
|
464
|
+
"ugc_how_to",
|
|
453
465
|
"problem_product_cta",
|
|
454
466
|
"product_showcase",
|
|
455
467
|
"cinematic",
|
|
468
|
+
"wild_card",
|
|
456
469
|
"metaphor_product_cta",
|
|
457
470
|
"wearable_showcase",
|
|
458
471
|
"animated_problem_pixar",
|
|
@@ -471,9 +484,11 @@ var VideoResolution = z.enum([
|
|
|
471
484
|
var VideoPreset = z.enum([
|
|
472
485
|
"auto",
|
|
473
486
|
"ugc_dynamic",
|
|
487
|
+
"ugc_how_to",
|
|
474
488
|
"problem_solution",
|
|
475
489
|
"product_showcase",
|
|
476
490
|
"cinematic",
|
|
491
|
+
"wild_card",
|
|
477
492
|
"wearable_showcase",
|
|
478
493
|
"pixar_problem",
|
|
479
494
|
"pixar_sassy",
|
|
@@ -1388,6 +1403,8 @@ var INGEST_ALLOWED_IMAGE_MIME_TYPES = [
|
|
|
1388
1403
|
var PRODUCT_CONTEXT_MAX_CHARS = 3e3;
|
|
1389
1404
|
var INGEST_ALLOWED_IMAGE_MIME_TYPE_SET = new Set(INGEST_ALLOWED_IMAGE_MIME_TYPES);
|
|
1390
1405
|
var IngestOptions = z13.object({
|
|
1406
|
+
/** Optional owner-scoped guided journey context. Never bypasses ingest gates. */
|
|
1407
|
+
dropshippingProjectId: z13.string().uuid().optional(),
|
|
1391
1408
|
languageCode: LanguageCodeSchema.default("es-CO"),
|
|
1392
1409
|
ugcFormat: VideoFormat.default("single_15s"),
|
|
1393
1410
|
country: CountrySchema,
|
|
@@ -2461,6 +2478,7 @@ var TASK_CREATIVE_VARIANT_TEXT_LIMITS = {
|
|
|
2461
2478
|
recommendationRationale: 600
|
|
2462
2479
|
};
|
|
2463
2480
|
var TaskCreativeVariantVideoPreset = VideoPreset.exclude([
|
|
2481
|
+
"problem_solution",
|
|
2464
2482
|
"ugc_unboxing_chaos",
|
|
2465
2483
|
"ugc_curiosity_reveal",
|
|
2466
2484
|
"ugc_listicle_3",
|
|
@@ -2573,6 +2591,7 @@ var TaskVariantSummary = z21.object({
|
|
|
2573
2591
|
var MAX_LANDING_IMAGES = 20;
|
|
2574
2592
|
var AutoResolvedPresetSchema = z22.enum([
|
|
2575
2593
|
"ugc_dynamic",
|
|
2594
|
+
"ugc_how_to",
|
|
2576
2595
|
"ugc_demo_review",
|
|
2577
2596
|
"ugc_unboxing_chaos",
|
|
2578
2597
|
"ugc_curiosity_reveal",
|
|
@@ -2581,6 +2600,7 @@ var AutoResolvedPresetSchema = z22.enum([
|
|
|
2581
2600
|
"problem_solution",
|
|
2582
2601
|
"product_showcase",
|
|
2583
2602
|
"cinematic",
|
|
2603
|
+
"wild_card",
|
|
2584
2604
|
"wearable_showcase",
|
|
2585
2605
|
"pixar_problem",
|
|
2586
2606
|
"pixar_sassy",
|
|
@@ -6539,17 +6559,185 @@ var RegenerateEditRequestSchema = z36.object({
|
|
|
6539
6559
|
comment: z36.string().min(1).max(2e3)
|
|
6540
6560
|
});
|
|
6541
6561
|
|
|
6542
|
-
// ../../packages/types/src/
|
|
6562
|
+
// ../../packages/types/src/dropshipping-project.ts
|
|
6543
6563
|
import { z as z37 } from "zod";
|
|
6544
|
-
var
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6564
|
+
var DropshippingProjectStatusSchema = z37.enum([
|
|
6565
|
+
"active",
|
|
6566
|
+
"completed",
|
|
6567
|
+
"archived"
|
|
6568
|
+
]);
|
|
6569
|
+
var DropshippingProjectPhaseSchema = z37.enum([
|
|
6570
|
+
"research",
|
|
6571
|
+
"costing",
|
|
6572
|
+
"media",
|
|
6573
|
+
"generating",
|
|
6574
|
+
"storefront",
|
|
6575
|
+
"advertising",
|
|
6576
|
+
"complete"
|
|
6577
|
+
]);
|
|
6578
|
+
var DropshippingProjectCostingInputSchema = z37.object({
|
|
6579
|
+
country: z37.string().min(2).max(3),
|
|
6580
|
+
supplierCost: z37.number().finite().positive(),
|
|
6581
|
+
shippingCost: z37.number().finite().nonnegative(),
|
|
6582
|
+
returnRate: z37.number().finite().min(0).lt(1),
|
|
6583
|
+
cancellationRate: z37.number().finite().min(0).lt(1),
|
|
6584
|
+
adsManagerCpa: z37.number().finite().nonnegative(),
|
|
6585
|
+
desiredMargin: z37.number().finite().min(0).lt(1)
|
|
6586
|
+
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
6587
|
+
if (returnRate + cancellationRate >= 1) {
|
|
6588
|
+
context.addIssue({
|
|
6589
|
+
code: z37.ZodIssueCode.custom,
|
|
6590
|
+
path: [
|
|
6591
|
+
"cancellationRate"
|
|
6592
|
+
],
|
|
6593
|
+
message: "delivery_rate_positive"
|
|
6594
|
+
});
|
|
6595
|
+
}
|
|
6596
|
+
});
|
|
6597
|
+
var DropshippingProjectCostingResultSchema = z37.object({
|
|
6598
|
+
country: z37.string().min(2).max(3),
|
|
6599
|
+
deliveryRate: z37.number().finite(),
|
|
6600
|
+
adjustedShippingCost: z37.number().finite(),
|
|
6601
|
+
adjustedCpa: z37.number().finite(),
|
|
6602
|
+
totalCost: z37.number().finite(),
|
|
6603
|
+
suggestedPrice: z37.number().finite(),
|
|
6604
|
+
baseCommercialPrice: z37.number().finite(),
|
|
6605
|
+
minimumSafePrice: z37.number().finite(),
|
|
6606
|
+
commercialPrice: z37.number().finite(),
|
|
6607
|
+
comparisonPrice: z37.number().finite(),
|
|
6608
|
+
estimatedProfit: z37.number().finite(),
|
|
6609
|
+
actualMargin: z37.number().finite(),
|
|
6610
|
+
breakEvenAdsManagerCpa: z37.number().finite(),
|
|
6611
|
+
wasPriceAutoAdjusted: z37.boolean(),
|
|
6612
|
+
profitabilityStatus: z37.literal("healthy")
|
|
6613
|
+
});
|
|
6614
|
+
var HttpUrlSchema = z37.string().url().max(2e3).refine((value) => {
|
|
6615
|
+
try {
|
|
6616
|
+
return [
|
|
6617
|
+
"http:",
|
|
6618
|
+
"https:"
|
|
6619
|
+
].includes(new URL(value).protocol);
|
|
6620
|
+
} catch {
|
|
6621
|
+
return false;
|
|
6622
|
+
}
|
|
6623
|
+
}, "Product URL must use HTTP(S)");
|
|
6624
|
+
var ResearchCandidateOriginSchema = z37.object({
|
|
6625
|
+
type: z37.literal("research_candidate"),
|
|
6626
|
+
runId: z37.string().uuid(),
|
|
6627
|
+
candidateSourceId: z37.string().min(1).max(160)
|
|
6628
|
+
});
|
|
6629
|
+
var TaskOriginSchema = z37.object({
|
|
6630
|
+
type: z37.literal("task"),
|
|
6631
|
+
taskId: z37.string().uuid()
|
|
6632
|
+
});
|
|
6633
|
+
var ManualOriginSchema = z37.object({
|
|
6634
|
+
type: z37.literal("manual"),
|
|
6635
|
+
clientRequestId: z37.string().uuid(),
|
|
6636
|
+
country: z37.string().min(2).max(3).optional()
|
|
6637
|
+
});
|
|
6638
|
+
var CreateDropshippingProjectRequestSchema = z37.object({
|
|
6639
|
+
origin: z37.discriminatedUnion("type", [
|
|
6640
|
+
ResearchCandidateOriginSchema,
|
|
6641
|
+
TaskOriginSchema,
|
|
6642
|
+
ManualOriginSchema
|
|
6643
|
+
]),
|
|
6644
|
+
productName: z37.string().trim().min(1).max(240).optional(),
|
|
6645
|
+
productUrl: HttpUrlSchema.optional(),
|
|
6646
|
+
country: z37.string().min(2).max(3).optional(),
|
|
6647
|
+
languageCode: z37.string().min(2).max(16).optional()
|
|
6648
|
+
}).strict();
|
|
6649
|
+
var SaveDropshippingProjectCostingRequestSchema = z37.object({
|
|
6650
|
+
input: DropshippingProjectCostingInputSchema,
|
|
6651
|
+
version: z37.number().int().positive()
|
|
6652
|
+
}).strict();
|
|
6653
|
+
var DropshippingProjectNextActionSchema = z37.discriminatedUnion("kind", [
|
|
6654
|
+
z37.object({
|
|
6655
|
+
kind: z37.literal("cost_product"),
|
|
6656
|
+
href: z37.string().min(1)
|
|
6657
|
+
}),
|
|
6658
|
+
z37.object({
|
|
6659
|
+
kind: z37.literal("provide_product_media"),
|
|
6660
|
+
href: z37.string().min(1)
|
|
6661
|
+
}),
|
|
6662
|
+
z37.object({
|
|
6663
|
+
kind: z37.literal("generate_creatives"),
|
|
6664
|
+
href: z37.string().min(1)
|
|
6665
|
+
}),
|
|
6666
|
+
z37.object({
|
|
6667
|
+
kind: z37.literal("wait_for_creatives"),
|
|
6668
|
+
href: z37.string().min(1)
|
|
6669
|
+
}),
|
|
6670
|
+
z37.object({
|
|
6671
|
+
kind: z37.literal("repair_creatives"),
|
|
6672
|
+
href: z37.string().min(1)
|
|
6673
|
+
}),
|
|
6674
|
+
z37.object({
|
|
6675
|
+
kind: z37.literal("complete_creative_set"),
|
|
6676
|
+
href: z37.string().min(1)
|
|
6677
|
+
}),
|
|
6678
|
+
z37.object({
|
|
6679
|
+
kind: z37.literal("connect_shopify"),
|
|
6680
|
+
href: z37.string().min(1)
|
|
6681
|
+
}),
|
|
6682
|
+
z37.object({
|
|
6683
|
+
kind: z37.literal("publish_storefront"),
|
|
6684
|
+
href: z37.string().min(1)
|
|
6685
|
+
}),
|
|
6686
|
+
z37.object({
|
|
6687
|
+
kind: z37.literal("wait_for_storefront"),
|
|
6688
|
+
href: z37.string().min(1)
|
|
6689
|
+
}),
|
|
6690
|
+
z37.object({
|
|
6691
|
+
kind: z37.literal("connect_meta"),
|
|
6692
|
+
href: z37.string().min(1)
|
|
6693
|
+
}),
|
|
6694
|
+
z37.object({
|
|
6695
|
+
kind: z37.literal("create_meta_campaign"),
|
|
6696
|
+
href: z37.string().min(1)
|
|
6697
|
+
}),
|
|
6698
|
+
z37.object({
|
|
6699
|
+
kind: z37.literal("repair_meta_campaign"),
|
|
6700
|
+
href: z37.string().min(1)
|
|
6701
|
+
}),
|
|
6702
|
+
z37.object({
|
|
6703
|
+
kind: z37.literal("review_paused_campaign"),
|
|
6704
|
+
href: z37.string().min(1)
|
|
6705
|
+
})
|
|
6706
|
+
]);
|
|
6707
|
+
var DropshippingProjectResponseSchema = z37.object({
|
|
6708
|
+
id: z37.string().uuid(),
|
|
6709
|
+
taskId: z37.string().uuid().nullable(),
|
|
6710
|
+
status: DropshippingProjectStatusSchema,
|
|
6711
|
+
originKey: z37.string().min(1),
|
|
6712
|
+
researchRunId: z37.string().uuid().nullable(),
|
|
6713
|
+
candidateSourceId: z37.string().nullable(),
|
|
6714
|
+
productName: z37.string().nullable(),
|
|
6715
|
+
productUrl: HttpUrlSchema.nullable(),
|
|
6716
|
+
referenceImageUrl: z37.string().url().nullable(),
|
|
6717
|
+
hasReferenceImage: z37.boolean(),
|
|
6718
|
+
targetCountry: z37.string().nullable(),
|
|
6719
|
+
languageCode: z37.string().nullable(),
|
|
6720
|
+
costingInput: DropshippingProjectCostingInputSchema.nullable(),
|
|
6721
|
+
costingResult: DropshippingProjectCostingResultSchema.nullable(),
|
|
6722
|
+
costingVersion: z37.number().int().positive().nullable(),
|
|
6723
|
+
version: z37.number().int().positive(),
|
|
6724
|
+
phase: DropshippingProjectPhaseSchema,
|
|
6725
|
+
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
6726
|
+
createdAt: z37.string().datetime(),
|
|
6727
|
+
updatedAt: z37.string().datetime()
|
|
6728
|
+
});
|
|
6729
|
+
|
|
6730
|
+
// ../../packages/types/src/scene-subject-contract.ts
|
|
6731
|
+
import { z as z38 } from "zod";
|
|
6732
|
+
var SceneSubjectContractSchema = z38.object({
|
|
6733
|
+
maxPeople: z38.number().int().min(1).max(10),
|
|
6734
|
+
minPeople: z38.number().int().min(0).max(10),
|
|
6735
|
+
minDistinctPeople: z38.number().int().min(0).max(10),
|
|
6736
|
+
maxHands: z38.number().int().min(0).max(20)
|
|
6549
6737
|
}).superRefine((value, ctx) => {
|
|
6550
6738
|
if (value.minPeople > value.maxPeople) {
|
|
6551
6739
|
ctx.addIssue({
|
|
6552
|
-
code:
|
|
6740
|
+
code: z38.ZodIssueCode.custom,
|
|
6553
6741
|
path: [
|
|
6554
6742
|
"minPeople"
|
|
6555
6743
|
],
|
|
@@ -6558,7 +6746,7 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6558
6746
|
}
|
|
6559
6747
|
if (value.minDistinctPeople > value.maxPeople) {
|
|
6560
6748
|
ctx.addIssue({
|
|
6561
|
-
code:
|
|
6749
|
+
code: z38.ZodIssueCode.custom,
|
|
6562
6750
|
path: [
|
|
6563
6751
|
"minDistinctPeople"
|
|
6564
6752
|
],
|
|
@@ -6567,7 +6755,7 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6567
6755
|
}
|
|
6568
6756
|
if (value.minDistinctPeople > value.minPeople) {
|
|
6569
6757
|
ctx.addIssue({
|
|
6570
|
-
code:
|
|
6758
|
+
code: z38.ZodIssueCode.custom,
|
|
6571
6759
|
path: [
|
|
6572
6760
|
"minDistinctPeople"
|
|
6573
6761
|
],
|
|
@@ -6576,6 +6764,166 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6576
6764
|
}
|
|
6577
6765
|
});
|
|
6578
6766
|
|
|
6767
|
+
// ../../packages/types/src/productmaker-chat-capabilities.ts
|
|
6768
|
+
var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
6769
|
+
{
|
|
6770
|
+
name: "approve_video_script",
|
|
6771
|
+
confirmation: "credit_consuming",
|
|
6772
|
+
schemaHash: "bab794a9700a8d3f42b97f444a776e7ed4dcd833038c52588f951b50970ff3fa"
|
|
6773
|
+
},
|
|
6774
|
+
{
|
|
6775
|
+
name: "cost_dropshipping_project",
|
|
6776
|
+
confirmation: "state_change",
|
|
6777
|
+
schemaHash: "746797b5400b170ba3a0704d432afff635794f0a7ae0b9da07b26d49e3b82242"
|
|
6778
|
+
},
|
|
6779
|
+
{
|
|
6780
|
+
name: "cost_product",
|
|
6781
|
+
confirmation: "none",
|
|
6782
|
+
schemaHash: "6d1f85a999dbdabae4eda406ff4689cdff2016df375b5b6741b91f4308d819af"
|
|
6783
|
+
},
|
|
6784
|
+
{
|
|
6785
|
+
name: "create_creative_variant",
|
|
6786
|
+
confirmation: "credit_consuming",
|
|
6787
|
+
schemaHash: "8feeed1e6e6a14bdcb0a1d9d8b03350ce7d8117d926db49f19ca5c5a8f1e7033"
|
|
6788
|
+
},
|
|
6789
|
+
{
|
|
6790
|
+
name: "create_product_task",
|
|
6791
|
+
confirmation: "credit_consuming",
|
|
6792
|
+
schemaHash: "828ee643bb3a05a63c6e63730459d35ce1621cbd559bbc76a6c5fcec9a45654d"
|
|
6793
|
+
},
|
|
6794
|
+
{
|
|
6795
|
+
name: "edit_task_draft",
|
|
6796
|
+
confirmation: "state_change",
|
|
6797
|
+
schemaHash: "f1763564083dcaac2d1f4d5e6c4625a2d4ec0ea3eea273aadc0fb9d4ab6c7d47"
|
|
6798
|
+
},
|
|
6799
|
+
{
|
|
6800
|
+
name: "estimate_creative_variant",
|
|
6801
|
+
confirmation: "none",
|
|
6802
|
+
schemaHash: "a5601adcb9578319528ca0a96f37a35b613370646a75932d1b3978d593f7e302"
|
|
6803
|
+
},
|
|
6804
|
+
{
|
|
6805
|
+
name: "find_winning_products",
|
|
6806
|
+
confirmation: "credit_consuming",
|
|
6807
|
+
schemaHash: "40f581e270ca668fb5fd1505a1f7cced6f629936e7d8394426aa0c655b9cef4f"
|
|
6808
|
+
},
|
|
6809
|
+
{
|
|
6810
|
+
name: "generate_free_video",
|
|
6811
|
+
confirmation: "credit_consuming",
|
|
6812
|
+
schemaHash: "a6f984d175c1ae5bc5f36ade27ee12c57763192000453c0387cd4cd6a9f1751d"
|
|
6813
|
+
},
|
|
6814
|
+
{
|
|
6815
|
+
name: "generate_image_creatives",
|
|
6816
|
+
confirmation: "credit_consuming",
|
|
6817
|
+
schemaHash: "fb6afcf8571887906340fa0b8dd17196d2814e480b734ad5d374e8810958152e"
|
|
6818
|
+
},
|
|
6819
|
+
{
|
|
6820
|
+
name: "generate_landing",
|
|
6821
|
+
confirmation: "credit_consuming",
|
|
6822
|
+
schemaHash: "539922b8fe611c73a7349b1c3f92632fe21f161d7874a0ef2172abfec5834759"
|
|
6823
|
+
},
|
|
6824
|
+
{
|
|
6825
|
+
name: "generate_video_creative",
|
|
6826
|
+
confirmation: "credit_consuming",
|
|
6827
|
+
schemaHash: "94e90d60ad5d68538c31d880a635c5be69d6d204fd2119139735af83ebf0b94a"
|
|
6828
|
+
},
|
|
6829
|
+
{
|
|
6830
|
+
name: "get_meta_campaign_status",
|
|
6831
|
+
confirmation: "none",
|
|
6832
|
+
schemaHash: "92077241cf4e9d14edefca410e85715cc383b1433081c3461c925f8fc3d6e8ab"
|
|
6833
|
+
},
|
|
6834
|
+
{
|
|
6835
|
+
name: "get_product_research_run",
|
|
6836
|
+
confirmation: "none",
|
|
6837
|
+
schemaHash: "3d0bfa4409daa4a8126d18787c3dc619dbdf2fbb679a2cffe9ffcd1c0d96402f"
|
|
6838
|
+
},
|
|
6839
|
+
{
|
|
6840
|
+
name: "get_task_status",
|
|
6841
|
+
confirmation: "none",
|
|
6842
|
+
schemaHash: "6876d865685dd371ae6c2da2d5a69b657731e5a032aff46ac95b6077e9a6d93e"
|
|
6843
|
+
},
|
|
6844
|
+
{
|
|
6845
|
+
name: "get_tiktok_campaign_status",
|
|
6846
|
+
confirmation: "none",
|
|
6847
|
+
schemaHash: "7a2f90a9a9ba91506fbb57a0a881d5a7b9ca1bb1074b0a754520f02fd81b2801"
|
|
6848
|
+
},
|
|
6849
|
+
{
|
|
6850
|
+
name: "get_video_script",
|
|
6851
|
+
confirmation: "none",
|
|
6852
|
+
schemaHash: "c96e7042368ba6f241773d26d4a443894b092801d1c81054f3798865138edfba"
|
|
6853
|
+
},
|
|
6854
|
+
{
|
|
6855
|
+
name: "guide_dropshipping_launch",
|
|
6856
|
+
confirmation: "none",
|
|
6857
|
+
schemaHash: "0e7a1cb5ad5c6681473df5689336edcd7a63b8d68853359982e44bfd98a65db8"
|
|
6858
|
+
},
|
|
6859
|
+
{
|
|
6860
|
+
name: "list_meta_ad_accounts",
|
|
6861
|
+
confirmation: "none",
|
|
6862
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6863
|
+
},
|
|
6864
|
+
{
|
|
6865
|
+
name: "list_product_research_runs",
|
|
6866
|
+
confirmation: "none",
|
|
6867
|
+
schemaHash: "3b8fac903cd9e30c5b6a6c584cc70a819af5392bbdbb32b69eab4c65dc52b556"
|
|
6868
|
+
},
|
|
6869
|
+
{
|
|
6870
|
+
name: "list_shopify_products",
|
|
6871
|
+
confirmation: "none",
|
|
6872
|
+
schemaHash: "152b137e01066f3b443987ad75f5be00de8696ce984144bd775416192be20667"
|
|
6873
|
+
},
|
|
6874
|
+
{
|
|
6875
|
+
name: "list_shopify_shops",
|
|
6876
|
+
confirmation: "none",
|
|
6877
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6878
|
+
},
|
|
6879
|
+
{
|
|
6880
|
+
name: "list_tasks",
|
|
6881
|
+
confirmation: "none",
|
|
6882
|
+
schemaHash: "cac5e9dda34b90550024cc546976fab1d6de4fc8fca85a3ec6abde65223cb56c"
|
|
6883
|
+
},
|
|
6884
|
+
{
|
|
6885
|
+
name: "list_tiktok_advertisers",
|
|
6886
|
+
confirmation: "none",
|
|
6887
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6888
|
+
},
|
|
6889
|
+
{
|
|
6890
|
+
name: "publish_creatives_to_meta",
|
|
6891
|
+
confirmation: "external_mutation",
|
|
6892
|
+
schemaHash: "ddb45071d61746b443124346e7a82095315a2a80bd393c73a45f12b895939cf5"
|
|
6893
|
+
},
|
|
6894
|
+
{
|
|
6895
|
+
name: "publish_to_meta",
|
|
6896
|
+
confirmation: "external_mutation",
|
|
6897
|
+
schemaHash: "4b6daa1a25e739ccf208a6acede067ec1c22b1ea5509f332361a17dd46f6bb0b"
|
|
6898
|
+
},
|
|
6899
|
+
{
|
|
6900
|
+
name: "publish_to_shopify",
|
|
6901
|
+
confirmation: "external_mutation",
|
|
6902
|
+
schemaHash: "ec37111aac872e6be22f34c8b547c1e4b58875f798c48e24ca9ca067a0a22d8b"
|
|
6903
|
+
},
|
|
6904
|
+
{
|
|
6905
|
+
name: "publish_to_tiktok",
|
|
6906
|
+
confirmation: "external_mutation",
|
|
6907
|
+
schemaHash: "4f8dccba51b99687f04e1a58e3fde003b6f52ec6c891afe74b1d81d4b6992908"
|
|
6908
|
+
},
|
|
6909
|
+
{
|
|
6910
|
+
name: "regenerate_video_script",
|
|
6911
|
+
confirmation: "credit_consuming",
|
|
6912
|
+
schemaHash: "745687cb41f904e293105f93bbe6bc0471f63fe097ab8f85d3df8d9833084844"
|
|
6913
|
+
},
|
|
6914
|
+
{
|
|
6915
|
+
name: "resolve_pending_action",
|
|
6916
|
+
confirmation: "credit_consuming",
|
|
6917
|
+
schemaHash: "3a9f33a26fce63b20bece3a528f8eb16e917dabc8a9ec5f04e746bad84757aa3"
|
|
6918
|
+
},
|
|
6919
|
+
{
|
|
6920
|
+
name: "start_dropshipping_project",
|
|
6921
|
+
confirmation: "state_change",
|
|
6922
|
+
schemaHash: "2b621702e8da8bb894d392060e5e4f677a8dc26f454e991dbb929053715a4f8b"
|
|
6923
|
+
}
|
|
6924
|
+
];
|
|
6925
|
+
var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITIES.map((capability) => capability.name);
|
|
6926
|
+
|
|
6579
6927
|
// src/resolve-media.ts
|
|
6580
6928
|
var MAX_MEDIA_BYTES = CAMPAIGN_LIMITS.MAX_FILE_SIZE_BYTES;
|
|
6581
6929
|
var MEDIA_FORMATS = [
|
|
@@ -6815,10 +7163,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
6815
7163
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
6816
7164
|
|
|
6817
7165
|
// src/tools/shared.ts
|
|
6818
|
-
import { z as
|
|
6819
|
-
var Lang =
|
|
6820
|
-
var Country =
|
|
6821
|
-
var LandingStrategyEnum =
|
|
7166
|
+
import { z as z39 } from "zod";
|
|
7167
|
+
var Lang = z39.string().min(2).max(10);
|
|
7168
|
+
var Country = z39.string().min(2).max(3);
|
|
7169
|
+
var LandingStrategyEnum = z39.enum([
|
|
6822
7170
|
"auto",
|
|
6823
7171
|
"classic",
|
|
6824
7172
|
"pain_solution",
|
|
@@ -6827,28 +7175,30 @@ var LandingStrategyEnum = z38.enum([
|
|
|
6827
7175
|
"offer_value",
|
|
6828
7176
|
"lifestyle_identity"
|
|
6829
7177
|
]);
|
|
6830
|
-
var LandingImageFormatEnum =
|
|
7178
|
+
var LandingImageFormatEnum = z39.enum([
|
|
6831
7179
|
"9:16",
|
|
6832
7180
|
"4:5",
|
|
6833
7181
|
"1:1"
|
|
6834
7182
|
]);
|
|
6835
|
-
var VideoPresetEnum =
|
|
7183
|
+
var VideoPresetEnum = z39.enum([
|
|
6836
7184
|
"auto",
|
|
6837
7185
|
"ugc_dynamic",
|
|
7186
|
+
"ugc_how_to",
|
|
6838
7187
|
"ugc_unboxing_chaos",
|
|
6839
|
-
"problem_solution",
|
|
6840
7188
|
"product_showcase",
|
|
6841
7189
|
"wearable_showcase",
|
|
6842
7190
|
"cinematic",
|
|
7191
|
+
"wild_card",
|
|
6843
7192
|
"pixar_problem",
|
|
6844
7193
|
"pixar_sassy"
|
|
6845
7194
|
]);
|
|
6846
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
7195
|
+
var TaskCreativeVariantVideoPresetEnum = z39.enum([
|
|
6847
7196
|
"auto",
|
|
6848
7197
|
"ugc_dynamic",
|
|
6849
|
-
"
|
|
7198
|
+
"ugc_how_to",
|
|
6850
7199
|
"product_showcase",
|
|
6851
7200
|
"cinematic",
|
|
7201
|
+
"wild_card",
|
|
6852
7202
|
"wearable_showcase",
|
|
6853
7203
|
"pixar_problem",
|
|
6854
7204
|
"pixar_sassy",
|
|
@@ -6861,15 +7211,15 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
6861
7211
|
narrativeStyle: "review",
|
|
6862
7212
|
videoModel: "veo"
|
|
6863
7213
|
},
|
|
6864
|
-
|
|
7214
|
+
ugc_how_to: {
|
|
6865
7215
|
videoStyle: "ai_dynamic",
|
|
6866
|
-
narrativeStyle: "
|
|
7216
|
+
narrativeStyle: "ugc_how_to",
|
|
6867
7217
|
videoModel: "veo"
|
|
6868
7218
|
},
|
|
6869
|
-
|
|
7219
|
+
ugc_unboxing_chaos: {
|
|
6870
7220
|
videoStyle: "ai_dynamic",
|
|
6871
|
-
narrativeStyle: "
|
|
6872
|
-
videoModel: "
|
|
7221
|
+
narrativeStyle: "ugc_unboxing_chaos",
|
|
7222
|
+
videoModel: "veo"
|
|
6873
7223
|
},
|
|
6874
7224
|
pixar_problem: {
|
|
6875
7225
|
videoStyle: "ai_dynamic",
|
|
@@ -6895,6 +7245,11 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
6895
7245
|
videoStyle: "product_only",
|
|
6896
7246
|
narrativeStyle: "cinematic",
|
|
6897
7247
|
videoModel: "grok"
|
|
7248
|
+
},
|
|
7249
|
+
wild_card: {
|
|
7250
|
+
videoStyle: "product_only",
|
|
7251
|
+
narrativeStyle: "wild_card",
|
|
7252
|
+
videoModel: "grok"
|
|
6898
7253
|
}
|
|
6899
7254
|
};
|
|
6900
7255
|
function resolveVideoPreset(preset) {
|
|
@@ -6902,7 +7257,7 @@ function resolveVideoPreset(preset) {
|
|
|
6902
7257
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
6903
7258
|
}
|
|
6904
7259
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
6905
|
-
var VideoTierEnum =
|
|
7260
|
+
var VideoTierEnum = z39.enum([
|
|
6906
7261
|
"basic"
|
|
6907
7262
|
]);
|
|
6908
7263
|
function resolveVideoTier(_tier) {
|
|
@@ -6917,21 +7272,23 @@ function resolveVideoFormatForDuration(durationSeconds) {
|
|
|
6917
7272
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
6918
7273
|
}
|
|
6919
7274
|
__name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
|
|
6920
|
-
var VideoResolutionEnum =
|
|
7275
|
+
var VideoResolutionEnum = z39.enum([
|
|
6921
7276
|
"480p",
|
|
6922
7277
|
"720p"
|
|
6923
7278
|
]);
|
|
6924
|
-
var VideoStyleEnum =
|
|
7279
|
+
var VideoStyleEnum = z39.enum([
|
|
6925
7280
|
"ugc",
|
|
6926
7281
|
"cartoon_3d",
|
|
6927
7282
|
"product_only",
|
|
6928
7283
|
"ai_dynamic"
|
|
6929
7284
|
]);
|
|
6930
|
-
var NarrativeStyleEnum =
|
|
7285
|
+
var NarrativeStyleEnum = z39.enum([
|
|
6931
7286
|
"review",
|
|
7287
|
+
"ugc_how_to",
|
|
6932
7288
|
"problem_product_cta",
|
|
6933
7289
|
"product_showcase",
|
|
6934
7290
|
"cinematic",
|
|
7291
|
+
"wild_card",
|
|
6935
7292
|
"metaphor_product_cta",
|
|
6936
7293
|
"wearable_showcase",
|
|
6937
7294
|
"animated_problem_pixar",
|
|
@@ -6942,17 +7299,18 @@ var NarrativeStyleEnum = z38.enum([
|
|
|
6942
7299
|
"ugc_skeptic_confession",
|
|
6943
7300
|
"ugc_demo_review"
|
|
6944
7301
|
]);
|
|
6945
|
-
var PublicNarrativeStyleEnum =
|
|
7302
|
+
var PublicNarrativeStyleEnum = z39.enum([
|
|
6946
7303
|
"review",
|
|
7304
|
+
"ugc_how_to",
|
|
6947
7305
|
"ugc_unboxing_chaos",
|
|
6948
|
-
"problem_product_cta",
|
|
6949
7306
|
"product_showcase",
|
|
6950
7307
|
"wearable_showcase",
|
|
6951
7308
|
"cinematic",
|
|
7309
|
+
"wild_card",
|
|
6952
7310
|
"animated_problem_pixar",
|
|
6953
7311
|
"sassy_product_pixar"
|
|
6954
7312
|
]);
|
|
6955
|
-
var VideoModelEnum =
|
|
7313
|
+
var VideoModelEnum = z39.enum([
|
|
6956
7314
|
"veo",
|
|
6957
7315
|
"wan",
|
|
6958
7316
|
"bytedance",
|
|
@@ -6960,25 +7318,25 @@ var VideoModelEnum = z38.enum([
|
|
|
6960
7318
|
"grok",
|
|
6961
7319
|
"kling"
|
|
6962
7320
|
]);
|
|
6963
|
-
var ProductReferenceUserChoiceEnum =
|
|
7321
|
+
var ProductReferenceUserChoiceEnum = z39.enum([
|
|
6964
7322
|
"same_product",
|
|
6965
7323
|
"variants",
|
|
6966
7324
|
"different_products",
|
|
6967
7325
|
"combo_distinct"
|
|
6968
7326
|
]);
|
|
6969
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
7327
|
+
var ProductReferenceCandidateGroupingEnum = z39.enum([
|
|
6970
7328
|
"same_product_same_variant",
|
|
6971
7329
|
"same_product_different_variants",
|
|
6972
7330
|
"different_products",
|
|
6973
7331
|
"unclear"
|
|
6974
7332
|
]);
|
|
6975
|
-
var GapDurationChoiceMirror =
|
|
6976
|
-
angleIndex:
|
|
6977
|
-
recommendedSec:
|
|
6978
|
-
|
|
6979
|
-
|
|
7333
|
+
var GapDurationChoiceMirror = z39.object({
|
|
7334
|
+
angleIndex: z39.number().int().nonnegative(),
|
|
7335
|
+
recommendedSec: z39.union([
|
|
7336
|
+
z39.literal(15),
|
|
7337
|
+
z39.literal(30)
|
|
6980
7338
|
]),
|
|
6981
|
-
estimatedDeltaCredits:
|
|
7339
|
+
estimatedDeltaCredits: z39.number().int().nonnegative().optional()
|
|
6982
7340
|
});
|
|
6983
7341
|
function buildSelectedImageUrlsHash(urls) {
|
|
6984
7342
|
const input = [
|
|
@@ -6992,13 +7350,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
6992
7350
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
6993
7351
|
}
|
|
6994
7352
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
6995
|
-
var ImageCreativeStyleEnum =
|
|
7353
|
+
var ImageCreativeStyleEnum = z39.enum([
|
|
6996
7354
|
"studio",
|
|
6997
7355
|
"floating",
|
|
6998
7356
|
"ingredients",
|
|
6999
7357
|
"in_use"
|
|
7000
7358
|
]);
|
|
7001
|
-
var ImageCreativeArchetypeEnum =
|
|
7359
|
+
var ImageCreativeArchetypeEnum = z39.enum([
|
|
7002
7360
|
"direct_response_product_ad",
|
|
7003
7361
|
"hero_outcome",
|
|
7004
7362
|
"offer_value_prop",
|
|
@@ -7007,23 +7365,23 @@ var ImageCreativeArchetypeEnum = z38.enum([
|
|
|
7007
7365
|
"problem_solution",
|
|
7008
7366
|
"lifestyle_identity"
|
|
7009
7367
|
]);
|
|
7010
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
7368
|
+
var ImageCreativeVisualTreatmentEnum = z39.enum([
|
|
7011
7369
|
"performance_product_ad",
|
|
7012
7370
|
"premium_dtc_carousel"
|
|
7013
7371
|
]);
|
|
7014
|
-
var ImageCreativeAspectRatioEnum =
|
|
7372
|
+
var ImageCreativeAspectRatioEnum = z39.enum([
|
|
7015
7373
|
"1:1",
|
|
7016
7374
|
"4:5",
|
|
7017
7375
|
"9:16",
|
|
7018
7376
|
"16:9"
|
|
7019
7377
|
]);
|
|
7020
|
-
var ImageRefSchema =
|
|
7021
|
-
url:
|
|
7022
|
-
path:
|
|
7378
|
+
var ImageRefSchema = z39.object({
|
|
7379
|
+
url: z39.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.'),
|
|
7380
|
+
path: z39.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`.')
|
|
7023
7381
|
}).refine((v) => Boolean(v.url) !== Boolean(v.path), {
|
|
7024
7382
|
message: "each image entry must have exactly one of `url` or `path`"
|
|
7025
7383
|
});
|
|
7026
|
-
var ImagesInput =
|
|
7384
|
+
var ImagesInput = z39.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.');
|
|
7027
7385
|
function asText(value) {
|
|
7028
7386
|
return {
|
|
7029
7387
|
content: [
|
|
@@ -7076,14 +7434,14 @@ async function submitCreative(api, opts) {
|
|
|
7076
7434
|
});
|
|
7077
7435
|
}
|
|
7078
7436
|
__name(submitCreative, "submitCreative");
|
|
7079
|
-
var ResearchTargetCountryEnum =
|
|
7437
|
+
var ResearchTargetCountryEnum = z39.enum([
|
|
7080
7438
|
"CO",
|
|
7081
7439
|
"MX",
|
|
7082
7440
|
"PE",
|
|
7083
7441
|
"EC",
|
|
7084
7442
|
"CL"
|
|
7085
7443
|
]);
|
|
7086
|
-
var ResearchCategoryEnum =
|
|
7444
|
+
var ResearchCategoryEnum = z39.enum([
|
|
7087
7445
|
"auto",
|
|
7088
7446
|
"automotive",
|
|
7089
7447
|
"kitchen",
|
|
@@ -7129,6 +7487,15 @@ var McpErrorCode = {
|
|
|
7129
7487
|
TASK_NOT_READY: "TASK_NOT_READY",
|
|
7130
7488
|
CREATIVE_VARIANT_FAILED: "CREATIVE_VARIANT_FAILED",
|
|
7131
7489
|
CREATIVE_VARIANT_DISPATCH_FAILED: "CREATIVE_VARIANT_DISPATCH_FAILED",
|
|
7490
|
+
// Guided dropshipping project / research
|
|
7491
|
+
DROPSHIPPING_PROJECT_NOT_FOUND: "DROPSHIPPING_PROJECT_NOT_FOUND",
|
|
7492
|
+
DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY: "DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY",
|
|
7493
|
+
DROPSHIPPING_PROJECT_VERSION_CONFLICT: "DROPSHIPPING_PROJECT_VERSION_CONFLICT",
|
|
7494
|
+
DROPSHIPPING_PROJECT_MEDIA_REQUIRED: "DROPSHIPPING_PROJECT_MEDIA_REQUIRED",
|
|
7495
|
+
DROPSHIPPING_PROJECT_DISABLED: "DROPSHIPPING_PROJECT_DISABLED",
|
|
7496
|
+
KALODATA_NOT_CONFIGURED: "KALODATA_NOT_CONFIGURED",
|
|
7497
|
+
META_AD_LIBRARY_NOT_CONFIGURED: "META_AD_LIBRARY_NOT_CONFIGURED",
|
|
7498
|
+
PRODUCT_RESEARCH_DISABLED: "PRODUCT_RESEARCH_DISABLED",
|
|
7132
7499
|
PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT: "PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT",
|
|
7133
7500
|
// Connection presence
|
|
7134
7501
|
NO_SHOPIFY_SHOPS: "NO_SHOPIFY_SHOPS",
|
|
@@ -7139,6 +7506,7 @@ var McpErrorCode = {
|
|
|
7139
7506
|
CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
|
|
7140
7507
|
CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
|
|
7141
7508
|
CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
|
|
7509
|
+
CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
|
|
7142
7510
|
// Shopify
|
|
7143
7511
|
SHOPIFY_NOT_CONNECTED: "SHOPIFY_NOT_CONNECTED",
|
|
7144
7512
|
SHOPIFY_TOKEN_EXPIRED: "SHOPIFY_TOKEN_EXPIRED",
|
|
@@ -7243,6 +7611,7 @@ var CODE_MESSAGES = {
|
|
|
7243
7611
|
CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish to Shopify first or pass `landingUrl` explicitly.",
|
|
7244
7612
|
CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
|
|
7245
7613
|
CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
|
|
7614
|
+
CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
|
|
7246
7615
|
// Connections
|
|
7247
7616
|
NO_SHOPIFY_SHOPS: "No Shopify stores connected. Connect one at https://productmaker.app/integrations.",
|
|
7248
7617
|
NO_META_AD_ACCOUNTS: "No Meta Ads accounts connected. Connect Facebook at https://productmaker.app/integrations.",
|
|
@@ -7251,6 +7620,14 @@ var CODE_MESSAGES = {
|
|
|
7251
7620
|
TASK_NOT_READY: "The task is not ready for this action yet. Wait for it to finish and retry.",
|
|
7252
7621
|
CREATIVE_VARIANT_FAILED: "The previous creative variant attempt failed. Ask for confirmation before starting a new paid attempt with a new clientRequestId.",
|
|
7253
7622
|
CREATIVE_VARIANT_DISPATCH_FAILED: "The creative variant could not be queued. Retry as a new paid attempt with a new clientRequestId.",
|
|
7623
|
+
DROPSHIPPING_PROJECT_NOT_FOUND: "Project not found or it does not belong to this user.",
|
|
7624
|
+
DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY: "That research candidate is no longer available. Return to the current research results and choose a fresh candidate.",
|
|
7625
|
+
DROPSHIPPING_PROJECT_VERSION_CONFLICT: "This project changed in another tab. Read it again, review the newer values, and retry with the fresh version.",
|
|
7626
|
+
DROPSHIPPING_PROJECT_MEDIA_REQUIRED: "This project needs a product photo before creating content. Upload one from the guided ingest step.",
|
|
7627
|
+
DROPSHIPPING_PROJECT_DISABLED: "Guided dropshipping projects are temporarily unavailable. Try again later.",
|
|
7628
|
+
KALODATA_NOT_CONFIGURED: "Product research is temporarily unavailable because the trend-data provider is not configured.",
|
|
7629
|
+
META_AD_LIBRARY_NOT_CONFIGURED: "Product research is temporarily unavailable because Meta Ad Library is not configured.",
|
|
7630
|
+
PRODUCT_RESEARCH_DISABLED: "Product research is temporarily unavailable. Try again later.",
|
|
7254
7631
|
PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT: "A product research run with the same country and category is already running. Check it with `list_product_research_runs` instead of starting a new paid run.",
|
|
7255
7632
|
// API key
|
|
7256
7633
|
INVALID_API_KEY: "Invalid API key. Check your PM_API_KEY in the MCP client configuration.",
|
|
@@ -7287,6 +7664,11 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7287
7664
|
McpErrorCode.CAMPAIGN_NOT_FOUND,
|
|
7288
7665
|
McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
|
|
7289
7666
|
McpErrorCode.TASK_NOT_FOUND,
|
|
7667
|
+
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
7668
|
+
McpErrorCode.DROPSHIPPING_PROJECT_DISABLED,
|
|
7669
|
+
McpErrorCode.DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY,
|
|
7670
|
+
McpErrorCode.DROPSHIPPING_PROJECT_VERSION_CONFLICT,
|
|
7671
|
+
McpErrorCode.DROPSHIPPING_PROJECT_MEDIA_REQUIRED,
|
|
7290
7672
|
McpErrorCode.META_TASK_NOT_FOUND,
|
|
7291
7673
|
McpErrorCode.META_INVALID_AD_ACCOUNT,
|
|
7292
7674
|
McpErrorCode.META_PIXEL_NOT_FOUND,
|
|
@@ -7295,6 +7677,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7295
7677
|
McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
|
|
7296
7678
|
McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
|
|
7297
7679
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
7680
|
+
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
7298
7681
|
McpErrorCode.META_NO_LANDING_URL,
|
|
7299
7682
|
McpErrorCode.META_DAILY_BUDGET_TOO_HIGH,
|
|
7300
7683
|
McpErrorCode.META_CAMPAIGN_CONFIG_INVALID,
|
|
@@ -7332,6 +7715,14 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7332
7715
|
var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
7333
7716
|
McpErrorCode.INSUFFICIENT_CREDITS,
|
|
7334
7717
|
McpErrorCode.TASK_QUOTA_EXCEEDED,
|
|
7718
|
+
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
7719
|
+
McpErrorCode.DROPSHIPPING_PROJECT_DISABLED,
|
|
7720
|
+
McpErrorCode.DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY,
|
|
7721
|
+
McpErrorCode.DROPSHIPPING_PROJECT_VERSION_CONFLICT,
|
|
7722
|
+
McpErrorCode.DROPSHIPPING_PROJECT_MEDIA_REQUIRED,
|
|
7723
|
+
McpErrorCode.KALODATA_NOT_CONFIGURED,
|
|
7724
|
+
McpErrorCode.META_AD_LIBRARY_NOT_CONFIGURED,
|
|
7725
|
+
McpErrorCode.PRODUCT_RESEARCH_DISABLED,
|
|
7335
7726
|
McpErrorCode.CREATIVE_VARIANT_DISPATCH_FAILED,
|
|
7336
7727
|
McpErrorCode.PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT,
|
|
7337
7728
|
// Shopify
|
|
@@ -7386,6 +7777,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
7386
7777
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
7387
7778
|
McpErrorCode.CAMPAIGN_NO_CREATIVES,
|
|
7388
7779
|
McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
|
|
7780
|
+
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
7389
7781
|
// Connections
|
|
7390
7782
|
McpErrorCode.NO_SHOPIFY_SHOPS,
|
|
7391
7783
|
McpErrorCode.NO_META_AD_ACCOUNTS,
|
|
@@ -7696,66 +8088,67 @@ function renderOutputsMarkdown(outputs) {
|
|
|
7696
8088
|
__name(renderOutputsMarkdown, "renderOutputsMarkdown");
|
|
7697
8089
|
|
|
7698
8090
|
// src/tools/tasks.ts
|
|
7699
|
-
var CreateProductTaskInput =
|
|
7700
|
-
images: ImagesInput,
|
|
7701
|
-
|
|
8091
|
+
var CreateProductTaskInput = z40.object({
|
|
8092
|
+
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
8093
|
+
projectId: z40.string().uuid().optional().describe("Opcional. Proyecto guiado propio. Permite continuar sin volver a subir la imagen guardada; nunca evita cr\xE9ditos, cuotas ni confirmaciones."),
|
|
8094
|
+
productUrl: z40.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."),
|
|
7702
8095
|
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.'),
|
|
7703
8096
|
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.'),
|
|
7704
|
-
price:
|
|
7705
|
-
compareAtPrice:
|
|
7706
|
-
offer:
|
|
7707
|
-
paymentMethods:
|
|
7708
|
-
productContext:
|
|
7709
|
-
productLabel:
|
|
7710
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla
|
|
7711
|
-
durationSeconds:
|
|
7712
|
-
|
|
7713
|
-
|
|
8097
|
+
price: z40.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.'),
|
|
8098
|
+
compareAtPrice: z40.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".'),
|
|
8099
|
+
offer: z40.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.'),
|
|
8100
|
+
paymentMethods: z40.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.'),
|
|
8101
|
+
productContext: z40.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."),
|
|
8102
|
+
productLabel: z40.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.'),
|
|
8103
|
+
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). Los presets funcionan a 15s y 30s. 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), "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.'),
|
|
8104
|
+
durationSeconds: z40.union([
|
|
8105
|
+
z40.literal(15),
|
|
8106
|
+
z40.literal(30)
|
|
7714
8107
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
7715
|
-
pauseForAngleReview:
|
|
8108
|
+
pauseForAngleReview: z40.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."),
|
|
7716
8109
|
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.'),
|
|
7717
8110
|
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 (~el doble de precio). Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
7718
|
-
multiAngleVideos:
|
|
7719
|
-
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "
|
|
7720
|
-
outputs:
|
|
8111
|
+
multiAngleVideos: z40.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."),
|
|
8112
|
+
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "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.'),
|
|
8113
|
+
outputs: z40.array(z40.enum([
|
|
7721
8114
|
"landing",
|
|
7722
8115
|
"video",
|
|
7723
8116
|
"image"
|
|
7724
8117
|
])).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.'),
|
|
7725
|
-
competitorScanEnabled:
|
|
7726
|
-
brandId:
|
|
7727
|
-
creativeDirection:
|
|
8118
|
+
competitorScanEnabled: z40.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."),
|
|
8119
|
+
brandId: z40.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."),
|
|
8120
|
+
creativeDirection: z40.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.'),
|
|
7728
8121
|
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".'),
|
|
7729
8122
|
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".')
|
|
7730
8123
|
}).strict();
|
|
7731
|
-
var GetTaskStatusInput =
|
|
7732
|
-
taskId:
|
|
7733
|
-
waitSeconds:
|
|
7734
|
-
});
|
|
7735
|
-
var ListTasksInput =
|
|
7736
|
-
limit:
|
|
7737
|
-
offset:
|
|
7738
|
-
search:
|
|
7739
|
-
});
|
|
7740
|
-
var EditTaskDraftInput =
|
|
7741
|
-
taskId:
|
|
7742
|
-
angleIndex:
|
|
7743
|
-
angle:
|
|
7744
|
-
angle:
|
|
7745
|
-
buyerPersona:
|
|
7746
|
-
actor:
|
|
7747
|
-
gender:
|
|
8124
|
+
var GetTaskStatusInput = z40.object({
|
|
8125
|
+
taskId: z40.string().min(1),
|
|
8126
|
+
waitSeconds: z40.number().int().min(0).max(120).optional()
|
|
8127
|
+
});
|
|
8128
|
+
var ListTasksInput = z40.object({
|
|
8129
|
+
limit: z40.number().int().min(1).max(50).optional(),
|
|
8130
|
+
offset: z40.number().int().min(0).optional(),
|
|
8131
|
+
search: z40.string().optional()
|
|
8132
|
+
});
|
|
8133
|
+
var EditTaskDraftInput = z40.object({
|
|
8134
|
+
taskId: z40.string().min(1),
|
|
8135
|
+
angleIndex: z40.number().int().min(0),
|
|
8136
|
+
angle: z40.object({
|
|
8137
|
+
angle: z40.string().min(1).max(480),
|
|
8138
|
+
buyerPersona: z40.string().min(1).max(360),
|
|
8139
|
+
actor: z40.string().min(1).max(360).optional(),
|
|
8140
|
+
gender: z40.enum([
|
|
7748
8141
|
"female",
|
|
7749
8142
|
"male"
|
|
7750
8143
|
]).optional(),
|
|
7751
|
-
scriptNotes:
|
|
8144
|
+
scriptNotes: z40.string().max(2e3).optional()
|
|
7752
8145
|
})
|
|
7753
8146
|
});
|
|
7754
|
-
var PendingActionPayload =
|
|
7755
|
-
|
|
7756
|
-
kind:
|
|
8147
|
+
var PendingActionPayload = z40.discriminatedUnion("kind", [
|
|
8148
|
+
z40.object({
|
|
8149
|
+
kind: z40.literal("product_reference_confirmation"),
|
|
7757
8150
|
userChoice: ProductReferenceUserChoiceEnum,
|
|
7758
|
-
confirmedProductNames:
|
|
8151
|
+
confirmedProductNames: z40.array(z40.string().min(1).max(120)).min(2).max(8).optional(),
|
|
7759
8152
|
// SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
|
|
7760
8153
|
// reachable via MCP. Valid ONLY together with userChoice='variants' (same
|
|
7761
8154
|
// product in several colors): renders one shot per color and stitches them,
|
|
@@ -7766,62 +8159,62 @@ var PendingActionPayload = z39.discriminatedUnion("kind", [
|
|
|
7766
8159
|
// safe because multi-scene IS the intended render for a color variant set,
|
|
7767
8160
|
// not a blind quality upsell. Maps to `videoTier: 'standard'` on the
|
|
7768
8161
|
// confirm call; the backend re-gates it (variants + variant_set only).
|
|
7769
|
-
useMultiSceneShowcase:
|
|
8162
|
+
useMultiSceneShowcase: z40.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".')
|
|
7770
8163
|
}),
|
|
7771
|
-
|
|
7772
|
-
kind:
|
|
8164
|
+
z40.object({
|
|
8165
|
+
kind: z40.literal("angle_review_approval"),
|
|
7773
8166
|
// All edits are optional — empty action body just approves the
|
|
7774
8167
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
7775
8168
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
7776
8169
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
7777
|
-
customAngle:
|
|
8170
|
+
customAngle: z40.string().min(1).max(480).optional(),
|
|
7778
8171
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
7779
8172
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
7780
|
-
painPoints:
|
|
7781
|
-
benefits:
|
|
7782
|
-
features:
|
|
7783
|
-
gapDurationSeconds:
|
|
7784
|
-
|
|
7785
|
-
|
|
8173
|
+
painPoints: z40.string().max(1500).optional(),
|
|
8174
|
+
benefits: z40.string().max(1500).optional(),
|
|
8175
|
+
features: z40.array(z40.string().min(1).max(300)).max(10).optional(),
|
|
8176
|
+
gapDurationSeconds: z40.union([
|
|
8177
|
+
z40.literal(15),
|
|
8178
|
+
z40.literal(30)
|
|
7786
8179
|
]).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.")
|
|
7787
8180
|
})
|
|
7788
8181
|
]);
|
|
7789
|
-
var ResolvePendingActionInput =
|
|
7790
|
-
taskId:
|
|
8182
|
+
var ResolvePendingActionInput = z40.object({
|
|
8183
|
+
taskId: z40.string().min(1),
|
|
7791
8184
|
action: PendingActionPayload
|
|
7792
8185
|
}).strict();
|
|
7793
8186
|
function resolveVariantConfirmVideoTier(action) {
|
|
7794
8187
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
7795
8188
|
}
|
|
7796
8189
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
7797
|
-
var StatusForResolveSchema =
|
|
8190
|
+
var StatusForResolveSchema = z40.object({
|
|
7798
8191
|
// Metadata used to select the backend resume contract. Older API responses
|
|
7799
8192
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
7800
|
-
kind:
|
|
8193
|
+
kind: z40.enum([
|
|
7801
8194
|
"autopilot",
|
|
7802
8195
|
"video",
|
|
7803
8196
|
"image",
|
|
7804
8197
|
"landing",
|
|
7805
8198
|
"mix"
|
|
7806
8199
|
]).optional(),
|
|
7807
|
-
selectedOutputs:
|
|
8200
|
+
selectedOutputs: z40.array(z40.enum([
|
|
7808
8201
|
"landing",
|
|
7809
8202
|
"video",
|
|
7810
8203
|
"image"
|
|
7811
8204
|
])).optional(),
|
|
7812
|
-
videoAngleCount:
|
|
7813
|
-
ugcFormat:
|
|
8205
|
+
videoAngleCount: z40.number().int().min(1).max(3).optional(),
|
|
8206
|
+
ugcFormat: z40.enum([
|
|
7814
8207
|
"single_8s",
|
|
7815
8208
|
"single_15s",
|
|
7816
8209
|
"double_30s"
|
|
7817
8210
|
]).optional(),
|
|
7818
|
-
videoStyle:
|
|
8211
|
+
videoStyle: z40.enum([
|
|
7819
8212
|
"ugc",
|
|
7820
8213
|
"cartoon_3d",
|
|
7821
8214
|
"product_only",
|
|
7822
8215
|
"ai_dynamic"
|
|
7823
8216
|
]).optional(),
|
|
7824
|
-
videoModel:
|
|
8217
|
+
videoModel: z40.enum([
|
|
7825
8218
|
"veo",
|
|
7826
8219
|
"wan",
|
|
7827
8220
|
"bytedance",
|
|
@@ -7829,26 +8222,26 @@ var StatusForResolveSchema = z39.object({
|
|
|
7829
8222
|
"grok",
|
|
7830
8223
|
"kling"
|
|
7831
8224
|
]).optional(),
|
|
7832
|
-
videoTier:
|
|
8225
|
+
videoTier: z40.enum([
|
|
7833
8226
|
"legacy",
|
|
7834
8227
|
"standard",
|
|
7835
8228
|
"pro",
|
|
7836
8229
|
"single_call"
|
|
7837
8230
|
]).optional(),
|
|
7838
|
-
videoResolution:
|
|
8231
|
+
videoResolution: z40.enum([
|
|
7839
8232
|
"480p",
|
|
7840
8233
|
"720p"
|
|
7841
8234
|
]).optional(),
|
|
7842
8235
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
7843
|
-
pendingUserAction:
|
|
7844
|
-
kind:
|
|
7845
|
-
candidateGrouping:
|
|
7846
|
-
selectedImageUrls:
|
|
7847
|
-
proposedProductNames:
|
|
7848
|
-
customAngleDraft:
|
|
7849
|
-
painPointsDraft:
|
|
7850
|
-
benefitsDraft:
|
|
7851
|
-
featuresDraft:
|
|
8236
|
+
pendingUserAction: z40.object({
|
|
8237
|
+
kind: z40.string(),
|
|
8238
|
+
candidateGrouping: z40.string().optional(),
|
|
8239
|
+
selectedImageUrls: z40.array(z40.string()).optional(),
|
|
8240
|
+
proposedProductNames: z40.array(z40.string()).optional(),
|
|
8241
|
+
customAngleDraft: z40.string().optional(),
|
|
8242
|
+
painPointsDraft: z40.string().optional(),
|
|
8243
|
+
benefitsDraft: z40.string().optional(),
|
|
8244
|
+
featuresDraft: z40.array(z40.string()).optional(),
|
|
7852
8245
|
// Recommendation consumed only when the caller explicitly sends
|
|
7853
8246
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
7854
8247
|
gapDurationChoice: GapDurationChoiceMirror.optional()
|
|
@@ -7889,11 +8282,14 @@ function resolveStatusTaskKind(status) {
|
|
|
7889
8282
|
}
|
|
7890
8283
|
__name(resolveStatusTaskKind, "resolveStatusTaskKind");
|
|
7891
8284
|
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http" } = {}) {
|
|
7892
|
-
server.tool("create_product_task",
|
|
8285
|
+
server.tool("create_product_task", "Crea una tarea de producto desde fotos o desde un proyecto guiado propio. Por defecto genera los 3 outputs (landing + video + image creatives) EN UN MISMO TASK. Devuelve un taskId.\n\nINPUTS REQUERIDOS: images (1-5 fotos del MISMO producto; la primera es la hero) O projectId si el proyecto ya tiene una imagen guardada; adem\xE1s language y country.\n\nANTES de invocar, PREG\xDANTALE al usuario por price, offer y paymentMethods si no los mencion\xF3 \u2014 son inputs de alto impacto en la landing y nunca debes asumirlos. Si hay descuento, pregunta tambi\xE9n compareAtPrice. NO defaultes country/language desde el contexto del chat: preg\xFAntale expl\xEDcitamente, incluso si est\xE1 en LATAM.\n\nSi env\xEDas projectId, debe ser el proyecto propio que el usuario acaba de costear; el backend resolver\xE1 la imagen privada y conservar\xE1 todos los controles de cr\xE9ditos/confirmaci\xF3n. Si el usuario adjunta images junto con projectId, esas fotos reemplazan la referencia solo para este task.\n\nANTES de invocar, DILE CLARAMENTE qu\xE9 outputs vas a generar y que `create_product_task` los genera juntos en un mismo task.\n\nUsa SOLO valores declarados en los enums.", CreateProductTaskInput.shape, async (input) => {
|
|
7893
8286
|
try {
|
|
7894
|
-
|
|
8287
|
+
if (!input.images && !input.projectId) {
|
|
8288
|
+
throw new Error("images es requerido salvo que env\xEDes projectId.");
|
|
8289
|
+
}
|
|
8290
|
+
const imgs = input.images ? await resolveImages(input.images, {
|
|
7895
8291
|
transport
|
|
7896
|
-
});
|
|
8292
|
+
}) : [];
|
|
7897
8293
|
const parts = imgs.map((img, i) => ({
|
|
7898
8294
|
...img,
|
|
7899
8295
|
filename: `image-${i}.png`
|
|
@@ -7904,6 +8300,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
7904
8300
|
const fields = flatten({
|
|
7905
8301
|
"options.languageCode": input.language,
|
|
7906
8302
|
"options.country": input.country,
|
|
8303
|
+
"options.dropshippingProjectId": input.projectId,
|
|
7907
8304
|
"options.price": input.price,
|
|
7908
8305
|
"options.compareAtPrice": input.compareAtPrice,
|
|
7909
8306
|
"options.offer": input.offer,
|
|
@@ -8170,54 +8567,54 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
8170
8567
|
|
|
8171
8568
|
// src/tools/creatives.ts
|
|
8172
8569
|
import { randomUUID } from "crypto";
|
|
8173
|
-
import { z as
|
|
8570
|
+
import { z as z41 } from "zod";
|
|
8174
8571
|
var CreativeRefs = {
|
|
8175
8572
|
images: ImagesInput,
|
|
8176
8573
|
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.'),
|
|
8177
8574
|
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.'),
|
|
8178
|
-
price:
|
|
8179
|
-
offer:
|
|
8180
|
-
compareAtPrice:
|
|
8181
|
-
paymentMethods:
|
|
8182
|
-
productContext:
|
|
8183
|
-
productLabel:
|
|
8184
|
-
buyerPersona:
|
|
8185
|
-
isCombo:
|
|
8186
|
-
competitorScanEnabled:
|
|
8187
|
-
brandId:
|
|
8188
|
-
creativeDirection:
|
|
8575
|
+
price: z41.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.'),
|
|
8576
|
+
offer: z41.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.'),
|
|
8577
|
+
compareAtPrice: z41.string().min(1).max(120).optional().describe('Opcional. Precio anterior o de referencia para mostrar descuento. Ej. "$129.000" cuando price="$89.900".'),
|
|
8578
|
+
paymentMethods: z41.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.'),
|
|
8579
|
+
productContext: z41.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."),
|
|
8580
|
+
productLabel: z41.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.'),
|
|
8581
|
+
buyerPersona: z41.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.'),
|
|
8582
|
+
isCombo: z41.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
8583
|
+
competitorScanEnabled: z41.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."),
|
|
8584
|
+
brandId: z41.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."),
|
|
8585
|
+
creativeDirection: z41.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.')
|
|
8189
8586
|
};
|
|
8190
|
-
var VideoInput =
|
|
8587
|
+
var VideoInput = z41.object({
|
|
8191
8588
|
images: CreativeRefs.images,
|
|
8192
|
-
title:
|
|
8193
|
-
primaryAngle:
|
|
8589
|
+
title: z41.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
8590
|
+
primaryAngle: z41.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".'),
|
|
8194
8591
|
language: CreativeRefs.language,
|
|
8195
8592
|
country: CreativeRefs.country,
|
|
8196
|
-
aspectRatio:
|
|
8593
|
+
aspectRatio: z41.enum([
|
|
8197
8594
|
"9:16",
|
|
8198
8595
|
"16:9",
|
|
8199
8596
|
"Auto"
|
|
8200
8597
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
8201
|
-
durationSeconds:
|
|
8202
|
-
|
|
8203
|
-
|
|
8598
|
+
durationSeconds: z41.union([
|
|
8599
|
+
z41.literal(15),
|
|
8600
|
+
z41.literal(30)
|
|
8204
8601
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8205
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla
|
|
8602
|
+
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). Los presets funcionan a 15s y 30s. 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), "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).'),
|
|
8206
8603
|
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.'),
|
|
8207
8604
|
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "720p" = m\xE1xima nitidez (RECOMENDADO, default si se omite); "480p" = render m\xE1s econ\xF3mico. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 720p).'),
|
|
8208
|
-
features:
|
|
8605
|
+
features: z41.array(z41.string()).optional().describe('Opcional. Lista de features/beneficios clave a mencionar. Ej. ["resistente al agua", "bater\xEDa 24h", "carga inal\xE1mbrica"].'),
|
|
8209
8606
|
price: CreativeRefs.price,
|
|
8210
8607
|
offer: CreativeRefs.offer,
|
|
8211
8608
|
productContext: CreativeRefs.productContext,
|
|
8212
8609
|
productLabel: CreativeRefs.productLabel,
|
|
8213
|
-
cta:
|
|
8214
|
-
scriptNotes:
|
|
8215
|
-
pauseForVideoScriptReview:
|
|
8216
|
-
pauseForAngleReview:
|
|
8610
|
+
cta: z41.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.'),
|
|
8611
|
+
scriptNotes: z41.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.'),
|
|
8612
|
+
pauseForVideoScriptReview: z41.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."),
|
|
8613
|
+
pauseForAngleReview: z41.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."),
|
|
8217
8614
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8218
8615
|
brandId: CreativeRefs.brandId
|
|
8219
8616
|
}).strict();
|
|
8220
|
-
var FreeVideoQualityEnum =
|
|
8617
|
+
var FreeVideoQualityEnum = z41.enum([
|
|
8221
8618
|
"economical",
|
|
8222
8619
|
"high_detail"
|
|
8223
8620
|
]);
|
|
@@ -8239,38 +8636,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
8239
8636
|
15
|
|
8240
8637
|
]
|
|
8241
8638
|
};
|
|
8242
|
-
var FreeVideoInput =
|
|
8639
|
+
var FreeVideoInput = z41.object({
|
|
8243
8640
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
8244
|
-
rawPrompt:
|
|
8641
|
+
rawPrompt: z41.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."),
|
|
8245
8642
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
|
|
8246
|
-
durationSeconds:
|
|
8643
|
+
durationSeconds: z41.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."),
|
|
8247
8644
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
8248
|
-
generateAiMusic:
|
|
8249
|
-
addSubtitles:
|
|
8250
|
-
idempotencyKey:
|
|
8645
|
+
generateAiMusic: z41.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
8646
|
+
addSubtitles: z41.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
8647
|
+
idempotencyKey: z41.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.")
|
|
8251
8648
|
}).strict();
|
|
8252
8649
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
8253
8650
|
var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
|
|
8254
8651
|
var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
|
|
8255
8652
|
var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
|
|
8256
|
-
var ImageInput =
|
|
8653
|
+
var ImageInput = z41.object({
|
|
8257
8654
|
images: CreativeRefs.images,
|
|
8258
|
-
productTitle:
|
|
8259
|
-
primaryAngle:
|
|
8655
|
+
productTitle: z41.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
8656
|
+
primaryAngle: z41.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
|
|
8260
8657
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
8261
8658
|
language: CreativeRefs.language,
|
|
8262
8659
|
country: CreativeRefs.country,
|
|
8263
|
-
nVariants:
|
|
8264
|
-
imageModel:
|
|
8660
|
+
nVariants: z41.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
|
|
8661
|
+
imageModel: z41.string().optional().describe('Opcional. Modelo de imagen. Ej. "gpt-image-2", "nano-banana-2". Om\xEDtelo para usar el default optimizado por costo/calidad.'),
|
|
8265
8662
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
8266
8663
|
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).`),
|
|
8267
8664
|
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.`),
|
|
8268
|
-
styleMix:
|
|
8665
|
+
styleMix: z41.boolean().optional().describe("Opcional. Si true, las N variantes mezclan distintos imageStyle para A/B test. Si false/omitido, todas comparten estilo. Default false."),
|
|
8269
8666
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
|
|
8270
|
-
generateAdCopy:
|
|
8271
|
-
pauseForAngleReview:
|
|
8272
|
-
features:
|
|
8273
|
-
brandColors:
|
|
8667
|
+
generateAdCopy: z41.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
|
|
8668
|
+
pauseForAngleReview: z41.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."),
|
|
8669
|
+
features: z41.array(z41.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
8670
|
+
brandColors: z41.array(z41.string()).optional().describe('Opcional. Paleta de marca en hex. Ej. ["#FF6B35", "#004E89"]. Si se omite, la IA elige seg\xFAn el producto.'),
|
|
8274
8671
|
price: CreativeRefs.price,
|
|
8275
8672
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
8276
8673
|
offer: CreativeRefs.offer,
|
|
@@ -8281,11 +8678,11 @@ var ImageInput = z40.object({
|
|
|
8281
8678
|
brandId: CreativeRefs.brandId,
|
|
8282
8679
|
creativeDirection: CreativeRefs.creativeDirection
|
|
8283
8680
|
});
|
|
8284
|
-
var LandingInput =
|
|
8681
|
+
var LandingInput = z41.object({
|
|
8285
8682
|
images: CreativeRefs.images,
|
|
8286
8683
|
language: CreativeRefs.language,
|
|
8287
8684
|
country: CreativeRefs.country,
|
|
8288
|
-
salesAngle:
|
|
8685
|
+
salesAngle: z41.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.'),
|
|
8289
8686
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
8290
8687
|
price: CreativeRefs.price,
|
|
8291
8688
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -8383,8 +8780,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8383
8780
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
8384
8781
|
|
|
8385
8782
|
// src/tools/creative-variants.ts
|
|
8386
|
-
import { z as
|
|
8387
|
-
var LandingSectionKeyEnum =
|
|
8783
|
+
import { z as z42 } from "zod";
|
|
8784
|
+
var LandingSectionKeyEnum = z42.enum([
|
|
8388
8785
|
"problem_hook",
|
|
8389
8786
|
"problem_cost",
|
|
8390
8787
|
"solution_mechanism",
|
|
@@ -8424,24 +8821,24 @@ var LandingSectionKeyEnum = z41.enum([
|
|
|
8424
8821
|
"lifestyle_fit",
|
|
8425
8822
|
"join_lifestyle"
|
|
8426
8823
|
]);
|
|
8427
|
-
var CreativeVariantKindEnum =
|
|
8824
|
+
var CreativeVariantKindEnum = z42.enum([
|
|
8428
8825
|
"video",
|
|
8429
8826
|
"image",
|
|
8430
8827
|
"landing"
|
|
8431
8828
|
]);
|
|
8432
|
-
var EstimateCreativeVariantInputBase =
|
|
8433
|
-
sourceTaskId:
|
|
8829
|
+
var EstimateCreativeVariantInputBase = z42.object({
|
|
8830
|
+
sourceTaskId: z42.string().uuid().describe("ID de la tarea original completada."),
|
|
8434
8831
|
kind: CreativeVariantKindEnum,
|
|
8435
8832
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
8436
8833
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
8437
|
-
nVariants:
|
|
8834
|
+
nVariants: z42.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
8438
8835
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
8439
|
-
instructions:
|
|
8836
|
+
instructions: z42.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.")
|
|
8440
8837
|
}).strict();
|
|
8441
8838
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
8442
8839
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
8443
8840
|
ctx.addIssue({
|
|
8444
|
-
code:
|
|
8841
|
+
code: z42.ZodIssueCode.custom,
|
|
8445
8842
|
path: [
|
|
8446
8843
|
"nVariants"
|
|
8447
8844
|
],
|
|
@@ -8451,7 +8848,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8451
8848
|
if (input.kind !== "video") {
|
|
8452
8849
|
if (input.videoPreset !== void 0) {
|
|
8453
8850
|
ctx.addIssue({
|
|
8454
|
-
code:
|
|
8851
|
+
code: z42.ZodIssueCode.custom,
|
|
8455
8852
|
path: [
|
|
8456
8853
|
"videoPreset"
|
|
8457
8854
|
],
|
|
@@ -8460,7 +8857,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8460
8857
|
}
|
|
8461
8858
|
if (input.videoResolution !== void 0) {
|
|
8462
8859
|
ctx.addIssue({
|
|
8463
|
-
code:
|
|
8860
|
+
code: z42.ZodIssueCode.custom,
|
|
8464
8861
|
path: [
|
|
8465
8862
|
"videoResolution"
|
|
8466
8863
|
],
|
|
@@ -8470,7 +8867,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8470
8867
|
}
|
|
8471
8868
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
8472
8869
|
ctx.addIssue({
|
|
8473
|
-
code:
|
|
8870
|
+
code: z42.ZodIssueCode.custom,
|
|
8474
8871
|
path: [
|
|
8475
8872
|
"nVariants"
|
|
8476
8873
|
],
|
|
@@ -8480,7 +8877,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8480
8877
|
if (input.kind !== "landing") {
|
|
8481
8878
|
if (input.sectionKey !== void 0) {
|
|
8482
8879
|
ctx.addIssue({
|
|
8483
|
-
code:
|
|
8880
|
+
code: z42.ZodIssueCode.custom,
|
|
8484
8881
|
path: [
|
|
8485
8882
|
"sectionKey"
|
|
8486
8883
|
],
|
|
@@ -8489,7 +8886,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8489
8886
|
}
|
|
8490
8887
|
if (input.instructions !== void 0) {
|
|
8491
8888
|
ctx.addIssue({
|
|
8492
|
-
code:
|
|
8889
|
+
code: z42.ZodIssueCode.custom,
|
|
8493
8890
|
path: [
|
|
8494
8891
|
"instructions"
|
|
8495
8892
|
],
|
|
@@ -8498,31 +8895,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8498
8895
|
}
|
|
8499
8896
|
}
|
|
8500
8897
|
});
|
|
8501
|
-
var CreateCreativeVariantInputBase =
|
|
8502
|
-
sourceTaskId:
|
|
8898
|
+
var CreateCreativeVariantInputBase = z42.object({
|
|
8899
|
+
sourceTaskId: z42.string().uuid().describe("ID de la tarea original completada."),
|
|
8503
8900
|
kind: CreativeVariantKindEnum,
|
|
8504
|
-
confirm:
|
|
8505
|
-
clientRequestId:
|
|
8506
|
-
angle:
|
|
8507
|
-
buyerPersona:
|
|
8508
|
-
scriptNotes:
|
|
8509
|
-
creativeDirection:
|
|
8901
|
+
confirm: z42.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
8902
|
+
clientRequestId: z42.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."),
|
|
8903
|
+
angle: z42.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
8904
|
+
buyerPersona: z42.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
8905
|
+
scriptNotes: z42.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
8906
|
+
creativeDirection: z42.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
8510
8907
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
8511
8908
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
8512
|
-
generateAiMusic:
|
|
8513
|
-
nVariants:
|
|
8909
|
+
generateAiMusic: z42.boolean().optional().describe("Opcional para video."),
|
|
8910
|
+
nVariants: z42.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
8514
8911
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
8515
8912
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
8516
8913
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
8517
8914
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
8518
|
-
styleMix:
|
|
8915
|
+
styleMix: z42.boolean().optional().describe("Opcional para imagen."),
|
|
8519
8916
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
8520
|
-
instructions:
|
|
8917
|
+
instructions: z42.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.")
|
|
8521
8918
|
}).strict();
|
|
8522
8919
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
8523
8920
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
8524
8921
|
ctx.addIssue({
|
|
8525
|
-
code:
|
|
8922
|
+
code: z42.ZodIssueCode.custom,
|
|
8526
8923
|
path: [
|
|
8527
8924
|
"angle"
|
|
8528
8925
|
],
|
|
@@ -8531,7 +8928,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
8531
8928
|
}
|
|
8532
8929
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
8533
8930
|
ctx.addIssue({
|
|
8534
|
-
code:
|
|
8931
|
+
code: z42.ZodIssueCode.custom,
|
|
8535
8932
|
path: [
|
|
8536
8933
|
"instructions"
|
|
8537
8934
|
],
|
|
@@ -8577,7 +8974,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
8577
8974
|
for (const field of fieldsByKind[input.kind]) {
|
|
8578
8975
|
if (input[field] !== void 0) {
|
|
8579
8976
|
ctx.addIssue({
|
|
8580
|
-
code:
|
|
8977
|
+
code: z42.ZodIssueCode.custom,
|
|
8581
8978
|
path: [
|
|
8582
8979
|
field
|
|
8583
8980
|
],
|
|
@@ -8694,27 +9091,27 @@ function registerCreativeVariantTools(server, api) {
|
|
|
8694
9091
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
8695
9092
|
|
|
8696
9093
|
// src/tools/script-review.ts
|
|
8697
|
-
import { z as
|
|
8698
|
-
var GetVideoScriptInput =
|
|
8699
|
-
taskId:
|
|
8700
|
-
angleKey:
|
|
9094
|
+
import { z as z43 } from "zod";
|
|
9095
|
+
var GetVideoScriptInput = z43.object({
|
|
9096
|
+
taskId: z43.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
9097
|
+
angleKey: z43.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.')
|
|
8701
9098
|
}).strict();
|
|
8702
9099
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
8703
9100
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
8704
|
-
var ApproveSceneEdit =
|
|
8705
|
-
index:
|
|
8706
|
-
dialogue:
|
|
9101
|
+
var ApproveSceneEdit = z43.object({
|
|
9102
|
+
index: z43.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
9103
|
+
dialogue: z43.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
8707
9104
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
8708
9105
|
}).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.")
|
|
8709
9106
|
}).strict();
|
|
8710
|
-
var ApproveVideoScriptInput =
|
|
8711
|
-
taskId:
|
|
8712
|
-
angleKey:
|
|
8713
|
-
scenes:
|
|
9107
|
+
var ApproveVideoScriptInput = z43.object({
|
|
9108
|
+
taskId: z43.string().min(1).describe("ID de la tarea."),
|
|
9109
|
+
angleKey: z43.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.'),
|
|
9110
|
+
scenes: z43.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.")
|
|
8714
9111
|
}).strict();
|
|
8715
|
-
var RegenerateVideoScriptInput =
|
|
8716
|
-
taskId:
|
|
8717
|
-
angleKey:
|
|
9112
|
+
var RegenerateVideoScriptInput = z43.object({
|
|
9113
|
+
taskId: z43.string().min(1).describe("ID de la tarea."),
|
|
9114
|
+
angleKey: z43.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.'),
|
|
8718
9115
|
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).')
|
|
8719
9116
|
}).strict();
|
|
8720
9117
|
function registerScriptReviewTools(server, api) {
|
|
@@ -8754,9 +9151,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
8754
9151
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
8755
9152
|
|
|
8756
9153
|
// src/tools/connections.ts
|
|
8757
|
-
import { z as
|
|
9154
|
+
import { z as z44 } from "zod";
|
|
8758
9155
|
function registerConnectionTools(server, api) {
|
|
8759
|
-
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.",
|
|
9156
|
+
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.", z44.object({}).shape, async () => {
|
|
8760
9157
|
try {
|
|
8761
9158
|
const r = await api.getJson("/v1/shopify/shops");
|
|
8762
9159
|
return asText(r);
|
|
@@ -8764,10 +9161,10 @@ function registerConnectionTools(server, api) {
|
|
|
8764
9161
|
throw translateError(e);
|
|
8765
9162
|
}
|
|
8766
9163
|
});
|
|
8767
|
-
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.',
|
|
8768
|
-
shopDomain:
|
|
8769
|
-
query:
|
|
8770
|
-
taskId:
|
|
9164
|
+
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.', z44.object({
|
|
9165
|
+
shopDomain: z44.string().min(3).max(120),
|
|
9166
|
+
query: z44.string().trim().max(120).optional(),
|
|
9167
|
+
taskId: z44.string().uuid().optional()
|
|
8771
9168
|
}).shape, async ({ shopDomain, query, taskId }) => {
|
|
8772
9169
|
try {
|
|
8773
9170
|
const params = new URLSearchParams({
|
|
@@ -8781,7 +9178,7 @@ function registerConnectionTools(server, api) {
|
|
|
8781
9178
|
throw translateError(e);
|
|
8782
9179
|
}
|
|
8783
9180
|
});
|
|
8784
|
-
server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.",
|
|
9181
|
+
server.tool("list_meta_ad_accounts", "Lista las cuentas publicitarias de Meta conectadas. Si est\xE1 vac\xEDa, ind\xEDcale al usuario conectar Meta en productmaker.app/integrations.", z44.object({}).shape, async () => {
|
|
8785
9182
|
try {
|
|
8786
9183
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
8787
9184
|
return asText(r);
|
|
@@ -8789,7 +9186,7 @@ function registerConnectionTools(server, api) {
|
|
|
8789
9186
|
throw translateError(e);
|
|
8790
9187
|
}
|
|
8791
9188
|
});
|
|
8792
|
-
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.",
|
|
9189
|
+
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.", z44.object({}).shape, async () => {
|
|
8793
9190
|
try {
|
|
8794
9191
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
8795
9192
|
return asText(r);
|
|
@@ -8801,105 +9198,105 @@ function registerConnectionTools(server, api) {
|
|
|
8801
9198
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
8802
9199
|
|
|
8803
9200
|
// src/tools/publish.ts
|
|
8804
|
-
import { z as
|
|
8805
|
-
var ShopifyInput =
|
|
8806
|
-
taskId:
|
|
8807
|
-
shopDomain:
|
|
9201
|
+
import { z as z45 } from "zod";
|
|
9202
|
+
var ShopifyInput = z45.object({
|
|
9203
|
+
taskId: z45.string().min(1),
|
|
9204
|
+
shopDomain: z45.string().min(1),
|
|
8808
9205
|
/** Override: number of landing images to include. Default = ALL images the
|
|
8809
9206
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
8810
9207
|
* generously here; the backend validates each index against
|
|
8811
9208
|
* landing.images.length and rejects out-of-range. */
|
|
8812
|
-
numLandingImages:
|
|
8813
|
-
variantIndex:
|
|
9209
|
+
numLandingImages: z45.number().int().min(1).max(20).optional(),
|
|
9210
|
+
variantIndex: z45.number().int().min(0).optional(),
|
|
8814
9211
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
8815
9212
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
8816
9213
|
* a single-option product page. Defaults to false. */
|
|
8817
|
-
showVariantPicker:
|
|
9214
|
+
showVariantPicker: z45.boolean().optional(),
|
|
8818
9215
|
/** Default `auto` updates the product previously published for this task and
|
|
8819
9216
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
8820
9217
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
8821
|
-
publicationMode:
|
|
9218
|
+
publicationMode: z45.enum([
|
|
8822
9219
|
"auto",
|
|
8823
9220
|
"existing",
|
|
8824
9221
|
"new"
|
|
8825
9222
|
]).optional(),
|
|
8826
9223
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
8827
9224
|
* publicationMode is `existing`. */
|
|
8828
|
-
targetProductId:
|
|
9225
|
+
targetProductId: z45.string().trim().min(1).max(300).optional()
|
|
8829
9226
|
});
|
|
8830
|
-
var McpCampaignConfig =
|
|
9227
|
+
var McpCampaignConfig = z45.object({
|
|
8831
9228
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
8832
9229
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
8833
9230
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
8834
|
-
dailyBudgetUsd:
|
|
9231
|
+
dailyBudgetUsd: z45.number().positive().optional(),
|
|
8835
9232
|
/** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
|
|
8836
9233
|
* ad set). TikTok takes only the first entry. */
|
|
8837
|
-
targetCountries:
|
|
8838
|
-
campaignName:
|
|
9234
|
+
targetCountries: z45.array(z45.string().length(2)).max(1).optional(),
|
|
9235
|
+
campaignName: z45.string().trim().min(1).max(100).optional()
|
|
8839
9236
|
});
|
|
8840
9237
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
8841
|
-
var MetaInput =
|
|
8842
|
-
taskId:
|
|
9238
|
+
var MetaInput = z45.object({
|
|
9239
|
+
taskId: z45.string().min(1),
|
|
8843
9240
|
adAccountId: McpAdAccountId,
|
|
8844
|
-
pixelId:
|
|
8845
|
-
landingUrl:
|
|
9241
|
+
pixelId: z45.string().min(1).optional(),
|
|
9242
|
+
landingUrl: z45.string().url().optional(),
|
|
8846
9243
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
8847
9244
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
8848
|
-
angleIndexes:
|
|
9245
|
+
angleIndexes: z45.array(z45.number().int().nonnegative()).optional(),
|
|
8849
9246
|
campaignConfig: McpCampaignConfig.optional(),
|
|
8850
9247
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
8851
9248
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
8852
9249
|
* (Meta's primary-text limit). */
|
|
8853
|
-
primaryText:
|
|
9250
|
+
primaryText: z45.string().trim().min(1).max(500).optional(),
|
|
8854
9251
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
8855
9252
|
* (wa.me) instead of a landing page. */
|
|
8856
|
-
phoneNumber:
|
|
9253
|
+
phoneNumber: z45.string().min(8).max(32).optional()
|
|
8857
9254
|
});
|
|
8858
|
-
var GroupedTaskSource =
|
|
8859
|
-
type:
|
|
8860
|
-
taskId:
|
|
8861
|
-
angleIndex:
|
|
8862
|
-
videoVariant:
|
|
9255
|
+
var GroupedTaskSource = z45.object({
|
|
9256
|
+
type: z45.literal("task"),
|
|
9257
|
+
taskId: z45.string().min(1),
|
|
9258
|
+
angleIndex: z45.number().int().min(0).optional(),
|
|
9259
|
+
videoVariant: z45.enum([
|
|
8863
9260
|
"with_subtitles",
|
|
8864
9261
|
"without_subtitles"
|
|
8865
9262
|
]).optional(),
|
|
8866
|
-
imageVariantIndex:
|
|
8867
|
-
});
|
|
8868
|
-
var GroupedMediaSource =
|
|
8869
|
-
type:
|
|
8870
|
-
url:
|
|
8871
|
-
path:
|
|
8872
|
-
thumbnailUrl:
|
|
8873
|
-
thumbnailPath:
|
|
9263
|
+
imageVariantIndex: z45.number().int().min(0).optional()
|
|
9264
|
+
});
|
|
9265
|
+
var GroupedMediaSource = z45.object({
|
|
9266
|
+
type: z45.literal("media"),
|
|
9267
|
+
url: z45.string().url().optional(),
|
|
9268
|
+
path: z45.string().min(1).optional(),
|
|
9269
|
+
thumbnailUrl: z45.string().url().optional(),
|
|
9270
|
+
thumbnailPath: z45.string().min(1).optional()
|
|
8874
9271
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
8875
9272
|
message: "media source needs exactly one of `url` or `path`"
|
|
8876
9273
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
8877
9274
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
8878
9275
|
});
|
|
8879
|
-
var GroupedCreative =
|
|
8880
|
-
type:
|
|
9276
|
+
var GroupedCreative = z45.object({
|
|
9277
|
+
type: z45.enum([
|
|
8881
9278
|
"image",
|
|
8882
9279
|
"video"
|
|
8883
9280
|
]),
|
|
8884
|
-
source:
|
|
9281
|
+
source: z45.union([
|
|
8885
9282
|
GroupedTaskSource,
|
|
8886
9283
|
GroupedMediaSource
|
|
8887
9284
|
]),
|
|
8888
|
-
title:
|
|
8889
|
-
description:
|
|
9285
|
+
title: z45.string().max(120).optional(),
|
|
9286
|
+
description: z45.string().max(500).optional(),
|
|
8890
9287
|
cta: MetaCtaType.optional(),
|
|
8891
|
-
creativeId:
|
|
9288
|
+
creativeId: z45.string().min(1).optional()
|
|
8892
9289
|
});
|
|
8893
|
-
var GroupedCampaignConfig =
|
|
9290
|
+
var GroupedCampaignConfig = z45.object({
|
|
8894
9291
|
campaignType: MetaCampaignType.default("sales"),
|
|
8895
9292
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
8896
9293
|
budgetMode: MetaBudgetMode.default("campaign"),
|
|
8897
|
-
campaignDailyBudget:
|
|
8898
|
-
adSets:
|
|
8899
|
-
tempId:
|
|
8900
|
-
name:
|
|
8901
|
-
dailyBudget:
|
|
8902
|
-
creativeIds:
|
|
9294
|
+
campaignDailyBudget: z45.number().int().positive().optional(),
|
|
9295
|
+
adSets: z45.array(z45.object({
|
|
9296
|
+
tempId: z45.string().min(1).max(80),
|
|
9297
|
+
name: z45.string().min(1).max(100),
|
|
9298
|
+
dailyBudget: z45.number().int().positive().optional(),
|
|
9299
|
+
creativeIds: z45.array(z45.string().min(1)).min(1)
|
|
8903
9300
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
8904
9301
|
/**
|
|
8905
9302
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -8907,22 +9304,22 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8907
9304
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
8908
9305
|
* the API since #849 — unreachable from this tool.
|
|
8909
9306
|
*/
|
|
8910
|
-
destination:
|
|
8911
|
-
|
|
8912
|
-
type:
|
|
8913
|
-
landingUrl:
|
|
9307
|
+
destination: z45.discriminatedUnion("type", [
|
|
9308
|
+
z45.object({
|
|
9309
|
+
type: z45.literal("landing"),
|
|
9310
|
+
landingUrl: z45.string().url()
|
|
8914
9311
|
}),
|
|
8915
|
-
|
|
8916
|
-
type:
|
|
8917
|
-
phoneNumber:
|
|
9312
|
+
z45.object({
|
|
9313
|
+
type: z45.literal("whatsapp"),
|
|
9314
|
+
phoneNumber: z45.string().min(8).max(32)
|
|
8918
9315
|
})
|
|
8919
9316
|
]),
|
|
8920
|
-
saveAsDefault:
|
|
9317
|
+
saveAsDefault: z45.boolean().default(false),
|
|
8921
9318
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
8922
9319
|
}).superRefine((value, ctx) => {
|
|
8923
9320
|
if (value.budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
8924
9321
|
ctx.addIssue({
|
|
8925
|
-
code:
|
|
9322
|
+
code: z45.ZodIssueCode.custom,
|
|
8926
9323
|
path: [
|
|
8927
9324
|
"campaignDailyBudget"
|
|
8928
9325
|
],
|
|
@@ -8933,7 +9330,7 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8933
9330
|
value.adSets.forEach((adSet, index) => {
|
|
8934
9331
|
if (adSet.dailyBudget === void 0) {
|
|
8935
9332
|
ctx.addIssue({
|
|
8936
|
-
code:
|
|
9333
|
+
code: z45.ZodIssueCode.custom,
|
|
8937
9334
|
path: [
|
|
8938
9335
|
"adSets",
|
|
8939
9336
|
index,
|
|
@@ -8945,22 +9342,22 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8945
9342
|
});
|
|
8946
9343
|
}
|
|
8947
9344
|
});
|
|
8948
|
-
var PublishCreativesToMetaInputBase =
|
|
8949
|
-
creatives:
|
|
9345
|
+
var PublishCreativesToMetaInputBase = z45.object({
|
|
9346
|
+
creatives: z45.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
8950
9347
|
adAccountId: McpAdAccountId,
|
|
8951
|
-
pixelId:
|
|
9348
|
+
pixelId: z45.string().min(1).optional(),
|
|
8952
9349
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
8953
9350
|
* superRefine below. Mirrors the API's `UploadToMetaRequest`. */
|
|
8954
|
-
landingUrl:
|
|
8955
|
-
targetCountry:
|
|
8956
|
-
campaignName:
|
|
9351
|
+
landingUrl: z45.string().url().optional(),
|
|
9352
|
+
targetCountry: z45.string().length(2),
|
|
9353
|
+
campaignName: z45.string().trim().min(1).max(100),
|
|
8957
9354
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
8958
9355
|
});
|
|
8959
9356
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
8960
9357
|
const destination = value.campaignConfig?.destination;
|
|
8961
9358
|
if (destination?.type !== "whatsapp" && !value.landingUrl) {
|
|
8962
9359
|
ctx.addIssue({
|
|
8963
|
-
code:
|
|
9360
|
+
code: z45.ZodIssueCode.custom,
|
|
8964
9361
|
path: [
|
|
8965
9362
|
"landingUrl"
|
|
8966
9363
|
],
|
|
@@ -8969,7 +9366,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
8969
9366
|
}
|
|
8970
9367
|
if (destination?.type === "landing" && destination.landingUrl !== value.landingUrl) {
|
|
8971
9368
|
ctx.addIssue({
|
|
8972
|
-
code:
|
|
9369
|
+
code: z45.ZodIssueCode.custom,
|
|
8973
9370
|
path: [
|
|
8974
9371
|
"campaignConfig",
|
|
8975
9372
|
"destination",
|
|
@@ -8979,12 +9376,12 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
8979
9376
|
});
|
|
8980
9377
|
}
|
|
8981
9378
|
});
|
|
8982
|
-
var PresignUploadResponseSchema =
|
|
8983
|
-
uploadUrl:
|
|
9379
|
+
var PresignUploadResponseSchema = z45.object({
|
|
9380
|
+
uploadUrl: z45.string().url().refine((value) => {
|
|
8984
9381
|
const url = new URL(value);
|
|
8985
9382
|
return !url.username && !url.password && url.protocol === "https:";
|
|
8986
9383
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
8987
|
-
publicUrl:
|
|
9384
|
+
publicUrl: z45.string().url().refine((value) => {
|
|
8988
9385
|
const url = new URL(value);
|
|
8989
9386
|
return !url.username && !url.password;
|
|
8990
9387
|
}, "public media URL must not contain embedded credentials")
|
|
@@ -9009,16 +9406,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, transport) {
|
|
|
9009
9406
|
return uploadResolvedMedia(api, media);
|
|
9010
9407
|
}
|
|
9011
9408
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
9012
|
-
var TikTokInput =
|
|
9013
|
-
taskId:
|
|
9014
|
-
advertiserId:
|
|
9015
|
-
pixelId:
|
|
9016
|
-
landingUrl:
|
|
9017
|
-
angleIndexes:
|
|
9409
|
+
var TikTokInput = z45.object({
|
|
9410
|
+
taskId: z45.string().min(1),
|
|
9411
|
+
advertiserId: z45.string().min(1),
|
|
9412
|
+
pixelId: z45.string().min(1).optional(),
|
|
9413
|
+
landingUrl: z45.string().url().optional(),
|
|
9414
|
+
angleIndexes: z45.array(z45.number().int().nonnegative()).optional(),
|
|
9018
9415
|
campaignConfig: McpCampaignConfig.optional(),
|
|
9019
9416
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
9020
9417
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
9021
|
-
primaryText:
|
|
9418
|
+
primaryText: z45.string().trim().min(1).max(500).optional()
|
|
9022
9419
|
});
|
|
9023
9420
|
function registerPublishTools(server, api, opts = {}) {
|
|
9024
9421
|
const transport = opts.transport ?? "http";
|
|
@@ -9229,13 +9626,13 @@ function toTikTokCampaignConfig(cfg) {
|
|
|
9229
9626
|
__name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
9230
9627
|
|
|
9231
9628
|
// src/tools/campaigns.ts
|
|
9232
|
-
import { z as
|
|
9233
|
-
var MetaStatusInput =
|
|
9234
|
-
campaignId:
|
|
9629
|
+
import { z as z46 } from "zod";
|
|
9630
|
+
var MetaStatusInput = z46.object({
|
|
9631
|
+
campaignId: z46.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
9235
9632
|
});
|
|
9236
|
-
var TikTokStatusInput =
|
|
9237
|
-
campaignId:
|
|
9238
|
-
advertiserId:
|
|
9633
|
+
var TikTokStatusInput = z46.object({
|
|
9634
|
+
campaignId: z46.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
9635
|
+
advertiserId: z46.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
9239
9636
|
});
|
|
9240
9637
|
function registerCampaignTools(server, api) {
|
|
9241
9638
|
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) => {
|
|
@@ -9332,10 +9729,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
9332
9729
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
9333
9730
|
|
|
9334
9731
|
// ../../packages/product-economics/src/product-costing.ts
|
|
9335
|
-
import { z as
|
|
9732
|
+
import { z as z48 } from "zod";
|
|
9336
9733
|
|
|
9337
9734
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
9338
|
-
import { z as
|
|
9735
|
+
import { z as z47 } from "zod";
|
|
9339
9736
|
|
|
9340
9737
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
9341
9738
|
var product_costing_shipping_references_default = {
|
|
@@ -9399,21 +9796,21 @@ var product_costing_shipping_references_default = {
|
|
|
9399
9796
|
};
|
|
9400
9797
|
|
|
9401
9798
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
9402
|
-
var ShippingReferenceSchema =
|
|
9403
|
-
reference:
|
|
9404
|
-
min:
|
|
9405
|
-
max:
|
|
9406
|
-
updatedAt:
|
|
9407
|
-
confidence:
|
|
9799
|
+
var ShippingReferenceSchema = z47.object({
|
|
9800
|
+
reference: z47.number().positive(),
|
|
9801
|
+
min: z47.number().nonnegative(),
|
|
9802
|
+
max: z47.number().positive(),
|
|
9803
|
+
updatedAt: z47.string().date(),
|
|
9804
|
+
confidence: z47.enum([
|
|
9408
9805
|
"high",
|
|
9409
9806
|
"medium",
|
|
9410
9807
|
"medium-low"
|
|
9411
9808
|
]),
|
|
9412
|
-
sources:
|
|
9809
|
+
sources: z47.array(z47.string().url().startsWith("https://")).min(1).max(3)
|
|
9413
9810
|
}).superRefine(({ reference, min, max }, context) => {
|
|
9414
9811
|
if (min > reference || reference > max) {
|
|
9415
9812
|
context.addIssue({
|
|
9416
|
-
code:
|
|
9813
|
+
code: z47.ZodIssueCode.custom,
|
|
9417
9814
|
message: "shipping_reference_outside_range",
|
|
9418
9815
|
path: [
|
|
9419
9816
|
"reference"
|
|
@@ -9421,7 +9818,7 @@ var ShippingReferenceSchema = z46.object({
|
|
|
9421
9818
|
});
|
|
9422
9819
|
}
|
|
9423
9820
|
});
|
|
9424
|
-
var SHIPPING_REFERENCES =
|
|
9821
|
+
var SHIPPING_REFERENCES = z47.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
9425
9822
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
9426
9823
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
9427
9824
|
"MX",
|
|
@@ -9603,18 +10000,18 @@ function getProductCostingCountryName(country) {
|
|
|
9603
10000
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
9604
10001
|
|
|
9605
10002
|
// ../../packages/product-economics/src/product-costing.ts
|
|
9606
|
-
var ProductCostingInputSchema =
|
|
9607
|
-
country:
|
|
9608
|
-
supplierCost:
|
|
9609
|
-
shippingCost:
|
|
9610
|
-
returnRate:
|
|
9611
|
-
cancellationRate:
|
|
9612
|
-
adsManagerCpa:
|
|
9613
|
-
desiredMargin:
|
|
10003
|
+
var ProductCostingInputSchema = z48.object({
|
|
10004
|
+
country: z48.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
10005
|
+
supplierCost: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
10006
|
+
shippingCost: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
10007
|
+
returnRate: z48.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
10008
|
+
cancellationRate: z48.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
10009
|
+
adsManagerCpa: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
10010
|
+
desiredMargin: z48.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
9614
10011
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
9615
10012
|
if (returnRate + cancellationRate >= 1) {
|
|
9616
10013
|
context.addIssue({
|
|
9617
|
-
code:
|
|
10014
|
+
code: z48.ZodIssueCode.custom,
|
|
9618
10015
|
message: "delivery_rate_positive",
|
|
9619
10016
|
path: [
|
|
9620
10017
|
"cancellationRate"
|
|
@@ -9681,14 +10078,14 @@ function calculateProductCosting(rawInput) {
|
|
|
9681
10078
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
9682
10079
|
|
|
9683
10080
|
// src/tools/product-costing.ts
|
|
9684
|
-
import { z as
|
|
9685
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
9686
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
9687
|
-
var ProductCostingToolInput =
|
|
9688
|
-
country:
|
|
10081
|
+
import { z as z49 } from "zod";
|
|
10082
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z49.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
10083
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z49.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
10084
|
+
var ProductCostingToolInput = z49.object({
|
|
10085
|
+
country: z49.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
9689
10086
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
9690
10087
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
9691
|
-
supplierCost:
|
|
10088
|
+
supplierCost: z49.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."),
|
|
9692
10089
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
9693
10090
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
9694
10091
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -9820,7 +10217,7 @@ function formatPercent(value) {
|
|
|
9820
10217
|
__name(formatPercent, "formatPercent");
|
|
9821
10218
|
|
|
9822
10219
|
// src/tools/product-research.ts
|
|
9823
|
-
import { z as
|
|
10220
|
+
import { z as z50 } from "zod";
|
|
9824
10221
|
|
|
9825
10222
|
// src/tools/product-research-idempotency.ts
|
|
9826
10223
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -9936,17 +10333,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
9936
10333
|
]);
|
|
9937
10334
|
var POLL_INTERVAL_MS = 5e3;
|
|
9938
10335
|
var MAX_WAIT_SECONDS = 120;
|
|
9939
|
-
var FindInput =
|
|
10336
|
+
var FindInput = z50.object({
|
|
9940
10337
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
9941
10338
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
9942
|
-
confirmed:
|
|
9943
|
-
waitSeconds:
|
|
10339
|
+
confirmed: z50.boolean().describe(`Ponlo en true SOLO despu\xE9s de que el usuario haya aceptado el cargo de ${PRICE_CREDITS} cr\xE9ditos. No lo asumas.`),
|
|
10340
|
+
waitSeconds: z50.number().int().min(0).max(MAX_WAIT_SECONDS).optional().describe("Segundos a esperar el reporte antes de devolver el runId. M\xE1ximo 120.")
|
|
9944
10341
|
});
|
|
9945
|
-
var GetInput =
|
|
9946
|
-
runId:
|
|
10342
|
+
var GetInput = z50.object({
|
|
10343
|
+
runId: z50.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
9947
10344
|
});
|
|
9948
|
-
var ListInput =
|
|
9949
|
-
limit:
|
|
10345
|
+
var ListInput = z50.object({
|
|
10346
|
+
limit: z50.number().int().min(1).max(20).default(10)
|
|
9950
10347
|
});
|
|
9951
10348
|
function textResult(text) {
|
|
9952
10349
|
return {
|
|
@@ -10037,6 +10434,230 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
10037
10434
|
}
|
|
10038
10435
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
10039
10436
|
|
|
10437
|
+
// src/tools/dropshipping-projects.ts
|
|
10438
|
+
import { z as z51 } from "zod";
|
|
10439
|
+
var ProjectId = z51.string().uuid();
|
|
10440
|
+
var DropshippingProjectStatus = z51.enum([
|
|
10441
|
+
"active",
|
|
10442
|
+
"completed",
|
|
10443
|
+
"archived"
|
|
10444
|
+
]);
|
|
10445
|
+
var DropshippingProjectPhase = z51.enum([
|
|
10446
|
+
"research",
|
|
10447
|
+
"costing",
|
|
10448
|
+
"media",
|
|
10449
|
+
"generating",
|
|
10450
|
+
"storefront",
|
|
10451
|
+
"advertising",
|
|
10452
|
+
"complete"
|
|
10453
|
+
]);
|
|
10454
|
+
var TargetCountry = z51.enum([
|
|
10455
|
+
"CO",
|
|
10456
|
+
"MX",
|
|
10457
|
+
"PE",
|
|
10458
|
+
"EC",
|
|
10459
|
+
"CL"
|
|
10460
|
+
]);
|
|
10461
|
+
var ResearchCategory = z51.enum([
|
|
10462
|
+
"auto",
|
|
10463
|
+
"automotive",
|
|
10464
|
+
"kitchen",
|
|
10465
|
+
"pets",
|
|
10466
|
+
"home_organization",
|
|
10467
|
+
"beauty",
|
|
10468
|
+
"wellness",
|
|
10469
|
+
"fitness",
|
|
10470
|
+
"baby",
|
|
10471
|
+
"tech",
|
|
10472
|
+
"tools",
|
|
10473
|
+
"garden",
|
|
10474
|
+
"cleaning"
|
|
10475
|
+
]);
|
|
10476
|
+
var HttpUrl3 = z51.string().url().max(2e3).refine((value) => {
|
|
10477
|
+
try {
|
|
10478
|
+
return [
|
|
10479
|
+
"http:",
|
|
10480
|
+
"https:"
|
|
10481
|
+
].includes(new URL(value).protocol);
|
|
10482
|
+
} catch {
|
|
10483
|
+
return false;
|
|
10484
|
+
}
|
|
10485
|
+
}, "URL must use HTTP(S)");
|
|
10486
|
+
var ResearchCandidateOrigin = z51.object({
|
|
10487
|
+
type: z51.literal("research_candidate"),
|
|
10488
|
+
runId: ProjectId,
|
|
10489
|
+
candidateSourceId: z51.string().min(1).max(160)
|
|
10490
|
+
});
|
|
10491
|
+
var TaskOrigin = z51.object({
|
|
10492
|
+
type: z51.literal("task"),
|
|
10493
|
+
taskId: ProjectId
|
|
10494
|
+
});
|
|
10495
|
+
var ManualOrigin = z51.object({
|
|
10496
|
+
type: z51.literal("manual"),
|
|
10497
|
+
clientRequestId: ProjectId,
|
|
10498
|
+
country: z51.string().min(2).max(3).optional()
|
|
10499
|
+
});
|
|
10500
|
+
var StartProjectInput = z51.object({
|
|
10501
|
+
origin: z51.discriminatedUnion("type", [
|
|
10502
|
+
ResearchCandidateOrigin,
|
|
10503
|
+
TaskOrigin,
|
|
10504
|
+
ManualOrigin
|
|
10505
|
+
]),
|
|
10506
|
+
productName: z51.string().trim().min(1).max(240).optional(),
|
|
10507
|
+
productUrl: HttpUrl3.optional(),
|
|
10508
|
+
country: z51.string().min(2).max(3).optional(),
|
|
10509
|
+
languageCode: z51.string().min(2).max(16).optional()
|
|
10510
|
+
}).strict();
|
|
10511
|
+
var CostProjectInput = z51.object({
|
|
10512
|
+
projectId: ProjectId,
|
|
10513
|
+
version: z51.number().int().positive(),
|
|
10514
|
+
country: z51.string().trim().min(2).max(3),
|
|
10515
|
+
supplierCost: z51.number().finite().positive(),
|
|
10516
|
+
shippingCost: z51.number().finite().nonnegative(),
|
|
10517
|
+
returnRate: z51.number().finite().min(0).lt(1),
|
|
10518
|
+
cancellationRate: z51.number().finite().min(0).lt(1),
|
|
10519
|
+
adsManagerCpa: z51.number().finite().nonnegative(),
|
|
10520
|
+
desiredMargin: z51.number().finite().min(0).lt(1)
|
|
10521
|
+
});
|
|
10522
|
+
var GuideInput = z51.object({
|
|
10523
|
+
projectId: ProjectId.optional()
|
|
10524
|
+
}).strict();
|
|
10525
|
+
var DropshippingProjectNextAction = z51.discriminatedUnion("kind", [
|
|
10526
|
+
"cost_product",
|
|
10527
|
+
"provide_product_media",
|
|
10528
|
+
"generate_creatives",
|
|
10529
|
+
"wait_for_creatives",
|
|
10530
|
+
"repair_creatives",
|
|
10531
|
+
"complete_creative_set",
|
|
10532
|
+
"connect_shopify",
|
|
10533
|
+
"publish_storefront",
|
|
10534
|
+
"wait_for_storefront",
|
|
10535
|
+
"connect_meta",
|
|
10536
|
+
"create_meta_campaign",
|
|
10537
|
+
"repair_meta_campaign",
|
|
10538
|
+
"review_paused_campaign"
|
|
10539
|
+
].map((kind) => z51.object({
|
|
10540
|
+
kind: z51.literal(kind),
|
|
10541
|
+
href: z51.string().min(1)
|
|
10542
|
+
})));
|
|
10543
|
+
var CostingInputSchema = z51.object({
|
|
10544
|
+
country: z51.string().min(2).max(3),
|
|
10545
|
+
supplierCost: z51.number().finite().positive(),
|
|
10546
|
+
shippingCost: z51.number().finite().nonnegative(),
|
|
10547
|
+
returnRate: z51.number().finite().min(0).lt(1),
|
|
10548
|
+
cancellationRate: z51.number().finite().min(0).lt(1),
|
|
10549
|
+
adsManagerCpa: z51.number().finite().nonnegative(),
|
|
10550
|
+
desiredMargin: z51.number().finite().min(0).lt(1)
|
|
10551
|
+
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
10552
|
+
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
10553
|
+
code: z51.ZodIssueCode.custom,
|
|
10554
|
+
path: [
|
|
10555
|
+
"cancellationRate"
|
|
10556
|
+
]
|
|
10557
|
+
});
|
|
10558
|
+
});
|
|
10559
|
+
var CostingResultSchema = z51.object({
|
|
10560
|
+
country: z51.string().min(2).max(3),
|
|
10561
|
+
deliveryRate: z51.number().finite(),
|
|
10562
|
+
adjustedShippingCost: z51.number().finite(),
|
|
10563
|
+
adjustedCpa: z51.number().finite(),
|
|
10564
|
+
totalCost: z51.number().finite(),
|
|
10565
|
+
suggestedPrice: z51.number().finite(),
|
|
10566
|
+
baseCommercialPrice: z51.number().finite(),
|
|
10567
|
+
minimumSafePrice: z51.number().finite(),
|
|
10568
|
+
commercialPrice: z51.number().finite(),
|
|
10569
|
+
comparisonPrice: z51.number().finite(),
|
|
10570
|
+
estimatedProfit: z51.number().finite(),
|
|
10571
|
+
actualMargin: z51.number().finite(),
|
|
10572
|
+
breakEvenAdsManagerCpa: z51.number().finite(),
|
|
10573
|
+
wasPriceAutoAdjusted: z51.boolean(),
|
|
10574
|
+
profitabilityStatus: z51.literal("healthy")
|
|
10575
|
+
});
|
|
10576
|
+
var ProjectResponseSchema = z51.object({
|
|
10577
|
+
id: ProjectId,
|
|
10578
|
+
taskId: ProjectId.nullable(),
|
|
10579
|
+
status: DropshippingProjectStatus,
|
|
10580
|
+
originKey: z51.string().min(1),
|
|
10581
|
+
researchRunId: ProjectId.nullable(),
|
|
10582
|
+
candidateSourceId: z51.string().nullable(),
|
|
10583
|
+
productName: z51.string().nullable(),
|
|
10584
|
+
productUrl: HttpUrl3.nullable(),
|
|
10585
|
+
referenceImageUrl: HttpUrl3.nullable(),
|
|
10586
|
+
targetCountry: z51.string().nullable(),
|
|
10587
|
+
languageCode: z51.string().nullable(),
|
|
10588
|
+
hasReferenceImage: z51.boolean(),
|
|
10589
|
+
costingInput: CostingInputSchema.nullable(),
|
|
10590
|
+
costingResult: CostingResultSchema.nullable(),
|
|
10591
|
+
costingVersion: z51.number().int().positive().nullable(),
|
|
10592
|
+
version: z51.number().int().positive(),
|
|
10593
|
+
phase: DropshippingProjectPhase,
|
|
10594
|
+
nextAction: DropshippingProjectNextAction.nullable(),
|
|
10595
|
+
createdAt: z51.string().datetime(),
|
|
10596
|
+
updatedAt: z51.string().datetime()
|
|
10597
|
+
}).passthrough();
|
|
10598
|
+
function projectText(raw) {
|
|
10599
|
+
const project = ProjectResponseSchema.parse(raw);
|
|
10600
|
+
const next = project.nextAction ? `${project.nextAction.kind} (${project.nextAction.href})` : "ninguna";
|
|
10601
|
+
return {
|
|
10602
|
+
content: [
|
|
10603
|
+
{
|
|
10604
|
+
type: "text",
|
|
10605
|
+
text: JSON.stringify({
|
|
10606
|
+
projectId: project.id,
|
|
10607
|
+
productName: project.productName,
|
|
10608
|
+
phase: project.phase,
|
|
10609
|
+
nextAction: project.nextAction,
|
|
10610
|
+
hasReferenceImage: project.hasReferenceImage,
|
|
10611
|
+
costingSaved: Boolean(project.costingResult),
|
|
10612
|
+
version: project.version,
|
|
10613
|
+
message: `Siguiente paso: ${next}. Relee este proyecto despu\xE9s de cada mutaci\xF3n.`
|
|
10614
|
+
})
|
|
10615
|
+
}
|
|
10616
|
+
]
|
|
10617
|
+
};
|
|
10618
|
+
}
|
|
10619
|
+
__name(projectText, "projectText");
|
|
10620
|
+
function registerDropshippingProjectTools(server, api) {
|
|
10621
|
+
server.tool("start_dropshipping_project", "Inicia o reanuda un proyecto opcional de dropshipping. \xDAsalo cuando el usuario quiera seguir un producto hasta publicarlo; para una operaci\xF3n puntual usa el tool directo. La creaci\xF3n es idempotente y no cobra cr\xE9ditos.", StartProjectInput.shape, async (input) => {
|
|
10622
|
+
try {
|
|
10623
|
+
return projectText(await api.postJson("/v1/dropshipping-projects", input));
|
|
10624
|
+
} catch (error) {
|
|
10625
|
+
throw translateError(error);
|
|
10626
|
+
}
|
|
10627
|
+
});
|
|
10628
|
+
server.tool("cost_dropshipping_project", "Guarda el costeo de un proyecto guiado. Escribe solo inputs; el backend recalcula el resultado can\xF3nico y controla la versi\xF3n. Pide al usuario el costo real del proveedor: nunca lo inventes. No crea tarea ni publica nada.", CostProjectInput.shape, async (input) => {
|
|
10629
|
+
try {
|
|
10630
|
+
if (input.returnRate + input.cancellationRate >= 1) {
|
|
10631
|
+
throw new Error("returnRate + cancellationRate debe ser menor que 1.");
|
|
10632
|
+
}
|
|
10633
|
+
const { projectId, version, ...costingInput } = input;
|
|
10634
|
+
return projectText(await api.putJson(`/v1/dropshipping-projects/${encodeURIComponent(projectId)}/costing`, {
|
|
10635
|
+
version,
|
|
10636
|
+
input: costingInput
|
|
10637
|
+
}));
|
|
10638
|
+
} catch (error) {
|
|
10639
|
+
throw translateError(error);
|
|
10640
|
+
}
|
|
10641
|
+
});
|
|
10642
|
+
server.tool("guide_dropshipping_launch", "Gu\xEDa read-only del lanzamiento. Sin projectId explica cu\xE1ndo usar un flujo directo versus uno guiado; con projectId devuelve la fase y la \xFAnica nextAction calculada por ProductMaker. Despu\xE9s de cada mutaci\xF3n vuelve a llamar este tool o lee el proyecto. Nunca activa Meta.", GuideInput.shape, async (input) => {
|
|
10643
|
+
try {
|
|
10644
|
+
if (!input.projectId) {
|
|
10645
|
+
return asText({
|
|
10646
|
+
mode: "choose",
|
|
10647
|
+
guided: "Usa start_dropshipping_project cuando el usuario quiera encontrar un producto y dejarlo listo para publicar.",
|
|
10648
|
+
direct: "En modo directo usa cost_product, create_product_task, publish_to_shopify o publish_to_meta cuando pidi\xF3 una operaci\xF3n espec\xEDfica.",
|
|
10649
|
+
confirmation: "Antes de acciones pagadas o externas, muestra el estimado y pide confirmaci\xF3n.",
|
|
10650
|
+
safety: "Las campa\xF1as Meta quedan PAUSED; el usuario las activa manualmente en Ads Manager."
|
|
10651
|
+
});
|
|
10652
|
+
}
|
|
10653
|
+
return projectText(await api.getJson(`/v1/dropshipping-projects/${encodeURIComponent(input.projectId)}`));
|
|
10654
|
+
} catch (error) {
|
|
10655
|
+
throw translateError(error);
|
|
10656
|
+
}
|
|
10657
|
+
});
|
|
10658
|
+
}
|
|
10659
|
+
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
10660
|
+
|
|
10040
10661
|
// src/server.ts
|
|
10041
10662
|
function createServer(opts) {
|
|
10042
10663
|
const { apiKey, apiBaseUrl, proxyBaseUrl = null, transport = "http" } = opts;
|
|
@@ -10054,6 +10675,7 @@ function createServer(opts) {
|
|
|
10054
10675
|
const api = new ApiClient(apiBaseUrl, apiKey);
|
|
10055
10676
|
registerProductCostingTools(server);
|
|
10056
10677
|
registerProductResearchTools(server, api);
|
|
10678
|
+
registerDropshippingProjectTools(server, api);
|
|
10057
10679
|
registerTaskTools(server, api, {
|
|
10058
10680
|
proxyBaseUrl,
|
|
10059
10681
|
transport
|