@nodaro/shared 3.11.0 → 3.12.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.
Files changed (52) hide show
  1. package/dist/index.cjs +2047 -84
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1556 -27
  4. package/dist/index.d.ts +1556 -27
  5. package/dist/index.js +1861 -85
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/caption-styles.test.ts +207 -0
  9. package/src/__tests__/edl-multicam.test.ts +304 -0
  10. package/src/__tests__/edl.test.ts +822 -0
  11. package/src/__tests__/fan-out-rows.test.ts +208 -0
  12. package/src/__tests__/instagram-scrape.test.ts +66 -0
  13. package/src/__tests__/llm-models.test.ts +48 -11
  14. package/src/__tests__/meta-ads-scrape.test.ts +284 -0
  15. package/src/__tests__/node-runtime-keys.test.ts +15 -0
  16. package/src/__tests__/presentation-utils.test.ts +67 -0
  17. package/src/__tests__/producer-types.test.ts +19 -0
  18. package/src/__tests__/schedule-rules.test.ts +265 -0
  19. package/src/__tests__/speaker-layouts.test.ts +203 -0
  20. package/src/__tests__/transcribe-capabilities.test.ts +104 -0
  21. package/src/__tests__/transcribe-preflight.test.ts +60 -0
  22. package/src/__tests__/trigger-feeds.test.ts +39 -0
  23. package/src/__tests__/video-duration-auto.test.ts +65 -0
  24. package/src/__tests__/video-duration.test.ts +56 -0
  25. package/src/__tests__/video-link.test.ts +137 -0
  26. package/src/__tests__/workflow-export-strip.test.ts +59 -1
  27. package/src/caption-styles.ts +240 -0
  28. package/src/credit-identifiers.ts +31 -0
  29. package/src/edit-plan-contract.ts +96 -0
  30. package/src/edl-multicam.ts +185 -0
  31. package/src/edl.ts +747 -0
  32. package/src/entity-image-handle.ts +24 -1
  33. package/src/fan-out-rows.ts +213 -0
  34. package/src/index.ts +206 -3
  35. package/src/instagram-scrape.ts +204 -0
  36. package/src/llm-models.ts +80 -3
  37. package/src/meta-ads-scrape.ts +463 -0
  38. package/src/model-catalog.ts +48 -5
  39. package/src/model-constants.ts +148 -5
  40. package/src/node-mappable-fields.ts +2 -0
  41. package/src/node-runtime-keys.ts +28 -0
  42. package/src/presentation-utils.ts +49 -0
  43. package/src/producer-types.ts +20 -0
  44. package/src/schedule-rules.ts +484 -0
  45. package/src/speaker-layouts.ts +220 -0
  46. package/src/transcribe-preflight.ts +101 -0
  47. package/src/trigger-feeds.ts +59 -0
  48. package/src/trigger-node-types.ts +20 -0
  49. package/src/video-duration-auto.ts +18 -0
  50. package/src/video-duration.ts +32 -0
  51. package/src/video-link.ts +167 -0
  52. package/src/workflow-export.ts +37 -1
package/dist/index.js CHANGED
@@ -43,6 +43,13 @@ function isFlux2Model(m) {
43
43
  return m === "flux-2-klein" || m === "flux-2-pro" || m === "flux-2-max";
44
44
  }
45
45
 
46
+ // src/video-duration-auto.ts
47
+ var VIDEO_DURATION_AUTO = -1;
48
+ function isAutoVideoDuration(duration) {
49
+ const n = typeof duration === "string" ? parseInt(duration, 10) : duration;
50
+ return n === VIDEO_DURATION_AUTO;
51
+ }
52
+
46
53
  // src/model-catalog.ts
47
54
  var MODEL_RECOMMENDATIONS = [
48
55
  // image
@@ -62,7 +69,7 @@ var MODEL_RECOMMENDATIONS = [
62
69
  { intent: "music / song generation", modelIds: ["suno-v6", "suno-v6_wild", "suno-v6_mini", "suno-v5_5"], note: "V6 is the default flagship; V6 Wild for bolder, less predictable results; V6 Mini when speed matters; v5.5 / v5 / v4 keep their own character. Same price." },
63
70
  { intent: "voice over / narration", modelIds: ["elevenlabs-v3", "elevenlabs-turbo"], note: "v3 supports [audio tags] for emotion; Turbo is cheaper for plain narration." },
64
71
  { intent: "lip-sync a portrait to audio", modelIds: ["kling-avatar-pro", "kling-avatar", "infinitalk"], note: "Pro for best mouth shape; InfiniTalk for resolution control." },
65
- { intent: "transcription / captions", modelIds: ["elevenlabs-stt"], note: "Word-level timestamps available." },
72
+ { intent: "transcription / captions", modelIds: ["elevenlabs-stt", "incredibly-fast-whisper", "whisper"], note: "Captions need WORD timestamps: ElevenLabs STT (always) or Incredibly Fast Whisper. Plain Whisper returns phrase segments only." },
66
73
  { intent: "motion transfer (drive a subject by another video)", modelIds: ["motion-transfer", "kling-3.0-motion"], note: "Kling 2.6 base is cheap; Kling 3.0 is premium." }
67
74
  ];
68
75
  var NANO_BANANA_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "4:5", "5:4", "21:9"];
