@productmaker/mcp 8.5.0 → 8.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 +9 -0
- package/dist/http.js +402 -210
- package/dist/stdio.js +402 -210
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -42,8 +42,20 @@ var NarrativeStyle = z.enum([
|
|
|
42
42
|
"ugc_skeptic_confession",
|
|
43
43
|
"ugc_demo_review",
|
|
44
44
|
"gap_replication",
|
|
45
|
-
"market"
|
|
45
|
+
"market",
|
|
46
|
+
"animated_storyteller",
|
|
47
|
+
"animated_inner_journey",
|
|
48
|
+
"animated_object_soul",
|
|
49
|
+
"animated_timeline"
|
|
50
|
+
]);
|
|
51
|
+
var AnimationStyleSchema = z.enum([
|
|
52
|
+
"pixar_3d",
|
|
53
|
+
"claymation",
|
|
54
|
+
"wes_anderson",
|
|
55
|
+
"sci_fi",
|
|
56
|
+
"realista"
|
|
46
57
|
]);
|
|
58
|
+
var ANIMATION_STYLE_VALUES = AnimationStyleSchema.options;
|
|
47
59
|
var VideoResolution = z.enum([
|
|
48
60
|
"480p",
|
|
49
61
|
"720p"
|
|
@@ -59,6 +71,10 @@ var VideoPreset = z.enum([
|
|
|
59
71
|
"wearable_showcase",
|
|
60
72
|
"pixar_problem",
|
|
61
73
|
"pixar_sassy",
|
|
74
|
+
"storyteller",
|
|
75
|
+
"inner_journey",
|
|
76
|
+
"object_soul",
|
|
77
|
+
"timeline",
|
|
62
78
|
"ugc_unboxing_chaos",
|
|
63
79
|
"ugc_curiosity_reveal",
|
|
64
80
|
"ugc_listicle_3",
|
|
@@ -3248,7 +3264,9 @@ var LandingProductSchema = z21.object({
|
|
|
3248
3264
|
whatsappNumber: z21.string().regex(/^\d{7,15}$/, 'digits only, 7\u201315 chars (e.g. "573001234567")').optional()
|
|
3249
3265
|
});
|
|
3250
3266
|
var CodeLandingProductSchema = LandingProductSchema.extend({
|
|
3251
|
-
price: z21.string().min(1).optional()
|
|
3267
|
+
price: z21.string().min(1).optional(),
|
|
3268
|
+
/** Keeps image-medium selection stable when a saved page is recomposed. */
|
|
3269
|
+
category: z21.string().min(1).optional()
|
|
3252
3270
|
});
|
|
3253
3271
|
var PAYMENT_METHOD_KEYS = [
|
|
3254
3272
|
"contraentrega",
|
|
@@ -4091,6 +4109,9 @@ var IngestOptions = z22.object({
|
|
|
4091
4109
|
videoTier: WritableVideoTier.default(DEFAULT_VIDEO_TIER),
|
|
4092
4110
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
4093
4111
|
videoPreset: VideoPreset.optional(),
|
|
4112
|
+
/** Orthogonal visual style for animated narratives only. The API rejects it
|
|
4113
|
+
* on non-animated presets; absent → the pipeline resolves 'pixar_3d'. */
|
|
4114
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
4094
4115
|
multiAngleVideos: z22.boolean().default(false),
|
|
4095
4116
|
videoAngleCount: z22.number().int().min(1).max(3).optional(),
|
|
4096
4117
|
/** Per-angle narrative override (positional). angleNarratives[i] forces the
|
|
@@ -4287,6 +4308,10 @@ var VideoOptionsOverride = z22.object({
|
|
|
4287
4308
|
ugcFormat: VideoFormat.optional(),
|
|
4288
4309
|
videoStyle: VideoStyle.optional(),
|
|
4289
4310
|
narrativeStyle: NarrativeStyle.optional(),
|
|
4311
|
+
/** Animation-style pick for THIS angle. The approve/draft handlers persist
|
|
4312
|
+
* it on the angle's own row (Angle.animationStyle) while its effective
|
|
4313
|
+
* narrative is animated; switching to a non-animated narrative clears it. */
|
|
4314
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
4290
4315
|
videoResolution: VideoResolution.optional(),
|
|
4291
4316
|
voiceId: VoiceId.optional(),
|
|
4292
4317
|
/** Actor/character description (role + appearance + attitude). Drives voice and video character. */
|
|
@@ -5256,14 +5281,17 @@ var ApproveVideoScriptRequest = z27.object({
|
|
|
5256
5281
|
angleKey: z27.string().trim().min(1).max(120).optional(),
|
|
5257
5282
|
scenes: z27.array(z27.object({
|
|
5258
5283
|
index: z27.number().int().nonnegative(),
|
|
5259
|
-
|
|
5284
|
+
// Empty is admitted at the wire: only the service knows whether the
|
|
5285
|
+
// shot is a designed-silent beat (productOnly / winner-copy), so the
|
|
5286
|
+
// per-shot empty-line policy lives there — NOT here.
|
|
5287
|
+
dialogue: z27.string().trim().max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS)
|
|
5260
5288
|
}).strict()).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES)
|
|
5261
5289
|
}).strict();
|
|
5262
5290
|
var ApproveVideoScriptResponse = z27.object({
|
|
5263
5291
|
status: ScriptReviewStatus
|
|
5264
5292
|
});
|
|
5265
5293
|
var RegenerateVideoScriptNarrativeRequest = z27.object({
|
|
5266
|
-
angleKey: z27.string().min(1),
|
|
5294
|
+
angleKey: z27.string().trim().min(1).max(120),
|
|
5267
5295
|
narrativeStyle: NarrativeStyle,
|
|
5268
5296
|
narrativeSelection: z27.enum([
|
|
5269
5297
|
"market",
|
|
@@ -5277,7 +5305,11 @@ var RegenerateVideoScriptNarrativeRequest = z27.object({
|
|
|
5277
5305
|
});
|
|
5278
5306
|
var RegenerateVideoScriptNarrativeResponse = z27.object({
|
|
5279
5307
|
/** 'not_ready' while Phase 1 re-runs; the client polls until 'ready'. */
|
|
5280
|
-
status: ScriptReviewStatus
|
|
5308
|
+
status: ScriptReviewStatus,
|
|
5309
|
+
/** The angle text the new script is written from — re-voiced into the new
|
|
5310
|
+
* narrative's speaker when that changed it. The review card shows it right
|
|
5311
|
+
* away so its next draft save cannot write the old voice back. */
|
|
5312
|
+
angle: z27.string().optional()
|
|
5281
5313
|
});
|
|
5282
5314
|
var RegenerateVideoRequest = z27.object({
|
|
5283
5315
|
angleKey: z27.string().min(1)
|
|
@@ -6303,7 +6335,11 @@ var AutoResolvedPresetSchema = z35.enum([
|
|
|
6303
6335
|
"wearable_showcase",
|
|
6304
6336
|
"pixar_problem",
|
|
6305
6337
|
"pixar_sassy",
|
|
6306
|
-
"metaphor_product"
|
|
6338
|
+
"metaphor_product",
|
|
6339
|
+
"storyteller",
|
|
6340
|
+
"inner_journey",
|
|
6341
|
+
"object_soul",
|
|
6342
|
+
"timeline"
|
|
6307
6343
|
]);
|
|
6308
6344
|
var SelectedOutputsSchema = z35.array(z35.enum([
|
|
6309
6345
|
"landing",
|
|
@@ -6396,6 +6432,9 @@ var TaskCreativeVariantResult = TaskCreativeVariantBaseResult.extend({
|
|
|
6396
6432
|
images: z35.array(LandingImageReadable).min(1).max(MAX_LANDING_IMAGES)
|
|
6397
6433
|
}).optional()
|
|
6398
6434
|
});
|
|
6435
|
+
var ResultAngle = Angle.extend({
|
|
6436
|
+
animationStyle: AnimationStyleSchema.optional()
|
|
6437
|
+
});
|
|
6399
6438
|
var MVPResult = z35.object({
|
|
6400
6439
|
taskId: z35.string().uuid(),
|
|
6401
6440
|
product: Product,
|
|
@@ -6407,7 +6446,7 @@ var MVPResult = z35.object({
|
|
|
6407
6446
|
// into a 500 on GET /v1/results/:taskId and hides EVERY deliverable of a
|
|
6408
6447
|
// task that already finished. Same failure shape as the variant landing cap
|
|
6409
6448
|
// below (alert 88badc8). The write path is what must stay at 3.
|
|
6410
|
-
angles: z35.array(
|
|
6449
|
+
angles: z35.array(ResultAngle),
|
|
6411
6450
|
topVideos: z35.array(AdVideo).max(20),
|
|
6412
6451
|
landing: z35.object({
|
|
6413
6452
|
// Allow legacy data (10 sections × 2 variants) and new data (7 sections × 2)
|
|
@@ -6439,6 +6478,10 @@ var MVPResult = z35.object({
|
|
|
6439
6478
|
// and by angles review banner.
|
|
6440
6479
|
autoResolvedPreset: AutoResolvedPresetSchema.optional(),
|
|
6441
6480
|
autoResolveReasoning: z35.string().optional(),
|
|
6481
|
+
/** Persisted animated-narrative visual style (Task.animationStyle). Absent on
|
|
6482
|
+
* non-animated tasks and rows predating the axis — readers resolve
|
|
6483
|
+
* 'pixar_3d' as the default. */
|
|
6484
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
6442
6485
|
partialVideoResult: PartialVideoResult.optional(),
|
|
6443
6486
|
/** Mixed images derived from MixTask rows linked to this task via sourceTaskId. */
|
|
6444
6487
|
mixedImages: z35.array(MixedImage).optional(),
|
|
@@ -6759,6 +6802,10 @@ var StatusResponse = z35.object({
|
|
|
6759
6802
|
videoRouteId: VideoRouteId.optional(),
|
|
6760
6803
|
videoResolution: VideoResolution.optional(),
|
|
6761
6804
|
narrativeStyle: NarrativeStyle.optional(),
|
|
6805
|
+
/** Persisted animated-narrative visual style (Task.animationStyle). Absent on
|
|
6806
|
+
* non-animated tasks and rows predating the axis — readers resolve
|
|
6807
|
+
* 'pixar_3d' as the default. */
|
|
6808
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
6762
6809
|
videoAngleCount: z35.number().int().min(1).max(3).optional(),
|
|
6763
6810
|
/** Historical authorization flag kept for clients resolving legacy reviews. */
|
|
6764
6811
|
multiAngleVideos: z35.boolean().optional(),
|
|
@@ -8645,13 +8692,16 @@ var DEFAULT_PRICING = {
|
|
|
8645
8692
|
ourCostCents: 0.07,
|
|
8646
8693
|
userPriceCents: 0.14
|
|
8647
8694
|
},
|
|
8695
|
+
// Both rewrites: RE-DERIVED 2026-09-28 from 14d of prod BillingEntry.
|
|
8696
|
+
// final-simplify n=123 mean 1.26¢ / p95 1.98¢ user; targeted-retry n=439 mean 2.09¢ /
|
|
8697
|
+
// p95 3.37¢ user. The old 0.8¢ (a Flash-era guess) under-quoted both 2.5-4x.
|
|
8648
8698
|
"openrouter:video-final-simplify-rewrite": {
|
|
8649
|
-
ourCostCents:
|
|
8650
|
-
userPriceCents:
|
|
8699
|
+
ourCostCents: 1,
|
|
8700
|
+
userPriceCents: 2
|
|
8651
8701
|
},
|
|
8652
8702
|
"openrouter:video-targeted-retry-rewrite": {
|
|
8653
|
-
ourCostCents:
|
|
8654
|
-
userPriceCents:
|
|
8703
|
+
ourCostCents: 1.7,
|
|
8704
|
+
userPriceCents: 3.4
|
|
8655
8705
|
},
|
|
8656
8706
|
// For helper-recorded entries (`callOpenRouter`), `ourCostCents` here is
|
|
8657
8707
|
// only used when `usage.cost` is missing from the provider response —
|
|
@@ -9713,11 +9763,15 @@ var DEFAULT_PRICING = {
|
|
|
9713
9763
|
// Video QA — combined describe+judge pass. The DETECTOR runs on gemini-3.8-flash at
|
|
9714
9764
|
// reasoning.effort=high (recall-critical: it gates a $2-4 re-render). Real billing
|
|
9715
9765
|
// uses OpenRouter's per-call usage.cost (×2), so this value is ONLY the estimator
|
|
9716
|
-
// basis + the rare fallback when usage.cost is missing
|
|
9717
|
-
//
|
|
9766
|
+
// basis + the rare fallback when usage.cost is missing.
|
|
9767
|
+
// RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9768
|
+
// n=2073, mean 3.57¢ / p95 8.95¢ / p99 12.04¢ / max 13.50¢ user per call.
|
|
9769
|
+
// 12¢ sits at the p99 and still covers DETECTOR_MAX_CALLS (3) × the mean (10.71¢) —
|
|
9770
|
+
// the invariant pinned in cost-estimator.spec.test.ts. The former 20¢ was sized to a
|
|
9771
|
+
// Pro+high call that no longer runs and inflated every QA pass of the credit gate.
|
|
9718
9772
|
"openrouter:video-qa-describe-judge": {
|
|
9719
|
-
ourCostCents:
|
|
9720
|
-
userPriceCents:
|
|
9773
|
+
ourCostCents: 6,
|
|
9774
|
+
userPriceCents: 12
|
|
9721
9775
|
},
|
|
9722
9776
|
// Video QA — hand scanner reinforcement (Gemini 3.7 Flash, dense frames around spike)
|
|
9723
9777
|
"openrouter:video-hand-reinforcement": {
|
|
@@ -9786,13 +9840,16 @@ var DEFAULT_PRICING = {
|
|
|
9786
9840
|
userPriceCents: 0.22
|
|
9787
9841
|
},
|
|
9788
9842
|
// Clip Judge — text-only comparison of QA results between original and retry clips
|
|
9789
|
-
// (google/gemini-3.8-flash, text-only).
|
|
9843
|
+
// (google/gemini-3.8-flash, text-only). RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9844
|
+
// n=92, mean 0.34¢ / p95 0.54¢ user
|
|
9845
|
+
// (the old 0.12¢ assumed ~$0.0006 and under-quoted 4.5x).
|
|
9790
9846
|
"openrouter:clip-judge-text": {
|
|
9791
|
-
ourCostCents: 0.
|
|
9792
|
-
userPriceCents: 0.
|
|
9847
|
+
ourCostCents: 0.28,
|
|
9848
|
+
userPriceCents: 0.56
|
|
9793
9849
|
},
|
|
9794
9850
|
// Clip Judge — vision comparison of two video clips (google/gemini-3.8-flash, 2 videos)
|
|
9795
|
-
// Our cost: ~$0.01 => 1.0 cents; 2x markup.
|
|
9851
|
+
// Our cost: ~$0.01 => 1.0 cents; 2x markup. Checked 2026-09-28 (n=346): mean 1.38¢ /
|
|
9852
|
+
// p95 1.90¢ user — already covered, unchanged.
|
|
9796
9853
|
"openrouter:clip-judge-vision": {
|
|
9797
9854
|
ourCostCents: 1,
|
|
9798
9855
|
userPriceCents: 2
|
|
@@ -9809,10 +9866,13 @@ var DEFAULT_PRICING = {
|
|
|
9809
9866
|
ourCostCents: 0.89,
|
|
9810
9867
|
userPriceCents: 1.78
|
|
9811
9868
|
},
|
|
9812
|
-
// Video QA — product integrity scanner (
|
|
9869
|
+
// Video QA — product integrity scanner (gemini-3.8-flash, 5 frames + reference).
|
|
9870
|
+
// RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9871
|
+
// n=1828, mean 2.91¢ / p95 5.07¢ / max 11.50¢ user per call. The old 0.3¢
|
|
9872
|
+
// (a 3.7-Flash-era guess) under-quoted it ~10x on every QA pass.
|
|
9813
9873
|
"openrouter:video-product-integrity": {
|
|
9814
|
-
ourCostCents:
|
|
9815
|
-
userPriceCents:
|
|
9874
|
+
ourCostCents: 2.6,
|
|
9875
|
+
userPriceCents: 5.2
|
|
9816
9876
|
},
|
|
9817
9877
|
// Video QA — anatomy. THREE keys, and they do NOT share a unit. Getting this wrong
|
|
9818
9878
|
// over-charges by ~42x, which is exactly what a first pass at the 2026-07-30 change did.
|
|
@@ -9850,11 +9910,35 @@ var DEFAULT_PRICING = {
|
|
|
9850
9910
|
userPriceCents: 0.4
|
|
9851
9911
|
},
|
|
9852
9912
|
// (c) Tracing confirmation of a frames-only finding: 3 stills + the full downscaled video,
|
|
9853
|
-
// one call.
|
|
9854
|
-
//
|
|
9913
|
+
// one call. RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9914
|
+
// n=46, mean 2.67¢ / p95 4.48¢ / max 5.43¢ user — the
|
|
9915
|
+
// former 3.0¢ (from a 14-call spike, 0.59¢ our mean) sat below the prod p95.
|
|
9855
9916
|
"openrouter:video-qa-anatomy-tracing-confirm": {
|
|
9856
|
-
ourCostCents:
|
|
9857
|
-
userPriceCents:
|
|
9917
|
+
ourCostCents: 2.25,
|
|
9918
|
+
userPriceCents: 4.5
|
|
9919
|
+
},
|
|
9920
|
+
// (d) DENSE anatomy detector (the default anatomy detector since 2026-09-26;
|
|
9921
|
+
// QA_ANATOMY_DETECTOR=frame_judge reverts): gemini-3.1-pro judges every extracted
|
|
9922
|
+
// frame at 1 fps, 5 frames per call, each call billing its frame count — the rate is
|
|
9923
|
+
// PER FRAME like (b) and scales with QA_DENSE_DETECTOR_MAX_FRAMES. Measured on the
|
|
9924
|
+
// owner corpus with the shipped config (reasoning=low, grouped): $1.062 / 296 frames
|
|
9925
|
+
// ≈ 0.36c/frame; 0.5c keeps ~40% headroom. The old 3.0c fallback was the 2026-09-22
|
|
9926
|
+
// one-still-per-call spike at default reasoning (~1.95c/frame) and would have quoted
|
|
9927
|
+
// QA ~10x its cost. Re-derive from 30d BillingEntry once live.
|
|
9928
|
+
"openrouter:video-qa-anatomy-dense-detector": {
|
|
9929
|
+
ourCostCents: 0.5,
|
|
9930
|
+
userPriceCents: 1
|
|
9931
|
+
},
|
|
9932
|
+
// (e) Dense-mode tracing confirmation: the SAME confirmer call as (c) but routed
|
|
9933
|
+
// to gemini-3.1-pro — flash measured 3/11 recall confirming dense stills, so
|
|
9934
|
+
// dense findings never confirm on the gate model. PER CALL.
|
|
9935
|
+
// Spike measured $2.22/80 ≈ 2.8c/call; the 2026-09-26 A/B measured 2.6c/flag.
|
|
9936
|
+
// 3.0c keeps it above both. (The former 5.0c/10.0c, times the old 4-confirmation cap,
|
|
9937
|
+
// inflated the credit gate's `max` by up to ~12,600 credits on a 30 s multi-scene.)
|
|
9938
|
+
// Re-derive from 30d BillingEntry once live.
|
|
9939
|
+
"openrouter:video-qa-anatomy-dense-confirm": {
|
|
9940
|
+
ourCostCents: 3,
|
|
9941
|
+
userPriceCents: 6
|
|
9858
9942
|
},
|
|
9859
9943
|
// Physics confirmation — skeptical second opinion on D+J floating-object flags
|
|
9860
9944
|
// (Gemini 3.7 Flash, ~3 frames per flagged moment, 1 call). Aligned with other vision-QA keys.
|
|
@@ -10244,6 +10328,14 @@ var DEFAULT_PRICING = {
|
|
|
10244
10328
|
ourCostCents: 3,
|
|
10245
10329
|
userPriceCents: 6
|
|
10246
10330
|
},
|
|
10331
|
+
// Unit = one storyteller brief (insight, figure, metaphor, money shot): ONE text call per
|
|
10332
|
+
// storyteller-family angle before its plan is authored (`rapid-storyteller-brief`, judge-text
|
|
10333
|
+
// role). Billed since the family shipped but quoted nowhere until 2026-09-25. Priced by ANALOGY
|
|
10334
|
+
// with `rapid-grok-shot-action` (one batched text call of similar size), not measured yet.
|
|
10335
|
+
"openrouter:rapid-storyteller-brief": {
|
|
10336
|
+
ourCostCents: 3,
|
|
10337
|
+
userPriceCents: 6
|
|
10338
|
+
},
|
|
10247
10339
|
// Unit = one frame inventory: a single-image vision pass over ONE rendered panel, listing which
|
|
10248
10340
|
// hands are visible and what each holds, so the shot-action flatten can author against the frame
|
|
10249
10341
|
// the clip animates from instead of against the text the panel was asked to be. PER SHOT, not
|
|
@@ -13534,25 +13626,37 @@ function whatsappFieldAuthority(field, source) {
|
|
|
13534
13626
|
}
|
|
13535
13627
|
__name(whatsappFieldAuthority, "whatsappFieldAuthority");
|
|
13536
13628
|
var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
13537
|
-
defineCapability(
|
|
13629
|
+
defineCapability(
|
|
13630
|
+
"approve_video_script",
|
|
13631
|
+
// 2026-09-29: dialogue admits "" at the wire — silent-allowed shots
|
|
13632
|
+
// (productOnly / gap_replication) are legal, the API decides per-shot.
|
|
13633
|
+
// Recomputed over the Fase-4 shared ApproveVideoScriptSceneEdit.
|
|
13634
|
+
"fdd641922f73907881ee09b62a006e0af1b277cab3d990ebc8c151c96b715693",
|
|
13538
13635
|
"credit_consuming",
|
|
13539
|
-
"
|
|
13540
|
-
|
|
13541
|
-
|
|
13542
|
-
"
|
|
13543
|
-
]
|
|
13544
|
-
|
|
13545
|
-
"
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
"
|
|
13549
|
-
|
|
13550
|
-
|
|
13551
|
-
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13636
|
+
"creative",
|
|
13637
|
+
[
|
|
13638
|
+
"credit_consuming",
|
|
13639
|
+
"state_change"
|
|
13640
|
+
],
|
|
13641
|
+
[
|
|
13642
|
+
slot("task", true, [
|
|
13643
|
+
"taskId"
|
|
13644
|
+
]),
|
|
13645
|
+
slot("angle", false, [
|
|
13646
|
+
"angleKey"
|
|
13647
|
+
]),
|
|
13648
|
+
slot("script_scenes", true, [
|
|
13649
|
+
"scenes"
|
|
13650
|
+
])
|
|
13651
|
+
],
|
|
13652
|
+
[
|
|
13653
|
+
"task",
|
|
13654
|
+
"video_script"
|
|
13655
|
+
],
|
|
13656
|
+
[
|
|
13657
|
+
"task"
|
|
13658
|
+
]
|
|
13659
|
+
),
|
|
13556
13660
|
defineCapability("check_meta_media_upload", "62b1af1d796d9466f8926afc5e6d18c4ddeccd5b0269ca7b21c2f6ebcfd2a945", "none", "read_only", [
|
|
13557
13661
|
"read"
|
|
13558
13662
|
], [
|
|
@@ -13651,54 +13755,65 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13651
13755
|
], [
|
|
13652
13756
|
"product_costing"
|
|
13653
13757
|
]),
|
|
13654
|
-
defineCapability(
|
|
13758
|
+
defineCapability(
|
|
13759
|
+
"create_creative_variant",
|
|
13760
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
13761
|
+
"db6d98e9e07d57dd1a78d9b73cdbfdaa7ee7a6ae4dff30d1bd2b3edf3225cd0d",
|
|
13655
13762
|
"credit_consuming",
|
|
13656
|
-
"
|
|
13657
|
-
|
|
13658
|
-
|
|
13659
|
-
"
|
|
13660
|
-
]
|
|
13661
|
-
|
|
13662
|
-
"
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
"
|
|
13666
|
-
|
|
13667
|
-
|
|
13668
|
-
"
|
|
13669
|
-
|
|
13670
|
-
|
|
13671
|
-
"
|
|
13672
|
-
|
|
13673
|
-
"
|
|
13674
|
-
"
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
|
|
13679
|
-
|
|
13680
|
-
"
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13763
|
+
"creative",
|
|
13764
|
+
[
|
|
13765
|
+
"credit_consuming",
|
|
13766
|
+
"state_change"
|
|
13767
|
+
],
|
|
13768
|
+
[
|
|
13769
|
+
slot("source_task", true, [
|
|
13770
|
+
"sourceTaskId"
|
|
13771
|
+
]),
|
|
13772
|
+
slot("creative_kind", true, [
|
|
13773
|
+
"kind"
|
|
13774
|
+
]),
|
|
13775
|
+
slot("confirmation", true, [
|
|
13776
|
+
"confirm"
|
|
13777
|
+
], [], "confirmation"),
|
|
13778
|
+
slot("idempotency", true, [
|
|
13779
|
+
"clientRequestId"
|
|
13780
|
+
], void 0, "server"),
|
|
13781
|
+
slot("creative_brief", false, [
|
|
13782
|
+
"angle",
|
|
13783
|
+
"buyerPersona",
|
|
13784
|
+
"scriptNotes",
|
|
13785
|
+
"creativeDirection"
|
|
13786
|
+
]),
|
|
13787
|
+
slot("render_options", false, [
|
|
13788
|
+
"videoPreset",
|
|
13789
|
+
"videoResolution",
|
|
13790
|
+
"generateAiMusic",
|
|
13791
|
+
"nVariants",
|
|
13792
|
+
"imageStyle",
|
|
13793
|
+
"creativeArchetype",
|
|
13794
|
+
"visualTreatment",
|
|
13795
|
+
"aspectRatio",
|
|
13796
|
+
"styleMix",
|
|
13797
|
+
"sectionKey",
|
|
13798
|
+
"instructions"
|
|
13799
|
+
])
|
|
13800
|
+
],
|
|
13801
|
+
[
|
|
13802
|
+
"task",
|
|
13803
|
+
"creative"
|
|
13804
|
+
],
|
|
13805
|
+
[
|
|
13806
|
+
"creative_variant"
|
|
13807
|
+
]
|
|
13808
|
+
),
|
|
13695
13809
|
defineCapability(
|
|
13696
13810
|
"create_product_task",
|
|
13697
13811
|
// MCP 8.4.0 (Fase 4, Tarea 3, .agent/plans/2026-09-26-refactor-fase4-detallado.md):
|
|
13698
13812
|
// outputs accepts 1 value, actorId max 120, landingStrategy optional (no
|
|
13699
13813
|
// default). Recomputed from the real tools/list digest printer.
|
|
13700
13814
|
// + market study opt-in copy (#2005, competitorScanEnabled description).
|
|
13701
|
-
|
|
13815
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
13816
|
+
"46b308923121dac1023b55f68b61dfbf4e89f682bdd48b04d4d0f8a3667f8999",
|
|
13702
13817
|
"credit_consuming",
|
|
13703
13818
|
"creative",
|
|
13704
13819
|
[
|
|
@@ -13757,6 +13872,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13757
13872
|
"videoResolution",
|
|
13758
13873
|
"videoAngleCount",
|
|
13759
13874
|
"angleNarratives",
|
|
13875
|
+
"animationStyle",
|
|
13760
13876
|
"competitorScanEnabled",
|
|
13761
13877
|
"replicateWinnerWhenFound"
|
|
13762
13878
|
], [
|
|
@@ -13768,6 +13884,8 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13768
13884
|
"videoResolution",
|
|
13769
13885
|
"multiAngleVideos",
|
|
13770
13886
|
"angleNarratives",
|
|
13887
|
+
// MCP-only for now: the WhatsApp contract schema does not expose the
|
|
13888
|
+
// animation-style axis yet (Phase 1 ships it on web + MCP).
|
|
13771
13889
|
"competitorScanEnabled",
|
|
13772
13890
|
"competitorCommercialStudyRequested",
|
|
13773
13891
|
"replicateWinnerWhenFound"
|
|
@@ -13866,7 +13984,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13866
13984
|
], [
|
|
13867
13985
|
"task_draft"
|
|
13868
13986
|
]),
|
|
13869
|
-
defineCapability("estimate_creative_variant", "
|
|
13987
|
+
defineCapability("estimate_creative_variant", "055a92336bfb773c14e3f7018368b4490404ebcb3e607f78d5e0d5c0e78254b8", "none", "read_only", [
|
|
13870
13988
|
"read"
|
|
13871
13989
|
], [
|
|
13872
13990
|
slot("source_task", true, [
|
|
@@ -14195,112 +14313,127 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14195
14313
|
fieldCompletion: "all"
|
|
14196
14314
|
}
|
|
14197
14315
|
]),
|
|
14198
|
-
defineCapability(
|
|
14316
|
+
defineCapability(
|
|
14317
|
+
"generate_video_creative",
|
|
14318
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
14319
|
+
"5545b24de7b344c9184cfe087a39b766490526a432d8b288c02c2e9a20529c3d",
|
|
14199
14320
|
"credit_consuming",
|
|
14200
|
-
"state_change"
|
|
14201
|
-
], [
|
|
14202
|
-
slot("product_reference", true, [
|
|
14203
|
-
"images",
|
|
14204
|
-
"winnerReference"
|
|
14205
|
-
], [
|
|
14206
|
-
"imageMessageIds",
|
|
14207
|
-
"imageAssetIds",
|
|
14208
|
-
"projectId",
|
|
14209
|
-
"productUrl"
|
|
14210
|
-
]),
|
|
14211
|
-
slot("product_identity", true, [
|
|
14212
|
-
"title"
|
|
14213
|
-
]),
|
|
14214
|
-
// Optional in the canonical API because the shared generation pipeline
|
|
14215
|
-
// owns delegated angles. WhatsApp still asks through conversationInputs.
|
|
14216
|
-
slot("creative_angle", false, [
|
|
14217
|
-
"primaryAngle"
|
|
14218
|
-
]),
|
|
14219
|
-
slot("locale", true, [
|
|
14220
|
-
"language",
|
|
14221
|
-
"country"
|
|
14222
|
-
]),
|
|
14223
|
-
slot("render_options", true, [
|
|
14224
|
-
"angleNarratives",
|
|
14225
|
-
"aspectRatio",
|
|
14226
|
-
"durationSeconds",
|
|
14227
|
-
"videoAngleCount",
|
|
14228
|
-
"creativeSetup",
|
|
14229
|
-
"videoStructure",
|
|
14230
|
-
"videoQuality",
|
|
14231
|
-
"videoResolution",
|
|
14232
|
-
"features",
|
|
14233
|
-
"cta",
|
|
14234
|
-
"scriptNotes",
|
|
14235
|
-
"competitorScanEnabled",
|
|
14236
|
-
"replicateWinnerWhenFound"
|
|
14237
|
-
], [
|
|
14238
|
-
"aspectRatio",
|
|
14239
|
-
"durationSeconds",
|
|
14240
|
-
"videoPreset",
|
|
14241
|
-
"videoStructure",
|
|
14242
|
-
"videoQuality",
|
|
14243
|
-
"videoResolution",
|
|
14244
|
-
"features",
|
|
14245
|
-
"cta",
|
|
14246
|
-
"scriptNotes",
|
|
14247
|
-
"pauseForVideoScriptReview",
|
|
14248
|
-
"pauseForAngleReview",
|
|
14249
|
-
"competitorScanEnabled",
|
|
14250
|
-
"competitorCommercialStudyRequested",
|
|
14251
|
-
"replicateWinnerWhenFound"
|
|
14252
|
-
]),
|
|
14253
|
-
slot("commercial_offer", false, [
|
|
14254
|
-
"price",
|
|
14255
|
-
"offer"
|
|
14256
|
-
]),
|
|
14257
|
-
slot("product_context", false, [
|
|
14258
|
-
"productContext",
|
|
14259
|
-
"productLabel"
|
|
14260
|
-
], []),
|
|
14261
|
-
slot("brand_direction", false, [
|
|
14262
|
-
"brandId"
|
|
14263
|
-
]),
|
|
14264
|
-
// Casting pin. MCP-only for now: the WhatsApp generate_video_creative request
|
|
14265
|
-
// schema is .strict() and does not carry it yet (follow-up), hence the explicit [].
|
|
14266
|
-
slot("actor", false, [
|
|
14267
|
-
"creativeGender"
|
|
14268
|
-
], [])
|
|
14269
|
-
], [
|
|
14270
|
-
"product_reference"
|
|
14271
|
-
], [
|
|
14272
|
-
"task",
|
|
14273
14321
|
"creative",
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14322
|
+
[
|
|
14323
|
+
"credit_consuming",
|
|
14324
|
+
"state_change"
|
|
14325
|
+
],
|
|
14326
|
+
[
|
|
14327
|
+
slot("product_reference", true, [
|
|
14328
|
+
"images",
|
|
14329
|
+
"winnerReference"
|
|
14330
|
+
], [
|
|
14331
|
+
"imageMessageIds",
|
|
14332
|
+
"imageAssetIds",
|
|
14333
|
+
"projectId",
|
|
14334
|
+
"productUrl"
|
|
14335
|
+
]),
|
|
14336
|
+
slot("product_identity", true, [
|
|
14337
|
+
"title"
|
|
14338
|
+
]),
|
|
14339
|
+
// Optional in the canonical API because the shared generation pipeline
|
|
14340
|
+
// owns delegated angles. WhatsApp still asks through conversationInputs.
|
|
14341
|
+
slot("creative_angle", false, [
|
|
14294
14342
|
"primaryAngle"
|
|
14295
|
-
]
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14343
|
+
]),
|
|
14344
|
+
slot("locale", true, [
|
|
14345
|
+
"language",
|
|
14346
|
+
"country"
|
|
14347
|
+
]),
|
|
14348
|
+
slot("render_options", true, [
|
|
14349
|
+
"angleNarratives",
|
|
14350
|
+
"aspectRatio",
|
|
14351
|
+
"durationSeconds",
|
|
14352
|
+
"videoAngleCount",
|
|
14353
|
+
// animationStyle rides inside creativeSetup.guided on this tool, so
|
|
14354
|
+
// it is not a top-level schema field here (it is on
|
|
14355
|
+
// create_product_task).
|
|
14356
|
+
"creativeSetup",
|
|
14357
|
+
"videoStructure",
|
|
14358
|
+
"videoQuality",
|
|
14359
|
+
"videoResolution",
|
|
14360
|
+
"features",
|
|
14361
|
+
"cta",
|
|
14362
|
+
"scriptNotes",
|
|
14363
|
+
"competitorScanEnabled",
|
|
14364
|
+
"replicateWinnerWhenFound"
|
|
14365
|
+
], [
|
|
14366
|
+
"aspectRatio",
|
|
14367
|
+
"durationSeconds",
|
|
14368
|
+
"videoPreset",
|
|
14369
|
+
"videoStructure",
|
|
14370
|
+
"videoQuality",
|
|
14371
|
+
"videoResolution",
|
|
14372
|
+
"features",
|
|
14373
|
+
"cta",
|
|
14374
|
+
"scriptNotes",
|
|
14375
|
+
"pauseForVideoScriptReview",
|
|
14376
|
+
"pauseForAngleReview",
|
|
14377
|
+
"competitorScanEnabled",
|
|
14378
|
+
"competitorCommercialStudyRequested",
|
|
14379
|
+
"replicateWinnerWhenFound"
|
|
14380
|
+
]),
|
|
14381
|
+
slot("commercial_offer", false, [
|
|
14382
|
+
"price",
|
|
14383
|
+
"offer"
|
|
14384
|
+
]),
|
|
14385
|
+
slot("product_context", false, [
|
|
14386
|
+
"productContext",
|
|
14387
|
+
"productLabel"
|
|
14388
|
+
], []),
|
|
14389
|
+
slot("brand_direction", false, [
|
|
14390
|
+
"brandId"
|
|
14391
|
+
]),
|
|
14392
|
+
// Casting pin. MCP-only for now: the WhatsApp generate_video_creative request
|
|
14393
|
+
// schema is .strict() and does not carry it yet (follow-up), hence the explicit [].
|
|
14394
|
+
slot("actor", false, [
|
|
14395
|
+
"creativeGender"
|
|
14396
|
+
], [])
|
|
14397
|
+
],
|
|
14398
|
+
[
|
|
14399
|
+
"product_reference"
|
|
14400
|
+
],
|
|
14401
|
+
[
|
|
14402
|
+
"task",
|
|
14403
|
+
"creative",
|
|
14404
|
+
"video"
|
|
14405
|
+
],
|
|
14406
|
+
SHARED_CHANNEL_EXPOSURE,
|
|
14407
|
+
[
|
|
14408
|
+
{
|
|
14409
|
+
slot: "product_reference",
|
|
14410
|
+
askBeforePaidExecution: true,
|
|
14411
|
+
explicitOmissionAllowed: false,
|
|
14412
|
+
fieldCompletion: "any"
|
|
14413
|
+
},
|
|
14414
|
+
{
|
|
14415
|
+
slot: "locale",
|
|
14416
|
+
askBeforePaidExecution: true,
|
|
14417
|
+
explicitOmissionAllowed: false,
|
|
14418
|
+
fieldCompletion: "all"
|
|
14419
|
+
},
|
|
14420
|
+
{
|
|
14421
|
+
slot: "creative_angle",
|
|
14422
|
+
askBeforePaidExecution: true,
|
|
14423
|
+
explicitOmissionAllowed: true,
|
|
14424
|
+
fieldCompletion: "any",
|
|
14425
|
+
completionFields: [
|
|
14426
|
+
"primaryAngle"
|
|
14427
|
+
]
|
|
14428
|
+
},
|
|
14429
|
+
{
|
|
14430
|
+
slot: "commercial_offer",
|
|
14431
|
+
askBeforePaidExecution: true,
|
|
14432
|
+
explicitOmissionAllowed: true,
|
|
14433
|
+
fieldCompletion: "all"
|
|
14434
|
+
}
|
|
14435
|
+
]
|
|
14436
|
+
),
|
|
14304
14437
|
defineCapability("get_meta_campaign_status", "92077241cf4e9d14edefca410e85715cc383b1433081c3461c925f8fc3d6e8ab", "none", "read_only", [
|
|
14305
14438
|
"read"
|
|
14306
14439
|
], [
|
|
@@ -14608,7 +14741,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14608
14741
|
], [
|
|
14609
14742
|
"product_media"
|
|
14610
14743
|
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
14611
|
-
defineCapability("regenerate_video_script", "
|
|
14744
|
+
defineCapability("regenerate_video_script", "198903f5d89b245daedde4e08020a6d536f2ea354f5924176253b71c84241859", "credit_consuming", "creative", [
|
|
14612
14745
|
"credit_consuming",
|
|
14613
14746
|
"state_change"
|
|
14614
14747
|
], [
|
|
@@ -14671,7 +14804,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14671
14804
|
], [
|
|
14672
14805
|
"media_upload_session"
|
|
14673
14806
|
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
14674
|
-
defineCapability("resolve_pending_action", "
|
|
14807
|
+
defineCapability("resolve_pending_action", "7d76b53ebce3265a751836e61f6959debd98bd8159291ef73437e1b7a0824333", "credit_consuming", "creative", [
|
|
14675
14808
|
"credit_consuming",
|
|
14676
14809
|
"state_change"
|
|
14677
14810
|
], [
|
|
@@ -15085,6 +15218,10 @@ var MCP_ANGLE_NARRATIVE_STYLES = [
|
|
|
15085
15218
|
"wild_card",
|
|
15086
15219
|
"animated_problem_pixar",
|
|
15087
15220
|
"sassy_product_pixar",
|
|
15221
|
+
"animated_storyteller",
|
|
15222
|
+
"animated_inner_journey",
|
|
15223
|
+
"animated_object_soul",
|
|
15224
|
+
"animated_timeline",
|
|
15088
15225
|
"market"
|
|
15089
15226
|
];
|
|
15090
15227
|
var McpAngleNarrativeStyleSchema = NarrativeStyle.extract(MCP_ANGLE_NARRATIVE_STYLES);
|
|
@@ -16359,9 +16496,7 @@ var FlightRecorderResponseSchema = z75.object({
|
|
|
16359
16496
|
import { z as z76 } from "zod";
|
|
16360
16497
|
var ApproveVideoScriptSceneEdit = z76.object({
|
|
16361
16498
|
index: z76.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
16362
|
-
dialogue: z76.string().
|
|
16363
|
-
message: "dialogue no puede ser s\xF3lo espacios"
|
|
16364
|
-
}).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.")
|
|
16499
|
+
dialogue: z76.string().trim().max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS).describe('Di\xE1logo final de la escena. Puede ser el original sin cambios o la edici\xF3n del usuario. Vac\xEDo ("") s\xF3lo es v\xE1lido en escenas silenciosas por dise\xF1o (productOnly o \xE1ngulos winner-copy); en una escena hablada el backend lo rechaza con 400.')
|
|
16365
16500
|
}).strict();
|
|
16366
16501
|
var ApproveVideoScriptCapabilityRequest = z76.object({
|
|
16367
16502
|
taskId: z76.string().min(1).describe("ID de la tarea."),
|
|
@@ -18057,7 +18192,7 @@ var ApiClient = class {
|
|
|
18057
18192
|
};
|
|
18058
18193
|
|
|
18059
18194
|
// src/index.ts
|
|
18060
|
-
var MCP_VERSION = "8.
|
|
18195
|
+
var MCP_VERSION = "8.6.0";
|
|
18061
18196
|
|
|
18062
18197
|
// src/meta-upload-app.ts
|
|
18063
18198
|
import { readFileSync } from "fs";
|
|
@@ -18706,7 +18841,11 @@ var VideoPresetEnum = VideoPreset.extract([
|
|
|
18706
18841
|
"cinematic",
|
|
18707
18842
|
"wild_card",
|
|
18708
18843
|
"pixar_problem",
|
|
18709
|
-
"pixar_sassy"
|
|
18844
|
+
"pixar_sassy",
|
|
18845
|
+
"storyteller",
|
|
18846
|
+
"inner_journey",
|
|
18847
|
+
"object_soul",
|
|
18848
|
+
"timeline"
|
|
18710
18849
|
]);
|
|
18711
18850
|
var VideoStructureEnum = VideoStructure;
|
|
18712
18851
|
var VideoQualityEnum = VideoQuality;
|
|
@@ -18753,6 +18892,22 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
18753
18892
|
wild_card: {
|
|
18754
18893
|
videoStyle: "product_only",
|
|
18755
18894
|
narrativeStyle: "wild_card"
|
|
18895
|
+
},
|
|
18896
|
+
storyteller: {
|
|
18897
|
+
videoStyle: "ai_dynamic",
|
|
18898
|
+
narrativeStyle: "animated_storyteller"
|
|
18899
|
+
},
|
|
18900
|
+
inner_journey: {
|
|
18901
|
+
videoStyle: "ai_dynamic",
|
|
18902
|
+
narrativeStyle: "animated_inner_journey"
|
|
18903
|
+
},
|
|
18904
|
+
object_soul: {
|
|
18905
|
+
videoStyle: "ai_dynamic",
|
|
18906
|
+
narrativeStyle: "animated_object_soul"
|
|
18907
|
+
},
|
|
18908
|
+
timeline: {
|
|
18909
|
+
videoStyle: "ai_dynamic",
|
|
18910
|
+
narrativeStyle: "animated_timeline"
|
|
18756
18911
|
}
|
|
18757
18912
|
};
|
|
18758
18913
|
function resolveVideoPreset(preset) {
|
|
@@ -18760,6 +18915,26 @@ function resolveVideoPreset(preset) {
|
|
|
18760
18915
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
18761
18916
|
}
|
|
18762
18917
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
18918
|
+
var ANIMATED_VIDEO_PRESETS = /* @__PURE__ */ new Set([
|
|
18919
|
+
"pixar_problem",
|
|
18920
|
+
"pixar_sassy",
|
|
18921
|
+
"storyteller",
|
|
18922
|
+
"inner_journey",
|
|
18923
|
+
"object_soul",
|
|
18924
|
+
"timeline"
|
|
18925
|
+
]);
|
|
18926
|
+
var ANIMATED_NARRATIVE_STYLES = /* @__PURE__ */ new Set([
|
|
18927
|
+
"animated_problem_pixar",
|
|
18928
|
+
"sassy_product_pixar",
|
|
18929
|
+
"animated_storyteller",
|
|
18930
|
+
"animated_inner_journey",
|
|
18931
|
+
"animated_object_soul",
|
|
18932
|
+
"animated_timeline"
|
|
18933
|
+
]);
|
|
18934
|
+
function animationStyleApplies(videoPreset, angleNarratives) {
|
|
18935
|
+
return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
|
|
18936
|
+
}
|
|
18937
|
+
__name(animationStyleApplies, "animationStyleApplies");
|
|
18763
18938
|
var VideoTierEnum = z78.enum([
|
|
18764
18939
|
"basic"
|
|
18765
18940
|
]);
|
|
@@ -18771,19 +18946,23 @@ function resolveWireVideoTier(tier, durationSeconds) {
|
|
|
18771
18946
|
return durationSeconds === 30 ? "standard" : resolveVideoTier(tier);
|
|
18772
18947
|
}
|
|
18773
18948
|
__name(resolveWireVideoTier, "resolveWireVideoTier");
|
|
18774
|
-
function assertVideoPresetDurationCompatibility(
|
|
18775
|
-
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18949
|
+
function assertVideoPresetDurationCompatibility(_videoPreset, _durationSeconds, _videoStructure, _videoQuality) {
|
|
18950
|
+
}
|
|
18951
|
+
__name(assertVideoPresetDurationCompatibility, "assertVideoPresetDurationCompatibility");
|
|
18952
|
+
var MULTI_SCENE_ONLY_NARRATIVES = /* @__PURE__ */ new Set([]);
|
|
18953
|
+
function assertAngleNarrativeDurationCompatibility(angleNarratives, durationSeconds, videoStructure) {
|
|
18954
|
+
if (!angleNarratives?.some((n) => MULTI_SCENE_ONLY_NARRATIVES.has(n))) return;
|
|
18955
|
+
if (videoStructure !== void 0) {
|
|
18956
|
+
if (videoStructure === "single_take") {
|
|
18957
|
+
throw new Error("Alguna de las narrativas por \xE1ngulo solo est\xE1 disponible en Multiescena.");
|
|
18779
18958
|
}
|
|
18780
18959
|
return;
|
|
18781
18960
|
}
|
|
18782
18961
|
if (durationSeconds !== 30) {
|
|
18783
|
-
throw new Error("
|
|
18962
|
+
throw new Error("Alguna de las narrativas por \xE1ngulo solo est\xE1 disponible en videos Multiescena de 30 segundos.");
|
|
18784
18963
|
}
|
|
18785
18964
|
}
|
|
18786
|
-
__name(
|
|
18965
|
+
__name(assertAngleNarrativeDurationCompatibility, "assertAngleNarrativeDurationCompatibility");
|
|
18787
18966
|
function resolveVideoFormatForDuration(durationSeconds) {
|
|
18788
18967
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
18789
18968
|
}
|
|
@@ -18804,6 +18983,7 @@ var VideoResolutionEnum = VideoResolution;
|
|
|
18804
18983
|
var CreativeGenderEnum = CreativeGenderPin;
|
|
18805
18984
|
var NarrativeStyleEnum = McpNarrativeStyleSchema;
|
|
18806
18985
|
var PublicNarrativeStyleEnum = McpAngleNarrativeStyleSchema;
|
|
18986
|
+
var AnimationStyleEnum = AnimationStyleSchema;
|
|
18807
18987
|
var TaskVideoModelEnum = VideoModel;
|
|
18808
18988
|
var ProductReferenceUserChoiceEnum = ProductReferenceUserChoiceSchema;
|
|
18809
18989
|
var ProductReferenceScopeEnum = ProductReferenceScopeSchema;
|
|
@@ -20456,7 +20636,8 @@ var CreateProductTaskInput = z81.object({
|
|
|
20456
20636
|
paymentMethods: z81.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.'),
|
|
20457
20637
|
productContext: z81.string().max(PRODUCT_CONTEXT_MAX_CHARS).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."),
|
|
20458
20638
|
productLabel: z81.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.'),
|
|
20459
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena)
|
|
20639
|
+
videoPreset: VideoPresetEnum.default("auto").describe('Opcional. Tipo/narrativa del video \u2014 \xFAnico campo de "estilo" que el usuario controla. Default "auto" (la IA escoge tras analizar el producto). Todos los presets funcionan a 15s (single_call) y 30s (Multiescena); "problem_solution" en single_call abre sin el producto y el producto entra por referencia en su beat de soluci\xF3n. Opciones: "auto", "ugc_dynamic" (review con experiencia y prueba), "ugc_how_to" (tutorial con pasos y resultado visible), "ugc_unboxing_chaos" (apertura y primera prueba), "problem_solution" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase" (producto ejecutando una funci\xF3n real), "wearable_showcase" (prenda o accesorio modelado), "cinematic" (TV spot con receta cinematogr\xE1fica), "wild_card" (idea imposible: un truco visual que en la vida real no podr\xEDa pasar, y al cierre la invitaci\xF3n a comprar), "pixar_problem" (problema animado 3D), "pixar_sassy" (producto que habla), "storyteller" (narrador animado + met\xE1fora visual), "inner_journey" (la c\xE1mara entra al interior del problema), "object_soul" (un objeto cotidiano con alma silenciosa), "timeline" (el mismo encuadre a trav\xE9s de \xE9pocas). Si el usuario pide algo fuera de esta lista, p\xEDdele una opci\xF3n v\xE1lida.'),
|
|
20640
|
+
animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem", "pixar_sassy", "storyteller", "inner_journey", "object_soul" o "timeline") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
|
|
20460
20641
|
durationSeconds: z81.union([
|
|
20461
20642
|
z81.literal(15),
|
|
20462
20643
|
z81.literal(30)
|
|
@@ -20468,7 +20649,7 @@ var CreateProductTaskInput = z81.object({
|
|
|
20468
20649
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
20469
20650
|
videoResolution: VideoResolutionEnum.optional().describe('Opcional. Resoluci\xF3n del render. En la web se pregunta "\xBFResoluci\xF3n del video?". "480p" = excelente calidad y m\xE1s econ\xF3mico (RECOMENDADO, default si se omite); "720p" = m\xE1xima nitidez, entre 3% y 15% m\xE1s caro seg\xFAn formato y tier. Si el usuario no menciona resoluci\xF3n, OMITE este campo (el backend usa 480p).'),
|
|
20470
20651
|
videoAngleCount: z81.number().int().min(1).max(3).optional().describe("Cantidad de videos a renderizar: 1, 2 o 3. REQUERIDO cuando outputs incluye video (o se omite outputs, cuyo default incluye video); om\xEDtelo s\xF3lo cuando no se generar\xE1 video. Preg\xFAntalo incluso con aiDecidesAll=true porque cambia el costo."),
|
|
20471
|
-
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
20652
|
+
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "animated_storyteller" (narrador + met\xE1fora), "animated_inner_journey" (viaje al interior), "animated_object_soul" (objeto con alma), "animated_timeline" (misma c\xE1mara por \xE9pocas), "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
20472
20653
|
outputs: z81.array(z81.enum([
|
|
20473
20654
|
"landing",
|
|
20474
20655
|
"video",
|
|
@@ -20576,7 +20757,7 @@ var PendingActionPayload = z81.discriminatedUnion("kind", [
|
|
|
20576
20757
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
20577
20758
|
features: z81.array(z81.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
20578
20759
|
buyerPersona: z81.string().min(1).max(360).optional(),
|
|
20579
|
-
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n)
|
|
20760
|
+
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") funciona en ambos formatos: 15s Un solo clip y 30s Multiescena.'),
|
|
20580
20761
|
actor: z81.string().min(1).max(360).optional().describe("Nueva descripci\xF3n del presentador. Al enviarla sin actorId, se elimina autom\xE1ticamente cualquier actor guardado previo de esos \xE1ngulos."),
|
|
20581
20762
|
actorId: z81.string().max(120).nullable().optional(),
|
|
20582
20763
|
creativeDirection: z81.string().max(2e3).optional(),
|
|
@@ -20589,7 +20770,7 @@ var PendingActionPayload = z81.discriminatedUnion("kind", [
|
|
|
20589
20770
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
20590
20771
|
angle: z81.string().min(1).max(480).optional(),
|
|
20591
20772
|
buyerPersona: z81.string().min(1).max(360).optional(),
|
|
20592
|
-
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n)
|
|
20773
|
+
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n) funciona en ambos formatos \u2014 en Un solo clip abre sin producto y el producto entra por referencia en su beat. La familia storyteller ("animated_storyteller", "animated_inner_journey", "animated_object_soul", "animated_timeline") funciona en ambos formatos: 15s Un solo clip y 30s Multiescena.'),
|
|
20593
20774
|
actor: z81.string().min(1).max(360).optional(),
|
|
20594
20775
|
actorId: z81.string().max(120).nullable().optional(),
|
|
20595
20776
|
creativeDirection: z81.string().max(2e3).optional()
|
|
@@ -20869,6 +21050,10 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
20869
21050
|
const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
|
|
20870
21051
|
const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
|
|
20871
21052
|
assertVideoPresetDurationCompatibility(videoPreset, input.durationSeconds, input.videoStructure, input.videoQuality);
|
|
21053
|
+
assertAngleNarrativeDurationCompatibility(input.angleNarratives, input.durationSeconds, input.videoStructure);
|
|
21054
|
+
if (input.animationStyle !== void 0 && !animationStyleApplies(videoPreset, input.angleNarratives)) {
|
|
21055
|
+
throw new Error("animationStyle solo aplica a narrativas animadas.");
|
|
21056
|
+
}
|
|
20872
21057
|
if (selectedOutputs.includes("video")) {
|
|
20873
21058
|
assertSemanticVideoDurationCompatibility(input.videoStructure, input.videoQuality, input.durationSeconds);
|
|
20874
21059
|
}
|
|
@@ -20912,6 +21097,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
20912
21097
|
"options.productContext": input.productContext,
|
|
20913
21098
|
"options.productLabel": input.productLabel,
|
|
20914
21099
|
"options.videoPreset": videoPreset,
|
|
21100
|
+
"options.animationStyle": input.animationStyle,
|
|
20915
21101
|
"options.videoStyle": resolved?.videoStyle,
|
|
20916
21102
|
"options.narrativeStyle": resolved?.narrativeStyle,
|
|
20917
21103
|
"options.videoTier": wireTier,
|
|
@@ -21673,8 +21859,9 @@ var VideoCreativeSetup = z82.discriminatedUnion("mode", [
|
|
|
21673
21859
|
}).strict(),
|
|
21674
21860
|
z82.object({
|
|
21675
21861
|
mode: z82.literal("guided"),
|
|
21676
|
-
videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario.
|
|
21862
|
+
videoPreset: VideoPresetEnum.default("auto").describe('Narrativa opcional. Con estudio de mercado no la preguntes: se usa "auto" y el estudio define la estructura. Sin estudio conserva la elecci\xF3n del usuario. Todas las narrativas funcionan en Un solo clip y Multiescena.'),
|
|
21677
21863
|
buyerPersona: z82.string().trim().min(1).max(360),
|
|
21864
|
+
animationStyle: AnimationStyleEnum.optional().describe('Opcional. Estilo visual SOLO para presets animados ("pixar_problem", "pixar_sassy", "storyteller", "inner_journey", "object_soul" o "timeline") \u2014 la API lo rechaza con cualquier otro preset. Opciones: "pixar_3d" (default, look 3D de pel\xEDcula animada), "claymation" (plastilina stop-motion artesanal), "wes_anderson" (tableau sim\xE9trico pastel), "sci_fi" (futurista con HUDs y ne\xF3n), "realista" (fotorrealista, fiel al producto). Si el usuario pide un look animado sin nombrar el estilo, omite el campo.'),
|
|
21678
21865
|
presenter: VideoPresenter,
|
|
21679
21866
|
creativeDirection: z82.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
21680
21867
|
}).strict()
|
|
@@ -21693,7 +21880,7 @@ var VideoInput = z82.object({
|
|
|
21693
21880
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
21694
21881
|
durationSeconds: z82.number().int().min(4).max(30).default(15).describe("Opcional. Duraci\xF3n objetivo: Un solo clip Econ\xF3mico o Medio usa 15s; Un solo clip Pro usa 15s o 30s; Multiescena usa 15s o 30s totales. La combinaci\xF3n de formato y calidad determina la ruta y el costo."),
|
|
21695
21882
|
videoAngleCount: z82.number().int().min(1).max(3).describe("Cantidad de videos a renderizar: 1, 2 o 3. Es una decisi\xF3n de costo obligatoria: preg\xFAntala incluso cuando creativeSetup.mode=automatic."),
|
|
21696
|
-
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
21883
|
+
angleNarratives: PublicNarrativeStyleEnum.array().max(3).optional().describe('Opcional. Narrativa POR \xC1NGULO (posicional). Valores actuales: "review", "ugc_how_to", "ugc_unboxing_chaos", "problem_product_cta" (problema concreto, producto como soluci\xF3n y CTA), "product_showcase", "wearable_showcase", "cinematic", "wild_card", "animated_problem_pixar", "sassy_product_pixar", "animated_storyteller" (narrador + met\xE1fora), "animated_inner_journey" (viaje al interior), "animated_object_soul" (objeto con alma), "animated_timeline" (misma c\xE1mara por \xE9pocas), "market" (narrativa an\xE1lisis de mercado: adapta el video a los patrones ganadores estudiados de la competencia; requiere competitorScanEnabled: true). angleNarratives[i] fuerza la narrativa del \xE1ngulo i; las posiciones restantes las elige la IA. La lista no puede superar videoAngleCount.'),
|
|
21697
21884
|
creativeSetup: VideoCreativeSetup.describe("Configuraci\xF3n creativa obligatoria. En guided pregunta narrativa, p\xFAblico, presentador y direcci\xF3n antes de confirmar. Usa automatic s\xF3lo si el usuario deleg\xF3 todo expl\xEDcitamente."),
|
|
21698
21885
|
videoStructure: VideoStructureEnum.default("single_take").describe('Opcional. Formato: "single_take" = Un solo clip (generado completo; puede incluir cambios de plano) o "multi_scene" = Multiescena (varias tomas concatenadas). Default: single_take.'),
|
|
21699
21886
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
@@ -22014,6 +22201,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
22014
22201
|
const guidedSetup = input.creativeSetup.mode === "guided" ? input.creativeSetup : null;
|
|
22015
22202
|
const videoPreset = input.competitorScanEnabled === true ? "auto" : guidedSetup?.videoPreset ?? "auto";
|
|
22016
22203
|
assertVideoPresetDurationCompatibility(videoPreset, input.durationSeconds, input.videoStructure, input.videoQuality);
|
|
22204
|
+
assertAngleNarrativeDurationCompatibility(input.angleNarratives, input.durationSeconds, input.videoStructure);
|
|
22205
|
+
if (guidedSetup?.animationStyle !== void 0 && !animationStyleApplies(videoPreset, input.angleNarratives)) {
|
|
22206
|
+
throw new Error("animationStyle solo aplica a narrativas animadas.");
|
|
22207
|
+
}
|
|
22017
22208
|
const resolved = resolveVideoPreset(videoPreset);
|
|
22018
22209
|
const reviewPolicy = resolveConversationalReviewPolicy(input.creativeSetup.mode === "automatic");
|
|
22019
22210
|
const { videoResolution: _vr, creativeSetup: _creativeSetup, winnerReference: _winnerReference, ...rest } = input;
|
|
@@ -22031,6 +22222,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
22031
22222
|
if (guidedSetup.presenter.mode === "described") wirePayload.actorDescription = guidedSetup.presenter.description;
|
|
22032
22223
|
const direction = guidedSetup.creativeDirection;
|
|
22033
22224
|
wirePayload.creativeDirectionMode = direction ? "provided" : "ai_decides";
|
|
22225
|
+
if (guidedSetup.animationStyle !== void 0) wirePayload.animationStyle = guidedSetup.animationStyle;
|
|
22034
22226
|
if (direction) {
|
|
22035
22227
|
wirePayload.scriptNotes = [
|
|
22036
22228
|
input.scriptNotes?.trim(),
|
|
@@ -22579,7 +22771,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
22579
22771
|
}
|
|
22580
22772
|
});
|
|
22581
22773
|
server.registerTool("approve_video_script", {
|
|
22582
|
-
description: approveVideoScriptGuidance.summary + ' Tras llamarlo, el render arranca y consume cr\xE9ditos.\n\nREGLAS DURAS:\n1. INCLUYE EN scenes[] S\xD3LO las escenas que cambian. El backend mergea por `index` \u2014 las escenas no incluidas conservan su di\xE1logo original. scenes vac\xEDo es rechazado con 400, as\xED que si el usuario no quiere editar nada, manda AL MENOS UNA escena con su `dialogue` original (ser\xE1 un no-op sem\xE1ntico pero satisface el
|
|
22774
|
+
description: approveVideoScriptGuidance.summary + ' Tras llamarlo, el render arranca y consume cr\xE9ditos.\n\nREGLAS DURAS:\n1. INCLUYE EN scenes[] S\xD3LO las escenas que cambian. El backend mergea por `index` \u2014 las escenas no incluidas conservan su di\xE1logo original. scenes vac\xEDo es rechazado con 400, as\xED que si el usuario no quiere editar nada, manda AL MENOS UNA escena con su `dialogue` original (ser\xE1 un no-op sem\xE1ntico pero satisface el m\xEDnimo de 1 escena).\n2. Para cada entrada incluida cuyo `dialogue` difiera del original, el backend valida `minWords \u2264 words(dialogue) \u2264 maxWords` (los rangos vienen en get_video_script). Si te sales del rango, rechaza con 400 \u2014 NO recortes en silencio; p\xEDdele al usuario que ajuste. Excepci\xF3n: un `dialogue` vac\xEDo es legal s\xF3lo en escenas silenciosas por dise\xF1o (`silentAllowed` en get_video_script); en una escena hablada el backend rechaza el vac\xEDo con 400.\n3. Escenas con LLM-original ya fuera de rango: el backend NO valida el rango POR-ESCENA si no las incluyes (la regla #2 s\xF3lo aplica a escenas editadas).\n4. TOPE GLOBAL: adem\xE1s del rango por-escena, el backend rechaza con 400 ("El guion no cabe en el tiempo del video. Ac\xF3rtalo y vuelve a aprobar.") cuando el TOTAL de palabras de TODO el guion (incluidas las escenas que no editaste) supera el cupo de la voz \u2014 porque ese guion se pasar\xEDa del tope de duraci\xF3n al renderizar. Si lo ves, acorta las escenas m\xE1s largas (la suma de `maxWords` de get_video_script es el techo total) y reintenta; o usa regenerate_video_script. Este 400 es s\xEDncrono y NO consume render.\n5. NUNCA inventes ni reescribas el guion por tu cuenta. Aplica los cambios del usuario al pie de la letra dentro de los l\xEDmites de palabras.\n6. MULTI-ANGLE: pasa el mismo `angleKey` que usaste en get_video_script. Si lo omites, el backend resuelve a "angle_0" literal \u2014 puedes aprobar un \xE1ngulo equivocado.\n\nDevuelve { status }. status="approved" confirma la aprobaci\xF3n; otro valor significa que la pausa sigue activa.',
|
|
22583
22775
|
inputSchema: ApproveVideoScriptInput.shape,
|
|
22584
22776
|
annotations: CREATES_PAID
|
|
22585
22777
|
}, async (input) => {
|