@nodaro/shared 1.9.0 → 1.11.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.
@@ -37,6 +37,7 @@ export const IMAGE_PROMPT_MAX = 5000
37
37
  export const MAX_IMAGE_PROMPT_CHARS_BY_PROVIDER: Record<string, number> = {
38
38
  // ── higher than the 5000 default ──
39
39
  "nano-banana-2": 20000, // docs.kie.ai/market/google/nano-banana-2
40
+ "nano-banana-2-lite": 20000, // docs.kie.ai/market/google/nano-banana-2-lite
40
41
  "nano-banana-pro": 20000, // docs.kie.ai/market/google/pro-image-to-image
41
42
  "gpt-image-2-i2i": 20000, // docs.kie.ai/market/gpt/gpt-image-2-image-to-image
42
43
  // ── lower than the 5000 default (over-send risk if left at default) ──
@@ -48,7 +49,8 @@ export const MAX_IMAGE_PROMPT_CHARS_BY_PROVIDER: Record<string, number> = {
48
49
  "qwen-edit": 2000, // docs.kie.ai/market/qwen/image-edit
49
50
  // verified == 5000 default (no entry needed): imagen4(-fast/-ultra), nano-banana,
50
51
  // nano-banana-edit, flux, flux-flex, gpt-image-2, ideogram-v3/-edit/-remix,
51
- // z-image, grok, qwen-i2i.
52
+ // z-image, grok, qwen-i2i, seedream-5-pro, seedream-5-pro-i2i
53
+ // (docs.kie.ai/market/seedream/5-pro-text-to-image + 5-pro-image-to-image).
52
54
  // grok-i2i: doc states 390000 (78× its t2i sibling) — treated as a KIE schema
53
55
  // typo and left at the 5000 default per the sanity-cap decision.
54
56
  // UNVERIFIED (no limit stated in schema) → 5000 default: flux-kontext(-max)
@@ -93,6 +95,18 @@ export const SUNO_TEXT_MAX = 5000
93
95
  */
94
96
  export const PROMPT_HARD_CEILING = 20000
95
97
 
98
+ /**
99
+ * Ceiling for LLM TEXT-generation node inputs (the "Generate Text"/llm-chat node
100
+ * + AI Writer + Generate Script `systemPrompt`/`userInput`/`prompt` fields).
101
+ * Distinct from PROMPT_HARD_CEILING (an image/video PROMPT budget): these inputs
102
+ * go straight into an LLM whose context is huge (Claude 200K / GPT 128K+ /
103
+ * Gemini 1M tokens), so the old flat 10000 was a false blocker on pasting a
104
+ * document to summarize or rewrite. 100000 chars (~25K input tokens) covers
105
+ * long-form inputs while still bounding abuse; the OUTPUT stays capped by each
106
+ * route's maxTokens.
107
+ */
108
+ export const LLM_TEXT_INPUT_MAX = 100_000
109
+
96
110
  /**
97
111
  * Per-provider maximum VIDEO prompt length (chars), VERIFIED against each model's
98
112
  * official docs.kie.ai schema (2026-06). Absent → {@link VIDEO_PROMPT_MAX} (8000)
@@ -333,6 +347,7 @@ export const MODELS_WITH_REFERENCE_IMAGE_SUPPORT = new Set([
333
347
  "nano-banana",
334
348
  "nano-banana-pro",
335
349
  "nano-banana-2",
350
+ "nano-banana-2-lite",
336
351
  // T2I providers that auto-route to their i2i sibling when refs are attached
337
352
  "gpt-image",
338
353
  "gpt-image-2",
@@ -340,6 +355,7 @@ export const MODELS_WITH_REFERENCE_IMAGE_SUPPORT = new Set([
340
355
  "qwen",
341
356
  "seedream",
342
357
  "seedream-5-lite",
358
+ "seedream-5-pro",
343
359
  "flux",
344
360
  "flux-flex",
345
361
  // Image editing / image-to-image (reference = source image)
@@ -357,6 +373,7 @@ export const MODELS_WITH_REFERENCE_IMAGE_SUPPORT = new Set([
357
373
  "qwen-edit",
358
374
  "seedream-edit",
359
375
  "seedream-5-lite-i2i",
376
+ "seedream-5-pro-i2i",
360
377
  "grok-i2i",
361
378
  // Upscale / background ops (source acts as the reference)
362
379
  "recraft-remove-bg",
@@ -386,6 +403,7 @@ export const T2I_TO_I2I_VARIANT: Record<string, string> = {
386
403
  "qwen": "qwen-i2i",
387
404
  "seedream": "seedream-edit",
388
405
  "seedream-5-lite": "seedream-5-lite-i2i",
406
+ "seedream-5-pro": "seedream-5-pro-i2i",
389
407
  "flux": "flux-pro-i2i",
390
408
  "flux-flex": "flux-i2i",
391
409
  }
@@ -405,6 +423,7 @@ export const REF_IMAGE_MAX_LIMITS: Record<string, number> = {
405
423
  "nano-banana": 8,
406
424
  "nano-banana-pro": 8,
407
425
  "nano-banana-2": 4,
426
+ "nano-banana-2-lite": 10,
408
427
  "wan-2.7": 9,
409
428
  // Image-to-image (multi-source array)
410
429
  "nano-banana-edit": 8,
@@ -414,6 +433,7 @@ export const REF_IMAGE_MAX_LIMITS: Record<string, number> = {
414
433
  "flux-pro-i2i": 4,
415
434
  "seedream-edit": 16,
416
435
  "seedream-5-lite-i2i": 16,
436
+ "seedream-5-pro-i2i": 16,
417
437
  // Single-source i2i (one input image)
418
438
  "flux-kontext": 1,
419
439
  "flux-kontext-max": 1,
@@ -484,6 +504,8 @@ export const VARIABLE_PRICING_MODELS: Record<string, "quality" | "resolution" |
484
504
  "seedream-edit": "quality",
485
505
  "seedream-5-lite": "quality",
486
506
  "seedream-5-lite-i2i": "quality",
507
+ "seedream-5-pro": "quality",
508
+ "seedream-5-pro-i2i": "quality",
487
509
  "topaz-image-upscale": "resolution",
488
510
  "ideogram-edit": "rendering-speed",
489
511
  "ideogram-remix": "rendering-speed",
@@ -495,7 +517,7 @@ export const VARIABLE_PRICING_MODELS: Record<string, "quality" | "resolution" |
495
517
 
496
518
 
497
519
  // Models where quality=high triggers composite credit identifier
498
- export const HIGH_QUALITY_PROVIDERS = new Set(["gpt-image", "gpt-image-i2i", "seedream", "seedream-edit", "seedream-5-lite", "seedream-5-lite-i2i"])
520
+ export const HIGH_QUALITY_PROVIDERS = new Set(["gpt-image", "gpt-image-i2i", "seedream", "seedream-edit", "seedream-5-lite", "seedream-5-lite-i2i", "seedream-5-pro", "seedream-5-pro-i2i"])
499
521
 
500
522
  // Models where resolution=2K triggers composite credit identifier
501
523
  export const TWO_K_RESOLUTION_PROVIDERS = new Set(["flux", "flux-pro-i2i", "flux-flex", "flux-i2i"])
@@ -522,6 +544,7 @@ export const IMAGE_GEN_PROVIDERS = [
522
544
  "flux",
523
545
  "nano-banana-pro",
524
546
  "nano-banana-2",
547
+ "nano-banana-2-lite",
525
548
  "grok",
526
549
  "gpt-image",
527
550
  "gpt-image-2",
@@ -532,6 +555,7 @@ export const IMAGE_GEN_PROVIDERS = [
532
555
  "qwen",
533
556
  "seedream",
534
557
  "seedream-5-lite",
558
+ "seedream-5-pro",
535
559
  "flux-flex",
536
560
  "flux-kontext",
537
561
  "flux-kontext-max",
@@ -548,6 +572,7 @@ export const IMAGE_GEN_PROVIDERS = [
548
572
  export const IMAGE_I2I_PROVIDERS = [
549
573
  "nano-banana",
550
574
  "nano-banana-2",
575
+ "nano-banana-2-lite",
551
576
  "nano-banana-pro",
552
577
  "grok-i2i",
553
578
  "flux-i2i",
@@ -561,6 +586,7 @@ export const IMAGE_I2I_PROVIDERS = [
561
586
  "qwen-edit",
562
587
  "seedream-edit",
563
588
  "seedream-5-lite-i2i",
589
+ "seedream-5-pro-i2i",
564
590
  "flux-kontext",
565
591
  "flux-kontext-max",
566
592
  // Replicate Open (uncensored) — multi-image Kontext via Replicate
@@ -1003,10 +1029,12 @@ export const IMAGE_MASK_MODE: Record<ImageGenProvider, ImageMaskMode> = {
1003
1029
  "nano-banana": "prompt",
1004
1030
  "nano-banana-pro": "prompt",
1005
1031
  "nano-banana-2": "prompt",
1032
+ "nano-banana-2-lite": "prompt",
1006
1033
  "gpt-image": "prompt",
1007
1034
  "gpt-image-2": "prompt",
1008
1035
  "seedream": "prompt",
1009
1036
  "seedream-5-lite": "prompt",
1037
+ "seedream-5-pro": "prompt",
1010
1038
  "qwen": "prompt",
1011
1039
  "flux-kontext": "prompt",
1012
1040
  "flux-kontext-max": "prompt",
@@ -1129,6 +1157,29 @@ export const SEEDANCE_2_REF_LIMITS = {
1129
1157
  audio: 3,
1130
1158
  } as const
1131
1159
 
1160
+ /**
1161
+ * KIE r2v REFERENCE-VIDEO MINIMUM (seconds) for the Seedance 2.0 family — the
1162
+ * provider hard-rejects shorter reference clips with a 400 BEFORE generation:
1163
+ * "the parameter video duration (seconds) specified in the request must be
1164
+ * greater than or equal to 1.8 for model dreamina-seedance-2-0-fast in r2v"
1165
+ * (2026-07-13, job dbf95612 — every 1.0s continuation tail failed
1166
+ * deterministically). Mirror of the reference-AUDIO maximum below.
1167
+ */
1168
+ export const SEEDANCE_2_R2V_MIN_REF_VIDEO_SEC = 1.8
1169
+
1170
+ /**
1171
+ * The continuation-reference length (seconds) every Seedance-2 chaining
1172
+ * feature actually cuts — extend-node tails, generate-video-pro segment
1173
+ * tails, edit-video-pro refOut/refIn brackets — AND the length the gvp/evp
1174
+ * credit formulas bill per continuation join. Clears the provider floor
1175
+ * above with margin while staying short enough to keep the model focused on
1176
+ * continuing the boundary motion instead of re-staging the whole clip.
1177
+ * Guarded ≥ floor by model-constants tests; the private-plugin twin
1178
+ * (nodaro-cloud-plugins chain.ts TAIL_SEC / bridge-math.ts MIN_REF) is
1179
+ * guarded by that repo's r2v-ref-floor.test.ts — keep the two in sync.
1180
+ */
1181
+ export const SEEDANCE_2_CONTINUATION_REF_SEC = 2
1182
+
1132
1183
  /**
1133
1184
  * Trim-stitch parameters for the seedance-2-extend provider (spike-validated
1134
1185
  * 2026-06-11):
@@ -1147,10 +1198,11 @@ export const SEEDANCE_2_EXTEND_STITCH = {
1147
1198
  trimHeadFrames: 3,
1148
1199
  /** Boundary audio fade length (seconds), timeline-preserving. */
1149
1200
  audioFadeSec: 0.15,
1150
- /** Seconds of the source's TAIL passed as the @video_1 reference —
1151
- * spike-validated: a short tail keeps the model focused on continuing
1152
- * the boundary motion instead of re-staging the whole clip. */
1153
- referenceTailSeconds: 1,
1201
+ /** Seconds of the source's TAIL passed as the @video_1 reference — short
1202
+ * keeps the model focused on continuing the boundary motion; the value is
1203
+ * floored by SEEDANCE_2_R2V_MIN_REF_VIDEO_SEC (the original spike's 1s
1204
+ * tail is now provider-rejected). */
1205
+ referenceTailSeconds: SEEDANCE_2_CONTINUATION_REF_SEC,
1154
1206
  } as const
1155
1207
 
1156
1208
  /**
@@ -1341,8 +1393,13 @@ export const AUDIO_ADDON_PROVIDERS = new Set([
1341
1393
  * lip-synced spoken dialogue. Toggle is offered; the
1342
1394
  * pipeline still uses TTS + lip-sync for dialogue.
1343
1395
  * "native_speech" — bakes spoken dialogue + lip movement from the prompt
1344
- * (VEO 3.x). The pipeline injects the dialogue line, enables
1345
- * audio, and revoices the clip to the character's saved voice.
1396
+ * (VEO 3.x always-on; Kling 2.6/3.0 behind the `sound`
1397
+ * toggle probe-verified 2026-07-16: scripted lines come
1398
+ * back word-for-word with articulated lips on the KIE
1399
+ * path, matching the official Kling 2.6 audio guide and
1400
+ * Kling 3.0 prompting docs). The pipeline injects the
1401
+ * dialogue line, enables audio, and revoices the clip to
1402
+ * the character's saved voice.
1346
1403
  * "audio_driven" — lip-syncs to a supplied reference-audio track (Seedance
1347
1404
  * 2.0 multimodal). The pipeline synthesises the character's
1348
1405
  * voice first, feeds it as reference audio, and skips the
@@ -1358,6 +1415,14 @@ export interface VideoAudioCapability {
1358
1415
  alwaysOn?: boolean
1359
1416
  /** Enabling audio raises the credit cost (Kling — see AUDIO_ADDON_PROVIDERS). */
1360
1417
  affectsCost?: boolean
1418
+ /**
1419
+ * The model generates audio when the caller expresses NO intent (its own
1420
+ * config default is on — kling-3.0's `sound: true`, kling-3-omni's
1421
+ * `generate_audio: true`). The `:audio` credit suffix mirrors this default
1422
+ * so an intent-less request is billed for the audio it actually produces
1423
+ * (see buildVideoCreditModelIdentifier). Absent ⇒ default off.
1424
+ */
1425
+ defaultOn?: boolean
1361
1426
  }