@@ -1357,6 +1364,7 @@ var VIDEO_MODELS = {
1357
1364
  features: ["end-frame", "audio", "reference-image", "video-reference"],
1358
1365
  aspectRatios: VIDEO_RATIOS_SEEDANCE_2,
1359
1366
  durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
1367
+ autoDuration: true,
1360
1368
  resolutions: ["480p", "720p", "1080p", "4k"],
1361
1369
  pricing: [
1362
1370
  { identifier: "seedance-2", credits: 380, note: "default \u2014 see :NsR variants for exact" },
@@ -1382,6 +1390,7 @@ var VIDEO_MODELS = {
1382
1390
  features: ["end-frame", "audio", "reference-image", "video-reference"],
1383
1391
  aspectRatios: VIDEO_RATIOS_SEEDANCE_2,
1384
1392
  durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
1393
+ autoDuration: true,
1385
1394
  resolutions: ["480p", "720p"],
1386
1395
  pricing: [
1387
1396
  { identifier: "seedance-2-fast", credits: 310, note: "default \u2014 see :NsR variants" },
@@ -1403,6 +1412,7 @@ var VIDEO_MODELS = {
1403
1412
  features: ["end-frame", "audio", "reference-image", "video-reference"],
1404
1413
  aspectRatios: VIDEO_RATIOS_SEEDANCE_2,
1405
1414
  durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
1415
+ autoDuration: true,
1406
1416
  resolutions: ["480p", "720p"],
1407
1417
  pricing: [
1408
1418
  { identifier: "seedance-2-mini", credits: 190, note: "default \u2014 see :NsR variants" },
@@ -1430,6 +1440,7 @@ var VIDEO_MODELS = {
1430
1440
  features: ["end-frame", "audio", "reference-image", "video-reference"],
1431
1441
  aspectRatios: VIDEO_RATIOS_SEEDANCE_2,
1432
1442
  durations: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
1443
+ autoDuration: true,
1433
1444
  resolutions: ["480p", "720p", "1080p"],
1434
1445
  pricing: [
1435
1446
  { identifier: "seedance-2-5", credits: 1260, note: "default 8s 720p \u2014 see :Ns:res variants for exact" },
@@ -2309,10 +2320,34 @@ var AUDIO_MODELS = {
2309
2320
  family: "ElevenLabs",
2310
2321
  label: "ElevenLabs STT",
2311
2322
  series: "ElevenLabs",
2312
- description: "Speech-to-text \u2014 transcribe audio with timestamps.",
2313
- useCases: ["transcription", "stt"],
2323
+ description: "Speech-to-text with WORD-level timestamps (always on), speaker diarization and audio-event tags. The engine to use when the transcript feeds captions.",
2324
+ useCases: ["transcription", "stt", "captions"],
2325
+ features: ["word-timestamps", "diarization", "audio-events"],
2314
2326
  pricing: [{ identifier: "elevenlabs-stt", credits: 22 }]
2315
2327
  },
2328
+ "incredibly-fast-whisper": {
2329
+ id: "incredibly-fast-whisper",
2330
+ kind: "audio",
2331
+ modes: ["stt"],
2332
+ family: "OpenAI",
2333
+ label: "Incredibly Fast Whisper",
2334
+ series: "Whisper",
2335
+ description: "Fast Whisper speech-to-text. Returns WORD-level timestamps when asked, so its transcript can feed captions.",
2336
+ useCases: ["transcription", "stt", "captions"],
2337
+ features: ["word-timestamps"],
2338
+ pricing: [{ identifier: "incredibly-fast-whisper", credits: 40 }]
2339
+ },
2340
+ "whisper": {
2341
+ id: "whisper",
2342
+ kind: "audio",
2343
+ modes: ["stt"],
2344
+ family: "OpenAI",
2345
+ label: "Whisper",
2346
+ series: "Whisper",
2347
+ description: "Whisper speech-to-text \u2014 PHRASE-level segments only, NO word timestamps. Fine for a transcript or a static subtitle; not for word-timed (kinetic) captions.",
2348
+ useCases: ["transcription", "stt"],
2349
+ pricing: [{ identifier: "whisper", credits: 40 }]
2350
+ },
2316
2351
  "elevenlabs-isolation": {
2317
2352
  id: "elevenlabs-isolation",
2318
2353
  kind: "audio",
@@ -2534,7 +2569,8 @@ function validateModelInput(modelId, input) {
2534
2569
  allowed: null
2535
2570
  };
2536
2571
  }
2537
- if (!m.durations.includes(input.duration)) {
2572
+ const isAuto = m.autoDuration === true && isAutoVideoDuration(input.duration);
2573
+ if (!isAuto && !m.durations.includes(input.duration)) {
2538
2574
  return {
2539
2575
  field: "duration",
2540
2576
  message: `Model "${modelId}" does not support duration ${input.duration}s. Supported: ${m.durations.join(", ")}s.`,
@@ -2594,7 +2630,7 @@ function normalizeModelInput(modelId, input) {
2594
2630
  defaultResolutionFor(modelId)
2595
2631
  );
2596
2632
  out.quality = snap("quality", input.quality, m.qualities);
2597
- out.duration = snap("duration", input.duration, m.durations);
2633
+ out.duration = m.autoDuration === true && isAutoVideoDuration(input.duration) ? input.duration : snap("duration", input.duration, m.durations);
2598
2634
  if (modelId === "gpt-image-2" || modelId === "gpt-image-2-i2i") {
2599
2635
  if (out.aspectRatio === "auto" && out.resolution !== void 0 && out.resolution !== "1K") {
2600
2636
  adjustments.push({
@@ -3077,11 +3113,11 @@ function videoNegativeSuffix(negativePrompt, base) {
3077
3113
  }
3078
3114
  function applyVideoNegativePrompt(prompt, negativePrompt, provider) {
3079
3115
  const promptMax = getMaxVideoPromptChars(provider);
3080
- const clamp = (p) => p != null && p.length > promptMax ? p.slice(0, promptMax) : p;
3116
+ const clamp2 = (p) => p != null && p.length > promptMax ? p.slice(0, promptMax) : p;
3081
3117
  const neg = negativePrompt?.trim();
3082
- if (!neg) return { prompt: clamp(prompt), nativeNegativePrompt: void 0 };
3118
+ if (!neg) return { prompt: clamp2(prompt), nativeNegativePrompt: void 0 };
3083
3119
  if (NATIVE_NEGATIVE_VIDEO_PROVIDERS.has(provider)) {
3084
- return { prompt: clamp(prompt), nativeNegativePrompt: neg.slice(0, getMaxNegativePromptChars(provider)) };
3120
+ return { prompt: clamp2(prompt), nativeNegativePrompt: neg.slice(0, getMaxNegativePromptChars(provider)) };
3085
3121
  }
3086
3122
  const base = prompt && prompt.trim().length > 0 ? prompt : "";
3087
3123
  if (!base) return { prompt: `Avoid: ${neg}`.slice(0, promptMax), nativeNegativePrompt: void 0 };
@@ -3478,6 +3514,12 @@ var VIDEO_TO_VIDEO_PROVIDERS = [
3478
3514
  "runway-aleph",
3479
3515
  "happyhorse-edit"
3480
3516
  ];
3517
+ var SEEDANCE_VIDEO_EDIT_PROVIDERS = ["seedance-2-5"];
3518
+ function isSeedanceVideoEditProvider(provider) {
3519
+ return !!provider && SEEDANCE_VIDEO_EDIT_PROVIDERS.includes(provider);
3520
+ }
3521
+ var VIDEO_TO_VIDEO_NODE_PROVIDERS = [...VIDEO_TO_VIDEO_PROVIDERS, ...SEEDANCE_VIDEO_EDIT_PROVIDERS];
3522
+ var SEEDANCE_VIDEO_EDIT_SHAPE = { aspectRatio: "adaptive", duration: VIDEO_DURATION_AUTO };
3481
3523
  var FACE_SWAP_PROVIDERS = [
3482
3524
  "roop"
3483
3525
  ];
@@ -3605,11 +3647,29 @@ var MUSIC_PROVIDERS = [
3605
3647
  // "bark",
3606
3648
  ];
3607
3649
  var TRANSCRIBE_PROVIDERS = [
3608
- // Replicate disabled
3609
- // "whisper",
3610
- // "incredibly-fast-whisper",
3650
+ "elevenlabs-stt",
3651
+ "whisper",
3652
+ "incredibly-fast-whisper"
3653
+ ];
3654
+ var TRANSCRIBE_LANES = [
3655
+ "whisper",
3656
+ "incredibly-fast-whisper",
3611
3657
  "elevenlabs-stt"
3612
3658
  ];
3659
+ var TRANSCRIBE_PROVIDER_CAPABILITIES = {
3660
+ "whisper": { wordTimestamps: false },
3661
+ "incredibly-fast-whisper": { wordTimestamps: true },
3662
+ "elevenlabs-stt": { wordTimestamps: true }
3663
+ };
3664
+ function transcribeProvidersWithWordTimestamps() {
3665
+ return TRANSCRIBE_LANES.filter((p) => TRANSCRIBE_PROVIDER_CAPABILITIES[p].wordTimestamps);
3666
+ }
3667
+ function transcribeLaneSupportsWordTimestamps(lane) {
3668
+ if (!lane) return false;
3669
+ return TRANSCRIBE_PROVIDER_CAPABILITIES[lane]?.wordTimestamps === true;
3670
+ }
3671
+ var DEFAULT_TRANSCRIBE_PROVIDER = "whisper";
3672
+ var DEFAULT_TRANSCRIBE_NODE_PROVIDER = "elevenlabs-stt";
3613
3673
  var SCRIPT_PROVIDERS = [
3614
3674
  "gemini",
3615
3675
  "claude",
@@ -4207,7 +4267,18 @@ var PRICING_DEFAULT_DURATION_SEC = {
4207
4267
  function pricedOutputDurationSec(provider, requested) {
4208
4268
  const fallback = PRICING_DEFAULT_DURATION_SEC[provider] ?? 5;
4209
4269
  const parsed = typeof requested === "string" ? parseInt(requested, 10) : requested;
4210
- return parsed === void 0 || Number.isNaN(parsed) ? fallback : parsed;
4270
+ if (parsed === void 0 || Number.isNaN(parsed)) return fallback;
4271
+ if (parsed <= 0) {
4272
+ return isAutoVideoDuration(parsed) && supportsAutoVideoDuration(provider) ? maxVideoDurationSec(provider) ?? fallback : fallback;
4273
+ }
4274
+ return parsed;
4275
+ }
4276
+ function supportsAutoVideoDuration(provider) {
4277
+ return !!provider && MODEL_CATALOG[provider]?.autoDuration === true;
4278
+ }
4279
+ function maxVideoDurationSec(provider) {
4280
+ const tiers = VIDEO_DURATION_TIERS[provider];
4281
+ return tiers && tiers.length > 0 ? tiers[tiers.length - 1].maxSeconds : void 0;
4211
4282
  }
4212
4283
  var PRICING_DEFAULT_RESOLUTION = {
4213
4284
  // KIE renders 720p when `resolution` is omitted (kie/models.ts extraParams).
@@ -4732,10 +4803,10 @@ function band(center) {
4732
4803
  var VERT = { low: "upper", mid: "middle", high: "lower" };
4733
4804
  var HORZ = { low: "left", mid: "center", high: "right" };
4734
4805
  function describeMaskRegion(box, image) {
4735
- const clamp012 = (n) => Math.max(0, Math.min(1, n));
4806
+ const clamp013 = (n) => Math.max(0, Math.min(1, n));
4736
4807
  const round2 = (n) => Math.round(n * 100) / 100;
4737
- const nx = clamp012(box.x / image.width);
4738
- const ny = clamp012(box.y / image.height);
4808
+ const nx = clamp013(box.x / image.width);
4809
+ const ny = clamp013(box.y / image.height);
4739
4810
  const normBbox = {
4740
4811
  x: round2(nx),
4741
4812
  y: round2(ny),
@@ -4899,6 +4970,21 @@ function expandExtraRefsToConnectedReferences(extras, lookupCharacterContext) {
4899
4970
  return out;
4900
4971
  }
4901
4972
 
4973
+ // src/video-ui-defaults.ts
4974
+ function uiAspectRatioFill(provider) {
4975
+ return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider) ? "adaptive" : void 0;
4976
+ }
4977
+ function uiResolutionFill(provider) {
4978
+ if (isWan3Provider(provider)) return PRICING_DEFAULT_RESOLUTION[provider];
4979
+ if (isSeedance2Provider(provider)) return MODEL_CATALOG[provider]?.resolutions?.[0];
4980
+ return void 0;
4981
+ }
4982
+ function uiDurationFill(provider) {
4983
+ if (isWan3Provider(provider)) return 5;
4984
+ if (isGeminiOmniProvider(provider)) return 8;
4985
+ return void 0;
4986
+ }
4987
+
4902
4988
  // src/credit-identifiers.ts
4903
4989
  function flux2MegapixelTier(model, resolution) {
4904
4990
  const bare = (v) => v.replace(/\s*MP$/i, "").trim();
@@ -4933,20 +5019,20 @@ function buildCreditModelIdentifier(provider, quality, resolution, renderingSpee
4933
5019
  return provider;
4934
5020
  }
4935
5021
  function resolveNormalizedImageGen(opts) {
4936
- const str = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
4937
- const provider = str(opts.provider) ?? "nano-banana";
5022
+ const str3 = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
5023
+ const provider = str3(opts.provider) ?? "nano-banana";
4938
5024
  const modelId = opts.swapToI2i && opts.refCount > 0 ? T2I_TO_I2I_VARIANT[provider] ?? provider : provider;
4939
5025
  const n = normalizeModelInput(modelId, {
4940
- aspectRatio: str(opts.aspectRatio),
4941
- resolution: str(opts.resolution),
4942
- quality: str(opts.quality)
5026
+ aspectRatio: str3(opts.aspectRatio),
5027
+ resolution: str3(opts.resolution),
5028
+ quality: str3(opts.quality)
4943
5029
  });
4944
5030
  return {
4945
5031
  identifier: buildCreditModelIdentifier(
4946
5032
  modelId,
4947
5033
  n.quality,
4948
5034
  n.resolution,
4949
- str(opts.renderingSpeed),
5035
+ str3(opts.renderingSpeed),
4950
5036
  void 0,
4951
5037
  opts.refCount
4952
5038
  ),
@@ -5048,6 +5134,18 @@ function buildVideoCreditModelIdentifier(provider, duration, sound, nodeType, mo
5048
5134
  }
5049
5135
  return identifier;
5050
5136
  }
5137
+ function seedanceVideoEditCreditId(provider, resolution) {
5138
+ return buildVideoCreditModelIdentifier(
5139
+ provider,
5140
+ VIDEO_DURATION_AUTO,
5141
+ void 0,
5142
+ "text-to-video",
5143
+ void 0,
5144
+ resolution ?? uiResolutionFill(provider),
5145
+ /* hasVideoRef */
5146
+ true
5147
+ );
5148
+ }
5051
5149
  function pricedVideoSelection(opts) {
5052
5150
  const adjustments = [];
5053
5151
  const ltx = ltxPricedTier(opts.provider, opts.resolution, opts.duration);
@@ -5250,6 +5348,16 @@ function extractVideoDurationFromNode(data) {
5250
5348
  }
5251
5349
  return void 0;
5252
5350
  }
5351
+ function editPlanSourceDurationSec(data) {
5352
+ const fromVideo = extractVideoDurationFromNode(data);
5353
+ if (fromVideo !== void 0) return fromVideo;
5354
+ const meta = data?.metadata;
5355
+ if (typeof meta?.mediaUrl === "string" && meta.mediaUrl !== data?.extractedAudioUrl && meta.mediaUrl !== data?.url) {
5356
+ return void 0;
5357
+ }
5358
+ const d = meta?.durationSeconds;
5359
+ return typeof d === "number" && Number.isFinite(d) && d > 0 ? d : void 0;
5360
+ }
5253
5361
 
5254
5362
  // src/topaz-upscale.ts
5255
5363
  var TOPAZ_UPSCALE_FACTORS = ["1", "2", "4"];
@@ -5421,7 +5529,20 @@ var DYNAMIC_PRODUCER_TYPES = /* @__PURE__ */ new Set([
5421
5529
  // so it lives here to be accepted on BOTH audio and video input handles. The
5422
5530
  // backend routes the correct lane by sourceHandle in getPrimaryOutput
5423
5531
  // (output-extractor.ts); the frontend does so in extractNodeOutput.
5424
- "split-media"
5532
+ "split-media",
5533
+ // apply-edl renders an EDL into ONE media output whose type is decided at
5534
+ // run time by the node's `output` setting (video OR audio) — so its static
5535
+ // medium is genuinely unknown and it belongs here, letting canvas validators
5536
+ // accept its default media handle on BOTH audio and video input handles. It
5537
+ // ALSO emits a fixed `json` handle (the remapped Transcript); that half lives
5538
+ // in JSON_PRODUCER_TYPES (frontend/src/lib/data-handles.ts). The FIRST node
5539
+ // with both a dynamic media handle and a fixed json handle. Because
5540
+ // getOutputType (presentation-utils.ts) deliberately returns "data" for
5541
+ // DYNAMIC members, apply-edl is ALSO added to the literal VIDEO_OUTPUT_TYPES
5542
+ // there so a published app renders the cut as video, mirroring the
5543
+ // voice-changer/dubbing precedent. Asserted in producer-types.test.ts (the
5544
+ // suite does not fail on omission).
5545
+ "apply-edl"
5425
5546
  ]);
5426
5547
  var AUDIO_PRODUCER_TYPES = /* @__PURE__ */ new Set([
5427
5548
  "text-to-speech",
@@ -5464,7 +5585,14 @@ var FAN_OUT_EACH_TYPES = /* @__PURE__ */ new Set([
5464
5585
  "deduplicate",
5465
5586
  "merge-lists",
5466
5587
  "sort-list",
5467
- "selector"
5588
+ "selector",
5589
+ // edit-plan `clips` mode emits a bare `Edl[]` on `data.generatedJson`, so an
5590
+ // edge leaving it defaults to "each" — one downstream execution (typically an
5591
+ // apply-edl render) per clip. The `tighten`/`chapters` modes emit an OBJECT,
5592
+ // for which the list extractors return undefined, so an "each" edge falls back
5593
+ // to the scalar `edl` value (no fan-out) — the same graceful degradation
5594
+ // web-scrape relies on. See `unwrapEditPlanOutput` in `edit-plan-contract.ts`.
5595
+ "edit-plan"
5468
5596
  ]);
5469
5597
 
5470
5598
  // src/presentation-utils.ts
@@ -5595,7 +5723,14 @@ var VIDEO_OUTPUT_TYPES = /* @__PURE__ */ new Set([
5595
5723
  "motion-transfer",
5596
5724
  "video-upscale",
5597
5725
  "add-captions",
5598
- "social-media-format"
5726
+ "social-media-format",
5727
+ // apply-edl renders an EDL into video OR audio. Its medium is decided at run
5728
+ // time (DYNAMIC_PRODUCER_TYPES), so getOutputType would answer "data" and a
5729
+ // published app would render the cut as a JSON blob. Declaring it here — as
5730
+ // the voice-changer/dubbing precedent does for their default medium — makes
5731
+ // the classifier answer "video" (the common case; an audio-only cut still
5732
+ // plays in a video element). Asserted in producer-types.test.ts.
5733
+ "apply-edl"
5599
5734
  ]);
5600
5735
  var AUDIO_OUTPUT_TYPES = /* @__PURE__ */ new Set([
5601
5736
  "text-to-speech",
@@ -5756,6 +5891,19 @@ var INPUT_FIELD_MAP = {
5756
5891
  function getInputFieldSchema(nodeType) {
5757
5892
  return INPUT_FIELD_MAP[nodeType];
5758
5893
  }
5894
+ var MEDIA_INPUT_FIELD_TYPES = /* @__PURE__ */ new Set([
5895
+ "image-url",
5896
+ "video-url",
5897
+ "audio-url"
5898
+ ]);
5899
+ function mergeNodeInputOverrides(nodeType, data, overrides) {
5900
+ const merged = { ...data, ...overrides };
5901
+ const schema = nodeType ? INPUT_FIELD_MAP[nodeType] : void 0;
5902
+ if (schema && MEDIA_INPUT_FIELD_TYPES.has(schema.type) && schema.key in overrides && overrides[schema.key] !== data[schema.key] && !("metadata" in overrides)) {
5903
+ delete merged.metadata;
5904
+ }
5905
+ return merged;
5906
+ }
5759
5907
  function migrateToItems(order) {
5760
5908
  if (!order) return void 0;
5761
5909
  return order.map((nodeId) => ({ type: "node", nodeId }));
@@ -5867,6 +6015,10 @@ function computeAggregateLanes(nodeId, wiredTypes, buckets, edges) {
5867
6015
  var LLM_REASONING_EFFORTS = ["none", "low", "medium", "high", "xhigh", "max"];
5868
6016
  var EFFORT_TIER_BUMP = /* @__PURE__ */ new Set(["xhigh", "max"]);
5869
6017
  var EFFORT_RANK = { none: 0, low: 1, medium: 2, high: 3, xhigh: 4, max: 5 };
6018
+ var REASONING_OUTPUT_FLOOR = 32768;
6019
+ function reasoningOutputFloor(model) {
6020
+ return model.reasoningOutputFloor ?? REASONING_OUTPUT_FLOOR;
6021
+ }
5870
6022
  var LLM_MODELS = [
5871
6023
  {
5872
6024
  id: "gemini-3-flash",
@@ -5885,7 +6037,12 @@ var LLM_MODELS = [
5885
6037
  directGeminiModel: "gemini-3-flash-preview",
5886
6038
  // No `reasoningEfforts` at all on the KIE lane, but the vendor API accepts
5887
6039
  // the full minimal→high ladder (`none` maps to Google's `minimal`).
5888
- directReasoningEfforts: ["none", "low", "medium", "high"]
6040
+ directReasoningEfforts: ["none", "low", "medium", "high"],
6041
+ // Reasons with no thinking param sent — Google's Gemini 3 default (dynamic
6042
+ // thinking; `minimal` is its floor, never off), measured on 3.6 in #1588.
6043
+ // Floored at the KIE-safe 8192, the same intersection as `maxOutputTokens`.
6044
+ thinkingDefaultOn: true,
6045
+ reasoningOutputFloor: 8192
5889
6046
  },
5890
6047
  {
5891
6048
  id: "gemini-3.6-flash",
@@ -5917,7 +6074,16 @@ var LLM_MODELS = [
5917
6074
  // video-analysis fast tier, so it carries the highest call volume of any
5918
6075
  // Gemini entry — the lane with the lower unit cost wins by default and
5919
6076
  // direct is the reliability fallback only.
5920
- directGeminiModel: "gemini-3.6-flash"
6077
+ directGeminiModel: "gemini-3.6-flash",
6078
+ // Reasons with NO thinking param sent — measured, issue #1588: a Generate
6079
+ // Text node capped at 1,100 tokens fell back to the direct lane (KIE 500),
6080
+ // spent ~1,060 of them reasoning, and returned 120 characters cut mid-URL.
6081
+ // On the same input the KIE runs used ~500 output tokens in all, so only
6082
+ // the fallback runs broke — every other run of a 5-minute schedule.
6083
+ // Floored at 8192, NOT the default 32768: the floor rides the KIE endpoint
6084
+ // too, and 8192 is all it is known to take (see `maxOutputTokens`).
6085
+ thinkingDefaultOn: true,
6086
+ reasoningOutputFloor: 8192
5921
6087
  },
5922
6088
  {
5923
6089
  id: "gemini-3.7-flash",
@@ -5945,7 +6111,11 @@ var LLM_MODELS = [
5945
6111
  reasoningEfforts: ["low", "high"],
5946
6112
  // Assumed parity with 3.6 pending a live probe on the direct lane.
5947
6113
  directReasoningEfforts: ["none", "low", "medium", "high"],
5948
- directGeminiModel: "gemini-3.7-flash"
6114
+ directGeminiModel: "gemini-3.7-flash",
6115
+ // Gemini 3 default: reasons with no thinking param sent (measured on 3.6,
6116
+ // #1588). KIE-safe floor, same intersection as `maxOutputTokens`.
6117
+ thinkingDefaultOn: true,
6118
+ reasoningOutputFloor: 8192
5949
6119
  },
5950
6120
  {
5951
6121
  id: "gemini-3.8-flash",
@@ -5985,7 +6155,12 @@ var LLM_MODELS = [
5985
6155
  directReasoningEfforts: ["none", "low", "medium", "high"],
5986
6156
  // KIE-first (no `preferDirect`) — 3.7's posture exactly: the cheap lane
5987
6157
  // serves the A/B, direct is Advanced mode + the reliability fallback.
5988
- directGeminiModel: "gemini-3.8-flash"
6158
+ directGeminiModel: "gemini-3.8-flash",
6159
+ // Gemini 3 default: reasons with no thinking param sent (measured on 3.6,
6160
+ // #1588). Floored at its own 16384, inside the 20000 its KIE endpoint was
6161
+ // measured to honour.
6162
+ thinkingDefaultOn: true,
6163
+ reasoningOutputFloor: 16384
5989
6164
  },
5990
6165
  {
5991
6166
  id: "claude-haiku-4.5",
@@ -6058,7 +6233,12 @@ var LLM_MODELS = [
6058
6233
  // control, native media ingestion, and a `responseJsonSchema` that honours
6059
6234
  // `additionalProperties` (KIE's `response_format` silently DROPS
6060
6235
  // record/map-shaped fields — see the z.record rule in backend/CLAUDE.md).
6061
- preferDirect: true
6236
+ preferDirect: true,
6237
+ // Reasons with no thinking param sent on both lanes — the proxied endpoint
6238
+ // DEFAULTS to "high" (above), and the direct lane reasons harder still.
6239
+ // Floored at its own 16384: its KIE fallback is not known to take more.
6240
+ thinkingDefaultOn: true,
6241
+ reasoningOutputFloor: 16384
6062
6242
  },
6063
6243
  {
6064
6244
  id: "claude-opus-4.7",
@@ -6153,7 +6333,23 @@ var LLM_MODELS = [
6153
6333
  supportsImages: true,
6154
6334
  maxOutputTokens: 16384,
6155
6335
  reasoningEfforts: ["none", "low", "medium", "high", "xhigh", "max"],
6156
- supportsTemperature: false
6336
+ supportsTemperature: false,
6337
+ // SERVED COLLAPSED, on the astra precedent (2026-09-17). The 2026-07-14
6338
+ // verification that KIE's non-stream responses endpoint serves the GPT-5.6
6339
+ // family reliably no longer holds: a live call — a recast continuity
6340
+ // review, ~3k tokens, `reasoning.effort: high`, `text.format: json_schema`
6341
+ // — came back `500 {"error":{"type":"server_error"}}` / "Server exception,
6342
+ // please try again later". Same endpoint family, same dialect and the same
6343
+ // signature astra was measured on (12 calls: non-stream 2/6, streaming
6344
+ // 5/6; a schema-less non-stream call 500'd too, so the lane is the trigger
6345
+ // and not the schema). ONE sighting here rather than a fresh 12-call probe
6346
+ // — the precedent is strong and the flag is cheap to reverse.
6347
+ //
6348
+ // THE COST: SSE does not reliably carry `credits_consumed`, so this model's
6349
+ // provider cost becomes the rate-table estimate instead of the billed
6350
+ // figure. That is the price of a lane that answers, and it is the same
6351
+ // trade astra already makes.
6352
+ kieCollapseStream: true
6157
6353
  },
6158
6354
  {
6159
6355
  id: "gpt-6-astra",
@@ -6348,6 +6544,10 @@ var LLM_FEATURE_DEFAULTS = {
6348
6544
  "3d-title": "claude-sonnet-4.6",
6349
6545
  "3d-scene": "claude-sonnet-4.6",
6350
6546
  "image-to-text": "claude-sonnet-4.6",
6547
+ // Economy on purpose: the analysis reads ONE frame + the copy per ad and
6548
+ // runs once per returned ad — volume, not depth. Must stay an image-capable
6549
+ // structured-output model (STRUCTURED_VISION_MODELS); a registry test pins it.
6550
+ "meta-ads-analysis": "gemini-3.6-flash",
6351
6551
  "describe-to-picker": "claude-opus-5",
6352
6552
  "qa-check": "gemini-3.6-flash",
6353
6553
  "generate-script": "gemini-3.6-flash",
@@ -6668,10 +6868,10 @@ function fieldRef(field) {
6668
6868
  return BARE_IDENT.test(field) ? `.${field}` : `.["${escapeString(field)}"]`;
6669
6869
  }
6670
6870
  function coerceValue(v) {
6671
- const trimmed = v.trim();
6672
- if (trimmed === "" || trimmed === "Infinity" || trimmed === "-Infinity" || trimmed === "NaN") return `"${trimmed}"`;
6673
- const n = Number(trimmed);
6674
- return Number.isFinite(n) ? String(n) : `"${escapeString(trimmed)}"`;
6871
+ const trimmed2 = v.trim();
6872
+ if (trimmed2 === "" || trimmed2 === "Infinity" || trimmed2 === "-Infinity" || trimmed2 === "NaN") return `"${trimmed2}"`;
6873
+ const n = Number(trimmed2);
6874
+ return Number.isFinite(n) ? String(n) : `"${escapeString(trimmed2)}"`;
6675
6875
  }
6676
6876
  function buildFilterExpr(f) {
6677
6877
  const ref = fieldRef(f.field);
@@ -7402,14 +7602,14 @@ function unresolvedRefTokens(text, opts) {
7402
7602
  // src/filter-condition.ts
7403
7603
  function tryParseJson(item) {
7404
7604
  if (typeof item !== "string") return item;
7405
- const trimmed = item.trim();
7406
- if (!trimmed) return item;
7407
- const first = trimmed[0];
7408
- if (first !== "{" && first !== "[" && first !== '"' && !/^-?\d/.test(trimmed) && trimmed !== "true" && trimmed !== "false" && trimmed !== "null") {
7605
+ const trimmed2 = item.trim();
7606
+ if (!trimmed2) return item;
7607
+ const first = trimmed2[0];
7608
+ if (first !== "{" && first !== "[" && first !== '"' && !/^-?\d/.test(trimmed2) && trimmed2 !== "true" && trimmed2 !== "false" && trimmed2 !== "null") {
7409
7609
  return item;
7410
7610
  }
7411
7611
  try {
7412
- return JSON.parse(trimmed);
7612
+ return JSON.parse(trimmed2);
7413
7613
  } catch {
7414
7614
  return item;
7415
7615
  }
@@ -7457,11 +7657,11 @@ function asComparableNumber(v) {
7457
7657
  if (typeof v === "number") return v;
7458
7658
  if (typeof v === "boolean") return v ? 1 : 0;
7459
7659
  if (typeof v === "string") {
7460
- const trimmed = v.trim();
7461
- if (trimmed === "") return NaN;
7462
- const n = Number(trimmed);
7660
+ const trimmed2 = v.trim();
7661
+ if (trimmed2 === "") return NaN;
7662
+ const n = Number(trimmed2);
7463
7663
  if (!isNaN(n)) return n;
7464
- const d = Date.parse(trimmed);
7664
+ const d = Date.parse(trimmed2);
7465
7665
  if (!isNaN(d)) return d;
7466
7666
  }
7467
7667
  return NaN;
@@ -7571,16 +7771,16 @@ var SCRAPER_OUTPUT_FIELDS = {
7571
7771
  // src/selector.ts
7572
7772
  function resolveIndex(expr, listLength, defaultExpr = "1") {
7573
7773
  if (listLength <= 0) return 0;
7574
- const trimmed = expr.trim();
7774
+ const trimmed2 = expr.trim();
7575
7775
  let index;
7576
- if (trimmed === "last") {
7776
+ if (trimmed2 === "last") {
7577
7777
  index = listLength - 1;
7578
- } else if (trimmed.startsWith("last-")) {
7579
- const offset = parseInt(trimmed.slice(5), 10);
7778
+ } else if (trimmed2.startsWith("last-")) {
7779
+ const offset = parseInt(trimmed2.slice(5), 10);
7580
7780
  if (isNaN(offset) || offset < 0) return resolveIndex(defaultExpr === expr ? "1" : defaultExpr, listLength);
7581
7781
  index = listLength - 1 - offset;
7582
7782
  } else {
7583
- const n = parseInt(trimmed, 10);
7783
+ const n = parseInt(trimmed2, 10);
7584
7784
  if (isNaN(n)) return resolveIndex(defaultExpr === expr ? "1" : defaultExpr, listLength);
7585
7785
  index = n - 1;
7586
7786
  }
@@ -7618,9 +7818,9 @@ function buildRangeLabel(mode, rangeFrom, rangeTo, rangeStep, itemIndex, selecto
7618
7818
  function buildItemLabel(mode, rangeFrom, rangeTo, rangeStep, itemIndex, selectorMode, listExpression) {
7619
7819
  if (mode === "last") return void 0;
7620
7820
  if ((mode === "each" || mode === "all") && selectorMode === "list") {
7621
- const trimmed = (listExpression ?? "").trim();
7622
- if (trimmed === "") return void 0;
7623
- return truncateLabel(trimmed, 18);
7821
+ const trimmed2 = (listExpression ?? "").trim();
7822
+ if (trimmed2 === "") return void 0;
7823
+ return truncateLabel(trimmed2, 18);
7624
7824
  }
7625
7825
  if (mode === "item") return itemIndex || void 0;
7626
7826
  const from = rangeFrom ?? "1";
@@ -7744,10 +7944,10 @@ function buildAllSentence(edgeData) {
7744
7944
  return `Passes ${phrase.text} at once.`;
7745
7945
  }
7746
7946
  function canonicalItemIndex(raw) {
7747
- const trimmed = (raw ?? "").trim();
7748
- if (trimmed === "") return "1";
7749
- if (!isValidIndexToken(trimmed)) return "1";
7750
- return trimmed;
7947
+ const trimmed2 = (raw ?? "").trim();
7948
+ if (trimmed2 === "") return "1";
7949
+ if (!isValidIndexToken(trimmed2)) return "1";
7950
+ return trimmed2;
7751
7951
  }
7752
7952
  function canonicalRange(edgeData) {
7753
7953
  const from = (edgeData?.rangeFrom ?? "").trim() || "1";
@@ -8138,6 +8338,83 @@ function expandItemsWithRepeat(listItems, nodeType, nodeData) {
8138
8338
  return null;
8139
8339
  }
8140
8340
 
8341
+ // src/fan-out-rows.ts
8342
+ var NON_PROMPT_TEXT_LANES = {
8343
+ negative: "*",
8344
+ "system-prompt": "*",
8345
+ script: ["ai-avatar"],
8346
+ transcript: ["add-captions", "apply-edl", "edit-plan"],
8347
+ edl: ["apply-edl"],
8348
+ silence: ["edit-plan"],
8349
+ qrText: ["image-overlay"],
8350
+ transition: ["slideshow"]
8351
+ };
8352
+ function fanOutTextFeedsPrompt(nodeType, targetHandle) {
8353
+ const scope = Object.hasOwn(NON_PROMPT_TEXT_LANES, targetHandle ?? "") ? NON_PROMPT_TEXT_LANES[targetHandle ?? ""] : void 0;
8354
+ if (scope === void 0) return true;
8355
+ return scope !== "*" && !scope.includes(nodeType ?? "");
8356
+ }
8357
+ var isBlank = (v) => typeof v !== "string" || v.trim().length === 0;
8358
+ function compactWithRows(aligned) {
8359
+ const items = [];
8360
+ const rowIndices = [];
8361
+ aligned.forEach((value, row) => {
8362
+ if (isBlank(value)) return;
8363
+ items.push(value);
8364
+ rowIndices.push(row);
8365
+ });
8366
+ return { items, rowIndices };
8367
+ }
8368
+ function liveRowColumn(rows, colIndex) {
8369
+ return rows.filter((row) => row.some((cell) => !isBlank(cell))).map((row) => typeof row[colIndex] === "string" ? row[colIndex].trim() : "");
8370
+ }
8371
+ function resolveListFanOut(candidates, nodeType) {
8372
+ if (candidates.length === 0) return void 0;
8373
+ const held = (c) => compactWithRows(c.aligned).items.length;
8374
+ const primary = candidates.reduce((best, c) => held(c) > held(best) ? c : best);
8375
+ const space = candidates.filter((c) => c.aligned.length === primary.aligned.length);
8376
+ const feedsPrompt = (c) => fanOutTextFeedsPrompt(nodeType, c.targetHandle) && isTextList(c.aligned);
8377
+ const driver = feedsPrompt(primary) ? primary : space.find(feedsPrompt) ?? primary;
8378
+ const rowIndices = [];
8379
+ for (let row = 0; row < primary.aligned.length; row++) {
8380
+ if (space.some((c) => !isBlank(c.aligned[row]))) rowIndices.push(row);
8381
+ }
8382
+ return {
8383
+ items: rowIndices.map((row) => isBlank(driver.aligned[row]) ? "" : driver.aligned[row]),
8384
+ rowIndices,
8385
+ targetHandle: driver.targetHandle
8386
+ };
8387
+ }
8388
+ function isFanOutUrlItem(item) {
8389
+ return item.startsWith("http") || /\.(png|jpg|jpeg|webp|gif|mp4|mov|webm|mp3|wav|ogg)(\?|$)/i.test(item);
8390
+ }
8391
+ function isTextList(aligned) {
8392
+ const first = aligned.find((v) => !isBlank(v));
8393
+ return first !== void 0 && !isFanOutUrlItem(first);
8394
+ }
8395
+ function planFanOut(fanOut, nodeType, nodeData) {
8396
+ const items = expandItemsWithRepeat(fanOut?.items, nodeType, nodeData);
8397
+ if (!items) return null;
8398
+ const listDriven = fanOut !== void 0 && fanOut.items.length > 1;
8399
+ if (!listDriven) return { items, rows: items.map(() => void 0), targetHandle: void 0 };
8400
+ const perRow = items.length / fanOut.items.length;
8401
+ return {
8402
+ items,
8403
+ rows: items.map((_, k) => fanOut.rowIndices[Math.floor(k / perRow)]),
8404
+ targetHandle: fanOut.targetHandle
8405
+ };
8406
+ }
8407
+ function alignedFieldList(value, path) {
8408
+ if (!Array.isArray(value) || value.length === 0) return void 0;
8409
+ const out = [];
8410
+ for (const element of value) {
8411
+ const found = evaluateJsonPath(element, path);
8412
+ if (found.length > 1) return void 0;
8413
+ out.push(stringifyPathResults(found)[0] ?? "");
8414
+ }
8415
+ return out.some((v) => v.length > 0) ? out : void 0;
8416
+ }
8417
+
8141
8418
  // src/settled-with-limit.ts
8142
8419
  async function settledWithLimit(tasks, limit, cancelledRef) {
8143
8420
  const results = new Array(tasks.length);
@@ -8720,8 +8997,8 @@ function splitByLoopDelimiter(text, columns) {
8720
8997
  const firstTextCol = (columns ?? []).find((c) => (c.type ?? "text") === "text");
8721
8998
  const raw = firstTextCol?.splitDelimiter;
8722
8999
  if (raw === NO_SPLIT_DELIMITER) {
8723
- const trimmed = text.trim();
8724
- return trimmed.length > 0 ? [trimmed] : [];
9000
+ const trimmed2 = text.trim();
9001
+ return trimmed2.length > 0 ? [trimmed2] : [];
8725
9002
  }
8726
9003
  const delimiter = raw ?? "\n";
8727
9004
  return text.split(delimiter).map((s) => s.trim()).filter((s) => s.length > 0);
@@ -8756,8 +9033,8 @@ function splitGeneratedItems(text) {
8756
9033
  if (!text) return [];
8757
9034
  const parts = text.split(GENERATE_TEXT_DELIMITER).map((s) => s.trim()).filter(Boolean);
8758
9035
  if (parts.length > 0) return parts;
8759
- const trimmed = text.trim();
8760
- return trimmed ? [trimmed] : [];
9036
+ const trimmed2 = text.trim();
9037
+ return trimmed2 ? [trimmed2] : [];
8761
9038
  }
8762
9039
 
8763
9040
  // src/text-separators.ts
@@ -8814,9 +9091,9 @@ function toNumberKey(v) {
8814
9091
  if (typeof v === "number") return Number.isFinite(v) ? v : void 0;
8815
9092
  if (typeof v === "boolean") return v ? 1 : 0;
8816
9093
  if (typeof v === "string") {
8817
- const trimmed = v.trim();
8818
- if (trimmed === "") return void 0;
8819
- const n = Number(trimmed);
9094
+ const trimmed2 = v.trim();
9095
+ if (trimmed2 === "") return void 0;
9096
+ const n = Number(trimmed2);
8820
9097
  return Number.isFinite(n) ? n : void 0;
8821
9098
  }
8822
9099
  return void 0;
@@ -9277,13 +9554,341 @@ var NODE_MAPPABLE_FIELDS = {
9277
9554
  "object": ["objectName", "description"],
9278
9555
  "creature": ["creatureName", "description"],
9279
9556
  "location": ["locationName", "description"],
9280
- "web-scrape": ["query", "url", "target"]
9557
+ "web-scrape": ["query", "url", "target"],
9558
+ "meta-ads-scrape": ["query", "pageUrls"],
9559
+ "instagram-scrape": ["targets"]
9281
9560
  };
9282
9561
  var SUNO_FIELD_HANDLE_FIELDS = ["style", "lyrics", "title", "negativeStyle"];
9283
9562
  function fieldKeyFromHandle(handleId) {
9284
9563
  return handleId.startsWith("field-") ? handleId.slice("field-".length) : null;
9285
9564
  }
9286
9565
 
9566
+ // src/trigger-node-types.ts
9567
+ var SCHEDULE_TRIGGER_NODE_TYPE = "schedule-trigger";
9568
+ var WEBHOOK_TRIGGER_NODE_TYPE = "webhook-trigger";
9569
+ var TELEGRAM_TRIGGER_NODE_TYPE = "telegram-trigger";
9570
+ var PROJECTED_TRIGGER_NODE_TYPES = /* @__PURE__ */ new Set([
9571
+ SCHEDULE_TRIGGER_NODE_TYPE,
9572
+ WEBHOOK_TRIGGER_NODE_TYPE,
9573
+ TELEGRAM_TRIGGER_NODE_TYPE
9574
+ ]);
9575
+ function isProjectedTriggerNodeType(type) {
9576
+ return typeof type === "string" && PROJECTED_TRIGGER_NODE_TYPES.has(type);
9577
+ }
9578
+
9579
+ // src/trigger-feeds.ts
9580
+ function buildFeedMaps(nodes, edges) {
9581
+ const live = new Set(nodes.map((n) => n.id));
9582
+ const children = /* @__PURE__ */ new Map();
9583
+ const parents = /* @__PURE__ */ new Map();
9584
+ const feeds = (source, target) => {
9585
+ if (!live.has(source) || !live.has(target) || source === target) return;
9586
+ children.set(source, [...children.get(source) ?? [], target]);
9587
+ parents.set(target, [...parents.get(target) ?? [], source]);
9588
+ };
9589
+ for (const edge of edges) feeds(edge.source, edge.target);
9590
+ for (const n of nodes) {
9591
+ if (typeof n.parentId === "string" && n.parentId) feeds(n.id, n.parentId);
9592
+ const mappings = n.data?.fieldMappings;
9593
+ if (mappings && typeof mappings === "object") {
9594
+ for (const mapping of Object.values(mappings)) {
9595
+ const sourceNodeId = mapping?.sourceNodeId;
9596
+ if (typeof sourceNodeId === "string" && sourceNodeId) feeds(sourceNodeId, n.id);
9597
+ }
9598
+ }
9599
+ }
9600
+ return { children, parents };
9601
+ }
9602
+ function nodeFeedsAnything(nodes, edges, nodeId) {
9603
+ return (buildFeedMaps(nodes, edges).children.get(nodeId) ?? []).length > 0;
9604
+ }
9605
+
9606
+ // src/schedule-rules.ts
9607
+ var SCHEDULE_RULE_KINDS = ["minutes", "hours", "days", "weeks", "months", "cron"];
9608
+ var SCHEDULE_EVERY_LIMITS = {
9609
+ minutes: [1, 59],
9610
+ hours: [1, 23],
9611
+ days: [1, 31],
9612
+ weeks: [1, 52],
9613
+ months: [1, 12]
9614
+ };
9615
+ function int(value) {
9616
+ if (typeof value === "number" && Number.isFinite(value)) return Math.trunc(value);
9617
+ if (typeof value === "string" && /^-?\d+$/.test(value.trim())) return parseInt(value.trim(), 10);
9618
+ return null;
9619
+ }
9620
+ function clamp(value, lo, hi, fallback) {
9621
+ if (value === null) return fallback;
9622
+ return Math.min(hi, Math.max(lo, value));
9623
+ }
9624
+ function positiveInt(value) {
9625
+ const n = int(value);
9626
+ return n !== null && n >= 1 ? n : null;
9627
+ }
9628
+ function isCronExpression(value) {
9629
+ return typeof value === "string" && value.trim().split(/\s+/).filter(Boolean).length === 5;
9630
+ }
9631
+ function normalizeScheduleRule(raw, fallbackId = "rule-1") {
9632
+ if (!raw || typeof raw !== "object") return null;
9633
+ const r = raw;
9634
+ if (typeof r.kind !== "string" || !SCHEDULE_RULE_KINDS.includes(r.kind)) return null;
9635
+ const kind = r.kind;
9636
+ const id = typeof r.id === "string" && r.id.trim() ? r.id.trim() : fallbackId;
9637
+ const minute = clamp(int(r.minute), 0, 59, 0);
9638
+ const hour = clamp(int(r.hour), 0, 23, 0);
9639
+ switch (kind) {
9640
+ case "minutes":
9641
+ return { id, kind, every: clamp(positiveInt(r.every), ...SCHEDULE_EVERY_LIMITS.minutes, 5) };
9642
+ case "hours":
9643
+ return { id, kind, every: clamp(positiveInt(r.every), ...SCHEDULE_EVERY_LIMITS.hours, 1), minute };
9644
+ case "days":
9645
+ return { id, kind, every: clamp(positiveInt(r.every), ...SCHEDULE_EVERY_LIMITS.days, 1), hour, minute };
9646
+ case "weeks": {
9647
+ const weekdays = Array.isArray(r.weekdays) ? [...new Set(r.weekdays.map(int).filter((d) => d !== null && d >= 0 && d <= 6))].sort((a, b) => a - b) : [];
9648
+ if (weekdays.length === 0) return null;
9649
+ return { id, kind, every: clamp(positiveInt(r.every), ...SCHEDULE_EVERY_LIMITS.weeks, 1), hour, minute, weekdays };
9650
+ }
9651
+ case "months":
9652
+ return {
9653
+ id,
9654
+ kind,
9655
+ every: clamp(positiveInt(r.every), ...SCHEDULE_EVERY_LIMITS.months, 1),
9656
+ hour,
9657
+ minute,
9658
+ dayOfMonth: clamp(int(r.dayOfMonth), 1, 31, 1)
9659
+ };
9660
+ case "cron": {
9661
+ const cron = typeof r.cron === "string" ? r.cron.trim().split(/\s+/).join(" ") : "";
9662
+ return isCronExpression(cron) ? { id, kind, cron } : null;
9663
+ }
9664
+ }
9665
+ }
9666
+ function normalizeScheduleRules(raw) {
9667
+ if (!Array.isArray(raw)) return [];
9668
+ return raw.map((r, i) => normalizeScheduleRule(r, `rule-${i + 1}`)).filter((r) => r !== null);
9669
+ }
9670
+ function legacyScheduleToRules(data) {
9671
+ const interval = typeof data.interval === "string" ? data.interval.trim() : "";
9672
+ const explicit = [data.cron, data.cronExpression].find((v) => typeof v === "string" && v.trim() !== "")?.trim() ?? "";
9673
+ const m = interval.match(/^(\d+)([smhd])$/);
9674
+ if (m) {
9675
+ const n = parseInt(m[1], 10);
9676
+ if (n < 1) return [];
9677
+ switch (m[2]) {
9678
+ case "s":
9679
+ return [{ id: "rule-1", kind: "minutes", every: 1 }];
9680
+ case "m":
9681
+ return n < 60 ? [{ id: "rule-1", kind: "minutes", every: n }] : [{ id: "rule-1", kind: "hours", every: Math.min(23, Math.max(1, Math.round(n / 60))), minute: 0 }];
9682
+ case "h":
9683
+ return n < 24 ? [{ id: "rule-1", kind: "hours", every: n, minute: 0 }] : [{ id: "rule-1", kind: "days", every: Math.min(31, Math.max(1, Math.round(n / 24))), hour: 0, minute: 0 }];
9684
+ default:
9685
+ return [{ id: "rule-1", kind: "days", every: Math.min(31, n), hour: 0, minute: 0 }];
9686
+ }
9687
+ }
9688
+ const expression = interval === "" || interval === "custom" ? explicit : interval;
9689
+ if (!isCronExpression(expression)) return [];
9690
+ const fromCron = cronToRule(expression);
9691
+ return normalizeScheduleRules([fromCron ?? { id: "rule-1", kind: "cron", cron: expression.split(/\s+/).join(" ") }]);
9692
+ }
9693
+ function cronStep(field) {
9694
+ const m = field.match(/^\*\/(\d+)$/);
9695
+ if (!m) return null;
9696
+ const n = parseInt(m[1], 10);
9697
+ return n >= 1 ? n : null;
9698
+ }
9699
+ function cronToRule(expression) {
9700
+ const [min, hour, dom, month, dow] = expression.trim().split(/\s+/);
9701
+ if (month !== "*") return null;
9702
+ const minN = /^\d+$/.test(min) ? parseInt(min, 10) : null;
9703
+ const hourN = /^\d+$/.test(hour) ? parseInt(hour, 10) : null;
9704
+ const stepMin = cronStep(min);
9705
+ const stepHour = cronStep(hour);
9706
+ if (stepMin !== null && hour === "*" && dom === "*" && dow === "*") return { id: "rule-1", kind: "minutes", every: stepMin };
9707
+ if (min === "*" && hour === "*" && dom === "*" && dow === "*") return { id: "rule-1", kind: "minutes", every: 1 };
9708
+ if (minN !== null && stepHour !== null && dom === "*" && dow === "*") return { id: "rule-1", kind: "hours", every: stepHour, minute: minN };
9709
+ if (minN !== null && hour === "*" && dom === "*" && dow === "*") return { id: "rule-1", kind: "hours", every: 1, minute: minN };
9710
+ if (minN !== null && hourN !== null && dom === "*" && dow === "*") return { id: "rule-1", kind: "days", every: 1, hour: hourN, minute: minN };
9711
+ if (minN !== null && hourN !== null && dom === "*" && /^[0-6](,[0-6])*$|^[0-6]-[0-6]$/.test(dow)) {
9712
+ const weekdays = dow.includes("-") ? (() => {
9713
+ const [a, b] = dow.split("-").map(Number);
9714
+ return Array.from({ length: b - a + 1 }, (_, i) => a + i);
9715
+ })() : dow.split(",").map(Number);
9716
+ return { id: "rule-1", kind: "weeks", every: 1, hour: hourN, minute: minN, weekdays };
9717
+ }
9718
+ if (minN !== null && hourN !== null && /^\d+$/.test(dom) && dow === "*") {
9719
+ return { id: "rule-1", kind: "months", every: 1, hour: hourN, minute: minN, dayOfMonth: parseInt(dom, 10) };
9720
+ }
9721
+ return null;
9722
+ }
9723
+ var formatters = /* @__PURE__ */ new Map();
9724
+ var canonicalZone = /* @__PURE__ */ new Map();
9725
+ var MAX_ZONE_SPELLINGS = 1024;
9726
+ function formatterFor(timezone) {
9727
+ const spelled = timezone && timezone.trim() ? timezone.trim() : "UTC";
9728
+ const known = canonicalZone.get(spelled);
9729
+ if (known) return formatters.get(known) ?? null;
9730
+ try {
9731
+ const fmt = new Intl.DateTimeFormat("en-US", {
9732
+ timeZone: spelled,
9733
+ hourCycle: "h23",
9734
+ year: "numeric",
9735
+ month: "2-digit",
9736
+ day: "2-digit",
9737
+ hour: "2-digit",
9738
+ minute: "2-digit"
9739
+ });
9740
+ const canonical = fmt.resolvedOptions().timeZone;
9741
+ if (!formatters.has(canonical)) formatters.set(canonical, fmt);
9742
+ if (canonicalZone.size >= MAX_ZONE_SPELLINGS) canonicalZone.clear();
9743
+ canonicalZone.set(spelled, canonical);
9744
+ return formatters.get(canonical) ?? fmt;
9745
+ } catch {
9746
+ return null;
9747
+ }
9748
+ }
9749
+ function isValidTimezone(value) {
9750
+ return typeof value === "string" && value.trim() !== "" && formatterFor(value) !== null;
9751
+ }
9752
+ function localMinuteKey(local) {
9753
+ return `${local.epochDay}:${local.hour}:${local.minute}`;
9754
+ }
9755
+ function localFromComponents(year, month, day, hour, minute) {
9756
+ const epochDay = Math.floor(Date.UTC(year, month - 1, day) / 864e5);
9757
+ const weekday = (epochDay % 7 + 7 + 4) % 7;
9758
+ return { year, month, day, hour: hour === 24 ? 0 : hour, minute, weekday, epochDay };
9759
+ }
9760
+ function localTimeIn(date, timezone) {
9761
+ const fmt = formatterFor(timezone);
9762
+ if (!fmt) return localFromComponents(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes());
9763
+ const parts = {};
9764
+ for (const p of fmt.formatToParts(date)) {
9765
+ if (p.type === "literal") continue;
9766
+ parts[p.type] = parseInt(p.value, 10);
9767
+ }
9768
+ return localFromComponents(parts.year, parts.month, parts.day, parts.hour, parts.minute);
9769
+ }
9770
+ function timezoneOffsetMinutes(date, timezone) {
9771
+ const local = localTimeIn(date, timezone);
9772
+ const asUtc = Date.UTC(local.year, local.month - 1, local.day, local.hour, local.minute);
9773
+ const truncated = Math.floor(date.getTime() / 6e4) * 6e4;
9774
+ return Math.round((asUtc - truncated) / 6e4);
9775
+ }
9776
+ function daysInMonth(year, month) {
9777
+ return new Date(Date.UTC(year, month, 0)).getUTCDate();
9778
+ }
9779
+ function matchesCronField(field, value, min, max) {
9780
+ if (field === "*") return true;
9781
+ if (field.includes(",")) return field.split(",").some((part) => matchesCronField(part.trim(), value, min, max));
9782
+ if (field.includes("/")) {
9783
+ const [range, step] = field.split("/");
9784
+ const stepNum = parseInt(step, 10);
9785
+ if (Number.isNaN(stepNum) || stepNum <= 0) return false;
9786
+ if (range === "*") return value % stepNum === 0;
9787
+ if (range.includes("-")) {
9788
+ const [start2, end] = parseRange(range);
9789
+ if (start2 === null || end === null) return false;
9790
+ return value >= start2 && value <= end && (value - start2) % stepNum === 0;
9791
+ }
9792
+ const start = parseInt(range, 10);
9793
+ if (Number.isNaN(start)) return false;
9794
+ return value >= start && value <= max && (value - start) % stepNum === 0;
9795
+ }
9796
+ if (field.includes("-")) {
9797
+ const [start, end] = parseRange(field);
9798
+ if (start === null || end === null) return false;
9799
+ return value >= start && value <= end;
9800
+ }
9801
+ const num2 = parseInt(field, 10);
9802
+ return !Number.isNaN(num2) && num2 === value;
9803
+ }
9804
+ function parseRange(range) {
9805
+ const parts = range.split("-");
9806
+ if (parts.length !== 2) return [null, null];
9807
+ const start = parseInt(parts[0], 10);
9808
+ const end = parseInt(parts[1], 10);
9809
+ return [Number.isNaN(start) ? null : start, Number.isNaN(end) ? null : end];
9810
+ }
9811
+ function matchesCron(expression, local) {
9812
+ const fields = expression.trim().split(/\s+/);
9813
+ if (fields.length !== 5) return false;
9814
+ return matchesCronField(fields[0], local.minute, 0, 59) && matchesCronField(fields[1], local.hour, 0, 23) && matchesCronField(fields[2], local.day, 1, 31) && matchesCronField(fields[3], local.month, 1, 12) && (matchesCronField(fields[4], local.weekday, 0, 6) || local.weekday === 0 && matchesCronField(fields[4], 7, 0, 7));
9815
+ }
9816
+ function ruleMatches(rule, local) {
9817
+ const every = Math.max(1, rule.every ?? 1);
9818
+ const minute = rule.minute ?? 0;
9819
+ const hour = rule.hour ?? 0;
9820
+ switch (rule.kind) {
9821
+ case "minutes":
9822
+ return local.minute % every === 0;
9823
+ case "hours":
9824
+ return local.minute === minute && local.hour % every === 0;
9825
+ case "days":
9826
+ return local.minute === minute && local.hour === hour && local.epochDay % every === 0;
9827
+ case "weeks": {
9828
+ const weekIndex = Math.floor((local.epochDay + 3) / 7);
9829
+ return local.minute === minute && local.hour === hour && (rule.weekdays ?? []).includes(local.weekday) && weekIndex % every === 0;
9830
+ }
9831
+ case "months": {
9832
+ const wanted = Math.min(rule.dayOfMonth ?? 1, daysInMonth(local.year, local.month));
9833
+ const monthIndex = local.year * 12 + (local.month - 1);
9834
+ return local.minute === minute && local.hour === hour && local.day === wanted && monthIndex % every === 0;
9835
+ }
9836
+ case "cron":
9837
+ return typeof rule.cron === "string" && matchesCron(rule.cron, local);
9838
+ }
9839
+ }
9840
+ function scheduleMatchesAt(spec, at) {
9841
+ if (spec.rules.length === 0) return false;
9842
+ const local = localTimeIn(at, spec.timezone);
9843
+ return spec.rules.some((rule) => ruleMatches(rule, local));
9844
+ }
9845
+ var OFFSET_SLOT_MS = 15 * 6e4;
9846
+ function scheduleOccurrences(spec, from, until, cap) {
9847
+ const out = [];
9848
+ if (spec.rules.length === 0 || cap <= 0) return out;
9849
+ const rules = spec.rules;
9850
+ let t2 = Math.ceil(from.getTime() / 6e4) * 6e4;
9851
+ const end = until.getTime();
9852
+ let slot = -1;
9853
+ let offset = 0;
9854
+ let lastKey = "";
9855
+ while (t2 <= end && out.length < cap) {
9856
+ const thisSlot = Math.floor(t2 / OFFSET_SLOT_MS);
9857
+ if (thisSlot !== slot) {
9858
+ slot = thisSlot;
9859
+ offset = timezoneOffsetMinutes(new Date(t2), spec.timezone);
9860
+ }
9861
+ const shifted = new Date(t2 + offset * 6e4);
9862
+ const local = localFromComponents(
9863
+ shifted.getUTCFullYear(),
9864
+ shifted.getUTCMonth() + 1,
9865
+ shifted.getUTCDate(),
9866
+ shifted.getUTCHours(),
9867
+ shifted.getUTCMinutes()
9868
+ );
9869
+ if (rules.some((rule) => ruleMatches(rule, local))) {
9870
+ const key = localMinuteKey(local);
9871
+ if (key !== lastKey) out.push(new Date(t2));
9872
+ lastKey = key;
9873
+ }
9874
+ t2 += 6e4;
9875
+ }
9876
+ return out;
9877
+ }
9878
+ var DAY_MS2 = 864e5;
9879
+ function previewHorizonMs(rules) {
9880
+ let longest = 0;
9881
+ for (const rule of rules) {
9882
+ const every = Math.max(1, rule.every ?? 1);
9883
+ const period = rule.kind === "days" ? every * DAY_MS2 : rule.kind === "weeks" ? every * 7 * DAY_MS2 : rule.kind === "months" ? every * 31 * DAY_MS2 : rule.kind === "cron" ? 366 * DAY_MS2 : DAY_MS2;
9884
+ if (period > longest) longest = period;
9885
+ }
9886
+ return Math.min(800 * DAY_MS2, Math.max(62 * DAY_MS2, longest * 2 + DAY_MS2));
9887
+ }
9888
+ function nextScheduleRuns(spec, from, count, horizonMs = previewHorizonMs(spec.rules)) {
9889
+ return scheduleOccurrences(spec, new Date(from.getTime() + 1), new Date(from.getTime() + horizonMs), count);
9890
+ }
9891
+
9287
9892
  // src/scraper-actors.ts
9288
9893
  var SCRAPER_ACTOR_IDS = [
9289
9894
  "content-crawler",
@@ -9325,6 +9930,338 @@ function resolveScraperCreditId(body) {
9325
9930
  return buildScraperCreditId({ actor: raw.actor, mode });
9326
9931
  }
9327
9932
 
9933
+ // src/meta-ads-scrape.ts
9934
+ var META_ADS_SCRAPE_NODE_TYPE = "meta-ads-scrape";
9935
+ var META_ADS_SCRAPE_MODES = ["search", "pages"];
9936
+ var META_ADS_NODE_MODES = [...META_ADS_SCRAPE_MODES, "advertiser"];
9937
+ function metaAdsNodeMode(value) {
9938
+ return typeof value === "string" && META_ADS_NODE_MODES.includes(value) ? value : "search";
9939
+ }
9940
+ var META_ADS_ADVERTISER_MAX_RESULTS = 8;
9941
+ var META_ADS_URL_MAX_LENGTH = 2048;
9942
+ function httpUrlOnHost(value, host) {
9943
+ if (typeof value !== "string" || value.length > META_ADS_URL_MAX_LENGTH) return false;
9944
+ try {
9945
+ const url = new URL(value);
9946
+ return (url.protocol === "https:" || url.protocol === "http:") && host.test(url.hostname);
9947
+ } catch {
9948
+ return false;
9949
+ }
9950
+ }
9951
+ function isFacebookPageUrl(value) {
9952
+ return httpUrlOnHost(value, /(^|\.)facebook\.com$/i);
9953
+ }
9954
+ function isMetaCdnImageUrl(value) {
9955
+ return httpUrlOnHost(value, /(^|\.)(fbcdn\.net|facebook\.com)$/i);
9956
+ }
9957
+ function metaAdsAdvertisersFrom(raw, limit = META_ADS_SCRAPE_MAX_SOURCES) {
9958
+ if (!Array.isArray(raw) || limit < 1) return [];
9959
+ const seen = /* @__PURE__ */ new Set();
9960
+ const out = [];
9961
+ for (const item of raw) {
9962
+ if (!item || typeof item !== "object") continue;
9963
+ const r = item;
9964
+ const pageId = typeof r.pageId === "string" ? r.pageId.trim() : typeof r.pageId === "number" && Number.isFinite(r.pageId) ? String(r.pageId) : "";
9965
+ const name = typeof r.name === "string" ? r.name.trim().slice(0, 120) : "";
9966
+ if (!pageId || !name || !isFacebookPageUrl(r.url) || seen.has(pageId)) continue;
9967
+ seen.add(pageId);
9968
+ out.push({
9969
+ pageId,
9970
+ name,
9971
+ url: r.url,
9972
+ ...isMetaCdnImageUrl(r.imageUrl) ? { imageUrl: r.imageUrl } : {},
9973
+ ...r.verified === true ? { verified: true } : {}
9974
+ });
9975
+ if (out.length >= limit) break;
9976
+ }
9977
+ return out;
9978
+ }
9979
+ var META_ADS_SCRAPE_PERIODS = ["24h", "7d", "30d", "all"];
9980
+ var META_ADS_SCRAPE_STATUSES = ["active", "inactive", "all"];
9981
+ var META_ADS_PLATFORMS = ["FACEBOOK", "INSTAGRAM", "AUDIENCE_NETWORK", "MESSENGER", "WHATSAPP", "THREADS"];
9982
+ function isMetaAdsPlatform(value) {
9983
+ return typeof value === "string" && META_ADS_PLATFORMS.includes(value);
9984
+ }
9985
+ var META_ADS_FORMATS = ["vertical", "square", "horizontal"];
9986
+ function isMetaAdsFormat(value) {
9987
+ return typeof value === "string" && META_ADS_FORMATS.includes(value);
9988
+ }
9989
+ function clampMetaAdsFeaturedIndex(stored, count) {
9990
+ if (count <= 0) return 0;
9991
+ const n = typeof stored === "number" && Number.isFinite(stored) ? Math.trunc(stored) : 0;
9992
+ return Math.min(Math.max(n, 0), count - 1);
9993
+ }
9994
+ function urlStrings(value) {
9995
+ return Array.isArray(value) ? value.filter((v) => typeof v === "string" && v.trim().length > 0) : [];
9996
+ }
9997
+ function featuredMetaAdOutputs(json, featuredIndex) {
9998
+ if (!Array.isArray(json) || json.length === 0) return {};
9999
+ const ad = json[clampMetaAdsFeaturedIndex(featuredIndex, json.length)];
10000
+ if (!ad || typeof ad !== "object") return {};
10001
+ const a = ad;
10002
+ const title = typeof a.title === "string" ? a.title.trim() : "";
10003
+ const body = typeof a.text === "string" ? a.text.trim() : "";
10004
+ const text = [title, body].filter((s) => s.length > 0).join("\n\n");
10005
+ const imageUrl = urlStrings(a.images)[0] ?? urlStrings(a.videoPreviews)[0];
10006
+ const videoUrl = urlStrings(a.videos)[0];
10007
+ return {
10008
+ ...text ? { text } : {},
10009
+ ...imageUrl ? { imageUrl } : {},
10010
+ ...videoUrl ? { videoUrl } : {}
10011
+ };
10012
+ }
10013
+ function classifyCreativeFormat(width, height) {
10014
+ if (typeof width !== "number" || typeof height !== "number" || !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
10015
+ return "unknown";
10016
+ }
10017
+ const ratio = width / height;
10018
+ if (ratio < 0.95) return "vertical";
10019
+ if (ratio <= 1.05) return "square";
10020
+ return "horizontal";
10021
+ }
10022
+ var META_ADS_SCRAPE_COUNT_OPTIONS = [10, 20, 50, 100];
10023
+ var META_ADS_SCRAPE_DEFAULT_COUNT = 20;
10024
+ var META_ADS_SCRAPE_MAX_COUNT = 100;
10025
+ var META_ADS_SCRAPE_MAX_SOURCES = 5;
10026
+ var META_ADS_SCRAPE_MAX_QUERY_LENGTH = 100;
10027
+ var META_ADS_SCRAPE_DEFAULT_COUNTRY = "ALL";
10028
+ var META_ADS_SCRAPE_TIERS = [10, 20, 50, 100, 200, 500];
10029
+ var META_ADS_ANALYSIS_TIERS = ["economy", "standard", "premium"];
10030
+ var META_ADS_ANALYSIS_CREDITS_PER_AD = { economy: 1, standard: 3, premium: 4 };
10031
+ var META_ADS_ANALYSIS_CREDIT_ID = "meta-ads-analysis";
10032
+ var META_ADS_ANALYSIS_FOCUS_MAX = 500;
10033
+ function metaAdsAnalysisCreditId(tier) {
10034
+ return tier === "standard" ? META_ADS_ANALYSIS_CREDIT_ID : `${META_ADS_ANALYSIS_CREDIT_ID}:${tier}`;
10035
+ }
10036
+ function metaAdsAnalysisTier(modelId) {
10037
+ const id = typeof modelId === "string" && modelId ? modelId : LLM_FEATURE_DEFAULTS["meta-ads-analysis"];
10038
+ return getLlmTier(id);
10039
+ }
10040
+ var strList = (v) => Array.isArray(v) ? v.filter((s) => typeof s === "string" && s.trim().length > 0) : [];
10041
+ var str = (v) => typeof v === "string" ? v : "";
10042
+ function adCreativeAnalysisFrom(raw) {
10043
+ if (!raw || typeof raw !== "object") return null;
10044
+ const r = raw;
10045
+ if (typeof r.summary !== "string" || !r.summary.trim()) return null;
10046
+ const assetType = r.assetType === "static" || r.assetType === "motion" || r.assetType === "carousel" ? r.assetType : "unknown";
10047
+ return {
10048
+ assetType,
10049
+ format: str(r.format),
10050
+ visualHooks: strList(r.visualHooks),
10051
+ audiences: strList(r.audiences),
10052
+ graphicIdentity: str(r.graphicIdentity),
10053
+ copywritingHooks: strList(r.copywritingHooks),
10054
+ usps: strList(r.usps),
10055
+ cta: str(r.cta),
10056
+ summary: r.summary
10057
+ };
10058
+ }
10059
+ function analysisSuffix(tier) {
10060
+ return tier === "standard" ? ":analysis" : `:analysis:${tier}`;
10061
+ }
10062
+ function buildMetaAdsCreditCostTable() {
10063
+ const table = { [META_ADS_SCRAPE_NODE_TYPE]: 20 };
10064
+ for (const tier of META_ADS_ANALYSIS_TIERS) table[metaAdsAnalysisCreditId(tier)] = META_ADS_ANALYSIS_CREDITS_PER_AD[tier];
10065
+ for (const t2 of META_ADS_SCRAPE_TIERS) {
10066
+ table[`${META_ADS_SCRAPE_NODE_TYPE}:${t2}`] = t2;
10067
+ for (const tier of META_ADS_ANALYSIS_TIERS) {
10068
+ table[`${META_ADS_SCRAPE_NODE_TYPE}:${t2}${analysisSuffix(tier)}`] = t2 * (1 + META_ADS_ANALYSIS_CREDITS_PER_AD[tier]);
10069
+ }
10070
+ }
10071
+ return table;
10072
+ }
10073
+ var META_ADS_SCRAPE_CREDIT_COSTS = buildMetaAdsCreditCostTable();
10074
+ var META_ADS_SCRAPE_FALLBACK_CREDIT_ID = "meta-ads-scrape:20";
10075
+ function splitMetaAdsPageUrls(value) {
10076
+ if (Array.isArray(value)) {
10077
+ return value.filter((v) => typeof v === "string").map((v) => v.trim()).filter((v) => v.length > 0);
10078
+ }
10079
+ if (typeof value !== "string") return [];
10080
+ return value.split(/[\n,\s]+/).map((v) => v.trim()).filter((v) => v.length > 0);
10081
+ }
10082
+ function isMetaAdsScrapeMode(value) {
10083
+ return typeof value === "string" && META_ADS_SCRAPE_MODES.includes(value);
10084
+ }
10085
+ function splitMetaAdsAdvertiserNames(value) {
10086
+ const raw = Array.isArray(value) ? value.filter((v) => typeof v === "string") : typeof value === "string" ? value.split(/[\n,]+/) : [];
10087
+ const seen = /* @__PURE__ */ new Set();
10088
+ const out = [];
10089
+ for (const item of raw) {
10090
+ const name = item.trim();
10091
+ if (name.length < 2 || name.length > META_ADS_SCRAPE_MAX_QUERY_LENGTH) continue;
10092
+ const key = name.toLowerCase();
10093
+ if (seen.has(key)) continue;
10094
+ seen.add(key);
10095
+ out.push(name);
10096
+ if (out.length >= META_ADS_SCRAPE_MAX_SOURCES) break;
10097
+ }
10098
+ return out;
10099
+ }
10100
+ function metaAdsScrapeSources(data) {
10101
+ switch (metaAdsNodeMode(data.mode)) {
10102
+ case "pages":
10103
+ return Math.max(1, Math.min(splitMetaAdsPageUrls(data.pageUrls).length, META_ADS_SCRAPE_MAX_SOURCES));
10104
+ case "advertiser":
10105
+ return Math.max(1, metaAdsAdvertisersFrom(data.advertisers).length);
10106
+ default:
10107
+ return 1;
10108
+ }
10109
+ }
10110
+ function metaAdsScrapeWireSources(data, upstream) {
10111
+ const upstreamText = typeof upstream === "string" ? upstream : void 0;
10112
+ switch (metaAdsNodeMode(data.mode)) {
10113
+ case "pages": {
10114
+ const own = splitMetaAdsPageUrls(data.pageUrls);
10115
+ return { mode: "pages", pageUrls: own.length > 0 ? own : splitMetaAdsPageUrls(upstreamText) };
10116
+ }
10117
+ case "advertiser": {
10118
+ const picks = metaAdsAdvertisersFrom(data.advertisers);
10119
+ if (picks.length > 0) return { mode: "pages", pageUrls: picks.map((a) => a.url) };
10120
+ const names = splitMetaAdsAdvertiserNames(upstreamText);
10121
+ return { mode: "pages", pageUrls: [], advertiserNames: names };
10122
+ }
10123
+ default: {
10124
+ const own = typeof data.query === "string" ? data.query : "";
10125
+ return { mode: "search", query: own || upstreamText };
10126
+ }
10127
+ }
10128
+ }
10129
+ function isMetaAdsScrapeCount(value) {
10130
+ return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= META_ADS_SCRAPE_MAX_COUNT;
10131
+ }
10132
+ function metaAdsScrapeTier(requestedTotal) {
10133
+ for (const tier of META_ADS_SCRAPE_TIERS) {
10134
+ if (requestedTotal <= tier) return tier;
10135
+ }
10136
+ return META_ADS_SCRAPE_TIERS[META_ADS_SCRAPE_TIERS.length - 1];
10137
+ }
10138
+ function buildMetaAdsScrapeCreditId(input) {
10139
+ const sources = Math.min(Math.max(Math.trunc(input.sources) || 1, 1), META_ADS_SCRAPE_MAX_SOURCES);
10140
+ const count = Math.min(Math.max(Math.trunc(input.count) || 1, 1), META_ADS_SCRAPE_MAX_COUNT);
10141
+ const base = `${META_ADS_SCRAPE_NODE_TYPE}:${metaAdsScrapeTier(count * sources)}`;
10142
+ return input.analysis ? `${base}${analysisSuffix(input.analysis)}` : base;
10143
+ }
10144
+ function metaAdsAnalysisTierFrom(data) {
10145
+ return data.analyze === true ? metaAdsAnalysisTier(data.analysisModel) : null;
10146
+ }
10147
+ function resolveMetaAdsScrapeCreditId(body) {
10148
+ const raw = body;
10149
+ if (!raw || typeof raw !== "object") return META_ADS_SCRAPE_FALLBACK_CREDIT_ID;
10150
+ const count = raw.count === void 0 ? META_ADS_SCRAPE_DEFAULT_COUNT : raw.count;
10151
+ if (!isMetaAdsScrapeCount(count)) return META_ADS_SCRAPE_FALLBACK_CREDIT_ID;
10152
+ const sources = raw.mode === "pages" ? (Array.isArray(raw.pageUrls) ? raw.pageUrls.length : 0) + (Array.isArray(raw.advertiserNames) ? raw.advertiserNames.length : 0) : 1;
10153
+ if (sources < 1 || sources > META_ADS_SCRAPE_MAX_SOURCES) return META_ADS_SCRAPE_FALLBACK_CREDIT_ID;
10154
+ return buildMetaAdsScrapeCreditId({ count, sources, analysis: metaAdsAnalysisTierFrom(raw) });
10155
+ }
10156
+ function metaAdsScrapeCreditIdFromNode(data) {
10157
+ const count = typeof data.count === "number" ? data.count : META_ADS_SCRAPE_DEFAULT_COUNT;
10158
+ return buildMetaAdsScrapeCreditId({ count, sources: metaAdsScrapeSources(data), analysis: metaAdsAnalysisTierFrom(data) });
10159
+ }
10160
+
10161
+ // src/instagram-scrape.ts
10162
+ var INSTAGRAM_SCRAPE_NODE_TYPE = "instagram-scrape";
10163
+ var INSTAGRAM_SCRAPE_MODES = ["profile", "hashtag"];
10164
+ function isInstagramScrapeMode(value) {
10165
+ return typeof value === "string" && INSTAGRAM_SCRAPE_MODES.includes(value);
10166
+ }
10167
+ function instagramScrapeMode(value) {
10168
+ return isInstagramScrapeMode(value) ? value : "profile";
10169
+ }
10170
+ var INSTAGRAM_SCRAPE_PERIODS = ["24h", "7d", "30d", "all"];
10171
+ var INSTAGRAM_SCRAPE_DEFAULT_COUNT = 20;
10172
+ var INSTAGRAM_SCRAPE_MAX_COUNT = 100;
10173
+ var INSTAGRAM_SCRAPE_MAX_SOURCES = 5;
10174
+ var INSTAGRAM_SCRAPE_MAX_TARGET_LENGTH = 200;
10175
+ var INSTAGRAM_SCRAPE_TIERS = [10, 20, 50, 100, 200, 500];
10176
+ function instagramScrapeTier(requestedTotal) {
10177
+ for (const tier of INSTAGRAM_SCRAPE_TIERS) if (requestedTotal <= tier) return tier;
10178
+ return INSTAGRAM_SCRAPE_TIERS[INSTAGRAM_SCRAPE_TIERS.length - 1];
10179
+ }
10180
+ function instagramAnalysisTierFrom(data) {
10181
+ return data.analyze === true ? metaAdsAnalysisTier(data.analysisModel) : null;
10182
+ }
10183
+ function analysisSuffix2(tier) {
10184
+ return tier === "standard" ? ":analysis" : `:analysis:${tier}`;
10185
+ }
10186
+ var INSTAGRAM_ANALYSIS_CREDIT_ID = "instagram-analysis";
10187
+ function instagramAnalysisCreditId(tier) {
10188
+ return tier === "standard" ? INSTAGRAM_ANALYSIS_CREDIT_ID : `${INSTAGRAM_ANALYSIS_CREDIT_ID}:${tier}`;
10189
+ }
10190
+ function buildInstagramScrapeCreditId(input) {
10191
+ const sources = Math.min(Math.max(Math.trunc(input.sources) || 1, 1), INSTAGRAM_SCRAPE_MAX_SOURCES);
10192
+ const count = Math.min(Math.max(Math.trunc(input.count) || 1, 1), INSTAGRAM_SCRAPE_MAX_COUNT);
10193
+ const base = `${INSTAGRAM_SCRAPE_NODE_TYPE}:${instagramScrapeTier(count * sources)}`;
10194
+ return input.analysis ? `${base}${analysisSuffix2(input.analysis)}` : base;
10195
+ }
10196
+ var INSTAGRAM_SCRAPE_CREDIT_COSTS = (() => {
10197
+ const table = { [INSTAGRAM_SCRAPE_NODE_TYPE]: 20 };
10198
+ for (const tier of META_ADS_ANALYSIS_TIERS) table[instagramAnalysisCreditId(tier)] = META_ADS_ANALYSIS_CREDITS_PER_AD[tier];
10199
+ for (const t2 of INSTAGRAM_SCRAPE_TIERS) {
10200
+ table[`${INSTAGRAM_SCRAPE_NODE_TYPE}:${t2}`] = t2;
10201
+ for (const tier of META_ADS_ANALYSIS_TIERS) {
10202
+ table[`${INSTAGRAM_SCRAPE_NODE_TYPE}:${t2}${analysisSuffix2(tier)}`] = t2 * (1 + META_ADS_ANALYSIS_CREDITS_PER_AD[tier]);
10203
+ }
10204
+ }
10205
+ return table;
10206
+ })();
10207
+ var INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID = "instagram-scrape:20";
10208
+ function isInstagramScrapeCount(value) {
10209
+ return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= INSTAGRAM_SCRAPE_MAX_COUNT;
10210
+ }
10211
+ function splitInstagramTargets(value) {
10212
+ const raw = Array.isArray(value) ? value.filter((v) => typeof v === "string") : typeof value === "string" ? value.split(/[\n,]+/) : [];
10213
+ const seen = /* @__PURE__ */ new Set();
10214
+ const out = [];
10215
+ for (const item of raw) {
10216
+ const t2 = item.trim().replace(/^[@#]+/, "").trim();
10217
+ if (t2.length < 1 || t2.length > INSTAGRAM_SCRAPE_MAX_TARGET_LENGTH) continue;
10218
+ const key = t2.toLowerCase();
10219
+ if (seen.has(key)) continue;
10220
+ seen.add(key);
10221
+ out.push(t2);
10222
+ if (out.length >= INSTAGRAM_SCRAPE_MAX_SOURCES) break;
10223
+ }
10224
+ return out;
10225
+ }
10226
+ function clampInstagramFeaturedIndex(stored, count) {
10227
+ if (count <= 0) return 0;
10228
+ const n = typeof stored === "number" && Number.isFinite(stored) ? Math.trunc(stored) : 0;
10229
+ return Math.min(Math.max(n, 0), count - 1);
10230
+ }
10231
+ function urlStrings2(value) {
10232
+ return Array.isArray(value) ? value.filter((v) => typeof v === "string" && v.trim().length > 0) : [];
10233
+ }
10234
+ function featuredInstagramOutputs(json, featuredIndex) {
10235
+ if (!Array.isArray(json) || json.length === 0) return {};
10236
+ const post = json[clampInstagramFeaturedIndex(featuredIndex, json.length)];
10237
+ if (!post || typeof post !== "object") return {};
10238
+ const p = post;
10239
+ const text = typeof p.caption === "string" ? p.caption.trim() : "";
10240
+ const imageUrl = urlStrings2(p.images)[0] ?? urlStrings2(p.videoPreviews)[0];
10241
+ const videoUrl = urlStrings2(p.videos)[0];
10242
+ return {
10243
+ ...text ? { text } : {},
10244
+ ...imageUrl ? { imageUrl } : {},
10245
+ ...videoUrl ? { videoUrl } : {}
10246
+ };
10247
+ }
10248
+ function instagramScrapeSources(data) {
10249
+ return Math.max(1, Math.min(splitInstagramTargets(data.targets).length, INSTAGRAM_SCRAPE_MAX_SOURCES));
10250
+ }
10251
+ function instagramScrapeCreditIdFromNode(data) {
10252
+ const count = typeof data.count === "number" ? data.count : INSTAGRAM_SCRAPE_DEFAULT_COUNT;
10253
+ return buildInstagramScrapeCreditId({ count, sources: instagramScrapeSources(data), analysis: instagramAnalysisTierFrom(data) });
10254
+ }
10255
+ function resolveInstagramScrapeCreditId(body) {
10256
+ const raw = body;
10257
+ if (!raw || typeof raw !== "object") return INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID;
10258
+ const count = raw.count === void 0 ? INSTAGRAM_SCRAPE_DEFAULT_COUNT : raw.count;
10259
+ if (!isInstagramScrapeCount(count)) return INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID;
10260
+ const sources = splitInstagramTargets(raw.targets).length;
10261
+ if (sources < 1) return INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID;
10262
+ return buildInstagramScrapeCreditId({ count, sources, analysis: instagramAnalysisTierFrom(raw) });
10263
+ }
10264
+
9328
10265
  // src/condition-variables.ts
9329
10266
  var VARIABLES_HANDLE_ID = "variables";
9330
10267
  function buildConditionVariables(targetNodeId, edges, nodes, extractOutput) {
@@ -9373,11 +10310,11 @@ function spreadJsonArrayIfSingleton(items) {
9373
10310
  if (items.length !== 1) return items;
9374
10311
  const single = items[0];
9375
10312
  if (typeof single !== "string") return items;
9376
- const trimmed = single.trim();
9377
- if (!trimmed.startsWith("[")) return items;
10313
+ const trimmed2 = single.trim();
10314
+ if (!trimmed2.startsWith("[")) return items;
9378
10315
  let parsed;
9379
10316
  try {
9380
- parsed = JSON.parse(trimmed);
10317
+ parsed = JSON.parse(trimmed2);
9381
10318
  } catch {
9382
10319
  return items;
9383
10320
  }
@@ -10633,6 +11570,127 @@ var KINETIC_SET = new Set(KINETIC_CAPTION_STYLES);
10633
11570
  function isKineticCaptionStyle(style) {
10634
11571
  return style !== null && style !== void 0 && KINETIC_SET.has(style);
10635
11572
  }
11573
+ var CAPTION_LOOK_IDS = ["outline", "clean"];
11574
+ var DEFAULT_CAPTION_LOOK = "outline";
11575
+ var DEFAULT_SUBTITLE_LOOK = "clean";
11576
+ var KINETIC_ONLY_CAPTION_LEVER_KEYS = [
11577
+ "highlightColor",
11578
+ "animate"
11579
+ ];
11580
+ function captionRoutesToRemotion(input) {
11581
+ if (input.segments && input.segments.length > 0) return true;
11582
+ if (isKineticCaptionStyle(input.style)) return true;
11583
+ const isSet = (v) => v !== void 0 && v !== null;
11584
+ const hasStylingLever = isSet(input.look) || isSet(input.fontFamily) || isSet(input.fontWeight) || isSet(input.strokeColor) || isSet(input.strokeWidth) || isSet(input.uppercase) || isSet(input.positionY) || isSet(input.maxWordsPerLine);
11585
+ if (hasStylingLever) return true;
11586
+ if (input.transcript !== void 0 && input.transcript !== null) return true;
11587
+ if (input.captions && input.captions.length > 0) return true;
11588
+ if (!input.text) return true;
11589
+ return false;
11590
+ }
11591
+ var CAPTION_MAX_WORDS_PER_LINE_MIN = 1;
11592
+ var CAPTION_MAX_WORDS_PER_LINE_MAX = 20;
11593
+ var CAPTION_LEVER_BOUNDS = {
11594
+ fontSize: { min: 12, max: 200 },
11595
+ strokeWidth: { min: 0, max: 40 },
11596
+ positionY: { min: 0, max: 100 },
11597
+ fontWeight: { min: 100, max: 900 },
11598
+ maxWordsPerLine: { min: CAPTION_MAX_WORDS_PER_LINE_MIN, max: CAPTION_MAX_WORDS_PER_LINE_MAX }
11599
+ };
11600
+ var CAPTION_NUMERIC_LEVER_KEYS = Object.keys(CAPTION_LEVER_BOUNDS);
11601
+ function normalizeCaptionNumericLevers(input) {
11602
+ const out = { ...input };
11603
+ for (const key of CAPTION_NUMERIC_LEVER_KEYS) {
11604
+ if (!(key in out) || out[key] === void 0) continue;
11605
+ if (out[key] === null) {
11606
+ delete out[key];
11607
+ continue;
11608
+ }
11609
+ const raw = typeof out[key] === "string" && out[key].trim() !== "" ? Number(out[key]) : out[key];
11610
+ if (typeof raw !== "number" || !Number.isFinite(raw)) {
11611
+ delete out[key];
11612
+ continue;
11613
+ }
11614
+ const { min, max } = CAPTION_LEVER_BOUNDS[key];
11615
+ const shaped = key === "fontWeight" ? Math.round(raw / 100) * 100 : key === "maxWordsPerLine" ? Math.round(raw) : raw;
11616
+ out[key] = Math.min(max, Math.max(min, shaped));
11617
+ }
11618
+ return out;
11619
+ }
11620
+ function autoStrokeWidth(fontSize) {
11621
+ return Math.max(2, Math.round(fontSize * 0.1));
11622
+ }
11623
+ var CAPTION_LOOKS = {
11624
+ // The TikTok / CapCut read: heavy geometric sans, caps, white on a thick black
11625
+ // outline, yellow spoken word.
11626
+ outline: (fs) => ({
11627
+ fontFamily: "Montserrat",
11628
+ fontWeight: 900,
11629
+ uppercase: true,
11630
+ color: "#ffffff",
11631
+ strokeColor: "#000000",
11632
+ strokeWidth: autoStrokeWidth(fs),
11633
+ highlightColor: "#FFE600"
11634
+ }),
11635
+ // The pre-look lever set with the face pinned (it never was): per-style weight,
11636
+ // soft shadow only, no casing, no outline.
11637
+ clean: () => ({ fontFamily: "Inter", color: "#ffffff" })
11638
+ };
11639
+ function resolveCaptionLook(look, explicit, fontSize) {
11640
+ const preset = CAPTION_LOOKS[look ?? DEFAULT_CAPTION_LOOK] ?? CAPTION_LOOKS[DEFAULT_CAPTION_LOOK];
11641
+ const out = { ...preset(fontSize) };
11642
+ for (const k of Object.keys(explicit)) {
11643
+ if (explicit[k] !== void 0) out[k] = explicit[k];
11644
+ }
11645
+ return out;
11646
+ }
11647
+ function resolveCaptionLevers(style, look, explicit, fontSize) {
11648
+ const effective = look ?? (isKineticCaptionStyle(style) ? DEFAULT_CAPTION_LOOK : DEFAULT_SUBTITLE_LOOK);
11649
+ return resolveCaptionLook(effective, explicit, fontSize);
11650
+ }
11651
+
11652
+ // src/transcribe-preflight.ts
11653
+ function transcribeWordTimestampsRefusal(provider) {
11654
+ const lane = provider || DEFAULT_TRANSCRIBE_NODE_PROVIDER;
11655
+ if (transcribeLaneSupportsWordTimestamps(lane)) return null;
11656
+ return `the "${lane}" engine does not return word timings \u2014 pick ${transcribeProvidersWithWordTimestamps().join(" or ")}`;
11657
+ }
11658
+ var TRANSCRIBE_JSON_OUT = "json";
11659
+ var TRANSCRIPT_IN = "transcript";
11660
+ var APPLY_EDL_JSON_OUT = "json";
11661
+ function findWordlessTranscriptFeeds(nodes, edges) {
11662
+ const byId = new Map(nodes.map((n) => [n.id, n]));
11663
+ const isSkipped = (n) => !n || n.data?.skipped === true;
11664
+ const out = [];
11665
+ for (const node of nodes) {
11666
+ if (node.type !== "transcribe" || isSkipped(node)) continue;
11667
+ const provider = typeof node.data?.provider === "string" && node.data.provider || DEFAULT_TRANSCRIBE_NODE_PROVIDER;
11668
+ const refusal = transcribeWordTimestampsRefusal(provider);
11669
+ if (!refusal) continue;
11670
+ const seen = /* @__PURE__ */ new Set();
11671
+ const frontier = [{ id: node.id, outHandle: TRANSCRIBE_JSON_OUT }];
11672
+ while (frontier.length > 0) {
11673
+ const { id, outHandle } = frontier.pop();
11674
+ for (const e of edges) {
11675
+ if (e.source !== id || (e.sourceHandle ?? null) !== outHandle || e.targetHandle !== TRANSCRIPT_IN) continue;
11676
+ const target = byId.get(e.target);
11677
+ if (isSkipped(target)) continue;
11678
+ if (target.type === "add-captions") {
11679
+ out.push({
11680
+ transcribeNodeId: node.id,
11681
+ consumerNodeId: target.id,
11682
+ provider,
11683
+ message: `Captions need word timings, but ${refusal}.`
11684
+ });
11685
+ } else if (target.type === "apply-edl" && !seen.has(target.id)) {
11686
+ seen.add(target.id);
11687
+ frontier.push({ id: target.id, outHandle: APPLY_EDL_JSON_OUT });
11688
+ }
11689
+ }
11690
+ }
11691
+ }
11692
+ return out;
11693
+ }
10636
11694
 
10637
11695
  // src/i18n/types.ts
10638
11696
  var LANGUAGES = [
@@ -10784,6 +11842,9 @@ var EXECUTION_DATA_KEYS = /* @__PURE__ */ new Set([
10784
11842
  "__listTotal",
10785
11843
  "__listCompleted",
10786
11844
  "__listResults",
11845
+ // Row-aligned twin of __listResults (Extract Field, List output) — read only
11846
+ // by the fan-out so two lists cut from one array pair by row.
11847
+ "__alignedListResults",
10787
11848
  // List fan-out window flag (abandon-guard exemption). Set/cleared by
10788
11849
  // executeNodeForList — purely execution-related, never user-edited.
10789
11850
  "__listRunning",
@@ -10812,7 +11873,26 @@ var EXECUTION_DATA_KEYS = /* @__PURE__ */ new Set([
10812
11873
  // Collect (fan-in) execution snapshot.
10813
11874
  "lastInputs",
10814
11875
  "lastMeta",
10815
- "__upstreamCount"
11876
+ "__upstreamCount",
11877
+ // Video URL node — the download's live percent/phase, written on every
11878
+ // progress tick (~2/s). Pure run-state; also in TRANSIENT_RUNTIME_KEYS below.
11879
+ "downloadPercent",
11880
+ "downloadPhase",
11881
+ // Webhook Output's delivery receipt. A webhook target may reflect the
11882
+ // request back (httpbin, RequestBin, an API that 400s with "headers
11883
+ // received: …"), so `webhookResponseBody` can carry whatever the request
11884
+ // carried — with an attached credential, the secret itself. Listing the three
11885
+ // here is what keeps the receipt out of template exports (GENERATED_FIELDS
11886
+ // derives from this set), out of node presets, and out of undo history.
11887
+ "webhookSuccess",
11888
+ "webhookStatusCode",
11889
+ "webhookResponseBody",
11890
+ // When the editor's "Clear results" last emptied this node (ISO time). Not a
11891
+ // result and not config: bookkeeping that tells the load-time recovery lanes
11892
+ // "this node is empty ON PURPOSE" — without it, every reload reads an empty
11893
+ // node as "ran while the editor was closed" and paints the last run back.
11894
+ // Persisted (never transient): the reload is exactly when it is read.
11895
+ "resultsClearedAt"
10816
11896
  ]);
10817
11897
  var TRANSIENT_RUNTIME_KEYS = /* @__PURE__ */ new Set([
10818
11898
  "executionStatus",
@@ -10825,7 +11905,13 @@ var TRANSIENT_RUNTIME_KEYS = /* @__PURE__ */ new Set([
10825
11905
  "__listCompleted",
10826
11906
  "__listRunning",
10827
11907
  "_upstreamRefresh",
10828
- "__upstreamCount"
11908
+ "__upstreamCount",
11909
+ // Video URL node download ticks. They used to dirty the workflow twice a
11910
+ // second for the length of the download — the same phantom-save chain the
11911
+ // job-progress keys above were moved here to stop. What SURVIVES a reload is
11912
+ // `downloadStatus` + `downloadId`; the percent is re-read from the server.
11913
+ "downloadPercent",
11914
+ "downloadPhase"
10829
11915
  ]);
10830
11916
  function stripTransientRuntimeData(nodes) {
10831
11917
  return nodes.map((node) => {
@@ -10854,6 +11940,10 @@ var GENERATED_FIELDS = [
10854
11940
  "assetId"
10855
11941
  ];
10856
11942
  var NODE_EXTRA_FIELDS = {
11943
+ // A template must never import ARMED: the switch is the importer's to flip
11944
+ // (a schedule starts paused), and the rules themselves are config that
11945
+ // travels.
11946
+ "schedule-trigger": ["active"],
10857
11947
  character: ["expressions", "poses", "lightingVariations", "angles", "customVariations"],
10858
11948
  object: ["angles", "materials", "variations", "customVariations"],
10859
11949
  creature: ["angles", "poses", "variations", "customVariations"],
@@ -10877,8 +11967,27 @@ var NODE_EXTRA_FIELDS = {
10877
11967
  // unlinked rather than dangling at the exporter's workflow.
10878
11968
  "sub-workflow": ["referencedWorkflowId"]
10879
11969
  };
10880
- function stripExportContent(nodes) {
11970
+ var UNOWNED_REF_FIELDS = {
11971
+ "webhook-output": ["credentialId"],
11972
+ ...Object.fromEntries([...SOCIAL_POST_NODE_TYPES].map((type) => [type, ["connectionId"]]))
11973
+ };
11974
+ function stripUnownedRefs(nodes) {
10881
11975
  return nodes.map((node) => {
11976
+ const fields = UNOWNED_REF_FIELDS[node.type];
11977
+ if (!fields || !node.data) return node;
11978
+ const data = { ...node.data };
11979
+ let changed = false;
11980
+ for (const field of fields) {
11981
+ if (field in data) {
11982
+ delete data[field];
11983
+ changed = true;
11984
+ }
11985
+ }
11986
+ return changed ? { ...node, data } : node;
11987
+ });
11988
+ }
11989
+ function stripExportContent(nodes) {
11990
+ return stripUnownedRefs(nodes).map((node) => {
10882
11991
  const data = { ...node.data };
10883
11992
  for (const field of GENERATED_FIELDS) delete data[field];
10884
11993
  const extras = NODE_EXTRA_FIELDS[node.type] ?? [];
@@ -13408,6 +14517,81 @@ var SUNO_TRACK_SOURCE_TYPES = /* @__PURE__ */ new Set([
13408
14517
  "suno-upload-extend"
13409
14518
  ]);
13410
14519
 
14520
+ // src/video-link.ts
14521
+ var SOCIAL_VIDEO_HOSTS = [
14522
+ "youtube.com",
14523
+ "youtu.be",
14524
+ "tiktok.com",
14525
+ "instagram.com",
14526
+ "twitter.com",
14527
+ "x.com",
14528
+ "facebook.com",
14529
+ "fb.watch",
14530
+ "fb.com"
14531
+ ];
14532
+ var YOUTUBE_HOSTS = ["youtube.com", "youtu.be"];
14533
+ var INSTAGRAM_HOSTS = ["instagram.com"];
14534
+ var TIKTOK_HOSTS = ["tiktok.com"];
14535
+ var TWITTER_HOSTS = ["twitter.com", "x.com"];
14536
+ var FACEBOOK_HOSTS = ["facebook.com", "fb.watch", "fb.com"];
14537
+ function hostnameMatchesAllowlist(hostname, domains) {
14538
+ const h = hostname.toLowerCase().replace(/\.$/, "");
14539
+ return domains.some((d) => {
14540
+ const dom = d.toLowerCase();
14541
+ return h === dom || h.endsWith("." + dom);
14542
+ });
14543
+ }
14544
+ function hasUrlParserHazard(url) {
14545
+ for (let i = 0; i < url.length; i++) {
14546
+ const code = url.charCodeAt(i);
14547
+ if (code === 92 || code <= 31 || code === 127) return true;
14548
+ }
14549
+ return false;
14550
+ }
14551
+ function isSocialVideoUrl(url, domains = SOCIAL_VIDEO_HOSTS) {
14552
+ if (hasUrlParserHazard(url)) return false;
14553
+ try {
14554
+ const parsed = new URL(url);
14555
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
14556
+ return hostnameMatchesAllowlist(parsed.hostname, domains);
14557
+ } catch {
14558
+ return false;
14559
+ }
14560
+ }
14561
+ function detectVideoLinkPlatform(url) {
14562
+ if (isSocialVideoUrl(url, YOUTUBE_HOSTS)) return "youtube";
14563
+ if (isSocialVideoUrl(url, FACEBOOK_HOSTS)) return "facebook";
14564
+ if (isSocialVideoUrl(url, TIKTOK_HOSTS)) return "tiktok";
14565
+ if (isSocialVideoUrl(url, INSTAGRAM_HOSTS)) return "instagram";
14566
+ if (isSocialVideoUrl(url, TWITTER_HOSTS)) return "twitter";
14567
+ return "unknown";
14568
+ }
14569
+ var VIDEO_LINK_TOLERANT_CONSUMER_TYPES = /* @__PURE__ */ new Set([
14570
+ "suno-cover",
14571
+ "transcribe",
14572
+ "dubbing"
14573
+ ]);
14574
+ function trimmed(value) {
14575
+ if (typeof value !== "string") return void 0;
14576
+ const t2 = value.trim();
14577
+ return t2 === "" ? void 0 : t2;
14578
+ }
14579
+ function videoLinkDownloadedFile(data) {
14580
+ const file = trimmed(data.downloadedVideoUrl);
14581
+ if (!file) return void 0;
14582
+ const from = trimmed(data.downloadedFromUrl);
14583
+ if (from && from !== trimmed(data.youtubeUrl)) return void 0;
14584
+ return file;
14585
+ }
14586
+ function resolveVideoLinkOutput(data) {
14587
+ return videoLinkDownloadedFile(data) ?? trimmed(data.youtubeUrl);
14588
+ }
14589
+ function videoLinkNeedsDownload(data) {
14590
+ const url = trimmed(data.youtubeUrl);
14591
+ if (!url || !isSocialVideoUrl(url)) return false;
14592
+ return videoLinkDownloadedFile(data) === void 0;
14593
+ }
14594
+
13411
14595
  // src/voice-changer-models.ts
13412
14596
  var VOICE_CHANGER_MODELS = [
13413
14597
  {
@@ -14471,6 +15655,12 @@ var AGGREGATE_LANE_EFFECTIVE_TYPE = {
14471
15655
  "out-audio": "upload-audio",
14472
15656
  "out-text": "list"
14473
15657
  };
15658
+ var SCRAPER_HANDLE_EFFECTIVE_TYPE = {
15659
+ text: "combine-text",
15660
+ image: "upload-image",
15661
+ video: "upload-video"
15662
+ };
15663
+ var SCRAPER_SOURCE_TYPES = /* @__PURE__ */ new Set(["meta-ads-scrape", "instagram-scrape"]);
14474
15664
  function resolveEffectiveSourceType(rawSourceType, sourceHandleId) {
14475
15665
  if (sourceHandleId === "image" && ENTITY_IMAGE_HANDLE_TYPES.has(rawSourceType ?? "")) {
14476
15666
  return "upload-image";
@@ -14479,6 +15669,10 @@ function resolveEffectiveSourceType(rawSourceType, sourceHandleId) {
14479
15669
  const effective = AGGREGATE_LANE_EFFECTIVE_TYPE[sourceHandleId ?? ""];
14480
15670
  if (effective) return effective;
14481
15671
  }
15672
+ if (SCRAPER_SOURCE_TYPES.has(rawSourceType ?? "")) {
15673
+ const effective = SCRAPER_HANDLE_EFFECTIVE_TYPE[sourceHandleId ?? ""];
15674
+ if (effective) return effective;
15675
+ }
14482
15676
  return rawSourceType ?? "";
14483
15677
  }
14484
15678
  function sourceRefKey(nodeId, sourceHandleId, rawSourceType) {
@@ -15078,21 +16272,6 @@ function bucketSecondsFromAuditCreditId(id) {
15078
16272
  return m ? Number(m[1]) : null;
15079
16273
  }
15080
16274
 
15081
- // src/video-ui-defaults.ts
15082
- function uiAspectRatioFill(provider) {
15083
- return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider) ? "adaptive" : void 0;
15084
- }
15085
- function uiResolutionFill(provider) {
15086
- if (isWan3Provider(provider)) return PRICING_DEFAULT_RESOLUTION[provider];
15087
- if (isSeedance2Provider(provider)) return MODEL_CATALOG[provider]?.resolutions?.[0];
15088
- return void 0;
15089
- }
15090
- function uiDurationFill(provider) {
15091
- if (isWan3Provider(provider)) return 5;
15092
- if (isGeminiOmniProvider(provider)) return 8;
15093
- return void 0;
15094
- }
15095
-
15096
16275
  // src/smart-cut-windows.ts
15097
16276
  var SMART_CUT_WINDOW_MAX = 24;
15098
16277
  var SMART_CUT_WINDOW_MIN = 1;
@@ -17671,6 +18850,603 @@ function resolveFrameDelivery(args) {
17671
18850
  return wanted;
17672
18851
  }
17673
18852
 
17674
- export { ACCESS_LEVELS, ACTIVE_SCENE_HELPERS, ADVANCED_MODE_UNAVAILABLE_REASON, AGGREGATEABLE_TYPES, AGGREGATE_LANE_SOURCE_TYPES, AI_AVATAR_DURATION_BUCKETS, AI_AVATAR_MAX_AUDIO_SEC, AI_AVATAR_MAX_DURATION_SEC, AI_AVATAR_RESERVE_IDS, AI_WRITER_PROVIDERS, ALA_CARTE_BOARDS, ALL_CAPTION_STYLES, ANIMALS, ANIMAL_SUBCATEGORY_LABELS, ANIMAL_SUBCATEGORY_ORDER, ASPECT_RATIO_DIMENSIONS, AUDIO_ADDON_PROVIDERS, AUDIO_CROSSFADE_CURVES, AUDIO_CROSSFADE_CURVE_IDS, AUDIO_FX_PRESETS, AUDIO_FX_PRESET_LABELS, AUDIO_FX_PRESET_SET, AUDIO_FX_REVERB_PRESETS, AUDIO_PRODUCER_TYPES, AddBRollResultSchema, AnchorSceneStyleResultSchema, AssetRefSchema, AuditImagesResultSchema, AuditImagesShotEntrySchema, AuditPromptIssueSchema, AuditPromptResultSchema, AvatarPayloadError, BOARD_TO_ASSET_TYPE, BOARD_TO_COLUMN, BOARD_VARIANTS, BridgeToNextSceneInputSchema, BridgeToNextSceneResultSchema, CATEGORY_DURATION_DEFAULTS, CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_ASSET_TYPES, CHARACTER_ASSET_VARIANTS, CHARACTER_ATTACH_COLUMNS, CHARACTER_FACETS, CHARACTER_FACET_IDS, CHARACTER_LORA_TRAINING_JOB_TYPE, CHARACTER_MOTION_PROVIDERS, CHARACTER_PICKER_DISPLAY_ORDER, CHARACTER_REFERENCE_PHOTO_KINDS, CHARACTER_STYLES, CHARACTER_VARIANT_ASSET_BUCKETS, CHAT_ENABLED_STAGES, CHAT_STAGES, CHAT_TURN_CAPS, CHAT_WIRED_STAGES, CINEMATIC_DEFAULT_DURATION_SEC, CINEMATIC_DEFAULT_RESOLUTION, CINEMATIC_MAX_DURATION_SEC, CINEMATIC_MAX_LOOKS, CINEMATIC_MAX_REFERENCE_IMAGES, CINEMATIC_MAX_REFERENCE_VIDEOS, CINEMATIC_MIN_DURATION_SEC, CINEMATIC_MIN_LOOKS, CINEMATIC_PROMPT_MAX, CINEMATIC_RESERVE_IDS, COLLABORATOR_ROLES, COLLECT_IN_HANDLE, COMBINE_TRANSITIONS, COMBINE_TRANSITION_GROUP_LABELS, COMBINE_TRANSITION_GROUP_ORDER, COMBINE_TRANSITION_IDS, COMPOSER_PLAN_FIELDS, COMPOSER_PLAN_MAP, CONTENT_TYPES_BY_PLATFORM, CREATURE_ATTACH_COLUMNS, CREDIT_BASE_USD, CREDIT_ROUNDING_RESOLUTION, CastCoverageCriticVerdictSchema, CharacterImageCriticVerdictSchema, CharacterMetadataSchema, ChatTurnResponseSchema, CriticIssueSchema, DEFAULT_AUDIO_CROSSFADE_CURVE_ID, DEFAULT_CARRIED_FRACTION, DEFAULT_CHARACTER_ANGLE_COUNT, DEFAULT_CHARACTER_EXPRESSION_COUNT, DEFAULT_CHARACTER_FACET, DEFAULT_FRAME_DELIVERY, DEFAULT_FRAME_FIT, DEFAULT_LABEL_BY_SOURCE, DEFAULT_LOCATION_USAGE_MODE, DEFAULT_OVERLAY_QR, DEFAULT_OVERLAY_SHAPE, DEFAULT_OVERLAY_TEXT, DEFAULT_PANEL_COUNT, DEFAULT_REF_IMAGE_MAX, DEFAULT_SECTIONS, DEFAULT_SUNO_MODEL, DEFAULT_TEMPLATE_CATEGORY, DEFAULT_USAGE_MODE, DEFAULT_VIDEO_ANALYSIS_MODEL, DEFAULT_VIDEO_ANALYSIS_TIER, DEFAULT_VIDEO_CLIP_COST, DEFAULT_VIDEO_DURATION_SEC, DEFAULT_VIDEO_PROVIDER, DEFAULT_VOICE_CHANGER_MODEL, DEFAULT_VOICE_DESIGN_MODEL, DETAIL_VARIANTS, DURATION_PRICED_PROVIDERS, DYNAMIC_PRODUCER_TYPES, DetectionResultSchema, EFFORT_TIER_BUMP, EMOTIONAL_BEAT, ENTITY_ASPECT_DEFAULTS, ENTITY_BUCKET_FIELDS, ENTITY_DB_ID_FIELD, ENTITY_IMAGE_HANDLE_TYPES, ENTITY_KIND_SCALAR_FIELDS, ENTITY_NAME_FIELD, ENTITY_NODE_KINDS, ENTITY_SCALAR_FIELDS, ENTITY_SECTIONS, ENTITY_STATUSES, ENTITY_TABLE, ENTITY_TOOL_RETRY_CAP, ENTITY_TYPES, EXECUTION_DATA_KEYS, EXECUTION_GRAPH_COMPOSED_PARAMETER_TYPES, EXTEND_VIDEO_PROVIDERS, EntityMetadataSchema, EntityRejectInputSchema, EntityStaleEventSchema, EntityStateChangeEventSchema, FACE_SWAP_PROVIDERS, FAL_LIP_SYNC_PROVIDERS, FAN_OUT_EACH_TYPES, FEATURED_ENTITIES, FILM_BASE_CREDITS, FLEXIBLE_INPUT_LIP_SYNC_PROVIDERS, FLUX2_RES_MP, FLUX_LORA_CHARACTER_MODEL_ID, FRAME_DELIVERIES, FRAME_DELIVERY_BY_PROVIDER, FRAME_FITS, FRAME_FIT_STRETCH_TOLERANCE, FRAME_MODE_ADAPTIVE_ONLY_ASPECT, FRAME_TARGET_HANDLES, FREECUT_EXPORT_COMPLETE, FREECUT_EXPORT_PROGRESS, FREECUT_READY, FREECUT_REQUEST_IMPORT, FURNITURE, FURNITURE_SUBCATEGORY_LABELS, FURNITURE_SUBCATEGORY_ORDER, FixContinuityInputSchema, FixContinuityResultSchema, GEMINI_OMNI_PROVIDERS, GENERATE_TEXT_DELIMITER, GLOBAL_MAX_DURATION_SECONDS, GRANTED_ACCESS, GROUP_HANDLE_PREFIX, GUIDANCE_SCALE_SUPPORT, GVP_ANCHOR_CHOICES, GVP_DEFAULT_PROVIDER, GVP_END_FRAME_PROVIDERS, GVP_EXTEND_PROVIDERS, GVP_SUPPORTED_PROVIDERS, GenerateMotionInputSchema, GenerateMotionResultSchema, HANDLE_PORT_SEPARATOR, HELPERS_SHIPPED_IN_1B3, HIGH_QUALITY_PROVIDERS, HINT_EXEMPT_PARAMETER_TYPES, I2I_MASK_SUPPORT, I2I_STRENGTH_SUPPORT, IDEOGRAM_PROVIDERS, IMAGE_ASPECT_RATIO_VALUES, IMAGE_CRITIC_LEAF_MODES, IMAGE_CRITIC_MAX_RETRIES, IMAGE_CRITIC_METADATA_KEYS, IMAGE_CRITIC_MIN_ADHERENCE_SCORE, IMAGE_CRITIC_MODES, IMAGE_CRITIC_UNRESOLVABLE, IMAGE_EDIT_PROVIDERS, IMAGE_GEN_PROVIDERS, IMAGE_I2I_PROVIDERS, IMAGE_MASK_MODE, IMAGE_OVERLAY_BASE_CREDITS, IMAGE_OVERLAY_VARIANT_CREDITS, IMAGE_PROMPT_MAX, IMAGE_REF_TYPES, IMAGE_TO_VIDEO_PROVIDERS, INPUT_FIELD_MAP2 as INPUT_FIELD_MAP, INPUT_NODE_TYPES, INSTAGRAM_CAROUSEL_MAX_ITEMS, INSTAGRAM_CAROUSEL_MIN_ITEMS, ITER_CLONE_PATTERN, ImageCriticIssueSchema, ImageCriticResultSchema, ImageCriticVerdictSchema, ImprovePromptInputSchema, ImprovePromptResultSchema, KEYFRAME_CREDITS_PER_SHOT, KINETIC_CAPTION_STYLES, LANGUAGES, LEGACY_LOTTIE_HOST_REMAP, LEGACY_TEMPLATE_CATEGORIES, LIP_SYNC_DURATION_BUCKETS, LIP_SYNC_MAX_AUDIO_SECONDS, LIP_SYNC_PROVIDERS, LLM_FEATURE_DEFAULTS, LLM_MODALITY_CAPS, LLM_MODELS, LLM_MODEL_IDS, LLM_REASONING_EFFORTS, LLM_ROUTE_DEFAULTS, LLM_TEXT_INPUT_MAX, LLM_VENDOR_LABELS, LLM_VENDOR_ORDER, LOCATION_ASSET_TYPES, LOCATION_ASSET_VARIANTS, LOCATION_ATMOSPHERE_PROVIDERS, LOCATION_ATTACH_COLUMNS, LOCATION_BUCKET_TO_CATALOG_ID, LOCATION_PRESET_TO_CATALOG, LOCATION_REFERENCE_PHOTO_KINDS, LOCATION_REFERENCE_PHOTO_KIND_LABELS, LOCATION_USAGE_MODES, LOTTIE_OVERLAY_CATALOG, LOTTIE_SLOT_FIELD_PREFIX, LocationImageCriticVerdictSchema, LocationMetadataSchema, LocationsCoverageCriticIssueSchema, LocationsCoverageCriticVerdictSchema, MAX_CUSTOM_ENTRIES_PER_BOARD, MAX_IMAGE_PROMPT_CHARS_BY_PROVIDER, MAX_LOCATION_VARIANTS, MAX_NEGATIVE_PROMPT_CHARS_BY_PROVIDER, MAX_PANELS_PER_SHEET, MAX_TTS_CHARS_BY_PROVIDER, MAX_VIDEO_PROMPT_CHARS_BY_PROVIDER, MEMBER_STATUSES, MINIMAX_H3_DEFAULT_RESOLUTION, MINIMAX_H3_PROVIDERS, MODELS_WITH_REFERENCE_IMAGE_SUPPORT, MODEL_CATALOG, MODEL_KINDS, MODEL_PARAM_NODE_TYPES, MODEL_RECOMMENDATIONS, MODIFY_IMAGE_PROVIDERS, MOTION_COLUMN, MOTION_TRANSFER_PROVIDERS, MUSIC_PROVIDERS, MatchCutVerdictSchema, NATIVE_ADAPTIVE_ASPECT, NATIVE_NEGATIVE_PROMPT_MODELS, NATIVE_NEGATIVE_VIDEO_PROVIDERS, NEGATIVE_PROMPT_MAX, NODARO_IMPORT_FILES, NODARO_LOAD_TIMELINE, NODARO_LOAD_VIDEO, NODARO_RESET_PROJECT, NODE_DEFAULT_TYPES, NODE_MAPPABLE_FIELDS, NODE_PRESET_EXPORT_KIND, NODE_REF_PATTERN, NON_EN_LOCALE_IDS, NO_SPLIT_DELIMITER, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ASSET_VARIANTS, OBJECT_ATTACH_COLUMNS, OBJECT_MOTION_PROVIDERS, OBJECT_PICKER_NODE_TYPES, ORG_ERROR_CODES, ORG_KINDS, ORG_ROLES, ORG_STATUSES, OUTPUT_BEARING_NODE_STATUSES, OUTPUT_FIELD_MAP, OUTPUT_FORMATS, OVERLAY_ANCHORS, OVERLAY_FONTS, OVERLAY_FONT_IDS, OVERLAY_IMAGE_MASKS, OVERLAY_LAYER_KINDS, OVERLAY_MAX_VARIANTS, OVERLAY_PLATFORMS, OVERLAY_PLATFORM_IDS, OVERLAY_SHAPES, OVERLAY_TEXT_ALIGNS, OVERLAY_VARIANT_HANDLE_PREFIX, ObjectMetadataSchema, OptimizeForModelInputSchema, OptimizeForModelResultSchema, OrgSettingsSchema, PARAMETER_NODE_TYPES, PASSTHROUGH_TYPES, PAYG_RETENTION_DAYS, PER_FORMAT_DURATION_BOUNDS, PICKER_TO_COMBINE_TRANSITION, PIPELINE_ACTIVATION_MODES, PIPELINE_FORMATS, PIPELINE_HARD_TIMEOUT_MS, PIPELINE_MODEL_STAGES, PIPELINE_MODES, PIPELINE_OUTPUT_RESOLUTIONS, PIPELINE_PINNABLE_IMAGE_MODELS, PIPELINE_PINNABLE_SCRIPT_LLMS, PIPELINE_PINNABLE_VIDEO_MODELS, PIPELINE_STAGE_NAMES, PIPELINE_STAGE_TIMEOUT_MS, PIPELINE_TYPES, PLACEHOLDER_CHARACTER_NAME, PLATFORM_LABELS, PLATFORM_SPECS, PRESET_APPLY_CLEAR_KEYS, PRESET_EXCLUDED_KEYS, PRESET_LABELS, PRESET_SETTING_KEYS, PRICING_DEFAULT_DURATION_SEC, PRICING_DEFAULT_RESOLUTION, PRO3D_RENDER_ASPECT_RATIOS, PRO3D_RENDER_CREDIT_ID, PRO3D_RENDER_DEFAULT_ENGINE, PRO3D_RENDER_DEFAULT_QUALITY, PRO3D_RENDER_DEFAULT_REPAIR_PASSES, PRO3D_RENDER_DEFAULT_STYLE, PRO3D_RENDER_ENGINES, PRO3D_RENDER_LABEL, PRO3D_RENDER_LIMITS, PRO3D_RENDER_MAX_REPAIR_PASSES, PRO3D_RENDER_MIN_REPAIR_PASSES, PRO3D_RENDER_NODE_TYPE, PRO3D_RENDER_PROMPT_MAX, PRO3D_RENDER_QUALITY_PROFILES, PRO3D_RENDER_SOURCE_KINDS, PRO3D_RENDER_STYLES, PROMPT_HARD_CEILING, PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY, PROVIDER_DIRECTIVE_DEFAULTS, PROVIDER_PLACEHOLDER_PREFIX, PipelineCompletedEventSchema, PipelineConfigSchema, PipelineDriftSummarySchema, PipelineEditorDecisionsReadyEventSchema, PipelineForkedEventSchema, PipelineInputSchema, PipelineMusicReadyEventSchema, PipelineStageNameSchema, PipelineStageStatusSchema, PipelineStateSchema, PipelineStatusSchema, PresetSettingsSchema, QA_CHECK_PROVIDERS, REDUCE_STRATEGIES, REDUCE_STRATEGY_IDS, REFERENCE_BOARD_PROVIDERS, REFERENCE_BOARD_TEMPLATES, REFERENCE_HANDLE_MAP, REFERENCE_ROLE_PRESETS, REF_HANDLE_CATEGORY, REF_IMAGE_MAX_LIMITS, REF_TOKEN_NAMESPACE_PREFIXES, RENDERING_SPEED_SUPPORT, RENDER_VIDEO_CREDIT_ID, REPEATABLE_NODE_TYPES, REPEAT_PLACEHOLDER, REPLICATE_LIP_SYNC_PROVIDERS, RESERVED_TEMPLATE_VARS, SCENE3D_ASSERTION_RESTORED_CODE, SCENE3D_ASSET_KINDS, SCENE3D_ASSET_ROLES, SCENE3D_ASSET_ROLE_KINDS, SCENE3D_AUTHORING_ASSUMPTION_CODE, SCENE3D_AUTHORING_ENGINES, SCENE3D_BASIC_ENGINE, SCENE3D_BASIC_SCHEMA_VERSION, SCENE3D_CAMERA_TRACK_FORMAT, SCENE3D_CAMERA_TRACK_LIMITS, SCENE3D_CAMERA_TRACK_VERSION, SCENE3D_CLAY_LIGHTING_PRESETS, SCENE3D_DEFAULT_ADVANCED_ENGINE, SCENE3D_DEFAULT_DURATION_SECONDS, SCENE3D_DEFAULT_ENTITY_CAPABILITIES, SCENE3D_DEFAULT_FPS, SCENE3D_EDIT_NODE_TYPE, SCENE3D_ENTITY_CAPABILITIES, SCENE3D_ENTITY_ROLES, SCENE3D_GENERATE_NODE_TYPE, SCENE3D_GLB_EXTRAS_ALLOWLIST, SCENE3D_GLB_EXTRAS_ENTITY_ID, SCENE3D_GLB_EXTRAS_MATERIAL_ROLE, SCENE3D_GLB_EXTRAS_SUBPART_ID, SCENE3D_LIMITS, SCENE3D_PLAN_FIELD, SCENE3D_PLAN_TYPE, SCENE3D_PRIMITIVES, SCENE3D_PRIMITIVE_MATERIAL_ROLE, SCENE3D_REMEDY_AUTO_APPLIED_CODE, SCENE3D_RENDERER_ASSET_KINDS, SCENE3D_RENDER_BASE_MAX_PX, SCENE3D_RENDER_TIERS, SCENE3D_RENDER_TIER_MULTIPLIERS, SCENE3D_RENDER_XLARGE_MIN_AREA_PX, SCENE3D_REVIEW_REFUSED_CODE, SCENE3D_REVIEW_UNAVAILABLE_CODE, SCENE3D_REVIEW_UNAVAILABLE_REASONS, SCENE3D_SCHEMA_VERSION, SCENE3D_SCHEMA_VERSION_V2, SCENE3D_SUPPORTED_SCHEMA_VERSIONS, SCENE3D_V2_CONTENT_HASH_EXCLUDED, SCENE3D_V2_ENGINES, SCENE3D_V2_LIMITS, SCENE3D_V2_OVERRIDE_OPERATION_VERSION, SCENE3D_V2_PRIMITIVES, SCENE_HELPER_NAMES, SCRAPER_ACTOR_LABELS, SCRAPER_CREDIT_COSTS, SCRAPER_OUTPUT_FIELDS, SCRIPT_PROVIDERS, SEASONS, SECTION_BOARD, SECTION_KINDS, SEEDANCE_2_5_REF_LIMITS, SEEDANCE_2_CONTINUATION_REF_SEC, SEEDANCE_2_EXTEND_STITCH, SEEDANCE_2_PROVIDERS, SEEDANCE_2_R2V_MAX_AUDIO_SEC_BY_PROVIDER, SEEDANCE_2_R2V_MIN_REF_VIDEO_SEC, SEEDANCE_2_REF_LIMITS, SEEDANCE_LIP_SYNC_PROVIDERS, SEED_SUPPORT, SEPARATOR_DISPLAY, SEPARATOR_PRESETS, SHEET_ASPECTS, SHEET_BACKGROUNDS, SHEET_PRESETS, SHEET_SKINS, SHEET_TYPES, SHORT_FILM_ANGLE_COUNT, SHORT_FILM_EXPRESSION_COUNT, SHORT_FILM_VARIANT_THRESHOLD_SEC, SLOT_TOKEN_RE, SMART_CUT_WINDOW_DEFAULT, SMART_CUT_WINDOW_MAX, SMART_CUT_WINDOW_MIN, SOCIAL_POST_NODE_TYPES, STAGE_PATCH_SCHEMA, STATIC_CAPTION_STYLES, STRUCTURAL_SECTIONS, STRUCTURED_VISION_MODELS, STUDIO_DEPENDENT_FRAMES_CAPABILITY, STUDIO_SHOT_TRANSIENT_KEYS, STUDIO_TRANSIENT_KEYS, SUBMISSION_STATUSES, SUNO_ACTIVE_MODELS, SUNO_ADD_TRACK_MODELS, SUNO_DURATION_MODELS, SUNO_FIELD_HANDLE_FIELDS, SUNO_HARD_CEILING, SUNO_LEGACY_MODELS, SUNO_MODELS, SUNO_SELECT_OPERATIONS, SUNO_TEXT_MAX, SUNO_TITLE_MAX, SUNO_TRACK_SOURCE_TYPES, SUNO_VERSION_CREDIT_KEYS, SUNO_VERSION_PRICED_OPERATIONS, SUPPORTED_FONT_NAMES, SURROUND_DIRECTIONS, SWITCHX_BLOCK_FRAMES, SWITCHX_FRAME_TIERS, SceneHelperNameSchema, SceneInputModeSchema, SceneMetadataSchema, SceneNodeDataSchema, SceneSpecSchema, ScriptCriticVerdictSchema, SequenceExecutionRequiredError, ShotSpecSchema, ShowrunnerPlanSchema, StageAwaitingSubGateEventSchema, StoryboardCohesionCriticVerdictSchema, StyleDirectivesSchema, SubGateNameSchema, T2I_TO_I2I_VARIANT, TASK_CHAINED_EDIT_PROVIDERS, TEMPLATE_CATEGORIES, TEXT_TO_AUDIO_PROVIDERS, TEXT_TO_VIDEO_PROVIDERS, TIER_MAX_PIPELINE_COST_CREDITS, TIER_PIPELINE_PARALLELISM, TILT_CARRIED_FRACTION, TOPAZ_DEFAULT_UPSCALE_FACTOR, TOPAZ_UPSCALE_FACTORS, TRANSCRIBE_PROVIDERS, TRANSIENT_RUNTIME_KEYS, TTS_PROVIDERS, TTS_TEXT_MAX, TWO_K_RESOLUTION_PROVIDERS, TransitionTypeSchema, UPSCALE_IMAGE_PROVIDERS, USAGE_GROUP_BYS, USAGE_MODES, VARIABLES_HANDLE_ID, VARIABLE_PRICING_MODELS, VEHICLES, VEHICLE_SUBCATEGORY_LABELS, VEHICLE_SUBCATEGORY_ORDER, VEO_PROVIDERS, VIDEO_ANALYSIS_AUDIO_MODES, VIDEO_ANALYSIS_BUCKET_CREDITS, VIDEO_ANALYSIS_CLIP_TRANSITIONS_IN, VIDEO_ANALYSIS_DEFAULT_VARIATION, VIDEO_ANALYSIS_DURATION_BUCKETS, VIDEO_ANALYSIS_DURATION_TOLERANCE_SEC, VIDEO_ANALYSIS_ENTITY_SOURCES, VIDEO_ANALYSIS_FACELESS_ANGLES, VIDEO_ANALYSIS_LEGACY_MODELS, VIDEO_ANALYSIS_LLM_MODELS, VIDEO_ANALYSIS_MAX_DURATION_SEC, VIDEO_ANALYSIS_MAX_SCENE_SEC, VIDEO_ANALYSIS_MAX_VARIATIONS, VIDEO_ANALYSIS_MIXED_TIERS, VIDEO_ANALYSIS_SHOT_ANGLES, VIDEO_ANALYSIS_SPEED_EFFECTS, VIDEO_ANALYSIS_STORY_JUMPS, VIDEO_ANALYSIS_TEXT_KINDS, VIDEO_ANALYSIS_TIERS, VIDEO_ANALYSIS_TIER_LABELS, VIDEO_ANALYSIS_TIER_ORDER, VIDEO_ANALYSIS_TIMES_OF_DAY, VIDEO_ANALYSIS_TRANSITIONS, VIDEO_ANALYSIS_VARIATION_SLUGS, VIDEO_ANALYSIS_VISUAL_EFFECTS, VIDEO_ANALYSIS_WINDOW, VIDEO_AUDIO_CAPABILITY, VIDEO_AUDIT_BUCKET_CREDITS, VIDEO_CLIP_CREDITS, VIDEO_CRITIC_CREDITS_PER_SHOT, VIDEO_CRITIC_FRAME_MODES, VIDEO_CRITIC_MAX_RETRIES, VIDEO_CRITIC_METADATA_KEYS, VIDEO_CRITIC_MIN_ADHERENCE_SCORE, VIDEO_DURATION_TIERS, VIDEO_GEN_COLLAPSED_T2V_IDS, VIDEO_GEN_PROVIDERS, VIDEO_INPUT_LIP_SYNC_PROVIDERS, VIDEO_MODEL_CAPS, VIDEO_MODE_ALIASES, VIDEO_ONLY_PARAMETER_NODE_TYPES, VIDEO_OUTPUT_CANVAS, VIDEO_PRODUCER_TYPES, VIDEO_PROMPT_MAX, VIDEO_PROVIDERS_REQUIRING_IMAGE, VIDEO_PROVIDERS_WITHOUT_DISPATCH, VIDEO_REF_LIMITS_BY_PROVIDER, VIDEO_REF_VIDEO_DURATION_LIMITS, VIDEO_TO_VIDEO_PROVIDERS, VIDEO_UPSCALE_PROVIDERS, VIDEO_UTIL_PRICING, VIDEO_VARIABLE_PRICING, VOICE_CHANGER_MODELS, VOICE_CHANGER_MODEL_IDS, VOICE_DESIGN_MODELS, ValidateMatchCutInputSchema, ValidateMatchCutResultSchema, VideoCriticVerdictSchema, VoiceMatchSchema, WAN_3_DEFAULT_RESOLUTION, WAN_3_PROVIDERS, WARDROBE_VARIANTS, WEAPONS, WEAPON_SUBCATEGORY_LABELS, WEAPON_SUBCATEGORY_ORDER, WORKFLOW_VISIBILITIES, WORKSPACE_HEADER, WORKSPACE_HEADER_LOWER, WORKSPACE_ROLES, WorkspaceSettingsSchema, aggregateByType, aiAvatarReserveCreditId, analyzedSceneSchema, applyDefaultVideoSelection, applyHandleInputOverride, applyRange, applyRangeIndices, applyScene3DEditOperations, applyScene3DV2EditOperations, applySlots, applyVideoAudioToggle, applyVideoNegativePrompt, aspectRatioFromDims, aspectRatioOptionsByKind, aspectRatioToNumber, assembleNarratedVideoCredits, assertCanvasExecutionAllowed, availableReasoningEfforts, bucketSecondsFromAuditCreditId, bucketSecondsFromCreditId, buildBoardPrompt, buildChildrenByParent, buildConditionVariables, buildCreditModelIdentifier, buildExpressionFromVisual, buildLipSyncCreditId, buildLlmCreditIdentifier, buildModelMenu, buildModelTree, buildMotionCreditModelIdentifier, buildNodePresetExport, buildPanelPrompt, buildPro3DRenderSource, buildProgressSegments, buildRangeLabel, buildScraperCreditId, buildVideoAnalysisCreditId, buildVideoAuditCreditId, buildVideoCreditModelIdentifier, calculateCombinedProgress, calculateMonetizationMarkup, calculateMonetizedCost, calculateProgress, canonicalScene3DPlanV2Json, canonicalVarName, centreCropToAspect, characterBoardItems, characterBucketDisplayRank, characterMentionSlug, characterMentionableAssetArrays, characterSheetRefItems, characterVariantAssetArrays, checkRefVideoDurations, cinematicCreditId, clampCinematicDuration, clampSmartCutWindow, classifyRefToken, cleanOrphanedItems, clearImageCriticMetadata, clearVideoCriticMetadata, clipLookSchema, collectAncestorRefs, combineSameLabelRefs, computeAggregateLanes, computeFrameFitPlan, computeScene3DPlanV2ContentHash, countRefModalityEdges, creditRangesAll, creditsToUsd, decodeProviderItem, defaultCarriedFraction, defaultResolutionFor, defaultRoleForSource, defaultVideoAspectRatio, deriveLinkedFields, deriveLottieSlotFields, deriveSlotRefs, describeEdgeBehavior, describeMaskRegion, describeNodeAdjustments, describeSlotControl, dropUnknownBindings, dropUnknownSpeakers, durationsByMode, effectiveReasoningEffort, encodeProviderItem, ensureLocaleCatalogLoaded, entityHydrationColumns, entityMentionSlug, entityMentionSlugForRef, entityScalarFields, entitySlotSchema, entryMatchesQuery, estimateCombineVideosCredits, estimateFilmCredits, estimateLoopTrimAddonCredits, estimateLoopVideoCredits, estimateScriptDurationSec, estimateSheetCost, estimateTrimVideoCredits, evaluateCondition, evaluateConditionGroup, evaluateJsonExpression, evaluateJsonPath, expandExtraRefsToConnectedReferences, expandItemsWithRepeat, extractAllGeneratedResults, extractCharacterLoraFields, extractGeneratedJsonAsList, extractPresetData, extractReferencedLabels, extractVideoDurationFromNode, fieldKeyFromHandle, filterCloneNodes, findCharacterMentionTokens, findEntityMentionTokens, findImageMentionTokens, findLocationMentionTokens, findSeedance2AudioOverLimit, firstSightExtraRole, flattenItems, getAnimal, getAnimalLabel, getAnimalPromptHint, getAnimalTerm, getAspectRatioOptions, getAudioCrossfadeCurve, getCharacterFacet, getCombineTransition, getCreditRange, getDurationsForModel, getEffectiveRepeatCount, getFeaturedEntities, getFurniture, getFurnitureLabel, getInputFieldSchema, getInputNodes, getItemSortId, getLipSyncMaxAudioSeconds, getLlmModalityCaps, getLlmModel, getLlmTier, getLocaleDirection, getMaxImagePromptChars, getMaxNegativePromptChars, getMaxSunoPromptChars, getMaxSunoStyleChars, getMaxTtsChars, getMaxVideoPromptChars, getModel, getNodeLabel, getNodeResult, getOutputNodes, getOutputType, getParameterValue, getQualityOptions, getResolutionOptions, getRouteReachableNodeIds, getStrategy, getTargetField, getValidValues, getVehicle, getVehicleLabel, getVideoAudioCapability, getWeapon, getWeaponLabel, groupByFamily, groupByKindAndFamily, groupHandleId, groupLlmModelsByVendor, hasContiguousSegmentDurations, hasFeature, hexToRgbaArray, humanizeSlotSid, imageMentionSlug, imageMentionSlugForRef, imageOverlayBillableVariants, imageOverlayCredits, imageReferenceLimit, inferMusicVideo, isAggregateableType, isCharacterAspectRatio, isCollectInEdge, isDefaultSelectorConfig, isExpandedClone, isFlux2Model, isGeminiOmniProvider, isGvpSupportedProvider, isHandleInputWired, isKineticCaptionStyle, isKnownScene3DEngine, isLegacySunoModel, isLocationUsageMode, isMinimaxH3Provider, isObjectAspectRatio, isOversizedScene, isPaygRetentionActive, isPerSecondLipSyncProvider, isPro3DRenderJobOutput, isPro3DRenderQuote, isPro3DRenderRenderOnly, isRtlText, isScene3DAuthoringEngine, isScene3DCameraTrack, isScene3DHttpUrl, isScene3DPlan, isScene3DPlanV1, isScene3DPlanV2, isScene3DReviewUnavailableReason, isScene3DSchemaVersionSupported, isScraperActor, isSeedance2Provider, isTemplateCategory, isTiltDirection, isUsageMode, isVeoProvider, isVideoAnalysisMixedTier, isVideoAnalysisTier, isWan3Provider, jsonResultToList, knownEntitySlugsFromRefs, knownImageSlugsFromRefs, listBoardTemplates, listModels, listSlotSids, llmRouteDefaults, locationMentionSlug, locationReferencePhotoKindLabel, locationUsageModeLabel, mapAspectRatio, mapQuality, mapShotIntentToProviderDirectives, matchVariant, maxSegmentSecFor, maxSegmentsFor, measuredCanvasCombinations, mergeClipLook, mergeExposedSettings, migrateEdgeOutputMode, migrateToItems, minSegmentSecFor, minimalRatioDimensions, modelIdsByKindMode, modelToNodeTarget, modelsForInputMode, modelsWithFeature, motionGraphicsFeature, newScene3DRevisionId, nodeStateMayCarryOutput, normalizeLottieLayers, normalizeMinimaxH3Resolution, normalizeModelInput, normalizeNodeModelParams, normalizePinterestUrl, normalizeRoleSlug, normalizeTemplateCategory, normalizeVideoRequestParams, normalizeWan3Resolution, orderedLlmModels, overlayFontById, overlayImageEffectsSchema, overlayPlatformById, overlayQrStyleSchema, overlayShapeElement, overlayShapeStyleSchema, overlayStrokeSchema, overlayTextStyleSchema, overlayVariantHandle, overlayVariantIdFromHandle, parseAspectToken, parseAttributedDialogue, parseCharacterMentionToken, parseEntityMentionToken, parseGroupHandle, parseHandleId, parseImageMentionToken, parseListExpression, parseLocationMentionToken, parseNodePresetExport, parseNodeRef, parseScene3DCameraTrackJson, parseScene3DPlanV2Json, pickAiAvatarBucket, pickIds, pickLipSyncBucket, pickSwitchXFrameTier, pickVideoAnalysisBucket, planSheetGeneration, planSheetPanels, preferredInputModeForModel, presentTypes, presetApplyClearKeys, presetDataMatches, presetEntries, pricedOutputDurationSec, pricedVideoSelection, pro3DRenderCoreOutputSchema, pro3DRenderFrameUnit, pro3DRenderJobOutputSchema, pro3DRenderProducedSchemaVersion, pro3DRenderQuoteSchema, pro3DRenderReviewVerdictSchema, pro3DRenderShotStillSchema, pro3DRenderShotStills, pro3DRenderTimingOverrides, qualityOptionsByKind, readPromptAffixes, refHandleCategory, referenceModalityForHandle, referenceSheetCreditId, registerCatalogSidecars, registerSidecarLoaders, renderAnalyzedScene, renderVideoCreditId, requiresSequenceExecution, resetCatalogSidecars, resolutionOptionsByKind, resolveAiAvatarCreditId, resolveAudioCrossfadeCurve, resolveCharacterAspectRatio, resolveCinematicCreditId, resolveConditionValue, resolveDefaultRole, resolveDescription, resolveDialogueVoices, resolveEffectiveSourceType, resolveEffectiveTier, resolveEntityAspect, resolveFieldMappings, resolveFrameDelivery, resolveFrameFitAspect, resolveGvpAnchorWire, resolveImageGenCreditIdentifier, resolveIndex, resolveLabel, resolveListExpression, resolveLlmCreditId, resolveLocationFields, resolveLocationPresetCatalog, resolveLottieOverlaySrc, resolveNodeRefs, resolveNormalizedImageGen, resolveObjectAspectRatio, resolveOutputCanvas, resolvePipelineModel, resolveRelativeWindowToken, resolveScene3DAuthoringEngine, resolveScraperCreditId, resolveSelectorRefs, resolveSeparator, resolveSheetSections, resolveSlideshowTransition, resolveSourceThroughConnectedList, resolveStoredTier, resolveSwitchXCreditId, resolveTemplateCategory, resolveTopazUpscale, resolveVideoAnalysisModel, resolveVideoModeForInputs, resolveVideoProviderForMode, resolveXfadeName, rewriteSceneBindings, rewriteSlotTokens, rewriteSpeakerSlots, rgbaArrayToHex, roleToPhrase, rotationVec3Schema, runSelector, safetyRetryPolicy, sanitizeRole, scaleVec3Schema, scene3DAcceptedSchemaVersionsSchema, scene3DAnchorNameSchema, scene3DAnchorSchema, scene3DAnyPlanSchema, scene3DAssetAnimationSchema, scene3DAssetIdSchema, scene3DAssetRefSchema, scene3DCameraChangesSchema, scene3DCameraKeyframeSchema, scene3DCameraSampleSchema, scene3DCameraSchema, scene3DCameraTrackIssues, scene3DCameraTrackObjectSchema, scene3DCameraTrackPlanIssues, scene3DCameraTrackSchema, scene3DClayLightingSchema, scene3DColorSchema, scene3DDeepEqual, scene3DEasingSchema, scene3DEditOperationSchema, scene3DEditOperationsSchema, scene3DEngineIdSchema, scene3DEntityAcceptsOverlay, scene3DEntityCapabilitySchema, scene3DEntityV2Schema, scene3DEntityVisualSchema, scene3DIdSchema, scene3DInputAssetSchema, scene3DInputAssetsForEngine, scene3DInputAssetsSchema, scene3DJsonByteLength, scene3DLightingChangesSchema, scene3DLightingSchema, scene3DMaterialBindingSchema, scene3DMaterialNameSchema, scene3DMaterialRoleSchema, scene3DNodeIdSchema, scene3DNodeNameSchema, scene3DObjectChangesSchema, scene3DObjectKeyframeSchema, scene3DObjectSchema, scene3DOverrideSchema, scene3DPlanIssues, scene3DPlanSchema, scene3DPlanSchemaVersion, scene3DPlanV1Issues, scene3DPlanV1ObjectSchema, scene3DPlanV1Schema, scene3DPlanV2Issues, scene3DPlanV2ObjectSchema, scene3DPlanV2Schema, scene3DPrimitiveSchema, scene3DProjectionIssues, scene3DProvenanceSchema, scene3DReferenceSchema, scene3DRenderTier, scene3DRenderTierCredits, scene3DReviewNote, scene3DReviewVerdictOf, scene3DSampleForFrame, scene3DSha256Schema, scene3DShotForFrame, scene3DShotIndexForFrame, scene3DShotSchema, scene3DUrlSchema, scene3DV2AdmissionIssues, scene3DV2EditOperationSchema, scene3DV2EditOperationsSchema, scene3DV2HierarchyDepth, scene3DV2NormalizationIssues, scene3DV2OverrideInputSchema, scene3DV2ResourceUsage, scene3DVersionTokenSchema, scene3DZodIssues, searchModelVariants, seedance2AudioLimitSec, segmentDurationsFor, selectByModulo, selectByNamedKey, selectByPredicate, selectListItems, selectLoraRoutingForMentions, selectRandom, setRegisteredPersonPackFields, settledWithLimit, sizeVec3Schema, slotVariationSchema, sortCharacterEntriesForDisplay, sortListItems, sourceRefKey, spliceDelimitedRows, splitByLoopDelimiter, splitGeneratedItems, spreadJsonArrayIfSingleton, stringifyPathResults, stripDerivedAnalysisFields, stripExportContent, stripStudioTransientSettings, stripTransientRuntimeData, summarizeScene3DOperations, sunoCreditType, sunoModelHonoursDuration, supportedDefaultDimensions, supportsAdvancedMode, supportsEndAnchor, supportsExtendRender, templateCategoryStoredValues, toConnectedReference, toConnectedReferences, togglePick, tryParseJson, uiAspectRatioFill, uiDurationFill, uiResolutionFill, unresolvedRefTokens, unwrapUnresolvedTokens, usageModeDirective, usageModeIncludesName, usageModeLabel, usdToCredits, validateAiAvatarPayload, validateCinematicAvatarPayload, validateDurationForFormat, validateModeActivation, validateModelInput, validateNoNestedGroups, validateObjects, validateProviderForNodeType, validateSubWorkflowRoutes, variantJobId, vec3Schema, verifyScene3DPlanV2ContentHash, videoAnalysisCreditSegment, videoAnalysisNumWindows, videoAnalysisResultSchema, videoAuditCreditsForBucket, videoModelCanSpeakDialogue, videoModelSupportsAudio, videoNegativeSuffix, videoProviderFoldsLoneEndFrame, videoProviderRequiresImage, windowAnalysisSchema, zipMergeLists };
18853
+ // src/edl-multicam.ts
18854
+ var hasOwn = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
18855
+ var isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
18856
+ function mergeEdlSourceOffsets(edl, offsets, opts) {
18857
+ const sources = Array.isArray(edl?.sources) ? edl.sources : [];
18858
+ const rows = offsets && typeof offsets === "object" ? offsets : {};
18859
+ const byId = /* @__PURE__ */ new Map();
18860
+ for (const s of sources) if (s && typeof s === "object" && !byId.has(s.id)) byId.set(s.id, s);
18861
+ let anchor;
18862
+ if (opts?.anchor !== void 0) {
18863
+ if (!byId.has(opts.anchor)) {
18864
+ return { edl: { ...edl }, applied: [], ignored: [{ sourceId: opts.anchor, reason: "anchor-unknown" }] };
18865
+ }
18866
+ anchor = opts.anchor;
18867
+ } else {
18868
+ const masters = sources.filter((s) => s && typeof s === "object" && s.role === "master-audio");
18869
+ if (masters.length === 1) anchor = masters[0].id;
18870
+ }
18871
+ let reference = 0;
18872
+ if (anchor !== void 0 && hasOwn(rows, anchor)) {
18873
+ const a = rows[anchor];
18874
+ if (!isFiniteNumber(a)) {
18875
+ return { edl: { ...edl }, anchor, applied: [], ignored: [{ sourceId: anchor, reason: "anchor-not-finite" }] };
18876
+ }
18877
+ reference = a;
18878
+ }
18879
+ const anchorOffsetMs = anchor !== void 0 ? byId.get(anchor)?.offsetMs ?? 0 : 0;
18880
+ const next = /* @__PURE__ */ new Map();
18881
+ const applied = [];
18882
+ const ignored = [];
18883
+ for (const sourceId of Object.keys(rows)) {
18884
+ if (sourceId === anchor) continue;
18885
+ if (!byId.has(sourceId)) {
18886
+ ignored.push({ sourceId, reason: "unknown-source" });
18887
+ continue;
18888
+ }
18889
+ const measured = rows[sourceId];
18890
+ const offsetMs = isFiniteNumber(measured) ? Math.round(anchor !== void 0 ? anchorOffsetMs + measured - reference : measured) : Number.NaN;
18891
+ if (!Number.isFinite(offsetMs)) {
18892
+ ignored.push({ sourceId, reason: "not-finite" });
18893
+ continue;
18894
+ }
18895
+ next.set(sourceId, offsetMs);
18896
+ applied.push(sourceId);
18897
+ }
18898
+ const merged = Array.isArray(edl?.sources) ? { ...edl, sources: edl.sources.map((s) => s && typeof s === "object" && next.has(s.id) ? { ...s, offsetMs: next.get(s.id) } : s) } : { ...edl };
18899
+ return { edl: merged, ...anchor !== void 0 ? { anchor } : {}, applied, ignored };
18900
+ }
18901
+ var EDL_FULL_FRAME = Object.freeze({ x: 0, y: 0, w: 1, h: 1 });
18902
+ function isInFrameRegion(r) {
18903
+ if (!r || typeof r !== "object") return false;
18904
+ const { x, y, w, h } = r;
18905
+ for (const v of [x, y, w, h]) if (!isFiniteNumber(v) || v < 0 || v > 1) return false;
18906
+ const box = r;
18907
+ return box.w > 0 && box.h > 0 && box.x + box.w <= 1 + 1e-9 && box.y + box.h <= 1 + 1e-9;
18908
+ }
18909
+ function resolveEdlSegmentSlots(edl, segment, opts) {
18910
+ if (!segment || typeof segment !== "object") return [];
18911
+ const sources = Array.isArray(edl?.sources) ? edl.sources : [];
18912
+ const layoutSlots = Array.isArray(segment.layout?.slots) ? segment.layout.slots : [];
18913
+ const slots = layoutSlots.length > 0 ? layoutSlots : typeof segment.video === "string" && segment.video ? [{ source: segment.video }] : [];
18914
+ const single = slots.length === 1;
18915
+ const out = [];
18916
+ for (const slot of slots) {
18917
+ if (!slot || typeof slot !== "object") continue;
18918
+ const source = slot.source;
18919
+ const speaker = slot.speaker ?? (single ? segment.speaker : void 0);
18920
+ const rungs = [
18921
+ ["slot", () => slot.region],
18922
+ ["segment", () => single ? segment.region : void 0],
18923
+ ["resolver", () => opts?.regionFor?.({ segment, source, ...speaker !== void 0 ? { speaker } : {} })],
18924
+ ["speaker", () => speaker === void 0 ? void 0 : Array.isArray(opts?.speakerRegions) ? opts.speakerRegions.find((row) => row && row.source === source && row.speaker === speaker)?.region : void 0],
18925
+ ["source", () => sources.find((s) => s && typeof s === "object" && s.id === source)?.region]
18926
+ ];
18927
+ let region = EDL_FULL_FRAME;
18928
+ let regionFrom = "full";
18929
+ for (const [from, read] of rungs) {
18930
+ const candidate = read();
18931
+ if (isInFrameRegion(candidate)) {
18932
+ region = candidate;
18933
+ regionFrom = from;
18934
+ break;
18935
+ }
18936
+ }
18937
+ out.push({
18938
+ source,
18939
+ region,
18940
+ regionFrom,
18941
+ ...speaker !== void 0 ? { speaker } : {},
18942
+ ...slot.weight !== void 0 ? { weight: slot.weight } : {}
18943
+ });
18944
+ }
18945
+ return out;
18946
+ }
18947
+
18948
+ // src/speaker-layouts.ts
18949
+ var EDL_TARGET_ASPECTS = ["16:9", "9:16", "1:1", "4:5"];
18950
+ var TARGET_ASPECT_SET = new Set(EDL_TARGET_ASPECTS);
18951
+ function isEdlTargetAspect(v) {
18952
+ return typeof v === "string" && TARGET_ASPECT_SET.has(v);
18953
+ }
18954
+ var SPEAKER_LAYOUTS = [
18955
+ { id: "single", minSlots: 1, maxSlots: 1, aspects: EDL_TARGET_ASPECTS },
18956
+ { id: "side-by-side", minSlots: 2, maxSlots: 2, aspects: ["16:9", "1:1"] },
18957
+ { id: "stacked", minSlots: 2, maxSlots: 2, aspects: ["9:16", "4:5", "1:1"] },
18958
+ { id: "grid", minSlots: 2, maxSlots: 6, aspects: EDL_TARGET_ASPECTS },
18959
+ { id: "pip", minSlots: 2, maxSlots: 2, aspects: EDL_TARGET_ASPECTS }
18960
+ ];
18961
+ var SPEAKER_LAYOUT_IDS = SPEAKER_LAYOUTS.map((l) => l.id);
18962
+ var LAYOUTS_BY_ID = new Map(SPEAKER_LAYOUTS.map((l) => [l.id, l]));
18963
+ function getSpeakerLayout(id) {
18964
+ return LAYOUTS_BY_ID.get(id);
18965
+ }
18966
+ function speakerLayoutAllows(sheet, q) {
18967
+ if (q.aspect !== void 0 && !sheet.aspects.includes(q.aspect)) return false;
18968
+ if (q.slotCount !== void 0 && !(q.slotCount >= sheet.minSlots && q.slotCount <= sheet.maxSlots)) return false;
18969
+ return true;
18970
+ }
18971
+ var XFADE_SWITCH_PREFIX = "xfade:";
18972
+ function speakerSwitchOverlaps(type) {
18973
+ return typeof type === "string" && type.startsWith(XFADE_SWITCH_PREFIX);
18974
+ }
18975
+ var switchSheet = (id, requiresSameSource) => ({
18976
+ id,
18977
+ overlaps: speakerSwitchOverlaps(id),
18978
+ requiresSameSource
18979
+ });
18980
+ var SPEAKER_SWITCHES = [
18981
+ switchSheet("cut", false),
18982
+ switchSheet("pan", true),
18983
+ switchSheet("zoom", false),
18984
+ ...COMBINE_TRANSITIONS.filter((t2) => t2.xfade !== null).map((t2) => switchSheet(XFADE_SWITCH_PREFIX + t2.id, false))
18985
+ ];
18986
+ var SPEAKER_SWITCH_IDS = SPEAKER_SWITCHES.map((s) => s.id);
18987
+ var SWITCHES_BY_ID = new Map(SPEAKER_SWITCHES.map((s) => [s.id, s]));
18988
+ function getSpeakerSwitch(id) {
18989
+ return SWITCHES_BY_ID.get(id);
18990
+ }
18991
+ var SPEAKER_EMPHASIS_STYLES = ["none", "scale", "border", "dim"];
18992
+ var EMPHASIS_STYLE_SET = new Set(SPEAKER_EMPHASIS_STYLES);
18993
+ function parseSpeakerEmphasisStyle(style) {
18994
+ if (typeof style !== "string") return [];
18995
+ return style.split("+").map((atom) => atom.trim()).filter((atom) => atom.length > 0);
18996
+ }
18997
+ function isKnownSpeakerEmphasisStyle(style) {
18998
+ const atoms = parseSpeakerEmphasisStyle(style);
18999
+ if (atoms.length === 0 || !atoms.every((atom) => EMPHASIS_STYLE_SET.has(atom))) return false;
19000
+ if (new Set(atoms).size !== atoms.length) return false;
19001
+ return !(atoms.includes("none") && atoms.length > 1);
19002
+ }
19003
+ var isObject = (v) => !!v && typeof v === "object";
19004
+ function speakerPresentationWarnings(edl) {
19005
+ const warnings = [];
19006
+ if (!isObject(edl)) return warnings;
19007
+ const safe = {
19008
+ ...edl,
19009
+ sources: Array.isArray(edl.sources) ? edl.sources : [],
19010
+ segments: Array.isArray(edl.segments) ? edl.segments : []
19011
+ };
19012
+ const rawAspect = isObject(safe.meta) ? safe.meta.targetAspect : void 0;
19013
+ const aspect = isEdlTargetAspect(rawAspect) ? rawAspect : void 0;
19014
+ if (rawAspect != null && aspect === void 0) {
19015
+ warnings.push(`meta.targetAspect "${String(rawAspect)}" is not a known target aspect (known: ${EDL_TARGET_ASPECTS.join(", ")})`);
19016
+ }
19017
+ safe.segments.forEach((seg, i) => {
19018
+ if (!isObject(seg) || !isObject(seg.layout)) return;
19019
+ const at = `segment[${i}] "${seg.id}"`;
19020
+ const layout = seg.layout;
19021
+ const sheet = typeof layout.mode === "string" ? getSpeakerLayout(layout.mode) : void 0;
19022
+ if (!sheet) {
19023
+ warnings.push(`${at}: unknown layout mode "${String(layout.mode)}" (known: ${SPEAKER_LAYOUT_IDS.join(", ")})`);
19024
+ } else {
19025
+ const slotCount = Array.isArray(layout.slots) ? layout.slots.length : 0;
19026
+ if (slotCount > 0 && !speakerLayoutAllows(sheet, { slotCount })) {
19027
+ const range = sheet.minSlots === sheet.maxSlots ? `${sheet.minSlots}` : `${sheet.minSlots}\u2013${sheet.maxSlots}`;
19028
+ warnings.push(`${at}: layout "${sheet.id}" takes ${range} slot(s), got ${slotCount}`);
19029
+ }
19030
+ if (aspect !== void 0 && !speakerLayoutAllows(sheet, { aspect })) {
19031
+ warnings.push(`${at}: layout "${sheet.id}" is not drawn for targetAspect ${aspect} (drawn for: ${sheet.aspects.join(", ")})`);
19032
+ }
19033
+ }
19034
+ if (isObject(layout.transition)) {
19035
+ const type = layout.transition.type;
19036
+ const sw = typeof type === "string" ? getSpeakerSwitch(type) : void 0;
19037
+ if (!sw) {
19038
+ warnings.push(`${at}: unknown layout transition "${String(type)}" (known: ${SPEAKER_SWITCHES.filter((s) => !s.overlaps).map((s) => s.id).join(", ")}, or ${XFADE_SWITCH_PREFIX}<id> for a combine-videos transition that is a real ffmpeg xfade \u2014 never ${XFADE_SWITCH_PREFIX}cut)`);
19039
+ } else if (sw.requiresSameSource && i > 0) {
19040
+ const prev = safe.segments[i - 1];
19041
+ const cur = resolveEdlSegmentSlots(safe, seg);
19042
+ const before = isObject(prev) ? resolveEdlSegmentSlots(safe, prev) : [];
19043
+ if (cur.length === 1 && before.length === 1 && cur[0].source !== before[0].source) {
19044
+ warnings.push(`${at}: switch "${sw.id}" moves within ONE picture source, but the previous segment shows "${before[0].source}" and this one "${cur[0].source}"`);
19045
+ }
19046
+ }
19047
+ }
19048
+ if (isObject(layout.emphasis) && !isKnownSpeakerEmphasisStyle(layout.emphasis.style)) {
19049
+ const style = String(layout.emphasis.style);
19050
+ const atoms = parseSpeakerEmphasisStyle(layout.emphasis.style);
19051
+ warnings.push(atoms.length > 0 && atoms.every((a) => EMPHASIS_STYLE_SET.has(a)) ? `${at}: emphasis style "${style}" \u2014 "none" must stand alone and no style may repeat` : `${at}: unknown emphasis style "${style}" (a "+"-joined set of: ${SPEAKER_EMPHASIS_STYLES.join(", ")})`);
19052
+ }
19053
+ });
19054
+ return warnings;
19055
+ }
19056
+
19057
+ // src/edl.ts
19058
+ var EDL_VERSION = 1;
19059
+ var EDL_SOURCE_ROLES = ["master-audio", "camera", "wide", "screen"];
19060
+ var KNOWN_SOURCE_ROLES = new Set(EDL_SOURCE_ROLES);
19061
+ function transcriptDurationSec(transcript) {
19062
+ if (!transcript || typeof transcript !== "object") return void 0;
19063
+ const t2 = transcript;
19064
+ let maxEndMs = 0;
19065
+ const scan = (rows) => {
19066
+ if (!Array.isArray(rows)) return;
19067
+ for (const row of rows) {
19068
+ const endMs = row?.endMs;
19069
+ if (typeof endMs === "number" && Number.isFinite(endMs) && endMs > maxEndMs) {
19070
+ maxEndMs = endMs;
19071
+ }
19072
+ }
19073
+ };
19074
+ scan(t2.words);
19075
+ scan(t2.segments);
19076
+ return maxEndMs > 0 ? maxEndMs / 1e3 : void 0;
19077
+ }
19078
+ function segmentTransitionOverlaps(t2) {
19079
+ return !!t2 && t2.type === "crossfade" && (t2.durationMs ?? 0) > 0;
19080
+ }
19081
+ function layoutTransitionOverlaps(t2) {
19082
+ return !!t2 && speakerSwitchOverlaps(t2.type) && (t2.durationMs ?? 0) > 0;
19083
+ }
19084
+ function overlapMsInto(seg) {
19085
+ if (segmentTransitionOverlaps(seg.transition)) return seg.transition.durationMs ?? 0;
19086
+ if (layoutTransitionOverlaps(seg.layout?.transition)) return seg.layout.transition.durationMs ?? 0;
19087
+ return 0;
19088
+ }
19089
+ function edlDurationMs(edl) {
19090
+ const starts = segmentOutputStarts(edl);
19091
+ if (starts.length === 0) return 0;
19092
+ const last = edl.segments[edl.segments.length - 1];
19093
+ return Math.max(0, Math.round(starts[starts.length - 1] + Math.max(0, last.outMs - last.inMs)));
19094
+ }
19095
+ function segmentOutputStarts(edl) {
19096
+ const starts = [];
19097
+ let cursor = 0;
19098
+ edl.segments.forEach((seg, i) => {
19099
+ if (i > 0) cursor -= overlapMsInto(seg);
19100
+ starts.push(Math.max(0, Math.round(cursor)));
19101
+ cursor += Math.max(0, seg.outMs - seg.inMs);
19102
+ });
19103
+ return starts;
19104
+ }
19105
+ var inRange = (v, lo = 0, hi = 1) => v >= lo && v <= hi;
19106
+ function regionIssues(r, where) {
19107
+ const out = [];
19108
+ for (const [k, v] of Object.entries(r)) {
19109
+ if (!Number.isFinite(v) || !inRange(v)) out.push(`${where}: region.${k}=${v} out of 0..1`);
19110
+ }
19111
+ if (r.w <= 0 || r.h <= 0) out.push(`${where}: region has non-positive w/h`);
19112
+ if (r.x + r.w > 1 + 1e-9) out.push(`${where}: region extends past right edge (x+w>1)`);
19113
+ if (r.y + r.h > 1 + 1e-9) out.push(`${where}: region extends past bottom edge (y+h>1)`);
19114
+ return out;
19115
+ }
19116
+ function validateEdl(edl) {
19117
+ const issues = [];
19118
+ const warnings = [];
19119
+ if (!Array.isArray(edl.segments) || !Array.isArray(edl.sources)) {
19120
+ edl = {
19121
+ ...edl,
19122
+ sources: Array.isArray(edl.sources) ? edl.sources : [],
19123
+ segments: Array.isArray(edl.segments) ? edl.segments : []
19124
+ };
19125
+ }
19126
+ if (edl.version !== EDL_VERSION) issues.push(`version must be ${EDL_VERSION}`);
19127
+ if (edl.clock !== "master" && edl.clock !== "output") issues.push(`clock must be "master" or "output"`);
19128
+ const sourceIds = /* @__PURE__ */ new Set();
19129
+ let masterAudioCount = 0;
19130
+ for (const s of edl.sources) {
19131
+ if (sourceIds.has(s.id)) issues.push(`duplicate source id "${s.id}"`);
19132
+ sourceIds.add(s.id);
19133
+ if (!s.url || !s.url.trim()) issues.push(`source "${s.id}": url is empty (media resolves from url)`);
19134
+ if (s.role === "master-audio") masterAudioCount++;
19135
+ else if (s.role != null && !KNOWN_SOURCE_ROLES.has(s.role)) {
19136
+ warnings.push(`source "${s.id}": unknown role "${s.role}" (known: ${EDL_SOURCE_ROLES.join(", ")})`);
19137
+ }
19138
+ if (s.region) issues.push(...regionIssues(s.region, `source "${s.id}"`));
19139
+ if (s.offsetMs !== void 0 && !Number.isFinite(s.offsetMs)) issues.push(`source "${s.id}": offsetMs not finite`);
19140
+ }
19141
+ if (masterAudioCount > 1) issues.push(`more than one source has role:"master-audio" (${masterAudioCount})`);
19142
+ if (edl.segments.length === 0) issues.push("segments is empty");
19143
+ edl.segments.forEach((seg, i) => {
19144
+ const at = `segment[${i}] "${seg.id}"`;
19145
+ if (!(seg.outMs > seg.inMs)) issues.push(`${at}: outMs (${seg.outMs}) must be > inMs (${seg.inMs})`);
19146
+ if (seg.inMs < 0) issues.push(`${at}: inMs negative`);
19147
+ if (seg.video && !sourceIds.has(seg.video)) issues.push(`${at}: video source "${seg.video}" not in sources`);
19148
+ else if (seg.video) {
19149
+ const vs = edl.sources.find((s) => s.id === seg.video);
19150
+ if (vs && vs.kind !== "video") issues.push(`${at}: video source "${seg.video}" is kind:"${vs.kind}", must be video`);
19151
+ }
19152
+ if (seg.audio && !sourceIds.has(seg.audio)) issues.push(`${at}: audio source "${seg.audio}" not in sources`);
19153
+ if (!seg.audio && masterAudioCount === 0 && !seg.video) {
19154
+ issues.push(`${at}: no audio source and no master-audio/video fallback`);
19155
+ }
19156
+ if (i === 0 && (seg.transition || seg.layout?.transition)) {
19157
+ issues.push(`${at}: segments[0] cannot have a transition ("into this segment" has no predecessor)`);
19158
+ }
19159
+ if (seg.transition && seg.layout?.transition) {
19160
+ issues.push(`${at}: both EdlSegment.transition and EdlLayout.transition set (pick one)`);
19161
+ }
19162
+ const ov = overlapMsInto(seg);
19163
+ if (ov > 0 && i > 0) {
19164
+ const prev = edl.segments[i - 1];
19165
+ const minAdj = Math.min(seg.outMs - seg.inMs, prev.outMs - prev.inMs);
19166
+ if (ov > 0.9 * minAdj + 1e-9) {
19167
+ issues.push(`${at}: overlap transition durationMs (${ov}) exceeds 0.9\xB7min(adjacent segment)=${(0.9 * minAdj).toFixed(1)} \u2014 ffmpeg xfade would error / be clamped`);
19168
+ }
19169
+ }
19170
+ if (seg.region) {
19171
+ issues.push(...regionIssues(seg.region, at));
19172
+ if (seg.layout?.slots && seg.layout.slots.length > 1) {
19173
+ issues.push(`${at}: segment.region is invalid when the layout has >1 slot (put the region on the slot)`);
19174
+ }
19175
+ }
19176
+ for (const slot of seg.layout?.slots ?? []) {
19177
+ if (!sourceIds.has(slot.source)) issues.push(`${at}: slot source "${slot.source}" not in sources`);
19178
+ else {
19179
+ const src = edl.sources.find((s) => s.id === slot.source);
19180
+ if (src && src.kind !== "video") issues.push(`${at}: slot source "${slot.source}" is kind:"${src.kind}", slots must be video`);
19181
+ }
19182
+ if (slot.weight !== void 0 && !inRange(slot.weight)) issues.push(`${at}: slot.weight=${slot.weight} out of 0..1`);
19183
+ if (slot.region) issues.push(...regionIssues(slot.region, `${at} slot "${slot.source}"`));
19184
+ }
19185
+ });
19186
+ for (const d of edl.dropped ?? []) {
19187
+ if (!(d.outMs > d.inMs)) issues.push(`dropped range [${d.inMs},${d.outMs}) is not positive`);
19188
+ for (const seg of edl.segments) {
19189
+ if (seg.inMs < d.outMs && d.inMs < seg.outMs) {
19190
+ issues.push(`dropped range [${d.inMs},${d.outMs}) overlaps kept segment "${seg.id}" [${seg.inMs},${seg.outMs})`);
19191
+ break;
19192
+ }
19193
+ }
19194
+ }
19195
+ warnings.push(...speakerPresentationWarnings(edl));
19196
+ return { ok: issues.length === 0, issues, warnings };
19197
+ }
19198
+ function validateEdlClipSet(set) {
19199
+ const issues = [];
19200
+ const warnings = [];
19201
+ if (set.version !== EDL_VERSION) issues.push(`clipset version must be ${EDL_VERSION}`);
19202
+ if (set.clips.length === 0) issues.push("clipset has no clips");
19203
+ set.clips.forEach((clip, i) => {
19204
+ const r = validateEdl(clip);
19205
+ if (!r.ok) issues.push(...r.issues.map((m) => `clip[${i}]: ${m}`));
19206
+ warnings.push(...r.warnings.map((m) => `clip[${i}]: ${m}`));
19207
+ });
19208
+ return { ok: issues.length === 0, issues, warnings };
19209
+ }
19210
+ function offsetFor(edl, sourceId) {
19211
+ if (!sourceId) return 0;
19212
+ return edl.sources.find((s) => s.id === sourceId)?.offsetMs ?? 0;
19213
+ }
19214
+ function remapMsThroughEdl(edl, sourceMs, sourceId) {
19215
+ const masterMs = sourceMs + offsetFor(edl, sourceId);
19216
+ const starts = segmentOutputStarts(edl);
19217
+ for (let i = 0; i < edl.segments.length; i++) {
19218
+ const seg = edl.segments[i];
19219
+ if (masterMs >= seg.inMs && masterMs < seg.outMs) {
19220
+ return Math.round(starts[i] + (masterMs - seg.inMs));
19221
+ }
19222
+ }
19223
+ return null;
19224
+ }
19225
+ function remapTranscriptThroughEdl(edl, transcript) {
19226
+ const off = offsetFor(edl, transcript.sourceId);
19227
+ const starts = segmentOutputStarts(edl);
19228
+ const mapWord = (w) => {
19229
+ const startMaster = w.startMs + off;
19230
+ const endMaster = w.endMs + off;
19231
+ if (startMaster === endMaster) {
19232
+ for (let i = 0; i < edl.segments.length; i++) {
19233
+ const seg = edl.segments[i];
19234
+ if (startMaster >= seg.inMs && startMaster < seg.outMs) {
19235
+ const out = Math.round(starts[i] + (startMaster - seg.inMs));
19236
+ return { ...w, startMs: out, endMs: out };
19237
+ }
19238
+ }
19239
+ return null;
19240
+ }
19241
+ for (let i = 0; i < edl.segments.length; i++) {
19242
+ const seg = edl.segments[i];
19243
+ const lo = Math.max(startMaster, seg.inMs);
19244
+ const hi = Math.min(endMaster, seg.outMs);
19245
+ if (lo < hi) {
19246
+ return {
19247
+ ...w,
19248
+ startMs: Math.round(starts[i] + (lo - seg.inMs)),
19249
+ endMs: Math.round(starts[i] + (hi - seg.inMs))
19250
+ };
19251
+ }
19252
+ }
19253
+ return null;
19254
+ };
19255
+ const words = [];
19256
+ for (const w of transcript.words) {
19257
+ const mapped = mapWord(w);
19258
+ if (mapped) words.push(mapped);
19259
+ }
19260
+ const mapSegment = (s) => {
19261
+ const startMaster = s.startMs + off;
19262
+ const endMaster = s.endMs + off;
19263
+ let outLo = null;
19264
+ let outHi = null;
19265
+ for (let i = 0; i < edl.segments.length; i++) {
19266
+ const seg = edl.segments[i];
19267
+ const lo = Math.max(startMaster, seg.inMs);
19268
+ const hi = Math.min(endMaster, seg.outMs);
19269
+ if (lo < hi) {
19270
+ const a = Math.round(starts[i] + (lo - seg.inMs));
19271
+ const b = Math.round(starts[i] + (hi - seg.inMs));
19272
+ if (outLo === null || a < outLo) outLo = a;
19273
+ if (outHi === null || b > outHi) outHi = b;
19274
+ }
19275
+ }
19276
+ if (outLo === null || outHi === null) return null;
19277
+ return { ...s, startMs: outLo, endMs: outHi };
19278
+ };
19279
+ const segments = transcript.segments?.map(mapSegment).filter((s) => s !== null);
19280
+ return { ...transcript, words, ...segments ? { segments } : {} };
19281
+ }
19282
+ function speakerTurns(transcript, opts) {
19283
+ const turns = [];
19284
+ for (const w of transcript.words) {
19285
+ const speaker = w.speaker ?? "spk";
19286
+ const last = turns[turns.length - 1];
19287
+ if (last && last.speaker === speaker && w.startMs - last.endMs <= opts.mergeGapMs) {
19288
+ last.endMs = Math.max(last.endMs, w.endMs);
19289
+ } else {
19290
+ turns.push({ speaker, startMs: w.startMs, endMs: w.endMs });
19291
+ }
19292
+ }
19293
+ return turns.filter((t2) => t2.endMs - t2.startMs >= opts.minTurnMs);
19294
+ }
19295
+ var num = (v, fallback = 0) => typeof v === "number" && Number.isFinite(v) ? v : fallback;
19296
+ var clamp012 = (v) => Math.min(1, Math.max(0, v));
19297
+ var str2 = (v) => typeof v === "string" ? v : void 0;
19298
+ function normalizeRegion(r) {
19299
+ if (!r || typeof r !== "object") return void 0;
19300
+ const o = r;
19301
+ if (["x", "y", "w", "h"].some((k) => typeof o[k] !== "number")) return void 0;
19302
+ const x = clamp012(num(o.x));
19303
+ const y = clamp012(num(o.y));
19304
+ const w = Math.min(clamp012(num(o.w)), 1 - x);
19305
+ const h = Math.min(clamp012(num(o.h)), 1 - y);
19306
+ if (w <= 0 || h <= 0) return void 0;
19307
+ return { x, y, w, h };
19308
+ }
19309
+ function normalizeEdl(input) {
19310
+ const o = input && typeof input === "object" ? input : {};
19311
+ const sources = Array.isArray(o.sources) ? o.sources.map((raw, i) => {
19312
+ const s = raw ?? {};
19313
+ const src = {
19314
+ id: str2(s.id) ?? `src-${i}`,
19315
+ url: str2(s.url) ?? "",
19316
+ kind: s.kind === "audio" ? "audio" : "video",
19317
+ ...s.offsetMs !== void 0 ? { offsetMs: Math.round(num(s.offsetMs)) } : {},
19318
+ ...str2(s.role) ? { role: s.role } : {},
19319
+ ...Array.isArray(s.speakers) ? { speakers: s.speakers.filter((x) => typeof x === "string") } : {},
19320
+ ...normalizeRegion(s.region) ? { region: normalizeRegion(s.region) } : {}
19321
+ };
19322
+ return src;
19323
+ }) : [];
19324
+ const segments = Array.isArray(o.segments) ? o.segments.map((raw, i) => {
19325
+ const s = raw ?? {};
19326
+ const region = normalizeRegion(s.region);
19327
+ const isFirst = i === 0;
19328
+ const t2 = isFirst ? void 0 : s.transition;
19329
+ const layout = normalizeLayout(s.layout, isFirst);
19330
+ const seg = {
19331
+ id: str2(s.id) ?? `seg-${i}`,
19332
+ inMs: Math.round(num(s.inMs)),
19333
+ outMs: Math.round(num(s.outMs)),
19334
+ ...str2(s.video) ? { video: str2(s.video) } : {},
19335
+ ...str2(s.audio) ? { audio: str2(s.audio) } : {},
19336
+ ...str2(s.speaker) ? { speaker: str2(s.speaker) } : {},
19337
+ ...t2 && (t2.type === "cut" || t2.type === "crossfade") ? { transition: { type: t2.type, durationMs: t2.type === "cut" ? 0 : Math.round(num(t2.durationMs)) } } : {},
19338
+ ...region ? { region } : {},
19339
+ ...layout ? { layout } : {},
19340
+ ...Array.isArray(s.labels) ? { labels: s.labels.filter((x) => typeof x === "string") } : {}
19341
+ };
19342
+ return seg;
19343
+ }) : [];
19344
+ const dropped = Array.isArray(o.dropped) ? o.dropped.map((raw) => {
19345
+ const d = raw ?? {};
19346
+ return { inMs: Math.round(num(d.inMs)), outMs: Math.round(num(d.outMs)), reason: str2(d.reason) ?? "manual" };
19347
+ }) : void 0;
19348
+ const meta = o.meta && typeof o.meta === "object" ? o.meta : void 0;
19349
+ return {
19350
+ version: EDL_VERSION,
19351
+ clock: o.clock === "output" ? "output" : "master",
19352
+ sources,
19353
+ segments,
19354
+ ...dropped ? { dropped } : {},
19355
+ ...o.derivedFrom && typeof o.derivedFrom === "object" ? { derivedFrom: { edlId: str2(o.derivedFrom.edlId) ?? "", clock: "output" } } : {},
19356
+ ...meta ? { meta } : {}
19357
+ };
19358
+ }
19359
+ function normalizeLayout(input, dropTransition = false) {
19360
+ if (!input || typeof input !== "object") return void 0;
19361
+ const o = input;
19362
+ const mode = str2(o.mode) || "single";
19363
+ const slots = Array.isArray(o.slots) ? o.slots.map((raw) => {
19364
+ const s = raw ?? {};
19365
+ const source = str2(s.source);
19366
+ if (!source) return null;
19367
+ const region = normalizeRegion(s.region);
19368
+ return {
19369
+ source,
19370
+ ...region ? { region } : {},
19371
+ ...str2(s.speaker) ? { speaker: str2(s.speaker) } : {},
19372
+ ...s.weight !== void 0 ? { weight: clamp012(num(s.weight)) } : {}
19373
+ };
19374
+ }).filter((x) => x !== null) : void 0;
19375
+ const emphasis = o.emphasis && typeof o.emphasis === "object" ? { style: str2(o.emphasis.style) ?? "none", durationMs: Math.round(num(o.emphasis.durationMs)) } : void 0;
19376
+ const transition = !dropTransition && o.transition && typeof o.transition === "object" ? { type: str2(o.transition.type) ?? "cut", durationMs: Math.round(num(o.transition.durationMs)) } : void 0;
19377
+ return {
19378
+ mode,
19379
+ ...slots ? { slots } : {},
19380
+ ...emphasis ? { emphasis } : {},
19381
+ ...transition ? { transition } : {}
19382
+ };
19383
+ }
19384
+ function normalizeTranscript(input) {
19385
+ const o = input && typeof input === "object" ? input : {};
19386
+ const words = Array.isArray(o.words) ? o.words.map((raw) => {
19387
+ const w = raw ?? {};
19388
+ const startMs = Math.round(num(w.startMs));
19389
+ return {
19390
+ text: str2(w.text) ?? "",
19391
+ startMs,
19392
+ // Never inverted: an endMs < startMs (garbage upstream) would be
19393
+ // silently dropped at remap; clamp it to a non-negative width.
19394
+ endMs: Math.max(startMs, Math.round(num(w.endMs))),
19395
+ ...str2(w.speaker) ? { speaker: str2(w.speaker) } : {},
19396
+ ...typeof w.confidence === "number" ? { confidence: w.confidence } : {}
19397
+ };
19398
+ }) : [];
19399
+ const segments = Array.isArray(o.segments) ? o.segments.map((raw) => {
19400
+ const s = raw ?? {};
19401
+ const startMs = Math.round(num(s.startMs));
19402
+ return { startMs, endMs: Math.max(startMs, Math.round(num(s.endMs))), text: str2(s.text) ?? "", ...str2(s.speaker) ? { speaker: str2(s.speaker) } : {} };
19403
+ }) : void 0;
19404
+ return {
19405
+ version: EDL_VERSION,
19406
+ ...str2(o.sourceId) ? { sourceId: str2(o.sourceId) } : {},
19407
+ ...str2(o.language) ? { language: str2(o.language) } : {},
19408
+ words,
19409
+ ...segments ? { segments } : {}
19410
+ };
19411
+ }
19412
+
19413
+ // src/edit-plan-contract.ts
19414
+ var EDIT_PLAN_MODES = ["tighten", "clips", "chapters"];
19415
+ var EDIT_PLAN_TIERS = ["economy", "standard", "premium"];
19416
+ var EDIT_PLAN_BUCKET_MINUTES = [15, 30, 60, 90, 120, 180];
19417
+ var EDIT_PLAN_MAX_MINUTES = 180;
19418
+ var EDIT_PLAN_DEFAULT_CLIP_COUNT = 8;
19419
+ var EDIT_PLAN_MAX_CLIP_COUNT = 50;
19420
+ function clampEditPlanClipCount(count) {
19421
+ if (typeof count !== "number" || !Number.isFinite(count) || count <= 0) return void 0;
19422
+ return Math.min(EDIT_PLAN_MAX_CLIP_COUNT, Math.max(1, Math.floor(count)));
19423
+ }
19424
+ var EDIT_PLAN_BASE_CREDIT_ID = "edit-plan";
19425
+ function editPlanBucketMinutes(durationSec) {
19426
+ const secs = typeof durationSec === "number" && Number.isFinite(durationSec) ? durationSec : EDIT_PLAN_MAX_MINUTES * 60;
19427
+ const mins = Math.max(1, Math.ceil(secs / 60));
19428
+ const capped = Math.min(mins, EDIT_PLAN_MAX_MINUTES);
19429
+ for (const b of EDIT_PLAN_BUCKET_MINUTES) if (capped <= b) return b;
19430
+ return EDIT_PLAN_BUCKET_MINUTES[EDIT_PLAN_BUCKET_MINUTES.length - 1];
19431
+ }
19432
+ function buildEditPlanCreditId(mode, tier, durationSec) {
19433
+ return `edit-plan:${mode}:${tier}:${editPlanBucketMinutes(durationSec)}m`;
19434
+ }
19435
+ function asEditPlanMode(v) {
19436
+ return v === "clips" || v === "chapters" ? v : "tighten";
19437
+ }
19438
+ function asEditPlanTier(v) {
19439
+ return v === "economy" || v === "premium" ? v : "standard";
19440
+ }
19441
+ function unwrapEditPlanOutput(outputData) {
19442
+ if (!outputData || typeof outputData !== "object") return outputData;
19443
+ const o = outputData;
19444
+ if (Array.isArray(o.clips)) return o.clips;
19445
+ if (Array.isArray(o.chapters)) return { version: EDL_VERSION, chapters: o.chapters };
19446
+ const { viaNodaroCloud: _viaNodaroCloud, ...rest } = o;
19447
+ return rest;
19448
+ }
19449
+
19450
+ export { ACCESS_LEVELS, ACTIVE_SCENE_HELPERS, ADVANCED_MODE_UNAVAILABLE_REASON, AGGREGATEABLE_TYPES, AGGREGATE_LANE_SOURCE_TYPES, AI_AVATAR_DURATION_BUCKETS, AI_AVATAR_MAX_AUDIO_SEC, AI_AVATAR_MAX_DURATION_SEC, AI_AVATAR_RESERVE_IDS, AI_WRITER_PROVIDERS, ALA_CARTE_BOARDS, ALL_CAPTION_STYLES, ANIMALS, ANIMAL_SUBCATEGORY_LABELS, ANIMAL_SUBCATEGORY_ORDER, ASPECT_RATIO_DIMENSIONS, AUDIO_ADDON_PROVIDERS, AUDIO_CROSSFADE_CURVES, AUDIO_CROSSFADE_CURVE_IDS, AUDIO_FX_PRESETS, AUDIO_FX_PRESET_LABELS, AUDIO_FX_PRESET_SET, AUDIO_FX_REVERB_PRESETS, AUDIO_PRODUCER_TYPES, AddBRollResultSchema, AnchorSceneStyleResultSchema, AssetRefSchema, AuditImagesResultSchema, AuditImagesShotEntrySchema, AuditPromptIssueSchema, AuditPromptResultSchema, AvatarPayloadError, BOARD_TO_ASSET_TYPE, BOARD_TO_COLUMN, BOARD_VARIANTS, BridgeToNextSceneInputSchema, BridgeToNextSceneResultSchema, CAPTION_LEVER_BOUNDS, CAPTION_LOOKS, CAPTION_LOOK_IDS, CAPTION_MAX_WORDS_PER_LINE_MAX, CAPTION_MAX_WORDS_PER_LINE_MIN, CATEGORY_DURATION_DEFAULTS, CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_ASSET_TYPES, CHARACTER_ASSET_VARIANTS, CHARACTER_ATTACH_COLUMNS, CHARACTER_FACETS, CHARACTER_FACET_IDS, CHARACTER_LORA_TRAINING_JOB_TYPE, CHARACTER_MOTION_PROVIDERS, CHARACTER_PICKER_DISPLAY_ORDER, CHARACTER_REFERENCE_PHOTO_KINDS, CHARACTER_STYLES, CHARACTER_VARIANT_ASSET_BUCKETS, CHAT_ENABLED_STAGES, CHAT_STAGES, CHAT_TURN_CAPS, CHAT_WIRED_STAGES, CINEMATIC_DEFAULT_DURATION_SEC, CINEMATIC_DEFAULT_RESOLUTION, CINEMATIC_MAX_DURATION_SEC, CINEMATIC_MAX_LOOKS, CINEMATIC_MAX_REFERENCE_IMAGES, CINEMATIC_MAX_REFERENCE_VIDEOS, CINEMATIC_MIN_DURATION_SEC, CINEMATIC_MIN_LOOKS, CINEMATIC_PROMPT_MAX, CINEMATIC_RESERVE_IDS, COLLABORATOR_ROLES, COLLECT_IN_HANDLE, COMBINE_TRANSITIONS, COMBINE_TRANSITION_GROUP_LABELS, COMBINE_TRANSITION_GROUP_ORDER, COMBINE_TRANSITION_IDS, COMPOSER_PLAN_FIELDS, COMPOSER_PLAN_MAP, CONTENT_TYPES_BY_PLATFORM, CREATURE_ATTACH_COLUMNS, CREDIT_BASE_USD, CREDIT_ROUNDING_RESOLUTION, CastCoverageCriticVerdictSchema, CharacterImageCriticVerdictSchema, CharacterMetadataSchema, ChatTurnResponseSchema, CriticIssueSchema, DEFAULT_AUDIO_CROSSFADE_CURVE_ID, DEFAULT_CAPTION_LOOK, DEFAULT_CARRIED_FRACTION, DEFAULT_CHARACTER_ANGLE_COUNT, DEFAULT_CHARACTER_EXPRESSION_COUNT, DEFAULT_CHARACTER_FACET, DEFAULT_FRAME_DELIVERY, DEFAULT_FRAME_FIT, DEFAULT_LABEL_BY_SOURCE, DEFAULT_LOCATION_USAGE_MODE, DEFAULT_OVERLAY_QR, DEFAULT_OVERLAY_SHAPE, DEFAULT_OVERLAY_TEXT, DEFAULT_PANEL_COUNT, DEFAULT_REF_IMAGE_MAX, DEFAULT_SECTIONS, DEFAULT_SUBTITLE_LOOK, DEFAULT_SUNO_MODEL, DEFAULT_TEMPLATE_CATEGORY, DEFAULT_TRANSCRIBE_NODE_PROVIDER, DEFAULT_TRANSCRIBE_PROVIDER, DEFAULT_USAGE_MODE, DEFAULT_VIDEO_ANALYSIS_MODEL, DEFAULT_VIDEO_ANALYSIS_TIER, DEFAULT_VIDEO_CLIP_COST, DEFAULT_VIDEO_DURATION_SEC, DEFAULT_VIDEO_PROVIDER, DEFAULT_VOICE_CHANGER_MODEL, DEFAULT_VOICE_DESIGN_MODEL, DETAIL_VARIANTS, DURATION_PRICED_PROVIDERS, DYNAMIC_PRODUCER_TYPES, DetectionResultSchema, EDIT_PLAN_BASE_CREDIT_ID, EDIT_PLAN_BUCKET_MINUTES, EDIT_PLAN_DEFAULT_CLIP_COUNT, EDIT_PLAN_MAX_CLIP_COUNT, EDIT_PLAN_MAX_MINUTES, EDIT_PLAN_MODES, EDIT_PLAN_TIERS, EDL_FULL_FRAME, EDL_SOURCE_ROLES, EDL_TARGET_ASPECTS, EDL_VERSION, EFFORT_TIER_BUMP, EMOTIONAL_BEAT, ENTITY_ASPECT_DEFAULTS, ENTITY_BUCKET_FIELDS, ENTITY_DB_ID_FIELD, ENTITY_IMAGE_HANDLE_TYPES, ENTITY_KIND_SCALAR_FIELDS, ENTITY_NAME_FIELD, ENTITY_NODE_KINDS, ENTITY_SCALAR_FIELDS, ENTITY_SECTIONS, ENTITY_STATUSES, ENTITY_TABLE, ENTITY_TOOL_RETRY_CAP, ENTITY_TYPES, EXECUTION_DATA_KEYS, EXECUTION_GRAPH_COMPOSED_PARAMETER_TYPES, EXTEND_VIDEO_PROVIDERS, EntityMetadataSchema, EntityRejectInputSchema, EntityStaleEventSchema, EntityStateChangeEventSchema, FACE_SWAP_PROVIDERS, FAL_LIP_SYNC_PROVIDERS, FAN_OUT_EACH_TYPES, FEATURED_ENTITIES, FILM_BASE_CREDITS, FLEXIBLE_INPUT_LIP_SYNC_PROVIDERS, FLUX2_RES_MP, FLUX_LORA_CHARACTER_MODEL_ID, FRAME_DELIVERIES, FRAME_DELIVERY_BY_PROVIDER, FRAME_FITS, FRAME_FIT_STRETCH_TOLERANCE, FRAME_MODE_ADAPTIVE_ONLY_ASPECT, FRAME_TARGET_HANDLES, FREECUT_EXPORT_COMPLETE, FREECUT_EXPORT_PROGRESS, FREECUT_READY, FREECUT_REQUEST_IMPORT, FURNITURE, FURNITURE_SUBCATEGORY_LABELS, FURNITURE_SUBCATEGORY_ORDER, FixContinuityInputSchema, FixContinuityResultSchema, GEMINI_OMNI_PROVIDERS, GENERATE_TEXT_DELIMITER, GLOBAL_MAX_DURATION_SECONDS, GRANTED_ACCESS, GROUP_HANDLE_PREFIX, GUIDANCE_SCALE_SUPPORT, GVP_ANCHOR_CHOICES, GVP_DEFAULT_PROVIDER, GVP_END_FRAME_PROVIDERS, GVP_EXTEND_PROVIDERS, GVP_SUPPORTED_PROVIDERS, GenerateMotionInputSchema, GenerateMotionResultSchema, HANDLE_PORT_SEPARATOR, HELPERS_SHIPPED_IN_1B3, HIGH_QUALITY_PROVIDERS, HINT_EXEMPT_PARAMETER_TYPES, I2I_MASK_SUPPORT, I2I_STRENGTH_SUPPORT, IDEOGRAM_PROVIDERS, IMAGE_ASPECT_RATIO_VALUES, IMAGE_CRITIC_LEAF_MODES, IMAGE_CRITIC_MAX_RETRIES, IMAGE_CRITIC_METADATA_KEYS, IMAGE_CRITIC_MIN_ADHERENCE_SCORE, IMAGE_CRITIC_MODES, IMAGE_CRITIC_UNRESOLVABLE, IMAGE_EDIT_PROVIDERS, IMAGE_GEN_PROVIDERS, IMAGE_I2I_PROVIDERS, IMAGE_MASK_MODE, IMAGE_OVERLAY_BASE_CREDITS, IMAGE_OVERLAY_VARIANT_CREDITS, IMAGE_PROMPT_MAX, IMAGE_REF_TYPES, IMAGE_TO_VIDEO_PROVIDERS, INPUT_FIELD_MAP2 as INPUT_FIELD_MAP, INPUT_NODE_TYPES, INSTAGRAM_ANALYSIS_CREDIT_ID, INSTAGRAM_CAROUSEL_MAX_ITEMS, INSTAGRAM_CAROUSEL_MIN_ITEMS, INSTAGRAM_HOSTS, INSTAGRAM_SCRAPE_CREDIT_COSTS, INSTAGRAM_SCRAPE_DEFAULT_COUNT, INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID, INSTAGRAM_SCRAPE_MAX_COUNT, INSTAGRAM_SCRAPE_MAX_SOURCES, INSTAGRAM_SCRAPE_MAX_TARGET_LENGTH, INSTAGRAM_SCRAPE_MODES, INSTAGRAM_SCRAPE_NODE_TYPE, INSTAGRAM_SCRAPE_PERIODS, INSTAGRAM_SCRAPE_TIERS, ITER_CLONE_PATTERN, ImageCriticIssueSchema, ImageCriticResultSchema, ImageCriticVerdictSchema, ImprovePromptInputSchema, ImprovePromptResultSchema, KEYFRAME_CREDITS_PER_SHOT, KINETIC_CAPTION_STYLES, KINETIC_ONLY_CAPTION_LEVER_KEYS, LANGUAGES, LEGACY_LOTTIE_HOST_REMAP, LEGACY_TEMPLATE_CATEGORIES, LIP_SYNC_DURATION_BUCKETS, LIP_SYNC_MAX_AUDIO_SECONDS, LIP_SYNC_PROVIDERS, LLM_FEATURE_DEFAULTS, LLM_MODALITY_CAPS, LLM_MODELS, LLM_MODEL_IDS, LLM_REASONING_EFFORTS, LLM_ROUTE_DEFAULTS, LLM_TEXT_INPUT_MAX, LLM_VENDOR_LABELS, LLM_VENDOR_ORDER, LOCATION_ASSET_TYPES, LOCATION_ASSET_VARIANTS, LOCATION_ATMOSPHERE_PROVIDERS, LOCATION_ATTACH_COLUMNS, LOCATION_BUCKET_TO_CATALOG_ID, LOCATION_PRESET_TO_CATALOG, LOCATION_REFERENCE_PHOTO_KINDS, LOCATION_REFERENCE_PHOTO_KIND_LABELS, LOCATION_USAGE_MODES, LOTTIE_OVERLAY_CATALOG, LOTTIE_SLOT_FIELD_PREFIX, LocationImageCriticVerdictSchema, LocationMetadataSchema, LocationsCoverageCriticIssueSchema, LocationsCoverageCriticVerdictSchema, MAX_CUSTOM_ENTRIES_PER_BOARD, MAX_IMAGE_PROMPT_CHARS_BY_PROVIDER, MAX_LOCATION_VARIANTS, MAX_NEGATIVE_PROMPT_CHARS_BY_PROVIDER, MAX_PANELS_PER_SHEET, MAX_TTS_CHARS_BY_PROVIDER, MAX_VIDEO_PROMPT_CHARS_BY_PROVIDER, MEMBER_STATUSES, META_ADS_ADVERTISER_MAX_RESULTS, META_ADS_ANALYSIS_CREDITS_PER_AD, META_ADS_ANALYSIS_CREDIT_ID, META_ADS_ANALYSIS_FOCUS_MAX, META_ADS_ANALYSIS_TIERS, META_ADS_FORMATS, META_ADS_NODE_MODES, META_ADS_PLATFORMS, META_ADS_SCRAPE_COUNT_OPTIONS, META_ADS_SCRAPE_CREDIT_COSTS, META_ADS_SCRAPE_DEFAULT_COUNT, META_ADS_SCRAPE_DEFAULT_COUNTRY, META_ADS_SCRAPE_FALLBACK_CREDIT_ID, META_ADS_SCRAPE_MAX_COUNT, META_ADS_SCRAPE_MAX_QUERY_LENGTH, META_ADS_SCRAPE_MAX_SOURCES, META_ADS_SCRAPE_MODES, META_ADS_SCRAPE_NODE_TYPE, META_ADS_SCRAPE_PERIODS, META_ADS_SCRAPE_STATUSES, META_ADS_SCRAPE_TIERS, MINIMAX_H3_DEFAULT_RESOLUTION, MINIMAX_H3_PROVIDERS, MODELS_WITH_REFERENCE_IMAGE_SUPPORT, MODEL_CATALOG, MODEL_KINDS, MODEL_PARAM_NODE_TYPES, MODEL_RECOMMENDATIONS, MODIFY_IMAGE_PROVIDERS, MOTION_COLUMN, MOTION_TRANSFER_PROVIDERS, MUSIC_PROVIDERS, MatchCutVerdictSchema, NATIVE_ADAPTIVE_ASPECT, NATIVE_NEGATIVE_PROMPT_MODELS, NATIVE_NEGATIVE_VIDEO_PROVIDERS, NEGATIVE_PROMPT_MAX, NODARO_IMPORT_FILES, NODARO_LOAD_TIMELINE, NODARO_LOAD_VIDEO, NODARO_RESET_PROJECT, NODE_DEFAULT_TYPES, NODE_MAPPABLE_FIELDS, NODE_PRESET_EXPORT_KIND, NODE_REF_PATTERN, NON_EN_LOCALE_IDS, NON_PROMPT_TEXT_LANES, NO_SPLIT_DELIMITER, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ASSET_VARIANTS, OBJECT_ATTACH_COLUMNS, OBJECT_MOTION_PROVIDERS, OBJECT_PICKER_NODE_TYPES, ORG_ERROR_CODES, ORG_KINDS, ORG_ROLES, ORG_STATUSES, OUTPUT_BEARING_NODE_STATUSES, OUTPUT_FIELD_MAP, OUTPUT_FORMATS, OVERLAY_ANCHORS, OVERLAY_FONTS, OVERLAY_FONT_IDS, OVERLAY_IMAGE_MASKS, OVERLAY_LAYER_KINDS, OVERLAY_MAX_VARIANTS, OVERLAY_PLATFORMS, OVERLAY_PLATFORM_IDS, OVERLAY_SHAPES, OVERLAY_TEXT_ALIGNS, OVERLAY_VARIANT_HANDLE_PREFIX, ObjectMetadataSchema, OptimizeForModelInputSchema, OptimizeForModelResultSchema, OrgSettingsSchema, PARAMETER_NODE_TYPES, PASSTHROUGH_TYPES, PAYG_RETENTION_DAYS, PER_FORMAT_DURATION_BOUNDS, PICKER_TO_COMBINE_TRANSITION, PIPELINE_ACTIVATION_MODES, PIPELINE_FORMATS, PIPELINE_HARD_TIMEOUT_MS, PIPELINE_MODEL_STAGES, PIPELINE_MODES, PIPELINE_OUTPUT_RESOLUTIONS, PIPELINE_PINNABLE_IMAGE_MODELS, PIPELINE_PINNABLE_SCRIPT_LLMS, PIPELINE_PINNABLE_VIDEO_MODELS, PIPELINE_STAGE_NAMES, PIPELINE_STAGE_TIMEOUT_MS, PIPELINE_TYPES, PLACEHOLDER_CHARACTER_NAME, PLATFORM_LABELS, PLATFORM_SPECS, PRESET_APPLY_CLEAR_KEYS, PRESET_EXCLUDED_KEYS, PRESET_LABELS, PRESET_SETTING_KEYS, PRICING_DEFAULT_DURATION_SEC, PRICING_DEFAULT_RESOLUTION, PRO3D_RENDER_ASPECT_RATIOS, PRO3D_RENDER_CREDIT_ID, PRO3D_RENDER_DEFAULT_ENGINE, PRO3D_RENDER_DEFAULT_QUALITY, PRO3D_RENDER_DEFAULT_REPAIR_PASSES, PRO3D_RENDER_DEFAULT_STYLE, PRO3D_RENDER_ENGINES, PRO3D_RENDER_LABEL, PRO3D_RENDER_LIMITS, PRO3D_RENDER_MAX_REPAIR_PASSES, PRO3D_RENDER_MIN_REPAIR_PASSES, PRO3D_RENDER_NODE_TYPE, PRO3D_RENDER_PROMPT_MAX, PRO3D_RENDER_QUALITY_PROFILES, PRO3D_RENDER_SOURCE_KINDS, PRO3D_RENDER_STYLES, PROJECTED_TRIGGER_NODE_TYPES, PROMPT_HARD_CEILING, PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY, PROVIDER_DIRECTIVE_DEFAULTS, PROVIDER_PLACEHOLDER_PREFIX, PipelineCompletedEventSchema, PipelineConfigSchema, PipelineDriftSummarySchema, PipelineEditorDecisionsReadyEventSchema, PipelineForkedEventSchema, PipelineInputSchema, PipelineMusicReadyEventSchema, PipelineStageNameSchema, PipelineStageStatusSchema, PipelineStateSchema, PipelineStatusSchema, PresetSettingsSchema, QA_CHECK_PROVIDERS, REASONING_OUTPUT_FLOOR, REDUCE_STRATEGIES, REDUCE_STRATEGY_IDS, REFERENCE_BOARD_PROVIDERS, REFERENCE_BOARD_TEMPLATES, REFERENCE_HANDLE_MAP, REFERENCE_ROLE_PRESETS, REF_HANDLE_CATEGORY, REF_IMAGE_MAX_LIMITS, REF_TOKEN_NAMESPACE_PREFIXES, RENDERING_SPEED_SUPPORT, RENDER_VIDEO_CREDIT_ID, REPEATABLE_NODE_TYPES, REPEAT_PLACEHOLDER, REPLICATE_LIP_SYNC_PROVIDERS, RESERVED_TEMPLATE_VARS, SCENE3D_ASSERTION_RESTORED_CODE, SCENE3D_ASSET_KINDS, SCENE3D_ASSET_ROLES, SCENE3D_ASSET_ROLE_KINDS, SCENE3D_AUTHORING_ASSUMPTION_CODE, SCENE3D_AUTHORING_ENGINES, SCENE3D_BASIC_ENGINE, SCENE3D_BASIC_SCHEMA_VERSION, SCENE3D_CAMERA_TRACK_FORMAT, SCENE3D_CAMERA_TRACK_LIMITS, SCENE3D_CAMERA_TRACK_VERSION, SCENE3D_CLAY_LIGHTING_PRESETS, SCENE3D_DEFAULT_ADVANCED_ENGINE, SCENE3D_DEFAULT_DURATION_SECONDS, SCENE3D_DEFAULT_ENTITY_CAPABILITIES, SCENE3D_DEFAULT_FPS, SCENE3D_EDIT_NODE_TYPE, SCENE3D_ENTITY_CAPABILITIES, SCENE3D_ENTITY_ROLES, SCENE3D_GENERATE_NODE_TYPE, SCENE3D_GLB_EXTRAS_ALLOWLIST, SCENE3D_GLB_EXTRAS_ENTITY_ID, SCENE3D_GLB_EXTRAS_MATERIAL_ROLE, SCENE3D_GLB_EXTRAS_SUBPART_ID, SCENE3D_LIMITS, SCENE3D_PLAN_FIELD, SCENE3D_PLAN_TYPE, SCENE3D_PRIMITIVES, SCENE3D_PRIMITIVE_MATERIAL_ROLE, SCENE3D_REMEDY_AUTO_APPLIED_CODE, SCENE3D_RENDERER_ASSET_KINDS, SCENE3D_RENDER_BASE_MAX_PX, SCENE3D_RENDER_TIERS, SCENE3D_RENDER_TIER_MULTIPLIERS, SCENE3D_RENDER_XLARGE_MIN_AREA_PX, SCENE3D_REVIEW_REFUSED_CODE, SCENE3D_REVIEW_UNAVAILABLE_CODE, SCENE3D_REVIEW_UNAVAILABLE_REASONS, SCENE3D_SCHEMA_VERSION, SCENE3D_SCHEMA_VERSION_V2, SCENE3D_SUPPORTED_SCHEMA_VERSIONS, SCENE3D_V2_CONTENT_HASH_EXCLUDED, SCENE3D_V2_ENGINES, SCENE3D_V2_LIMITS, SCENE3D_V2_OVERRIDE_OPERATION_VERSION, SCENE3D_V2_PRIMITIVES, SCENE_HELPER_NAMES, SCHEDULE_EVERY_LIMITS, SCHEDULE_RULE_KINDS, SCHEDULE_TRIGGER_NODE_TYPE, SCRAPER_ACTOR_LABELS, SCRAPER_CREDIT_COSTS, SCRAPER_OUTPUT_FIELDS, SCRIPT_PROVIDERS, SEASONS, SECTION_BOARD, SECTION_KINDS, SEEDANCE_2_5_REF_LIMITS, SEEDANCE_2_CONTINUATION_REF_SEC, SEEDANCE_2_EXTEND_STITCH, SEEDANCE_2_PROVIDERS, SEEDANCE_2_R2V_MAX_AUDIO_SEC_BY_PROVIDER, SEEDANCE_2_R2V_MIN_REF_VIDEO_SEC, SEEDANCE_2_REF_LIMITS, SEEDANCE_LIP_SYNC_PROVIDERS, SEEDANCE_VIDEO_EDIT_PROVIDERS, SEEDANCE_VIDEO_EDIT_SHAPE, SEED_SUPPORT, SEPARATOR_DISPLAY, SEPARATOR_PRESETS, SHEET_ASPECTS, SHEET_BACKGROUNDS, SHEET_PRESETS, SHEET_SKINS, SHEET_TYPES, SHORT_FILM_ANGLE_COUNT, SHORT_FILM_EXPRESSION_COUNT, SHORT_FILM_VARIANT_THRESHOLD_SEC, SLOT_TOKEN_RE, SMART_CUT_WINDOW_DEFAULT, SMART_CUT_WINDOW_MAX, SMART_CUT_WINDOW_MIN, SOCIAL_POST_NODE_TYPES, SOCIAL_VIDEO_HOSTS, SPEAKER_EMPHASIS_STYLES, SPEAKER_LAYOUTS, SPEAKER_LAYOUT_IDS, SPEAKER_SWITCHES, SPEAKER_SWITCH_IDS, STAGE_PATCH_SCHEMA, STATIC_CAPTION_STYLES, STRUCTURAL_SECTIONS, STRUCTURED_VISION_MODELS, STUDIO_DEPENDENT_FRAMES_CAPABILITY, STUDIO_SHOT_TRANSIENT_KEYS, STUDIO_TRANSIENT_KEYS, SUBMISSION_STATUSES, SUNO_ACTIVE_MODELS, SUNO_ADD_TRACK_MODELS, SUNO_DURATION_MODELS, SUNO_FIELD_HANDLE_FIELDS, SUNO_HARD_CEILING, SUNO_LEGACY_MODELS, SUNO_MODELS, SUNO_SELECT_OPERATIONS, SUNO_TEXT_MAX, SUNO_TITLE_MAX, SUNO_TRACK_SOURCE_TYPES, SUNO_VERSION_CREDIT_KEYS, SUNO_VERSION_PRICED_OPERATIONS, SUPPORTED_FONT_NAMES, SURROUND_DIRECTIONS, SWITCHX_BLOCK_FRAMES, SWITCHX_FRAME_TIERS, SceneHelperNameSchema, SceneInputModeSchema, SceneMetadataSchema, SceneNodeDataSchema, SceneSpecSchema, ScriptCriticVerdictSchema, SequenceExecutionRequiredError, ShotSpecSchema, ShowrunnerPlanSchema, StageAwaitingSubGateEventSchema, StoryboardCohesionCriticVerdictSchema, StyleDirectivesSchema, SubGateNameSchema, T2I_TO_I2I_VARIANT, TASK_CHAINED_EDIT_PROVIDERS, TELEGRAM_TRIGGER_NODE_TYPE, TEMPLATE_CATEGORIES, TEXT_TO_AUDIO_PROVIDERS, TEXT_TO_VIDEO_PROVIDERS, TIER_MAX_PIPELINE_COST_CREDITS, TIER_PIPELINE_PARALLELISM, TILT_CARRIED_FRACTION, TOPAZ_DEFAULT_UPSCALE_FACTOR, TOPAZ_UPSCALE_FACTORS, TRANSCRIBE_LANES, TRANSCRIBE_PROVIDERS, TRANSCRIBE_PROVIDER_CAPABILITIES, TRANSIENT_RUNTIME_KEYS, TTS_PROVIDERS, TTS_TEXT_MAX, TWO_K_RESOLUTION_PROVIDERS, TransitionTypeSchema, UPSCALE_IMAGE_PROVIDERS, USAGE_GROUP_BYS, USAGE_MODES, VARIABLES_HANDLE_ID, VARIABLE_PRICING_MODELS, VEHICLES, VEHICLE_SUBCATEGORY_LABELS, VEHICLE_SUBCATEGORY_ORDER, VEO_PROVIDERS, VIDEO_ANALYSIS_AUDIO_MODES, VIDEO_ANALYSIS_BUCKET_CREDITS, VIDEO_ANALYSIS_CLIP_TRANSITIONS_IN, VIDEO_ANALYSIS_DEFAULT_VARIATION, VIDEO_ANALYSIS_DURATION_BUCKETS, VIDEO_ANALYSIS_DURATION_TOLERANCE_SEC, VIDEO_ANALYSIS_ENTITY_SOURCES, VIDEO_ANALYSIS_FACELESS_ANGLES, VIDEO_ANALYSIS_LEGACY_MODELS, VIDEO_ANALYSIS_LLM_MODELS, VIDEO_ANALYSIS_MAX_DURATION_SEC, VIDEO_ANALYSIS_MAX_SCENE_SEC, VIDEO_ANALYSIS_MAX_VARIATIONS, VIDEO_ANALYSIS_MIXED_TIERS, VIDEO_ANALYSIS_SHOT_ANGLES, VIDEO_ANALYSIS_SPEED_EFFECTS, VIDEO_ANALYSIS_STORY_JUMPS, VIDEO_ANALYSIS_TEXT_KINDS, VIDEO_ANALYSIS_TIERS, VIDEO_ANALYSIS_TIER_LABELS, VIDEO_ANALYSIS_TIER_ORDER, VIDEO_ANALYSIS_TIMES_OF_DAY, VIDEO_ANALYSIS_TRANSITIONS, VIDEO_ANALYSIS_VARIATION_SLUGS, VIDEO_ANALYSIS_VISUAL_EFFECTS, VIDEO_ANALYSIS_WINDOW, VIDEO_AUDIO_CAPABILITY, VIDEO_AUDIT_BUCKET_CREDITS, VIDEO_CLIP_CREDITS, VIDEO_CRITIC_CREDITS_PER_SHOT, VIDEO_CRITIC_FRAME_MODES, VIDEO_CRITIC_MAX_RETRIES, VIDEO_CRITIC_METADATA_KEYS, VIDEO_CRITIC_MIN_ADHERENCE_SCORE, VIDEO_DURATION_AUTO, VIDEO_DURATION_TIERS, VIDEO_GEN_COLLAPSED_T2V_IDS, VIDEO_GEN_PROVIDERS, VIDEO_INPUT_LIP_SYNC_PROVIDERS, VIDEO_LINK_TOLERANT_CONSUMER_TYPES, VIDEO_MODEL_CAPS, VIDEO_MODE_ALIASES, VIDEO_ONLY_PARAMETER_NODE_TYPES, VIDEO_OUTPUT_CANVAS, VIDEO_PRODUCER_TYPES, VIDEO_PROMPT_MAX, VIDEO_PROVIDERS_REQUIRING_IMAGE, VIDEO_PROVIDERS_WITHOUT_DISPATCH, VIDEO_REF_LIMITS_BY_PROVIDER, VIDEO_REF_VIDEO_DURATION_LIMITS, VIDEO_TO_VIDEO_NODE_PROVIDERS, VIDEO_TO_VIDEO_PROVIDERS, VIDEO_UPSCALE_PROVIDERS, VIDEO_UTIL_PRICING, VIDEO_VARIABLE_PRICING, VOICE_CHANGER_MODELS, VOICE_CHANGER_MODEL_IDS, VOICE_DESIGN_MODELS, ValidateMatchCutInputSchema, ValidateMatchCutResultSchema, VideoCriticVerdictSchema, VoiceMatchSchema, WAN_3_DEFAULT_RESOLUTION, WAN_3_PROVIDERS, WARDROBE_VARIANTS, WEAPONS, WEAPON_SUBCATEGORY_LABELS, WEAPON_SUBCATEGORY_ORDER, WEBHOOK_TRIGGER_NODE_TYPE, WORKFLOW_VISIBILITIES, WORKSPACE_HEADER, WORKSPACE_HEADER_LOWER, WORKSPACE_ROLES, WorkspaceSettingsSchema, YOUTUBE_HOSTS, adCreativeAnalysisFrom, aggregateByType, aiAvatarReserveCreditId, alignedFieldList, analyzedSceneSchema, applyDefaultVideoSelection, applyHandleInputOverride, applyRange, applyRangeIndices, applyScene3DEditOperations, applyScene3DV2EditOperations, applySlots, applyVideoAudioToggle, applyVideoNegativePrompt, asEditPlanMode, asEditPlanTier, aspectRatioFromDims, aspectRatioOptionsByKind, aspectRatioToNumber, assembleNarratedVideoCredits, assertCanvasExecutionAllowed, autoStrokeWidth, availableReasoningEfforts, bucketSecondsFromAuditCreditId, bucketSecondsFromCreditId, buildBoardPrompt, buildChildrenByParent, buildConditionVariables, buildCreditModelIdentifier, buildEditPlanCreditId, buildExpressionFromVisual, buildFeedMaps, buildInstagramScrapeCreditId, buildLipSyncCreditId, buildLlmCreditIdentifier, buildMetaAdsScrapeCreditId, buildModelMenu, buildModelTree, buildMotionCreditModelIdentifier, buildNodePresetExport, buildPanelPrompt, buildPro3DRenderSource, buildProgressSegments, buildRangeLabel, buildScraperCreditId, buildVideoAnalysisCreditId, buildVideoAuditCreditId, buildVideoCreditModelIdentifier, calculateCombinedProgress, calculateMonetizationMarkup, calculateMonetizedCost, calculateProgress, canonicalScene3DPlanV2Json, canonicalVarName, captionRoutesToRemotion, centreCropToAspect, characterBoardItems, characterBucketDisplayRank, characterMentionSlug, characterMentionableAssetArrays, characterSheetRefItems, characterVariantAssetArrays, checkRefVideoDurations, cinematicCreditId, clampCinematicDuration, clampEditPlanClipCount, clampInstagramFeaturedIndex, clampMetaAdsFeaturedIndex, clampSmartCutWindow, classifyCreativeFormat, classifyRefToken, cleanOrphanedItems, clearImageCriticMetadata, clearVideoCriticMetadata, clipLookSchema, collectAncestorRefs, combineSameLabelRefs, compactWithRows, computeAggregateLanes, computeFrameFitPlan, computeScene3DPlanV2ContentHash, countRefModalityEdges, creditRangesAll, creditsToUsd, decodeProviderItem, defaultCarriedFraction, defaultResolutionFor, defaultRoleForSource, defaultVideoAspectRatio, deriveLinkedFields, deriveLottieSlotFields, deriveSlotRefs, describeEdgeBehavior, describeMaskRegion, describeNodeAdjustments, describeSlotControl, detectVideoLinkPlatform, dropUnknownBindings, dropUnknownSpeakers, durationsByMode, editPlanBucketMinutes, editPlanSourceDurationSec, edlDurationMs, effectiveReasoningEffort, encodeProviderItem, ensureLocaleCatalogLoaded, entityHydrationColumns, entityMentionSlug, entityMentionSlugForRef, entityScalarFields, entitySlotSchema, entryMatchesQuery, estimateCombineVideosCredits, estimateFilmCredits, estimateLoopTrimAddonCredits, estimateLoopVideoCredits, estimateScriptDurationSec, estimateSheetCost, estimateTrimVideoCredits, evaluateCondition, evaluateConditionGroup, evaluateJsonExpression, evaluateJsonPath, expandExtraRefsToConnectedReferences, expandItemsWithRepeat, extractAllGeneratedResults, extractCharacterLoraFields, extractGeneratedJsonAsList, extractPresetData, extractReferencedLabels, extractVideoDurationFromNode, fanOutTextFeedsPrompt, featuredInstagramOutputs, featuredMetaAdOutputs, fieldKeyFromHandle, filterCloneNodes, findCharacterMentionTokens, findEntityMentionTokens, findImageMentionTokens, findLocationMentionTokens, findSeedance2AudioOverLimit, findWordlessTranscriptFeeds, firstSightExtraRole, flattenItems, getAnimal, getAnimalLabel, getAnimalPromptHint, getAnimalTerm, getAspectRatioOptions, getAudioCrossfadeCurve, getCharacterFacet, getCombineTransition, getCreditRange, getDurationsForModel, getEffectiveRepeatCount, getFeaturedEntities, getFurniture, getFurnitureLabel, getInputFieldSchema, getInputNodes, getItemSortId, getLipSyncMaxAudioSeconds, getLlmModalityCaps, getLlmModel, getLlmTier, getLocaleDirection, getMaxImagePromptChars, getMaxNegativePromptChars, getMaxSunoPromptChars, getMaxSunoStyleChars, getMaxTtsChars, getMaxVideoPromptChars, getModel, getNodeLabel, getNodeResult, getOutputNodes, getOutputType, getParameterValue, getQualityOptions, getResolutionOptions, getRouteReachableNodeIds, getSpeakerLayout, getSpeakerSwitch, getStrategy, getTargetField, getValidValues, getVehicle, getVehicleLabel, getVideoAudioCapability, getWeapon, getWeaponLabel, groupByFamily, groupByKindAndFamily, groupHandleId, groupLlmModelsByVendor, hasContiguousSegmentDurations, hasFeature, hasUrlParserHazard, hexToRgbaArray, hostnameMatchesAllowlist, humanizeSlotSid, imageMentionSlug, imageMentionSlugForRef, imageOverlayBillableVariants, imageOverlayCredits, imageReferenceLimit, inferMusicVideo, instagramAnalysisCreditId, instagramAnalysisTierFrom, instagramScrapeCreditIdFromNode, instagramScrapeMode, instagramScrapeSources, instagramScrapeTier, isAggregateableType, isAutoVideoDuration, isCharacterAspectRatio, isCollectInEdge, isCronExpression, isDefaultSelectorConfig, isEdlTargetAspect, isExpandedClone, isFacebookPageUrl, isFanOutUrlItem, isFlux2Model, isGeminiOmniProvider, isGvpSupportedProvider, isHandleInputWired, isInstagramScrapeCount, isInstagramScrapeMode, isKineticCaptionStyle, isKnownScene3DEngine, isKnownSpeakerEmphasisStyle, isLegacySunoModel, isLocationUsageMode, isMetaAdsFormat, isMetaAdsPlatform, isMetaAdsScrapeCount, isMetaAdsScrapeMode, isMetaCdnImageUrl, isMinimaxH3Provider, isObjectAspectRatio, isOversizedScene, isPaygRetentionActive, isPerSecondLipSyncProvider, isPro3DRenderJobOutput, isPro3DRenderQuote, isPro3DRenderRenderOnly, isProjectedTriggerNodeType, isRtlText, isScene3DAuthoringEngine, isScene3DCameraTrack, isScene3DHttpUrl, isScene3DPlan, isScene3DPlanV1, isScene3DPlanV2, isScene3DReviewUnavailableReason, isScene3DSchemaVersionSupported, isScraperActor, isSeedance2Provider, isSeedanceVideoEditProvider, isSocialVideoUrl, isTemplateCategory, isTiltDirection, isUsageMode, isValidTimezone, isVeoProvider, isVideoAnalysisMixedTier, isVideoAnalysisTier, isWan3Provider, jsonResultToList, knownEntitySlugsFromRefs, knownImageSlugsFromRefs, legacyScheduleToRules, listBoardTemplates, listModels, listSlotSids, liveRowColumn, llmRouteDefaults, localMinuteKey, localTimeIn, locationMentionSlug, locationReferencePhotoKindLabel, locationUsageModeLabel, mapAspectRatio, mapQuality, mapShotIntentToProviderDirectives, matchVariant, matchesCron, matchesCronField, maxSegmentSecFor, maxSegmentsFor, maxVideoDurationSec, measuredCanvasCombinations, mergeClipLook, mergeEdlSourceOffsets, mergeExposedSettings, mergeNodeInputOverrides, metaAdsAdvertisersFrom, metaAdsAnalysisCreditId, metaAdsAnalysisTier, metaAdsAnalysisTierFrom, metaAdsNodeMode, metaAdsScrapeCreditIdFromNode, metaAdsScrapeSources, metaAdsScrapeTier, metaAdsScrapeWireSources, migrateEdgeOutputMode, migrateToItems, minSegmentSecFor, minimalRatioDimensions, modelIdsByKindMode, modelToNodeTarget, modelsForInputMode, modelsWithFeature, motionGraphicsFeature, newScene3DRevisionId, nextScheduleRuns, nodeFeedsAnything, nodeStateMayCarryOutput, normalizeCaptionNumericLevers, normalizeEdl, normalizeLottieLayers, normalizeMinimaxH3Resolution, normalizeModelInput, normalizeNodeModelParams, normalizePinterestUrl, normalizeRoleSlug, normalizeScheduleRule, normalizeScheduleRules, normalizeTemplateCategory, normalizeTranscript, normalizeVideoRequestParams, normalizeWan3Resolution, orderedLlmModels, overlayFontById, overlayImageEffectsSchema, overlayPlatformById, overlayQrStyleSchema, overlayShapeElement, overlayShapeStyleSchema, overlayStrokeSchema, overlayTextStyleSchema, overlayVariantHandle, overlayVariantIdFromHandle, parseAspectToken, parseAttributedDialogue, parseCharacterMentionToken, parseEntityMentionToken, parseGroupHandle, parseHandleId, parseImageMentionToken, parseListExpression, parseLocationMentionToken, parseNodePresetExport, parseNodeRef, parseScene3DCameraTrackJson, parseScene3DPlanV2Json, parseSpeakerEmphasisStyle, pickAiAvatarBucket, pickIds, pickLipSyncBucket, pickSwitchXFrameTier, pickVideoAnalysisBucket, planFanOut, planSheetGeneration, planSheetPanels, preferredInputModeForModel, presentTypes, presetApplyClearKeys, presetDataMatches, presetEntries, previewHorizonMs, pricedOutputDurationSec, pricedVideoSelection, pro3DRenderCoreOutputSchema, pro3DRenderFrameUnit, pro3DRenderJobOutputSchema, pro3DRenderProducedSchemaVersion, pro3DRenderQuoteSchema, pro3DRenderReviewVerdictSchema, pro3DRenderShotStillSchema, pro3DRenderShotStills, pro3DRenderTimingOverrides, qualityOptionsByKind, readPromptAffixes, reasoningOutputFloor, refHandleCategory, referenceModalityForHandle, referenceSheetCreditId, registerCatalogSidecars, registerSidecarLoaders, remapMsThroughEdl, remapTranscriptThroughEdl, renderAnalyzedScene, renderVideoCreditId, requiresSequenceExecution, resetCatalogSidecars, resolutionOptionsByKind, resolveAiAvatarCreditId, resolveAudioCrossfadeCurve, resolveCaptionLevers, resolveCaptionLook, resolveCharacterAspectRatio, resolveCinematicCreditId, resolveConditionValue, resolveDefaultRole, resolveDescription, resolveDialogueVoices, resolveEdlSegmentSlots, resolveEffectiveSourceType, resolveEffectiveTier, resolveEntityAspect, resolveFieldMappings, resolveFrameDelivery, resolveFrameFitAspect, resolveGvpAnchorWire, resolveImageGenCreditIdentifier, resolveIndex, resolveInstagramScrapeCreditId, resolveLabel, resolveListExpression, resolveListFanOut, resolveLlmCreditId, resolveLocationFields, resolveLocationPresetCatalog, resolveLottieOverlaySrc, resolveMetaAdsScrapeCreditId, resolveNodeRefs, resolveNormalizedImageGen, resolveObjectAspectRatio, resolveOutputCanvas, resolvePipelineModel, resolveRelativeWindowToken, resolveScene3DAuthoringEngine, resolveScraperCreditId, resolveSelectorRefs, resolveSeparator, resolveSheetSections, resolveSlideshowTransition, resolveSourceThroughConnectedList, resolveStoredTier, resolveSwitchXCreditId, resolveTemplateCategory, resolveTopazUpscale, resolveVideoAnalysisModel, resolveVideoLinkOutput, resolveVideoModeForInputs, resolveVideoProviderForMode, resolveXfadeName, rewriteSceneBindings, rewriteSlotTokens, rewriteSpeakerSlots, rgbaArrayToHex, roleToPhrase, rotationVec3Schema, ruleMatches, runSelector, safetyRetryPolicy, sanitizeRole, scaleVec3Schema, scene3DAcceptedSchemaVersionsSchema, scene3DAnchorNameSchema, scene3DAnchorSchema, scene3DAnyPlanSchema, scene3DAssetAnimationSchema, scene3DAssetIdSchema, scene3DAssetRefSchema, scene3DCameraChangesSchema, scene3DCameraKeyframeSchema, scene3DCameraSampleSchema, scene3DCameraSchema, scene3DCameraTrackIssues, scene3DCameraTrackObjectSchema, scene3DCameraTrackPlanIssues, scene3DCameraTrackSchema, scene3DClayLightingSchema, scene3DColorSchema, scene3DDeepEqual, scene3DEasingSchema, scene3DEditOperationSchema, scene3DEditOperationsSchema, scene3DEngineIdSchema, scene3DEntityAcceptsOverlay, scene3DEntityCapabilitySchema, scene3DEntityV2Schema, scene3DEntityVisualSchema, scene3DIdSchema, scene3DInputAssetSchema, scene3DInputAssetsForEngine, scene3DInputAssetsSchema, scene3DJsonByteLength, scene3DLightingChangesSchema, scene3DLightingSchema, scene3DMaterialBindingSchema, scene3DMaterialNameSchema, scene3DMaterialRoleSchema, scene3DNodeIdSchema, scene3DNodeNameSchema, scene3DObjectChangesSchema, scene3DObjectKeyframeSchema, scene3DObjectSchema, scene3DOverrideSchema, scene3DPlanIssues, scene3DPlanSchema, scene3DPlanSchemaVersion, scene3DPlanV1Issues, scene3DPlanV1ObjectSchema, scene3DPlanV1Schema, scene3DPlanV2Issues, scene3DPlanV2ObjectSchema, scene3DPlanV2Schema, scene3DPrimitiveSchema, scene3DProjectionIssues, scene3DProvenanceSchema, scene3DReferenceSchema, scene3DRenderTier, scene3DRenderTierCredits, scene3DReviewNote, scene3DReviewVerdictOf, scene3DSampleForFrame, scene3DSha256Schema, scene3DShotForFrame, scene3DShotIndexForFrame, scene3DShotSchema, scene3DUrlSchema, scene3DV2AdmissionIssues, scene3DV2EditOperationSchema, scene3DV2EditOperationsSchema, scene3DV2HierarchyDepth, scene3DV2NormalizationIssues, scene3DV2OverrideInputSchema, scene3DV2ResourceUsage, scene3DVersionTokenSchema, scene3DZodIssues, scheduleMatchesAt, scheduleOccurrences, searchModelVariants, seedance2AudioLimitSec, seedanceVideoEditCreditId, segmentDurationsFor, selectByModulo, selectByNamedKey, selectByPredicate, selectListItems, selectLoraRoutingForMentions, selectRandom, setRegisteredPersonPackFields, settledWithLimit, sizeVec3Schema, slotVariationSchema, sortCharacterEntriesForDisplay, sortListItems, sourceRefKey, speakerLayoutAllows, speakerPresentationWarnings, speakerSwitchOverlaps, speakerTurns, spliceDelimitedRows, splitByLoopDelimiter, splitGeneratedItems, splitInstagramTargets, splitMetaAdsAdvertiserNames, splitMetaAdsPageUrls, spreadJsonArrayIfSingleton, stringifyPathResults, stripDerivedAnalysisFields, stripExportContent, stripStudioTransientSettings, stripTransientRuntimeData, stripUnownedRefs, summarizeScene3DOperations, sunoCreditType, sunoModelHonoursDuration, supportedDefaultDimensions, supportsAdvancedMode, supportsAutoVideoDuration, supportsEndAnchor, supportsExtendRender, templateCategoryStoredValues, timezoneOffsetMinutes, toConnectedReference, toConnectedReferences, togglePick, transcribeLaneSupportsWordTimestamps, transcribeProvidersWithWordTimestamps, transcribeWordTimestampsRefusal, transcriptDurationSec, tryParseJson, uiAspectRatioFill, uiDurationFill, uiResolutionFill, unresolvedRefTokens, unwrapEditPlanOutput, unwrapUnresolvedTokens, usageModeDirective, usageModeIncludesName, usageModeLabel, usdToCredits, validateAiAvatarPayload, validateCinematicAvatarPayload, validateDurationForFormat, validateEdl, validateEdlClipSet, validateModeActivation, validateModelInput, validateNoNestedGroups, validateObjects, validateProviderForNodeType, validateSubWorkflowRoutes, variantJobId, vec3Schema, verifyScene3DPlanV2ContentHash, videoAnalysisCreditSegment, videoAnalysisNumWindows, videoAnalysisResultSchema, videoAuditCreditsForBucket, videoLinkDownloadedFile, videoLinkNeedsDownload, videoModelCanSpeakDialogue, videoModelSupportsAudio, videoNegativeSuffix, videoProviderFoldsLoneEndFrame, videoProviderRequiresImage, windowAnalysisSchema, zipMergeLists };
17675
19451
  //# sourceMappingURL=index.js.map
17676
19452
  //# sourceMappingURL=index.js.map