@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/stdio.js
CHANGED
|
@@ -64,8 +64,20 @@ var NarrativeStyle = z.enum([
|
|
|
64
64
|
"ugc_skeptic_confession",
|
|
65
65
|
"ugc_demo_review",
|
|
66
66
|
"gap_replication",
|
|
67
|
-
"market"
|
|
67
|
+
"market",
|
|
68
|
+
"animated_storyteller",
|
|
69
|
+
"animated_inner_journey",
|
|
70
|
+
"animated_object_soul",
|
|
71
|
+
"animated_timeline"
|
|
72
|
+
]);
|
|
73
|
+
var AnimationStyleSchema = z.enum([
|
|
74
|
+
"pixar_3d",
|
|
75
|
+
"claymation",
|
|
76
|
+
"wes_anderson",
|
|
77
|
+
"sci_fi",
|
|
78
|
+
"realista"
|
|
68
79
|
]);
|
|
80
|
+
var ANIMATION_STYLE_VALUES = AnimationStyleSchema.options;
|
|
69
81
|
var VideoResolution = z.enum([
|
|
70
82
|
"480p",
|
|
71
83
|
"720p"
|
|
@@ -81,6 +93,10 @@ var VideoPreset = z.enum([
|
|
|
81
93
|
"wearable_showcase",
|
|
82
94
|
"pixar_problem",
|
|
83
95
|
"pixar_sassy",
|
|
96
|
+
"storyteller",
|
|
97
|
+
"inner_journey",
|
|
98
|
+
"object_soul",
|
|
99
|
+
"timeline",
|
|
84
100
|
"ugc_unboxing_chaos",
|
|
85
101
|
"ugc_curiosity_reveal",
|
|
86
102
|
"ugc_listicle_3",
|
|
@@ -3270,7 +3286,9 @@ var LandingProductSchema = z21.object({
|
|
|
3270
3286
|
whatsappNumber: z21.string().regex(/^\d{7,15}$/, 'digits only, 7\u201315 chars (e.g. "573001234567")').optional()
|
|
3271
3287
|
});
|
|
3272
3288
|
var CodeLandingProductSchema = LandingProductSchema.extend({
|
|
3273
|
-
price: z21.string().min(1).optional()
|
|
3289
|
+
price: z21.string().min(1).optional(),
|
|
3290
|
+
/** Keeps image-medium selection stable when a saved page is recomposed. */
|
|
3291
|
+
category: z21.string().min(1).optional()
|
|
3274
3292
|
});
|
|
3275
3293
|
var PAYMENT_METHOD_KEYS = [
|
|
3276
3294
|
"contraentrega",
|
|
@@ -4113,6 +4131,9 @@ var IngestOptions = z22.object({
|
|
|
4113
4131
|
videoTier: WritableVideoTier.default(DEFAULT_VIDEO_TIER),
|
|
4114
4132
|
narrativeStyle: NarrativeStyle.default("review"),
|
|
4115
4133
|
videoPreset: VideoPreset.optional(),
|
|
4134
|
+
/** Orthogonal visual style for animated narratives only. The API rejects it
|
|
4135
|
+
* on non-animated presets; absent → the pipeline resolves 'pixar_3d'. */
|
|
4136
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
4116
4137
|
multiAngleVideos: z22.boolean().default(false),
|
|
4117
4138
|
videoAngleCount: z22.number().int().min(1).max(3).optional(),
|
|
4118
4139
|
/** Per-angle narrative override (positional). angleNarratives[i] forces the
|
|
@@ -4309,6 +4330,10 @@ var VideoOptionsOverride = z22.object({
|
|
|
4309
4330
|
ugcFormat: VideoFormat.optional(),
|
|
4310
4331
|
videoStyle: VideoStyle.optional(),
|
|
4311
4332
|
narrativeStyle: NarrativeStyle.optional(),
|
|
4333
|
+
/** Animation-style pick for THIS angle. The approve/draft handlers persist
|
|
4334
|
+
* it on the angle's own row (Angle.animationStyle) while its effective
|
|
4335
|
+
* narrative is animated; switching to a non-animated narrative clears it. */
|
|
4336
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
4312
4337
|
videoResolution: VideoResolution.optional(),
|
|
4313
4338
|
voiceId: VoiceId.optional(),
|
|
4314
4339
|
/** Actor/character description (role + appearance + attitude). Drives voice and video character. */
|
|
@@ -5278,14 +5303,17 @@ var ApproveVideoScriptRequest = z27.object({
|
|
|
5278
5303
|
angleKey: z27.string().trim().min(1).max(120).optional(),
|
|
5279
5304
|
scenes: z27.array(z27.object({
|
|
5280
5305
|
index: z27.number().int().nonnegative(),
|
|
5281
|
-
|
|
5306
|
+
// Empty is admitted at the wire: only the service knows whether the
|
|
5307
|
+
// shot is a designed-silent beat (productOnly / winner-copy), so the
|
|
5308
|
+
// per-shot empty-line policy lives there — NOT here.
|
|
5309
|
+
dialogue: z27.string().trim().max(VIDEO_SCRIPT_APPROVAL_MAX_DIALOGUE_CHARS)
|
|
5282
5310
|
}).strict()).min(1).max(VIDEO_SCRIPT_APPROVAL_MAX_SCENES)
|
|
5283
5311
|
}).strict();
|
|
5284
5312
|
var ApproveVideoScriptResponse = z27.object({
|
|
5285
5313
|
status: ScriptReviewStatus
|
|
5286
5314
|
});
|
|
5287
5315
|
var RegenerateVideoScriptNarrativeRequest = z27.object({
|
|
5288
|
-
angleKey: z27.string().min(1),
|
|
5316
|
+
angleKey: z27.string().trim().min(1).max(120),
|
|
5289
5317
|
narrativeStyle: NarrativeStyle,
|
|
5290
5318
|
narrativeSelection: z27.enum([
|
|
5291
5319
|
"market",
|
|
@@ -5299,7 +5327,11 @@ var RegenerateVideoScriptNarrativeRequest = z27.object({
|
|
|
5299
5327
|
});
|
|
5300
5328
|
var RegenerateVideoScriptNarrativeResponse = z27.object({
|
|
5301
5329
|
/** 'not_ready' while Phase 1 re-runs; the client polls until 'ready'. */
|
|
5302
|
-
status: ScriptReviewStatus
|
|
5330
|
+
status: ScriptReviewStatus,
|
|
5331
|
+
/** The angle text the new script is written from — re-voiced into the new
|
|
5332
|
+
* narrative's speaker when that changed it. The review card shows it right
|
|
5333
|
+
* away so its next draft save cannot write the old voice back. */
|
|
5334
|
+
angle: z27.string().optional()
|
|
5303
5335
|
});
|
|
5304
5336
|
var RegenerateVideoRequest = z27.object({
|
|
5305
5337
|
angleKey: z27.string().min(1)
|
|
@@ -6325,7 +6357,11 @@ var AutoResolvedPresetSchema = z35.enum([
|
|
|
6325
6357
|
"wearable_showcase",
|
|
6326
6358
|
"pixar_problem",
|
|
6327
6359
|
"pixar_sassy",
|
|
6328
|
-
"metaphor_product"
|
|
6360
|
+
"metaphor_product",
|
|
6361
|
+
"storyteller",
|
|
6362
|
+
"inner_journey",
|
|
6363
|
+
"object_soul",
|
|
6364
|
+
"timeline"
|
|
6329
6365
|
]);
|
|
6330
6366
|
var SelectedOutputsSchema = z35.array(z35.enum([
|
|
6331
6367
|
"landing",
|
|
@@ -6418,6 +6454,9 @@ var TaskCreativeVariantResult = TaskCreativeVariantBaseResult.extend({
|
|
|
6418
6454
|
images: z35.array(LandingImageReadable).min(1).max(MAX_LANDING_IMAGES)
|
|
6419
6455
|
}).optional()
|
|
6420
6456
|
});
|
|
6457
|
+
var ResultAngle = Angle.extend({
|
|
6458
|
+
animationStyle: AnimationStyleSchema.optional()
|
|
6459
|
+
});
|
|
6421
6460
|
var MVPResult = z35.object({
|
|
6422
6461
|
taskId: z35.string().uuid(),
|
|
6423
6462
|
product: Product,
|
|
@@ -6429,7 +6468,7 @@ var MVPResult = z35.object({
|
|
|
6429
6468
|
// into a 500 on GET /v1/results/:taskId and hides EVERY deliverable of a
|
|
6430
6469
|
// task that already finished. Same failure shape as the variant landing cap
|
|
6431
6470
|
// below (alert 88badc8). The write path is what must stay at 3.
|
|
6432
|
-
angles: z35.array(
|
|
6471
|
+
angles: z35.array(ResultAngle),
|
|
6433
6472
|
topVideos: z35.array(AdVideo).max(20),
|
|
6434
6473
|
landing: z35.object({
|
|
6435
6474
|
// Allow legacy data (10 sections × 2 variants) and new data (7 sections × 2)
|
|
@@ -6461,6 +6500,10 @@ var MVPResult = z35.object({
|
|
|
6461
6500
|
// and by angles review banner.
|
|
6462
6501
|
autoResolvedPreset: AutoResolvedPresetSchema.optional(),
|
|
6463
6502
|
autoResolveReasoning: z35.string().optional(),
|
|
6503
|
+
/** Persisted animated-narrative visual style (Task.animationStyle). Absent on
|
|
6504
|
+
* non-animated tasks and rows predating the axis — readers resolve
|
|
6505
|
+
* 'pixar_3d' as the default. */
|
|
6506
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
6464
6507
|
partialVideoResult: PartialVideoResult.optional(),
|
|
6465
6508
|
/** Mixed images derived from MixTask rows linked to this task via sourceTaskId. */
|
|
6466
6509
|
mixedImages: z35.array(MixedImage).optional(),
|
|
@@ -6781,6 +6824,10 @@ var StatusResponse = z35.object({
|
|
|
6781
6824
|
videoRouteId: VideoRouteId.optional(),
|
|
6782
6825
|
videoResolution: VideoResolution.optional(),
|
|
6783
6826
|
narrativeStyle: NarrativeStyle.optional(),
|
|
6827
|
+
/** Persisted animated-narrative visual style (Task.animationStyle). Absent on
|
|
6828
|
+
* non-animated tasks and rows predating the axis — readers resolve
|
|
6829
|
+
* 'pixar_3d' as the default. */
|
|
6830
|
+
animationStyle: AnimationStyleSchema.optional(),
|
|
6784
6831
|
videoAngleCount: z35.number().int().min(1).max(3).optional(),
|
|
6785
6832
|
/** Historical authorization flag kept for clients resolving legacy reviews. */
|
|
6786
6833
|
multiAngleVideos: z35.boolean().optional(),
|
|
@@ -8667,13 +8714,16 @@ var DEFAULT_PRICING = {
|
|
|
8667
8714
|
ourCostCents: 0.07,
|
|
8668
8715
|
userPriceCents: 0.14
|
|
8669
8716
|
},
|
|
8717
|
+
// Both rewrites: RE-DERIVED 2026-09-28 from 14d of prod BillingEntry.
|
|
8718
|
+
// final-simplify n=123 mean 1.26¢ / p95 1.98¢ user; targeted-retry n=439 mean 2.09¢ /
|
|
8719
|
+
// p95 3.37¢ user. The old 0.8¢ (a Flash-era guess) under-quoted both 2.5-4x.
|
|
8670
8720
|
"openrouter:video-final-simplify-rewrite": {
|
|
8671
|
-
ourCostCents:
|
|
8672
|
-
userPriceCents:
|
|
8721
|
+
ourCostCents: 1,
|
|
8722
|
+
userPriceCents: 2
|
|
8673
8723
|
},
|
|
8674
8724
|
"openrouter:video-targeted-retry-rewrite": {
|
|
8675
|
-
ourCostCents:
|
|
8676
|
-
userPriceCents:
|
|
8725
|
+
ourCostCents: 1.7,
|
|
8726
|
+
userPriceCents: 3.4
|
|
8677
8727
|
},
|
|
8678
8728
|
// For helper-recorded entries (`callOpenRouter`), `ourCostCents` here is
|
|
8679
8729
|
// only used when `usage.cost` is missing from the provider response —
|
|
@@ -9735,11 +9785,15 @@ var DEFAULT_PRICING = {
|
|
|
9735
9785
|
// Video QA — combined describe+judge pass. The DETECTOR runs on gemini-3.8-flash at
|
|
9736
9786
|
// reasoning.effort=high (recall-critical: it gates a $2-4 re-render). Real billing
|
|
9737
9787
|
// uses OpenRouter's per-call usage.cost (×2), so this value is ONLY the estimator
|
|
9738
|
-
// basis + the rare fallback when usage.cost is missing
|
|
9739
|
-
//
|
|
9788
|
+
// basis + the rare fallback when usage.cost is missing.
|
|
9789
|
+
// RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9790
|
+
// n=2073, mean 3.57¢ / p95 8.95¢ / p99 12.04¢ / max 13.50¢ user per call.
|
|
9791
|
+
// 12¢ sits at the p99 and still covers DETECTOR_MAX_CALLS (3) × the mean (10.71¢) —
|
|
9792
|
+
// the invariant pinned in cost-estimator.spec.test.ts. The former 20¢ was sized to a
|
|
9793
|
+
// Pro+high call that no longer runs and inflated every QA pass of the credit gate.
|
|
9740
9794
|
"openrouter:video-qa-describe-judge": {
|
|
9741
|
-
ourCostCents:
|
|
9742
|
-
userPriceCents:
|
|
9795
|
+
ourCostCents: 6,
|
|
9796
|
+
userPriceCents: 12
|
|
9743
9797
|
},
|
|
9744
9798
|
// Video QA — hand scanner reinforcement (Gemini 3.7 Flash, dense frames around spike)
|
|
9745
9799
|
"openrouter:video-hand-reinforcement": {
|
|
@@ -9808,13 +9862,16 @@ var DEFAULT_PRICING = {
|
|
|
9808
9862
|
userPriceCents: 0.22
|
|
9809
9863
|
},
|
|
9810
9864
|
// Clip Judge — text-only comparison of QA results between original and retry clips
|
|
9811
|
-
// (google/gemini-3.8-flash, text-only).
|
|
9865
|
+
// (google/gemini-3.8-flash, text-only). RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9866
|
+
// n=92, mean 0.34¢ / p95 0.54¢ user
|
|
9867
|
+
// (the old 0.12¢ assumed ~$0.0006 and under-quoted 4.5x).
|
|
9812
9868
|
"openrouter:clip-judge-text": {
|
|
9813
|
-
ourCostCents: 0.
|
|
9814
|
-
userPriceCents: 0.
|
|
9869
|
+
ourCostCents: 0.28,
|
|
9870
|
+
userPriceCents: 0.56
|
|
9815
9871
|
},
|
|
9816
9872
|
// Clip Judge — vision comparison of two video clips (google/gemini-3.8-flash, 2 videos)
|
|
9817
|
-
// Our cost: ~$0.01 => 1.0 cents; 2x markup.
|
|
9873
|
+
// Our cost: ~$0.01 => 1.0 cents; 2x markup. Checked 2026-09-28 (n=346): mean 1.38¢ /
|
|
9874
|
+
// p95 1.90¢ user — already covered, unchanged.
|
|
9818
9875
|
"openrouter:clip-judge-vision": {
|
|
9819
9876
|
ourCostCents: 1,
|
|
9820
9877
|
userPriceCents: 2
|
|
@@ -9831,10 +9888,13 @@ var DEFAULT_PRICING = {
|
|
|
9831
9888
|
ourCostCents: 0.89,
|
|
9832
9889
|
userPriceCents: 1.78
|
|
9833
9890
|
},
|
|
9834
|
-
// Video QA — product integrity scanner (
|
|
9891
|
+
// Video QA — product integrity scanner (gemini-3.8-flash, 5 frames + reference).
|
|
9892
|
+
// RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9893
|
+
// n=1828, mean 2.91¢ / p95 5.07¢ / max 11.50¢ user per call. The old 0.3¢
|
|
9894
|
+
// (a 3.7-Flash-era guess) under-quoted it ~10x on every QA pass.
|
|
9835
9895
|
"openrouter:video-product-integrity": {
|
|
9836
|
-
ourCostCents:
|
|
9837
|
-
userPriceCents:
|
|
9896
|
+
ourCostCents: 2.6,
|
|
9897
|
+
userPriceCents: 5.2
|
|
9838
9898
|
},
|
|
9839
9899
|
// Video QA — anatomy. THREE keys, and they do NOT share a unit. Getting this wrong
|
|
9840
9900
|
// over-charges by ~42x, which is exactly what a first pass at the 2026-07-30 change did.
|
|
@@ -9872,11 +9932,35 @@ var DEFAULT_PRICING = {
|
|
|
9872
9932
|
userPriceCents: 0.4
|
|
9873
9933
|
},
|
|
9874
9934
|
// (c) Tracing confirmation of a frames-only finding: 3 stills + the full downscaled video,
|
|
9875
|
-
// one call.
|
|
9876
|
-
//
|
|
9935
|
+
// one call. RE-DERIVED 2026-09-28 (14d prod BillingEntry):
|
|
9936
|
+
// n=46, mean 2.67¢ / p95 4.48¢ / max 5.43¢ user — the
|
|
9937
|
+
// former 3.0¢ (from a 14-call spike, 0.59¢ our mean) sat below the prod p95.
|
|
9877
9938
|
"openrouter:video-qa-anatomy-tracing-confirm": {
|
|
9878
|
-
ourCostCents:
|
|
9879
|
-
userPriceCents:
|
|
9939
|
+
ourCostCents: 2.25,
|
|
9940
|
+
userPriceCents: 4.5
|
|
9941
|
+
},
|
|
9942
|
+
// (d) DENSE anatomy detector (the default anatomy detector since 2026-09-26;
|
|
9943
|
+
// QA_ANATOMY_DETECTOR=frame_judge reverts): gemini-3.1-pro judges every extracted
|
|
9944
|
+
// frame at 1 fps, 5 frames per call, each call billing its frame count — the rate is
|
|
9945
|
+
// PER FRAME like (b) and scales with QA_DENSE_DETECTOR_MAX_FRAMES. Measured on the
|
|
9946
|
+
// owner corpus with the shipped config (reasoning=low, grouped): $1.062 / 296 frames
|
|
9947
|
+
// ≈ 0.36c/frame; 0.5c keeps ~40% headroom. The old 3.0c fallback was the 2026-09-22
|
|
9948
|
+
// one-still-per-call spike at default reasoning (~1.95c/frame) and would have quoted
|
|
9949
|
+
// QA ~10x its cost. Re-derive from 30d BillingEntry once live.
|
|
9950
|
+
"openrouter:video-qa-anatomy-dense-detector": {
|
|
9951
|
+
ourCostCents: 0.5,
|
|
9952
|
+
userPriceCents: 1
|
|
9953
|
+
},
|
|
9954
|
+
// (e) Dense-mode tracing confirmation: the SAME confirmer call as (c) but routed
|
|
9955
|
+
// to gemini-3.1-pro — flash measured 3/11 recall confirming dense stills, so
|
|
9956
|
+
// dense findings never confirm on the gate model. PER CALL.
|
|
9957
|
+
// Spike measured $2.22/80 ≈ 2.8c/call; the 2026-09-26 A/B measured 2.6c/flag.
|
|
9958
|
+
// 3.0c keeps it above both. (The former 5.0c/10.0c, times the old 4-confirmation cap,
|
|
9959
|
+
// inflated the credit gate's `max` by up to ~12,600 credits on a 30 s multi-scene.)
|
|
9960
|
+
// Re-derive from 30d BillingEntry once live.
|
|
9961
|
+
"openrouter:video-qa-anatomy-dense-confirm": {
|
|
9962
|
+
ourCostCents: 3,
|
|
9963
|
+
userPriceCents: 6
|
|
9880
9964
|
},
|
|
9881
9965
|
// Physics confirmation — skeptical second opinion on D+J floating-object flags
|
|
9882
9966
|
// (Gemini 3.7 Flash, ~3 frames per flagged moment, 1 call). Aligned with other vision-QA keys.
|
|
@@ -10266,6 +10350,14 @@ var DEFAULT_PRICING = {
|
|
|
10266
10350
|
ourCostCents: 3,
|
|
10267
10351
|
userPriceCents: 6
|
|
10268
10352
|
},
|
|
10353
|
+
// Unit = one storyteller brief (insight, figure, metaphor, money shot): ONE text call per
|
|
10354
|
+
// storyteller-family angle before its plan is authored (`rapid-storyteller-brief`, judge-text
|
|
10355
|
+
// role). Billed since the family shipped but quoted nowhere until 2026-09-25. Priced by ANALOGY
|
|
10356
|
+
// with `rapid-grok-shot-action` (one batched text call of similar size), not measured yet.
|
|
10357
|
+
"openrouter:rapid-storyteller-brief": {
|
|
10358
|
+
ourCostCents: 3,
|
|
10359
|
+
userPriceCents: 6
|
|
10360
|
+
},
|
|
10269
10361
|
// Unit = one frame inventory: a single-image vision pass over ONE rendered panel, listing which
|
|
10270
10362
|
// hands are visible and what each holds, so the shot-action flatten can author against the frame
|
|
10271
10363
|
// the clip animates from instead of against the text the panel was asked to be. PER SHOT, not
|
|
@@ -13556,25 +13648,37 @@ function whatsappFieldAuthority(field, source) {
|
|
|
13556
13648
|
}
|
|
13557
13649
|
__name(whatsappFieldAuthority, "whatsappFieldAuthority");
|
|
13558
13650
|
var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
13559
|
-
defineCapability(
|
|
13651
|
+
defineCapability(
|
|
13652
|
+
"approve_video_script",
|
|
13653
|
+
// 2026-09-29: dialogue admits "" at the wire — silent-allowed shots
|
|
13654
|
+
// (productOnly / gap_replication) are legal, the API decides per-shot.
|
|
13655
|
+
// Recomputed over the Fase-4 shared ApproveVideoScriptSceneEdit.
|
|
13656
|
+
"fdd641922f73907881ee09b62a006e0af1b277cab3d990ebc8c151c96b715693",
|
|
13560
13657
|
"credit_consuming",
|
|
13561
|
-
"
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
"
|
|
13565
|
-
]
|
|
13566
|
-
|
|
13567
|
-
"
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
"
|
|
13571
|
-
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13658
|
+
"creative",
|
|
13659
|
+
[
|
|
13660
|
+
"credit_consuming",
|
|
13661
|
+
"state_change"
|
|
13662
|
+
],
|
|
13663
|
+
[
|
|
13664
|
+
slot("task", true, [
|
|
13665
|
+
"taskId"
|
|
13666
|
+
]),
|
|
13667
|
+
slot("angle", false, [
|
|
13668
|
+
"angleKey"
|
|
13669
|
+
]),
|
|
13670
|
+
slot("script_scenes", true, [
|
|
13671
|
+
"scenes"
|
|
13672
|
+
])
|
|
13673
|
+
],
|
|
13674
|
+
[
|
|
13675
|
+
"task",
|
|
13676
|
+
"video_script"
|
|
13677
|
+
],
|
|
13678
|
+
[
|
|
13679
|
+
"task"
|
|
13680
|
+
]
|
|
13681
|
+
),
|
|
13578
13682
|
defineCapability("check_meta_media_upload", "62b1af1d796d9466f8926afc5e6d18c4ddeccd5b0269ca7b21c2f6ebcfd2a945", "none", "read_only", [
|
|
13579
13683
|
"read"
|
|
13580
13684
|
], [
|
|
@@ -13673,54 +13777,65 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13673
13777
|
], [
|
|
13674
13778
|
"product_costing"
|
|
13675
13779
|
]),
|
|
13676
|
-
defineCapability(
|
|
13780
|
+
defineCapability(
|
|
13781
|
+
"create_creative_variant",
|
|
13782
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
13783
|
+
"db6d98e9e07d57dd1a78d9b73cdbfdaa7ee7a6ae4dff30d1bd2b3edf3225cd0d",
|
|
13677
13784
|
"credit_consuming",
|
|
13678
|
-
"
|
|
13679
|
-
|
|
13680
|
-
|
|
13681
|
-
"
|
|
13682
|
-
]
|
|
13683
|
-
|
|
13684
|
-
"
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
"
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
"
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
"
|
|
13694
|
-
|
|
13695
|
-
"
|
|
13696
|
-
"
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
"
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13785
|
+
"creative",
|
|
13786
|
+
[
|
|
13787
|
+
"credit_consuming",
|
|
13788
|
+
"state_change"
|
|
13789
|
+
],
|
|
13790
|
+
[
|
|
13791
|
+
slot("source_task", true, [
|
|
13792
|
+
"sourceTaskId"
|
|
13793
|
+
]),
|
|
13794
|
+
slot("creative_kind", true, [
|
|
13795
|
+
"kind"
|
|
13796
|
+
]),
|
|
13797
|
+
slot("confirmation", true, [
|
|
13798
|
+
"confirm"
|
|
13799
|
+
], [], "confirmation"),
|
|
13800
|
+
slot("idempotency", true, [
|
|
13801
|
+
"clientRequestId"
|
|
13802
|
+
], void 0, "server"),
|
|
13803
|
+
slot("creative_brief", false, [
|
|
13804
|
+
"angle",
|
|
13805
|
+
"buyerPersona",
|
|
13806
|
+
"scriptNotes",
|
|
13807
|
+
"creativeDirection"
|
|
13808
|
+
]),
|
|
13809
|
+
slot("render_options", false, [
|
|
13810
|
+
"videoPreset",
|
|
13811
|
+
"videoResolution",
|
|
13812
|
+
"generateAiMusic",
|
|
13813
|
+
"nVariants",
|
|
13814
|
+
"imageStyle",
|
|
13815
|
+
"creativeArchetype",
|
|
13816
|
+
"visualTreatment",
|
|
13817
|
+
"aspectRatio",
|
|
13818
|
+
"styleMix",
|
|
13819
|
+
"sectionKey",
|
|
13820
|
+
"instructions"
|
|
13821
|
+
])
|
|
13822
|
+
],
|
|
13823
|
+
[
|
|
13824
|
+
"task",
|
|
13825
|
+
"creative"
|
|
13826
|
+
],
|
|
13827
|
+
[
|
|
13828
|
+
"creative_variant"
|
|
13829
|
+
]
|
|
13830
|
+
),
|
|
13717
13831
|
defineCapability(
|
|
13718
13832
|
"create_product_task",
|
|
13719
13833
|
// MCP 8.4.0 (Fase 4, Tarea 3, .agent/plans/2026-09-26-refactor-fase4-detallado.md):
|
|
13720
13834
|
// outputs accepts 1 value, actorId max 120, landingStrategy optional (no
|
|
13721
13835
|
// default). Recomputed from the real tools/list digest printer.
|
|
13722
13836
|
// + market study opt-in copy (#2005, competitorScanEnabled description).
|
|
13723
|
-
|
|
13837
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
13838
|
+
"46b308923121dac1023b55f68b61dfbf4e89f682bdd48b04d4d0f8a3667f8999",
|
|
13724
13839
|
"credit_consuming",
|
|
13725
13840
|
"creative",
|
|
13726
13841
|
[
|
|
@@ -13779,6 +13894,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13779
13894
|
"videoResolution",
|
|
13780
13895
|
"videoAngleCount",
|
|
13781
13896
|
"angleNarratives",
|
|
13897
|
+
"animationStyle",
|
|
13782
13898
|
"competitorScanEnabled",
|
|
13783
13899
|
"replicateWinnerWhenFound"
|
|
13784
13900
|
], [
|
|
@@ -13790,6 +13906,8 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13790
13906
|
"videoResolution",
|
|
13791
13907
|
"multiAngleVideos",
|
|
13792
13908
|
"angleNarratives",
|
|
13909
|
+
// MCP-only for now: the WhatsApp contract schema does not expose the
|
|
13910
|
+
// animation-style axis yet (Phase 1 ships it on web + MCP).
|
|
13793
13911
|
"competitorScanEnabled",
|
|
13794
13912
|
"competitorCommercialStudyRequested",
|
|
13795
13913
|
"replicateWinnerWhenFound"
|
|
@@ -13888,7 +14006,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
13888
14006
|
], [
|
|
13889
14007
|
"task_draft"
|
|
13890
14008
|
]),
|
|
13891
|
-
defineCapability("estimate_creative_variant", "
|
|
14009
|
+
defineCapability("estimate_creative_variant", "055a92336bfb773c14e3f7018368b4490404ebcb3e607f78d5e0d5c0e78254b8", "none", "read_only", [
|
|
13892
14010
|
"read"
|
|
13893
14011
|
], [
|
|
13894
14012
|
slot("source_task", true, [
|
|
@@ -14217,112 +14335,127 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14217
14335
|
fieldCompletion: "all"
|
|
14218
14336
|
}
|
|
14219
14337
|
]),
|
|
14220
|
-
defineCapability(
|
|
14338
|
+
defineCapability(
|
|
14339
|
+
"generate_video_creative",
|
|
14340
|
+
// MCP 8.6.0: + storyteller narrative family and animationStyle axis.
|
|
14341
|
+
"5545b24de7b344c9184cfe087a39b766490526a432d8b288c02c2e9a20529c3d",
|
|
14221
14342
|
"credit_consuming",
|
|
14222
|
-
"state_change"
|
|
14223
|
-
], [
|
|
14224
|
-
slot("product_reference", true, [
|
|
14225
|
-
"images",
|
|
14226
|
-
"winnerReference"
|
|
14227
|
-
], [
|
|
14228
|
-
"imageMessageIds",
|
|
14229
|
-
"imageAssetIds",
|
|
14230
|
-
"projectId",
|
|
14231
|
-
"productUrl"
|
|
14232
|
-
]),
|
|
14233
|
-
slot("product_identity", true, [
|
|
14234
|
-
"title"
|
|
14235
|
-
]),
|
|
14236
|
-
// Optional in the canonical API because the shared generation pipeline
|
|
14237
|
-
// owns delegated angles. WhatsApp still asks through conversationInputs.
|
|
14238
|
-
slot("creative_angle", false, [
|
|
14239
|
-
"primaryAngle"
|
|
14240
|
-
]),
|
|
14241
|
-
slot("locale", true, [
|
|
14242
|
-
"language",
|
|
14243
|
-
"country"
|
|
14244
|
-
]),
|
|
14245
|
-
slot("render_options", true, [
|
|
14246
|
-
"angleNarratives",
|
|
14247
|
-
"aspectRatio",
|
|
14248
|
-
"durationSeconds",
|
|
14249
|
-
"videoAngleCount",
|
|
14250
|
-
"creativeSetup",
|
|
14251
|
-
"videoStructure",
|
|
14252
|
-
"videoQuality",
|
|
14253
|
-
"videoResolution",
|
|
14254
|
-
"features",
|
|
14255
|
-
"cta",
|
|
14256
|
-
"scriptNotes",
|
|
14257
|
-
"competitorScanEnabled",
|
|
14258
|
-
"replicateWinnerWhenFound"
|
|
14259
|
-
], [
|
|
14260
|
-
"aspectRatio",
|
|
14261
|
-
"durationSeconds",
|
|
14262
|
-
"videoPreset",
|
|
14263
|
-
"videoStructure",
|
|
14264
|
-
"videoQuality",
|
|
14265
|
-
"videoResolution",
|
|
14266
|
-
"features",
|
|
14267
|
-
"cta",
|
|
14268
|
-
"scriptNotes",
|
|
14269
|
-
"pauseForVideoScriptReview",
|
|
14270
|
-
"pauseForAngleReview",
|
|
14271
|
-
"competitorScanEnabled",
|
|
14272
|
-
"competitorCommercialStudyRequested",
|
|
14273
|
-
"replicateWinnerWhenFound"
|
|
14274
|
-
]),
|
|
14275
|
-
slot("commercial_offer", false, [
|
|
14276
|
-
"price",
|
|
14277
|
-
"offer"
|
|
14278
|
-
]),
|
|
14279
|
-
slot("product_context", false, [
|
|
14280
|
-
"productContext",
|
|
14281
|
-
"productLabel"
|
|
14282
|
-
], []),
|
|
14283
|
-
slot("brand_direction", false, [
|
|
14284
|
-
"brandId"
|
|
14285
|
-
]),
|
|
14286
|
-
// Casting pin. MCP-only for now: the WhatsApp generate_video_creative request
|
|
14287
|
-
// schema is .strict() and does not carry it yet (follow-up), hence the explicit [].
|
|
14288
|
-
slot("actor", false, [
|
|
14289
|
-
"creativeGender"
|
|
14290
|
-
], [])
|
|
14291
|
-
], [
|
|
14292
|
-
"product_reference"
|
|
14293
|
-
], [
|
|
14294
|
-
"task",
|
|
14295
14343
|
"creative",
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
|
|
14310
|
-
|
|
14311
|
-
|
|
14312
|
-
|
|
14313
|
-
|
|
14314
|
-
|
|
14315
|
-
|
|
14344
|
+
[
|
|
14345
|
+
"credit_consuming",
|
|
14346
|
+
"state_change"
|
|
14347
|
+
],
|
|
14348
|
+
[
|
|
14349
|
+
slot("product_reference", true, [
|
|
14350
|
+
"images",
|
|
14351
|
+
"winnerReference"
|
|
14352
|
+
], [
|
|
14353
|
+
"imageMessageIds",
|
|
14354
|
+
"imageAssetIds",
|
|
14355
|
+
"projectId",
|
|
14356
|
+
"productUrl"
|
|
14357
|
+
]),
|
|
14358
|
+
slot("product_identity", true, [
|
|
14359
|
+
"title"
|
|
14360
|
+
]),
|
|
14361
|
+
// Optional in the canonical API because the shared generation pipeline
|
|
14362
|
+
// owns delegated angles. WhatsApp still asks through conversationInputs.
|
|
14363
|
+
slot("creative_angle", false, [
|
|
14316
14364
|
"primaryAngle"
|
|
14317
|
-
]
|
|
14318
|
-
|
|
14319
|
-
|
|
14320
|
-
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14365
|
+
]),
|
|
14366
|
+
slot("locale", true, [
|
|
14367
|
+
"language",
|
|
14368
|
+
"country"
|
|
14369
|
+
]),
|
|
14370
|
+
slot("render_options", true, [
|
|
14371
|
+
"angleNarratives",
|
|
14372
|
+
"aspectRatio",
|
|
14373
|
+
"durationSeconds",
|
|
14374
|
+
"videoAngleCount",
|
|
14375
|
+
// animationStyle rides inside creativeSetup.guided on this tool, so
|
|
14376
|
+
// it is not a top-level schema field here (it is on
|
|
14377
|
+
// create_product_task).
|
|
14378
|
+
"creativeSetup",
|
|
14379
|
+
"videoStructure",
|
|
14380
|
+
"videoQuality",
|
|
14381
|
+
"videoResolution",
|
|
14382
|
+
"features",
|
|
14383
|
+
"cta",
|
|
14384
|
+
"scriptNotes",
|
|
14385
|
+
"competitorScanEnabled",
|
|
14386
|
+
"replicateWinnerWhenFound"
|
|
14387
|
+
], [
|
|
14388
|
+
"aspectRatio",
|
|
14389
|
+
"durationSeconds",
|
|
14390
|
+
"videoPreset",
|
|
14391
|
+
"videoStructure",
|
|
14392
|
+
"videoQuality",
|
|
14393
|
+
"videoResolution",
|
|
14394
|
+
"features",
|
|
14395
|
+
"cta",
|
|
14396
|
+
"scriptNotes",
|
|
14397
|
+
"pauseForVideoScriptReview",
|
|
14398
|
+
"pauseForAngleReview",
|
|
14399
|
+
"competitorScanEnabled",
|
|
14400
|
+
"competitorCommercialStudyRequested",
|
|
14401
|
+
"replicateWinnerWhenFound"
|
|
14402
|
+
]),
|
|
14403
|
+
slot("commercial_offer", false, [
|
|
14404
|
+
"price",
|
|
14405
|
+
"offer"
|
|
14406
|
+
]),
|
|
14407
|
+
slot("product_context", false, [
|
|
14408
|
+
"productContext",
|
|
14409
|
+
"productLabel"
|
|
14410
|
+
], []),
|
|
14411
|
+
slot("brand_direction", false, [
|
|
14412
|
+
"brandId"
|
|
14413
|
+
]),
|
|
14414
|
+
// Casting pin. MCP-only for now: the WhatsApp generate_video_creative request
|
|
14415
|
+
// schema is .strict() and does not carry it yet (follow-up), hence the explicit [].
|
|
14416
|
+
slot("actor", false, [
|
|
14417
|
+
"creativeGender"
|
|
14418
|
+
], [])
|
|
14419
|
+
],
|
|
14420
|
+
[
|
|
14421
|
+
"product_reference"
|
|
14422
|
+
],
|
|
14423
|
+
[
|
|
14424
|
+
"task",
|
|
14425
|
+
"creative",
|
|
14426
|
+
"video"
|
|
14427
|
+
],
|
|
14428
|
+
SHARED_CHANNEL_EXPOSURE,
|
|
14429
|
+
[
|
|
14430
|
+
{
|
|
14431
|
+
slot: "product_reference",
|
|
14432
|
+
askBeforePaidExecution: true,
|
|
14433
|
+
explicitOmissionAllowed: false,
|
|
14434
|
+
fieldCompletion: "any"
|
|
14435
|
+
},
|
|
14436
|
+
{
|
|
14437
|
+
slot: "locale",
|
|
14438
|
+
askBeforePaidExecution: true,
|
|
14439
|
+
explicitOmissionAllowed: false,
|
|
14440
|
+
fieldCompletion: "all"
|
|
14441
|
+
},
|
|
14442
|
+
{
|
|
14443
|
+
slot: "creative_angle",
|
|
14444
|
+
askBeforePaidExecution: true,
|
|
14445
|
+
explicitOmissionAllowed: true,
|
|
14446
|
+
fieldCompletion: "any",
|
|
14447
|
+
completionFields: [
|
|
14448
|
+
"primaryAngle"
|
|
14449
|
+
]
|
|
14450
|
+
},
|
|
14451
|
+
{
|
|
14452
|
+
slot: "commercial_offer",
|
|
14453
|
+
askBeforePaidExecution: true,
|
|
14454
|
+
explicitOmissionAllowed: true,
|
|
14455
|
+
fieldCompletion: "all"
|
|
14456
|
+
}
|
|
14457
|
+
]
|
|
14458
|
+
),
|
|
14326
14459
|
defineCapability("get_meta_campaign_status", "92077241cf4e9d14edefca410e85715cc383b1433081c3461c925f8fc3d6e8ab", "none", "read_only", [
|
|
14327
14460
|
"read"
|
|
14328
14461
|
], [
|
|
@@ -14630,7 +14763,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14630
14763
|
], [
|
|
14631
14764
|
"product_media"
|
|
14632
14765
|
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
14633
|
-
defineCapability("regenerate_video_script", "
|
|
14766
|
+
defineCapability("regenerate_video_script", "198903f5d89b245daedde4e08020a6d536f2ea354f5924176253b71c84241859", "credit_consuming", "creative", [
|
|
14634
14767
|
"credit_consuming",
|
|
14635
14768
|
"state_change"
|
|
14636
14769
|
], [
|
|
@@ -14693,7 +14826,7 @@ var PRODUCTMAKER_CAPABILITY_REGISTRY = deepFreeze([
|
|
|
14693
14826
|
], [
|
|
14694
14827
|
"media_upload_session"
|
|
14695
14828
|
], MCP_ONLY_CHANNEL_EXPOSURE),
|
|
14696
|
-
defineCapability("resolve_pending_action", "
|
|
14829
|
+
defineCapability("resolve_pending_action", "7d76b53ebce3265a751836e61f6959debd98bd8159291ef73437e1b7a0824333", "credit_consuming", "creative", [
|
|
14697
14830
|
"credit_consuming",
|
|
14698
14831
|
"state_change"
|
|
14699
14832
|
], [
|
|
@@ -15100,6 +15233,10 @@ var MCP_ANGLE_NARRATIVE_STYLES = [
|
|
|
15100
15233
|
"wild_card",
|
|
15101
15234
|
"animated_problem_pixar",
|
|
15102
15235
|
"sassy_product_pixar",
|
|
15236
|
+
"animated_storyteller",
|
|
15237
|
+
"animated_inner_journey",
|
|
15238
|
+
"animated_object_soul",
|
|
15239
|
+
"animated_timeline",
|
|
15103
15240
|
"market"
|
|
15104
15241
|
];
|
|
15105
15242
|
var McpAngleNarrativeStyleSchema = NarrativeStyle.extract(MCP_ANGLE_NARRATIVE_STYLES);
|
|
@@ -16127,9 +16264,7 @@ var FlightRecorderResponseSchema = z75.object({
|
|
|
16127
16264
|
import { z as z76 } from "zod";
|
|
16128
16265
|
var ApproveVideoScriptSceneEdit = z76.object({
|
|
16129
16266
|
index: z76.number().int().nonnegative().describe("\xCDndice de la escena (0-based, mismo que devuelve get_video_script)."),
|
|
16130
|
-
dialogue: z76.string().
|
|
16131
|
-
message: "dialogue no puede ser s\xF3lo espacios"
|
|
16132
|
-
}).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.")
|
|
16267
|
+
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.')
|
|
16133
16268
|
}).strict();
|
|
16134
16269
|
var ApproveVideoScriptCapabilityRequest = z76.object({
|
|
16135
16270
|
taskId: z76.string().min(1).describe("ID de la tarea."),
|
|
@@ -16389,7 +16524,7 @@ var ApiClient = class {
|
|
|
16389
16524
|
};
|
|
16390
16525
|
|
|
16391
16526
|
// src/index.ts
|
|
16392
|
-
var MCP_VERSION = "8.
|
|
16527
|
+
var MCP_VERSION = "8.6.0";
|
|
16393
16528
|
|
|
16394
16529
|
// src/meta-upload-app.ts
|
|
16395
16530
|
import { readFileSync } from "fs";
|
|
@@ -17038,7 +17173,11 @@ var VideoPresetEnum = VideoPreset.extract([
|
|
|
17038
17173
|
"cinematic",
|
|
17039
17174
|
"wild_card",
|
|
17040
17175
|
"pixar_problem",
|
|
17041
|
-
"pixar_sassy"
|
|
17176
|
+
"pixar_sassy",
|
|
17177
|
+
"storyteller",
|
|
17178
|
+
"inner_journey",
|
|
17179
|
+
"object_soul",
|
|
17180
|
+
"timeline"
|
|
17042
17181
|
]);
|
|
17043
17182
|
var VideoStructureEnum = VideoStructure;
|
|
17044
17183
|
var VideoQualityEnum = VideoQuality;
|
|
@@ -17085,6 +17224,22 @@ var VIDEO_PRESET_RESOLUTION = {
|
|
|
17085
17224
|
wild_card: {
|
|
17086
17225
|
videoStyle: "product_only",
|
|
17087
17226
|
narrativeStyle: "wild_card"
|
|
17227
|
+
},
|
|
17228
|
+
storyteller: {
|
|
17229
|
+
videoStyle: "ai_dynamic",
|
|
17230
|
+
narrativeStyle: "animated_storyteller"
|
|
17231
|
+
},
|
|
17232
|
+
inner_journey: {
|
|
17233
|
+
videoStyle: "ai_dynamic",
|
|
17234
|
+
narrativeStyle: "animated_inner_journey"
|
|
17235
|
+
},
|
|
17236
|
+
object_soul: {
|
|
17237
|
+
videoStyle: "ai_dynamic",
|
|
17238
|
+
narrativeStyle: "animated_object_soul"
|
|
17239
|
+
},
|
|
17240
|
+
timeline: {
|
|
17241
|
+
videoStyle: "ai_dynamic",
|
|
17242
|
+
narrativeStyle: "animated_timeline"
|
|
17088
17243
|
}
|
|
17089
17244
|
};
|
|
17090
17245
|
function resolveVideoPreset(preset) {
|
|
@@ -17092,6 +17247,26 @@ function resolveVideoPreset(preset) {
|
|
|
17092
17247
|
return VIDEO_PRESET_RESOLUTION[preset] ?? null;
|
|
17093
17248
|
}
|
|
17094
17249
|
__name(resolveVideoPreset, "resolveVideoPreset");
|
|
17250
|
+
var ANIMATED_VIDEO_PRESETS = /* @__PURE__ */ new Set([
|
|
17251
|
+
"pixar_problem",
|
|
17252
|
+
"pixar_sassy",
|
|
17253
|
+
"storyteller",
|
|
17254
|
+
"inner_journey",
|
|
17255
|
+
"object_soul",
|
|
17256
|
+
"timeline"
|
|
17257
|
+
]);
|
|
17258
|
+
var ANIMATED_NARRATIVE_STYLES = /* @__PURE__ */ new Set([
|
|
17259
|
+
"animated_problem_pixar",
|
|
17260
|
+
"sassy_product_pixar",
|
|
17261
|
+
"animated_storyteller",
|
|
17262
|
+
"animated_inner_journey",
|
|
17263
|
+
"animated_object_soul",
|
|
17264
|
+
"animated_timeline"
|
|
17265
|
+
]);
|
|
17266
|
+
function animationStyleApplies(videoPreset, angleNarratives) {
|
|
17267
|
+
return ANIMATED_VIDEO_PRESETS.has(videoPreset ?? "") || (angleNarratives ?? []).some((n) => ANIMATED_NARRATIVE_STYLES.has(n));
|
|
17268
|
+
}
|
|
17269
|
+
__name(animationStyleApplies, "animationStyleApplies");
|
|
17095
17270
|
var VideoTierEnum = z77.enum([
|
|
17096
17271
|
"basic"
|
|
17097
17272
|
]);
|
|
@@ -17103,19 +17278,23 @@ function resolveWireVideoTier(tier, durationSeconds) {
|
|
|
17103
17278
|
return durationSeconds === 30 ? "standard" : resolveVideoTier(tier);
|
|
17104
17279
|
}
|
|
17105
17280
|
__name(resolveWireVideoTier, "resolveWireVideoTier");
|
|
17106
|
-
function assertVideoPresetDurationCompatibility(
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
|
|
17281
|
+
function assertVideoPresetDurationCompatibility(_videoPreset, _durationSeconds, _videoStructure, _videoQuality) {
|
|
17282
|
+
}
|
|
17283
|
+
__name(assertVideoPresetDurationCompatibility, "assertVideoPresetDurationCompatibility");
|
|
17284
|
+
var MULTI_SCENE_ONLY_NARRATIVES = /* @__PURE__ */ new Set([]);
|
|
17285
|
+
function assertAngleNarrativeDurationCompatibility(angleNarratives, durationSeconds, videoStructure) {
|
|
17286
|
+
if (!angleNarratives?.some((n) => MULTI_SCENE_ONLY_NARRATIVES.has(n))) return;
|
|
17287
|
+
if (videoStructure !== void 0) {
|
|
17288
|
+
if (videoStructure === "single_take") {
|
|
17289
|
+
throw new Error("Alguna de las narrativas por \xE1ngulo solo est\xE1 disponible en Multiescena.");
|
|
17111
17290
|
}
|
|
17112
17291
|
return;
|
|
17113
17292
|
}
|
|
17114
17293
|
if (durationSeconds !== 30) {
|
|
17115
|
-
throw new Error("
|
|
17294
|
+
throw new Error("Alguna de las narrativas por \xE1ngulo solo est\xE1 disponible en videos Multiescena de 30 segundos.");
|
|
17116
17295
|
}
|
|
17117
17296
|
}
|
|
17118
|
-
__name(
|
|
17297
|
+
__name(assertAngleNarrativeDurationCompatibility, "assertAngleNarrativeDurationCompatibility");
|
|
17119
17298
|
function resolveVideoFormatForDuration(durationSeconds) {
|
|
17120
17299
|
return durationSeconds === 30 ? "double_30s" : "single_15s";
|
|
17121
17300
|
}
|
|
@@ -17136,6 +17315,7 @@ var VideoResolutionEnum = VideoResolution;
|
|
|
17136
17315
|
var CreativeGenderEnum = CreativeGenderPin;
|
|
17137
17316
|
var NarrativeStyleEnum = McpNarrativeStyleSchema;
|
|
17138
17317
|
var PublicNarrativeStyleEnum = McpAngleNarrativeStyleSchema;
|
|
17318
|
+
var AnimationStyleEnum = AnimationStyleSchema;
|
|
17139
17319
|
var TaskVideoModelEnum = VideoModel;
|
|
17140
17320
|
var ProductReferenceUserChoiceEnum = ProductReferenceUserChoiceSchema;
|
|
17141
17321
|
var ProductReferenceScopeEnum = ProductReferenceScopeSchema;
|
|
@@ -18841,7 +19021,8 @@ var CreateProductTaskInput = z80.object({
|
|
|
18841
19021
|
paymentMethods: z80.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.'),
|
|
18842
19022
|
productContext: z80.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."),
|
|
18843
19023
|
productLabel: z80.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.'),
|
|
18844
|
-
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)
|
|
19024
|
+
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.'),
|
|
19025
|
+
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.'),
|
|
18845
19026
|
durationSeconds: z80.union([
|
|
18846
19027
|
z80.literal(15),
|
|
18847
19028
|
z80.literal(30)
|
|
@@ -18853,7 +19034,7 @@ var CreateProductTaskInput = z80.object({
|
|
|
18853
19034
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El proveedor se elige internamente. Default: economy.'),
|
|
18854
19035
|
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).'),
|
|
18855
19036
|
videoAngleCount: z80.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."),
|
|
18856
|
-
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.'),
|
|
19037
|
+
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.'),
|
|
18857
19038
|
outputs: z80.array(z80.enum([
|
|
18858
19039
|
"landing",
|
|
18859
19040
|
"video",
|
|
@@ -18961,7 +19142,7 @@ var PendingActionPayload = z80.discriminatedUnion("kind", [
|
|
|
18961
19142
|
// an opaque HTTP 400 after the model already believed it had been saved.
|
|
18962
19143
|
features: z80.array(z80.string().min(1).max(MCP_REVIEW_FEATURE_ITEM_MAX)).max(10).optional(),
|
|
18963
19144
|
buyerPersona: z80.string().min(1).max(360).optional(),
|
|
18964
|
-
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n)
|
|
19145
|
+
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.'),
|
|
18965
19146
|
actor: z80.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."),
|
|
18966
19147
|
actorId: z80.string().max(120).nullable().optional(),
|
|
18967
19148
|
creativeDirection: z80.string().max(2e3).optional(),
|
|
@@ -18974,7 +19155,7 @@ var PendingActionPayload = z80.discriminatedUnion("kind", [
|
|
|
18974
19155
|
]).optional().describe("Elecci\xF3n expl\xEDcita: market usa el estudio disponible; guided usa la narrativa elegida para este \xE1ngulo."),
|
|
18975
19156
|
angle: z80.string().min(1).max(480).optional(),
|
|
18976
19157
|
buyerPersona: z80.string().min(1).max(360).optional(),
|
|
18977
|
-
narrativeStyle: PublicNarrativeStyleEnum.optional().describe('Narrativa del video. "problem_product_cta" (Problema y Soluci\xF3n)
|
|
19158
|
+
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.'),
|
|
18978
19159
|
actor: z80.string().min(1).max(360).optional(),
|
|
18979
19160
|
actorId: z80.string().max(120).nullable().optional(),
|
|
18980
19161
|
creativeDirection: z80.string().max(2e3).optional()
|
|
@@ -19254,6 +19435,10 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19254
19435
|
const selectedOutputs = input.outputs ?? DEFAULT_PRODUCT_TASK_OUTPUTS;
|
|
19255
19436
|
const videoPreset = selectedOutputs.includes("video") && input.competitorScanEnabled === true ? "auto" : input.videoPreset;
|
|
19256
19437
|
assertVideoPresetDurationCompatibility(videoPreset, input.durationSeconds, input.videoStructure, input.videoQuality);
|
|
19438
|
+
assertAngleNarrativeDurationCompatibility(input.angleNarratives, input.durationSeconds, input.videoStructure);
|
|
19439
|
+
if (input.animationStyle !== void 0 && !animationStyleApplies(videoPreset, input.angleNarratives)) {
|
|
19440
|
+
throw new Error("animationStyle solo aplica a narrativas animadas.");
|
|
19441
|
+
}
|
|
19257
19442
|
if (selectedOutputs.includes("video")) {
|
|
19258
19443
|
assertSemanticVideoDurationCompatibility(input.videoStructure, input.videoQuality, input.durationSeconds);
|
|
19259
19444
|
}
|
|
@@ -19297,6 +19482,7 @@ ANTES de invocar, resume outputs, cantidad de videos y datos comerciales, explic
|
|
|
19297
19482
|
"options.productContext": input.productContext,
|
|
19298
19483
|
"options.productLabel": input.productLabel,
|
|
19299
19484
|
"options.videoPreset": videoPreset,
|
|
19485
|
+
"options.animationStyle": input.animationStyle,
|
|
19300
19486
|
"options.videoStyle": resolved?.videoStyle,
|
|
19301
19487
|
"options.narrativeStyle": resolved?.narrativeStyle,
|
|
19302
19488
|
"options.videoTier": wireTier,
|
|
@@ -20058,8 +20244,9 @@ var VideoCreativeSetup = z81.discriminatedUnion("mode", [
|
|
|
20058
20244
|
}).strict(),
|
|
20059
20245
|
z81.object({
|
|
20060
20246
|
mode: z81.literal("guided"),
|
|
20061
|
-
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.
|
|
20247
|
+
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.'),
|
|
20062
20248
|
buyerPersona: z81.string().trim().min(1).max(360),
|
|
20249
|
+
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.'),
|
|
20063
20250
|
presenter: VideoPresenter,
|
|
20064
20251
|
creativeDirection: z81.string().trim().min(1).max(500).nullable().describe("Direcci\xF3n visual elegida. null significa que el usuario deleg\xF3 expl\xEDcitamente esta decisi\xF3n.")
|
|
20065
20252
|
}).strict()
|
|
@@ -20078,7 +20265,7 @@ var VideoInput = z81.object({
|
|
|
20078
20265
|
]).describe('Relaci\xF3n de aspecto. "9:16" = vertical (TikTok/Reels \u2014 default recomendado para ads). "16:9" = horizontal (YouTube). "Auto" = decide la IA.'),
|
|
20079
20266
|
durationSeconds: z81.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."),
|
|
20080
20267
|
videoAngleCount: z81.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."),
|
|
20081
|
-
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.'),
|
|
20268
|
+
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.'),
|
|
20082
20269
|
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."),
|
|
20083
20270
|
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.'),
|
|
20084
20271
|
videoQuality: VideoQualityEnum.default("economy").describe('Opcional. Calidad: "economy" = Econ\xF3mico, "medium" = Medio o "pro" = Pro. El sistema elige el proveedor internamente. Default: economy.'),
|
|
@@ -20399,6 +20586,10 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20399
20586
|
const guidedSetup = input.creativeSetup.mode === "guided" ? input.creativeSetup : null;
|
|
20400
20587
|
const videoPreset = input.competitorScanEnabled === true ? "auto" : guidedSetup?.videoPreset ?? "auto";
|
|
20401
20588
|
assertVideoPresetDurationCompatibility(videoPreset, input.durationSeconds, input.videoStructure, input.videoQuality);
|
|
20589
|
+
assertAngleNarrativeDurationCompatibility(input.angleNarratives, input.durationSeconds, input.videoStructure);
|
|
20590
|
+
if (guidedSetup?.animationStyle !== void 0 && !animationStyleApplies(videoPreset, input.angleNarratives)) {
|
|
20591
|
+
throw new Error("animationStyle solo aplica a narrativas animadas.");
|
|
20592
|
+
}
|
|
20402
20593
|
const resolved = resolveVideoPreset(videoPreset);
|
|
20403
20594
|
const reviewPolicy = resolveConversationalReviewPolicy(input.creativeSetup.mode === "automatic");
|
|
20404
20595
|
const { videoResolution: _vr, creativeSetup: _creativeSetup, winnerReference: _winnerReference, ...rest } = input;
|
|
@@ -20416,6 +20607,7 @@ function registerCreativeTools(server, api, { transport = "http" } = {}) {
|
|
|
20416
20607
|
if (guidedSetup.presenter.mode === "described") wirePayload.actorDescription = guidedSetup.presenter.description;
|
|
20417
20608
|
const direction = guidedSetup.creativeDirection;
|
|
20418
20609
|
wirePayload.creativeDirectionMode = direction ? "provided" : "ai_decides";
|
|
20610
|
+
if (guidedSetup.animationStyle !== void 0) wirePayload.animationStyle = guidedSetup.animationStyle;
|
|
20419
20611
|
if (direction) {
|
|
20420
20612
|
wirePayload.scriptNotes = [
|
|
20421
20613
|
input.scriptNotes?.trim(),
|
|
@@ -20964,7 +21156,7 @@ function registerScriptReviewTools(server, api) {
|
|
|
20964
21156
|
}
|
|
20965
21157
|
});
|
|
20966
21158
|
server.registerTool("approve_video_script", {
|
|
20967
|
-
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
|
|
21159
|
+
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.',
|
|
20968
21160
|
inputSchema: ApproveVideoScriptInput.shape,
|
|
20969
21161
|
annotations: CREATES_PAID
|
|
20970
21162
|
}, async (input) => {
|