@nodaro/shared 2.18.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.
- package/dist/index.cjs +251 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -6
- package/dist/index.d.ts +100 -6
- package/dist/index.js +243 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/credit-identifiers.test.ts +47 -0
- package/src/__tests__/gvp-supported-providers.test.ts +22 -1
- package/src/__tests__/prompt-length-limits.test.ts +4 -0
- package/src/__tests__/video-audio-capability.test.ts +43 -0
- package/src/__tests__/video-mode-for-inputs.test.ts +1 -1
- package/src/__tests__/wan-3-catalog.test.ts +243 -0
- package/src/credit-identifiers.ts +42 -9
- package/src/i18n/held-prop.ar.ts +2 -0
- package/src/i18n/held-prop.de.ts +3 -0
- package/src/i18n/held-prop.es.ts +3 -0
- package/src/i18n/held-prop.fr.ts +2 -0
- package/src/i18n/held-prop.he.ts +3 -0
- package/src/i18n/held-prop.hi.ts +2 -0
- package/src/i18n/held-prop.ja.ts +3 -0
- package/src/i18n/held-prop.ko.ts +3 -0
- package/src/i18n/held-prop.pt-BR.ts +3 -0
- package/src/i18n/held-prop.ru.ts +2 -0
- package/src/i18n/held-prop.zh-CN.ts +3 -0
- package/src/i18n/person.ar.ts +3 -0
- package/src/i18n/person.de.ts +4 -0
- package/src/i18n/person.es.ts +4 -0
- package/src/i18n/person.fr.ts +3 -0
- package/src/i18n/person.he.ts +4 -0
- package/src/i18n/person.hi.ts +3 -0
- package/src/i18n/person.ja.ts +4 -0
- package/src/i18n/person.ko.ts +4 -0
- package/src/i18n/person.pt-BR.ts +4 -0
- package/src/i18n/person.ru.ts +3 -0
- package/src/i18n/person.zh-CN.ts +4 -0
- package/src/i18n/setting.ar.ts +2 -0
- package/src/i18n/setting.de.ts +3 -0
- package/src/i18n/setting.es.ts +3 -0
- package/src/i18n/setting.fr.ts +2 -0
- package/src/i18n/setting.he.ts +3 -0
- package/src/i18n/setting.hi.ts +2 -0
- package/src/i18n/setting.ja.ts +3 -0
- package/src/i18n/setting.ko.ts +3 -0
- package/src/i18n/setting.pt-BR.ts +3 -0
- package/src/i18n/setting.ru.ts +2 -0
- package/src/i18n/setting.zh-CN.ts +3 -0
- package/src/i18n/style.ar.ts +2 -0
- package/src/i18n/style.de.ts +3 -0
- package/src/i18n/style.es.ts +3 -0
- package/src/i18n/style.fr.ts +2 -0
- package/src/i18n/style.he.ts +3 -0
- package/src/i18n/style.hi.ts +2 -0
- package/src/i18n/style.ja.ts +3 -0
- package/src/i18n/style.ko.ts +3 -0
- package/src/i18n/style.pt-BR.ts +3 -0
- package/src/i18n/style.ru.ts +2 -0
- package/src/i18n/style.zh-CN.ts +3 -0
- package/src/i18n/styling.ar.ts +4 -0
- package/src/i18n/styling.de.ts +5 -0
- package/src/i18n/styling.es.ts +5 -0
- package/src/i18n/styling.fr.ts +4 -0
- package/src/i18n/styling.he.ts +5 -0
- package/src/i18n/styling.hi.ts +4 -0
- package/src/i18n/styling.ja.ts +5 -0
- package/src/i18n/styling.ko.ts +5 -0
- package/src/i18n/styling.pt-BR.ts +5 -0
- package/src/i18n/styling.ru.ts +4 -0
- package/src/i18n/styling.zh-CN.ts +5 -0
- package/src/index.ts +9 -0
- package/src/model-catalog.ts +101 -0
- package/src/model-constants.ts +182 -7
- package/src/node-default-mappings.ts +5 -0
- package/src/video-ui-defaults.ts +66 -0
package/src/model-catalog.ts
CHANGED
|
@@ -228,6 +228,12 @@ const VIDEO_RATIOS_SEEDANCE_2 = ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "a
|
|
|
228
228
|
// portrait-social and 21:9/9:21 cinematic (docs.kie.ai/market/happyhorse-1-1).
|
|
229
229
|
// Kept separate so the wider set can't leak to models that don't support it.
|
|
230
230
|
const VIDEO_RATIOS_HAPPYHORSE_11 = ["16:9", "9:16", "1:1", "4:3", "3:4", "4:5", "5:4", "21:9", "9:21"] as const
|
|
231
|
+
// Wan 3.0 (standard + Prime) — the model's own six-ratio enum, `adaptive` first
|
|
232
|
+
// because that is the KIE default ("automatically selects the ratio based on the
|
|
233
|
+
// input media and intent"). Deliberately NO 21:9 — the Wan 3.0 enum rejects it,
|
|
234
|
+
// so VIDEO_RATIOS_SEEDANCE_2 must NOT be reused here
|
|
235
|
+
// (docs.kie.ai/market/wan/3-0-video and /3-0-video-prime — identical schemas).
|
|
236
|
+
const VIDEO_RATIOS_WAN_3 = ["adaptive", "16:9", "4:3", "1:1", "3:4", "9:16"] as const
|
|
231
237
|
|
|
232
238
|
// =============================================================================
|
|
233
239
|
// IMAGE MODELS
|
|
@@ -1179,6 +1185,41 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
|
|
|
1179
1185
|
{ identifier: "gemini-omni-video:4k:vref", credits: 900, note: "video-edit 4K" },
|
|
1180
1186
|
],
|
|
1181
1187
|
},
|
|
1188
|
+
// Gemini Omni Flash 1.1 — the faster/cheaper Omni SKU (KIE
|
|
1189
|
+
// `google/gemini-omni-flash-1-1`). Identical request surface to
|
|
1190
|
+
// gemini-omni-video, so every capability below is deliberate PARITY with the
|
|
1191
|
+
// sibling: same 4/6/8/10s ladder, same 720p/1080p + 4K bands, same
|
|
1192
|
+
// features (the KIE schema also exposes first/last frame, but the pro
|
|
1193
|
+
// sibling's frame path is unwired here too — no "end-frame" until it is).
|
|
1194
|
+
// 360p is on the KIE enum but NOT exposed: it sits in the same credit band as
|
|
1195
|
+
// 720p/1080p, so it could only hand the user a worse render at the same price.
|
|
1196
|
+
"gemini-omni-flash": {
|
|
1197
|
+
id: "gemini-omni-flash",
|
|
1198
|
+
kind: "video",
|
|
1199
|
+
modes: ["i2v", "t2v"] as const, // V2V is served via the i2v handle, not a catalog mode
|
|
1200
|
+
family: "Google",
|
|
1201
|
+
label: "Gemini Omni Flash",
|
|
1202
|
+
series: "Gemini",
|
|
1203
|
+
description: "Google Gemini Omni Flash — faster/cheaper Omni tier: multimodal video with native audio, text/image-to-video + video-edit.",
|
|
1204
|
+
useCases: ["cinematic", "fast"],
|
|
1205
|
+
features: ["audio", "reference-image"],
|
|
1206
|
+
aspectRatios: VIDEO_RATIOS_HV,
|
|
1207
|
+
resolutions: ["720p", "1080p", "4k"],
|
|
1208
|
+
durations: [4, 6, 8, 10],
|
|
1209
|
+
pricing: [
|
|
1210
|
+
{ identifier: "gemini-omni-flash", credits: 270, note: "default — 8s 720p/1080p (the credit builder's duration fallback)" },
|
|
1211
|
+
{ identifier: "gemini-omni-flash:4", credits: 160, note: "720p/1080p 4s" },
|
|
1212
|
+
{ identifier: "gemini-omni-flash:6", credits: 210, note: "720p/1080p 6s" },
|
|
1213
|
+
{ identifier: "gemini-omni-flash:8", credits: 270, note: "720p/1080p 8s" },
|
|
1214
|
+
{ identifier: "gemini-omni-flash:10", credits: 320, note: "720p/1080p 10s" },
|
|
1215
|
+
{ identifier: "gemini-omni-flash:4k:4", credits: 370, note: "4K 4s" },
|
|
1216
|
+
{ identifier: "gemini-omni-flash:4k:6", credits: 420, note: "4K 6s" },
|
|
1217
|
+
{ identifier: "gemini-omni-flash:4k:8", credits: 480, note: "4K 8s" },
|
|
1218
|
+
{ identifier: "gemini-omni-flash:4k:10", credits: 530, note: "4K 10s" },
|
|
1219
|
+
{ identifier: "gemini-omni-flash:vref", credits: 420, note: "video-edit 720p/1080p" },
|
|
1220
|
+
{ identifier: "gemini-omni-flash:4k:vref", credits: 630, note: "video-edit 4K" },
|
|
1221
|
+
],
|
|
1222
|
+
},
|
|
1182
1223
|
|
|
1183
1224
|
// ── Kling ──
|
|
1184
1225
|
"kling": {
|
|
@@ -1450,6 +1491,66 @@ const VIDEO_MODELS: Record<string, ModelCatalogEntry> = {
|
|
|
1450
1491
|
},
|
|
1451
1492
|
|
|
1452
1493
|
// ── Wan ──
|
|
1494
|
+
// Wan 3.0 (standard + Prime) — a NEW generation, not a tier of the 2.x ladder.
|
|
1495
|
+
// One id per SKU serves BOTH modes (no t2v twin, no alias): first/last frame
|
|
1496
|
+
// OR an all-purpose reference mode (images/videos/audio, bound in the prompt
|
|
1497
|
+
// as Image1/Video1/Audio1 — no space, unlike Wan 2.x), native audio behind a
|
|
1498
|
+
// boolean `audio` lever, 2-30s at 480p/720p/1080p.
|
|
1499
|
+
// `video-reference` is deliberately NOT declared: KIE accepts reference videos,
|
|
1500
|
+
// but the extend chain is unwired and KIE caps input-video + output at 30s,
|
|
1501
|
+
// which the segment bounds cannot express. Precedent: gemini-omni-video carries
|
|
1502
|
+
// ref limits without the feature. The ref CAPS still live in
|
|
1503
|
+
// VIDEO_REF_LIMITS_BY_PROVIDER (model-constants).
|
|
1504
|
+
// `resolutions` is ascending (repo convention); the DEFAULT tier (720p) is
|
|
1505
|
+
// declared explicitly in PRICING_DEFAULT_RESOLUTION, never by array position.
|
|
1506
|
+
"wan-3": {
|
|
1507
|
+
id: "wan-3",
|
|
1508
|
+
kind: "video",
|
|
1509
|
+
modes: ["i2v", "t2v"] as const,
|
|
1510
|
+
family: "Alibaba",
|
|
1511
|
+
label: "Wan 3.0",
|
|
1512
|
+
series: "Wan",
|
|
1513
|
+
description: "Wan 3.0 — multimodal: first/last frame or image/video/audio references, native audio, 2-30s at 480p/720p/1080p.",
|
|
1514
|
+
useCases: ["motion", "narrative", "long-form"],
|
|
1515
|
+
features: ["end-frame", "audio", "reference-image"],
|
|
1516
|
+
aspectRatios: VIDEO_RATIOS_WAN_3,
|
|
1517
|
+
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],
|
|
1518
|
+
resolutions: ["480p", "720p", "1080p"],
|
|
1519
|
+
pricing: [
|
|
1520
|
+
{ identifier: "wan-3", credits: 200, note: "default 5s 720p — see :Ns:res variants for exact" },
|
|
1521
|
+
{ identifier: "wan-3:5s:720p", credits: 200, note: "5s 720p (the default tier)" },
|
|
1522
|
+
{ identifier: "wan-3:8s:480p", credits: 160, note: "8s 480p" },
|
|
1523
|
+
{ identifier: "wan-3:8s:720p", credits: 320, note: "8s 720p" },
|
|
1524
|
+
{ identifier: "wan-3:8s:1080p", credits: 640, note: "8s 1080p" },
|
|
1525
|
+
{ identifier: "wan-3:30s:480p", credits: 600, note: "30s 480p (max)" },
|
|
1526
|
+
{ identifier: "wan-3:30s:720p", credits: 1200, note: "30s 720p (max)" },
|
|
1527
|
+
{ identifier: "wan-3:30s:1080p", credits: 2400, note: "30s 1080p (max)" },
|
|
1528
|
+
],
|
|
1529
|
+
},
|
|
1530
|
+
"wan-3-prime": {
|
|
1531
|
+
id: "wan-3-prime",
|
|
1532
|
+
kind: "video",
|
|
1533
|
+
modes: ["i2v", "t2v"] as const,
|
|
1534
|
+
family: "Alibaba",
|
|
1535
|
+
label: "Wan 3.0 Prime",
|
|
1536
|
+
series: "Wan",
|
|
1537
|
+
description: "Wan 3.0 Prime — Alibaba's high-speed Wan 3.0 tier: same multimodal surface and 2-30s range, faster turnaround at a higher per-second rate.",
|
|
1538
|
+
useCases: ["fast", "motion", "narrative"],
|
|
1539
|
+
features: ["end-frame", "audio", "reference-image"],
|
|
1540
|
+
aspectRatios: VIDEO_RATIOS_WAN_3,
|
|
1541
|
+
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],
|
|
1542
|
+
resolutions: ["480p", "720p", "1080p"],
|
|
1543
|
+
pricing: [
|
|
1544
|
+
{ identifier: "wan-3-prime", credits: 320, note: "default 5s 720p — see :Ns:res variants for exact" },
|
|
1545
|
+
{ identifier: "wan-3-prime:5s:720p", credits: 320, note: "5s 720p (the default tier)" },
|
|
1546
|
+
{ identifier: "wan-3-prime:8s:480p", credits: 250, note: "8s 480p" },
|
|
1547
|
+
{ identifier: "wan-3-prime:8s:720p", credits: 510, note: "8s 720p" },
|
|
1548
|
+
{ identifier: "wan-3-prime:8s:1080p", credits: 1010, note: "8s 1080p" },
|
|
1549
|
+
{ identifier: "wan-3-prime:30s:480p", credits: 920, note: "30s 480p (max)" },
|
|
1550
|
+
{ identifier: "wan-3-prime:30s:720p", credits: 1890, note: "30s 720p (max)" },
|
|
1551
|
+
{ identifier: "wan-3-prime:30s:1080p", credits: 3780, note: "30s 1080p (max)" },
|
|
1552
|
+
],
|
|
1553
|
+
},
|
|
1453
1554
|
"wan-i2v": {
|
|
1454
1555
|
id: "wan-i2v",
|
|
1455
1556
|
kind: "video",
|
package/src/model-constants.ts
CHANGED
|
@@ -139,6 +139,13 @@ export const MAX_VIDEO_PROMPT_CHARS_BY_PROVIDER: Record<string, number> = {
|
|
|
139
139
|
// (docs.kie.ai/market/bytedance/seedance-2-5).
|
|
140
140
|
"seedance-2-5": 30000,
|
|
141
141
|
"gemini-omni-video": 20000,
|
|
142
|
+
// Gemini Omni Flash 1.1 — same 20000-char prompt surface as the pro sibling
|
|
143
|
+
// (docs.kie.ai/market/google/gemini-omni-flash-1-1).
|
|
144
|
+
"gemini-omni-flash": 20000,
|
|
145
|
+
// Wan 3.0 / 3.0 Prime — 20000 chars, excess truncated by the provider
|
|
146
|
+
// (docs.kie.ai/market/wan/3-0-video and /3-0-video-prime).
|
|
147
|
+
"wan-3": 20000,
|
|
148
|
+
"wan-3-prime": 20000,
|
|
142
149
|
"bytedance-lite": 10000,
|
|
143
150
|
"bytedance-pro": 10000,
|
|
144
151
|
"bytedance-pro-fast": 10000,
|
|
@@ -750,6 +757,11 @@ export const IMAGE_TO_VIDEO_PROVIDERS = [
|
|
|
750
757
|
"runway-kie",
|
|
751
758
|
"kling-3-omni",
|
|
752
759
|
"gemini-omni-video",
|
|
760
|
+
"gemini-omni-flash",
|
|
761
|
+
// Wan 3.0 family — one id per SKU serves BOTH modes (no t2v twin, no alias),
|
|
762
|
+
// so each id is listed in this array AND in TEXT_TO_VIDEO_PROVIDERS.
|
|
763
|
+
"wan-3",
|
|
764
|
+
"wan-3-prime",
|
|
753
765
|
"ltx-2.3-pro",
|
|
754
766
|
"ltx-2.3-fast",
|
|
755
767
|
// xAI Grok Imagine Video 1.5 — KIE i2v (image_urls required). Also listed in
|
|
@@ -788,6 +800,12 @@ export const TEXT_TO_VIDEO_PROVIDERS = [
|
|
|
788
800
|
"happyhorse",
|
|
789
801
|
"runway-kie",
|
|
790
802
|
"gemini-omni-video",
|
|
803
|
+
"gemini-omni-flash",
|
|
804
|
+
// Wan 3.0 family — REAL t2v (prompt-only runs are the documented default
|
|
805
|
+
// mode), so they belong in this main section and must NOT be gated by
|
|
806
|
+
// VIDEO_PROVIDERS_REQUIRING_IMAGE.
|
|
807
|
+
"wan-3",
|
|
808
|
+
"wan-3-prime",
|
|
791
809
|
"ltx-2.3-pro",
|
|
792
810
|
"ltx-2.3-fast",
|
|
793
811
|
// ── i2v-only providers (image required) ──────────────────────────────────
|
|
@@ -1245,6 +1263,12 @@ export const DURATION_PRICED_PROVIDERS = new Set([
|
|
|
1245
1263
|
"happyhorse",
|
|
1246
1264
|
"happyhorse-i2v",
|
|
1247
1265
|
"happyhorse-ref2v",
|
|
1266
|
+
// Wan 3.0 family — per-second billing at three resolution rates. NOTE:
|
|
1267
|
+
// gemini-omni-flash is deliberately ABSENT (like gemini-omni-video): the
|
|
1268
|
+
// Gemini Omni branch in buildVideoCreditModelIdentifier early-returns before
|
|
1269
|
+
// this gate is consulted.
|
|
1270
|
+
"wan-3",
|
|
1271
|
+
"wan-3-prime",
|
|
1248
1272
|
])
|
|
1249
1273
|
|
|
1250
1274
|
/**
|
|
@@ -1302,6 +1326,75 @@ export function normalizeMinimaxH3Resolution(resolution: string | undefined): "7
|
|
|
1302
1326
|
return resolution?.trim().toLowerCase() === "768p" ? "768P" : MINIMAX_H3_DEFAULT_RESOLUTION
|
|
1303
1327
|
}
|
|
1304
1328
|
|
|
1329
|
+
/**
|
|
1330
|
+
* Wan 3.0 family — the KIE "wan/3-0-video" market model and its high-speed
|
|
1331
|
+
* "wan/3-0-video-prime" sibling. The two share a BYTE-IDENTICAL input schema
|
|
1332
|
+
* (first/last frame OR an all-purpose reference mode with images/videos/audio,
|
|
1333
|
+
* native `audio` boolean, 2-30s, 480P/720P/1080P, six aspect ratios with
|
|
1334
|
+
* `adaptive` as the default); only the per-second rate differs. Prime is the
|
|
1335
|
+
* FASTER tier at a higher rate — never describe it as "higher quality".
|
|
1336
|
+
*
|
|
1337
|
+
* Exact-membership set — NEVER match on a "wan" prefix: "wan", "wan-i2v",
|
|
1338
|
+
* "wan-turbo", "wan-flash", "wan-videoedit" and the "wan-2.7-*" ids are
|
|
1339
|
+
* unrelated 2.x models with a different surface (and a different reference
|
|
1340
|
+
* token format — see WAN_3_DOCTRINE in @nodaro/prompts).
|
|
1341
|
+
*/
|
|
1342
|
+
export const WAN_3_PROVIDERS = new Set<string>([
|
|
1343
|
+
"wan-3",
|
|
1344
|
+
"wan-3-prime",
|
|
1345
|
+
])
|
|
1346
|
+
|
|
1347
|
+
export function isWan3Provider(provider: string | undefined): boolean {
|
|
1348
|
+
return !!provider && WAN_3_PROVIDERS.has(provider)
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
/** Wan 3.0 resolution the PLATFORM renders when the param is omitted or unknown.
|
|
1352
|
+
* Deliberately NOT KIE's own default (1080P): 720p is the tier the bare credit
|
|
1353
|
+
* identifier prices, so the provider layer pins it to keep render == billed. */
|
|
1354
|
+
export const WAN_3_DEFAULT_RESOLUTION = "720P"
|
|
1355
|
+
|
|
1356
|
+
/**
|
|
1357
|
+
* SINGLE normalization for the Wan 3.0 resolution lever (KIE wire enum
|
|
1358
|
+
* "480P" | "720P" | "1080P"). Everything INTERNAL — the catalog, QUALITY_MAP,
|
|
1359
|
+
* dropdowns, RESOLUTION_DURATION_PRICING keys and every emitted credit
|
|
1360
|
+
* identifier — stays LOWERCASE; this helper is the ONE place the uppercase wire
|
|
1361
|
+
* form is produced (backend KIE payload build), the twin of
|
|
1362
|
+
* {@link normalizeMinimaxH3Resolution}.
|
|
1363
|
+
*
|
|
1364
|
+
* Case-insensitive. Anything else (undefined, garbage, a stale "4k") collapses
|
|
1365
|
+
* to {@link WAN_3_DEFAULT_RESOLUTION} — the tier the default credit identifier
|
|
1366
|
+
* reserves — so the billed tier can never undercut the rendered one.
|
|
1367
|
+
*/
|
|
1368
|
+
export function normalizeWan3Resolution(resolution: string | undefined): "480P" | "720P" | "1080P" {
|
|
1369
|
+
switch (resolution?.trim().toLowerCase()) {
|
|
1370
|
+
case "480p": return "480P"
|
|
1371
|
+
case "1080p": return "1080P"
|
|
1372
|
+
case "720p": return "720P"
|
|
1373
|
+
default: return WAN_3_DEFAULT_RESOLUTION
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
/**
|
|
1378
|
+
* Google Gemini Omni family — the KIE "gemini-omni-video" market model and its
|
|
1379
|
+
* faster/cheaper "google/gemini-omni-flash-1-1" sibling. Both take the SAME
|
|
1380
|
+
* request shape (prompt + image_urls references, video-edit through the i2v
|
|
1381
|
+
* handle, 4/6/8/10s, 720p/1080p or a 4K band) and are dispatched through the
|
|
1382
|
+
* same runner, so every behavioural branch that used to compare against the
|
|
1383
|
+
* literal "gemini-omni-video" must ask this predicate instead — V2V routing,
|
|
1384
|
+
* the 7-slot reference quota, the mode swap and the aspect-ratio panels.
|
|
1385
|
+
*
|
|
1386
|
+
* Exact-membership set — NEVER match on a "gemini" prefix (the Gemini LLM ids
|
|
1387
|
+
* would collide).
|
|
1388
|
+
*/
|
|
1389
|
+
export const GEMINI_OMNI_PROVIDERS = new Set<string>([
|
|
1390
|
+
"gemini-omni-video",
|
|
1391
|
+
"gemini-omni-flash",
|
|
1392
|
+
])
|
|
1393
|
+
|
|
1394
|
+
export function isGeminiOmniProvider(provider: string | undefined): boolean {
|
|
1395
|
+
return !!provider && GEMINI_OMNI_PROVIDERS.has(provider)
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1305
1398
|
/**
|
|
1306
1399
|
* Video models that are CATALOGUED and priced but have NO working dispatch
|
|
1307
1400
|
* path today — selecting one fails at the router, not at validation.
|
|
@@ -1553,9 +1646,15 @@ export function maxSegmentsFor(provider: string | undefined, capSec: number): nu
|
|
|
1553
1646
|
* param at all (inferred from the frame). Only the pure-t2v endpoint requires
|
|
1554
1647
|
* a concrete ratio — the KIE provider layer coerces `adaptive` → `16:9` there
|
|
1555
1648
|
* (see applyMinimaxH3Params in backend kie/video.ts).
|
|
1649
|
+
*
|
|
1650
|
+
* Wan 3.0 also defaults to `adaptive` — it is the model's own KIE default and
|
|
1651
|
+
* the first value in its aspect enum, so an un-set node must not silently run
|
|
1652
|
+
* at 16:9 while the panel displays Adaptive.
|
|
1556
1653
|
*/
|
|
1557
1654
|
export function defaultVideoAspectRatio(provider: string | undefined): string {
|
|
1558
|
-
return isSeedance2Provider(provider) || isMinimaxH3Provider(provider)
|
|
1655
|
+
return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider)
|
|
1656
|
+
? "adaptive"
|
|
1657
|
+
: "16:9"
|
|
1559
1658
|
}
|
|
1560
1659
|
|
|
1561
1660
|
/**
|
|
@@ -1656,6 +1755,10 @@ export const SEEDANCE_2_R2V_MAX_AUDIO_SEC_BY_PROVIDER: Record<string, number> =
|
|
|
1656
1755
|
// MiniMax Hailuo 3 — documented hard limit: each reference audio segment
|
|
1657
1756
|
// 2-15s, ≤15s total (docs.kie.ai/market/minimax-h3/reference-to-video).
|
|
1658
1757
|
"minimax-h3": 15,
|
|
1758
|
+
// Wan 3.0 family — documented hard limit: each reference audio clip 1-15s,
|
|
1759
|
+
// ≤15s combined (docs.kie.ai/market/wan/3-0-video).
|
|
1760
|
+
"wan-3": 15,
|
|
1761
|
+
"wan-3-prime": 15,
|
|
1659
1762
|
}
|
|
1660
1763
|
|
|
1661
1764
|
/** The verified r2v reference-audio cap (seconds) for a provider, or null when
|
|
@@ -1711,8 +1814,17 @@ export const VIDEO_REF_LIMITS_BY_PROVIDER: Record<
|
|
|
1711
1814
|
// bills input images beyond the first 5 (11 KIE cr each) — see the
|
|
1712
1815
|
// minimax-h3 credit helper in backend ee/billing.
|
|
1713
1816
|
"minimax-h3": { ...SEEDANCE_2_REF_LIMITS },
|
|
1817
|
+
// Wan 3.0 family — all-purpose reference mode: up to 10 images / 5 videos
|
|
1818
|
+
// (each 1-15s, ≤15s combined) / 5 audio clips (each 1-15s, ≤15s combined).
|
|
1819
|
+
// The reference arrays are mutually EXCLUSIVE with first/last frame at the
|
|
1820
|
+
// provider (docs.kie.ai/market/wan/3-0-video).
|
|
1821
|
+
"wan-3": { images: 10, videos: 5, audio: 5 },
|
|
1822
|
+
"wan-3-prime": { images: 10, videos: 5, audio: 5 },
|
|
1714
1823
|
// Multi-image reference providers.
|
|
1715
1824
|
"gemini-omni-video": { images: 7, videos: 1 },
|
|
1825
|
+
// Gemini Omni Flash 1.1 — identical quota to the pro sibling
|
|
1826
|
+
// (images + 2×videos + character_ids ≤ 7).
|
|
1827
|
+
"gemini-omni-flash": { images: 7, videos: 1 },
|
|
1716
1828
|
"kling-3-omni": { images: 7 }, // catalog/docs: "end frame + up to 7 reference images"
|
|
1717
1829
|
"grok-i2v": { images: 7 }, // backend kie/models.ts maxRefImages: 7
|
|
1718
1830
|
"happyhorse-ref2v": { images: 9 }, // backend kie/models.ts maxRefImages: 9
|
|
@@ -1738,10 +1850,15 @@ export const RESOLUTION_VIDEO_REF_PRICING = SEEDANCE_2_PROVIDERS
|
|
|
1738
1850
|
/**
|
|
1739
1851
|
* Video models priced by (duration × resolution) WITHOUT a video-ref dimension.
|
|
1740
1852
|
* Identifier suffix: `:{resolution}`, appended after the duration tier; value =
|
|
1741
|
-
* the provider's PRICED resolution tiers.
|
|
1742
|
-
*
|
|
1743
|
-
*
|
|
1744
|
-
*
|
|
1853
|
+
* the provider's PRICED resolution tiers.
|
|
1854
|
+
*
|
|
1855
|
+
* Any resolution outside the list (or undefined) collapses to the provider's
|
|
1856
|
+
* DEFAULT tier, so the builder can never emit an unpriced composite (the
|
|
1857
|
+
* hard-fail guard fuzzes the full resolution space). That default is
|
|
1858
|
+
* {@link PRICING_DEFAULT_RESOLUTION} when the provider declares one, and
|
|
1859
|
+
* otherwise the FIRST entry here — so a member with a declared default (wan-3)
|
|
1860
|
+
* can list its tiers in the repo-standard ascending order without index 0
|
|
1861
|
+
* silently becoming the billed default. Distinct from
|
|
1745
1862
|
* RESOLUTION_VIDEO_REF_PRICING (Seedance gen), which also adds `-ref` variants.
|
|
1746
1863
|
*/
|
|
1747
1864
|
export const RESOLUTION_DURATION_PRICING: Record<string, readonly string[]> = {
|
|
@@ -1757,6 +1874,12 @@ export const RESOLUTION_DURATION_PRICING: Record<string, readonly string[]> = {
|
|
|
1757
1874
|
"happyhorse": ["720p", "1080p"],
|
|
1758
1875
|
"happyhorse-i2v": ["720p", "1080p"],
|
|
1759
1876
|
"happyhorse-ref2v": ["720p", "1080p"],
|
|
1877
|
+
// Wan 3.0 / Prime — per-second billing at three published resolution rates.
|
|
1878
|
+
// Ascending, matching the catalog; the BILLED default is declared explicitly
|
|
1879
|
+
// in PRICING_DEFAULT_RESOLUTION ("720p") rather than carried by index 0, and
|
|
1880
|
+
// the provider layer pins the same 720P so render == billed.
|
|
1881
|
+
"wan-3": ["480p", "720p", "1080p"],
|
|
1882
|
+
"wan-3-prime": ["480p", "720p", "1080p"],
|
|
1760
1883
|
}
|
|
1761
1884
|
|
|
1762
1885
|
/**
|
|
@@ -1779,6 +1902,13 @@ export const NATIVE_ADAPTIVE_ASPECT: Record<string, string> = {
|
|
|
1779
1902
|
"seedance-2-fast": "adaptive",
|
|
1780
1903
|
"seedance-2-mini": "adaptive",
|
|
1781
1904
|
"seedance-2-5": "adaptive",
|
|
1905
|
+
// Wan 3.0 family: `adaptive` is the enum DEFAULT and KIE documents it as
|
|
1906
|
+
// "automatically selects the ratio based on the input media and intent"
|
|
1907
|
+
// (docs.kie.ai/market/wan/3-0-video) — i.e. match-the-input, not merely
|
|
1908
|
+
// "provider default" (the grok `auto` trap). DOC-verified only; re-confirm
|
|
1909
|
+
// with a live job before relying on it for off-catalog ratios.
|
|
1910
|
+
"wan-3": "adaptive",
|
|
1911
|
+
"wan-3-prime": "adaptive",
|
|
1782
1912
|
}
|
|
1783
1913
|
|
|
1784
1914
|
/**
|
|
@@ -1877,8 +2007,9 @@ export type VideoAudioMode = "none" | "ambient" | "native_speech" | "audio_drive
|
|
|
1877
2007
|
|
|
1878
2008
|
export interface VideoAudioCapability {
|
|
1879
2009
|
mode: VideoAudioMode
|
|
1880
|
-
/** Provider-option field carrying the on/off toggle, when user-controllable.
|
|
1881
|
-
|
|
2010
|
+
/** Provider-option field carrying the on/off toggle, when user-controllable.
|
|
2011
|
+
* `audio` is Wan 3.0's own boolean lever (KIE `input.audio`, default true). */
|
|
2012
|
+
field?: "generateAudio" | "sound" | "audio"
|
|
1882
2013
|
/** Audio is always produced and can't be turned off by the user (VEO 3.x). */
|
|
1883
2014
|
alwaysOn?: boolean
|
|
1884
2015
|
/** Enabling audio raises the credit cost (Kling — see AUDIO_ADDON_PROVIDERS). */
|
|
@@ -1937,6 +2068,19 @@ export const VIDEO_AUDIO_CAPABILITY: Record<string, VideoAudioCapability> = {
|
|
|
1937
2068
|
// KIE API exposes NO audio on/off parameter (audio is always produced), so
|
|
1938
2069
|
// there is no toggle field — alwaysOn, like VEO.
|
|
1939
2070
|
"minimax-h3": { mode: "audio_driven", alwaysOn: true },
|
|
2071
|
+
// Wan 3.0 family — a single boolean `audio` lever (KIE default true) produces
|
|
2072
|
+
// an ambient/SFX track with the clip. Classified "ambient", NOT
|
|
2073
|
+
// "native_speech" or "audio_driven": the schema documents no dialogue
|
|
2074
|
+
// guarantee, and reference audio is a generic conditioning array, not a
|
|
2075
|
+
// verified lip-sync transport. Upgrade only on a live probe (the kling-3.0
|
|
2076
|
+
// standard) — `audio_driven` would reroute the Story→Video dialogue pipeline
|
|
2077
|
+
// and skip the lip-sync pass. `defaultOn` mirrors the KIE default so an
|
|
2078
|
+
// intent-less request is described honestly; audio is priced into the uniform
|
|
2079
|
+
// per-second rate, so NOT cost-affecting (no `:audio` composite).
|
|
2080
|
+
// gemini-omni-flash is deliberately ABSENT — gemini-omni-video is absent too
|
|
2081
|
+
// (mode "none"), and the siblings must not disagree.
|
|
2082
|
+
"wan-3": { mode: "ambient", field: "audio", defaultOn: true },
|
|
2083
|
+
"wan-3-prime": { mode: "ambient", field: "audio", defaultOn: true },
|
|
1940
2084
|
}
|
|
1941
2085
|
|
|
1942
2086
|
const VIDEO_AUDIO_NONE: VideoAudioCapability = { mode: "none" }
|
|
@@ -2008,6 +2152,7 @@ export function applyVideoAudioToggle(
|
|
|
2008
2152
|
const enabled = cap.affectsCost ? opts?.sound : (opts?.sound ?? opts?.generateAudio)
|
|
2009
2153
|
if (enabled === undefined) return // no intent — keep the model's own default
|
|
2010
2154
|
if (cap.field === "generateAudio") input.generate_audio = enabled
|
|
2155
|
+
else if (cap.field === "audio") input.audio = enabled
|
|
2011
2156
|
else input.sound = enabled
|
|
2012
2157
|
}
|
|
2013
2158
|
|
|
@@ -2063,6 +2208,11 @@ export const VIDEO_VARIABLE_PRICING: Record<string, "duration" | "duration+audio
|
|
|
2063
2208
|
"minimax-h3": "duration+resolution",
|
|
2064
2209
|
// Grok Imagine Video 1.5 — per-second billing split 480p/720p (no video-ref dimension).
|
|
2065
2210
|
"grok-imagine-video-1.5": "duration+resolution",
|
|
2211
|
+
// Wan 3.0 family — per-second billing at three resolution rates (no video-ref
|
|
2212
|
+
// dimension: reference runs bill output seconds only). No gemini-omni-flash
|
|
2213
|
+
// entry, mirroring gemini-omni-video which has none either.
|
|
2214
|
+
"wan-3": "duration+resolution",
|
|
2215
|
+
"wan-3-prime": "duration+resolution",
|
|
2066
2216
|
}
|
|
2067
2217
|
|
|
2068
2218
|
/**
|
|
@@ -2098,6 +2248,14 @@ export const PRICING_DEFAULT_DURATION_SEC: Record<string, number> = {
|
|
|
2098
2248
|
export const PRICING_DEFAULT_RESOLUTION: Record<string, string> = {
|
|
2099
2249
|
// KIE renders 720p when `resolution` is omitted (kie/models.ts extraParams).
|
|
2100
2250
|
"seedance-2-5": "720p",
|
|
2251
|
+
// Wan 3.0 family — KIE's OWN default is 1080P, but the provider layer pins
|
|
2252
|
+
// 720P (normalizeWan3Resolution / WAN_3_DEFAULT_RESOLUTION) so the rendered
|
|
2253
|
+
// tier equals the tier the bare identifier bills. This declaration is what
|
|
2254
|
+
// makes the billed default explicit instead of an array ordering: the
|
|
2255
|
+
// RESOLUTION_DURATION_PRICING branch consults it before falling back to the
|
|
2256
|
+
// first tier, so the catalog can stay ascending without repricing anything.
|
|
2257
|
+
"wan-3": "720p",
|
|
2258
|
+
"wan-3-prime": "720p",
|
|
2101
2259
|
}
|
|
2102
2260
|
|
|
2103
2261
|
/** HappyHorse 1.1 per-second tiers — one per allowed duration (3–15s), shared
|
|
@@ -2122,6 +2280,21 @@ const SEEDANCE_2_5_DURATION_TIERS: Array<{ maxSeconds: number; suffix: string }>
|
|
|
2122
2280
|
(_, i) => ({ maxSeconds: i + 4, suffix: `${i + 4}s` }),
|
|
2123
2281
|
)
|
|
2124
2282
|
|
|
2283
|
+
/**
|
|
2284
|
+
* Wan 3.0 per-second tiers — one per allowed duration (2-30s), shared by both
|
|
2285
|
+
* SKUs (the ladder shape is identical; only the seeded rates differ).
|
|
2286
|
+
*
|
|
2287
|
+
* Per-second is REQUIRED, not a nicety: the ladder snaps a request UP to the
|
|
2288
|
+
* first tier whose `maxSeconds` covers it and falls back to the LAST tier when
|
|
2289
|
+
* none does, so a coarse ladder over a 29-value range would reserve a
|
|
2290
|
+
* short-clip price for a 30s render. `commit_credits` only ever refunds a
|
|
2291
|
+
* surplus and can never collect an upward delta.
|
|
2292
|
+
*/
|
|
2293
|
+
const WAN_3_DURATION_TIERS: Array<{ maxSeconds: number; suffix: string }> = Array.from(
|
|
2294
|
+
{ length: 29 },
|
|
2295
|
+
(_, i) => ({ maxSeconds: i + 2, suffix: `${i + 2}s` }),
|
|
2296
|
+
)
|
|
2297
|
+
|
|
2125
2298
|
/**
|
|
2126
2299
|
* Duration tier breakpoints for variable-priced video models.
|
|
2127
2300
|
* Maps provider → array of { maxSeconds, suffix } in ascending order.
|
|
@@ -2202,6 +2375,8 @@ export const VIDEO_DURATION_TIERS: Record<string, Array<{ maxSeconds: number; su
|
|
|
2202
2375
|
{ maxSeconds: 15, suffix: "15s" },
|
|
2203
2376
|
],
|
|
2204
2377
|
"seedance-2-5": SEEDANCE_2_5_DURATION_TIERS,
|
|
2378
|
+
"wan-3": WAN_3_DURATION_TIERS,
|
|
2379
|
+
"wan-3-prime": WAN_3_DURATION_TIERS,
|
|
2205
2380
|
// MiniMax Hailuo 3 — true per-second billing (KIE 36.5 cr/s @2K, 22.5 cr/s
|
|
2206
2381
|
// @768P). One tier per allowed second (4-15s) so the composite identifier
|
|
2207
2382
|
// maps 1:1 to the seeded price — no rounding/overcharge for any on-menu
|
|
@@ -187,6 +187,10 @@ const QUALITY_MAP: Record<string, QualityMapping> = {
|
|
|
187
187
|
// Seedance 2.5 spans 480p/720p/1080p on KIE (1080p accepted since the
|
|
188
188
|
// 2026-08-17 re-probe; 4k still rejected), so each quality rung gets its own tier.
|
|
189
189
|
"seedance-2-5": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
|
|
190
|
+
// Wan 3.0 family — 480p / 720p / 1080p (lowercase catalog spellings; the
|
|
191
|
+
// uppercase KIE wire form is produced only by normalizeWan3Resolution).
|
|
192
|
+
"wan-3": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
|
|
193
|
+
"wan-3-prime": { field: "resolution", values: { low: "480p", mid: "720p", high: "1080p" } },
|
|
190
194
|
"wan-2.7-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
191
195
|
"wan-2.7-t2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
192
196
|
"happyhorse": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
|
|
@@ -200,6 +204,7 @@ const QUALITY_MAP: Record<string, QualityMapping> = {
|
|
|
200
204
|
"ltx-2.3-pro": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
|
|
201
205
|
"ltx-2.3-fast": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
|
|
202
206
|
"gemini-omni-video": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
|
|
207
|
+
"gemini-omni-flash": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
|
|
203
208
|
// Grok Imagine Video 1.5 — only 480p/720p (no 1080p tier); high clamps to 720p.
|
|
204
209
|
"grok-imagine-video-1.5": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
|
|
205
210
|
// Replicate Flux 2 family — MP-based resolution (matching IMAGE_RESOLUTION_OPTIONS["flux-2-*"]).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI-default fills for the unified video nodes — the ONE source of truth shared
|
|
3
|
+
* by the backend DAG payload builder, the config-panel fail-safe snaps and the
|
|
4
|
+
* node's hover/run strip.
|
|
5
|
+
*
|
|
6
|
+
* Several config panels RENDER a default without persisting it to node data, so
|
|
7
|
+
* an untouched node submits `aspectRatio` / `resolution` undefined and the
|
|
8
|
+
* enqueued job row (and the /v1/jobs echo) then disagrees with what actually
|
|
9
|
+
* renders. Worse, the panels' generic snap writes `resolutions[0]` for a stale
|
|
10
|
+
* value, which is the CHEAPEST tier under the repo's ascending-resolution
|
|
11
|
+
* convention — not necessarily the tier the model renders and bills.
|
|
12
|
+
*
|
|
13
|
+
* These helpers were local to `backend/src/services/workflow-engine/payload-builder.ts`
|
|
14
|
+
* until the Wan 3.0 launch gave the platform its first provider whose declared
|
|
15
|
+
* billing default differs from `resolutions[0]`; three surfaces then had to
|
|
16
|
+
* agree, so they live here.
|
|
17
|
+
*
|
|
18
|
+
* The resolution fill is per-family ON PURPOSE. Wan 3.0 reads its DECLARED
|
|
19
|
+
* billing default (PRICING_DEFAULT_RESOLUTION = 720p) because its catalog list
|
|
20
|
+
* is ascending, so an index-0 fill would write 480p — a tier both `runWan3`
|
|
21
|
+
* (which renders 720P) and the credit identifier (which bills the 720p row)
|
|
22
|
+
* disagree with. The Seedance family keeps its historical first-catalog-tier
|
|
23
|
+
* fill, deliberately: switching it to PRICING_DEFAULT_RESOLUTION would reprice
|
|
24
|
+
* live seedance-2-5 runs, whose declared default (720p) differs from the 480p
|
|
25
|
+
* this has always filled. That 480p-fill vs 720p-billing-default divergence on
|
|
26
|
+
* seedance-2-5 is a KNOWN pre-existing gap, out of scope here — do not "align"
|
|
27
|
+
* the branches without repricing it deliberately.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
PRICING_DEFAULT_RESOLUTION,
|
|
32
|
+
isSeedance2Provider,
|
|
33
|
+
isMinimaxH3Provider,
|
|
34
|
+
isWan3Provider,
|
|
35
|
+
isGeminiOmniProvider,
|
|
36
|
+
} from "./model-constants.js"
|
|
37
|
+
import { MODEL_CATALOG } from "./model-catalog.js"
|
|
38
|
+
|
|
39
|
+
/** `adaptive` is the aspect default for Seedance 2, MiniMax H3 and Wan 3.0. */
|
|
40
|
+
export function uiAspectRatioFill(provider: string): string | undefined {
|
|
41
|
+
return isSeedance2Provider(provider) || isMinimaxH3Provider(provider) || isWan3Provider(provider)
|
|
42
|
+
? "adaptive"
|
|
43
|
+
: undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** See the file docstring — per-family on purpose; never a generic
|
|
47
|
+
* PRICING_DEFAULT_RESOLUTION read (that would reprice seedance-2-5). */
|
|
48
|
+
export function uiResolutionFill(provider: string): string | undefined {
|
|
49
|
+
if (isWan3Provider(provider)) return PRICING_DEFAULT_RESOLUTION[provider]
|
|
50
|
+
if (isSeedance2Provider(provider)) return MODEL_CATALOG[provider]?.resolutions?.[0]
|
|
51
|
+
return undefined
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Duration the node RENDERS and BILLS when `data.duration` is unset, for the
|
|
56
|
+
* families whose credit identifier declares a duration fallback that is NOT
|
|
57
|
+
* `durations[0]`. Wan 3.0's bare identifier is the 5s tier while its ladder
|
|
58
|
+
* starts at 2s; the Gemini Omni family's is the 8s tier while its ladder starts
|
|
59
|
+
* at 4s. Everyone else falls back to the first listed duration, so this returns
|
|
60
|
+
* undefined and the caller keeps `durations[0]`.
|
|
61
|
+
*/
|
|
62
|
+
export function uiDurationFill(provider: string): number | undefined {
|
|
63
|
+
if (isWan3Provider(provider)) return 5
|
|
64
|
+
if (isGeminiOmniProvider(provider)) return 8
|
|
65
|
+
return undefined
|
|
66
|
+
}
|