@nodaro/shared 2.17.0 → 2.19.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 (75) hide show
  1. package/dist/index.cjs +260 -14
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +111 -6
  4. package/dist/index.d.ts +111 -6
  5. package/dist/index.js +251 -15
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/apply-video-negative-prompt.test.ts +38 -1
  9. package/src/__tests__/credit-identifiers.test.ts +47 -0
  10. package/src/__tests__/gvp-supported-providers.test.ts +22 -1
  11. package/src/__tests__/prompt-length-limits.test.ts +4 -0
  12. package/src/__tests__/video-audio-capability.test.ts +43 -0
  13. package/src/__tests__/video-mode-for-inputs.test.ts +1 -1
  14. package/src/__tests__/wan-3-catalog.test.ts +243 -0
  15. package/src/credit-identifiers.ts +42 -9
  16. package/src/i18n/held-prop.ar.ts +2 -0
  17. package/src/i18n/held-prop.de.ts +3 -0
  18. package/src/i18n/held-prop.es.ts +3 -0
  19. package/src/i18n/held-prop.fr.ts +2 -0
  20. package/src/i18n/held-prop.he.ts +3 -0
  21. package/src/i18n/held-prop.hi.ts +2 -0
  22. package/src/i18n/held-prop.ja.ts +3 -0
  23. package/src/i18n/held-prop.ko.ts +3 -0
  24. package/src/i18n/held-prop.pt-BR.ts +3 -0
  25. package/src/i18n/held-prop.ru.ts +2 -0
  26. package/src/i18n/held-prop.zh-CN.ts +3 -0
  27. package/src/i18n/person.ar.ts +3 -0
  28. package/src/i18n/person.de.ts +4 -0
  29. package/src/i18n/person.es.ts +4 -0
  30. package/src/i18n/person.fr.ts +3 -0
  31. package/src/i18n/person.he.ts +4 -0
  32. package/src/i18n/person.hi.ts +3 -0
  33. package/src/i18n/person.ja.ts +4 -0
  34. package/src/i18n/person.ko.ts +4 -0
  35. package/src/i18n/person.pt-BR.ts +4 -0
  36. package/src/i18n/person.ru.ts +3 -0
  37. package/src/i18n/person.zh-CN.ts +4 -0
  38. package/src/i18n/setting.ar.ts +2 -0
  39. package/src/i18n/setting.de.ts +3 -0
  40. package/src/i18n/setting.es.ts +3 -0
  41. package/src/i18n/setting.fr.ts +2 -0
  42. package/src/i18n/setting.he.ts +3 -0
  43. package/src/i18n/setting.hi.ts +2 -0
  44. package/src/i18n/setting.ja.ts +3 -0
  45. package/src/i18n/setting.ko.ts +3 -0
  46. package/src/i18n/setting.pt-BR.ts +3 -0
  47. package/src/i18n/setting.ru.ts +2 -0
  48. package/src/i18n/setting.zh-CN.ts +3 -0
  49. package/src/i18n/style.ar.ts +2 -0
  50. package/src/i18n/style.de.ts +3 -0
  51. package/src/i18n/style.es.ts +3 -0
  52. package/src/i18n/style.fr.ts +2 -0
  53. package/src/i18n/style.he.ts +3 -0
  54. package/src/i18n/style.hi.ts +2 -0
  55. package/src/i18n/style.ja.ts +3 -0
  56. package/src/i18n/style.ko.ts +3 -0
  57. package/src/i18n/style.pt-BR.ts +3 -0
  58. package/src/i18n/style.ru.ts +2 -0
  59. package/src/i18n/style.zh-CN.ts +3 -0
  60. package/src/i18n/styling.ar.ts +4 -0
  61. package/src/i18n/styling.de.ts +5 -0
  62. package/src/i18n/styling.es.ts +5 -0
  63. package/src/i18n/styling.fr.ts +4 -0
  64. package/src/i18n/styling.he.ts +5 -0
  65. package/src/i18n/styling.hi.ts +4 -0
  66. package/src/i18n/styling.ja.ts +5 -0
  67. package/src/i18n/styling.ko.ts +5 -0
  68. package/src/i18n/styling.pt-BR.ts +5 -0
  69. package/src/i18n/styling.ru.ts +4 -0
  70. package/src/i18n/styling.zh-CN.ts +5 -0
  71. package/src/index.ts +10 -0
  72. package/src/model-catalog.ts +101 -0
  73. package/src/model-constants.ts +217 -8
  74. package/src/node-default-mappings.ts +5 -0
  75. package/src/video-ui-defaults.ts +66 -0
package/dist/index.cjs CHANGED
@@ -84,6 +84,7 @@ var WAN_27_IMAGE_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "8:1", "
84
84
  var VIDEO_RATIOS_HVS345 = ["16:9", "9:16", "1:1", "4:3", "3:4"];
85
85
  var VIDEO_RATIOS_SEEDANCE_2 = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "adaptive"];
86
86
  var VIDEO_RATIOS_HAPPYHORSE_11 = ["16:9", "9:16", "1:1", "4:3", "3:4", "4:5", "5:4", "21:9", "9:21"];
