@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/stdio.js
CHANGED
|
@@ -73,6 +73,17 @@ var ApiClient = class {
|
|
|
73
73
|
});
|
|
74
74
|
return this.parse(res);
|
|
75
75
|
}
|
|
76
|
+
async putJson(path3, body) {
|
|
77
|
+
const res = await fetch(`${this.baseUrl}${path3}`, {
|
|
78
|
+
method: "PUT",
|
|
79
|
+
headers: {
|
|
80
|
+
...this.authHeaders(),
|
|
81
|
+
"Content-Type": "application/json"
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify(body)
|
|
84
|
+
});
|
|
85
|
+
return this.parse(res);
|
|
86
|
+
}
|
|
76
87
|
async deleteJson(path3) {
|
|
77
88
|
const res = await fetch(`${this.baseUrl}${path3}`, {
|
|
78
89
|
method: "DELETE",
|
|
@@ -139,10 +150,10 @@ var ApiClient = class {
|
|
|
139
150
|
};
|
|
140
151
|
|
|
141
152
|
// src/index.ts
|
|
142
|
-
var MCP_VERSION = "1.
|
|
153
|
+
var MCP_VERSION = "2.1.0";
|
|
143
154
|
|
|
144
155
|
// src/tools/tasks.ts
|
|
145
|
-
import { z as
|
|
156
|
+
import { z as z40 } from "zod";
|
|
146
157
|
|
|
147
158
|
// src/resolve-image.ts
|
|
148
159
|
import { lookup as dnsLookup } from "dns/promises";
|
|
@@ -447,9 +458,11 @@ var VideoModel = z.enum([
|
|
|
447
458
|
]);
|
|
448
459
|
var NarrativeStyle = z.enum([
|
|
449
460
|
"review",
|
|
461
|
+
"ugc_how_to",
|
|
450
462
|
"problem_product_cta",
|
|
451
463
|
"product_showcase",
|
|
452
464
|
"cinematic",
|
|
465
|
+
"wild_card",
|
|
453
466
|
"metaphor_product_cta",
|
|
454
467
|
"wearable_showcase",
|
|
455
468
|
"animated_problem_pixar",
|
|
@@ -468,9 +481,11 @@ var VideoResolution = z.enum([
|
|
|
468
481
|
var VideoPreset = z.enum([
|
|
469
482
|
"auto",
|
|
470
483
|
"ugc_dynamic",
|
|
484
|
+
"ugc_how_to",
|
|
471
485
|
"problem_solution",
|
|
472
486
|
"product_showcase",
|
|
473
487
|
"cinematic",
|
|
488
|
+
"wild_card",
|
|
474
489
|
"wearable_showcase",
|
|
475
490
|
"pixar_problem",
|
|
476
491
|
"pixar_sassy",
|
|
@@ -1385,6 +1400,8 @@ var INGEST_ALLOWED_IMAGE_MIME_TYPES = [
|
|
|
1385
1400
|
var PRODUCT_CONTEXT_MAX_CHARS = 3e3;
|
|
1386
1401
|
var INGEST_ALLOWED_IMAGE_MIME_TYPE_SET = new Set(INGEST_ALLOWED_IMAGE_MIME_TYPES);
|
|
1387
1402
|
var IngestOptions = z13.object({
|
|
1403
|
+
/** Optional owner-scoped guided journey context. Never bypasses ingest gates. */
|
|
1404
|
+
dropshippingProjectId: z13.string().uuid().optional(),
|
|
1388
1405
|
languageCode: LanguageCodeSchema.default("es-CO"),
|
|
1389
1406
|
ugcFormat: VideoFormat.default("single_15s"),
|
|
1390
1407
|
country: CountrySchema,
|
|
@@ -2458,6 +2475,7 @@ var TASK_CREATIVE_VARIANT_TEXT_LIMITS = {
|
|
|
2458
2475
|
recommendationRationale: 600
|
|
2459
2476
|
};
|
|
2460
2477
|
var TaskCreativeVariantVideoPreset = VideoPreset.exclude([
|
|
2478
|
+
"problem_solution",
|
|
2461
2479
|
"ugc_unboxing_chaos",
|
|
2462
2480
|
"ugc_curiosity_reveal",
|
|
2463
2481
|
"ugc_listicle_3",
|
|
@@ -2570,6 +2588,7 @@ var TaskVariantSummary = z21.object({
|
|
|
2570
2588
|
var MAX_LANDING_IMAGES = 20;
|
|
2571
2589
|
var AutoResolvedPresetSchema = z22.enum([
|
|
2572
2590
|
"ugc_dynamic",
|
|
2591
|
+
"ugc_how_to",
|
|
2573
2592
|
"ugc_demo_review",
|
|
2574
2593
|
"ugc_unboxing_chaos",
|
|
2575
2594
|
"ugc_curiosity_reveal",
|
|
@@ -2578,6 +2597,7 @@ var AutoResolvedPresetSchema = z22.enum([
|
|
|
2578
2597
|
"problem_solution",
|
|
2579
2598
|
"product_showcase",
|
|
2580
2599
|
"cinematic",
|
|
2600
|
+
"wild_card",
|
|
2581
2601
|
"wearable_showcase",
|
|
2582
2602
|
"pixar_problem",
|
|
2583
2603
|
"pixar_sassy",
|
|
@@ -6536,17 +6556,185 @@ var RegenerateEditRequestSchema = z36.object({
|
|
|
6536
6556
|
comment: z36.string().min(1).max(2e3)
|
|
6537
6557
|
});
|
|
6538
6558
|
|
|
6539
|
-
// ../../packages/types/src/
|
|
6559
|
+
// ../../packages/types/src/dropshipping-project.ts
|
|
6540
6560
|
import { z as z37 } from "zod";
|
|
6541
|
-
var
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6561
|
+
var DropshippingProjectStatusSchema = z37.enum([
|
|
6562
|
+
"active",
|
|
6563
|
+
"completed",
|
|
6564
|
+
"archived"
|
|
6565
|
+
]);
|
|
6566
|
+
var DropshippingProjectPhaseSchema = z37.enum([
|
|
6567
|
+
"research",
|
|
6568
|
+
"costing",
|
|
6569
|
+
"media",
|
|
6570
|
+
"generating",
|
|
6571
|
+
"storefront",
|
|
6572
|
+
"advertising",
|
|
6573
|
+
"complete"
|
|
6574
|
+
]);
|
|
6575
|
+
var DropshippingProjectCostingInputSchema = z37.object({
|
|
6576
|
+
country: z37.string().min(2).max(3),
|
|
6577
|
+
supplierCost: z37.number().finite().positive(),
|
|
6578
|
+
shippingCost: z37.number().finite().nonnegative(),
|
|
6579
|
+
returnRate: z37.number().finite().min(0).lt(1),
|
|
6580
|
+
cancellationRate: z37.number().finite().min(0).lt(1),
|
|
6581
|
+
adsManagerCpa: z37.number().finite().nonnegative(),
|
|
6582
|
+
desiredMargin: z37.number().finite().min(0).lt(1)
|
|
6583
|
+
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
6584
|
+
if (returnRate + cancellationRate >= 1) {
|
|
6585
|
+
context.addIssue({
|
|
6586
|
+
code: z37.ZodIssueCode.custom,
|
|
6587
|
+
path: [
|
|
6588
|
+
"cancellationRate"
|
|
6589
|
+
],
|
|
6590
|
+
message: "delivery_rate_positive"
|
|
6591
|
+
});
|
|
6592
|
+
}
|
|
6593
|
+
});
|
|
6594
|
+
var DropshippingProjectCostingResultSchema = z37.object({
|
|
6595
|
+
country: z37.string().min(2).max(3),
|
|
6596
|
+
deliveryRate: z37.number().finite(),
|
|
6597
|
+
adjustedShippingCost: z37.number().finite(),
|
|
6598
|
+
adjustedCpa: z37.number().finite(),
|
|
6599
|
+
totalCost: z37.number().finite(),
|
|
6600
|
+
suggestedPrice: z37.number().finite(),
|
|
6601
|
+
baseCommercialPrice: z37.number().finite(),
|
|
6602
|
+
minimumSafePrice: z37.number().finite(),
|
|
6603
|
+
commercialPrice: z37.number().finite(),
|
|
6604
|
+
comparisonPrice: z37.number().finite(),
|
|
6605
|
+
estimatedProfit: z37.number().finite(),
|
|
6606
|
+
actualMargin: z37.number().finite(),
|
|
6607
|
+
breakEvenAdsManagerCpa: z37.number().finite(),
|
|
6608
|
+
wasPriceAutoAdjusted: z37.boolean(),
|
|
6609
|
+
profitabilityStatus: z37.literal("healthy")
|
|
6610
|
+
});
|
|
6611
|
+
var HttpUrlSchema = z37.string().url().max(2e3).refine((value) => {
|
|
6612
|
+
try {
|
|
6613
|
+
return [
|
|
6614
|
+
"http:",
|
|
6615
|
+
"https:"
|
|
6616
|
+
].includes(new URL(value).protocol);
|
|
6617
|
+
} catch {
|
|
6618
|
+
return false;
|
|
6619
|
+
}
|
|
6620
|
+
}, "Product URL must use HTTP(S)");
|
|
6621
|
+
var ResearchCandidateOriginSchema = z37.object({
|
|
6622
|
+
type: z37.literal("research_candidate"),
|
|
6623
|
+
runId: z37.string().uuid(),
|
|
6624
|
+
candidateSourceId: z37.string().min(1).max(160)
|
|
6625
|
+
});
|
|
6626
|
+
var TaskOriginSchema = z37.object({
|
|
6627
|
+
type: z37.literal("task"),
|
|
6628
|
+
taskId: z37.string().uuid()
|
|
6629
|
+
});
|
|
6630
|
+
var ManualOriginSchema = z37.object({
|
|
6631
|
+
type: z37.literal("manual"),
|
|
6632
|
+
clientRequestId: z37.string().uuid(),
|
|
6633
|
+
country: z37.string().min(2).max(3).optional()
|
|
6634
|
+
});
|
|
6635
|
+
var CreateDropshippingProjectRequestSchema = z37.object({
|
|
6636
|
+
origin: z37.discriminatedUnion("type", [
|
|
6637
|
+
ResearchCandidateOriginSchema,
|
|
6638
|
+
TaskOriginSchema,
|
|
6639
|
+
ManualOriginSchema
|
|
6640
|
+
]),
|
|
6641
|
+
productName: z37.string().trim().min(1).max(240).optional(),
|
|
6642
|
+
productUrl: HttpUrlSchema.optional(),
|
|
6643
|
+
country: z37.string().min(2).max(3).optional(),
|
|
6644
|
+
languageCode: z37.string().min(2).max(16).optional()
|
|
6645
|
+
}).strict();
|
|
6646
|
+
var SaveDropshippingProjectCostingRequestSchema = z37.object({
|
|
6647
|
+
input: DropshippingProjectCostingInputSchema,
|
|
6648
|
+
version: z37.number().int().positive()
|
|
6649
|
+
}).strict();
|
|
6650
|
+
var DropshippingProjectNextActionSchema = z37.discriminatedUnion("kind", [
|
|
6651
|
+
z37.object({
|
|
6652
|
+
kind: z37.literal("cost_product"),
|
|
6653
|
+
href: z37.string().min(1)
|
|
6654
|
+
}),
|
|
6655
|
+
z37.object({
|
|
6656
|
+
kind: z37.literal("provide_product_media"),
|
|
6657
|
+
href: z37.string().min(1)
|
|
6658
|
+
}),
|
|
6659
|
+
z37.object({
|
|
6660
|
+
kind: z37.literal("generate_creatives"),
|
|
6661
|
+
href: z37.string().min(1)
|
|
6662
|
+
}),
|
|
6663
|
+
z37.object({
|
|
6664
|
+
kind: z37.literal("wait_for_creatives"),
|
|
6665
|
+
href: z37.string().min(1)
|
|
6666
|
+
}),
|
|
6667
|
+
z37.object({
|
|
6668
|
+
kind: z37.literal("repair_creatives"),
|
|
6669
|
+
href: z37.string().min(1)
|
|
6670
|
+
}),
|
|
6671
|
+
z37.object({
|
|
6672
|
+
kind: z37.literal("complete_creative_set"),
|
|
6673
|
+
href: z37.string().min(1)
|
|
6674
|
+
}),
|
|
6675
|
+
z37.object({
|
|
6676
|
+
kind: z37.literal("connect_shopify"),
|
|
6677
|
+
href: z37.string().min(1)
|
|
6678
|
+
}),
|
|
6679
|
+
z37.object({
|
|
6680
|
+
kind: z37.literal("publish_storefront"),
|
|
6681
|
+
href: z37.string().min(1)
|
|
6682
|
+
}),
|
|
6683
|
+
z37.object({
|
|
6684
|
+
kind: z37.literal("wait_for_storefront"),
|
|
6685
|
+
href: z37.string().min(1)
|
|
6686
|
+
}),
|
|
6687
|
+
z37.object({
|
|
6688
|
+
kind: z37.literal("connect_meta"),
|
|
6689
|
+
href: z37.string().min(1)
|
|
6690
|
+
}),
|
|
6691
|
+
z37.object({
|
|
6692
|
+
kind: z37.literal("create_meta_campaign"),
|
|
6693
|
+
href: z37.string().min(1)
|
|
6694
|
+
}),
|
|
6695
|
+
z37.object({
|
|
6696
|
+
kind: z37.literal("repair_meta_campaign"),
|
|
6697
|
+
href: z37.string().min(1)
|
|
6698
|
+
}),
|
|
6699
|
+
z37.object({
|
|
6700
|
+
kind: z37.literal("review_paused_campaign"),
|
|
6701
|
+
href: z37.string().min(1)
|
|
6702
|
+
})
|
|
6703
|
+
]);
|
|
6704
|
+
var DropshippingProjectResponseSchema = z37.object({
|
|
6705
|
+
id: z37.string().uuid(),
|
|
6706
|
+
taskId: z37.string().uuid().nullable(),
|
|
6707
|
+
status: DropshippingProjectStatusSchema,
|
|
6708
|
+
originKey: z37.string().min(1),
|
|
6709
|
+
researchRunId: z37.string().uuid().nullable(),
|
|
6710
|
+
candidateSourceId: z37.string().nullable(),
|
|
6711
|
+
productName: z37.string().nullable(),
|
|
6712
|
+
productUrl: HttpUrlSchema.nullable(),
|
|
6713
|
+
referenceImageUrl: z37.string().url().nullable(),
|
|
6714
|
+
hasReferenceImage: z37.boolean(),
|
|
6715
|
+
targetCountry: z37.string().nullable(),
|
|
6716
|
+
languageCode: z37.string().nullable(),
|
|
6717
|
+
costingInput: DropshippingProjectCostingInputSchema.nullable(),
|
|
6718
|
+
costingResult: DropshippingProjectCostingResultSchema.nullable(),
|
|
6719
|
+
costingVersion: z37.number().int().positive().nullable(),
|
|
6720
|
+
version: z37.number().int().positive(),
|
|
6721
|
+
phase: DropshippingProjectPhaseSchema,
|
|
6722
|
+
nextAction: DropshippingProjectNextActionSchema.nullable(),
|
|
6723
|
+
createdAt: z37.string().datetime(),
|
|
6724
|
+
updatedAt: z37.string().datetime()
|
|
6725
|
+
});
|
|
6726
|
+
|
|
6727
|
+
// ../../packages/types/src/scene-subject-contract.ts
|
|
6728
|
+
import { z as z38 } from "zod";
|
|
6729
|
+
var SceneSubjectContractSchema = z38.object({
|
|
6730
|
+
maxPeople: z38.number().int().min(1).max(10),
|
|
6731
|
+
minPeople: z38.number().int().min(0).max(10),
|
|
6732
|
+
minDistinctPeople: z38.number().int().min(0).max(10),
|
|
6733
|
+
maxHands: z38.number().int().min(0).max(20)
|
|
6546
6734
|
}).superRefine((value, ctx) => {
|
|
6547
6735
|
if (value.minPeople > value.maxPeople) {
|
|
6548
6736
|
ctx.addIssue({
|
|
6549
|
-
code:
|
|
6737
|
+
code: z38.ZodIssueCode.custom,
|
|
6550
6738
|
path: [
|
|
6551
6739
|
"minPeople"
|
|
6552
6740
|
],
|
|
@@ -6555,7 +6743,7 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6555
6743
|
}
|
|
6556
6744
|
if (value.minDistinctPeople > value.maxPeople) {
|
|
6557
6745
|
ctx.addIssue({
|
|
6558
|
-
code:
|
|
6746
|
+
code: z38.ZodIssueCode.custom,
|
|
6559
6747
|
path: [
|
|
6560
6748
|
"minDistinctPeople"
|
|
6561
6749
|
],
|
|
@@ -6564,7 +6752,7 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6564
6752
|
}
|
|
6565
6753
|
if (value.minDistinctPeople > value.minPeople) {
|
|
6566
6754
|
ctx.addIssue({
|
|
6567
|
-
code:
|
|
6755
|
+
code: z38.ZodIssueCode.custom,
|
|
6568
6756
|
path: [
|
|
6569
6757
|
"minDistinctPeople"
|
|
6570
6758
|
],
|
|
@@ -6573,6 +6761,166 @@ var SceneSubjectContractSchema = z37.object({
|
|
|
6573
6761
|
}
|
|
6574
6762
|
});
|
|
6575
6763
|
|
|
6764
|
+
// ../../packages/types/src/productmaker-chat-capabilities.ts
|
|
6765
|
+
var PRODUCTMAKER_MCP_CAPABILITIES = [
|
|
6766
|
+
{
|
|
6767
|
+
name: "approve_video_script",
|
|
6768
|
+
confirmation: "credit_consuming",
|
|
6769
|
+
schemaHash: "bab794a9700a8d3f42b97f444a776e7ed4dcd833038c52588f951b50970ff3fa"
|
|
6770
|
+
},
|
|
6771
|
+
{
|
|
6772
|
+
name: "cost_dropshipping_project",
|
|
6773
|
+
confirmation: "state_change",
|
|
6774
|
+
schemaHash: "746797b5400b170ba3a0704d432afff635794f0a7ae0b9da07b26d49e3b82242"
|
|
6775
|
+
},
|
|
6776
|
+
{
|
|
6777
|
+
name: "cost_product",
|
|
6778
|
+
confirmation: "none",
|
|
6779
|
+
schemaHash: "6d1f85a999dbdabae4eda406ff4689cdff2016df375b5b6741b91f4308d819af"
|
|
6780
|
+
},
|
|
6781
|
+
{
|
|
6782
|
+
name: "create_creative_variant",
|
|
6783
|
+
confirmation: "credit_consuming",
|
|
6784
|
+
schemaHash: "8feeed1e6e6a14bdcb0a1d9d8b03350ce7d8117d926db49f19ca5c5a8f1e7033"
|
|
6785
|
+
},
|
|
6786
|
+
{
|
|
6787
|
+
name: "create_product_task",
|
|
6788
|
+
confirmation: "credit_consuming",
|
|
6789
|
+
schemaHash: "828ee643bb3a05a63c6e63730459d35ce1621cbd559bbc76a6c5fcec9a45654d"
|
|
6790
|
+
},
|
|
6791
|
+
{
|
|
6792
|
+
name: "edit_task_draft",
|
|
6793
|
+
confirmation: "state_change",
|
|
6794
|
+
schemaHash: "f1763564083dcaac2d1f4d5e6c4625a2d4ec0ea3eea273aadc0fb9d4ab6c7d47"
|
|
6795
|
+
},
|
|
6796
|
+
{
|
|
6797
|
+
name: "estimate_creative_variant",
|
|
6798
|
+
confirmation: "none",
|
|
6799
|
+
schemaHash: "a5601adcb9578319528ca0a96f37a35b613370646a75932d1b3978d593f7e302"
|
|
6800
|
+
},
|
|
6801
|
+
{
|
|
6802
|
+
name: "find_winning_products",
|
|
6803
|
+
confirmation: "credit_consuming",
|
|
6804
|
+
schemaHash: "40f581e270ca668fb5fd1505a1f7cced6f629936e7d8394426aa0c655b9cef4f"
|
|
6805
|
+
},
|
|
6806
|
+
{
|
|
6807
|
+
name: "generate_free_video",
|
|
6808
|
+
confirmation: "credit_consuming",
|
|
6809
|
+
schemaHash: "a6f984d175c1ae5bc5f36ade27ee12c57763192000453c0387cd4cd6a9f1751d"
|
|
6810
|
+
},
|
|
6811
|
+
{
|
|
6812
|
+
name: "generate_image_creatives",
|
|
6813
|
+
confirmation: "credit_consuming",
|
|
6814
|
+
schemaHash: "fb6afcf8571887906340fa0b8dd17196d2814e480b734ad5d374e8810958152e"
|
|
6815
|
+
},
|
|
6816
|
+
{
|
|
6817
|
+
name: "generate_landing",
|
|
6818
|
+
confirmation: "credit_consuming",
|
|
6819
|
+
schemaHash: "539922b8fe611c73a7349b1c3f92632fe21f161d7874a0ef2172abfec5834759"
|
|
6820
|
+
},
|
|
6821
|
+
{
|
|
6822
|
+
name: "generate_video_creative",
|
|
6823
|
+
confirmation: "credit_consuming",
|
|
6824
|
+
schemaHash: "94e90d60ad5d68538c31d880a635c5be69d6d204fd2119139735af83ebf0b94a"
|
|
6825
|
+
},
|
|
6826
|
+
{
|
|
6827
|
+
name: "get_meta_campaign_status",
|
|
6828
|
+
confirmation: "none",
|
|
6829
|
+
schemaHash: "92077241cf4e9d14edefca410e85715cc383b1433081c3461c925f8fc3d6e8ab"
|
|
6830
|
+
},
|
|
6831
|
+
{
|
|
6832
|
+
name: "get_product_research_run",
|
|
6833
|
+
confirmation: "none",
|
|
6834
|
+
schemaHash: "3d0bfa4409daa4a8126d18787c3dc619dbdf2fbb679a2cffe9ffcd1c0d96402f"
|
|
6835
|
+
},
|
|
6836
|
+
{
|
|
6837
|
+
name: "get_task_status",
|
|
6838
|
+
confirmation: "none",
|
|
6839
|
+
schemaHash: "6876d865685dd371ae6c2da2d5a69b657731e5a032aff46ac95b6077e9a6d93e"
|
|
6840
|
+
},
|
|
6841
|
+
{
|
|
6842
|
+
name: "get_tiktok_campaign_status",
|
|
6843
|
+
confirmation: "none",
|
|
6844
|
+
schemaHash: "7a2f90a9a9ba91506fbb57a0a881d5a7b9ca1bb1074b0a754520f02fd81b2801"
|
|
6845
|
+
},
|
|
6846
|
+
{
|
|
6847
|
+
name: "get_video_script",
|
|
6848
|
+
confirmation: "none",
|
|
6849
|
+
schemaHash: "c96e7042368ba6f241773d26d4a443894b092801d1c81054f3798865138edfba"
|
|
6850
|
+
},
|
|
6851
|
+
{
|
|
6852
|
+
name: "guide_dropshipping_launch",
|
|
6853
|
+
confirmation: "none",
|
|
6854
|
+
schemaHash: "0e7a1cb5ad5c6681473df5689336edcd7a63b8d68853359982e44bfd98a65db8"
|
|
6855
|
+
},
|
|
6856
|
+
{
|
|
6857
|
+
name: "list_meta_ad_accounts",
|
|
6858
|
+
confirmation: "none",
|
|
6859
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6860
|
+
},
|
|
6861
|
+
{
|
|
6862
|
+
name: "list_product_research_runs",
|
|
6863
|
+
confirmation: "none",
|
|
6864
|
+
schemaHash: "3b8fac903cd9e30c5b6a6c584cc70a819af5392bbdbb32b69eab4c65dc52b556"
|
|
6865
|
+
},
|
|
6866
|
+
{
|
|
6867
|
+
name: "list_shopify_products",
|
|
6868
|
+
confirmation: "none",
|
|
6869
|
+
schemaHash: "152b137e01066f3b443987ad75f5be00de8696ce984144bd775416192be20667"
|
|
6870
|
+
},
|
|
6871
|
+
{
|
|
6872
|
+
name: "list_shopify_shops",
|
|
6873
|
+
confirmation: "none",
|
|
6874
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6875
|
+
},
|
|
6876
|
+
{
|
|
6877
|
+
name: "list_tasks",
|
|
6878
|
+
confirmation: "none",
|
|
6879
|
+
schemaHash: "cac5e9dda34b90550024cc546976fab1d6de4fc8fca85a3ec6abde65223cb56c"
|
|
6880
|
+
},
|
|
6881
|
+
{
|
|
6882
|
+
name: "list_tiktok_advertisers",
|
|
6883
|
+
confirmation: "none",
|
|
6884
|
+
schemaHash: "7a014b717a77aac971ea0ab5c0ff47bb13e6cae7ef9442d9dedb15ce36381b15"
|
|
6885
|
+
},
|
|
6886
|
+
{
|
|
6887
|
+
name: "publish_creatives_to_meta",
|
|
6888
|
+
confirmation: "external_mutation",
|
|
6889
|
+
schemaHash: "ddb45071d61746b443124346e7a82095315a2a80bd393c73a45f12b895939cf5"
|
|
6890
|
+
},
|
|
6891
|
+
{
|
|
6892
|
+
name: "publish_to_meta",
|
|
6893
|
+
confirmation: "external_mutation",
|
|
6894
|
+
schemaHash: "4b6daa1a25e739ccf208a6acede067ec1c22b1ea5509f332361a17dd46f6bb0b"
|
|
6895
|
+
},
|
|
6896
|
+
{
|
|
6897
|
+
name: "publish_to_shopify",
|
|
6898
|
+
confirmation: "external_mutation",
|
|
6899
|
+
schemaHash: "ec37111aac872e6be22f34c8b547c1e4b58875f798c48e24ca9ca067a0a22d8b"
|
|
6900
|
+
},
|
|
6901
|
+
{
|
|
6902
|
+
name: "publish_to_tiktok",
|
|
6903
|
+
confirmation: "external_mutation",
|
|
6904
|
+
schemaHash: "4f8dccba51b99687f04e1a58e3fde003b6f52ec6c891afe74b1d81d4b6992908"
|
|
6905
|
+
},
|
|
6906
|
+
{
|
|
6907
|
+
name: "regenerate_video_script",
|
|
6908
|
+
confirmation: "credit_consuming",
|
|
6909
|
+
schemaHash: "745687cb41f904e293105f93bbe6bc0471f63fe097ab8f85d3df8d9833084844"
|
|
6910
|
+
},
|
|
6911
|
+
{
|
|
6912
|
+
name: "resolve_pending_action",
|
|
6913
|
+
confirmation: "credit_consuming",
|
|
6914
|
+
schemaHash: "3a9f33a26fce63b20bece3a528f8eb16e917dabc8a9ec5f04e746bad84757aa3"
|
|
6915
|
+
},
|
|
6916
|
+
{
|
|
6917
|
+
name: "start_dropshipping_project",
|
|
6918
|
+
confirmation: "state_change",
|
|
6919
|
+
schemaHash: "2b621702e8da8bb894d392060e5e4f677a8dc26f454e991dbb929053715a4f8b"
|
|
6920
|
+
}
|
|
6921
|
+
];
|
|
6922
|
+
var PRODUCTMAKER_MCP_CAPABILITY_NAMES = PRODUCTMAKER_MCP_CAPABILITIES.map((capability) => capability.name);
|
|
6923
|
+
|
|
6576
6924
|
// src/resolve-media.ts
|
|
6577
6925
|
var MAX_MEDIA_BYTES = CAMPAIGN_LIMITS.MAX_FILE_SIZE_BYTES;
|
|
6578
6926
|
var MEDIA_FORMATS = [
|
|
@@ -6812,10 +7160,10 @@ async function resolveMediaRef(ref, opts) {
|
|
|
6812
7160
|
__name(resolveMediaRef, "resolveMediaRef");
|
|
6813
7161
|
|
|
6814
7162
|
// src/tools/shared.ts
|
|
6815
|
-
import { z as
|
|
6816
|
-
var Lang =
|
|
6817
|
-
var Country =
|
|
6818
|
-
var LandingStrategyEnum =
|
|
7163
|
+
import { z as z39 } from "zod";
|
|
7164
|
+
var Lang = z39.string().min(2).max(10);
|
|
7165
|
+
var Country = z39.string().min(2).max(3);
|
|
7166
|
+
var LandingStrategyEnum = z39.enum([
|
|
6819
7167
|
"auto",
|
|
6820
7168
|
"classic",
|
|
6821
7169
|
"pain_solution",
|
|
@@ -6824,28 +7172,30 @@ var LandingStrategyEnum = z38.enum([
|
|
|
6824
7172
|
"offer_value",
|
|
6825
7173
|
"lifestyle_identity"
|
|
6826
7174
|
]);
|
|
6827
|
-
var LandingImageFormatEnum =
|
|
7175
|
+
var LandingImageFormatEnum = z39.enum([
|
|
6828
7176
|
"9:16",
|
|
6829
7177
|
"4:5",
|
|
6830
7178
|
"1:1"
|
|
6831
7179
|
]);
|
|
6832
|
-
var VideoPresetEnum =
|
|
7180
|
+
var VideoPresetEnum = z39.enum([
|
|
6833
7181
|
"auto",
|
|
6834
7182
|
"ugc_dynamic",
|
|
7183
|
+
"ugc_how_to",
|
|
6835
7184
|
"ugc_unboxing_chaos",
|
|
6836
|
-
"problem_solution",
|
|
6837
7185
|
"product_showcase",
|
|
6838
7186
|
"wearable_showcase",
|
|
6839
7187
|
"cinematic",
|
|
7188
|
+
"wild_card",
|
|
6840
7189
|
"pixar_problem",
|
|
6841
7190
|
"pixar_sassy"
|
|
6842
7191
|
]);
|
|
6843
|
-
var TaskCreativeVariantVideoPresetEnum =
|
|
7192
|
+
var TaskCreativeVariantVideoPresetEnum = z39.enum([
|
|
6844
7193
|
"auto",
|
|
6845
7194
|
"ugc_dynamic",
|
|
6846
|
-
"
|
|
7195
|
+
"ugc_how_to",
|
|
6847
7196
|
"product_showcase",
|
|
6848
7197
|
"cinematic",
|
|
7198
|
+
"wild_card",
|
|
6849
7199
|
"wearable_showcase",
|
|
6850
7200
|
"pixar_problem",
|
|
6851
7201
|
"pixar_sassy",
|
|
@@ -6858,15 +7208,15 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
6858
7208
|
narrativeStyle: "review",
|
|
6859
7209
|
videoModel: "veo"
|
|
6860
7210
|
},
|
|
6861
|
-
|
|
7211
|
+
ugc_how_to: {
|
|
6862
7212
|
videoStyle: "ai_dynamic",
|
|
6863
|
-
narrativeStyle: "
|
|
7213
|
+
narrativeStyle: "ugc_how_to",
|
|
6864
7214
|
videoModel: "veo"
|
|
6865
7215
|
},
|
|
6866
|
-
|
|
7216
|
+
ugc_unboxing_chaos: {
|
|
6867
7217
|
videoStyle: "ai_dynamic",
|
|
6868
|
-
narrativeStyle: "
|
|
6869
|
-
videoModel: "
|
|
7218
|
+
narrativeStyle: "ugc_unboxing_chaos",
|
|
7219
|
+
videoModel: "veo"
|
|
6870
7220
|
},
|
|
6871
7221
|
pixar_problem: {
|
|
6872
7222
|
videoStyle: "ai_dynamic",
|
|
@@ -6892,6 +7242,11 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
6892
7242
|
videoStyle: "product_only",
|
|
6893
7243
|
narrativeStyle: "cinematic",
|
|
6894
7244
|
videoModel: "grok"
|
|
7245
|
+
},
|
|
7246
|
+
wild_card: {
|
|
7247
|
+
videoStyle: "product_only",
|
|
7248
|
+
narrativeStyle: "wild_card",
|
|
7249
|
+
videoModel: "grok"
|
|
6895
7250
|
}
|
|
6896
7251
|
};
|
|
6897
7252
|
function resolveVideoPreset(preset) {
|
|
@@ -6899,7 +7254,7 @@ function resolveVideoPreset(preset) {
|
|
|
6899
7254
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
6900
7255
|
}
|
|
6901
7256
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
6902
|
-
var VideoTierEnum =
|
|
7257
|
+
var VideoTierEnum = z39.enum([
|
|
6903
7258
|
"basic"
|
|
6904
7259
|
]);
|
|
6905
7260
|
function resolveVideoTier(_tier) {
|
|
@@ -6914,21 +7269,23 @@ function resolveVideoFormatForDuration(durationSeconds) {
|
|
|
6914
7269
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
6915
7270
|
}
|
|
6916
7271
|
__name(resolveVideoFormatForDuration, "resolveVideoFormatForDuration");
|
|
6917
|
-
var VideoResolutionEnum =
|
|
7272
|
+
var VideoResolutionEnum = z39.enum([
|
|
6918
7273
|
"480p",
|
|
6919
7274
|
"720p"
|
|
6920
7275
|
]);
|
|
6921
|
-
var VideoStyleEnum =
|
|
7276
|
+
var VideoStyleEnum = z39.enum([
|
|
6922
7277
|
"ugc",
|
|
6923
7278
|
"cartoon_3d",
|
|
6924
7279
|
"product_only",
|
|
6925
7280
|
"ai_dynamic"
|
|
6926
7281
|
]);
|
|
6927
|
-
var NarrativeStyleEnum =
|
|
7282
|
+
var NarrativeStyleEnum = z39.enum([
|
|
6928
7283
|
"review",
|
|
7284
|
+
"ugc_how_to",
|
|
6929
7285
|
"problem_product_cta",
|
|
6930
7286
|
"product_showcase",
|
|
6931
7287
|
"cinematic",
|
|
7288
|
+
"wild_card",
|
|
6932
7289
|
"metaphor_product_cta",
|
|
6933
7290
|
"wearable_showcase",
|
|
6934
7291
|
"animated_problem_pixar",
|
|
@@ -6939,17 +7296,18 @@ var NarrativeStyleEnum = z38.enum([
|
|
|
6939
7296
|
"ugc_skeptic_confession",
|
|
6940
7297
|
"ugc_demo_review"
|
|
6941
7298
|
]);
|
|
6942
|
-
var PublicNarrativeStyleEnum =
|
|
7299
|
+
var PublicNarrativeStyleEnum = z39.enum([
|
|
6943
7300
|
"review",
|
|
7301
|
+
"ugc_how_to",
|
|
6944
7302
|
"ugc_unboxing_chaos",
|
|
6945
|
-
"problem_product_cta",
|
|
6946
7303
|
"product_showcase",
|
|
6947
7304
|
"wearable_showcase",
|
|
6948
7305
|
"cinematic",
|
|
7306
|
+
"wild_card",
|
|
6949
7307
|
"animated_problem_pixar",
|
|
6950
7308
|
"sassy_product_pixar"
|
|
6951
7309
|
]);
|
|
6952
|
-
var VideoModelEnum =
|
|
7310
|
+
var VideoModelEnum = z39.enum([
|
|
6953
7311
|
"veo",
|
|
6954
7312
|
"wan",
|
|
6955
7313
|
"bytedance",
|
|
@@ -6957,25 +7315,25 @@ var VideoModelEnum = z38.enum([
|
|
|
6957
7315
|
"grok",
|
|
6958
7316
|
"kling"
|
|
6959
7317
|
]);
|
|
6960
|
-
var ProductReferenceUserChoiceEnum =
|
|
7318
|
+
var ProductReferenceUserChoiceEnum = z39.enum([
|
|
6961
7319
|
"same_product",
|
|
6962
7320
|
"variants",
|
|
6963
7321
|
"different_products",
|
|
6964
7322
|
"combo_distinct"
|
|
6965
7323
|
]);
|
|
6966
|
-
var ProductReferenceCandidateGroupingEnum =
|
|
7324
|
+
var ProductReferenceCandidateGroupingEnum = z39.enum([
|
|
6967
7325
|
"same_product_same_variant",
|
|
6968
7326
|
"same_product_different_variants",
|
|
6969
7327
|
"different_products",
|
|
6970
7328
|
"unclear"
|
|
6971
7329
|
]);
|
|
6972
|
-
var GapDurationChoiceMirror =
|
|
6973
|
-
angleIndex:
|
|
6974
|
-
recommendedSec:
|
|
6975
|
-
|
|
6976
|
-
|
|
7330
|
+
var GapDurationChoiceMirror = z39.object({
|
|
7331
|
+
angleIndex: z39.number().int().nonnegative(),
|
|
7332
|
+
recommendedSec: z39.union([
|
|
7333
|
+
z39.literal(15),
|
|
7334
|
+
z39.literal(30)
|
|
6977
7335
|
]),
|
|
6978
|
-
estimatedDeltaCredits:
|
|
7336
|
+
estimatedDeltaCredits: z39.number().int().nonnegative().optional()
|
|
6979
7337
|
});
|
|
6980
7338
|
function buildSelectedImageUrlsHash(urls) {
|
|
6981
7339
|
const input = [
|
|
@@ -6989,13 +7347,13 @@ function buildSelectedImageUrlsHash(urls) {
|
|
|
6989
7347
|
return `fnv1a:${hash.toString(16).padStart(8, "0")}:${urls.length}`;
|
|
6990
7348
|
}
|
|
6991
7349
|
__name(buildSelectedImageUrlsHash, "buildSelectedImageUrlsHash");
|
|
6992
|
-
var ImageCreativeStyleEnum =
|
|
7350
|
+
var ImageCreativeStyleEnum = z39.enum([
|
|
6993
7351
|
"studio",
|
|
6994
7352
|
"floating",
|
|
6995
7353
|
"ingredients",
|
|
6996
7354
|
"in_use"
|
|
6997
7355
|
]);
|
|
6998
|
-
var ImageCreativeArchetypeEnum =
|
|
7356
|
+
var ImageCreativeArchetypeEnum = z39.enum([
|
|
6999
7357
|
"direct_response_product_ad",
|
|
7000
7358
|
"hero_outcome",
|
|
7001
7359
|
"offer_value_prop",
|
|
@@ -7004,23 +7362,23 @@ var ImageCreativeArchetypeEnum = z38.enum([
|
|
|
7004
7362
|
"problem_solution",
|
|
7005
7363
|
"lifestyle_identity"
|
|
7006
7364
|
]);
|
|
7007
|
-
var ImageCreativeVisualTreatmentEnum =
|
|
7365
|
+
var ImageCreativeVisualTreatmentEnum = z39.enum([
|
|
7008
7366
|
"performance_product_ad",
|
|
7009
7367
|
"premium_dtc_carousel"
|
|
7010
7368
|
]);
|
|
7011
|
-
var ImageCreativeAspectRatioEnum =
|
|
7369
|
+
var ImageCreativeAspectRatioEnum = z39.enum([
|
|
7012
7370
|
"1:1",
|
|
7013
7371
|
"4:5",
|
|
7014
7372
|
"9:16",
|
|
7015
7373
|
"16:9"
|
|
7016
7374
|
]);
|
|
7017
|
-
var ImageRefSchema =
|
|
7018
|
-
url:
|
|
7019
|
-
path:
|
|
7375
|
+
var ImageRefSchema = z39.object({
|
|
7376
|
+
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.'),
|
|
7377
|
+
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`.')
|
|
7020
7378
|
}).refine((v) => Boolean(v.url) !== Boolean(v.path), {
|
|
7021
7379
|
message: "each image entry must have exactly one of `url` or `path`"
|
|
7022
7380
|
});
|
|
7023
|
-
var ImagesInput =
|
|
7381
|
+
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.');
|
|
7024
7382
|
function asText(value) {
|
|
7025
7383
|
return {
|
|
7026
7384
|
content: [
|
|
@@ -7073,14 +7431,14 @@ async function submitCreative(api, opts) {
|
|
|
7073
7431
|
});
|
|
7074
7432
|
}
|
|
7075
7433
|
__name(submitCreative, "submitCreative");
|
|
7076
|
-
var ResearchTargetCountryEnum =
|
|
7434
|
+
var ResearchTargetCountryEnum = z39.enum([
|
|
7077
7435
|
"CO",
|
|
7078
7436
|
"MX",
|
|
7079
7437
|
"PE",
|
|
7080
7438
|
"EC",
|
|
7081
7439
|
"CL"
|
|
7082
7440
|
]);
|
|
7083
|
-
var ResearchCategoryEnum =
|
|
7441
|
+
var ResearchCategoryEnum = z39.enum([
|
|
7084
7442
|
"auto",
|
|
7085
7443
|
"automotive",
|
|
7086
7444
|
"kitchen",
|
|
@@ -7126,6 +7484,15 @@ var McpErrorCode = {
|
|
|
7126
7484
|
TASK_NOT_READY: "TASK_NOT_READY",
|
|
7127
7485
|
CREATIVE_VARIANT_FAILED: "CREATIVE_VARIANT_FAILED",
|
|
7128
7486
|
CREATIVE_VARIANT_DISPATCH_FAILED: "CREATIVE_VARIANT_DISPATCH_FAILED",
|
|
7487
|
+
// Guided dropshipping project / research
|
|
7488
|
+
DROPSHIPPING_PROJECT_NOT_FOUND: "DROPSHIPPING_PROJECT_NOT_FOUND",
|
|
7489
|
+
DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY: "DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY",
|
|
7490
|
+
DROPSHIPPING_PROJECT_VERSION_CONFLICT: "DROPSHIPPING_PROJECT_VERSION_CONFLICT",
|
|
7491
|
+
DROPSHIPPING_PROJECT_MEDIA_REQUIRED: "DROPSHIPPING_PROJECT_MEDIA_REQUIRED",
|
|
7492
|
+
DROPSHIPPING_PROJECT_DISABLED: "DROPSHIPPING_PROJECT_DISABLED",
|
|
7493
|
+
KALODATA_NOT_CONFIGURED: "KALODATA_NOT_CONFIGURED",
|
|
7494
|
+
META_AD_LIBRARY_NOT_CONFIGURED: "META_AD_LIBRARY_NOT_CONFIGURED",
|
|
7495
|
+
PRODUCT_RESEARCH_DISABLED: "PRODUCT_RESEARCH_DISABLED",
|
|
7129
7496
|
PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT: "PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT",
|
|
7130
7497
|
// Connection presence
|
|
7131
7498
|
NO_SHOPIFY_SHOPS: "NO_SHOPIFY_SHOPS",
|
|
@@ -7136,6 +7503,7 @@ var McpErrorCode = {
|
|
|
7136
7503
|
CAMPAIGN_MISSING_LANDING_URL: "CAMPAIGN_MISSING_LANDING_URL",
|
|
7137
7504
|
CAMPAIGN_NO_CREATIVES: "CAMPAIGN_NO_CREATIVES",
|
|
7138
7505
|
CAMPAIGN_MISSING_THUMBNAILS: "CAMPAIGN_MISSING_THUMBNAILS",
|
|
7506
|
+
CAMPAIGN_RECONCILIATION_REQUIRED: "CAMPAIGN_RECONCILIATION_REQUIRED",
|
|
7139
7507
|
// Shopify
|
|
7140
7508
|
SHOPIFY_NOT_CONNECTED: "SHOPIFY_NOT_CONNECTED",
|
|
7141
7509
|
SHOPIFY_TOKEN_EXPIRED: "SHOPIFY_TOKEN_EXPIRED",
|
|
@@ -7240,6 +7608,7 @@ var CODE_MESSAGES = {
|
|
|
7240
7608
|
CAMPAIGN_MISSING_LANDING_URL: "Missing landing URL for the campaign. Publish to Shopify first or pass `landingUrl` explicitly.",
|
|
7241
7609
|
CAMPAIGN_NO_CREATIVES: "The task has no creatives (video/image) ready for the campaign. Wait for generation to finish.",
|
|
7242
7610
|
CAMPAIGN_MISSING_THUMBNAILS: "Missing thumbnails for the videos. Verify that image/video generation has finished.",
|
|
7611
|
+
CAMPAIGN_RECONCILIATION_REQUIRED: "A campaign may already have been created. Do not retry creation; reopen the project and reconcile it or contact support.",
|
|
7243
7612
|
// Connections
|
|
7244
7613
|
NO_SHOPIFY_SHOPS: "No Shopify stores connected. Connect one at https://productmaker.app/integrations.",
|
|
7245
7614
|
NO_META_AD_ACCOUNTS: "No Meta Ads accounts connected. Connect Facebook at https://productmaker.app/integrations.",
|
|
@@ -7248,6 +7617,14 @@ var CODE_MESSAGES = {
|
|
|
7248
7617
|
TASK_NOT_READY: "The task is not ready for this action yet. Wait for it to finish and retry.",
|
|
7249
7618
|
CREATIVE_VARIANT_FAILED: "The previous creative variant attempt failed. Ask for confirmation before starting a new paid attempt with a new clientRequestId.",
|
|
7250
7619
|
CREATIVE_VARIANT_DISPATCH_FAILED: "The creative variant could not be queued. Retry as a new paid attempt with a new clientRequestId.",
|
|
7620
|
+
DROPSHIPPING_PROJECT_NOT_FOUND: "Project not found or it does not belong to this user.",
|
|
7621
|
+
DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY: "That research candidate is no longer available. Return to the current research results and choose a fresh candidate.",
|
|
7622
|
+
DROPSHIPPING_PROJECT_VERSION_CONFLICT: "This project changed in another tab. Read it again, review the newer values, and retry with the fresh version.",
|
|
7623
|
+
DROPSHIPPING_PROJECT_MEDIA_REQUIRED: "This project needs a product photo before creating content. Upload one from the guided ingest step.",
|
|
7624
|
+
DROPSHIPPING_PROJECT_DISABLED: "Guided dropshipping projects are temporarily unavailable. Try again later.",
|
|
7625
|
+
KALODATA_NOT_CONFIGURED: "Product research is temporarily unavailable because the trend-data provider is not configured.",
|
|
7626
|
+
META_AD_LIBRARY_NOT_CONFIGURED: "Product research is temporarily unavailable because Meta Ad Library is not configured.",
|
|
7627
|
+
PRODUCT_RESEARCH_DISABLED: "Product research is temporarily unavailable. Try again later.",
|
|
7251
7628
|
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.",
|
|
7252
7629
|
// API key
|
|
7253
7630
|
INVALID_API_KEY: "Invalid API key. Check your PM_API_KEY in the MCP client configuration.",
|
|
@@ -7284,6 +7661,11 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7284
7661
|
McpErrorCode.CAMPAIGN_NOT_FOUND,
|
|
7285
7662
|
McpErrorCode.CAMPAIGN_TASK_NOT_FOUND,
|
|
7286
7663
|
McpErrorCode.TASK_NOT_FOUND,
|
|
7664
|
+
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
7665
|
+
McpErrorCode.DROPSHIPPING_PROJECT_DISABLED,
|
|
7666
|
+
McpErrorCode.DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY,
|
|
7667
|
+
McpErrorCode.DROPSHIPPING_PROJECT_VERSION_CONFLICT,
|
|
7668
|
+
McpErrorCode.DROPSHIPPING_PROJECT_MEDIA_REQUIRED,
|
|
7287
7669
|
McpErrorCode.META_TASK_NOT_FOUND,
|
|
7288
7670
|
McpErrorCode.META_INVALID_AD_ACCOUNT,
|
|
7289
7671
|
McpErrorCode.META_PIXEL_NOT_FOUND,
|
|
@@ -7292,6 +7674,7 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7292
7674
|
McpErrorCode.TIKTOK_ADVERTISER_REQUIRED,
|
|
7293
7675
|
McpErrorCode.TIKTOK_PIXEL_NOT_FOUND,
|
|
7294
7676
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
7677
|
+
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
7295
7678
|
McpErrorCode.META_NO_LANDING_URL,
|
|
7296
7679
|
McpErrorCode.META_DAILY_BUDGET_TOO_HIGH,
|
|
7297
7680
|
McpErrorCode.META_CAMPAIGN_CONFIG_INVALID,
|
|
@@ -7329,6 +7712,14 @@ var INVALID_PARAM_CODES = /* @__PURE__ */ new Set([
|
|
|
7329
7712
|
var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
7330
7713
|
McpErrorCode.INSUFFICIENT_CREDITS,
|
|
7331
7714
|
McpErrorCode.TASK_QUOTA_EXCEEDED,
|
|
7715
|
+
McpErrorCode.DROPSHIPPING_PROJECT_NOT_FOUND,
|
|
7716
|
+
McpErrorCode.DROPSHIPPING_PROJECT_DISABLED,
|
|
7717
|
+
McpErrorCode.DROPSHIPPING_PROJECT_CANDIDATE_NOT_READY,
|
|
7718
|
+
McpErrorCode.DROPSHIPPING_PROJECT_VERSION_CONFLICT,
|
|
7719
|
+
McpErrorCode.DROPSHIPPING_PROJECT_MEDIA_REQUIRED,
|
|
7720
|
+
McpErrorCode.KALODATA_NOT_CONFIGURED,
|
|
7721
|
+
McpErrorCode.META_AD_LIBRARY_NOT_CONFIGURED,
|
|
7722
|
+
McpErrorCode.PRODUCT_RESEARCH_DISABLED,
|
|
7332
7723
|
McpErrorCode.CREATIVE_VARIANT_DISPATCH_FAILED,
|
|
7333
7724
|
McpErrorCode.PRODUCT_RESEARCH_IDEMPOTENCY_CONFLICT,
|
|
7334
7725
|
// Shopify
|
|
@@ -7383,6 +7774,7 @@ var PASSTHROUGH_CODES = /* @__PURE__ */ new Set([
|
|
|
7383
7774
|
McpErrorCode.CAMPAIGN_MISSING_LANDING_URL,
|
|
7384
7775
|
McpErrorCode.CAMPAIGN_NO_CREATIVES,
|
|
7385
7776
|
McpErrorCode.CAMPAIGN_MISSING_THUMBNAILS,
|
|
7777
|
+
McpErrorCode.CAMPAIGN_RECONCILIATION_REQUIRED,
|
|
7386
7778
|
// Connections
|
|
7387
7779
|
McpErrorCode.NO_SHOPIFY_SHOPS,
|
|
7388
7780
|
McpErrorCode.NO_META_AD_ACCOUNTS,
|
|
@@ -7652,66 +8044,67 @@ function renderOutputsMarkdown(outputs) {
|
|
|
7652
8044
|
__name(renderOutputsMarkdown, "renderOutputsMarkdown");
|
|
7653
8045
|
|
|
7654
8046
|
// src/tools/tasks.ts
|
|
7655
|
-
var CreateProductTaskInput =
|
|
7656
|
-
images: ImagesInput,
|
|
7657
|
-
|
|
8047
|
+
var CreateProductTaskInput = z40.object({
|
|
8048
|
+
images: ImagesInput.optional().describe("1\u20135 fotos del mismo producto. Omitir \xFAnicamente cuando projectId apunta a un proyecto propio con imagen guardada."),
|
|
8049
|
+
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."),
|
|
8050
|
+
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."),
|
|
7658
8051
|
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.'),
|
|
7659
8052
|
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.'),
|
|
7660
|
-
price:
|
|
7661
|
-
compareAtPrice:
|
|
7662
|
-
offer:
|
|
7663
|
-
paymentMethods:
|
|
7664
|
-
productContext:
|
|
7665
|
-
productLabel:
|
|
7666
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla
|
|
7667
|
-
durationSeconds:
|
|
7668
|
-
|
|
7669
|
-
|
|
8053
|
+
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.'),
|
|
8054
|
+
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".'),
|
|
8055
|
+
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.'),
|
|
8056
|
+
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.'),
|
|
8057
|
+
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."),
|
|
8058
|
+
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.'),
|
|
8059
|
+
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.'),
|
|
8060
|
+
durationSeconds: z40.union([
|
|
8061
|
+
z40.literal(15),
|
|
8062
|
+
z40.literal(30)
|
|
7670
8063
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo del video: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
7671
|
-
pauseForAngleReview:
|
|
8064
|
+
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."),
|
|
7672
8065
|
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.'),
|
|
7673
8066
|
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).'),
|
|
7674
|
-
multiAngleVideos:
|
|
7675
|
-
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "
|
|
7676
|
-
outputs:
|
|
8067
|
+
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."),
|
|
8068
|
+
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.'),
|
|
8069
|
+
outputs: z40.array(z40.enum([
|
|
7677
8070
|
"landing",
|
|
7678
8071
|
"video",
|
|
7679
8072
|
"image"
|
|
7680
8073
|
])).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.'),
|
|
7681
|
-
competitorScanEnabled:
|
|
7682
|
-
brandId:
|
|
7683
|
-
creativeDirection:
|
|
8074
|
+
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."),
|
|
8075
|
+
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."),
|
|
8076
|
+
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.'),
|
|
7684
8077
|
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".'),
|
|
7685
8078
|
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".')
|
|
7686
8079
|
}).strict();
|
|
7687
|
-
var GetTaskStatusInput =
|
|
7688
|
-
taskId:
|
|
7689
|
-
waitSeconds:
|
|
7690
|
-
});
|
|
7691
|
-
var ListTasksInput =
|
|
7692
|
-
limit:
|
|
7693
|
-
offset:
|
|
7694
|
-
search:
|
|
7695
|
-
});
|
|
7696
|
-
var EditTaskDraftInput =
|
|
7697
|
-
taskId:
|
|
7698
|
-
angleIndex:
|
|
7699
|
-
angle:
|
|
7700
|
-
angle:
|
|
7701
|
-
buyerPersona:
|
|
7702
|
-
actor:
|
|
7703
|
-
gender:
|
|
8080
|
+
var GetTaskStatusInput = z40.object({
|
|
8081
|
+
taskId: z40.string().min(1),
|
|
8082
|
+
waitSeconds: z40.number().int().min(0).max(120).optional()
|
|
8083
|
+
});
|
|
8084
|
+
var ListTasksInput = z40.object({
|
|
8085
|
+
limit: z40.number().int().min(1).max(50).optional(),
|
|
8086
|
+
offset: z40.number().int().min(0).optional(),
|
|
8087
|
+
search: z40.string().optional()
|
|
8088
|
+
});
|
|
8089
|
+
var EditTaskDraftInput = z40.object({
|
|
8090
|
+
taskId: z40.string().min(1),
|
|
8091
|
+
angleIndex: z40.number().int().min(0),
|
|
8092
|
+
angle: z40.object({
|
|
8093
|
+
angle: z40.string().min(1).max(480),
|
|
8094
|
+
buyerPersona: z40.string().min(1).max(360),
|
|
8095
|
+
actor: z40.string().min(1).max(360).optional(),
|
|
8096
|
+
gender: z40.enum([
|
|
7704
8097
|
"female",
|
|
7705
8098
|
"male"
|
|
7706
8099
|
]).optional(),
|
|
7707
|
-
scriptNotes:
|
|
8100
|
+
scriptNotes: z40.string().max(2e3).optional()
|
|
7708
8101
|
})
|
|
7709
8102
|
});
|
|
7710
|
-
var PendingActionPayload =
|
|
7711
|
-
|
|
7712
|
-
kind:
|
|
8103
|
+
var PendingActionPayload = z40.discriminatedUnion("kind", [
|
|
8104
|
+
z40.object({
|
|
8105
|
+
kind: z40.literal("product_reference_confirmation"),
|
|
7713
8106
|
userChoice: ProductReferenceUserChoiceEnum,
|
|
7714
|
-
confirmedProductNames:
|
|
8107
|
+
confirmedProductNames: z40.array(z40.string().min(1).max(120)).min(2).max(8).optional(),
|
|
7715
8108
|
// SCOPED multi-scene opt-in — the ONLY way STANDARD ("Multiescena") is
|
|
7716
8109
|
// reachable via MCP. Valid ONLY together with userChoice='variants' (same
|
|
7717
8110
|
// product in several colors): renders one shot per color and stitches them,
|
|
@@ -7722,62 +8115,62 @@ var PendingActionPayload = z39.discriminatedUnion("kind", [
|
|
|
7722
8115
|
// safe because multi-scene IS the intended render for a color variant set,
|
|
7723
8116
|
// not a blind quality upsell. Maps to `videoTier: 'standard'` on the
|
|
7724
8117
|
// confirm call; the backend re-gates it (variants + variant_set only).
|
|
7725
|
-
useMultiSceneShowcase:
|
|
8118
|
+
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".')
|
|
7726
8119
|
}),
|
|
7727
|
-
|
|
7728
|
-
kind:
|
|
8120
|
+
z40.object({
|
|
8121
|
+
kind: z40.literal("angle_review_approval"),
|
|
7729
8122
|
// All edits are optional — empty action body just approves the
|
|
7730
8123
|
// backend-generated draft as-is. Field shapes mirror the angle-review
|
|
7731
8124
|
// request contracts in @packages/types/wizard.ts; the handler routes to
|
|
7732
8125
|
// the dedicated video/image/autopilot endpoint based on StatusResponse.kind.
|
|
7733
|
-
customAngle:
|
|
8126
|
+
customAngle: z40.string().min(1).max(480).optional(),
|
|
7734
8127
|
// Keep the shared MCP action within the strictest downstream contract:
|
|
7735
8128
|
// autopilot/image resume endpoints cap these fields at 1500 characters.
|
|
7736
|
-
painPoints:
|
|
7737
|
-
benefits:
|
|
7738
|
-
features:
|
|
7739
|
-
gapDurationSeconds:
|
|
7740
|
-
|
|
7741
|
-
|
|
8129
|
+
painPoints: z40.string().max(1500).optional(),
|
|
8130
|
+
benefits: z40.string().max(1500).optional(),
|
|
8131
|
+
features: z40.array(z40.string().min(1).max(300)).max(10).optional(),
|
|
8132
|
+
gapDurationSeconds: z40.union([
|
|
8133
|
+
z40.literal(15),
|
|
8134
|
+
z40.literal(30)
|
|
7742
8135
|
]).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.")
|
|
7743
8136
|
})
|
|
7744
8137
|
]);
|
|
7745
|
-
var ResolvePendingActionInput =
|
|
7746
|
-
taskId:
|
|
8138
|
+
var ResolvePendingActionInput = z40.object({
|
|
8139
|
+
taskId: z40.string().min(1),
|
|
7747
8140
|
action: PendingActionPayload
|
|
7748
8141
|
}).strict();
|
|
7749
8142
|
function resolveVariantConfirmVideoTier(action) {
|
|
7750
8143
|
return action.useMultiSceneShowcase && action.userChoice === "variants" ? "standard" : void 0;
|
|
7751
8144
|
}
|
|
7752
8145
|
__name(resolveVariantConfirmVideoTier, "resolveVariantConfirmVideoTier");
|
|
7753
|
-
var StatusForResolveSchema =
|
|
8146
|
+
var StatusForResolveSchema = z40.object({
|
|
7754
8147
|
// Metadata used to select the backend resume contract. Older API responses
|
|
7755
8148
|
// may omit these fields, so the resolver keeps the generic fallback.
|
|
7756
|
-
kind:
|
|
8149
|
+
kind: z40.enum([
|
|
7757
8150
|
"autopilot",
|
|
7758
8151
|
"video",
|
|
7759
8152
|
"image",
|
|
7760
8153
|
"landing",
|
|
7761
8154
|
"mix"
|
|
7762
8155
|
]).optional(),
|
|
7763
|
-
selectedOutputs:
|
|
8156
|
+
selectedOutputs: z40.array(z40.enum([
|
|
7764
8157
|
"landing",
|
|
7765
8158
|
"video",
|
|
7766
8159
|
"image"
|
|
7767
8160
|
])).optional(),
|
|
7768
|
-
videoAngleCount:
|
|
7769
|
-
ugcFormat:
|
|
8161
|
+
videoAngleCount: z40.number().int().min(1).max(3).optional(),
|
|
8162
|
+
ugcFormat: z40.enum([
|
|
7770
8163
|
"single_8s",
|
|
7771
8164
|
"single_15s",
|
|
7772
8165
|
"double_30s"
|
|
7773
8166
|
]).optional(),
|
|
7774
|
-
videoStyle:
|
|
8167
|
+
videoStyle: z40.enum([
|
|
7775
8168
|
"ugc",
|
|
7776
8169
|
"cartoon_3d",
|
|
7777
8170
|
"product_only",
|
|
7778
8171
|
"ai_dynamic"
|
|
7779
8172
|
]).optional(),
|
|
7780
|
-
videoModel:
|
|
8173
|
+
videoModel: z40.enum([
|
|
7781
8174
|
"veo",
|
|
7782
8175
|
"wan",
|
|
7783
8176
|
"bytedance",
|
|
@@ -7785,26 +8178,26 @@ var StatusForResolveSchema = z39.object({
|
|
|
7785
8178
|
"grok",
|
|
7786
8179
|
"kling"
|
|
7787
8180
|
]).optional(),
|
|
7788
|
-
videoTier:
|
|
8181
|
+
videoTier: z40.enum([
|
|
7789
8182
|
"legacy",
|
|
7790
8183
|
"standard",
|
|
7791
8184
|
"pro",
|
|
7792
8185
|
"single_call"
|
|
7793
8186
|
]).optional(),
|
|
7794
|
-
videoResolution:
|
|
8187
|
+
videoResolution: z40.enum([
|
|
7795
8188
|
"480p",
|
|
7796
8189
|
"720p"
|
|
7797
8190
|
]).optional(),
|
|
7798
8191
|
narrativeStyle: NarrativeStyleEnum.optional(),
|
|
7799
|
-
pendingUserAction:
|
|
7800
|
-
kind:
|
|
7801
|
-
candidateGrouping:
|
|
7802
|
-
selectedImageUrls:
|
|
7803
|
-
proposedProductNames:
|
|
7804
|
-
customAngleDraft:
|
|
7805
|
-
painPointsDraft:
|
|
7806
|
-
benefitsDraft:
|
|
7807
|
-
featuresDraft:
|
|
8192
|
+
pendingUserAction: z40.object({
|
|
8193
|
+
kind: z40.string(),
|
|
8194
|
+
candidateGrouping: z40.string().optional(),
|
|
8195
|
+
selectedImageUrls: z40.array(z40.string()).optional(),
|
|
8196
|
+
proposedProductNames: z40.array(z40.string()).optional(),
|
|
8197
|
+
customAngleDraft: z40.string().optional(),
|
|
8198
|
+
painPointsDraft: z40.string().optional(),
|
|
8199
|
+
benefitsDraft: z40.string().optional(),
|
|
8200
|
+
featuresDraft: z40.array(z40.string()).optional(),
|
|
7808
8201
|
// Recommendation consumed only when the caller explicitly sends
|
|
7809
8202
|
// gapDurationSeconds: 30 in the angle approval action.
|
|
7810
8203
|
gapDurationChoice: GapDurationChoiceMirror.optional()
|
|
@@ -7845,11 +8238,14 @@ function resolveStatusTaskKind(status) {
|
|
|
7845
8238
|
}
|
|
7846
8239
|
__name(resolveStatusTaskKind, "resolveStatusTaskKind");
|
|
7847
8240
|
function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http" } = {}) {
|
|
7848
|
-
server.tool("create_product_task",
|
|
8241
|
+
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) => {
|
|
7849
8242
|
try {
|
|
7850
|
-
|
|
8243
|
+
if (!input.images && !input.projectId) {
|
|
8244
|
+
throw new Error("images es requerido salvo que env\xEDes projectId.");
|
|
8245
|
+
}
|
|
8246
|
+
const imgs = input.images ? await resolveImages(input.images, {
|
|
7851
8247
|
transport
|
|
7852
|
-
});
|
|
8248
|
+
}) : [];
|
|
7853
8249
|
const parts = imgs.map((img, i) => ({
|
|
7854
8250
|
...img,
|
|
7855
8251
|
filename: `image-${i}.png`
|
|
@@ -7860,6 +8256,7 @@ function registerTaskTools(server, api, { proxyBaseUrl = null, transport = "http
|
|
|
7860
8256
|
const fields = flatten({
|
|
7861
8257
|
"options.languageCode": input.language,
|
|
7862
8258
|
"options.country": input.country,
|
|
8259
|
+
"options.dropshippingProjectId": input.projectId,
|
|
7863
8260
|
"options.price": input.price,
|
|
7864
8261
|
"options.compareAtPrice": input.compareAtPrice,
|
|
7865
8262
|
"options.offer": input.offer,
|
|
@@ -8126,54 +8523,54 @@ __name(registerTaskTools, "registerTaskTools");
|
|
|
8126
8523
|
|
|
8127
8524
|
// src/tools/creatives.ts
|
|
8128
8525
|
import { randomUUID } from "crypto";
|
|
8129
|
-
import { z as
|
|
8526
|
+
import { z as z41 } from "zod";
|
|
8130
8527
|
var CreativeRefs = {
|
|
8131
8528
|
images: ImagesInput,
|
|
8132
8529
|
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.'),
|
|
8133
8530
|
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.'),
|
|
8134
|
-
price:
|
|
8135
|
-
offer:
|
|
8136
|
-
compareAtPrice:
|
|
8137
|
-
paymentMethods:
|
|
8138
|
-
productContext:
|
|
8139
|
-
productLabel:
|
|
8140
|
-
buyerPersona:
|
|
8141
|
-
isCombo:
|
|
8142
|
-
competitorScanEnabled:
|
|
8143
|
-
brandId:
|
|
8144
|
-
creativeDirection:
|
|
8531
|
+
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.'),
|
|
8532
|
+
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.'),
|
|
8533
|
+
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".'),
|
|
8534
|
+
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.'),
|
|
8535
|
+
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."),
|
|
8536
|
+
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.'),
|
|
8537
|
+
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.'),
|
|
8538
|
+
isCombo: z41.boolean().optional().describe("Opcional. Si true, el creativo presenta el producto como combo/pack. Default false."),
|
|
8539
|
+
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."),
|
|
8540
|
+
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."),
|
|
8541
|
+
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.')
|
|
8145
8542
|
};
|
|
8146
|
-
var VideoInput =
|
|
8543
|
+
var VideoInput = z41.object({
|
|
8147
8544
|
images: CreativeRefs.images,
|
|
8148
|
-
title:
|
|
8149
|
-
primaryAngle:
|
|
8545
|
+
title: z41.string().min(1).describe('T\xEDtulo corto del producto. Aparece en la primera vista del video. Ej. "Crema Anti-Edad Premium".'),
|
|
8546
|
+
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".'),
|
|
8150
8547
|
language: CreativeRefs.language,
|
|
8151
8548
|
country: CreativeRefs.country,
|
|
8152
|
-
aspectRatio:
|
|
8549
|
+
aspectRatio: z41.enum([
|
|
8153
8550
|
"9:16",
|
|
8154
8551
|
"16:9",
|
|
8155
8552
|
"Auto"
|
|
8156
8553
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
8157
|
-
durationSeconds:
|
|
8158
|
-
|
|
8159
|
-
|
|
8554
|
+
durationSeconds: z41.union([
|
|
8555
|
+
z41.literal(15),
|
|
8556
|
+
z41.literal(30)
|
|
8160
8557
|
]).default(15).describe("Opcional. Duraci\xF3n objetivo: 15s (single_call, default) o 30s (Multiescena, aproximadamente 30s y facturado por escena)."),
|
|
8161
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla
|
|
8558
|
+
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).'),
|
|
8162
8559
|
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.'),
|
|
8163
8560
|
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).'),
|
|
8164
|
-
features:
|
|
8561
|
+
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"].'),
|
|
8165
8562
|
price: CreativeRefs.price,
|
|
8166
8563
|
offer: CreativeRefs.offer,
|
|
8167
8564
|
productContext: CreativeRefs.productContext,
|
|
8168
8565
|
productLabel: CreativeRefs.productLabel,
|
|
8169
|
-
cta:
|
|
8170
|
-
scriptNotes:
|
|
8171
|
-
pauseForVideoScriptReview:
|
|
8172
|
-
pauseForAngleReview:
|
|
8566
|
+
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.'),
|
|
8567
|
+
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.'),
|
|
8568
|
+
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."),
|
|
8569
|
+
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."),
|
|
8173
8570
|
competitorScanEnabled: CreativeRefs.competitorScanEnabled,
|
|
8174
8571
|
brandId: CreativeRefs.brandId
|
|
8175
8572
|
}).strict();
|
|
8176
|
-
var FreeVideoQualityEnum =
|
|
8573
|
+
var FreeVideoQualityEnum = z41.enum([
|
|
8177
8574
|
"economical",
|
|
8178
8575
|
"high_detail"
|
|
8179
8576
|
]);
|
|
@@ -8195,38 +8592,38 @@ var FREE_VIDEO_DURATIONS_BY_QUALITY = {
|
|
|
8195
8592
|
15
|
|
8196
8593
|
]
|
|
8197
8594
|
};
|
|
8198
|
-
var FreeVideoInput =
|
|
8595
|
+
var FreeVideoInput = z41.object({
|
|
8199
8596
|
images: ImagesInput.optional().describe("Opcional. 1-5 fotos del producto. Om\xEDtelo para generar desde texto puro."),
|
|
8200
|
-
rawPrompt:
|
|
8597
|
+
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."),
|
|
8201
8598
|
quality: FreeVideoQualityEnum.describe('Calidad del video: "economical" = Econ\xF3mico o "high_detail" = Alto detalle.'),
|
|
8202
|
-
durationSeconds:
|
|
8599
|
+
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."),
|
|
8203
8600
|
videoResolution: VideoResolutionEnum.describe("Resoluci\xF3n del video: 480p o 720p."),
|
|
8204
|
-
generateAiMusic:
|
|
8205
|
-
addSubtitles:
|
|
8206
|
-
idempotencyKey:
|
|
8601
|
+
generateAiMusic: z41.boolean().default(false).describe("Opcional. Agrega m\xFAsica instrumental IA debajo del audio nativo. Default false."),
|
|
8602
|
+
addSubtitles: z41.boolean().default(false).describe("Opcional. Quema subt\xEDtulos usando el rawPrompt exacto. Default false."),
|
|
8603
|
+
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.")
|
|
8207
8604
|
}).strict();
|
|
8208
8605
|
var imageStyleList = ImageCreativeStyleEnum.options.join(" | ");
|
|
8209
8606
|
var archetypeList = ImageCreativeArchetypeEnum.options.join(" | ");
|
|
8210
8607
|
var visualTreatmentList = ImageCreativeVisualTreatmentEnum.options.join(" | ");
|
|
8211
8608
|
var aspectRatioList = ImageCreativeAspectRatioEnum.options.join(" | ");
|
|
8212
|
-
var ImageInput =
|
|
8609
|
+
var ImageInput = z41.object({
|
|
8213
8610
|
images: CreativeRefs.images,
|
|
8214
|
-
productTitle:
|
|
8215
|
-
primaryAngle:
|
|
8611
|
+
productTitle: z41.string().min(1).describe('Nombre del producto. Ej. "Crema Anti-Edad Premium".'),
|
|
8612
|
+
primaryAngle: z41.string().min(1).describe('\xC1ngulo de venta principal. Ej. "Reduce arrugas en 14 d\xEDas".'),
|
|
8216
8613
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
8217
8614
|
language: CreativeRefs.language,
|
|
8218
8615
|
country: CreativeRefs.country,
|
|
8219
|
-
nVariants:
|
|
8220
|
-
imageModel:
|
|
8616
|
+
nVariants: z41.number().int().min(1).max(6).optional().describe("Opcional. N\xFAmero de variantes a generar (1-6). Default 3."),
|
|
8617
|
+
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.'),
|
|
8221
8618
|
imageStyle: ImageCreativeStyleEnum.optional().describe(`Opcional. Estilo del shot del producto. Valores: ${imageStyleList}. Si se omite, la IA escoge seg\xFAn el archetype.`),
|
|
8222
8619
|
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).`),
|
|
8223
8620
|
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.`),
|
|
8224
|
-
styleMix:
|
|
8621
|
+
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."),
|
|
8225
8622
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe(`Opcional. Relaci\xF3n de aspecto. Valores: ${aspectRatioList}. Default "4:5" (vertical Instagram feed).`),
|
|
8226
|
-
generateAdCopy:
|
|
8227
|
-
pauseForAngleReview:
|
|
8228
|
-
features:
|
|
8229
|
-
brandColors:
|
|
8623
|
+
generateAdCopy: z41.boolean().optional().describe("Opcional. Si true, tambi\xE9n genera headline/body/CTA para el ad. Default false."),
|
|
8624
|
+
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."),
|
|
8625
|
+
features: z41.array(z41.string()).optional().describe('Opcional. Features/beneficios a destacar visualmente. Ej. ["resistente al agua", "ultra liviano"].'),
|
|
8626
|
+
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.'),
|
|
8230
8627
|
price: CreativeRefs.price,
|
|
8231
8628
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
8232
8629
|
offer: CreativeRefs.offer,
|
|
@@ -8237,11 +8634,11 @@ var ImageInput = z40.object({
|
|
|
8237
8634
|
brandId: CreativeRefs.brandId,
|
|
8238
8635
|
creativeDirection: CreativeRefs.creativeDirection
|
|
8239
8636
|
});
|
|
8240
|
-
var LandingInput =
|
|
8637
|
+
var LandingInput = z41.object({
|
|
8241
8638
|
images: CreativeRefs.images,
|
|
8242
8639
|
language: CreativeRefs.language,
|
|
8243
8640
|
country: CreativeRefs.country,
|
|
8244
|
-
salesAngle:
|
|
8641
|
+
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.'),
|
|
8245
8642
|
buyerPersona: CreativeRefs.buyerPersona,
|
|
8246
8643
|
price: CreativeRefs.price,
|
|
8247
8644
|
compareAtPrice: CreativeRefs.compareAtPrice,
|
|
@@ -8339,8 +8736,8 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
8339
8736
|
__name(registerCreativeTools, "registerCreativeTools");
|
|
8340
8737
|
|
|
8341
8738
|
// src/tools/creative-variants.ts
|
|
8342
|
-
import { z as
|
|
8343
|
-
var LandingSectionKeyEnum =
|
|
8739
|
+
import { z as z42 } from "zod";
|
|
8740
|
+
var LandingSectionKeyEnum = z42.enum([
|
|
8344
8741
|
"problem_hook",
|
|
8345
8742
|
"problem_cost",
|
|
8346
8743
|
"solution_mechanism",
|
|
@@ -8380,24 +8777,24 @@ var LandingSectionKeyEnum = z41.enum([
|
|
|
8380
8777
|
"lifestyle_fit",
|
|
8381
8778
|
"join_lifestyle"
|
|
8382
8779
|
]);
|
|
8383
|
-
var CreativeVariantKindEnum =
|
|
8780
|
+
var CreativeVariantKindEnum = z42.enum([
|
|
8384
8781
|
"video",
|
|
8385
8782
|
"image",
|
|
8386
8783
|
"landing"
|
|
8387
8784
|
]);
|
|
8388
|
-
var EstimateCreativeVariantInputBase =
|
|
8389
|
-
sourceTaskId:
|
|
8785
|
+
var EstimateCreativeVariantInputBase = z42.object({
|
|
8786
|
+
sourceTaskId: z42.string().uuid().describe("ID de la tarea original completada."),
|
|
8390
8787
|
kind: CreativeVariantKindEnum,
|
|
8391
8788
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Solo cambia el preset p\xFAblico; el servidor conserva el modelo/tier del task origen."),
|
|
8392
8789
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video. Resoluci\xF3n del nuevo render."),
|
|
8393
|
-
nVariants:
|
|
8790
|
+
nVariants: z42.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
8394
8791
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si ya conoces la secci\xF3n, evita cotizar la clasificaci\xF3n con IA."),
|
|
8395
|
-
instructions:
|
|
8792
|
+
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.")
|
|
8396
8793
|
}).strict();
|
|
8397
8794
|
var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
8398
8795
|
if (input.kind === "video" && input.nVariants !== void 0) {
|
|
8399
8796
|
ctx.addIssue({
|
|
8400
|
-
code:
|
|
8797
|
+
code: z42.ZodIssueCode.custom,
|
|
8401
8798
|
path: [
|
|
8402
8799
|
"nVariants"
|
|
8403
8800
|
],
|
|
@@ -8407,7 +8804,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8407
8804
|
if (input.kind !== "video") {
|
|
8408
8805
|
if (input.videoPreset !== void 0) {
|
|
8409
8806
|
ctx.addIssue({
|
|
8410
|
-
code:
|
|
8807
|
+
code: z42.ZodIssueCode.custom,
|
|
8411
8808
|
path: [
|
|
8412
8809
|
"videoPreset"
|
|
8413
8810
|
],
|
|
@@ -8416,7 +8813,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8416
8813
|
}
|
|
8417
8814
|
if (input.videoResolution !== void 0) {
|
|
8418
8815
|
ctx.addIssue({
|
|
8419
|
-
code:
|
|
8816
|
+
code: z42.ZodIssueCode.custom,
|
|
8420
8817
|
path: [
|
|
8421
8818
|
"videoResolution"
|
|
8422
8819
|
],
|
|
@@ -8426,7 +8823,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8426
8823
|
}
|
|
8427
8824
|
if (input.kind !== "image" && input.nVariants !== void 0) {
|
|
8428
8825
|
ctx.addIssue({
|
|
8429
|
-
code:
|
|
8826
|
+
code: z42.ZodIssueCode.custom,
|
|
8430
8827
|
path: [
|
|
8431
8828
|
"nVariants"
|
|
8432
8829
|
],
|
|
@@ -8436,7 +8833,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8436
8833
|
if (input.kind !== "landing") {
|
|
8437
8834
|
if (input.sectionKey !== void 0) {
|
|
8438
8835
|
ctx.addIssue({
|
|
8439
|
-
code:
|
|
8836
|
+
code: z42.ZodIssueCode.custom,
|
|
8440
8837
|
path: [
|
|
8441
8838
|
"sectionKey"
|
|
8442
8839
|
],
|
|
@@ -8445,7 +8842,7 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8445
8842
|
}
|
|
8446
8843
|
if (input.instructions !== void 0) {
|
|
8447
8844
|
ctx.addIssue({
|
|
8448
|
-
code:
|
|
8845
|
+
code: z42.ZodIssueCode.custom,
|
|
8449
8846
|
path: [
|
|
8450
8847
|
"instructions"
|
|
8451
8848
|
],
|
|
@@ -8454,31 +8851,31 @@ var EstimateCreativeVariantInput = EstimateCreativeVariantInputBase.superRefine(
|
|
|
8454
8851
|
}
|
|
8455
8852
|
}
|
|
8456
8853
|
});
|
|
8457
|
-
var CreateCreativeVariantInputBase =
|
|
8458
|
-
sourceTaskId:
|
|
8854
|
+
var CreateCreativeVariantInputBase = z42.object({
|
|
8855
|
+
sourceTaskId: z42.string().uuid().describe("ID de la tarea original completada."),
|
|
8459
8856
|
kind: CreativeVariantKindEnum,
|
|
8460
|
-
confirm:
|
|
8461
|
-
clientRequestId:
|
|
8462
|
-
angle:
|
|
8463
|
-
buyerPersona:
|
|
8464
|
-
scriptNotes:
|
|
8465
|
-
creativeDirection:
|
|
8857
|
+
confirm: z42.literal(true).describe("Confirmaci\xF3n expl\xEDcita del usuario despu\xE9s de mostrarle el estimado de cr\xE9ditos."),
|
|
8858
|
+
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."),
|
|
8859
|
+
angle: z42.string().trim().min(1).max(500).optional().describe("\xC1ngulo nuevo para video o imagen."),
|
|
8860
|
+
buyerPersona: z42.string().trim().min(1).max(360).optional().describe("Buyer persona coherente con el \xE1ngulo."),
|
|
8861
|
+
scriptNotes: z42.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n breve del guion para una variante de video."),
|
|
8862
|
+
creativeDirection: z42.string().trim().min(1).max(2e3).optional().describe("Direcci\xF3n creativa para una variante de imagen."),
|
|
8466
8863
|
videoPreset: TaskCreativeVariantVideoPresetEnum.optional().describe("Opcional para video. Preset p\xFAblico; el servidor resuelve modelo/tier desde el task origen."),
|
|
8467
8864
|
videoResolution: VideoResolutionEnum.optional().describe("Opcional para video."),
|
|
8468
|
-
generateAiMusic:
|
|
8469
|
-
nVariants:
|
|
8865
|
+
generateAiMusic: z42.boolean().optional().describe("Opcional para video."),
|
|
8866
|
+
nVariants: z42.number().int().min(1).max(3).optional().describe("Opcional para imagen. N\xFAmero de im\xE1genes adicionales (1-3)."),
|
|
8470
8867
|
imageStyle: ImageCreativeStyleEnum.optional().describe("Opcional para imagen."),
|
|
8471
8868
|
creativeArchetype: ImageCreativeArchetypeEnum.optional().describe("Opcional para imagen."),
|
|
8472
8869
|
visualTreatment: ImageCreativeVisualTreatmentEnum.optional().describe("Opcional para imagen."),
|
|
8473
8870
|
aspectRatio: ImageCreativeAspectRatioEnum.optional().describe("Opcional para imagen."),
|
|
8474
|
-
styleMix:
|
|
8871
|
+
styleMix: z42.boolean().optional().describe("Opcional para imagen."),
|
|
8475
8872
|
sectionKey: LandingSectionKeyEnum.optional().describe("Opcional para landing. Si se omite, se clasifica con IA a partir de instructions."),
|
|
8476
|
-
instructions:
|
|
8873
|
+
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.")
|
|
8477
8874
|
}).strict();
|
|
8478
8875
|
var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((input, ctx) => {
|
|
8479
8876
|
if ((input.kind === "video" || input.kind === "image") && !input.angle) {
|
|
8480
8877
|
ctx.addIssue({
|
|
8481
|
-
code:
|
|
8878
|
+
code: z42.ZodIssueCode.custom,
|
|
8482
8879
|
path: [
|
|
8483
8880
|
"angle"
|
|
8484
8881
|
],
|
|
@@ -8487,7 +8884,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
8487
8884
|
}
|
|
8488
8885
|
if (input.kind === "landing" && !input.sectionKey && !input.instructions) {
|
|
8489
8886
|
ctx.addIssue({
|
|
8490
|
-
code:
|
|
8887
|
+
code: z42.ZodIssueCode.custom,
|
|
8491
8888
|
path: [
|
|
8492
8889
|
"instructions"
|
|
8493
8890
|
],
|
|
@@ -8533,7 +8930,7 @@ var CreateCreativeVariantInput = CreateCreativeVariantInputBase.superRefine((inp
|
|
|
8533
8930
|
for (const field of fieldsByKind[input.kind]) {
|
|
8534
8931
|
if (input[field] !== void 0) {
|
|
8535
8932
|
ctx.addIssue({
|
|
8536
|
-
code:
|
|
8933
|
+
code: z42.ZodIssueCode.custom,
|
|
8537
8934
|
path: [
|
|
8538
8935
|
field
|
|
8539
8936
|
],
|
|
@@ -8650,27 +9047,27 @@ function registerCreativeVariantTools(server, api) {
|
|
|
8650
9047
|
__name(registerCreativeVariantTools, "registerCreativeVariantTools");
|
|
8651
9048
|
|
|
8652
9049
|
// src/tools/script-review.ts
|
|
8653
|
-
import { z as
|
|
8654
|
-
var GetVideoScriptInput =
|
|
8655
|
-
taskId:
|
|
8656
|
-
angleKey:
|
|
9050
|
+
import { z as z43 } from "zod";
|
|
9051
|
+
var GetVideoScriptInput = z43.object({
|
|
9052
|
+
taskId: z43.string().min(1).describe("ID de la tarea (la misma que devolvi\xF3 create_product_task / generate_video_creative)."),
|
|
9053
|
+
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.')
|
|
8657
9054
|
}).strict();
|
|
8658
9055
|
var VIDEO_SCRIPT_APPROVAL_MAX_SCENES2 = 50;
|
|
8659
9056
|
var VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2 = 2e3;
|
|
8660
|
-
var ApproveSceneEdit =
|
|
8661
|
-
index:
|
|
8662
|
-
dialogue:
|
|
9057
|
+
var ApproveSceneEdit = z43.object({
|
|
9058
|
+
index: z43.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
9059
|
+
dialogue: z43.string().min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS2).refine((v) => v.trim().length > 0, {
|
|
8663
9060
|
message: "dialogue no puede ser s\xF3lo espacios"
|
|
8664
9061
|
}).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.")
|
|
8665
9062
|
}).strict();
|
|
8666
|
-
var ApproveVideoScriptInput =
|
|
8667
|
-
taskId:
|
|
8668
|
-
angleKey:
|
|
8669
|
-
scenes:
|
|
9063
|
+
var ApproveVideoScriptInput = z43.object({
|
|
9064
|
+
taskId: z43.string().min(1).describe("ID de la tarea."),
|
|
9065
|
+
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.'),
|
|
9066
|
+
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.")
|
|
8670
9067
|
}).strict();
|
|
8671
|
-
var RegenerateVideoScriptInput =
|
|
8672
|
-
taskId:
|
|
8673
|
-
angleKey:
|
|
9068
|
+
var RegenerateVideoScriptInput = z43.object({
|
|
9069
|
+
taskId: z43.string().min(1).describe("ID de la tarea."),
|
|
9070
|
+
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.'),
|
|
8674
9071
|
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).')
|
|
8675
9072
|
}).strict();
|
|
8676
9073
|
function registerScriptReviewTools(server, api) {
|
|
@@ -8710,9 +9107,9 @@ function registerScriptReviewTools(server, api) {
|
|
|
8710
9107
|
__name(registerScriptReviewTools, "registerScriptReviewTools");
|
|
8711
9108
|
|
|
8712
9109
|
// src/tools/connections.ts
|
|
8713
|
-
import { z as
|
|
9110
|
+
import { z as z44 } from "zod";
|
|
8714
9111
|
function registerConnectionTools(server, api) {
|
|
8715
|
-
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.",
|
|
9112
|
+
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 () => {
|
|
8716
9113
|
try {
|
|
8717
9114
|
const r = await api.getJson("/v1/shopify/shops");
|
|
8718
9115
|
return asText(r);
|
|
@@ -8720,10 +9117,10 @@ function registerConnectionTools(server, api) {
|
|
|
8720
9117
|
throw translateError(e);
|
|
8721
9118
|
}
|
|
8722
9119
|
});
|
|
8723
|
-
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.',
|
|
8724
|
-
shopDomain:
|
|
8725
|
-
query:
|
|
8726
|
-
taskId:
|
|
9120
|
+
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({
|
|
9121
|
+
shopDomain: z44.string().min(3).max(120),
|
|
9122
|
+
query: z44.string().trim().max(120).optional(),
|
|
9123
|
+
taskId: z44.string().uuid().optional()
|
|
8727
9124
|
}).shape, async ({ shopDomain, query, taskId }) => {
|
|
8728
9125
|
try {
|
|
8729
9126
|
const params = new URLSearchParams({
|
|
@@ -8737,7 +9134,7 @@ function registerConnectionTools(server, api) {
|
|
|
8737
9134
|
throw translateError(e);
|
|
8738
9135
|
}
|
|
8739
9136
|
});
|
|
8740
|
-
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.",
|
|
9137
|
+
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 () => {
|
|
8741
9138
|
try {
|
|
8742
9139
|
const r = await api.getJson("/v1/facebook/ad-accounts");
|
|
8743
9140
|
return asText(r);
|
|
@@ -8745,7 +9142,7 @@ function registerConnectionTools(server, api) {
|
|
|
8745
9142
|
throw translateError(e);
|
|
8746
9143
|
}
|
|
8747
9144
|
});
|
|
8748
|
-
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.",
|
|
9145
|
+
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 () => {
|
|
8749
9146
|
try {
|
|
8750
9147
|
const r = await api.getJson("/v1/tiktok/advertisers");
|
|
8751
9148
|
return asText(r);
|
|
@@ -8757,105 +9154,105 @@ function registerConnectionTools(server, api) {
|
|
|
8757
9154
|
__name(registerConnectionTools, "registerConnectionTools");
|
|
8758
9155
|
|
|
8759
9156
|
// src/tools/publish.ts
|
|
8760
|
-
import { z as
|
|
8761
|
-
var ShopifyInput =
|
|
8762
|
-
taskId:
|
|
8763
|
-
shopDomain:
|
|
9157
|
+
import { z as z45 } from "zod";
|
|
9158
|
+
var ShopifyInput = z45.object({
|
|
9159
|
+
taskId: z45.string().min(1),
|
|
9160
|
+
shopDomain: z45.string().min(1),
|
|
8764
9161
|
/** Override: number of landing images to include. Default = ALL images the
|
|
8765
9162
|
* task generated (the MCP fetches /v1/results first to count). Bounded
|
|
8766
9163
|
* generously here; the backend validates each index against
|
|
8767
9164
|
* landing.images.length and rejects out-of-range. */
|
|
8768
|
-
numLandingImages:
|
|
8769
|
-
variantIndex:
|
|
9165
|
+
numLandingImages: z45.number().int().min(1).max(20).optional(),
|
|
9166
|
+
variantIndex: z45.number().int().min(0).optional(),
|
|
8770
9167
|
/** ASK THE USER before setting: "¿Tu producto tiene variantes (talla, color, etc.)?".
|
|
8771
9168
|
* When true, the landing renders variant-picker pills; when false, it ships
|
|
8772
9169
|
* a single-option product page. Defaults to false. */
|
|
8773
|
-
showVariantPicker:
|
|
9170
|
+
showVariantPicker: z45.boolean().optional(),
|
|
8774
9171
|
/** Default `auto` updates the product previously published for this task and
|
|
8775
9172
|
* shop. Use `existing` with targetProductId to choose another product, or
|
|
8776
9173
|
* `new` only when the user explicitly wants a duplicate/new listing. */
|
|
8777
|
-
publicationMode:
|
|
9174
|
+
publicationMode: z45.enum([
|
|
8778
9175
|
"auto",
|
|
8779
9176
|
"existing",
|
|
8780
9177
|
"new"
|
|
8781
9178
|
]).optional(),
|
|
8782
9179
|
/** Shopify product GID, numeric id, or admin product URL. Required when
|
|
8783
9180
|
* publicationMode is `existing`. */
|
|
8784
|
-
targetProductId:
|
|
9181
|
+
targetProductId: z45.string().trim().min(1).max(300).optional()
|
|
8785
9182
|
});
|
|
8786
|
-
var McpCampaignConfig =
|
|
9183
|
+
var McpCampaignConfig = z45.object({
|
|
8787
9184
|
/** ALWAYS in US dollars, whatever the ad account's currency is. ProductMaker
|
|
8788
9185
|
* converts to the account currency server-side. Do NOT pre-convert: on a COP
|
|
8789
9186
|
* account the user's "60.000 al día" is `dailyBudgetUsd: 15`, not 60000. */
|
|
8790
|
-
dailyBudgetUsd:
|
|
9187
|
+
dailyBudgetUsd: z45.number().positive().optional(),
|
|
8791
9188
|
/** ISO-3166-1 alpha-2 country codes. Meta accepts max 1 (single-country
|
|
8792
9189
|
* ad set). TikTok takes only the first entry. */
|
|
8793
|
-
targetCountries:
|
|
8794
|
-
campaignName:
|
|
9190
|
+
targetCountries: z45.array(z45.string().length(2)).max(1).optional(),
|
|
9191
|
+
campaignName: z45.string().trim().min(1).max(100).optional()
|
|
8795
9192
|
});
|
|
8796
9193
|
var McpAdAccountId = MetaAdAccountId.describe('Meta ad account id. Accepts "act_1234567890" or the bare numeric id "1234567890".');
|
|
8797
|
-
var MetaInput =
|
|
8798
|
-
taskId:
|
|
9194
|
+
var MetaInput = z45.object({
|
|
9195
|
+
taskId: z45.string().min(1),
|
|
8799
9196
|
adAccountId: McpAdAccountId,
|
|
8800
|
-
pixelId:
|
|
8801
|
-
landingUrl:
|
|
9197
|
+
pixelId: z45.string().min(1).optional(),
|
|
9198
|
+
landingUrl: z45.string().url().optional(),
|
|
8802
9199
|
/** Select which angles to publish by 0-based index. Omit to publish all
|
|
8803
9200
|
* successful angles. Example: a task with 3 angles → `[0,2]` publishes #0 + #2. */
|
|
8804
|
-
angleIndexes:
|
|
9201
|
+
angleIndexes: z45.array(z45.number().int().nonnegative()).optional(),
|
|
8805
9202
|
campaignConfig: McpCampaignConfig.optional(),
|
|
8806
9203
|
/** Override the ad's primary text (body copy). If omitted, ProductMaker
|
|
8807
9204
|
* uses the auto-generated copy attached to the task. Capped at 500 chars
|
|
8808
9205
|
* (Meta's primary-text limit). */
|
|
8809
|
-
primaryText:
|
|
9206
|
+
primaryText: z45.string().trim().min(1).max(500).optional(),
|
|
8810
9207
|
/** Optional WhatsApp number. When set, the ad button opens a WhatsApp chat
|
|
8811
9208
|
* (wa.me) instead of a landing page. */
|
|
8812
|
-
phoneNumber:
|
|
9209
|
+
phoneNumber: z45.string().min(8).max(32).optional()
|
|
8813
9210
|
});
|
|
8814
|
-
var GroupedTaskSource =
|
|
8815
|
-
type:
|
|
8816
|
-
taskId:
|
|
8817
|
-
angleIndex:
|
|
8818
|
-
videoVariant:
|
|
9211
|
+
var GroupedTaskSource = z45.object({
|
|
9212
|
+
type: z45.literal("task"),
|
|
9213
|
+
taskId: z45.string().min(1),
|
|
9214
|
+
angleIndex: z45.number().int().min(0).optional(),
|
|
9215
|
+
videoVariant: z45.enum([
|
|
8819
9216
|
"with_subtitles",
|
|
8820
9217
|
"without_subtitles"
|
|
8821
9218
|
]).optional(),
|
|
8822
|
-
imageVariantIndex:
|
|
8823
|
-
});
|
|
8824
|
-
var GroupedMediaSource =
|
|
8825
|
-
type:
|
|
8826
|
-
url:
|
|
8827
|
-
path:
|
|
8828
|
-
thumbnailUrl:
|
|
8829
|
-
thumbnailPath:
|
|
9219
|
+
imageVariantIndex: z45.number().int().min(0).optional()
|
|
9220
|
+
});
|
|
9221
|
+
var GroupedMediaSource = z45.object({
|
|
9222
|
+
type: z45.literal("media"),
|
|
9223
|
+
url: z45.string().url().optional(),
|
|
9224
|
+
path: z45.string().min(1).optional(),
|
|
9225
|
+
thumbnailUrl: z45.string().url().optional(),
|
|
9226
|
+
thumbnailPath: z45.string().min(1).optional()
|
|
8830
9227
|
}).refine((value) => Boolean(value.url) !== Boolean(value.path), {
|
|
8831
9228
|
message: "media source needs exactly one of `url` or `path`"
|
|
8832
9229
|
}).refine((value) => !(value.thumbnailUrl && value.thumbnailPath), {
|
|
8833
9230
|
message: "media source needs at most one of `thumbnailUrl` or `thumbnailPath`"
|
|
8834
9231
|
});
|
|
8835
|
-
var GroupedCreative =
|
|
8836
|
-
type:
|
|
9232
|
+
var GroupedCreative = z45.object({
|
|
9233
|
+
type: z45.enum([
|
|
8837
9234
|
"image",
|
|
8838
9235
|
"video"
|
|
8839
9236
|
]),
|
|
8840
|
-
source:
|
|
9237
|
+
source: z45.union([
|
|
8841
9238
|
GroupedTaskSource,
|
|
8842
9239
|
GroupedMediaSource
|
|
8843
9240
|
]),
|
|
8844
|
-
title:
|
|
8845
|
-
description:
|
|
9241
|
+
title: z45.string().max(120).optional(),
|
|
9242
|
+
description: z45.string().max(500).optional(),
|
|
8846
9243
|
cta: MetaCtaType.optional(),
|
|
8847
|
-
creativeId:
|
|
9244
|
+
creativeId: z45.string().min(1).optional()
|
|
8848
9245
|
});
|
|
8849
|
-
var GroupedCampaignConfig =
|
|
9246
|
+
var GroupedCampaignConfig = z45.object({
|
|
8850
9247
|
campaignType: MetaCampaignType.default("sales"),
|
|
8851
9248
|
optimizationMode: MetaOptimizationMode.default("advantage_plus"),
|
|
8852
9249
|
budgetMode: MetaBudgetMode.default("campaign"),
|
|
8853
|
-
campaignDailyBudget:
|
|
8854
|
-
adSets:
|
|
8855
|
-
tempId:
|
|
8856
|
-
name:
|
|
8857
|
-
dailyBudget:
|
|
8858
|
-
creativeIds:
|
|
9250
|
+
campaignDailyBudget: z45.number().int().positive().optional(),
|
|
9251
|
+
adSets: z45.array(z45.object({
|
|
9252
|
+
tempId: z45.string().min(1).max(80),
|
|
9253
|
+
name: z45.string().min(1).max(100),
|
|
9254
|
+
dailyBudget: z45.number().int().positive().optional(),
|
|
9255
|
+
creativeIds: z45.array(z45.string().min(1)).min(1)
|
|
8859
9256
|
})).min(1).max(CAMPAIGN_LIMITS.MAX_AD_SETS),
|
|
8860
9257
|
/**
|
|
8861
9258
|
* Valid values are 'landing' and 'whatsapp' — there is no 'website'. This
|
|
@@ -8863,22 +9260,22 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8863
9260
|
* opaque `invalid_literal` and made the WhatsApp destination — supported by
|
|
8864
9261
|
* the API since #849 — unreachable from this tool.
|
|
8865
9262
|
*/
|
|
8866
|
-
destination:
|
|
8867
|
-
|
|
8868
|
-
type:
|
|
8869
|
-
landingUrl:
|
|
9263
|
+
destination: z45.discriminatedUnion("type", [
|
|
9264
|
+
z45.object({
|
|
9265
|
+
type: z45.literal("landing"),
|
|
9266
|
+
landingUrl: z45.string().url()
|
|
8870
9267
|
}),
|
|
8871
|
-
|
|
8872
|
-
type:
|
|
8873
|
-
phoneNumber:
|
|
9268
|
+
z45.object({
|
|
9269
|
+
type: z45.literal("whatsapp"),
|
|
9270
|
+
phoneNumber: z45.string().min(8).max(32)
|
|
8874
9271
|
})
|
|
8875
9272
|
]),
|
|
8876
|
-
saveAsDefault:
|
|
9273
|
+
saveAsDefault: z45.boolean().default(false),
|
|
8877
9274
|
budgetPolicy: MetaBudgetPolicy.optional()
|
|
8878
9275
|
}).superRefine((value, ctx) => {
|
|
8879
9276
|
if (value.budgetMode === "campaign" && value.campaignDailyBudget === void 0) {
|
|
8880
9277
|
ctx.addIssue({
|
|
8881
|
-
code:
|
|
9278
|
+
code: z45.ZodIssueCode.custom,
|
|
8882
9279
|
path: [
|
|
8883
9280
|
"campaignDailyBudget"
|
|
8884
9281
|
],
|
|
@@ -8889,7 +9286,7 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8889
9286
|
value.adSets.forEach((adSet, index) => {
|
|
8890
9287
|
if (adSet.dailyBudget === void 0) {
|
|
8891
9288
|
ctx.addIssue({
|
|
8892
|
-
code:
|
|
9289
|
+
code: z45.ZodIssueCode.custom,
|
|
8893
9290
|
path: [
|
|
8894
9291
|
"adSets",
|
|
8895
9292
|
index,
|
|
@@ -8901,22 +9298,22 @@ var GroupedCampaignConfig = z44.object({
|
|
|
8901
9298
|
});
|
|
8902
9299
|
}
|
|
8903
9300
|
});
|
|
8904
|
-
var PublishCreativesToMetaInputBase =
|
|
8905
|
-
creatives:
|
|
9301
|
+
var PublishCreativesToMetaInputBase = z45.object({
|
|
9302
|
+
creatives: z45.array(GroupedCreative).min(1).max(CAMPAIGN_LIMITS.MAX_CREATIVES),
|
|
8906
9303
|
adAccountId: McpAdAccountId,
|
|
8907
|
-
pixelId:
|
|
9304
|
+
pixelId: z45.string().min(1).optional(),
|
|
8908
9305
|
/** Required unless `campaignConfig.destination` is whatsapp — see the
|
|
8909
9306
|
* superRefine below. Mirrors the API's `UploadToMetaRequest`. */
|
|
8910
|
-
landingUrl:
|
|
8911
|
-
targetCountry:
|
|
8912
|
-
campaignName:
|
|
9307
|
+
landingUrl: z45.string().url().optional(),
|
|
9308
|
+
targetCountry: z45.string().length(2),
|
|
9309
|
+
campaignName: z45.string().trim().min(1).max(100),
|
|
8913
9310
|
campaignConfig: GroupedCampaignConfig.optional()
|
|
8914
9311
|
});
|
|
8915
9312
|
var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((value, ctx) => {
|
|
8916
9313
|
const destination = value.campaignConfig?.destination;
|
|
8917
9314
|
if (destination?.type !== "whatsapp" && !value.landingUrl) {
|
|
8918
9315
|
ctx.addIssue({
|
|
8919
|
-
code:
|
|
9316
|
+
code: z45.ZodIssueCode.custom,
|
|
8920
9317
|
path: [
|
|
8921
9318
|
"landingUrl"
|
|
8922
9319
|
],
|
|
@@ -8925,7 +9322,7 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
8925
9322
|
}
|
|
8926
9323
|
if (destination?.type === "landing" && destination.landingUrl !== value.landingUrl) {
|
|
8927
9324
|
ctx.addIssue({
|
|
8928
|
-
code:
|
|
9325
|
+
code: z45.ZodIssueCode.custom,
|
|
8929
9326
|
path: [
|
|
8930
9327
|
"campaignConfig",
|
|
8931
9328
|
"destination",
|
|
@@ -8935,12 +9332,12 @@ var PublishCreativesToMetaInput = PublishCreativesToMetaInputBase.superRefine((v
|
|
|
8935
9332
|
});
|
|
8936
9333
|
}
|
|
8937
9334
|
});
|
|
8938
|
-
var PresignUploadResponseSchema =
|
|
8939
|
-
uploadUrl:
|
|
9335
|
+
var PresignUploadResponseSchema = z45.object({
|
|
9336
|
+
uploadUrl: z45.string().url().refine((value) => {
|
|
8940
9337
|
const url = new URL(value);
|
|
8941
9338
|
return !url.username && !url.password && url.protocol === "https:";
|
|
8942
9339
|
}, "presigned upload URL must be HTTPS without embedded credentials"),
|
|
8943
|
-
publicUrl:
|
|
9340
|
+
publicUrl: z45.string().url().refine((value) => {
|
|
8944
9341
|
const url = new URL(value);
|
|
8945
9342
|
return !url.username && !url.password;
|
|
8946
9343
|
}, "public media URL must not contain embedded credentials")
|
|
@@ -8965,16 +9362,16 @@ async function resolveAndUploadMedia(api, ref, expectedKind, transport) {
|
|
|
8965
9362
|
return uploadResolvedMedia(api, media);
|
|
8966
9363
|
}
|
|
8967
9364
|
__name(resolveAndUploadMedia, "resolveAndUploadMedia");
|
|
8968
|
-
var TikTokInput =
|
|
8969
|
-
taskId:
|
|
8970
|
-
advertiserId:
|
|
8971
|
-
pixelId:
|
|
8972
|
-
landingUrl:
|
|
8973
|
-
angleIndexes:
|
|
9365
|
+
var TikTokInput = z45.object({
|
|
9366
|
+
taskId: z45.string().min(1),
|
|
9367
|
+
advertiserId: z45.string().min(1),
|
|
9368
|
+
pixelId: z45.string().min(1).optional(),
|
|
9369
|
+
landingUrl: z45.string().url().optional(),
|
|
9370
|
+
angleIndexes: z45.array(z45.number().int().nonnegative()).optional(),
|
|
8974
9371
|
campaignConfig: McpCampaignConfig.optional(),
|
|
8975
9372
|
/** Override the ad's description (TikTok's body copy). If omitted,
|
|
8976
9373
|
* ProductMaker uses the auto-generated copy attached to the task. */
|
|
8977
|
-
primaryText:
|
|
9374
|
+
primaryText: z45.string().trim().min(1).max(500).optional()
|
|
8978
9375
|
});
|
|
8979
9376
|
function registerPublishTools(server, api, opts = {}) {
|
|
8980
9377
|
const transport = opts.transport ?? "http";
|
|
@@ -9185,13 +9582,13 @@ function toTikTokCampaignConfig(cfg) {
|
|
|
9185
9582
|
__name(toTikTokCampaignConfig, "toTikTokCampaignConfig");
|
|
9186
9583
|
|
|
9187
9584
|
// src/tools/campaigns.ts
|
|
9188
|
-
import { z as
|
|
9189
|
-
var MetaStatusInput =
|
|
9190
|
-
campaignId:
|
|
9585
|
+
import { z as z46 } from "zod";
|
|
9586
|
+
var MetaStatusInput = z46.object({
|
|
9587
|
+
campaignId: z46.string().min(1).describe("Meta campaign ID returned by publish_to_meta.")
|
|
9191
9588
|
});
|
|
9192
|
-
var TikTokStatusInput =
|
|
9193
|
-
campaignId:
|
|
9194
|
-
advertiserId:
|
|
9589
|
+
var TikTokStatusInput = z46.object({
|
|
9590
|
+
campaignId: z46.string().min(1).describe("TikTok campaign ID returned by publish_to_tiktok."),
|
|
9591
|
+
advertiserId: z46.string().min(1).describe("The same advertiserId used to publish the campaign.")
|
|
9195
9592
|
});
|
|
9196
9593
|
function registerCampaignTools(server, api) {
|
|
9197
9594
|
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) => {
|
|
@@ -9288,10 +9685,10 @@ function renderTikTokStatusMarkdown(r) {
|
|
|
9288
9685
|
__name(renderTikTokStatusMarkdown, "renderTikTokStatusMarkdown");
|
|
9289
9686
|
|
|
9290
9687
|
// ../../packages/product-economics/src/product-costing.ts
|
|
9291
|
-
import { z as
|
|
9688
|
+
import { z as z48 } from "zod";
|
|
9292
9689
|
|
|
9293
9690
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
9294
|
-
import { z as
|
|
9691
|
+
import { z as z47 } from "zod";
|
|
9295
9692
|
|
|
9296
9693
|
// ../../packages/product-economics/src/product-costing-shipping-references.json
|
|
9297
9694
|
var product_costing_shipping_references_default = {
|
|
@@ -9355,21 +9752,21 @@ var product_costing_shipping_references_default = {
|
|
|
9355
9752
|
};
|
|
9356
9753
|
|
|
9357
9754
|
// ../../packages/product-economics/src/product-costing-countries.ts
|
|
9358
|
-
var ShippingReferenceSchema =
|
|
9359
|
-
reference:
|
|
9360
|
-
min:
|
|
9361
|
-
max:
|
|
9362
|
-
updatedAt:
|
|
9363
|
-
confidence:
|
|
9755
|
+
var ShippingReferenceSchema = z47.object({
|
|
9756
|
+
reference: z47.number().positive(),
|
|
9757
|
+
min: z47.number().nonnegative(),
|
|
9758
|
+
max: z47.number().positive(),
|
|
9759
|
+
updatedAt: z47.string().date(),
|
|
9760
|
+
confidence: z47.enum([
|
|
9364
9761
|
"high",
|
|
9365
9762
|
"medium",
|
|
9366
9763
|
"medium-low"
|
|
9367
9764
|
]),
|
|
9368
|
-
sources:
|
|
9765
|
+
sources: z47.array(z47.string().url().startsWith("https://")).min(1).max(3)
|
|
9369
9766
|
}).superRefine(({ reference, min, max }, context) => {
|
|
9370
9767
|
if (min > reference || reference > max) {
|
|
9371
9768
|
context.addIssue({
|
|
9372
|
-
code:
|
|
9769
|
+
code: z47.ZodIssueCode.custom,
|
|
9373
9770
|
message: "shipping_reference_outside_range",
|
|
9374
9771
|
path: [
|
|
9375
9772
|
"reference"
|
|
@@ -9377,7 +9774,7 @@ var ShippingReferenceSchema = z46.object({
|
|
|
9377
9774
|
});
|
|
9378
9775
|
}
|
|
9379
9776
|
});
|
|
9380
|
-
var SHIPPING_REFERENCES =
|
|
9777
|
+
var SHIPPING_REFERENCES = z47.record(ShippingReferenceSchema).parse(product_costing_shipping_references_default);
|
|
9381
9778
|
var PRODUCT_COSTING_COUNTRY_CODES = Object.freeze(Object.keys(SHIPPING_REFERENCES));
|
|
9382
9779
|
var SPANISH_LOCALE_COUNTRIES = /* @__PURE__ */ new Set([
|
|
9383
9780
|
"MX",
|
|
@@ -9559,18 +9956,18 @@ function getProductCostingCountryName(country) {
|
|
|
9559
9956
|
__name(getProductCostingCountryName, "getProductCostingCountryName");
|
|
9560
9957
|
|
|
9561
9958
|
// ../../packages/product-economics/src/product-costing.ts
|
|
9562
|
-
var ProductCostingInputSchema =
|
|
9563
|
-
country:
|
|
9564
|
-
supplierCost:
|
|
9565
|
-
shippingCost:
|
|
9566
|
-
returnRate:
|
|
9567
|
-
cancellationRate:
|
|
9568
|
-
adsManagerCpa:
|
|
9569
|
-
desiredMargin:
|
|
9959
|
+
var ProductCostingInputSchema = z48.object({
|
|
9960
|
+
country: z48.string().refine(isProductCostingCountryCode, "unsupported_country"),
|
|
9961
|
+
supplierCost: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").positive("supplier_cost_positive"),
|
|
9962
|
+
shippingCost: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("shipping_cost_nonnegative"),
|
|
9963
|
+
returnRate: z48.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
9964
|
+
cancellationRate: z48.number().finite().min(0, "rate_nonnegative").lt(1, "rate_below_one"),
|
|
9965
|
+
adsManagerCpa: z48.number().finite().max(Number.MAX_SAFE_INTEGER, "amount_too_large").nonnegative("cpa_nonnegative"),
|
|
9966
|
+
desiredMargin: z48.number().finite().min(0, "margin_nonnegative").lt(1, "margin_below_one")
|
|
9570
9967
|
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
9571
9968
|
if (returnRate + cancellationRate >= 1) {
|
|
9572
9969
|
context.addIssue({
|
|
9573
|
-
code:
|
|
9970
|
+
code: z48.ZodIssueCode.custom,
|
|
9574
9971
|
message: "delivery_rate_positive",
|
|
9575
9972
|
path: [
|
|
9576
9973
|
"cancellationRate"
|
|
@@ -9637,14 +10034,14 @@ function calculateProductCosting(rawInput) {
|
|
|
9637
10034
|
__name(calculateProductCosting, "calculateProductCosting");
|
|
9638
10035
|
|
|
9639
10036
|
// src/tools/product-costing.ts
|
|
9640
|
-
import { z as
|
|
9641
|
-
var optionalAmount = /* @__PURE__ */ __name((description) =>
|
|
9642
|
-
var optionalPercent = /* @__PURE__ */ __name((description) =>
|
|
9643
|
-
var ProductCostingToolInput =
|
|
9644
|
-
country:
|
|
10037
|
+
import { z as z49 } from "zod";
|
|
10038
|
+
var optionalAmount = /* @__PURE__ */ __name((description) => z49.number().finite().max(Number.MAX_SAFE_INTEGER).nonnegative().optional().describe(description), "optionalAmount");
|
|
10039
|
+
var optionalPercent = /* @__PURE__ */ __name((description) => z49.number().finite().min(0).lt(100).optional().describe(description), "optionalPercent");
|
|
10040
|
+
var ProductCostingToolInput = z49.object({
|
|
10041
|
+
country: z49.string().trim().toUpperCase().refine(isProductCostingCountryCode, {
|
|
9645
10042
|
message: "Pa\xEDs no soportado por ProductMaker."
|
|
9646
10043
|
}).optional().describe("C\xF3digo ISO-2 de cualquiera de los pa\xEDses disponibles en ProductMaker. Omite para Colombia."),
|
|
9647
|
-
supplierCost:
|
|
10044
|
+
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."),
|
|
9648
10045
|
supplierCostCop: optionalAmount("Alias anterior para costo del proveedor en Colombia. Prefiere supplierCost."),
|
|
9649
10046
|
shippingCost: optionalAmount("Costo de un env\xEDo en la moneda del pa\xEDs. Omite para usar el valor gu\xEDa vigente."),
|
|
9650
10047
|
shippingCostCop: optionalAmount("Alias anterior para flete en Colombia. Prefiere shippingCost."),
|
|
@@ -9776,7 +10173,7 @@ function formatPercent(value) {
|
|
|
9776
10173
|
__name(formatPercent, "formatPercent");
|
|
9777
10174
|
|
|
9778
10175
|
// src/tools/product-research.ts
|
|
9779
|
-
import { z as
|
|
10176
|
+
import { z as z50 } from "zod";
|
|
9780
10177
|
|
|
9781
10178
|
// src/tools/product-research-idempotency.ts
|
|
9782
10179
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -9892,17 +10289,17 @@ var TERMINAL2 = /* @__PURE__ */ new Set([
|
|
|
9892
10289
|
]);
|
|
9893
10290
|
var POLL_INTERVAL_MS = 5e3;
|
|
9894
10291
|
var MAX_WAIT_SECONDS = 120;
|
|
9895
|
-
var FindInput =
|
|
10292
|
+
var FindInput = z50.object({
|
|
9896
10293
|
targetCountry: ResearchTargetCountryEnum.describe("Pa\xEDs objetivo. S\xF3lo CO, MX, PE, EC y CL tienen cobertura de investigaci\xF3n."),
|
|
9897
10294
|
categoryKey: ResearchCategoryEnum.default("auto").describe('Categor\xEDa a investigar. Usa "auto" para que la IA elija seg\xFAn el mercado.'),
|
|
9898
|
-
confirmed:
|
|
9899
|
-
waitSeconds:
|
|
10295
|
+
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.`),
|
|
10296
|
+
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.")
|
|
9900
10297
|
});
|
|
9901
|
-
var GetInput =
|
|
9902
|
-
runId:
|
|
10298
|
+
var GetInput = z50.object({
|
|
10299
|
+
runId: z50.string().uuid().describe("ID del run devuelto por find_winning_products.")
|
|
9903
10300
|
});
|
|
9904
|
-
var ListInput =
|
|
9905
|
-
limit:
|
|
10301
|
+
var ListInput = z50.object({
|
|
10302
|
+
limit: z50.number().int().min(1).max(20).default(10)
|
|
9906
10303
|
});
|
|
9907
10304
|
function textResult(text) {
|
|
9908
10305
|
return {
|
|
@@ -9993,6 +10390,230 @@ _Esta llamada no cobr\xF3 cr\xE9ditos: se reutiliz\xF3 una investigaci\xF3n reci
|
|
|
9993
10390
|
}
|
|
9994
10391
|
__name(registerProductResearchTools, "registerProductResearchTools");
|
|
9995
10392
|
|
|
10393
|
+
// src/tools/dropshipping-projects.ts
|
|
10394
|
+
import { z as z51 } from "zod";
|
|
10395
|
+
var ProjectId = z51.string().uuid();
|
|
10396
|
+
var DropshippingProjectStatus = z51.enum([
|
|
10397
|
+
"active",
|
|
10398
|
+
"completed",
|
|
10399
|
+
"archived"
|
|
10400
|
+
]);
|
|
10401
|
+
var DropshippingProjectPhase = z51.enum([
|
|
10402
|
+
"research",
|
|
10403
|
+
"costing",
|
|
10404
|
+
"media",
|
|
10405
|
+
"generating",
|
|
10406
|
+
"storefront",
|
|
10407
|
+
"advertising",
|
|
10408
|
+
"complete"
|
|
10409
|
+
]);
|
|
10410
|
+
var TargetCountry = z51.enum([
|
|
10411
|
+
"CO",
|
|
10412
|
+
"MX",
|
|
10413
|
+
"PE",
|
|
10414
|
+
"EC",
|
|
10415
|
+
"CL"
|
|
10416
|
+
]);
|
|
10417
|
+
var ResearchCategory = z51.enum([
|
|
10418
|
+
"auto",
|
|
10419
|
+
"automotive",
|
|
10420
|
+
"kitchen",
|
|
10421
|
+
"pets",
|
|
10422
|
+
"home_organization",
|
|
10423
|
+
"beauty",
|
|
10424
|
+
"wellness",
|
|
10425
|
+
"fitness",
|
|
10426
|
+
"baby",
|
|
10427
|
+
"tech",
|
|
10428
|
+
"tools",
|
|
10429
|
+
"garden",
|
|
10430
|
+
"cleaning"
|
|
10431
|
+
]);
|
|
10432
|
+
var HttpUrl3 = z51.string().url().max(2e3).refine((value) => {
|
|
10433
|
+
try {
|
|
10434
|
+
return [
|
|
10435
|
+
"http:",
|
|
10436
|
+
"https:"
|
|
10437
|
+
].includes(new URL(value).protocol);
|
|
10438
|
+
} catch {
|
|
10439
|
+
return false;
|
|
10440
|
+
}
|
|
10441
|
+
}, "URL must use HTTP(S)");
|
|
10442
|
+
var ResearchCandidateOrigin = z51.object({
|
|
10443
|
+
type: z51.literal("research_candidate"),
|
|
10444
|
+
runId: ProjectId,
|
|
10445
|
+
candidateSourceId: z51.string().min(1).max(160)
|
|
10446
|
+
});
|
|
10447
|
+
var TaskOrigin = z51.object({
|
|
10448
|
+
type: z51.literal("task"),
|
|
10449
|
+
taskId: ProjectId
|
|
10450
|
+
});
|
|
10451
|
+
var ManualOrigin = z51.object({
|
|
10452
|
+
type: z51.literal("manual"),
|
|
10453
|
+
clientRequestId: ProjectId,
|
|
10454
|
+
country: z51.string().min(2).max(3).optional()
|
|
10455
|
+
});
|
|
10456
|
+
var StartProjectInput = z51.object({
|
|
10457
|
+
origin: z51.discriminatedUnion("type", [
|
|
10458
|
+
ResearchCandidateOrigin,
|
|
10459
|
+
TaskOrigin,
|
|
10460
|
+
ManualOrigin
|
|
10461
|
+
]),
|
|
10462
|
+
productName: z51.string().trim().min(1).max(240).optional(),
|
|
10463
|
+
productUrl: HttpUrl3.optional(),
|
|
10464
|
+
country: z51.string().min(2).max(3).optional(),
|
|
10465
|
+
languageCode: z51.string().min(2).max(16).optional()
|
|
10466
|
+
}).strict();
|
|
10467
|
+
var CostProjectInput = z51.object({
|
|
10468
|
+
projectId: ProjectId,
|
|
10469
|
+
version: z51.number().int().positive(),
|
|
10470
|
+
country: z51.string().trim().min(2).max(3),
|
|
10471
|
+
supplierCost: z51.number().finite().positive(),
|
|
10472
|
+
shippingCost: z51.number().finite().nonnegative(),
|
|
10473
|
+
returnRate: z51.number().finite().min(0).lt(1),
|
|
10474
|
+
cancellationRate: z51.number().finite().min(0).lt(1),
|
|
10475
|
+
adsManagerCpa: z51.number().finite().nonnegative(),
|
|
10476
|
+
desiredMargin: z51.number().finite().min(0).lt(1)
|
|
10477
|
+
});
|
|
10478
|
+
var GuideInput = z51.object({
|
|
10479
|
+
projectId: ProjectId.optional()
|
|
10480
|
+
}).strict();
|
|
10481
|
+
var DropshippingProjectNextAction = z51.discriminatedUnion("kind", [
|
|
10482
|
+
"cost_product",
|
|
10483
|
+
"provide_product_media",
|
|
10484
|
+
"generate_creatives",
|
|
10485
|
+
"wait_for_creatives",
|
|
10486
|
+
"repair_creatives",
|
|
10487
|
+
"complete_creative_set",
|
|
10488
|
+
"connect_shopify",
|
|
10489
|
+
"publish_storefront",
|
|
10490
|
+
"wait_for_storefront",
|
|
10491
|
+
"connect_meta",
|
|
10492
|
+
"create_meta_campaign",
|
|
10493
|
+
"repair_meta_campaign",
|
|
10494
|
+
"review_paused_campaign"
|
|
10495
|
+
].map((kind) => z51.object({
|
|
10496
|
+
kind: z51.literal(kind),
|
|
10497
|
+
href: z51.string().min(1)
|
|
10498
|
+
})));
|
|
10499
|
+
var CostingInputSchema = z51.object({
|
|
10500
|
+
country: z51.string().min(2).max(3),
|
|
10501
|
+
supplierCost: z51.number().finite().positive(),
|
|
10502
|
+
shippingCost: z51.number().finite().nonnegative(),
|
|
10503
|
+
returnRate: z51.number().finite().min(0).lt(1),
|
|
10504
|
+
cancellationRate: z51.number().finite().min(0).lt(1),
|
|
10505
|
+
adsManagerCpa: z51.number().finite().nonnegative(),
|
|
10506
|
+
desiredMargin: z51.number().finite().min(0).lt(1)
|
|
10507
|
+
}).superRefine(({ returnRate, cancellationRate }, context) => {
|
|
10508
|
+
if (returnRate + cancellationRate >= 1) context.addIssue({
|
|
10509
|
+
code: z51.ZodIssueCode.custom,
|
|
10510
|
+
path: [
|
|
10511
|
+
"cancellationRate"
|
|
10512
|
+
]
|
|
10513
|
+
});
|
|
10514
|
+
});
|
|
10515
|
+
var CostingResultSchema = z51.object({
|
|
10516
|
+
country: z51.string().min(2).max(3),
|
|
10517
|
+
deliveryRate: z51.number().finite(),
|
|
10518
|
+
adjustedShippingCost: z51.number().finite(),
|
|
10519
|
+
adjustedCpa: z51.number().finite(),
|
|
10520
|
+
totalCost: z51.number().finite(),
|
|
10521
|
+
suggestedPrice: z51.number().finite(),
|
|
10522
|
+
baseCommercialPrice: z51.number().finite(),
|
|
10523
|
+
minimumSafePrice: z51.number().finite(),
|
|
10524
|
+
commercialPrice: z51.number().finite(),
|
|
10525
|
+
comparisonPrice: z51.number().finite(),
|
|
10526
|
+
estimatedProfit: z51.number().finite(),
|
|
10527
|
+
actualMargin: z51.number().finite(),
|
|
10528
|
+
breakEvenAdsManagerCpa: z51.number().finite(),
|
|
10529
|
+
wasPriceAutoAdjusted: z51.boolean(),
|
|
10530
|
+
profitabilityStatus: z51.literal("healthy")
|
|
10531
|
+
});
|
|
10532
|
+
var ProjectResponseSchema = z51.object({
|
|
10533
|
+
id: ProjectId,
|
|
10534
|
+
taskId: ProjectId.nullable(),
|
|
10535
|
+
status: DropshippingProjectStatus,
|
|
10536
|
+
originKey: z51.string().min(1),
|
|
10537
|
+
researchRunId: ProjectId.nullable(),
|
|
10538
|
+
candidateSourceId: z51.string().nullable(),
|
|
10539
|
+
productName: z51.string().nullable(),
|
|
10540
|
+
productUrl: HttpUrl3.nullable(),
|
|
10541
|
+
referenceImageUrl: HttpUrl3.nullable(),
|
|
10542
|
+
targetCountry: z51.string().nullable(),
|
|
10543
|
+
languageCode: z51.string().nullable(),
|
|
10544
|
+
hasReferenceImage: z51.boolean(),
|
|
10545
|
+
costingInput: CostingInputSchema.nullable(),
|
|
10546
|
+
costingResult: CostingResultSchema.nullable(),
|
|
10547
|
+
costingVersion: z51.number().int().positive().nullable(),
|
|
10548
|
+
version: z51.number().int().positive(),
|
|
10549
|
+
phase: DropshippingProjectPhase,
|
|
10550
|
+
nextAction: DropshippingProjectNextAction.nullable(),
|
|
10551
|
+
createdAt: z51.string().datetime(),
|
|
10552
|
+
updatedAt: z51.string().datetime()
|
|
10553
|
+
}).passthrough();
|
|
10554
|
+
function projectText(raw) {
|
|
10555
|
+
const project = ProjectResponseSchema.parse(raw);
|
|
10556
|
+
const next = project.nextAction ? `${project.nextAction.kind} (${project.nextAction.href})` : "ninguna";
|
|
10557
|
+
return {
|
|
10558
|
+
content: [
|
|
10559
|
+
{
|
|
10560
|
+
type: "text",
|
|
10561
|
+
text: JSON.stringify({
|
|
10562
|
+
projectId: project.id,
|
|
10563
|
+
productName: project.productName,
|
|
10564
|
+
phase: project.phase,
|
|
10565
|
+
nextAction: project.nextAction,
|
|
10566
|
+
hasReferenceImage: project.hasReferenceImage,
|
|
10567
|
+
costingSaved: Boolean(project.costingResult),
|
|
10568
|
+
version: project.version,
|
|
10569
|
+
message: `Siguiente paso: ${next}. Relee este proyecto despu\xE9s de cada mutaci\xF3n.`
|
|
10570
|
+
})
|
|
10571
|
+
}
|
|
10572
|
+
]
|
|
10573
|
+
};
|
|
10574
|
+
}
|
|
10575
|
+
__name(projectText, "projectText");
|
|
10576
|
+
function registerDropshippingProjectTools(server, api) {
|
|
10577
|
+
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) => {
|
|
10578
|
+
try {
|
|
10579
|
+
return projectText(await api.postJson("/v1/dropshipping-projects", input));
|
|
10580
|
+
} catch (error) {
|
|
10581
|
+
throw translateError(error);
|
|
10582
|
+
}
|
|
10583
|
+
});
|
|
10584
|
+
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) => {
|
|
10585
|
+
try {
|
|
10586
|
+
if (input.returnRate + input.cancellationRate >= 1) {
|
|
10587
|
+
throw new Error("returnRate + cancellationRate debe ser menor que 1.");
|
|
10588
|
+
}
|
|
10589
|
+
const { projectId, version, ...costingInput } = input;
|
|
10590
|
+
return projectText(await api.putJson(`/v1/dropshipping-projects/${encodeURIComponent(projectId)}/costing`, {
|
|
10591
|
+
version,
|
|
10592
|
+
input: costingInput
|
|
10593
|
+
}));
|
|
10594
|
+
} catch (error) {
|
|
10595
|
+
throw translateError(error);
|
|
10596
|
+
}
|
|
10597
|
+
});
|
|
10598
|
+
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) => {
|
|
10599
|
+
try {
|
|
10600
|
+
if (!input.projectId) {
|
|
10601
|
+
return asText({
|
|
10602
|
+
mode: "choose",
|
|
10603
|
+
guided: "Usa start_dropshipping_project cuando el usuario quiera encontrar un producto y dejarlo listo para publicar.",
|
|
10604
|
+
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.",
|
|
10605
|
+
confirmation: "Antes de acciones pagadas o externas, muestra el estimado y pide confirmaci\xF3n.",
|
|
10606
|
+
safety: "Las campa\xF1as Meta quedan PAUSED; el usuario las activa manualmente en Ads Manager."
|
|
10607
|
+
});
|
|
10608
|
+
}
|
|
10609
|
+
return projectText(await api.getJson(`/v1/dropshipping-projects/${encodeURIComponent(input.projectId)}`));
|
|
10610
|
+
} catch (error) {
|
|
10611
|
+
throw translateError(error);
|
|
10612
|
+
}
|
|
10613
|
+
});
|
|
10614
|
+
}
|
|
10615
|
+
__name(registerDropshippingProjectTools, "registerDropshippingProjectTools");
|
|
10616
|
+
|
|
9996
10617
|
// src/server.ts
|
|
9997
10618
|
function createServer(opts) {
|
|
9998
10619
|
const { apiKey, apiBaseUrl, proxyBaseUrl = null, transport = "http" } = opts;
|
|
@@ -10010,6 +10631,7 @@ function createServer(opts) {
|
|
|
10010
10631
|
const api = new ApiClient(apiBaseUrl, apiKey);
|
|
10011
10632
|
registerProductCostingTools(server);
|
|
10012
10633
|
registerProductResearchTools(server, api);
|
|
10634
|
+
registerDropshippingProjectTools(server, api);
|
|
10013
10635
|
registerTaskTools(server, api, {
|
|
10014
10636
|
proxyBaseUrl,
|
|
10015
10637
|
transport
|