1362
1427
 
1363
1428
  /**
@@ -1374,9 +1439,22 @@ export const VIDEO_AUDIO_CAPABILITY: Record<string, VideoAudioCapability> = {
1374
1439
  veo3: { mode: "native_speech", alwaysOn: true },
1375
1440
  "veo3.1": { mode: "native_speech", alwaysOn: true },
1376
1441
  veo3_lite: { mode: "native_speech", alwaysOn: true },
1377
- // Kling 2.6 / 3.0 — ambient sound/SFX toggle; not lip-synced speech. Cost-affecting.
1378
- kling: { mode: "ambient", field: "sound", affectsCost: true },
1379
- "kling-3.0": { mode: "ambient", field: "sound", affectsCost: true },
1442
+ // Kling 2.6 / 3.0 — native spoken dialogue + lip sync behind the `sound`
1443
+ // toggle (probe-verified on the KIE path 2026-07-16: scripted quoted lines
1444
+ // are spoken verbatim with articulated lips; the official Kling 2.6 audio
1445
+ // guide documents speech/dialogue/narration/singing with [Character@Voice]
1446
+ // binding, zh+en voices). Cost-affecting: `:audio` credit suffix.
1447
+ // kling-3.0's model default is sound ON (kie models.ts extraParams +
1448
+ // kling3-client `?? true`) → defaultOn keeps billing aligned with what an
1449
+ // intent-less request actually generates; kling 2.6 defaults OFF.
1450
+ kling: { mode: "native_speech", field: "sound", affectsCost: true },
1451
+ "kling-3.0": { mode: "native_speech", field: "sound", affectsCost: true, defaultOn: true },
1452
+ // Kling 3.0 Omni (Replicate kwaivgi/kling-v3-omni-video) — the Omni tier's
1453
+ // headline feature IS native dialogue (per-character voices, unified audio
1454
+ // timeline). Lever is Replicate's `generate_audio` (default true in our
1455
+ // provider config → defaultOn); audio is priced into the flat per-duration
1456
+ // rate, so NOT cost-affecting (no :audio composite).
1457
+ "kling-3-omni": { mode: "native_speech", field: "generateAudio", defaultOn: true },
1380
1458
  // Seedance 1.x — optional ambient audio (generate_audio); not dialogue.
1381
1459
  seedance: { mode: "ambient", field: "generateAudio" },
1382
1460
  // Seedance 2.0 — multimodal; lip-syncs to a supplied reference-audio track.
@@ -1405,11 +1483,11 @@ export function videoModelSupportsAudio(model: string | undefined): boolean {
1405
1483
 
1406
1484
  /**
1407
1485
  * True when the model can produce lip-synced spoken DIALOGUE — either natively
1408
- * (VEO) or driven by a supplied audio track (Seedance 2.0). Drives the Story→Video
1409
- * dialogue auto-pick: in-model speech + character revoice (VEO) / character-voiced
1410
- * reference audio (Seedance 2.0) vs. the TTS + separate-lip-sync fallback.
1411
- * Ambient-only models (Kling, Seedance 1.x) return `false` — their audio is SFX,
1412
- * not speech.
1486
+ * (VEO 3.x, Kling 2.6/3.0/Omni) or driven by a supplied audio track (Seedance
1487
+ * 2.0). Drives the Story→Video dialogue auto-pick: in-model speech + character
1488
+ * revoice (VEO, Kling) / character-voiced reference audio (Seedance 2.0) vs.
1489
+ * the TTS + separate-lip-sync fallback. Ambient-only models (Seedance 1.x)
1490
+ * return `false` — their audio is SFX, not speech.
1413
1491
  */