87
+ var VIDEO_RATIOS_WAN_3 = ["adaptive", "16:9", "4:3", "1:1", "3:4", "9:16"];
87
88
  var IMAGE_MODELS = {
88
89
  // ── Google Nano Banana ──
89
90
  "nano-banana": {
@@ -1023,6 +1024,42 @@ var VIDEO_MODELS = {
1023
1024
  { identifier: "gemini-omni-video:4k:vref", credits: 900, note: "video-edit 4K" }
1024
1025
  ]
1025
1026
  },
1027
+ // Gemini Omni Flash 1.1 — the faster/cheaper Omni SKU (KIE
1028
+ // `google/gemini-omni-flash-1-1`). Identical request surface to
1029
+ // gemini-omni-video, so every capability below is deliberate PARITY with the
1030
+ // sibling: same 4/6/8/10s ladder, same 720p/1080p + 4K bands, same
1031
+ // features (the KIE schema also exposes first/last frame, but the pro
1032
+ // sibling's frame path is unwired here too — no "end-frame" until it is).
1033
+ // 360p is on the KIE enum but NOT exposed: it sits in the same credit band as
1034
+ // 720p/1080p, so it could only hand the user a worse render at the same price.
1035
+ "gemini-omni-flash": {
1036
+ id: "gemini-omni-flash",
1037
+ kind: "video",
1038
+ modes: ["i2v", "t2v"],
1039
+ // V2V is served via the i2v handle, not a catalog mode
1040
+ family: "Google",
1041
+ label: "Gemini Omni Flash",
1042
+ series: "Gemini",
1043
+ description: "Google Gemini Omni Flash \u2014 faster/cheaper Omni tier: multimodal video with native audio, text/image-to-video + video-edit.",
1044
+ useCases: ["cinematic", "fast"],
1045
+ features: ["audio", "reference-image"],
1046
+ aspectRatios: VIDEO_RATIOS_HV,
1047
+ resolutions: ["720p", "1080p", "4k"],
1048
+ durations: [4, 6, 8, 10],
1049
+ pricing: [
1050
+ { identifier: "gemini-omni-flash", credits: 270, note: "default \u2014 8s 720p/1080p (the credit builder's duration fallback)" },
1051
+ { identifier: "gemini-omni-flash:4", credits: 160, note: "720p/1080p 4s" },
1052
+ { identifier: "gemini-omni-flash:6", credits: 210, note: "720p/1080p 6s" },
1053
+ { identifier: "gemini-omni-flash:8", credits: 270, note: "720p/1080p 8s" },
1054
+ { identifier: "gemini-omni-flash:10", credits: 320, note: "720p/1080p 10s" },
1055
+ { identifier: "gemini-omni-flash:4k:4", credits: 370, note: "4K 4s" },
1056
+ { identifier: "gemini-omni-flash:4k:6", credits: 420, note: "4K 6s" },
1057
+ { identifier: "gemini-omni-flash:4k:8", credits: 480, note: "4K 8s" },
1058
+ { identifier: "gemini-omni-flash:4k:10", credits: 530, note: "4K 10s" },
1059
+ { identifier: "gemini-omni-flash:vref", credits: 420, note: "video-edit 720p/1080p" },
1060
+ { identifier: "gemini-omni-flash:4k:vref", credits: 630, note: "video-edit 4K" }
1061
+ ]
1062
+ },
1026
1063
  // ── Kling ──
1027
1064
  "kling": {
1028
1065
  id: "kling",
@@ -1290,6 +1327,66 @@ var VIDEO_MODELS = {
1290
1327
  ]
1291
1328
  },
1292
1329
  // ── Wan ──
1330
+ // Wan 3.0 (standard + Prime) — a NEW generation, not a tier of the 2.x ladder.
1331
+ // One id per SKU serves BOTH modes (no t2v twin, no alias): first/last frame
1332
+ // OR an all-purpose reference mode (images/videos/audio, bound in the prompt
1333
+ // as Image1/Video1/Audio1 — no space, unlike Wan 2.x), native audio behind a
1334
+ // boolean `audio` lever, 2-30s at 480p/720p/1080p.
1335
+ // `video-reference` is deliberately NOT declared: KIE accepts reference videos,
1336
+ // but the extend chain is unwired and KIE caps input-video + output at 30s,
1337
+ // which the segment bounds cannot express. Precedent: gemini-omni-video carries
1338
+ // ref limits without the feature. The ref CAPS still live in
1339
+ // VIDEO_REF_LIMITS_BY_PROVIDER (model-constants).
1340
+ // `resolutions` is ascending (repo convention); the DEFAULT tier (720p) is
1341
+ // declared explicitly in PRICING_DEFAULT_RESOLUTION, never by array position.
1342
+ "wan-3": {
1343
+ id: "wan-3",
1344
+ kind: "video",
1345
+ modes: ["i2v", "t2v"],
1346
+ family: "Alibaba",
1347
+ label: "Wan 3.0",
1348
+ series: "Wan",
1349
+ description: "Wan 3.0 \u2014 multimodal: first/last frame or image/video/audio references, native audio, 2-30s at 480p/720p/1080p.",
1350
+ useCases: ["motion", "narrative", "long-form"],
1351
+ features: ["end-frame", "audio", "reference-image"],
1352
+ aspectRatios: VIDEO_RATIOS_WAN_3,
1353
+ durations: [2, 3, 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],
1354
+ resolutions: ["480p", "720p", "1080p"],
1355
+ pricing: [
1356
+ { identifier: "wan-3", credits: 200, note: "default 5s 720p \u2014 see :Ns:res variants for exact" },
1357
+ { identifier: "wan-3:5s:720p", credits: 200, note: "5s 720p (the default tier)" },
1358
+ { identifier: "wan-3:8s:480p", credits: 160, note: "8s 480p" },
1359
+ { identifier: "wan-3:8s:720p", credits: 320, note: "8s 720p" },
1360
+ { identifier: "wan-3:8s:1080p", credits: 640, note: "8s 1080p" },
1361
+ { identifier: "wan-3:30s:480p", credits: 600, note: "30s 480p (max)" },
1362
+ { identifier: "wan-3:30s:720p", credits: 1200, note: "30s 720p (max)" },
1363
+ { identifier: "wan-3:30s:1080p", credits: 2400, note: "30s 1080p (max)" }
1364
+ ]
1365
+ },
1366
+ "wan-3-prime": {
1367
+ id: "wan-3-prime",
1368
+ kind: "video",
1369
+ modes: ["i2v", "t2v"],
1370
+ family: "Alibaba",
1371
+ label: "Wan 3.0 Prime",
1372
+ series: "Wan",
1373
+ description: "Wan 3.0 Prime \u2014 Alibaba's high-speed Wan 3.0 tier: same multimodal surface and 2-30s range, faster turnaround at a higher per-second rate.",
1374
+ useCases: ["fast", "motion", "narrative"],
1375
+ features: ["end-frame", "audio", "reference-image"],
1376
+ aspectRatios: VIDEO_RATIOS_WAN_3,
1377
+ durations: [2, 3, 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],
1378
+ resolutions: ["480p", "720p", "1080p"],
1379
+ pricing: [
1380
+ { identifier: "wan-3-prime", credits: 320, note: "default 5s 720p \u2014 see :Ns:res variants for exact" },
1381
+ { identifier: "wan-3-prime:5s:720p", credits: 320, note: "5s 720p (the default tier)" },
1382
+ { identifier: "wan-3-prime:8s:480p", credits: 250, note: "8s 480p" },
1383
+ { identifier: "wan-3-prime:8s:720p", credits: 510, note: "8s 720p" },
1384
+ { identifier: "wan-3-prime:8s:1080p", credits: 1010, note: "8s 1080p" },
1385
+ { identifier: "wan-3-prime:30s:480p", credits: 920, note: "30s 480p (max)" },
1386
+ { identifier: "wan-3-prime:30s:720p", credits: 1890, note: "30s 720p (max)" },
1387
+ { identifier: "wan-3-prime:30s:1080p", credits: 3780, note: "30s 1080p (max)" }
1388
+ ]
1389
+ },
1293
1390
  "wan-i2v": {
1294
1391
  id: "wan-i2v",
1295
1392
  kind: "video",
@@ -2481,6 +2578,13 @@ var MAX_VIDEO_PROMPT_CHARS_BY_PROVIDER = {
2481
2578
  // (docs.kie.ai/market/bytedance/seedance-2-5).
2482
2579
  "seedance-2-5": 3e4,
2483
2580
  "gemini-omni-video": 2e4,
2581
+ // Gemini Omni Flash 1.1 — same 20000-char prompt surface as the pro sibling
2582
+ // (docs.kie.ai/market/google/gemini-omni-flash-1-1).
2583
+ "gemini-omni-flash": 2e4,
2584
+ // Wan 3.0 / 3.0 Prime — 20000 chars, excess truncated by the provider
2585
+ // (docs.kie.ai/market/wan/3-0-video and /3-0-video-prime).
2586
+ "wan-3": 2e4,
2587
+ "wan-3-prime": 2e4,
2484
2588
  "bytedance-lite": 1e4,
2485
2589
  "bytedance-pro": 1e4,
2486
2590
  "bytedance-pro-fast": 1e4,
@@ -2590,6 +2694,13 @@ var NATIVE_NEGATIVE_VIDEO_PROVIDERS = /* @__PURE__ */ new Set([
2590
2694
  // Wan speech-to-video
2591
2695
  "wan-s2v"
2592
2696
  ]);
2697
+ var STYLE_SECTION_HEADER_LINE = "[style]:\n";
2698
+ function videoNegativeSuffix(negativePrompt, base) {
2699
+ const gapAt = base?.lastIndexOf("\n\n") ?? -1;
2700
+ const lastBlock = base === void 0 ? void 0 : gapAt >= 0 ? base.slice(gapAt + 2) : base;
2701
+ const separator = lastBlock === void 0 || lastBlock.startsWith(STYLE_SECTION_HEADER_LINE) ? "\n\n" : "\n";
2702
+ return `${separator}Avoid: ${negativePrompt}`;
2703
+ }
2593
2704
  function applyVideoNegativePrompt(prompt, negativePrompt, provider) {
2594
2705
  const promptMax = getMaxVideoPromptChars(provider);
2595
2706
  const clamp = (p) => p != null && p.length > promptMax ? p.slice(0, promptMax) : p;
@@ -2600,8 +2711,7 @@ function applyVideoNegativePrompt(prompt, negativePrompt, provider) {
2600
2711
  }
2601
2712
  const base = prompt && prompt.trim().length > 0 ? prompt : "";
2602
2713
  if (!base) return { prompt: `Avoid: ${neg}`.slice(0, promptMax), nativeNegativePrompt: void 0 };
2603
- const avoid = `
2604
- Avoid: ${neg}`;
2714
+ const avoid = videoNegativeSuffix(neg, base);
2605
2715
  const room = Math.max(0, promptMax - avoid.length);
2606
2716
  const injected = `${base.slice(0, room)}${avoid}`.slice(0, promptMax);
2607
2717
  return { prompt: injected, nativeNegativePrompt: void 0 };
@@ -2867,6 +2977,11 @@ var IMAGE_TO_VIDEO_PROVIDERS = [
2867
2977
  "runway-kie",
2868
2978
  "kling-3-omni",
2869
2979
  "gemini-omni-video",
2980
+ "gemini-omni-flash",
2981
+ // Wan 3.0 family — one id per SKU serves BOTH modes (no t2v twin, no alias),
2982
+ // so each id is listed in this array AND in TEXT_TO_VIDEO_PROVIDERS.
2983
+ "wan-3",
2984
+ "wan-3-prime",
2870
2985
  "ltx-2.3-pro",
2871
2986
  "ltx-2.3-fast",
2872
2987
  // xAI Grok Imagine Video 1.5 — KIE i2v (image_urls required). Also listed in
@@ -2902,6 +3017,12 @@ var TEXT_TO_VIDEO_PROVIDERS = [
2902
3017
  "happyhorse",
2903
3018
  "runway-kie",
2904
3019
  "gemini-omni-video",
3020
+ "gemini-omni-flash",
3021
+ // Wan 3.0 family — REAL t2v (prompt-only runs are the documented default
3022
+ // mode), so they belong in this main section and must NOT be gated by
3023
+ // VIDEO_PROVIDERS_REQUIRING_IMAGE.
3024
+ "wan-3",
3025
+ "wan-3-prime",
2905
3026
  "ltx-2.3-pro",
2906
3027
  "ltx-2.3-fast",
2907
3028
  // ── i2v-only providers (image required) ──────────────────────────────────
@@ -3198,7 +3319,13 @@ var DURATION_PRICED_PROVIDERS = /* @__PURE__ */ new Set([
3198
3319
  "grok-imagine-video-1.5",
3199
3320
  "happyhorse",
3200
3321
  "happyhorse-i2v",
3201
- "happyhorse-ref2v"
3322
+ "happyhorse-ref2v",
3323
+ // Wan 3.0 family — per-second billing at three resolution rates. NOTE:
3324
+ // gemini-omni-flash is deliberately ABSENT (like gemini-omni-video): the
3325
+ // Gemini Omni branch in buildVideoCreditModelIdentifier early-returns before
3326
+ // this gate is consulted.
3327
+ "wan-3",
3328
+ "wan-3-prime"
3202
3329
  ]);
3203
3330
  var SEEDANCE_2_PROVIDERS = /* @__PURE__ */ new Set([
3204
3331
  "seedance-2",
@@ -3224,6 +3351,33 @@ var MINIMAX_H3_DEFAULT_RESOLUTION = "2K";
3224
3351
  function normalizeMinimaxH3Resolution(resolution) {
3225
3352
  return resolution?.trim().toLowerCase() === "768p" ? "768P" : MINIMAX_H3_DEFAULT_RESOLUTION;
3226
3353
  }
3354
+ var WAN_3_PROVIDERS = /* @__PURE__ */ new Set([
3355
+ "wan-3",
3356
+ "wan-3-prime"
3357
+ ]);
3358
+ function isWan3Provider(provider) {
3359
+ return !!provider && WAN_3_PROVIDERS.has(provider);
3360
+ }
3361
+ var WAN_3_DEFAULT_RESOLUTION = "720P";
3362
+ function normalizeWan3Resolution(resolution) {
3363
+ switch (resolution?.trim().toLowerCase()) {
3364
+ case "480p":
3365
+ return "480P";
3366
+ case "1080p":
3367
+ return "1080P";
3368
+ case "720p":
3369
+ return "720P";
3370
+ default:
3371
+ return WAN_3_DEFAULT_RESOLUTION;
3372
+ }
3373
+ }
3374
+ var GEMINI_OMNI_PROVIDERS = /* @__PURE__ */ new Set([
3375
+ "gemini-omni-video",
3376
+ "gemini-omni-flash"
3377
+ ]);
3378
+ function isGeminiOmniProvider(provider) {
3379
+ return !!provider && GEMINI_OMNI_PROVIDERS.has(provider);
3380
+ }
3227
3381
  var VIDEO_PROVIDERS_WITHOUT_DISPATCH = /* @__PURE__ */ new Set([
3228
3382
  "kling-3-omni"
3229
3383
  ]);
@@ -3307,7 +3461,7 @@ function maxSegmentsFor(provider, capSec) {
3307
3461
  return max > 0 ? Math.ceil(capSec / max) : 0;
3308
3462
  }
3309
3463
  function defaultVideoAspectRatio(provider) {
3310
- return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) ? "adaptive" : "16:9";
3464
+ return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider) ? "adaptive" : "16:9";
3311
3465
  }
3312
3466
  var VEO_PROVIDERS = /* @__PURE__ */ new Set([
3313
3467
  "veo3",
@@ -3351,7 +3505,11 @@ var SEEDANCE_2_R2V_MAX_AUDIO_SEC_BY_PROVIDER = {
3351
3505
  "seedance-2-5": 30,
3352
3506
  // MiniMax Hailuo 3 — documented hard limit: each reference audio segment
3353
3507
  // 2-15s, ≤15s total (docs.kie.ai/market/minimax-h3/reference-to-video).
3354
- "minimax-h3": 15
3508
+ "minimax-h3": 15,
3509
+ // Wan 3.0 family — documented hard limit: each reference audio clip 1-15s,
3510
+ // ≤15s combined (docs.kie.ai/market/wan/3-0-video).
3511
+ "wan-3": 15,
3512
+ "wan-3-prime": 15
3355
3513
  };
3356
3514
  function seedance2AudioLimitSec(provider) {
3357
3515
  if (!provider) return null;
@@ -3377,8 +3535,17 @@ var VIDEO_REF_LIMITS_BY_PROVIDER = {
3377
3535
  // bills input images beyond the first 5 (11 KIE cr each) — see the
3378
3536
  // minimax-h3 credit helper in backend ee/billing.
3379
3537
  "minimax-h3": { ...SEEDANCE_2_REF_LIMITS },
3538
+ // Wan 3.0 family — all-purpose reference mode: up to 10 images / 5 videos
3539
+ // (each 1-15s, ≤15s combined) / 5 audio clips (each 1-15s, ≤15s combined).
3540
+ // The reference arrays are mutually EXCLUSIVE with first/last frame at the
3541
+ // provider (docs.kie.ai/market/wan/3-0-video).
3542
+ "wan-3": { images: 10, videos: 5, audio: 5 },
3543
+ "wan-3-prime": { images: 10, videos: 5, audio: 5 },
3380
3544
  // Multi-image reference providers.
3381
3545
  "gemini-omni-video": { images: 7, videos: 1 },
3546
+ // Gemini Omni Flash 1.1 — identical quota to the pro sibling
3547
+ // (images + 2×videos + character_ids ≤ 7).
3548
+ "gemini-omni-flash": { images: 7, videos: 1 },
3382
3549
  "kling-3-omni": { images: 7 },
3383
3550
  // catalog/docs: "end frame + up to 7 reference images"
3384
3551
  "grok-i2v": { images: 7 },
@@ -3409,13 +3576,26 @@ var RESOLUTION_DURATION_PRICING = {
3409
3576
  // pinned to 720p via extraParams in backend kie/models.ts so render matches.
3410
3577
  "happyhorse": ["720p", "1080p"],
3411
3578
  "happyhorse-i2v": ["720p", "1080p"],
3412
- "happyhorse-ref2v": ["720p", "1080p"]
3579
+ "happyhorse-ref2v": ["720p", "1080p"],
3580
+ // Wan 3.0 / Prime — per-second billing at three published resolution rates.
3581
+ // Ascending, matching the catalog; the BILLED default is declared explicitly
3582
+ // in PRICING_DEFAULT_RESOLUTION ("720p") rather than carried by index 0, and
3583
+ // the provider layer pins the same 720P so render == billed.
3584
+ "wan-3": ["480p", "720p", "1080p"],
3585
+ "wan-3-prime": ["480p", "720p", "1080p"]
3413
3586
  };
3414
3587
  var NATIVE_ADAPTIVE_ASPECT = {
3415
3588
  "seedance-2": "adaptive",
3416
3589
  "seedance-2-fast": "adaptive",
3417
3590
  "seedance-2-mini": "adaptive",
3418
- "seedance-2-5": "adaptive"
3591
+ "seedance-2-5": "adaptive",
3592
+ // Wan 3.0 family: `adaptive` is the enum DEFAULT and KIE documents it as
3593
+ // "automatically selects the ratio based on the input media and intent"
3594
+ // (docs.kie.ai/market/wan/3-0-video) — i.e. match-the-input, not merely
3595
+ // "provider default" (the grok `auto` trap). DOC-verified only; re-confirm
3596
+ // with a live job before relying on it for off-catalog ratios.
3597
+ "wan-3": "adaptive",
3598
+ "wan-3-prime": "adaptive"
3419
3599
  };
3420
3600
  var FRAME_MODE_ADAPTIVE_ONLY_ASPECT = /* @__PURE__ */ new Set([
3421
3601
  "seedance-2-5"
@@ -3466,7 +3646,20 @@ var VIDEO_AUDIO_CAPABILITY = {
3466
3646
  // MiniMax Hailuo 3 — multimodal; lip-syncs to reference audio (r2v). The
3467
3647
  // KIE API exposes NO audio on/off parameter (audio is always produced), so
3468
3648
  // there is no toggle field — alwaysOn, like VEO.
3469
- "minimax-h3": { mode: "audio_driven", alwaysOn: true }
3649
+ "minimax-h3": { mode: "audio_driven", alwaysOn: true },
3650
+ // Wan 3.0 family — a single boolean `audio` lever (KIE default true) produces
3651
+ // an ambient/SFX track with the clip. Classified "ambient", NOT
3652
+ // "native_speech" or "audio_driven": the schema documents no dialogue
3653
+ // guarantee, and reference audio is a generic conditioning array, not a
3654
+ // verified lip-sync transport. Upgrade only on a live probe (the kling-3.0
3655
+ // standard) — `audio_driven` would reroute the Story→Video dialogue pipeline
3656
+ // and skip the lip-sync pass. `defaultOn` mirrors the KIE default so an
3657
+ // intent-less request is described honestly; audio is priced into the uniform
3658
+ // per-second rate, so NOT cost-affecting (no `:audio` composite).
3659
+ // gemini-omni-flash is deliberately ABSENT — gemini-omni-video is absent too
3660
+ // (mode "none"), and the siblings must not disagree.
3661
+ "wan-3": { mode: "ambient", field: "audio", defaultOn: true },
3662
+ "wan-3-prime": { mode: "ambient", field: "audio", defaultOn: true }
3470
3663
  };
3471
3664
  var VIDEO_AUDIO_NONE = { mode: "none" };
3472
3665
  function getVideoAudioCapability(model) {
@@ -3485,6 +3678,7 @@ function applyVideoAudioToggle(input, provider, opts) {
3485
3678
  const enabled = cap.affectsCost ? opts?.sound : opts?.sound ?? opts?.generateAudio;
3486
3679
  if (enabled === void 0) return;
3487
3680
  if (cap.field === "generateAudio") input.generate_audio = enabled;
3681
+ else if (cap.field === "audio") input.audio = enabled;
3488
3682
  else input.sound = enabled;
3489
3683
  }
3490
3684
  var MODE_ADDON_PROVIDERS = /* @__PURE__ */ new Set([]);
@@ -3514,14 +3708,27 @@ var VIDEO_VARIABLE_PRICING = {
3514
3708
  // images are billed via the dedicated compute hook, not the identifier.
3515
3709
  "minimax-h3": "duration+resolution",
3516
3710
  // Grok Imagine Video 1.5 — per-second billing split 480p/720p (no video-ref dimension).
3517
- "grok-imagine-video-1.5": "duration+resolution"
3711
+ "grok-imagine-video-1.5": "duration+resolution",
3712
+ // Wan 3.0 family — per-second billing at three resolution rates (no video-ref
3713
+ // dimension: reference runs bill output seconds only). No gemini-omni-flash
3714
+ // entry, mirroring gemini-omni-video which has none either.
3715
+ "wan-3": "duration+resolution",
3716
+ "wan-3-prime": "duration+resolution"
3518
3717
  };
3519
3718
  var PRICING_DEFAULT_DURATION_SEC = {
3520
3719
  "minimax-h3": 6
3521
3720
  };
3522
3721
  var PRICING_DEFAULT_RESOLUTION = {
3523
3722
  // KIE renders 720p when `resolution` is omitted (kie/models.ts extraParams).
3524
- "seedance-2-5": "720p"
3723
+ "seedance-2-5": "720p",
3724
+ // Wan 3.0 family — KIE's OWN default is 1080P, but the provider layer pins
3725
+ // 720P (normalizeWan3Resolution / WAN_3_DEFAULT_RESOLUTION) so the rendered
3726
+ // tier equals the tier the bare identifier bills. This declaration is what
3727
+ // makes the billed default explicit instead of an array ordering: the
3728
+ // RESOLUTION_DURATION_PRICING branch consults it before falling back to the
3729
+ // first tier, so the catalog can stay ascending without repricing anything.
3730
+ "wan-3": "720p",
3731
+ "wan-3-prime": "720p"
3525
3732
  };
3526
3733
  var HAPPYHORSE_DURATION_TIERS = Array.from(
3527
3734
  { length: 13 },
@@ -3531,6 +3738,10 @@ var SEEDANCE_2_5_DURATION_TIERS = Array.from(
3531
3738
  { length: 27 },
3532
3739
  (_, i) => ({ maxSeconds: i + 4, suffix: `${i + 4}s` })
3533
3740
  );
3741
+ var WAN_3_DURATION_TIERS = Array.from(
3742
+ { length: 29 },
3743
+ (_, i) => ({ maxSeconds: i + 2, suffix: `${i + 2}s` })
3744
+ );
3534
3745
  var VIDEO_DURATION_TIERS = {
3535
3746
  "kling-3.0": [
3536
3747
  { maxSeconds: 5, suffix: "5s" },
@@ -3606,6 +3817,8 @@ var VIDEO_DURATION_TIERS = {
3606
3817
  { maxSeconds: 15, suffix: "15s" }
3607
3818
  ],
3608
3819
  "seedance-2-5": SEEDANCE_2_5_DURATION_TIERS,
3820
+ "wan-3": WAN_3_DURATION_TIERS,
3821
+ "wan-3-prime": WAN_3_DURATION_TIERS,
3609
3822
  // MiniMax Hailuo 3 — true per-second billing (KIE 36.5 cr/s @2K, 22.5 cr/s
3610
3823
  // @768P). One tier per allowed second (4-15s) so the composite identifier
3611
3824
  // maps 1:1 to the seeded price — no rounding/overcharge for any on-menu
@@ -4255,13 +4468,13 @@ function buildVideoCreditModelIdentifier(provider, duration, sound, nodeType, mo
4255
4468
  if (resolution === "1080p" && VEO_RESOLUTION_TIERED_PROVIDERS.has(effectiveProvider)) return `${effectiveProvider}:1080p`;
4256
4469
  return effectiveProvider;
4257
4470
  }
4258
- if (effectiveProvider === "gemini-omni-video") {
4471
+ if (isGeminiOmniProvider(effectiveProvider)) {
4259
4472
  if (hasVideoRef) {
4260
- return resolution === "4k" ? "gemini-omni-video:4k:vref" : "gemini-omni-video:vref";
4473
+ return resolution === "4k" ? `${effectiveProvider}:4k:vref` : `${effectiveProvider}:vref`;
4261
4474
  }
4262
4475
  const raw = parseInt(String(duration ?? 8), 10);
4263
4476
  const d = Number.isNaN(raw) ? 8 : GEMINI_OMNI_DURATIONS.reduce((b, a) => Math.abs(a - raw) < Math.abs(b - raw) ? a : b);
4264
- return resolution === "4k" ? `gemini-omni-video:4k:${d}` : `gemini-omni-video:${d}`;
4477
+ return resolution === "4k" ? `${effectiveProvider}:4k:${d}` : `${effectiveProvider}:${d}`;
4265
4478
  }
4266
4479
  if (effectiveProvider === "ltx-2.3-pro" || effectiveProvider === "ltx-2.3-fast") {
4267
4480
  const bands = LTX_DURATION_TIERS[effectiveProvider];
@@ -4299,7 +4512,10 @@ function buildVideoCreditModelIdentifier(provider, duration, sound, nodeType, mo
4299
4512
  }
4300
4513
  const resTiers = RESOLUTION_DURATION_PRICING[effectiveProvider];
4301
4514
  if (resTiers) {
4302
- const res = resolution && resTiers.includes(resolution) ? resolution : resTiers[0];
4515
+ const declaredDefault = PRICING_DEFAULT_RESOLUTION[effectiveProvider];
4516
+ const fallback = declaredDefault && resTiers.includes(declaredDefault) ? declaredDefault : resTiers[0];
4517
+ const requested = isWan3Provider(effectiveProvider) ? normalizeWan3Resolution(resolution).toLowerCase() : resolution;
4518
+ const res = requested && resTiers.includes(requested) ? requested : fallback;
4303
4519
  identifier += `:${res}`;
4304
4520
  }
4305
4521
  if (isMinimaxH3Provider(effectiveProvider) && normalizeMinimaxH3Resolution(resolution) === "768P") {
@@ -7919,6 +8135,10 @@ var QUALITY_MAP = {
7919
8135
  // Seedance 2.5 spans 480p/720p/1080p on KIE (1080p accepted since the
7920
8136
  // 2026-08-17 re-probe; 4k still rejected), so each quality rung gets its own tier.
7921
8137
  "seedance-2-5": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
8138
+ // Wan 3.0 family — 480p / 720p / 1080p (lowercase catalog spellings; the
8139
+ // uppercase KIE wire form is produced only by normalizeWan3Resolution).
8140
+ "wan-3": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
8141
+ "wan-3-prime": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
7922
8142
  "wan-2.7-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
7923
8143
  "wan-2.7-t2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
7924
8144
  "happyhorse": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
@@ -7932,6 +8152,7 @@ var QUALITY_MAP = {
7932
8152
  "ltx-2.3-pro": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
7933
8153
  "ltx-2.3-fast": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
7934
8154
  "gemini-omni-video": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
8155
+ "gemini-omni-flash": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
7935
8156
  // Grok Imagine Video 1.5 — only 480p/720p (no 1080p tier); high clamps to 720p.
7936
8157
  "grok-imagine-video-1.5": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
7937
8158
  // Replicate Flux 2 family — MP-based resolution (matching IMAGE_RESOLUTION_OPTIONS["flux-2-*"]).
@@ -13636,6 +13857,21 @@ function bucketSecondsFromAuditCreditId(id) {
13636
13857
  return m ? Number(m[1]) : null;
13637
13858
  }
13638
13859
 
13860
+ // src/video-ui-defaults.ts
13861
+ function uiAspectRatioFill(provider) {
13862
+ return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider) ? "adaptive" : void 0;
13863
+ }
13864
+ function uiResolutionFill(provider) {
13865
+ if (isWan3Provider(provider)) return PRICING_DEFAULT_RESOLUTION[provider];
13866
+ if (isSeedance2Provider(provider)) return MODEL_CATALOG[provider]?.resolutions?.[0];
13867
+ return void 0;
13868
+ }
13869
+ function uiDurationFill(provider) {
13870
+ if (isWan3Provider(provider)) return 5;
13871
+ if (isGeminiOmniProvider(provider)) return 8;
13872
+ return void 0;
13873
+ }
13874
+
13639
13875
  // src/smart-cut-windows.ts
13640
13876
  var SMART_CUT_WINDOW_MAX = 24;
13641
13877
  var SMART_CUT_WINDOW_MIN = 1;
@@ -13960,6 +14196,7 @@ exports.FURNITURE_SUBCATEGORY_LABELS = FURNITURE_SUBCATEGORY_LABELS;
13960
14196
  exports.FURNITURE_SUBCATEGORY_ORDER = FURNITURE_SUBCATEGORY_ORDER;
13961
14197
  exports.FixContinuityInputSchema = FixContinuityInputSchema;
13962
14198
  exports.FixContinuityResultSchema = FixContinuityResultSchema;
14199
+ exports.GEMINI_OMNI_PROVIDERS = GEMINI_OMNI_PROVIDERS;
13963
14200
  exports.GENERATE_TEXT_DELIMITER = GENERATE_TEXT_DELIMITER;
13964
14201
  exports.GLOBAL_MAX_DURATION_SECONDS = GLOBAL_MAX_DURATION_SECONDS;
13965
14202
  exports.GRANTED_ACCESS = GRANTED_ACCESS;
@@ -14275,6 +14512,8 @@ exports.ValidateMatchCutInputSchema = ValidateMatchCutInputSchema;
14275
14512
  exports.ValidateMatchCutResultSchema = ValidateMatchCutResultSchema;
14276
14513
  exports.VideoCriticVerdictSchema = VideoCriticVerdictSchema;
14277
14514
  exports.VoiceMatchSchema = VoiceMatchSchema;
14515
+ exports.WAN_3_DEFAULT_RESOLUTION = WAN_3_DEFAULT_RESOLUTION;
14516
+ exports.WAN_3_PROVIDERS = WAN_3_PROVIDERS;
14278
14517
  exports.WARDROBE_VARIANTS = WARDROBE_VARIANTS;
14279
14518
  exports.WEAPONS = WEAPONS;
14280
14519
  exports.WEAPON_SUBCATEGORY_LABELS = WEAPON_SUBCATEGORY_LABELS;
@@ -14457,6 +14696,7 @@ exports.isCollectInEdge = isCollectInEdge;
14457
14696
  exports.isDefaultSelectorConfig = isDefaultSelectorConfig;
14458
14697
  exports.isExpandedClone = isExpandedClone;
14459
14698
  exports.isFlux2Model = isFlux2Model;
14699
+ exports.isGeminiOmniProvider = isGeminiOmniProvider;
14460
14700
  exports.isGvpSupportedProvider = isGvpSupportedProvider;
14461
14701
  exports.isHandleInputWired = isHandleInputWired;
14462
14702
  exports.isKineticCaptionStyle = isKineticCaptionStyle;
@@ -14473,6 +14713,7 @@ exports.isUsageMode = isUsageMode;
14473
14713
  exports.isVeoProvider = isVeoProvider;
14474
14714
  exports.isVideoAnalysisMixedTier = isVideoAnalysisMixedTier;
14475
14715
  exports.isVideoAnalysisTier = isVideoAnalysisTier;
14716
+ exports.isWan3Provider = isWan3Provider;
14476
14717
  exports.jsonResultToList = jsonResultToList;
14477
14718
  exports.knownEntitySlugsFromRefs = knownEntitySlugsFromRefs;
14478
14719
  exports.knownImageSlugsFromRefs = knownImageSlugsFromRefs;
@@ -14505,6 +14746,7 @@ exports.normalizeModelInput = normalizeModelInput;
14505
14746
  exports.normalizeNodeModelParams = normalizeNodeModelParams;
14506
14747
  exports.normalizePinterestUrl = normalizePinterestUrl;
14507
14748
  exports.normalizeRoleSlug = normalizeRoleSlug;
14749
+ exports.normalizeWan3Resolution = normalizeWan3Resolution;
14508
14750
  exports.orderedLlmModels = orderedLlmModels;
14509
14751
  exports.parseAttributedDialogue = parseAttributedDialogue;
14510
14752
  exports.parseCharacterMentionToken = parseCharacterMentionToken;
@@ -14612,6 +14854,9 @@ exports.toConnectedReference = toConnectedReference;
14612
14854
  exports.toConnectedReferences = toConnectedReferences;
14613
14855
  exports.togglePick = togglePick;
14614
14856
  exports.tryParseJson = tryParseJson;
14857
+ exports.uiAspectRatioFill = uiAspectRatioFill;
14858
+ exports.uiDurationFill = uiDurationFill;
14859
+ exports.uiResolutionFill = uiResolutionFill;
14615
14860
  exports.unwrapUnresolvedTokens = unwrapUnresolvedTokens;
14616
14861
  exports.usageModeDirective = usageModeDirective;
14617
14862
  exports.usageModeIncludesName = usageModeIncludesName;
@@ -14633,6 +14878,7 @@ exports.videoAnalysisResultSchema = videoAnalysisResultSchema;
14633
14878
  exports.videoAuditCreditsForBucket = videoAuditCreditsForBucket;
14634
14879
  exports.videoModelCanSpeakDialogue = videoModelCanSpeakDialogue;
14635
14880
  exports.videoModelSupportsAudio = videoModelSupportsAudio;
14881
+ exports.videoNegativeSuffix = videoNegativeSuffix;
14636
14882
  exports.videoProviderRequiresImage = videoProviderRequiresImage;
14637
14883
  exports.windowAnalysisSchema = windowAnalysisSchema;
14638
14884
  exports.zipMergeLists = zipMergeLists;