@productmaker/mcp 12.5.0 → 12.6.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/README.md +1 -0
- package/dist/http.js +388 -13
- package/dist/stdio.js +388 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,6 +212,7 @@ its service-page editor, including its generation progress.
|
|
|
212
212
|
| `set_ad_spend` | Correct by hand what was spent on ads that month. `amount: 0` ASSERTS "I did not advertise"; `null` WITHDRAWS the correction and gives the campaigns back the say. They are not the same |
|
|
213
213
|
| `prepare_winning_product_image` | Prepare and show the exact photo of a user-selected winning-product candidate for free; securely stages it before the next photo choice. |
|
|
214
214
|
| `get_product_control` | Read-only daily profitability verdicts and measurement status per store product. Incomplete samples or unmeasured delivered sales must remain explicit; never changes campaigns. |
|
|
215
|
+
| `get_product_ads` | Read-only Meta figures for each ad (sales angle) of one product on one day: spend, pixel purchases, cost per purchase, video retention and a keep/turn off/review suggestion against the break-even. Pixel purchases are not store orders; never changes ads. |
|
|
215
216
|
| `list_importable_products` | Read one page of store products eligible for financial control; preserve `hasNextPage` and already-imported markers. |
|
|
216
217
|
| `import_product_controls` | Add selected store products to financial control. They remain `no_costing` until their real costs are saved. |
|
|
217
218
|
| `set_product_costing` | Save seller-provided supplier cost, freight and estimated cancellation/return rates; store price stays canonical and missing costs cannot be invented. |
|
package/dist/http.js
CHANGED
|
@@ -2315,6 +2315,15 @@ var DEFAULT_PRICING = {
|
|
|
2315
2315
|
ourCostCents: 0.01,
|
|
2316
2316
|
userPriceCents: 0.02
|
|
2317
2317
|
},
|
|
2318
|
+
// OpenAI Decisions same-product check of DropKiller listings (market formats study),
|
|
2319
|
+
// per 1,000 input tokens. Decisions has no price row of its own; it bills as its
|
|
2320
|
+
// model, gpt-6-luna: $0.10/1M input (https://developers.openai.com/api/docs/pricing,
|
|
2321
|
+
// 2026-11-02). Answers are closed choices, so output is negligible. Cost-only:
|
|
2322
|
+
// the seller is not charged, the fixed study quote absorbs it.
|
|
2323
|
+
"openai:competitor-listing-decision": {
|
|
2324
|
+
ourCostCents: 0.01,
|
|
2325
|
+
userPriceCents: 0
|
|
2326
|
+
},
|
|
2318
2327
|
// Full competitor-source transcript used by the flat-price Frankenstein bundle.
|
|
2319
2328
|
"openai:frankenstein-source-transcribe": {
|
|
2320
2329
|
ourCostCents: 0.01,
|
|
@@ -2476,6 +2485,19 @@ var DEFAULT_PRICING = {
|
|
|
2476
2485
|
ourCostCents: 1,
|
|
2477
2486
|
userPriceCents: 2
|
|
2478
2487
|
},
|
|
2488
|
+
// Market formats read each competitor ad by its medium. Video: Gemini over
|
|
2489
|
+
// the whole ad with audio, measured 1.641¢ avg / 2.071¢ max over 60 local
|
|
2490
|
+
// analyses (6.9k in / 3.0k out tokens, 2026-11-04). Image: one still with the
|
|
2491
|
+
// same prompt, estimated (~4.2k in / ~2k out) — no producer until image ads
|
|
2492
|
+
// are analyzed. Frames (the key above) stays the flag-off and fallback leg.
|
|
2493
|
+
"openrouter:market-ad-video-analysis": {
|
|
2494
|
+
ourCostCents: 1.65,
|
|
2495
|
+
userPriceCents: 3.3
|
|
2496
|
+
},
|
|
2497
|
+
"openrouter:market-ad-image-analysis": {
|
|
2498
|
+
ourCostCents: 1.1,
|
|
2499
|
+
userPriceCents: 2.2
|
|
2500
|
+
},
|
|
2479
2501
|
"openrouter:competitor-commercial-dossier": {
|
|
2480
2502
|
ourCostCents: 5,
|
|
2481
2503
|
userPriceCents: 10
|
|
@@ -4093,6 +4115,13 @@ var AiEditWinnerOverlayItemSchema = z5.object({
|
|
|
4093
4115
|
/** Target-truth field ids backing `text` (from the adaptation plan). */
|
|
4094
4116
|
truthSourceIds: z5.array(z5.string().min(1).max(200)).max(16).optional()
|
|
4095
4117
|
}).strict();
|
|
4118
|
+
var AiEditDeliveredExecutionSchema = z5.object({
|
|
4119
|
+
taskId: z5.string().min(1).max(200),
|
|
4120
|
+
angleKey: z5.string().min(1).max(200),
|
|
4121
|
+
creativeRevision: z5.string().min(1).max(200),
|
|
4122
|
+
planHash: z5.string().min(1).max(200),
|
|
4123
|
+
outputHash: z5.string().min(1).max(200)
|
|
4124
|
+
}).strict();
|
|
4096
4125
|
var AiEditWinnerOverlaysSchema = z5.object({
|
|
4097
4126
|
version: z5.literal(1),
|
|
4098
4127
|
source: z5.object({
|
|
@@ -4102,13 +4131,7 @@ var AiEditWinnerOverlaysSchema = z5.object({
|
|
|
4102
4131
|
adaptationPlanRevision: z5.string().regex(/^[a-f0-9]{64}$/).optional()
|
|
4103
4132
|
}).strict(),
|
|
4104
4133
|
/** The delivered execution this plan was fitted against. */
|
|
4105
|
-
current:
|
|
4106
|
-
taskId: z5.string().min(1).max(200),
|
|
4107
|
-
angleKey: z5.string().min(1).max(200),
|
|
4108
|
-
creativeRevision: z5.string().min(1).max(200),
|
|
4109
|
-
planHash: z5.string().min(1).max(200),
|
|
4110
|
-
outputHash: z5.string().min(1).max(200)
|
|
4111
|
-
}).strict(),
|
|
4134
|
+
current: AiEditDeliveredExecutionSchema,
|
|
4112
4135
|
items: z5.array(AiEditWinnerOverlayItemSchema).max(64),
|
|
4113
4136
|
omitted: z5.array(z5.object({
|
|
4114
4137
|
id: z5.string().min(1).max(200),
|
|
@@ -4124,12 +4147,46 @@ var AiEditWinnerOverlaysSchema = z5.object({
|
|
|
4124
4147
|
])
|
|
4125
4148
|
}).strict()).max(64)
|
|
4126
4149
|
}).strict();
|
|
4150
|
+
var AiEditMarketFormatOverlaysSchema = z5.object({
|
|
4151
|
+
version: z5.literal(1),
|
|
4152
|
+
source: z5.object({
|
|
4153
|
+
formatId: z5.string().min(1).max(200),
|
|
4154
|
+
anchorSourceId: z5.string().min(1).max(200),
|
|
4155
|
+
contextHash: z5.string().min(1).max(200)
|
|
4156
|
+
}).strict(),
|
|
4157
|
+
current: AiEditDeliveredExecutionSchema,
|
|
4158
|
+
/** The format's look and editing pace, for the overlay style. */
|
|
4159
|
+
style: z5.object({
|
|
4160
|
+
visualStyle: z5.string().max(600),
|
|
4161
|
+
editingPace: z5.string().max(300).optional()
|
|
4162
|
+
}).strict(),
|
|
4163
|
+
items: z5.array(z5.object({
|
|
4164
|
+
formatBeatIndex: z5.number().int().nonnegative(),
|
|
4165
|
+
beat: z5.string().max(200),
|
|
4166
|
+
sourceText: z5.string().min(1).max(400),
|
|
4167
|
+
target: z5.object({
|
|
4168
|
+
sceneId: z5.string().min(1).max(200),
|
|
4169
|
+
beatIds: z5.array(z5.string().min(1).max(200)).max(16),
|
|
4170
|
+
startSec: z5.number().finite().nonnegative(),
|
|
4171
|
+
endSec: z5.number().finite().nonnegative()
|
|
4172
|
+
}).strict()
|
|
4173
|
+
}).strict()).max(10),
|
|
4174
|
+
omitted: z5.array(z5.object({
|
|
4175
|
+
formatBeatIndex: z5.number().int().nonnegative(),
|
|
4176
|
+
reason: z5.enum([
|
|
4177
|
+
"unmapped_beat",
|
|
4178
|
+
"unfitted_interval"
|
|
4179
|
+
])
|
|
4180
|
+
}).strict()).max(10)
|
|
4181
|
+
}).strict();
|
|
4127
4182
|
var AiEditBriefSchema = z5.object({
|
|
4128
4183
|
script: z5.string(),
|
|
4129
4184
|
words: z5.array(AiEditWordSchema),
|
|
4130
4185
|
sceneCutsSec: z5.array(z5.number().min(0)),
|
|
4131
4186
|
/** Optional winner-overlay adaptation plan; absent without winner+edit consent. */
|
|
4132
|
-
winnerOverlays: AiEditWinnerOverlaysSchema.optional()
|
|
4187
|
+
winnerOverlays: AiEditWinnerOverlaysSchema.optional(),
|
|
4188
|
+
/** Optional market-format overlays; absent without an applied format. */
|
|
4189
|
+
marketFormatOverlays: AiEditMarketFormatOverlaysSchema.optional()
|
|
4133
4190
|
});
|
|
4134
4191
|
var AiEditOutputsSchema = z5.object({
|
|
4135
4192
|
editKey: z5.string(),
|
|
@@ -5279,8 +5336,11 @@ var COUNTRY_NAME_TO_ISO2 = {
|
|
|
5279
5336
|
var COUNTRY_NAME_ALIASES = {
|
|
5280
5337
|
usa: "united states",
|
|
5281
5338
|
"estados unidos": "united states",
|
|
5339
|
+
estadosunidos: "united states",
|
|
5340
|
+
unitedstates: "united states",
|
|
5282
5341
|
uk: "united kingdom",
|
|
5283
5342
|
"reino unido": "united kingdom",
|
|
5343
|
+
unitedkingdom: "united kingdom",
|
|
5284
5344
|
brasil: "brazil",
|
|
5285
5345
|
espana: "spain",
|
|
5286
5346
|
alemania: "germany",
|
|
@@ -5333,6 +5393,7 @@ function normalizeToIso2(value) {
|
|
|
5333
5393
|
return void 0;
|
|
5334
5394
|
}
|
|
5335
5395
|
__name(normalizeToIso2, "normalizeToIso2");
|
|
5396
|
+
var SUPPORTED_COUNTRY_ISO2 = new Set(Object.values(COUNTRY_NAME_TO_ISO2));
|
|
5336
5397
|
var CountryIso2Schema = z11.preprocess(
|
|
5337
5398
|
(value) => typeof value === "string" ? normalizeToIso2(value) ?? value : value,
|
|
5338
5399
|
// The regex rejects unresolvable 2-unit garbage ('$$', '💩') that would
|
|
@@ -7885,6 +7946,13 @@ var CodeLandingCommerceSnapshotSchema = z23.object({
|
|
|
7885
7946
|
compareAtPrice: z23.string().trim().min(1).max(500).optional(),
|
|
7886
7947
|
/** Explicit removal survives projections that otherwise derive a comparison. */
|
|
7887
7948
|
compareAtPriceRemoved: z23.literal(true).optional(),
|
|
7949
|
+
/** Seller-confirmed prices by product option, never purchase quantities. */
|
|
7950
|
+
offerVariants: z23.array(z23.object({
|
|
7951
|
+
option: z23.string().trim().min(1).max(60),
|
|
7952
|
+
value: z23.string().trim().min(1).max(60),
|
|
7953
|
+
price: PublishCommerceValuesSchema.shape.unitPrice,
|
|
7954
|
+
compareAtPrice: PublishCommerceValuesSchema.shape.unitPrice.nullable().optional()
|
|
7955
|
+
}).strict()).max(20).optional(),
|
|
7888
7956
|
/** Confirmed offer facts before Shopify supplies real chargeable variants. */
|
|
7889
7957
|
offerPacks: z23.array(z23.object({
|
|
7890
7958
|
units: z23.number().int().min(2).max(99),
|
|
@@ -10478,6 +10546,49 @@ var ObservedCommercialClaimSchema = z37.object({
|
|
|
10478
10546
|
"other"
|
|
10479
10547
|
])
|
|
10480
10548
|
}).strict();
|
|
10549
|
+
var CreativeFormatFramingSchema = z37.object({
|
|
10550
|
+
shotSize: z37.enum([
|
|
10551
|
+
"macro",
|
|
10552
|
+
"close_up",
|
|
10553
|
+
"medium",
|
|
10554
|
+
"wide"
|
|
10555
|
+
]),
|
|
10556
|
+
camera: z37.enum([
|
|
10557
|
+
"static",
|
|
10558
|
+
"handheld",
|
|
10559
|
+
"selfie",
|
|
10560
|
+
"moving"
|
|
10561
|
+
]),
|
|
10562
|
+
faceVisible: z37.boolean()
|
|
10563
|
+
}).strict();
|
|
10564
|
+
var CompetitorCreativeFormatSchema = z37.object({
|
|
10565
|
+
formatName: z37.string().trim().min(1).max(120),
|
|
10566
|
+
renderTechnique: z37.string().trim().min(1).max(300),
|
|
10567
|
+
visualWorld: z37.string().trim().min(1).max(600),
|
|
10568
|
+
protagonist: z37.string().trim().min(1).max(300),
|
|
10569
|
+
narrativeEngine: z37.string().trim().min(1).max(600),
|
|
10570
|
+
beats: z37.array(z37.object({
|
|
10571
|
+
atSec: z37.number().finite().nonnegative(),
|
|
10572
|
+
beat: z37.string().trim().min(1).max(200),
|
|
10573
|
+
/** What physically happens on camera, never its overlay text. */
|
|
10574
|
+
visual: z37.string().trim().min(1).max(400),
|
|
10575
|
+
/** Text, captions or graphics shown over that beat ("" = none). */
|
|
10576
|
+
onScreenText: z37.string().trim().max(400).optional()
|
|
10577
|
+
}).strict()).min(1).max(12),
|
|
10578
|
+
hookDevice: z37.string().trim().min(1).max(600),
|
|
10579
|
+
ctaDevice: z37.string().trim().min(1).max(600),
|
|
10580
|
+
productRole: z37.string().trim().min(1).max(600),
|
|
10581
|
+
tone: z37.string().trim().min(1).max(300),
|
|
10582
|
+
editingPace: z37.string().trim().min(1).max(300),
|
|
10583
|
+
confidence: z37.enum([
|
|
10584
|
+
"high",
|
|
10585
|
+
"medium",
|
|
10586
|
+
"low"
|
|
10587
|
+
]),
|
|
10588
|
+
/** ISO 639-1 of the spoken words, or "none" without speech. */
|
|
10589
|
+
spokenLanguage: z37.string().trim().toLowerCase().regex(/^(?:[a-z]{2}|none)$/).optional(),
|
|
10590
|
+
framing: CreativeFormatFramingSchema.optional()
|
|
10591
|
+
}).strict();
|
|
10481
10592
|
var CompetitorCommercialProfileSchema = z37.object({
|
|
10482
10593
|
durationSec: z37.number().finite().positive(),
|
|
10483
10594
|
transcript: z37.string().max(2e4).optional(),
|
|
@@ -10503,7 +10614,9 @@ var CompetitorCommercialProfileSchema = z37.object({
|
|
|
10503
10614
|
"incompatible",
|
|
10504
10615
|
"uncertain"
|
|
10505
10616
|
]).optional(),
|
|
10506
|
-
marketRelevanceEvidence: z37.string().trim().min(1).max(1e3).optional()
|
|
10617
|
+
marketRelevanceEvidence: z37.string().trim().min(1).max(1e3).optional(),
|
|
10618
|
+
/** Requested only for market-format studies; absent on every other path. */
|
|
10619
|
+
creativeFormat: CompetitorCreativeFormatSchema.optional()
|
|
10507
10620
|
}).strict();
|
|
10508
10621
|
var MarketSceneIntentSchema = z37.object({
|
|
10509
10622
|
id: z37.string().trim().min(1).max(80),
|
|
@@ -10561,6 +10674,99 @@ var CommercialMarketDossierSchema = z37.object({
|
|
|
10561
10674
|
recipes: z37.array(MarketCreativeRecipeSchema).length(3),
|
|
10562
10675
|
evidenceDisclaimer: z37.string().trim().min(1).max(1e3)
|
|
10563
10676
|
}).strict();
|
|
10677
|
+
var MarketVoiceLineSchema = z37.object({
|
|
10678
|
+
/** Quoted exactly as spoken in the source transcript, original language. */
|
|
10679
|
+
text: z37.string().trim().min(1).max(400),
|
|
10680
|
+
sourceId: z37.string().trim().min(1)
|
|
10681
|
+
}).strict();
|
|
10682
|
+
var MarketFormatVoiceSchema = z37.object({
|
|
10683
|
+
hookLines: z37.array(MarketVoiceLineSchema).max(6),
|
|
10684
|
+
ctaLines: z37.array(MarketVoiceLineSchema).max(6),
|
|
10685
|
+
recurringPhrases: z37.array(z37.string().trim().min(1).max(200)).max(12),
|
|
10686
|
+
topics: z37.array(z37.string().trim().min(1).max(200)).max(10),
|
|
10687
|
+
rawness: z37.number().int().min(1).max(5)
|
|
10688
|
+
}).strict();
|
|
10689
|
+
var MarketFormatAnchorFrameSchema = z37.object({
|
|
10690
|
+
index: z37.number().int().min(0).max(3),
|
|
10691
|
+
assetKey: z37.string().trim().min(1).max(500),
|
|
10692
|
+
timestampSec: z37.number().finite().nonnegative()
|
|
10693
|
+
}).strict();
|
|
10694
|
+
var MarketFormatPacingSchema = z37.object({
|
|
10695
|
+
shotCount: z37.number().int().min(1).max(12),
|
|
10696
|
+
secondsPerShot: z37.number().finite().positive().max(600),
|
|
10697
|
+
editingPace: z37.string().trim().min(1).max(300).optional()
|
|
10698
|
+
}).strict();
|
|
10699
|
+
var MarketBeatExampleSchema = z37.object({
|
|
10700
|
+
visual: z37.string().trim().min(1).max(400),
|
|
10701
|
+
sourceId: z37.string().trim().min(1)
|
|
10702
|
+
}).strict();
|
|
10703
|
+
var MarketFormatDirectionSchema = z37.object({
|
|
10704
|
+
id: z37.string().trim().min(1).max(80),
|
|
10705
|
+
formatName: z37.string().trim().min(1).max(120),
|
|
10706
|
+
anchorSourceId: z37.string().trim().min(1),
|
|
10707
|
+
sourceIds: z37.array(z37.string().trim().min(1)).min(1).max(20),
|
|
10708
|
+
advertiserCount: z37.number().int().positive(),
|
|
10709
|
+
weightShare: z37.number().finite().min(0).max(1),
|
|
10710
|
+
advertiserShare: z37.number().finite().min(0).max(1),
|
|
10711
|
+
visualStyle: z37.string().trim().min(1).max(600),
|
|
10712
|
+
protagonist: z37.string().trim().min(1).max(300),
|
|
10713
|
+
narrative: z37.string().trim().min(1).max(600),
|
|
10714
|
+
storyLine: z37.string().trim().min(1).max(600),
|
|
10715
|
+
beats: z37.array(z37.object({
|
|
10716
|
+
beat: z37.string().trim().min(1).max(200),
|
|
10717
|
+
/** The on-camera action to stage (a CTA action included). */
|
|
10718
|
+
visual: z37.string().trim().min(1).max(600),
|
|
10719
|
+
/** Graphics for the optional edit ("" = none); never staged. */
|
|
10720
|
+
onScreenText: z37.string().trim().max(400).optional(),
|
|
10721
|
+
/** How different member ads stage this shared beat. */
|
|
10722
|
+
examples: z37.array(MarketBeatExampleSchema).max(4).optional()
|
|
10723
|
+
}).strict()).min(2).max(10),
|
|
10724
|
+
hook: z37.string().trim().min(1).max(600),
|
|
10725
|
+
cta: z37.string().trim().min(1).max(600),
|
|
10726
|
+
productRole: z37.string().trim().min(1).max(600),
|
|
10727
|
+
adaptToProduct: z37.string().trim().min(1).max(1e3),
|
|
10728
|
+
doNotCopy: z37.array(z37.string().trim().min(1).max(300)).max(10),
|
|
10729
|
+
whyThisFormat: z37.string().trim().min(1).max(1e3),
|
|
10730
|
+
voice: MarketFormatVoiceSchema.optional(),
|
|
10731
|
+
anchorFrames: z37.array(MarketFormatAnchorFrameSchema).max(4).optional(),
|
|
10732
|
+
/** Server-owned: the anchor ad's framing, binding for the director. */
|
|
10733
|
+
framing: CreativeFormatFramingSchema.optional(),
|
|
10734
|
+
/** Server-owned: the anchor ad's cut rhythm, binding for the director. */
|
|
10735
|
+
pacing: MarketFormatPacingSchema.optional(),
|
|
10736
|
+
/** Server-owned: no member speaks the target market's language. */
|
|
10737
|
+
languageFallback: z37.boolean().optional()
|
|
10738
|
+
}).strict();
|
|
10739
|
+
var MarketMenuItemSchema = z37.object({
|
|
10740
|
+
kind: z37.string().trim().min(1).max(120),
|
|
10741
|
+
description: z37.string().trim().min(1).max(400),
|
|
10742
|
+
lines: z37.array(MarketVoiceLineSchema).max(4).optional(),
|
|
10743
|
+
sourceIds: z37.array(z37.string().trim().min(1)).min(1).max(20),
|
|
10744
|
+
advertiserCount: z37.number().int().positive(),
|
|
10745
|
+
weightShare: z37.number().finite().min(0).max(1)
|
|
10746
|
+
}).strict();
|
|
10747
|
+
var MarketCreativeMenuSchema = z37.object({
|
|
10748
|
+
hooks: z37.array(MarketMenuItemSchema).max(6),
|
|
10749
|
+
ctas: z37.array(MarketMenuItemSchema).max(6),
|
|
10750
|
+
visualStyles: z37.array(MarketMenuItemSchema).max(6),
|
|
10751
|
+
demos: z37.array(MarketMenuItemSchema).max(8),
|
|
10752
|
+
rhythms: z37.array(MarketMenuItemSchema).max(4)
|
|
10753
|
+
}).strict();
|
|
10754
|
+
var MarketCreativeDirectionSchema = z37.object({
|
|
10755
|
+
version: z37.literal("1.0.0"),
|
|
10756
|
+
sourceSnapshotHash: z37.string().trim().min(1),
|
|
10757
|
+
evidenceSource: z37.enum([
|
|
10758
|
+
"dropkiller",
|
|
10759
|
+
"meta",
|
|
10760
|
+
"mixed"
|
|
10761
|
+
]),
|
|
10762
|
+
analyzedVideoCount: z37.number().int().positive(),
|
|
10763
|
+
advertiserCount: z37.number().int().positive(),
|
|
10764
|
+
/** Dropi units sold in 30 days across confirmed listings, when known. */
|
|
10765
|
+
productSoldUnits30d: z37.number().int().nonnegative().optional(),
|
|
10766
|
+
formats: z37.array(MarketFormatDirectionSchema).min(1).max(3),
|
|
10767
|
+
/** The market's recurring hooks, CTAs, styles, demos and rhythms. */
|
|
10768
|
+
menu: MarketCreativeMenuSchema.optional()
|
|
10769
|
+
}).strict();
|
|
10564
10770
|
var MarketPersuasionDeviceSchema = z37.object({
|
|
10565
10771
|
/** Verbatim hook/CTA/market pattern from the persisted dossier. */
|
|
10566
10772
|
sourcePattern: z37.string().trim().min(1).max(1e3),
|
|
@@ -10769,6 +10975,24 @@ var CreativeEngineWinnerContextSchema = z38.object({
|
|
|
10769
10975
|
}).strict()).max(24)
|
|
10770
10976
|
}).strict().optional()
|
|
10771
10977
|
}).strict();
|
|
10978
|
+
var CreativeEngineMarketPickSchema = z38.object({
|
|
10979
|
+
kind: z38.string().trim().min(1).max(120),
|
|
10980
|
+
description: z38.string().trim().min(1).max(400),
|
|
10981
|
+
/** A verbatim market line to adapt (hooks and CTAs). */
|
|
10982
|
+
line: z38.string().trim().min(1).max(400).optional(),
|
|
10983
|
+
sourceId: id2
|
|
10984
|
+
}).strict();
|
|
10985
|
+
var CreativeEngineMarketSelectionSchema = z38.object({
|
|
10986
|
+
version: z38.literal(1),
|
|
10987
|
+
formatId: id2,
|
|
10988
|
+
/** The member ad shown as one example of the format, never a template. */
|
|
10989
|
+
exampleSourceId: id2,
|
|
10990
|
+
hook: CreativeEngineMarketPickSchema.optional(),
|
|
10991
|
+
cta: CreativeEngineMarketPickSchema.optional(),
|
|
10992
|
+
visualStyle: CreativeEngineMarketPickSchema.optional(),
|
|
10993
|
+
demo: CreativeEngineMarketPickSchema.optional(),
|
|
10994
|
+
rhythm: CreativeEngineMarketPickSchema.optional()
|
|
10995
|
+
}).strict();
|
|
10772
10996
|
var CreativeEngineMarketInputSchema = z38.object({
|
|
10773
10997
|
version: z38.literal(1),
|
|
10774
10998
|
/** The dossier's own snapshot hash (not necessarily hex-64). */
|
|
@@ -10797,7 +11021,22 @@ var CreativeEngineMarketInputSchema = z38.object({
|
|
|
10797
11021
|
])
|
|
10798
11022
|
}).strict()).max(64),
|
|
10799
11023
|
/** Validated when it names a recipe actually present in `recipes`. */
|
|
10800
|
-
marketRecipeId: id2.optional()
|
|
11024
|
+
marketRecipeId: id2.optional(),
|
|
11025
|
+
/**
|
|
11026
|
+
* Market formats flag only: formats #1..#3 (HOW the video looks and flows)
|
|
11027
|
+
* with the anchor ad's transcript. Absent keeps the historical context.
|
|
11028
|
+
*/
|
|
11029
|
+
formats: z38.array(MarketFormatDirectionSchema.extend({
|
|
11030
|
+
anchorTranscript: z38.string().max(2e4).optional()
|
|
11031
|
+
}).strict()).min(1).max(3).optional(),
|
|
11032
|
+
/** The format the server binds; the director may drop to the next with a reason. */
|
|
11033
|
+
marketFormatId: id2.optional(),
|
|
11034
|
+
/**
|
|
11035
|
+
* Market formats only: the combination sampled for this creative by market
|
|
11036
|
+
* weight (format, hook, CTA, style, demo, example member), seeded by the
|
|
11037
|
+
* task so a retry repeats it and sibling creatives vary inside the market.
|
|
11038
|
+
*/
|
|
11039
|
+
marketSelection: CreativeEngineMarketSelectionSchema.optional()
|
|
10801
11040
|
}).strict();
|
|
10802
11041
|
var CreativeEngineCommercialExecutionSchema = z38.discriminatedUnion("mode", [
|
|
10803
11042
|
z38.object({
|
|
@@ -10806,7 +11045,17 @@ var CreativeEngineCommercialExecutionSchema = z38.discriminatedUnion("mode", [
|
|
|
10806
11045
|
mode: z38.literal("market"),
|
|
10807
11046
|
sourceSnapshotHash: z38.string().min(1).max(200),
|
|
10808
11047
|
recipeId: id2,
|
|
10809
|
-
sourceIds: z38.array(id2).min(1).max(64)
|
|
11048
|
+
sourceIds: z38.array(id2).min(1).max(64),
|
|
11049
|
+
/** The market format actually applied (context `market.formats` only). */
|
|
11050
|
+
formatId: id2.optional(),
|
|
11051
|
+
/** Each format beat mapped onto the authored scene/beats. */
|
|
11052
|
+
beatMap: z38.array(z38.object({
|
|
11053
|
+
formatBeatIndex: z38.number().int().nonnegative(),
|
|
11054
|
+
targetSceneId: id2,
|
|
11055
|
+
targetBeatIds: z38.array(id2).max(16)
|
|
11056
|
+
}).strict()).min(1).max(10).optional(),
|
|
11057
|
+
/** Required only when formatId is not the server-bound format. */
|
|
11058
|
+
formatFallbackReason: z38.string().min(1).max(500).optional()
|
|
10810
11059
|
}).strict(),
|
|
10811
11060
|
z38.object({
|
|
10812
11061
|
version: z38.literal(1),
|
|
@@ -15508,8 +15757,13 @@ var AdminQualityReportSummary = z53.object({
|
|
|
15508
15757
|
mixTaskId: z53.string().nullable(),
|
|
15509
15758
|
kind: QualityReportKind,
|
|
15510
15759
|
// Historical rows can contain `quality` in the DB's free-text reason column.
|
|
15760
|
+
// Support refunds can also contain `generation_failed`, presented as `other`.
|
|
15511
15761
|
// Normalize only on read; new submissions keep the strict QualityReportReason enum.
|
|
15512
|
-
reason: z53.preprocess((value) =>
|
|
15762
|
+
reason: z53.preprocess((value) => {
|
|
15763
|
+
if (value === "quality") return "unacceptable_quality";
|
|
15764
|
+
if (value === "generation_failed") return "other";
|
|
15765
|
+
return value;
|
|
15766
|
+
}, QualityReportReason),
|
|
15513
15767
|
status: QualityReportStatus,
|
|
15514
15768
|
estimatedCostCents: z53.number().nullable(),
|
|
15515
15769
|
refundedCents: z53.number().nullable(),
|
|
@@ -21553,6 +21807,24 @@ var CAPABILITY_MODEL_GUIDANCE = {
|
|
|
21553
21807
|
"solo lectura; un d\xEDa sin conteos usa la tasa estimada"
|
|
21554
21808
|
]
|
|
21555
21809
|
},
|
|
21810
|
+
get_product_ads: {
|
|
21811
|
+
summary: "Muestra cada anuncio (\xE1ngulo de venta) de un producto en un d\xEDa, con cifras de Meta y qu\xE9 hacer con \xE9l.",
|
|
21812
|
+
useWhen: [
|
|
21813
|
+
"cu\xE1l de mis anuncios est\xE1 vendiendo",
|
|
21814
|
+
"qu\xE9 anuncio apago",
|
|
21815
|
+
"c\xF3mo le fue a cada \xE1ngulo ayer"
|
|
21816
|
+
],
|
|
21817
|
+
avoidWhen: [
|
|
21818
|
+
"pregunta por el producto entero: get_product_control"
|
|
21819
|
+
],
|
|
21820
|
+
defaults: [
|
|
21821
|
+
"el id sale de get_product_control, nunca se inventa",
|
|
21822
|
+
"compras del p\xEDxel de Meta, no pedidos de la tienda"
|
|
21823
|
+
],
|
|
21824
|
+
disclosures: [
|
|
21825
|
+
"solo lectura; nunca pausa ni modifica un anuncio"
|
|
21826
|
+
]
|
|
21827
|
+
},
|
|
21556
21828
|
report_product_counts: {
|
|
21557
21829
|
summary: "Registra lo que de verdad pas\xF3 con un producto en un d\xEDa: pedidos, cancelados, entregados y devueltos.",
|
|
21558
21830
|
useWhen: [
|
|
@@ -22933,6 +23205,76 @@ var CreateManualProductControlResponseSchema = z100.object({
|
|
|
22933
23205
|
productControlId: z100.string().guid(),
|
|
22934
23206
|
created: z100.boolean()
|
|
22935
23207
|
});
|
|
23208
|
+
var ProductControlAdsQuerySchema = z100.object({
|
|
23209
|
+
date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
23210
|
+
});
|
|
23211
|
+
var PRODUCT_CONTROL_AD_VERDICTS = [
|
|
23212
|
+
"keep",
|
|
23213
|
+
"turn_off",
|
|
23214
|
+
"review",
|
|
23215
|
+
"no_data"
|
|
23216
|
+
];
|
|
23217
|
+
var ProductControlAdVerdictSchema = z100.enum(PRODUCT_CONTROL_AD_VERDICTS);
|
|
23218
|
+
var PRODUCT_CONTROL_AD_REASONS = [
|
|
23219
|
+
"sells_within_break_even",
|
|
23220
|
+
"sells_above_break_even",
|
|
23221
|
+
"spent_break_even_without_sales",
|
|
23222
|
+
"low_spend_no_sales",
|
|
23223
|
+
"no_spend",
|
|
23224
|
+
"missing_break_even",
|
|
23225
|
+
"unknown_purchases",
|
|
23226
|
+
"different_time_zone"
|
|
23227
|
+
];
|
|
23228
|
+
var ProductControlAdReasonSchema = z100.enum(PRODUCT_CONTROL_AD_REASONS);
|
|
23229
|
+
var metric = z100.number().finite().nonnegative().nullable();
|
|
23230
|
+
var ProductControlAdSchema = z100.object({
|
|
23231
|
+
adId: z100.string(),
|
|
23232
|
+
campaignId: z100.string(),
|
|
23233
|
+
accountId: z100.string(),
|
|
23234
|
+
name: z100.string(),
|
|
23235
|
+
/** `effective_status` de Meta (ACTIVE, PAUSED, …), tal cual. */
|
|
23236
|
+
status: z100.string().nullable(),
|
|
23237
|
+
thumbnailUrl: z100.string().url().nullable(),
|
|
23238
|
+
creativeKind: z100.enum([
|
|
23239
|
+
"video",
|
|
23240
|
+
"image",
|
|
23241
|
+
"unknown"
|
|
23242
|
+
]),
|
|
23243
|
+
adsManagerUrl: z100.string().url(),
|
|
23244
|
+
spend: metric,
|
|
23245
|
+
impressions: metric,
|
|
23246
|
+
clicks: metric,
|
|
23247
|
+
ctr: metric,
|
|
23248
|
+
landingPageViews: metric,
|
|
23249
|
+
viewContent: metric,
|
|
23250
|
+
initiatedCheckout: metric,
|
|
23251
|
+
/** Compras del píxel (`offsite_conversion.fb_pixel_purchase`). */
|
|
23252
|
+
purchases: metric,
|
|
23253
|
+
costPerPurchase: metric,
|
|
23254
|
+
videoPlays: metric,
|
|
23255
|
+
videoP25: metric,
|
|
23256
|
+
videoP75: metric,
|
|
23257
|
+
videoP100: metric,
|
|
23258
|
+
/** p100 / reproducciones; `null` si no es vídeo o no hubo reproducciones. */
|
|
23259
|
+
completionRate: z100.number().finite().min(0).max(1).nullable(),
|
|
23260
|
+
verdict: ProductControlAdVerdictSchema,
|
|
23261
|
+
reason: ProductControlAdReasonSchema
|
|
23262
|
+
});
|
|
23263
|
+
var ProductControlAdsStatusSchema = z100.enum([
|
|
23264
|
+
"ok",
|
|
23265
|
+
"no_meta_campaign",
|
|
23266
|
+
"meta_not_connected",
|
|
23267
|
+
"unavailable"
|
|
23268
|
+
]);
|
|
23269
|
+
var ProductControlAdsResponseSchema = z100.object({
|
|
23270
|
+
productControlId: z100.string(),
|
|
23271
|
+
date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
23272
|
+
status: ProductControlAdsStatusSchema,
|
|
23273
|
+
currency: z100.string().nullable(),
|
|
23274
|
+
/** Publicidad máxima por compra para no perder (CPA de equilibrio). */
|
|
23275
|
+
breakEvenCpa: z100.number().finite().nonnegative().nullable(),
|
|
23276
|
+
ads: z100.array(ProductControlAdSchema)
|
|
23277
|
+
});
|
|
22936
23278
|
|
|
22937
23279
|
// ../../packages/types/src/productmaker-capability-registry.ts
|
|
22938
23280
|
var SHARED_CHANNEL_EXPOSURE = {
|
|
@@ -24723,6 +25065,20 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
24723
25065
|
], [
|
|
24724
25066
|
"product_control_report"
|
|
24725
25067
|
]),
|
|
25068
|
+
defineCapability("get_product_ads", "df2873f9776f34f8a5a4c02b2878fbd6fb6ed1cfd9998cf728603b2bbd10069b", "none", "read_only", [
|
|
25069
|
+
"read"
|
|
25070
|
+
], [
|
|
25071
|
+
slot("product_control", true, [
|
|
25072
|
+
"productControlId"
|
|
25073
|
+
]),
|
|
25074
|
+
slot("day", true, [
|
|
25075
|
+
"date"
|
|
25076
|
+
])
|
|
25077
|
+
], [
|
|
25078
|
+
"product_control"
|
|
25079
|
+
], [
|
|
25080
|
+
"product_control_ads"
|
|
25081
|
+
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
24726
25082
|
defineCapability("report_product_counts", "8fa2561901b7743506a3639038d7806186c0512470bc6988a54c6bee5dbbb0b0", "state_change", "business", [
|
|
24727
25083
|
"state_change"
|
|
24728
25084
|
], [
|
|
@@ -30987,7 +31343,7 @@ var ApiClient = class {
|
|
|
30987
31343
|
};
|
|
30988
31344
|
|
|
30989
31345
|
// src/index.ts
|
|
30990
|
-
var MCP_VERSION = "12.
|
|
31346
|
+
var MCP_VERSION = "12.6.0";
|
|
30991
31347
|
|
|
30992
31348
|
// src/meta-upload-app.ts
|
|
30993
31349
|
import { readFileSync } from "fs";
|
|
@@ -40924,6 +41280,7 @@ import { readFile, stat } from "fs/promises";
|
|
|
40924
41280
|
import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
|
|
40925
41281
|
import { z as z156 } from "zod";
|
|
40926
41282
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
41283
|
+
var getProductAdsGuidance = getProductMakerCapabilityModelGuidance("get_product_ads");
|
|
40927
41284
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
40928
41285
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
40929
41286
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
@@ -40951,6 +41308,10 @@ var ProductControlListInput = z156.object({
|
|
|
40951
41308
|
date: DateOnly2.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, termina en el \xFAltimo d\xEDa cerrado \u2014 nunca hoy, que est\xE1 incompleto."),
|
|
40952
41309
|
shopDomain: z156.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
40953
41310
|
}).strict();
|
|
41311
|
+
var ProductAdsInput = z156.object({
|
|
41312
|
+
productControlId: z156.string().uuid().describe("El `productControlId` que devuelve get_product_control."),
|
|
41313
|
+
date: DateOnly2.describe("D\xEDa a leer (YYYY-MM-DD).")
|
|
41314
|
+
}).strict();
|
|
40954
41315
|
var ImportableProductsInput = z156.object({
|
|
40955
41316
|
q: z156.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
40956
41317
|
after: z156.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
@@ -41078,6 +41439,20 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
|
41078
41439
|
throw translateError(error);
|
|
41079
41440
|
}
|
|
41080
41441
|
});
|
|
41442
|
+
server.registerTool("get_product_ads", {
|
|
41443
|
+
description: getProductAdsGuidance.summary + " Devuelve cada anuncio de las campa\xF1as de Meta enlazadas al producto, con sus cifras DE META ese d\xEDa: gasto, impresiones, clics, CTR, visitas a la landing, view content, inicios de pago, compras del p\xEDxel, costo por compra y retenci\xF3n del v\xEDdeo (reproducciones, 25/75/100 % y `completionRate`). `verdict` es lo que la pantalla le sugiere: `keep` (mantener), `turn_off` (apagar), `review` (revisar) y `no_data` (todav\xEDa no hay con qu\xE9 juzgarlo); `reason` dice por qu\xE9, y el umbral es `breakEvenCpa`, la publicidad m\xE1xima por compra para no perder. Las compras del p\xEDxel NO son los pedidos de la tienda: el producto se decide con get_product_control y los anuncios se comparan entre s\xED con esto, porque un pedido contraentrega no dice de qu\xE9 anuncio vino. `status` distinto de `ok` no trae anuncios: `meta_not_connected` (conectar Meta), `no_meta_campaign` (enlazar campa\xF1a) o `unavailable` (Meta no respondi\xF3). Si falta un dato o Meta no respondi\xF3 y el usuario tiene su propio MCP de Meta, complementa ah\xED y di de d\xF3nde sale cada cifra. Es READ-ONLY: nunca pausa ni modifica un anuncio; apagar lo decide y lo hace ella en Meta.",
|
|
41444
|
+
inputSchema: ProductAdsInput.shape,
|
|
41445
|
+
annotations: READS_EXTERNAL
|
|
41446
|
+
}, async (input) => {
|
|
41447
|
+
try {
|
|
41448
|
+
const params = new URLSearchParams({
|
|
41449
|
+
date: input.date
|
|
41450
|
+
});
|
|
41451
|
+
return asText(await api.getJson(`/v1/product-control/${encodeURIComponent(input.productControlId)}/ads?${params.toString()}`));
|
|
41452
|
+
} catch (error) {
|
|
41453
|
+
throw translateError(error);
|
|
41454
|
+
}
|
|
41455
|
+
});
|
|
41081
41456
|
server.registerTool("get_finances", {
|
|
41082
41457
|
description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana. Si viene `costEstimate` con `source: "product_costing"`, presenta sus importes como ESTIMACI\xD3N antes de impuestos, usando los costos actuales configurados del producto: no son costos reales confirmados de esos pedidos. Conserva el aviso de `costsKnown: false` y distingue esta estimaci\xF3n de los importes reales del libro. `linesEstimated` indica cu\xE1ntas l\xEDneas usan costos configurados. La API s\xF3lo ofrece esta estimaci\xF3n cuando cubre todos los costos faltantes con perfiles asociados del mismo pa\xEDs y moneda, y conoce ventas entregadas, publicidad y gastos revisados. Si `costEstimate` es null o no existe, no inventes una estimaci\xF3n ni completes importes faltantes.',
|
|
41083
41458
|
inputSchema: GetFinancesInput.shape,
|
package/dist/stdio.js
CHANGED
|
@@ -2090,6 +2090,15 @@ var DEFAULT_PRICING = {
|
|
|
2090
2090
|
ourCostCents: 0.01,
|
|
2091
2091
|
userPriceCents: 0.02
|
|
2092
2092
|
},
|
|
2093
|
+
// OpenAI Decisions same-product check of DropKiller listings (market formats study),
|
|
2094
|
+
// per 1,000 input tokens. Decisions has no price row of its own; it bills as its
|
|
2095
|
+
// model, gpt-6-luna: $0.10/1M input (https://developers.openai.com/api/docs/pricing,
|
|
2096
|
+
// 2026-11-02). Answers are closed choices, so output is negligible. Cost-only:
|
|
2097
|
+
// the seller is not charged, the fixed study quote absorbs it.
|
|
2098
|
+
"openai:competitor-listing-decision": {
|
|
2099
|
+
ourCostCents: 0.01,
|
|
2100
|
+
userPriceCents: 0
|
|
2101
|
+
},
|
|
2093
2102
|
// Full competitor-source transcript used by the flat-price Frankenstein bundle.
|
|
2094
2103
|
"openai:frankenstein-source-transcribe": {
|
|
2095
2104
|
ourCostCents: 0.01,
|
|
@@ -2251,6 +2260,19 @@ var DEFAULT_PRICING = {
|
|
|
2251
2260
|
ourCostCents: 1,
|
|
2252
2261
|
userPriceCents: 2
|
|
2253
2262
|
},
|
|
2263
|
+
// Market formats read each competitor ad by its medium. Video: Gemini over
|
|
2264
|
+
// the whole ad with audio, measured 1.641¢ avg / 2.071¢ max over 60 local
|
|
2265
|
+
// analyses (6.9k in / 3.0k out tokens, 2026-11-04). Image: one still with the
|
|
2266
|
+
// same prompt, estimated (~4.2k in / ~2k out) — no producer until image ads
|
|
2267
|
+
// are analyzed. Frames (the key above) stays the flag-off and fallback leg.
|
|
2268
|
+
"openrouter:market-ad-video-analysis": {
|
|
2269
|
+
ourCostCents: 1.65,
|
|
2270
|
+
userPriceCents: 3.3
|
|
2271
|
+
},
|
|
2272
|
+
"openrouter:market-ad-image-analysis": {
|
|
2273
|
+
ourCostCents: 1.1,
|
|
2274
|
+
userPriceCents: 2.2
|
|
2275
|
+
},
|
|
2254
2276
|
"openrouter:competitor-commercial-dossier": {
|
|
2255
2277
|
ourCostCents: 5,
|
|
2256
2278
|
userPriceCents: 10
|
|
@@ -3868,6 +3890,13 @@ var AiEditWinnerOverlayItemSchema = z5.object({
|
|
|
3868
3890
|
/** Target-truth field ids backing `text` (from the adaptation plan). */
|
|
3869
3891
|
truthSourceIds: z5.array(z5.string().min(1).max(200)).max(16).optional()
|
|
3870
3892
|
}).strict();
|
|
3893
|
+
var AiEditDeliveredExecutionSchema = z5.object({
|
|
3894
|
+
taskId: z5.string().min(1).max(200),
|
|
3895
|
+
angleKey: z5.string().min(1).max(200),
|
|
3896
|
+
creativeRevision: z5.string().min(1).max(200),
|
|
3897
|
+
planHash: z5.string().min(1).max(200),
|
|
3898
|
+
outputHash: z5.string().min(1).max(200)
|
|
3899
|
+
}).strict();
|
|
3871
3900
|
var AiEditWinnerOverlaysSchema = z5.object({
|
|
3872
3901
|
version: z5.literal(1),
|
|
3873
3902
|
source: z5.object({
|
|
@@ -3877,13 +3906,7 @@ var AiEditWinnerOverlaysSchema = z5.object({
|
|
|
3877
3906
|
adaptationPlanRevision: z5.string().regex(/^[a-f0-9]{64}$/).optional()
|
|
3878
3907
|
}).strict(),
|
|
3879
3908
|
/** The delivered execution this plan was fitted against. */
|
|
3880
|
-
current:
|
|
3881
|
-
taskId: z5.string().min(1).max(200),
|
|
3882
|
-
angleKey: z5.string().min(1).max(200),
|
|
3883
|
-
creativeRevision: z5.string().min(1).max(200),
|
|
3884
|
-
planHash: z5.string().min(1).max(200),
|
|
3885
|
-
outputHash: z5.string().min(1).max(200)
|
|
3886
|
-
}).strict(),
|
|
3909
|
+
current: AiEditDeliveredExecutionSchema,
|
|
3887
3910
|
items: z5.array(AiEditWinnerOverlayItemSchema).max(64),
|
|
3888
3911
|
omitted: z5.array(z5.object({
|
|
3889
3912
|
id: z5.string().min(1).max(200),
|
|
@@ -3899,12 +3922,46 @@ var AiEditWinnerOverlaysSchema = z5.object({
|
|
|
3899
3922
|
])
|
|
3900
3923
|
}).strict()).max(64)
|
|
3901
3924
|
}).strict();
|
|
3925
|
+
var AiEditMarketFormatOverlaysSchema = z5.object({
|
|
3926
|
+
version: z5.literal(1),
|
|
3927
|
+
source: z5.object({
|
|
3928
|
+
formatId: z5.string().min(1).max(200),
|
|
3929
|
+
anchorSourceId: z5.string().min(1).max(200),
|
|
3930
|
+
contextHash: z5.string().min(1).max(200)
|
|
3931
|
+
}).strict(),
|
|
3932
|
+
current: AiEditDeliveredExecutionSchema,
|
|
3933
|
+
/** The format's look and editing pace, for the overlay style. */
|
|
3934
|
+
style: z5.object({
|
|
3935
|
+
visualStyle: z5.string().max(600),
|
|
3936
|
+
editingPace: z5.string().max(300).optional()
|
|
3937
|
+
}).strict(),
|
|
3938
|
+
items: z5.array(z5.object({
|
|
3939
|
+
formatBeatIndex: z5.number().int().nonnegative(),
|
|
3940
|
+
beat: z5.string().max(200),
|
|
3941
|
+
sourceText: z5.string().min(1).max(400),
|
|
3942
|
+
target: z5.object({
|
|
3943
|
+
sceneId: z5.string().min(1).max(200),
|
|
3944
|
+
beatIds: z5.array(z5.string().min(1).max(200)).max(16),
|
|
3945
|
+
startSec: z5.number().finite().nonnegative(),
|
|
3946
|
+
endSec: z5.number().finite().nonnegative()
|
|
3947
|
+
}).strict()
|
|
3948
|
+
}).strict()).max(10),
|
|
3949
|
+
omitted: z5.array(z5.object({
|
|
3950
|
+
formatBeatIndex: z5.number().int().nonnegative(),
|
|
3951
|
+
reason: z5.enum([
|
|
3952
|
+
"unmapped_beat",
|
|
3953
|
+
"unfitted_interval"
|
|
3954
|
+
])
|
|
3955
|
+
}).strict()).max(10)
|
|
3956
|
+
}).strict();
|
|
3902
3957
|
var AiEditBriefSchema = z5.object({
|
|
3903
3958
|
script: z5.string(),
|
|
3904
3959
|
words: z5.array(AiEditWordSchema),
|
|
3905
3960
|
sceneCutsSec: z5.array(z5.number().min(0)),
|
|
3906
3961
|
/** Optional winner-overlay adaptation plan; absent without winner+edit consent. */
|
|
3907
|
-
winnerOverlays: AiEditWinnerOverlaysSchema.optional()
|
|
3962
|
+
winnerOverlays: AiEditWinnerOverlaysSchema.optional(),
|
|
3963
|
+
/** Optional market-format overlays; absent without an applied format. */
|
|
3964
|
+
marketFormatOverlays: AiEditMarketFormatOverlaysSchema.optional()
|
|
3908
3965
|
});
|
|
3909
3966
|
var AiEditOutputsSchema = z5.object({
|
|
3910
3967
|
editKey: z5.string(),
|
|
@@ -5054,8 +5111,11 @@ var COUNTRY_NAME_TO_ISO2 = {
|
|
|
5054
5111
|
var COUNTRY_NAME_ALIASES = {
|
|
5055
5112
|
usa: "united states",
|
|
5056
5113
|
"estados unidos": "united states",
|
|
5114
|
+
estadosunidos: "united states",
|
|
5115
|
+
unitedstates: "united states",
|
|
5057
5116
|
uk: "united kingdom",
|
|
5058
5117
|
"reino unido": "united kingdom",
|
|
5118
|
+
unitedkingdom: "united kingdom",
|
|
5059
5119
|
brasil: "brazil",
|
|
5060
5120
|
espana: "spain",
|
|
5061
5121
|
alemania: "germany",
|
|
@@ -5108,6 +5168,7 @@ function normalizeToIso2(value) {
|
|
|
5108
5168
|
return void 0;
|
|
5109
5169
|
}
|
|
5110
5170
|
__name(normalizeToIso2, "normalizeToIso2");
|
|
5171
|
+
var SUPPORTED_COUNTRY_ISO2 = new Set(Object.values(COUNTRY_NAME_TO_ISO2));
|
|
5111
5172
|
var CountryIso2Schema = z11.preprocess(
|
|
5112
5173
|
(value) => typeof value === "string" ? normalizeToIso2(value) ?? value : value,
|
|
5113
5174
|
// The regex rejects unresolvable 2-unit garbage ('$$', '💩') that would
|
|
@@ -7660,6 +7721,13 @@ var CodeLandingCommerceSnapshotSchema = z23.object({
|
|
|
7660
7721
|
compareAtPrice: z23.string().trim().min(1).max(500).optional(),
|
|
7661
7722
|
/** Explicit removal survives projections that otherwise derive a comparison. */
|
|
7662
7723
|
compareAtPriceRemoved: z23.literal(true).optional(),
|
|
7724
|
+
/** Seller-confirmed prices by product option, never purchase quantities. */
|
|
7725
|
+
offerVariants: z23.array(z23.object({
|
|
7726
|
+
option: z23.string().trim().min(1).max(60),
|
|
7727
|
+
value: z23.string().trim().min(1).max(60),
|
|
7728
|
+
price: PublishCommerceValuesSchema.shape.unitPrice,
|
|
7729
|
+
compareAtPrice: PublishCommerceValuesSchema.shape.unitPrice.nullable().optional()
|
|
7730
|
+
}).strict()).max(20).optional(),
|
|
7663
7731
|
/** Confirmed offer facts before Shopify supplies real chargeable variants. */
|
|
7664
7732
|
offerPacks: z23.array(z23.object({
|
|
7665
7733
|
units: z23.number().int().min(2).max(99),
|
|
@@ -10253,6 +10321,49 @@ var ObservedCommercialClaimSchema = z37.object({
|
|
|
10253
10321
|
"other"
|
|
10254
10322
|
])
|
|
10255
10323
|
}).strict();
|
|
10324
|
+
var CreativeFormatFramingSchema = z37.object({
|
|
10325
|
+
shotSize: z37.enum([
|
|
10326
|
+
"macro",
|
|
10327
|
+
"close_up",
|
|
10328
|
+
"medium",
|
|
10329
|
+
"wide"
|
|
10330
|
+
]),
|
|
10331
|
+
camera: z37.enum([
|
|
10332
|
+
"static",
|
|
10333
|
+
"handheld",
|
|
10334
|
+
"selfie",
|
|
10335
|
+
"moving"
|
|
10336
|
+
]),
|
|
10337
|
+
faceVisible: z37.boolean()
|
|
10338
|
+
}).strict();
|
|
10339
|
+
var CompetitorCreativeFormatSchema = z37.object({
|
|
10340
|
+
formatName: z37.string().trim().min(1).max(120),
|
|
10341
|
+
renderTechnique: z37.string().trim().min(1).max(300),
|
|
10342
|
+
visualWorld: z37.string().trim().min(1).max(600),
|
|
10343
|
+
protagonist: z37.string().trim().min(1).max(300),
|
|
10344
|
+
narrativeEngine: z37.string().trim().min(1).max(600),
|
|
10345
|
+
beats: z37.array(z37.object({
|
|
10346
|
+
atSec: z37.number().finite().nonnegative(),
|
|
10347
|
+
beat: z37.string().trim().min(1).max(200),
|
|
10348
|
+
/** What physically happens on camera, never its overlay text. */
|
|
10349
|
+
visual: z37.string().trim().min(1).max(400),
|
|
10350
|
+
/** Text, captions or graphics shown over that beat ("" = none). */
|
|
10351
|
+
onScreenText: z37.string().trim().max(400).optional()
|
|
10352
|
+
}).strict()).min(1).max(12),
|
|
10353
|
+
hookDevice: z37.string().trim().min(1).max(600),
|
|
10354
|
+
ctaDevice: z37.string().trim().min(1).max(600),
|
|
10355
|
+
productRole: z37.string().trim().min(1).max(600),
|
|
10356
|
+
tone: z37.string().trim().min(1).max(300),
|
|
10357
|
+
editingPace: z37.string().trim().min(1).max(300),
|
|
10358
|
+
confidence: z37.enum([
|
|
10359
|
+
"high",
|
|
10360
|
+
"medium",
|
|
10361
|
+
"low"
|
|
10362
|
+
]),
|
|
10363
|
+
/** ISO 639-1 of the spoken words, or "none" without speech. */
|
|
10364
|
+
spokenLanguage: z37.string().trim().toLowerCase().regex(/^(?:[a-z]{2}|none)$/).optional(),
|
|
10365
|
+
framing: CreativeFormatFramingSchema.optional()
|
|
10366
|
+
}).strict();
|
|
10256
10367
|
var CompetitorCommercialProfileSchema = z37.object({
|
|
10257
10368
|
durationSec: z37.number().finite().positive(),
|
|
10258
10369
|
transcript: z37.string().max(2e4).optional(),
|
|
@@ -10278,7 +10389,9 @@ var CompetitorCommercialProfileSchema = z37.object({
|
|
|
10278
10389
|
"incompatible",
|
|
10279
10390
|
"uncertain"
|
|
10280
10391
|
]).optional(),
|
|
10281
|
-
marketRelevanceEvidence: z37.string().trim().min(1).max(1e3).optional()
|
|
10392
|
+
marketRelevanceEvidence: z37.string().trim().min(1).max(1e3).optional(),
|
|
10393
|
+
/** Requested only for market-format studies; absent on every other path. */
|
|
10394
|
+
creativeFormat: CompetitorCreativeFormatSchema.optional()
|
|
10282
10395
|
}).strict();
|
|
10283
10396
|
var MarketSceneIntentSchema = z37.object({
|
|
10284
10397
|
id: z37.string().trim().min(1).max(80),
|
|
@@ -10336,6 +10449,99 @@ var CommercialMarketDossierSchema = z37.object({
|
|
|
10336
10449
|
recipes: z37.array(MarketCreativeRecipeSchema).length(3),
|
|
10337
10450
|
evidenceDisclaimer: z37.string().trim().min(1).max(1e3)
|
|
10338
10451
|
}).strict();
|
|
10452
|
+
var MarketVoiceLineSchema = z37.object({
|
|
10453
|
+
/** Quoted exactly as spoken in the source transcript, original language. */
|
|
10454
|
+
text: z37.string().trim().min(1).max(400),
|
|
10455
|
+
sourceId: z37.string().trim().min(1)
|
|
10456
|
+
}).strict();
|
|
10457
|
+
var MarketFormatVoiceSchema = z37.object({
|
|
10458
|
+
hookLines: z37.array(MarketVoiceLineSchema).max(6),
|
|
10459
|
+
ctaLines: z37.array(MarketVoiceLineSchema).max(6),
|
|
10460
|
+
recurringPhrases: z37.array(z37.string().trim().min(1).max(200)).max(12),
|
|
10461
|
+
topics: z37.array(z37.string().trim().min(1).max(200)).max(10),
|
|
10462
|
+
rawness: z37.number().int().min(1).max(5)
|
|
10463
|
+
}).strict();
|
|
10464
|
+
var MarketFormatAnchorFrameSchema = z37.object({
|
|
10465
|
+
index: z37.number().int().min(0).max(3),
|
|
10466
|
+
assetKey: z37.string().trim().min(1).max(500),
|
|
10467
|
+
timestampSec: z37.number().finite().nonnegative()
|
|
10468
|
+
}).strict();
|
|
10469
|
+
var MarketFormatPacingSchema = z37.object({
|
|
10470
|
+
shotCount: z37.number().int().min(1).max(12),
|
|
10471
|
+
secondsPerShot: z37.number().finite().positive().max(600),
|
|
10472
|
+
editingPace: z37.string().trim().min(1).max(300).optional()
|
|
10473
|
+
}).strict();
|
|
10474
|
+
var MarketBeatExampleSchema = z37.object({
|
|
10475
|
+
visual: z37.string().trim().min(1).max(400),
|
|
10476
|
+
sourceId: z37.string().trim().min(1)
|
|
10477
|
+
}).strict();
|
|
10478
|
+
var MarketFormatDirectionSchema = z37.object({
|
|
10479
|
+
id: z37.string().trim().min(1).max(80),
|
|
10480
|
+
formatName: z37.string().trim().min(1).max(120),
|
|
10481
|
+
anchorSourceId: z37.string().trim().min(1),
|
|
10482
|
+
sourceIds: z37.array(z37.string().trim().min(1)).min(1).max(20),
|
|
10483
|
+
advertiserCount: z37.number().int().positive(),
|
|
10484
|
+
weightShare: z37.number().finite().min(0).max(1),
|
|
10485
|
+
advertiserShare: z37.number().finite().min(0).max(1),
|
|
10486
|
+
visualStyle: z37.string().trim().min(1).max(600),
|
|
10487
|
+
protagonist: z37.string().trim().min(1).max(300),
|
|
10488
|
+
narrative: z37.string().trim().min(1).max(600),
|
|
10489
|
+
storyLine: z37.string().trim().min(1).max(600),
|
|
10490
|
+
beats: z37.array(z37.object({
|
|
10491
|
+
beat: z37.string().trim().min(1).max(200),
|
|
10492
|
+
/** The on-camera action to stage (a CTA action included). */
|
|
10493
|
+
visual: z37.string().trim().min(1).max(600),
|
|
10494
|
+
/** Graphics for the optional edit ("" = none); never staged. */
|
|
10495
|
+
onScreenText: z37.string().trim().max(400).optional(),
|
|
10496
|
+
/** How different member ads stage this shared beat. */
|
|
10497
|
+
examples: z37.array(MarketBeatExampleSchema).max(4).optional()
|
|
10498
|
+
}).strict()).min(2).max(10),
|
|
10499
|
+
hook: z37.string().trim().min(1).max(600),
|
|
10500
|
+
cta: z37.string().trim().min(1).max(600),
|
|
10501
|
+
productRole: z37.string().trim().min(1).max(600),
|
|
10502
|
+
adaptToProduct: z37.string().trim().min(1).max(1e3),
|
|
10503
|
+
doNotCopy: z37.array(z37.string().trim().min(1).max(300)).max(10),
|
|
10504
|
+
whyThisFormat: z37.string().trim().min(1).max(1e3),
|
|
10505
|
+
voice: MarketFormatVoiceSchema.optional(),
|
|
10506
|
+
anchorFrames: z37.array(MarketFormatAnchorFrameSchema).max(4).optional(),
|
|
10507
|
+
/** Server-owned: the anchor ad's framing, binding for the director. */
|
|
10508
|
+
framing: CreativeFormatFramingSchema.optional(),
|
|
10509
|
+
/** Server-owned: the anchor ad's cut rhythm, binding for the director. */
|
|
10510
|
+
pacing: MarketFormatPacingSchema.optional(),
|
|
10511
|
+
/** Server-owned: no member speaks the target market's language. */
|
|
10512
|
+
languageFallback: z37.boolean().optional()
|
|
10513
|
+
}).strict();
|
|
10514
|
+
var MarketMenuItemSchema = z37.object({
|
|
10515
|
+
kind: z37.string().trim().min(1).max(120),
|
|
10516
|
+
description: z37.string().trim().min(1).max(400),
|
|
10517
|
+
lines: z37.array(MarketVoiceLineSchema).max(4).optional(),
|
|
10518
|
+
sourceIds: z37.array(z37.string().trim().min(1)).min(1).max(20),
|
|
10519
|
+
advertiserCount: z37.number().int().positive(),
|
|
10520
|
+
weightShare: z37.number().finite().min(0).max(1)
|
|
10521
|
+
}).strict();
|
|
10522
|
+
var MarketCreativeMenuSchema = z37.object({
|
|
10523
|
+
hooks: z37.array(MarketMenuItemSchema).max(6),
|
|
10524
|
+
ctas: z37.array(MarketMenuItemSchema).max(6),
|
|
10525
|
+
visualStyles: z37.array(MarketMenuItemSchema).max(6),
|
|
10526
|
+
demos: z37.array(MarketMenuItemSchema).max(8),
|
|
10527
|
+
rhythms: z37.array(MarketMenuItemSchema).max(4)
|
|
10528
|
+
}).strict();
|
|
10529
|
+
var MarketCreativeDirectionSchema = z37.object({
|
|
10530
|
+
version: z37.literal("1.0.0"),
|
|
10531
|
+
sourceSnapshotHash: z37.string().trim().min(1),
|
|
10532
|
+
evidenceSource: z37.enum([
|
|
10533
|
+
"dropkiller",
|
|
10534
|
+
"meta",
|
|
10535
|
+
"mixed"
|
|
10536
|
+
]),
|
|
10537
|
+
analyzedVideoCount: z37.number().int().positive(),
|
|
10538
|
+
advertiserCount: z37.number().int().positive(),
|
|
10539
|
+
/** Dropi units sold in 30 days across confirmed listings, when known. */
|
|
10540
|
+
productSoldUnits30d: z37.number().int().nonnegative().optional(),
|
|
10541
|
+
formats: z37.array(MarketFormatDirectionSchema).min(1).max(3),
|
|
10542
|
+
/** The market's recurring hooks, CTAs, styles, demos and rhythms. */
|
|
10543
|
+
menu: MarketCreativeMenuSchema.optional()
|
|
10544
|
+
}).strict();
|
|
10339
10545
|
var MarketPersuasionDeviceSchema = z37.object({
|
|
10340
10546
|
/** Verbatim hook/CTA/market pattern from the persisted dossier. */
|
|
10341
10547
|
sourcePattern: z37.string().trim().min(1).max(1e3),
|
|
@@ -10544,6 +10750,24 @@ var CreativeEngineWinnerContextSchema = z38.object({
|
|
|
10544
10750
|
}).strict()).max(24)
|
|
10545
10751
|
}).strict().optional()
|
|
10546
10752
|
}).strict();
|
|
10753
|
+
var CreativeEngineMarketPickSchema = z38.object({
|
|
10754
|
+
kind: z38.string().trim().min(1).max(120),
|
|
10755
|
+
description: z38.string().trim().min(1).max(400),
|
|
10756
|
+
/** A verbatim market line to adapt (hooks and CTAs). */
|
|
10757
|
+
line: z38.string().trim().min(1).max(400).optional(),
|
|
10758
|
+
sourceId: id2
|
|
10759
|
+
}).strict();
|
|
10760
|
+
var CreativeEngineMarketSelectionSchema = z38.object({
|
|
10761
|
+
version: z38.literal(1),
|
|
10762
|
+
formatId: id2,
|
|
10763
|
+
/** The member ad shown as one example of the format, never a template. */
|
|
10764
|
+
exampleSourceId: id2,
|
|
10765
|
+
hook: CreativeEngineMarketPickSchema.optional(),
|
|
10766
|
+
cta: CreativeEngineMarketPickSchema.optional(),
|
|
10767
|
+
visualStyle: CreativeEngineMarketPickSchema.optional(),
|
|
10768
|
+
demo: CreativeEngineMarketPickSchema.optional(),
|
|
10769
|
+
rhythm: CreativeEngineMarketPickSchema.optional()
|
|
10770
|
+
}).strict();
|
|
10547
10771
|
var CreativeEngineMarketInputSchema = z38.object({
|
|
10548
10772
|
version: z38.literal(1),
|
|
10549
10773
|
/** The dossier's own snapshot hash (not necessarily hex-64). */
|
|
@@ -10572,7 +10796,22 @@ var CreativeEngineMarketInputSchema = z38.object({
|
|
|
10572
10796
|
])
|
|
10573
10797
|
}).strict()).max(64),
|
|
10574
10798
|
/** Validated when it names a recipe actually present in `recipes`. */
|
|
10575
|
-
marketRecipeId: id2.optional()
|
|
10799
|
+
marketRecipeId: id2.optional(),
|
|
10800
|
+
/**
|
|
10801
|
+
* Market formats flag only: formats #1..#3 (HOW the video looks and flows)
|
|
10802
|
+
* with the anchor ad's transcript. Absent keeps the historical context.
|
|
10803
|
+
*/
|
|
10804
|
+
formats: z38.array(MarketFormatDirectionSchema.extend({
|
|
10805
|
+
anchorTranscript: z38.string().max(2e4).optional()
|
|
10806
|
+
}).strict()).min(1).max(3).optional(),
|
|
10807
|
+
/** The format the server binds; the director may drop to the next with a reason. */
|
|
10808
|
+
marketFormatId: id2.optional(),
|
|
10809
|
+
/**
|
|
10810
|
+
* Market formats only: the combination sampled for this creative by market
|
|
10811
|
+
* weight (format, hook, CTA, style, demo, example member), seeded by the
|
|
10812
|
+
* task so a retry repeats it and sibling creatives vary inside the market.
|
|
10813
|
+
*/
|
|
10814
|
+
marketSelection: CreativeEngineMarketSelectionSchema.optional()
|
|
10576
10815
|
}).strict();
|
|
10577
10816
|
var CreativeEngineCommercialExecutionSchema = z38.discriminatedUnion("mode", [
|
|
10578
10817
|
z38.object({
|
|
@@ -10581,7 +10820,17 @@ var CreativeEngineCommercialExecutionSchema = z38.discriminatedUnion("mode", [
|
|
|
10581
10820
|
mode: z38.literal("market"),
|
|
10582
10821
|
sourceSnapshotHash: z38.string().min(1).max(200),
|
|
10583
10822
|
recipeId: id2,
|
|
10584
|
-
sourceIds: z38.array(id2).min(1).max(64)
|
|
10823
|
+
sourceIds: z38.array(id2).min(1).max(64),
|
|
10824
|
+
/** The market format actually applied (context `market.formats` only). */
|
|
10825
|
+
formatId: id2.optional(),
|
|
10826
|
+
/** Each format beat mapped onto the authored scene/beats. */
|
|
10827
|
+
beatMap: z38.array(z38.object({
|
|
10828
|
+
formatBeatIndex: z38.number().int().nonnegative(),
|
|
10829
|
+
targetSceneId: id2,
|
|
10830
|
+
targetBeatIds: z38.array(id2).max(16)
|
|
10831
|
+
}).strict()).min(1).max(10).optional(),
|
|
10832
|
+
/** Required only when formatId is not the server-bound format. */
|
|
10833
|
+
formatFallbackReason: z38.string().min(1).max(500).optional()
|
|
10585
10834
|
}).strict(),
|
|
10586
10835
|
z38.object({
|
|
10587
10836
|
version: z38.literal(1),
|
|
@@ -15283,8 +15532,13 @@ var AdminQualityReportSummary = z53.object({
|
|
|
15283
15532
|
mixTaskId: z53.string().nullable(),
|
|
15284
15533
|
kind: QualityReportKind,
|
|
15285
15534
|
// Historical rows can contain `quality` in the DB's free-text reason column.
|
|
15535
|
+
// Support refunds can also contain `generation_failed`, presented as `other`.
|
|
15286
15536
|
// Normalize only on read; new submissions keep the strict QualityReportReason enum.
|
|
15287
|
-
reason: z53.preprocess((value) =>
|
|
15537
|
+
reason: z53.preprocess((value) => {
|
|
15538
|
+
if (value === "quality") return "unacceptable_quality";
|
|
15539
|
+
if (value === "generation_failed") return "other";
|
|
15540
|
+
return value;
|
|
15541
|
+
}, QualityReportReason),
|
|
15288
15542
|
status: QualityReportStatus,
|
|
15289
15543
|
estimatedCostCents: z53.number().nullable(),
|
|
15290
15544
|
refundedCents: z53.number().nullable(),
|
|
@@ -21328,6 +21582,24 @@ var CAPABILITY_MODEL_GUIDANCE = {
|
|
|
21328
21582
|
"solo lectura; un d\xEDa sin conteos usa la tasa estimada"
|
|
21329
21583
|
]
|
|
21330
21584
|
},
|
|
21585
|
+
get_product_ads: {
|
|
21586
|
+
summary: "Muestra cada anuncio (\xE1ngulo de venta) de un producto en un d\xEDa, con cifras de Meta y qu\xE9 hacer con \xE9l.",
|
|
21587
|
+
useWhen: [
|
|
21588
|
+
"cu\xE1l de mis anuncios est\xE1 vendiendo",
|
|
21589
|
+
"qu\xE9 anuncio apago",
|
|
21590
|
+
"c\xF3mo le fue a cada \xE1ngulo ayer"
|
|
21591
|
+
],
|
|
21592
|
+
avoidWhen: [
|
|
21593
|
+
"pregunta por el producto entero: get_product_control"
|
|
21594
|
+
],
|
|
21595
|
+
defaults: [
|
|
21596
|
+
"el id sale de get_product_control, nunca se inventa",
|
|
21597
|
+
"compras del p\xEDxel de Meta, no pedidos de la tienda"
|
|
21598
|
+
],
|
|
21599
|
+
disclosures: [
|
|
21600
|
+
"solo lectura; nunca pausa ni modifica un anuncio"
|
|
21601
|
+
]
|
|
21602
|
+
},
|
|
21331
21603
|
report_product_counts: {
|
|
21332
21604
|
summary: "Registra lo que de verdad pas\xF3 con un producto en un d\xEDa: pedidos, cancelados, entregados y devueltos.",
|
|
21333
21605
|
useWhen: [
|
|
@@ -22708,6 +22980,76 @@ var CreateManualProductControlResponseSchema = z100.object({
|
|
|
22708
22980
|
productControlId: z100.string().guid(),
|
|
22709
22981
|
created: z100.boolean()
|
|
22710
22982
|
});
|
|
22983
|
+
var ProductControlAdsQuerySchema = z100.object({
|
|
22984
|
+
date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
22985
|
+
});
|
|
22986
|
+
var PRODUCT_CONTROL_AD_VERDICTS = [
|
|
22987
|
+
"keep",
|
|
22988
|
+
"turn_off",
|
|
22989
|
+
"review",
|
|
22990
|
+
"no_data"
|
|
22991
|
+
];
|
|
22992
|
+
var ProductControlAdVerdictSchema = z100.enum(PRODUCT_CONTROL_AD_VERDICTS);
|
|
22993
|
+
var PRODUCT_CONTROL_AD_REASONS = [
|
|
22994
|
+
"sells_within_break_even",
|
|
22995
|
+
"sells_above_break_even",
|
|
22996
|
+
"spent_break_even_without_sales",
|
|
22997
|
+
"low_spend_no_sales",
|
|
22998
|
+
"no_spend",
|
|
22999
|
+
"missing_break_even",
|
|
23000
|
+
"unknown_purchases",
|
|
23001
|
+
"different_time_zone"
|
|
23002
|
+
];
|
|
23003
|
+
var ProductControlAdReasonSchema = z100.enum(PRODUCT_CONTROL_AD_REASONS);
|
|
23004
|
+
var metric = z100.number().finite().nonnegative().nullable();
|
|
23005
|
+
var ProductControlAdSchema = z100.object({
|
|
23006
|
+
adId: z100.string(),
|
|
23007
|
+
campaignId: z100.string(),
|
|
23008
|
+
accountId: z100.string(),
|
|
23009
|
+
name: z100.string(),
|
|
23010
|
+
/** `effective_status` de Meta (ACTIVE, PAUSED, …), tal cual. */
|
|
23011
|
+
status: z100.string().nullable(),
|
|
23012
|
+
thumbnailUrl: z100.string().url().nullable(),
|
|
23013
|
+
creativeKind: z100.enum([
|
|
23014
|
+
"video",
|
|
23015
|
+
"image",
|
|
23016
|
+
"unknown"
|
|
23017
|
+
]),
|
|
23018
|
+
adsManagerUrl: z100.string().url(),
|
|
23019
|
+
spend: metric,
|
|
23020
|
+
impressions: metric,
|
|
23021
|
+
clicks: metric,
|
|
23022
|
+
ctr: metric,
|
|
23023
|
+
landingPageViews: metric,
|
|
23024
|
+
viewContent: metric,
|
|
23025
|
+
initiatedCheckout: metric,
|
|
23026
|
+
/** Compras del píxel (`offsite_conversion.fb_pixel_purchase`). */
|
|
23027
|
+
purchases: metric,
|
|
23028
|
+
costPerPurchase: metric,
|
|
23029
|
+
videoPlays: metric,
|
|
23030
|
+
videoP25: metric,
|
|
23031
|
+
videoP75: metric,
|
|
23032
|
+
videoP100: metric,
|
|
23033
|
+
/** p100 / reproducciones; `null` si no es vídeo o no hubo reproducciones. */
|
|
23034
|
+
completionRate: z100.number().finite().min(0).max(1).nullable(),
|
|
23035
|
+
verdict: ProductControlAdVerdictSchema,
|
|
23036
|
+
reason: ProductControlAdReasonSchema
|
|
23037
|
+
});
|
|
23038
|
+
var ProductControlAdsStatusSchema = z100.enum([
|
|
23039
|
+
"ok",
|
|
23040
|
+
"no_meta_campaign",
|
|
23041
|
+
"meta_not_connected",
|
|
23042
|
+
"unavailable"
|
|
23043
|
+
]);
|
|
23044
|
+
var ProductControlAdsResponseSchema = z100.object({
|
|
23045
|
+
productControlId: z100.string(),
|
|
23046
|
+
date: z100.string().regex(/^\d{4}-\d{2}-\d{2}$/),
|
|
23047
|
+
status: ProductControlAdsStatusSchema,
|
|
23048
|
+
currency: z100.string().nullable(),
|
|
23049
|
+
/** Publicidad máxima por compra para no perder (CPA de equilibrio). */
|
|
23050
|
+
breakEvenCpa: z100.number().finite().nonnegative().nullable(),
|
|
23051
|
+
ads: z100.array(ProductControlAdSchema)
|
|
23052
|
+
});
|
|
22711
23053
|
|
|
22712
23054
|
// ../../packages/types/src/productmaker-capability-registry.ts
|
|
22713
23055
|
var SHARED_CHANNEL_EXPOSURE = {
|
|
@@ -24498,6 +24840,20 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
24498
24840
|
], [
|
|
24499
24841
|
"product_control_report"
|
|
24500
24842
|
]),
|
|
24843
|
+
defineCapability("get_product_ads", "df2873f9776f34f8a5a4c02b2878fbd6fb6ed1cfd9998cf728603b2bbd10069b", "none", "read_only", [
|
|
24844
|
+
"read"
|
|
24845
|
+
], [
|
|
24846
|
+
slot("product_control", true, [
|
|
24847
|
+
"productControlId"
|
|
24848
|
+
]),
|
|
24849
|
+
slot("day", true, [
|
|
24850
|
+
"date"
|
|
24851
|
+
])
|
|
24852
|
+
], [
|
|
24853
|
+
"product_control"
|
|
24854
|
+
], [
|
|
24855
|
+
"product_control_ads"
|
|
24856
|
+
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
24501
24857
|
defineCapability("report_product_counts", "8fa2561901b7743506a3639038d7806186c0512470bc6988a54c6bee5dbbb0b0", "state_change", "business", [
|
|
24502
24858
|
"state_change"
|
|
24503
24859
|
], [
|
|
@@ -29314,7 +29670,7 @@ var ApiClient = class {
|
|
|
29314
29670
|
};
|
|
29315
29671
|
|
|
29316
29672
|
// src/index.ts
|
|
29317
|
-
var MCP_VERSION = "12.
|
|
29673
|
+
var MCP_VERSION = "12.6.0";
|
|
29318
29674
|
|
|
29319
29675
|
// src/meta-upload-app.ts
|
|
29320
29676
|
import { readFileSync } from "fs";
|
|
@@ -39409,6 +39765,7 @@ import { readFile, stat } from "fs/promises";
|
|
|
39409
39765
|
import { basename as basename2, isAbsolute, resolve as resolve3 } from "path";
|
|
39410
39766
|
import { z as z155 } from "zod";
|
|
39411
39767
|
var getProductControlGuidance = getProductMakerCapabilityModelGuidance("get_product_control");
|
|
39768
|
+
var getProductAdsGuidance = getProductMakerCapabilityModelGuidance("get_product_ads");
|
|
39412
39769
|
var listImportableProductsGuidance = getProductMakerCapabilityModelGuidance("list_importable_products");
|
|
39413
39770
|
var importProductControlsGuidance = getProductMakerCapabilityModelGuidance("import_product_controls");
|
|
39414
39771
|
var setProductCostingGuidance = getProductMakerCapabilityModelGuidance("set_product_costing");
|
|
@@ -39436,6 +39793,10 @@ var ProductControlListInput = z155.object({
|
|
|
39436
39793
|
date: DateOnly2.optional().describe("D\xEDa final de la ventana (YYYY-MM-DD). Si se omite, termina en el \xFAltimo d\xEDa cerrado \u2014 nunca hoy, que est\xE1 incompleto."),
|
|
39437
39794
|
shopDomain: z155.string().min(1).optional().describe("Tienda, si tiene m\xE1s de una conectada.")
|
|
39438
39795
|
}).strict();
|
|
39796
|
+
var ProductAdsInput = z155.object({
|
|
39797
|
+
productControlId: z155.string().uuid().describe("El `productControlId` que devuelve get_product_control."),
|
|
39798
|
+
date: DateOnly2.describe("D\xEDa a leer (YYYY-MM-DD).")
|
|
39799
|
+
}).strict();
|
|
39439
39800
|
var ImportableProductsInput = z155.object({
|
|
39440
39801
|
q: z155.string().trim().max(120).optional().describe("B\xFAsqueda por t\xEDtulo. Sin esto un cat\xE1logo grande es inrecorrible."),
|
|
39441
39802
|
after: z155.string().max(512).optional().describe("Cursor de la p\xE1gina anterior, tal como vino en la respuesta."),
|
|
@@ -39563,6 +39924,20 @@ function registerProductControlTools(server, api, { transport = "http" } = {}) {
|
|
|
39563
39924
|
throw translateError(error);
|
|
39564
39925
|
}
|
|
39565
39926
|
});
|
|
39927
|
+
server.registerTool("get_product_ads", {
|
|
39928
|
+
description: getProductAdsGuidance.summary + " Devuelve cada anuncio de las campa\xF1as de Meta enlazadas al producto, con sus cifras DE META ese d\xEDa: gasto, impresiones, clics, CTR, visitas a la landing, view content, inicios de pago, compras del p\xEDxel, costo por compra y retenci\xF3n del v\xEDdeo (reproducciones, 25/75/100 % y `completionRate`). `verdict` es lo que la pantalla le sugiere: `keep` (mantener), `turn_off` (apagar), `review` (revisar) y `no_data` (todav\xEDa no hay con qu\xE9 juzgarlo); `reason` dice por qu\xE9, y el umbral es `breakEvenCpa`, la publicidad m\xE1xima por compra para no perder. Las compras del p\xEDxel NO son los pedidos de la tienda: el producto se decide con get_product_control y los anuncios se comparan entre s\xED con esto, porque un pedido contraentrega no dice de qu\xE9 anuncio vino. `status` distinto de `ok` no trae anuncios: `meta_not_connected` (conectar Meta), `no_meta_campaign` (enlazar campa\xF1a) o `unavailable` (Meta no respondi\xF3). Si falta un dato o Meta no respondi\xF3 y el usuario tiene su propio MCP de Meta, complementa ah\xED y di de d\xF3nde sale cada cifra. Es READ-ONLY: nunca pausa ni modifica un anuncio; apagar lo decide y lo hace ella en Meta.",
|
|
39929
|
+
inputSchema: ProductAdsInput.shape,
|
|
39930
|
+
annotations: READS_EXTERNAL
|
|
39931
|
+
}, async (input) => {
|
|
39932
|
+
try {
|
|
39933
|
+
const params = new URLSearchParams({
|
|
39934
|
+
date: input.date
|
|
39935
|
+
});
|
|
39936
|
+
return asText(await api.getJson(`/v1/product-control/${encodeURIComponent(input.productControlId)}/ads?${params.toString()}`));
|
|
39937
|
+
} catch (error) {
|
|
39938
|
+
throw translateError(error);
|
|
39939
|
+
}
|
|
39940
|
+
});
|
|
39566
39941
|
server.registerTool("get_finances", {
|
|
39567
39942
|
description: getFinancesGuidance.summary + ' Contesta la pregunta que de verdad importa --- \xABeste negocio gana plata?\xBB --- con el mes armado: ventas totales y entregadas, fletes, costo de los productos, utilidad bruta, publicidad, gastos fijos y utilidad NETA. Esa utilidad es ANTES de impuestos y hay que decirlo asi: el contador es un gasto mas, no un calculo nuestro. Trae tambien los porcentajes contra sus metas. Si `deliveredSalesKnown` no es true, faltan importes de ventas entregadas: la utilidad y los m\xE1rgenes no est\xE1n completos. `grossSalesKnown` distinto de true indica ventas totales parciales. Si `costsKnown` viene en `false`, esos pedidos llegaron de una fuente que NO sabe cuanto costaron \u2014la tienda, o la API del proveedor\u2014 y la utilidad BRUTA esta incompleta: no es que el producto salga gratis. Si `adSpendKnown` viene en `false`, la publicidad NO se pudo leer y la utilidad esta INCOMPLETA: dilo antes de que alguien celebre un mes que perdio plata. `adSpendSource: "user"` significa que ella corrigio la cifra a mano, y eso se revisa distinto de una leida. Si `unconfirmedExpenses` es mayor que cero, ese monto viene heredado del mes pasado y ella no lo ha revisado. Es READ-ONLY: nunca pausa ni modifica una campana. Si viene `costEstimate` con `source: "product_costing"`, presenta sus importes como ESTIMACI\xD3N antes de impuestos, usando los costos actuales configurados del producto: no son costos reales confirmados de esos pedidos. Conserva el aviso de `costsKnown: false` y distingue esta estimaci\xF3n de los importes reales del libro. `linesEstimated` indica cu\xE1ntas l\xEDneas usan costos configurados. La API s\xF3lo ofrece esta estimaci\xF3n cuando cubre todos los costos faltantes con perfiles asociados del mismo pa\xEDs y moneda, y conoce ventas entregadas, publicidad y gastos revisados. Si `costEstimate` es null o no existe, no inventes una estimaci\xF3n ni completes importes faltantes.',
|
|
39568
39943
|
inputSchema: GetFinancesInput.shape,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@productmaker/mcp",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "ProductMaker MCP server — cost products, generate landing pages, UGC videos, and ad creatives, and publish to Shopify, Meta Ads, and TikTok Ads.",
|