1414
1492
  export function videoModelCanSpeakDialogue(model: string | undefined): boolean {
1415
1493
  const mode = getVideoAudioCapability(model).mode
@@ -174,6 +174,8 @@ const QUALITY_MAP: Record<string, QualityMapping> = {
174
174
  "seedream-edit": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
175
175
  "seedream-5-lite": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
176
176
  "seedream-5-lite-i2i": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
177
+ "seedream-5-pro": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
178
+ "seedream-5-pro-i2i": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
177
179
  // Video gen — resolution-style (720p/1080p)
178
180
  "veo3": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
179
181
  "veo3.1": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
@@ -248,6 +250,7 @@ const GENERATE_IMAGE_PROVIDER_TO_MODEL: Record<string, string> = {
248
250
  "nano-banana": "gemini-2.5-flash-image",
249
251
  "nano-banana-pro": "gemini-2.5-flash-image",
250
252
  "nano-banana-2": "gemini-2.5-flash-image",
253
+ "nano-banana-2-lite": "gemini-3.1-flash-lite-image",
251
254
  }
252
255
 
253
256
  export function deriveLinkedFields(
@@ -10,13 +10,16 @@
10
10
  * these.
11
11
  *
12
12
  * The measured-rate constants and the $-derived `videoAnalysisBucketCredits`
13
- * formula live in `backend/src/lib/pricing/video-analysis-cost.ts` (core,
14
- * not ee/ — the MCP tool description builder needs them regardless of
15
- * edition). They were moved out of this package (published Apache-2.0 on
16
- * npm an irrevocable grant) per the 2026-07-06 public-flip IP audit, S5.
13
+ * formula that GENERATE these numbers live PRIVATELY in the
14
+ * `@nodaroai/cloud-plugins` package (`src/plugins/video-analysis/cost.ts`)
15
+ * never in this public repo. They were first moved out of this package
16
+ * (published Apache-2.0 on npm) per the 2026-07-06 public-flip IP audit S5,
17
+ * then out of the app repo entirely alongside the rest of the video-analysis
18
+ * node. A cross-check test in that private package guards this table so the
19
+ * public numbers can't silently drift from the formula.
17
20
  *
18
21
  * `VIDEO_ANALYSIS_BUCKET_CREDITS` below is the precomputed OUTPUT of that
19
- * backend formula for every (model × bucket) combination — a plain credit
22
+ * private formula for every (model × bucket) combination — a plain credit
20
23
  * lookup table, not a formula, mirroring the same wire-contract pattern
21
24
  * `VIDEO_CLIP_CREDITS` uses in `film-pricing.ts`. It is what the frontend's
22
25
  * client-side cost preview (`estimateNodeCredits` in
@@ -34,11 +37,12 @@ const WINDOW_LEN = 150, WINDOW_STRIDE = 145, WINDOW_OVERLAP = 5
34
37
  export const VIDEO_ANALYSIS_WINDOW = { LEN: WINDOW_LEN, STRIDE: WINDOW_STRIDE, OVERLAP: WINDOW_OVERLAP, SINGLE_MAX: 180 } as const
35
38
 
36
39
  /**
37
- * Precomputed credit cost per (model, bucket) — the OUTPUT of the backend's
38
- * `videoAnalysisBucketCredits` formula, not a formula itself. Regenerate by
39
- * running that function for every `VIDEO_ANALYSIS_LLM_MODELS` × duration
40
- * bucket combination whenever the underlying rate/token constants change
41
- * (backend test guards drift). Keep in sync with
40
+ * Precomputed credit cost per (model, bucket) — the OUTPUT of the private
41
+ * `videoAnalysisBucketCredits` formula (in `@nodaroai/cloud-plugins`), not a
42
+ * formula itself. Regenerate by running that function for every
43
+ * `VIDEO_ANALYSIS_LLM_MODELS` × duration bucket combination whenever the
44
+ * underlying rate/token constants change (the plugin's cost test guards drift).
45
+ * Keep in sync with
42
46
  * `docs/nodes/processing-video/video-analysis.md`.
43
47
  */
44
48
  export const VIDEO_ANALYSIS_BUCKET_CREDITS: Record<string, number> = {
@@ -34,11 +34,18 @@ export const entitySlotSchema = z.object({
34
34
  })
35
35
  export type EntitySlot = z.infer<typeof entitySlotSchema>
36
36
 
37
- const audioSchema = z.object({
38
- mode: z.enum(["speech", "music", "sfx", "silence"]),
39
- content: z.string(), // speech: verbatim quote; music/sfx: gen-ready description; silence: "" allowed
37
+ /**
38
+ * One concurrent sound layer in a scene. Real footage stacks sound (music bed
39
+ * under dialogue over ambient sfx), so a scene carries an ARRAY of these an
40
+ * empty array means genuine silence. `content`: speech = verbatim words;
41
+ * music/sfx = gen-ready description. `voice` is speech-only voice-casting.
42
+ */
43
+ const audioLayerSchema = z.object({
44
+ mode: z.enum(["speech", "music", "sfx"]),
45
+ content: z.string().min(1),
40
46
  voice: z.string().optional(),
41
47
  })
48
+ export type AudioLayer = z.infer<typeof audioLayerSchema>
42
49
 
43
50
  const windowSceneBase = z.object({
44
51
  startSec: z.number().min(0),
@@ -48,7 +55,8 @@ const windowSceneBase = z.object({
48
55
  camera: z.string(),
49
56
  visual: z.string().min(1),
50
57
  transitionOut: z.enum(["cut", "fade", "wipe", "whip"]).optional(),
51
- audio: audioSchema,
58
+ // Array of concurrent layers (music + speech + sfx together); [] = silence.
59
+ audio: z.array(audioLayerSchema),
52
60
  })
53
61
  // .strip() (default) drops model-emitted oversized/slotRefs — validator-computed only.
54
62
  const windowSceneSchema = windowSceneBase.refine((s) => s.endSec > s.startSec, { message: "endSec must be > startSec" })