@nodaro/shared 1.4.2

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 (665) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +32 -0
  3. package/dist/index.cjs +12506 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +12269 -0
  6. package/dist/index.d.ts +12269 -0
  7. package/dist/index.js +11831 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +54 -0
  10. package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
  11. package/src/__tests__/ai-avatar-pricing.test.ts +321 -0
  12. package/src/__tests__/apply-video-negative-prompt.test.ts +76 -0
  13. package/src/__tests__/attach-columns.test.ts +28 -0
  14. package/src/__tests__/audio-crossfade-curves.test.ts +33 -0
  15. package/src/__tests__/build-model-menu.test.ts +58 -0
  16. package/src/__tests__/character-aspect-defaults.test.ts +142 -0
  17. package/src/__tests__/character-mention-slug.test.ts +199 -0
  18. package/src/__tests__/character-reference-photo-kinds.test.ts +32 -0
  19. package/src/__tests__/character-usage-mode.test.ts +147 -0
  20. package/src/__tests__/character-variant-assets.test.ts +142 -0
  21. package/src/__tests__/character-voice.test.ts +130 -0
  22. package/src/__tests__/cinematic-avatar-pricing.test.ts +119 -0
  23. package/src/__tests__/combine-transitions.test.ts +137 -0
  24. package/src/__tests__/component-types.test.ts +87 -0
  25. package/src/__tests__/condition-variables.test.ts +98 -0
  26. package/src/__tests__/credit-identifiers.test.ts +811 -0
  27. package/src/__tests__/default-video-provider.test.ts +63 -0
  28. package/src/__tests__/entity-image-handle.test.ts +43 -0
  29. package/src/__tests__/entity-variants.test.ts +33 -0
  30. package/src/__tests__/fal-lip-sync-sets.test.ts +31 -0
  31. package/src/__tests__/featured-entities.test.ts +33 -0
  32. package/src/__tests__/film-pricing.test.ts +64 -0
  33. package/src/__tests__/filter-condition.test.ts +285 -0
  34. package/src/__tests__/freecut-protocol.test.ts +35 -0
  35. package/src/__tests__/generate-text-items.test.ts +19 -0
  36. package/src/__tests__/generated-results.test.ts +50 -0
  37. package/src/__tests__/graph-utils.test.ts +618 -0
  38. package/src/__tests__/group-aggregation.test.ts +83 -0
  39. package/src/__tests__/i18n-locale-completeness.test.ts +156 -0
  40. package/src/__tests__/image-critic-node.test.ts +86 -0
  41. package/src/__tests__/image-mask-mode.test.ts +16 -0
  42. package/src/__tests__/image-ref-limit.test.ts +78 -0
  43. package/src/__tests__/inpaint-region.test.ts +24 -0
  44. package/src/__tests__/input-field-map-parity.test.ts +30 -0
  45. package/src/__tests__/json-evaluator.test.ts +289 -0
  46. package/src/__tests__/json-path.test.ts +64 -0
  47. package/src/__tests__/lip-sync-pricing.test.ts +142 -0
  48. package/src/__tests__/list-merge.test.ts +96 -0
  49. package/src/__tests__/list-sort.test.ts +134 -0
  50. package/src/__tests__/llm-models.test.ts +445 -0
  51. package/src/__tests__/location-mention-slug.test.ts +246 -0
  52. package/src/__tests__/locations-coverage-critic-schema.test.ts +92 -0
  53. package/src/__tests__/loop-delimiter.test.ts +39 -0
  54. package/src/__tests__/lottie-slots.test.ts +245 -0
  55. package/src/__tests__/model-catalog-flux2-resolutions.test.ts +21 -0
  56. package/src/__tests__/model-constants-location.test.ts +20 -0
  57. package/src/__tests__/model-constants.test.ts +122 -0
  58. package/src/__tests__/model-tree.test.ts +86 -0
  59. package/src/__tests__/no-internal-imports.test.ts +25 -0
  60. package/src/__tests__/node-default-mappings.test.ts +175 -0
  61. package/src/__tests__/node-mappable-fields.test.ts +7 -0
  62. package/src/__tests__/node-preset-export.test.ts +46 -0
  63. package/src/__tests__/node-preset-extract.test.ts +166 -0
  64. package/src/__tests__/node-refs-canonical.test.ts +54 -0
  65. package/src/__tests__/node-refs-combine.test.ts +54 -0
  66. package/src/__tests__/node-refs.test.ts +187 -0
  67. package/src/__tests__/node-runtime-keys.test.ts +99 -0
  68. package/src/__tests__/object-aspect-defaults.test.ts +59 -0
  69. package/src/__tests__/parameter-node-value.test.ts +137 -0
  70. package/src/__tests__/pinterest-url.test.ts +35 -0
  71. package/src/__tests__/pipeline-chat.test.ts +110 -0
  72. package/src/__tests__/pipeline-validation.test.ts +98 -0
  73. package/src/__tests__/presentation-utils.test.ts +1137 -0
  74. package/src/__tests__/producer-types.test.ts +47 -0
  75. package/src/__tests__/prompt-length-limits.test.ts +156 -0
  76. package/src/__tests__/provider-directive-defaults.test.ts +46 -0
  77. package/src/__tests__/reduce-strategy-registry.test.ts +43 -0
  78. package/src/__tests__/reference-board-templates.test.ts +33 -0
  79. package/src/__tests__/reference-roles.test.ts +36 -0
  80. package/src/__tests__/resolve-field-mappings.test.ts +110 -0
  81. package/src/__tests__/resolve-pipeline-model.test.ts +76 -0
  82. package/src/__tests__/scene-node-types.test.ts +80 -0
  83. package/src/__tests__/scraper-actors.test.ts +67 -0
  84. package/src/__tests__/seedance-2-catalog.test.ts +18 -0
  85. package/src/__tests__/seedance-2-credit-id.test.ts +23 -0
  86. package/src/__tests__/seedance-aspects.test.ts +52 -0
  87. package/src/__tests__/selector.test.ts +1151 -0
  88. package/src/__tests__/settled-with-limit.test.ts +214 -0
  89. package/src/__tests__/social-media-specs.test.ts +129 -0
  90. package/src/__tests__/sub-workflow-validation.test.ts +88 -0
  91. package/src/__tests__/switchx-pricing.test.ts +28 -0
  92. package/src/__tests__/to-connected-references.test.ts +153 -0
  93. package/src/__tests__/utilities.test.ts +541 -0
  94. package/src/__tests__/video-analysis-pricing.test.ts +58 -0
  95. package/src/__tests__/video-analysis.test.ts +63 -0
  96. package/src/__tests__/video-audio-capability.test.ts +204 -0
  97. package/src/__tests__/video-gen-providers.test.ts +28 -0
  98. package/src/__tests__/video-mode-aliases.test.ts +150 -0
  99. package/src/__tests__/video-ref-limits.test.ts +72 -0
  100. package/src/__tests__/video-utils.test.ts +303 -0
  101. package/src/__tests__/voice-changer-models.test.ts +33 -0
  102. package/src/__tests__/workflow-export-strip.test.ts +46 -0
  103. package/src/ai-avatar-pricing.ts +213 -0
  104. package/src/ancestor-refs.ts +48 -0
  105. package/src/animals.ts +231 -0
  106. package/src/audio-crossfade-curves.ts +73 -0
  107. package/src/audio-fx-presets.ts +64 -0
  108. package/src/avatar-payload-validators.ts +214 -0
  109. package/src/caption-styles.ts +31 -0
  110. package/src/character-aspect-defaults.ts +102 -0
  111. package/src/character-facets.ts +37 -0
  112. package/src/character-mention-slug.ts +166 -0
  113. package/src/character-usage-mode.ts +109 -0
  114. package/src/character-variant-assets.ts +121 -0
  115. package/src/character-voice.ts +151 -0
  116. package/src/cinematic-avatar-pricing.ts +111 -0
  117. package/src/clone-utils.ts +46 -0
  118. package/src/combine-transitions.ts +482 -0
  119. package/src/community.ts +112 -0
  120. package/src/component-types.ts +127 -0
  121. package/src/condition-variables.ts +65 -0
  122. package/src/credit-estimators/index.ts +15 -0
  123. package/src/credit-estimators/video-utils.ts +165 -0
  124. package/src/credit-identifiers.ts +304 -0
  125. package/src/entity-approval-types.ts +31 -0
  126. package/src/entity-aspect-defaults.ts +82 -0
  127. package/src/entity-asset-types.ts +296 -0
  128. package/src/entity-image-handle.ts +36 -0
  129. package/src/extra-refs.ts +139 -0
  130. package/src/featured-entities.ts +136 -0
  131. package/src/film-pricing.ts +117 -0
  132. package/src/filter-condition.ts +250 -0
  133. package/src/flux2-pricing.ts +18 -0
  134. package/src/freecut-protocol.ts +52 -0
  135. package/src/furniture.ts +167 -0
  136. package/src/generate-text-items.ts +15 -0
  137. package/src/generated-results.ts +63 -0
  138. package/src/group-aggregation.ts +75 -0
  139. package/src/hint-graph-types.ts +18 -0
  140. package/src/i18n/action-fx.ar.ts +89 -0
  141. package/src/i18n/action-fx.de.ts +89 -0
  142. package/src/i18n/action-fx.es.ts +89 -0
  143. package/src/i18n/action-fx.fr.ts +89 -0
  144. package/src/i18n/action-fx.he.ts +89 -0
  145. package/src/i18n/action-fx.hi.ts +89 -0
  146. package/src/i18n/action-fx.ja.ts +89 -0
  147. package/src/i18n/action-fx.ko.ts +89 -0
  148. package/src/i18n/action-fx.pt-BR.ts +89 -0
  149. package/src/i18n/action-fx.ru.ts +89 -0
  150. package/src/i18n/action-fx.zh-CN.ts +89 -0
  151. package/src/i18n/aesthetic.ar.ts +170 -0
  152. package/src/i18n/aesthetic.de.ts +48 -0
  153. package/src/i18n/aesthetic.es.ts +169 -0
  154. package/src/i18n/aesthetic.fr.ts +52 -0
  155. package/src/i18n/aesthetic.he.ts +169 -0
  156. package/src/i18n/aesthetic.hi.ts +55 -0
  157. package/src/i18n/aesthetic.ja.ts +165 -0
  158. package/src/i18n/aesthetic.ko.ts +169 -0
  159. package/src/i18n/aesthetic.pt-BR.ts +148 -0
  160. package/src/i18n/aesthetic.ru.ts +155 -0
  161. package/src/i18n/aesthetic.zh-CN.ts +172 -0
  162. package/src/i18n/animals.ar.ts +145 -0
  163. package/src/i18n/animals.de.ts +144 -0
  164. package/src/i18n/animals.es.ts +158 -0
  165. package/src/i18n/animals.fr.ts +144 -0
  166. package/src/i18n/animals.he.ts +155 -0
  167. package/src/i18n/animals.hi.ts +157 -0
  168. package/src/i18n/animals.ja.ts +159 -0
  169. package/src/i18n/animals.ko.ts +159 -0
  170. package/src/i18n/animals.pt-BR.ts +157 -0
  171. package/src/i18n/animals.ru.ts +155 -0
  172. package/src/i18n/animals.zh-CN.ts +155 -0
  173. package/src/i18n/atmosphere.ar.ts +49 -0
  174. package/src/i18n/atmosphere.de.ts +47 -0
  175. package/src/i18n/atmosphere.es.ts +50 -0
  176. package/src/i18n/atmosphere.fr.ts +47 -0
  177. package/src/i18n/atmosphere.he.ts +47 -0
  178. package/src/i18n/atmosphere.hi.ts +49 -0
  179. package/src/i18n/atmosphere.ja.ts +49 -0
  180. package/src/i18n/atmosphere.ko.ts +49 -0
  181. package/src/i18n/atmosphere.pt-BR.ts +49 -0
  182. package/src/i18n/atmosphere.ru.ts +47 -0
  183. package/src/i18n/atmosphere.zh-CN.ts +152 -0
  184. package/src/i18n/backdrop.ar.ts +53 -0
  185. package/src/i18n/backdrop.de.ts +46 -0
  186. package/src/i18n/backdrop.es.ts +54 -0
  187. package/src/i18n/backdrop.fr.ts +52 -0
  188. package/src/i18n/backdrop.he.ts +51 -0
  189. package/src/i18n/backdrop.hi.ts +59 -0
  190. package/src/i18n/backdrop.ja.ts +61 -0
  191. package/src/i18n/backdrop.ko.ts +59 -0
  192. package/src/i18n/backdrop.pt-BR.ts +59 -0
  193. package/src/i18n/backdrop.ru.ts +57 -0
  194. package/src/i18n/backdrop.zh-CN.ts +57 -0
  195. package/src/i18n/camera-format.ar.ts +40 -0
  196. package/src/i18n/camera-format.de.ts +37 -0
  197. package/src/i18n/camera-format.es.ts +41 -0
  198. package/src/i18n/camera-format.fr.ts +37 -0
  199. package/src/i18n/camera-format.he.ts +37 -0
  200. package/src/i18n/camera-format.hi.ts +42 -0
  201. package/src/i18n/camera-format.ja.ts +37 -0
  202. package/src/i18n/camera-format.ko.ts +37 -0
  203. package/src/i18n/camera-format.pt-BR.ts +46 -0
  204. package/src/i18n/camera-format.ru.ts +42 -0
  205. package/src/i18n/camera-format.zh-CN.ts +42 -0
  206. package/src/i18n/camera-motions.ar.ts +86 -0
  207. package/src/i18n/camera-motions.de.ts +74 -0
  208. package/src/i18n/camera-motions.es.ts +86 -0
  209. package/src/i18n/camera-motions.fr.ts +86 -0
  210. package/src/i18n/camera-motions.he.ts +86 -0
  211. package/src/i18n/camera-motions.hi.ts +99 -0
  212. package/src/i18n/camera-motions.ja.ts +99 -0
  213. package/src/i18n/camera-motions.ko.ts +99 -0
  214. package/src/i18n/camera-motions.pt-BR.ts +99 -0
  215. package/src/i18n/camera-motions.ru.ts +99 -0
  216. package/src/i18n/camera-motions.zh-CN.ts +99 -0
  217. package/src/i18n/character-fx.ar.ts +72 -0
  218. package/src/i18n/character-fx.de.ts +72 -0
  219. package/src/i18n/character-fx.es.ts +72 -0
  220. package/src/i18n/character-fx.fr.ts +72 -0
  221. package/src/i18n/character-fx.he.ts +72 -0
  222. package/src/i18n/character-fx.hi.ts +72 -0
  223. package/src/i18n/character-fx.ja.ts +72 -0
  224. package/src/i18n/character-fx.ko.ts +72 -0
  225. package/src/i18n/character-fx.pt-BR.ts +72 -0
  226. package/src/i18n/character-fx.ru.ts +72 -0
  227. package/src/i18n/character-fx.zh-CN.ts +72 -0
  228. package/src/i18n/color-look.ar.ts +50 -0
  229. package/src/i18n/color-look.de.ts +47 -0
  230. package/src/i18n/color-look.es.ts +50 -0
  231. package/src/i18n/color-look.fr.ts +50 -0
  232. package/src/i18n/color-look.he.ts +49 -0
  233. package/src/i18n/color-look.hi.ts +52 -0
  234. package/src/i18n/color-look.ja.ts +54 -0
  235. package/src/i18n/color-look.ko.ts +54 -0
  236. package/src/i18n/color-look.pt-BR.ts +54 -0
  237. package/src/i18n/color-look.ru.ts +52 -0
  238. package/src/i18n/color-look.zh-CN.ts +53 -0
  239. package/src/i18n/composition-effects.ar.ts +26 -0
  240. package/src/i18n/composition-effects.de.ts +25 -0
  241. package/src/i18n/composition-effects.es.ts +27 -0
  242. package/src/i18n/composition-effects.fr.ts +25 -0
  243. package/src/i18n/composition-effects.he.ts +25 -0
  244. package/src/i18n/composition-effects.hi.ts +27 -0
  245. package/src/i18n/composition-effects.ja.ts +27 -0
  246. package/src/i18n/composition-effects.ko.ts +27 -0
  247. package/src/i18n/composition-effects.pt-BR.ts +25 -0
  248. package/src/i18n/composition-effects.ru.ts +82 -0
  249. package/src/i18n/composition-effects.zh-CN.ts +25 -0
  250. package/src/i18n/era.ar.ts +37 -0
  251. package/src/i18n/era.de.ts +34 -0
  252. package/src/i18n/era.es.ts +37 -0
  253. package/src/i18n/era.fr.ts +37 -0
  254. package/src/i18n/era.he.ts +36 -0
  255. package/src/i18n/era.hi.ts +39 -0
  256. package/src/i18n/era.ja.ts +41 -0
  257. package/src/i18n/era.ko.ts +39 -0
  258. package/src/i18n/era.pt-BR.ts +41 -0
  259. package/src/i18n/era.ru.ts +121 -0
  260. package/src/i18n/era.zh-CN.ts +39 -0
  261. package/src/i18n/exposure-settings.ar.ts +28 -0
  262. package/src/i18n/exposure-settings.de.ts +26 -0
  263. package/src/i18n/exposure-settings.es.ts +28 -0
  264. package/src/i18n/exposure-settings.fr.ts +29 -0
  265. package/src/i18n/exposure-settings.he.ts +28 -0
  266. package/src/i18n/exposure-settings.hi.ts +31 -0
  267. package/src/i18n/exposure-settings.ja.ts +31 -0
  268. package/src/i18n/exposure-settings.ko.ts +31 -0
  269. package/src/i18n/exposure-settings.pt-BR.ts +31 -0
  270. package/src/i18n/exposure-settings.ru.ts +31 -0
  271. package/src/i18n/exposure-settings.zh-CN.ts +31 -0
  272. package/src/i18n/framing.ar.ts +78 -0
  273. package/src/i18n/framing.de.ts +73 -0
  274. package/src/i18n/framing.es.ts +78 -0
  275. package/src/i18n/framing.fr.ts +78 -0
  276. package/src/i18n/framing.he.ts +77 -0
  277. package/src/i18n/framing.hi.ts +82 -0
  278. package/src/i18n/framing.ja.ts +84 -0
  279. package/src/i18n/framing.ko.ts +82 -0
  280. package/src/i18n/framing.pt-BR.ts +84 -0
  281. package/src/i18n/framing.ru.ts +82 -0
  282. package/src/i18n/framing.zh-CN.ts +82 -0
  283. package/src/i18n/furniture.ar.ts +92 -0
  284. package/src/i18n/furniture.de.ts +93 -0
  285. package/src/i18n/furniture.es.ts +101 -0
  286. package/src/i18n/furniture.fr.ts +93 -0
  287. package/src/i18n/furniture.he.ts +101 -0
  288. package/src/i18n/furniture.hi.ts +101 -0
  289. package/src/i18n/furniture.ja.ts +101 -0
  290. package/src/i18n/furniture.ko.ts +101 -0
  291. package/src/i18n/furniture.pt-BR.ts +101 -0
  292. package/src/i18n/furniture.ru.ts +101 -0
  293. package/src/i18n/furniture.zh-CN.ts +101 -0
  294. package/src/i18n/held-prop.ar.ts +74 -0
  295. package/src/i18n/held-prop.de.ts +65 -0
  296. package/src/i18n/held-prop.es.ts +83 -0
  297. package/src/i18n/held-prop.fr.ts +74 -0
  298. package/src/i18n/held-prop.he.ts +73 -0
  299. package/src/i18n/held-prop.hi.ts +82 -0
  300. package/src/i18n/held-prop.ja.ts +84 -0
  301. package/src/i18n/held-prop.ko.ts +84 -0
  302. package/src/i18n/held-prop.pt-BR.ts +84 -0
  303. package/src/i18n/held-prop.ru.ts +82 -0
  304. package/src/i18n/held-prop.zh-CN.ts +82 -0
  305. package/src/i18n/index.ts +208 -0
  306. package/src/i18n/instrumentation.ar.ts +195 -0
  307. package/src/i18n/instrumentation.de.ts +195 -0
  308. package/src/i18n/instrumentation.es.ts +195 -0
  309. package/src/i18n/instrumentation.fr.ts +195 -0
  310. package/src/i18n/instrumentation.he.ts +195 -0
  311. package/src/i18n/instrumentation.hi.ts +195 -0
  312. package/src/i18n/instrumentation.ja.ts +195 -0
  313. package/src/i18n/instrumentation.ko.ts +195 -0
  314. package/src/i18n/instrumentation.pt-BR.ts +195 -0
  315. package/src/i18n/instrumentation.ru.ts +195 -0
  316. package/src/i18n/instrumentation.zh-CN.ts +195 -0
  317. package/src/i18n/lens.ar.ts +24 -0
  318. package/src/i18n/lens.de.ts +24 -0
  319. package/src/i18n/lens.es.ts +24 -0
  320. package/src/i18n/lens.fr.ts +24 -0
  321. package/src/i18n/lens.he.ts +24 -0
  322. package/src/i18n/lens.hi.ts +24 -0
  323. package/src/i18n/lens.ja.ts +24 -0
  324. package/src/i18n/lens.ko.ts +24 -0
  325. package/src/i18n/lens.pt-BR.ts +24 -0
  326. package/src/i18n/lens.ru.ts +25 -0
  327. package/src/i18n/lens.zh-CN.ts +24 -0
  328. package/src/i18n/lighting.ar.ts +86 -0
  329. package/src/i18n/lighting.de.ts +84 -0
  330. package/src/i18n/lighting.es.ts +89 -0
  331. package/src/i18n/lighting.fr.ts +84 -0
  332. package/src/i18n/lighting.he.ts +88 -0
  333. package/src/i18n/lighting.hi.ts +90 -0
  334. package/src/i18n/lighting.ja.ts +90 -0
  335. package/src/i18n/lighting.ko.ts +90 -0
  336. package/src/i18n/lighting.pt-BR.ts +90 -0
  337. package/src/i18n/lighting.ru.ts +88 -0
  338. package/src/i18n/lighting.zh-CN.ts +92 -0
  339. package/src/i18n/loop-subject.ar.ts +39 -0
  340. package/src/i18n/loop-subject.de.ts +39 -0
  341. package/src/i18n/loop-subject.es.ts +39 -0
  342. package/src/i18n/loop-subject.fr.ts +39 -0
  343. package/src/i18n/loop-subject.he.ts +39 -0
  344. package/src/i18n/loop-subject.hi.ts +39 -0
  345. package/src/i18n/loop-subject.ja.ts +39 -0
  346. package/src/i18n/loop-subject.ko.ts +39 -0
  347. package/src/i18n/loop-subject.pt-BR.ts +39 -0
  348. package/src/i18n/loop-subject.ru.ts +39 -0
  349. package/src/i18n/loop-subject.zh-CN.ts +39 -0
  350. package/src/i18n/materials.ar.ts +80 -0
  351. package/src/i18n/materials.de.ts +80 -0
  352. package/src/i18n/materials.es.ts +87 -0
  353. package/src/i18n/materials.fr.ts +80 -0
  354. package/src/i18n/materials.he.ts +86 -0
  355. package/src/i18n/materials.hi.ts +86 -0
  356. package/src/i18n/materials.ja.ts +88 -0
  357. package/src/i18n/materials.ko.ts +88 -0
  358. package/src/i18n/materials.pt-BR.ts +88 -0
  359. package/src/i18n/materials.ru.ts +86 -0
  360. package/src/i18n/materials.zh-CN.ts +86 -0
  361. package/src/i18n/mood.ar.ts +61 -0
  362. package/src/i18n/mood.de.ts +61 -0
  363. package/src/i18n/mood.es.ts +66 -0
  364. package/src/i18n/mood.fr.ts +61 -0
  365. package/src/i18n/mood.he.ts +64 -0
  366. package/src/i18n/mood.hi.ts +66 -0
  367. package/src/i18n/mood.ja.ts +66 -0
  368. package/src/i18n/mood.ko.ts +66 -0
  369. package/src/i18n/mood.pt-BR.ts +64 -0
  370. package/src/i18n/mood.ru.ts +64 -0
  371. package/src/i18n/mood.zh-CN.ts +64 -0
  372. package/src/i18n/music-genre.ar.ts +302 -0
  373. package/src/i18n/music-genre.de.ts +302 -0
  374. package/src/i18n/music-genre.es.ts +302 -0
  375. package/src/i18n/music-genre.fr.ts +302 -0
  376. package/src/i18n/music-genre.he.ts +302 -0
  377. package/src/i18n/music-genre.hi.ts +302 -0
  378. package/src/i18n/music-genre.ja.ts +302 -0
  379. package/src/i18n/music-genre.ko.ts +302 -0
  380. package/src/i18n/music-genre.pt-BR.ts +302 -0
  381. package/src/i18n/music-genre.ru.ts +302 -0
  382. package/src/i18n/music-genre.zh-CN.ts +302 -0
  383. package/src/i18n/music-mood.ar.ts +75 -0
  384. package/src/i18n/music-mood.de.ts +75 -0
  385. package/src/i18n/music-mood.es.ts +75 -0
  386. package/src/i18n/music-mood.fr.ts +75 -0
  387. package/src/i18n/music-mood.he.ts +75 -0
  388. package/src/i18n/music-mood.hi.ts +75 -0
  389. package/src/i18n/music-mood.ja.ts +75 -0
  390. package/src/i18n/music-mood.ko.ts +75 -0
  391. package/src/i18n/music-mood.pt-BR.ts +75 -0
  392. package/src/i18n/music-mood.ru.ts +75 -0
  393. package/src/i18n/music-mood.zh-CN.ts +75 -0
  394. package/src/i18n/person.ar.ts +638 -0
  395. package/src/i18n/person.de.ts +629 -0
  396. package/src/i18n/person.es.ts +645 -0
  397. package/src/i18n/person.fr.ts +621 -0
  398. package/src/i18n/person.he.ts +656 -0
  399. package/src/i18n/person.hi.ts +654 -0
  400. package/src/i18n/person.ja.ts +662 -0
  401. package/src/i18n/person.ko.ts +662 -0
  402. package/src/i18n/person.pt-BR.ts +656 -0
  403. package/src/i18n/person.ru.ts +656 -0
  404. package/src/i18n/person.zh-CN.ts +656 -0
  405. package/src/i18n/photo-genre.ar.ts +58 -0
  406. package/src/i18n/photo-genre.de.ts +52 -0
  407. package/src/i18n/photo-genre.es.ts +64 -0
  408. package/src/i18n/photo-genre.fr.ts +58 -0
  409. package/src/i18n/photo-genre.he.ts +62 -0
  410. package/src/i18n/photo-genre.hi.ts +63 -0
  411. package/src/i18n/photo-genre.ja.ts +65 -0
  412. package/src/i18n/photo-genre.ko.ts +63 -0
  413. package/src/i18n/photo-genre.pt-BR.ts +65 -0
  414. package/src/i18n/photo-genre.ru.ts +63 -0
  415. package/src/i18n/photo-genre.zh-CN.ts +63 -0
  416. package/src/i18n/photographer.ar.ts +75 -0
  417. package/src/i18n/photographer.de.ts +74 -0
  418. package/src/i18n/photographer.es.ts +77 -0
  419. package/src/i18n/photographer.fr.ts +77 -0
  420. package/src/i18n/photographer.he.ts +78 -0
  421. package/src/i18n/photographer.hi.ts +80 -0
  422. package/src/i18n/photographer.ja.ts +84 -0
  423. package/src/i18n/photographer.ko.ts +84 -0
  424. package/src/i18n/photographer.pt-BR.ts +83 -0
  425. package/src/i18n/photographer.ru.ts +78 -0
  426. package/src/i18n/photographer.zh-CN.ts +78 -0
  427. package/src/i18n/pose.ar.ts +95 -0
  428. package/src/i18n/pose.de.ts +96 -0
  429. package/src/i18n/pose.es.ts +104 -0
  430. package/src/i18n/pose.fr.ts +96 -0
  431. package/src/i18n/pose.he.ts +104 -0
  432. package/src/i18n/pose.hi.ts +104 -0
  433. package/src/i18n/pose.ja.ts +104 -0
  434. package/src/i18n/pose.ko.ts +104 -0
  435. package/src/i18n/pose.pt-BR.ts +104 -0
  436. package/src/i18n/pose.ru.ts +104 -0
  437. package/src/i18n/pose.zh-CN.ts +104 -0
  438. package/src/i18n/post-process-effects.ar.ts +25 -0
  439. package/src/i18n/post-process-effects.de.ts +24 -0
  440. package/src/i18n/post-process-effects.es.ts +26 -0
  441. package/src/i18n/post-process-effects.fr.ts +24 -0
  442. package/src/i18n/post-process-effects.he.ts +24 -0
  443. package/src/i18n/post-process-effects.hi.ts +26 -0
  444. package/src/i18n/post-process-effects.ja.ts +26 -0
  445. package/src/i18n/post-process-effects.ko.ts +26 -0
  446. package/src/i18n/post-process-effects.pt-BR.ts +24 -0
  447. package/src/i18n/post-process-effects.ru.ts +24 -0
  448. package/src/i18n/post-process-effects.zh-CN.ts +24 -0
  449. package/src/i18n/render-quality.ar.ts +34 -0
  450. package/src/i18n/render-quality.de.ts +30 -0
  451. package/src/i18n/render-quality.es.ts +35 -0
  452. package/src/i18n/render-quality.fr.ts +34 -0
  453. package/src/i18n/render-quality.he.ts +33 -0
  454. package/src/i18n/render-quality.hi.ts +39 -0
  455. package/src/i18n/render-quality.ja.ts +39 -0
  456. package/src/i18n/render-quality.ko.ts +39 -0
  457. package/src/i18n/render-quality.pt-BR.ts +37 -0
  458. package/src/i18n/render-quality.ru.ts +37 -0
  459. package/src/i18n/render-quality.zh-CN.ts +37 -0
  460. package/src/i18n/seasons.ar.ts +10 -0
  461. package/src/i18n/seasons.de.ts +10 -0
  462. package/src/i18n/seasons.es.ts +10 -0
  463. package/src/i18n/seasons.fr.ts +10 -0
  464. package/src/i18n/seasons.he.ts +10 -0
  465. package/src/i18n/seasons.hi.ts +10 -0
  466. package/src/i18n/seasons.ja.ts +10 -0
  467. package/src/i18n/seasons.ko.ts +10 -0
  468. package/src/i18n/seasons.pt-BR.ts +10 -0
  469. package/src/i18n/seasons.ru.ts +10 -0
  470. package/src/i18n/seasons.zh-CN.ts +10 -0
  471. package/src/i18n/setting.ar.ts +73 -0
  472. package/src/i18n/setting.de.ts +73 -0
  473. package/src/i18n/setting.es.ts +77 -0
  474. package/src/i18n/setting.fr.ts +73 -0
  475. package/src/i18n/setting.he.ts +76 -0
  476. package/src/i18n/setting.hi.ts +76 -0
  477. package/src/i18n/setting.ja.ts +78 -0
  478. package/src/i18n/setting.ko.ts +76 -0
  479. package/src/i18n/setting.pt-BR.ts +78 -0
  480. package/src/i18n/setting.ru.ts +76 -0
  481. package/src/i18n/setting.zh-CN.ts +76 -0
  482. package/src/i18n/style.ar.ts +55 -0
  483. package/src/i18n/style.de.ts +54 -0
  484. package/src/i18n/style.es.ts +54 -0
  485. package/src/i18n/style.fr.ts +54 -0
  486. package/src/i18n/style.he.ts +54 -0
  487. package/src/i18n/style.hi.ts +54 -0
  488. package/src/i18n/style.ja.ts +54 -0
  489. package/src/i18n/style.ko.ts +54 -0
  490. package/src/i18n/style.pt-BR.ts +56 -0
  491. package/src/i18n/style.ru.ts +54 -0
  492. package/src/i18n/style.zh-CN.ts +54 -0
  493. package/src/i18n/styling.ar.ts +295 -0
  494. package/src/i18n/styling.de.ts +285 -0
  495. package/src/i18n/styling.es.ts +317 -0
  496. package/src/i18n/styling.fr.ts +285 -0
  497. package/src/i18n/styling.he.ts +307 -0
  498. package/src/i18n/styling.hi.ts +323 -0
  499. package/src/i18n/styling.ja.ts +317 -0
  500. package/src/i18n/styling.ko.ts +311 -0
  501. package/src/i18n/styling.pt-BR.ts +301 -0
  502. package/src/i18n/styling.ru.ts +301 -0
  503. package/src/i18n/styling.zh-CN.ts +307 -0
  504. package/src/i18n/temporal.ar.ts +31 -0
  505. package/src/i18n/temporal.de.ts +24 -0
  506. package/src/i18n/temporal.es.ts +27 -0
  507. package/src/i18n/temporal.fr.ts +28 -0
  508. package/src/i18n/temporal.he.ts +31 -0
  509. package/src/i18n/temporal.hi.ts +31 -0
  510. package/src/i18n/temporal.ja.ts +31 -0
  511. package/src/i18n/temporal.ko.ts +31 -0
  512. package/src/i18n/temporal.pt-BR.ts +31 -0
  513. package/src/i18n/temporal.ru.ts +31 -0
  514. package/src/i18n/temporal.zh-CN.ts +31 -0
  515. package/src/i18n/transitions.ar.ts +97 -0
  516. package/src/i18n/transitions.de.ts +97 -0
  517. package/src/i18n/transitions.es.ts +97 -0
  518. package/src/i18n/transitions.fr.ts +97 -0
  519. package/src/i18n/transitions.he.ts +97 -0
  520. package/src/i18n/transitions.hi.ts +97 -0
  521. package/src/i18n/transitions.ja.ts +97 -0
  522. package/src/i18n/transitions.ko.ts +97 -0
  523. package/src/i18n/transitions.pt-BR.ts +97 -0
  524. package/src/i18n/transitions.ru.ts +97 -0
  525. package/src/i18n/transitions.zh-CN.ts +97 -0
  526. package/src/i18n/types.ts +158 -0
  527. package/src/i18n/vehicles.ar.ts +137 -0
  528. package/src/i18n/vehicles.de.ts +125 -0
  529. package/src/i18n/vehicles.es.ts +138 -0
  530. package/src/i18n/vehicles.fr.ts +125 -0
  531. package/src/i18n/vehicles.he.ts +136 -0
  532. package/src/i18n/vehicles.hi.ts +138 -0
  533. package/src/i18n/vehicles.ja.ts +138 -0
  534. package/src/i18n/vehicles.ko.ts +138 -0
  535. package/src/i18n/vehicles.pt-BR.ts +136 -0
  536. package/src/i18n/vehicles.ru.ts +136 -0
  537. package/src/i18n/vehicles.zh-CN.ts +136 -0
  538. package/src/i18n/voice-character.ar.ts +126 -0
  539. package/src/i18n/voice-character.de.ts +126 -0
  540. package/src/i18n/voice-character.es.ts +126 -0
  541. package/src/i18n/voice-character.fr.ts +126 -0
  542. package/src/i18n/voice-character.he.ts +126 -0
  543. package/src/i18n/voice-character.hi.ts +126 -0
  544. package/src/i18n/voice-character.ja.ts +126 -0
  545. package/src/i18n/voice-character.ko.ts +126 -0
  546. package/src/i18n/voice-character.pt-BR.ts +126 -0
  547. package/src/i18n/voice-character.ru.ts +126 -0
  548. package/src/i18n/voice-character.zh-CN.ts +126 -0
  549. package/src/i18n/voice-delivery.ar.ts +77 -0
  550. package/src/i18n/voice-delivery.de.ts +77 -0
  551. package/src/i18n/voice-delivery.es.ts +77 -0
  552. package/src/i18n/voice-delivery.fr.ts +77 -0
  553. package/src/i18n/voice-delivery.he.ts +77 -0
  554. package/src/i18n/voice-delivery.hi.ts +77 -0
  555. package/src/i18n/voice-delivery.ja.ts +77 -0
  556. package/src/i18n/voice-delivery.ko.ts +77 -0
  557. package/src/i18n/voice-delivery.pt-BR.ts +77 -0
  558. package/src/i18n/voice-delivery.ru.ts +77 -0
  559. package/src/i18n/voice-delivery.zh-CN.ts +77 -0
  560. package/src/i18n/weapons.ar.ts +115 -0
  561. package/src/i18n/weapons.de.ts +114 -0
  562. package/src/i18n/weapons.es.ts +116 -0
  563. package/src/i18n/weapons.fr.ts +103 -0
  564. package/src/i18n/weapons.he.ts +114 -0
  565. package/src/i18n/weapons.hi.ts +116 -0
  566. package/src/i18n/weapons.ja.ts +116 -0
  567. package/src/i18n/weapons.ko.ts +116 -0
  568. package/src/i18n/weapons.pt-BR.ts +114 -0
  569. package/src/i18n/weapons.ru.ts +114 -0
  570. package/src/i18n/weapons.zh-CN.ts +114 -0
  571. package/src/image-critic-node.ts +61 -0
  572. package/src/image-critic-types.ts +40 -0
  573. package/src/index.ts +866 -0
  574. package/src/inject-upstream.ts +15 -0
  575. package/src/inpaint-region.ts +51 -0
  576. package/src/json-evaluator.ts +732 -0
  577. package/src/json-path.ts +52 -0
  578. package/src/lip-sync-pricing.ts +90 -0
  579. package/src/list-merge.ts +40 -0
  580. package/src/list-sort.ts +122 -0
  581. package/src/list-source-resolver.ts +50 -0
  582. package/src/llm-models.ts +245 -0
  583. package/src/location-mention-slug.ts +291 -0
  584. package/src/location-preset-catalog-map.ts +128 -0
  585. package/src/loop-delimiter.ts +73 -0
  586. package/src/lora-routing.ts +95 -0
  587. package/src/lottie-overlay-catalog.ts +175 -0
  588. package/src/lottie-slots.ts +309 -0
  589. package/src/model-catalog.ts +2386 -0
  590. package/src/model-constants.ts +1910 -0
  591. package/src/model-tree.ts +120 -0
  592. package/src/monetization.ts +15 -0
  593. package/src/multi-pick.ts +42 -0
  594. package/src/node-default-mappings.ts +262 -0
  595. package/src/node-mappable-fields.ts +70 -0
  596. package/src/node-preset-export.ts +56 -0
  597. package/src/node-preset-extract.ts +147 -0
  598. package/src/node-refs.ts +253 -0
  599. package/src/node-runtime-keys.ts +117 -0
  600. package/src/object-aspect-defaults.ts +72 -0
  601. package/src/object-picker-types.ts +22 -0
  602. package/src/parameter-node-value.ts +284 -0
  603. package/src/pinterest-url.ts +28 -0
  604. package/src/pipeline-chat.ts +72 -0
  605. package/src/pipeline-defaults.ts +318 -0
  606. package/src/pipeline-events.ts +162 -0
  607. package/src/pipeline-state-types.ts +196 -0
  608. package/src/pipeline-types.ts +647 -0
  609. package/src/pipeline-validation.ts +87 -0
  610. package/src/presentation-types.ts +23 -0
  611. package/src/presentation-utils.ts +397 -0
  612. package/src/producer-types.ts +188 -0
  613. package/src/progress-curve.ts +99 -0
  614. package/src/provider-directive-defaults.ts +69 -0
  615. package/src/reduce-strategy-registry.ts +121 -0
  616. package/src/reference-board-templates.ts +81 -0
  617. package/src/reference-roles.ts +153 -0
  618. package/src/reference-sheet/__tests__/board-to-column.test.ts +20 -0
  619. package/src/reference-sheet/__tests__/catalog.test.ts +50 -0
  620. package/src/reference-sheet/__tests__/cost.test.ts +38 -0
  621. package/src/reference-sheet/__tests__/no-drift.test.ts +28 -0
  622. package/src/reference-sheet/__tests__/panel-plan.test.ts +61 -0
  623. package/src/reference-sheet/__tests__/panel-prompts.test.ts +17 -0
  624. package/src/reference-sheet/__tests__/plan-generation.test.ts +72 -0
  625. package/src/reference-sheet/__tests__/presets.test.ts +54 -0
  626. package/src/reference-sheet/__tests__/types.test.ts +24 -0
  627. package/src/reference-sheet/catalog.ts +144 -0
  628. package/src/reference-sheet/cost.ts +37 -0
  629. package/src/reference-sheet/credit-id.ts +7 -0
  630. package/src/reference-sheet/index.ts +8 -0
  631. package/src/reference-sheet/panel-plan.ts +65 -0
  632. package/src/reference-sheet/panel-prompts.ts +14 -0
  633. package/src/reference-sheet/plan-generation.ts +79 -0
  634. package/src/reference-sheet/presets.ts +77 -0
  635. package/src/reference-sheet/types.ts +92 -0
  636. package/src/repeat-types.ts +97 -0
  637. package/src/resolve-field-mappings.ts +119 -0
  638. package/src/route-filter.ts +80 -0
  639. package/src/scene-helper-types.ts +249 -0
  640. package/src/scene-node-types.ts +281 -0
  641. package/src/scraper-actors.ts +57 -0
  642. package/src/scraper-output-schemas.ts +25 -0
  643. package/src/seasons.ts +45 -0
  644. package/src/selector.ts +864 -0
  645. package/src/settled-with-limit.ts +42 -0
  646. package/src/shot-element.ts +43 -0
  647. package/src/social-media-specs.ts +121 -0
  648. package/src/social-post.ts +24 -0
  649. package/src/sub-workflow-validation.ts +78 -0
  650. package/src/supported-fonts.ts +40 -0
  651. package/src/surround.ts +113 -0
  652. package/src/switchx-pricing.ts +33 -0
  653. package/src/text-separators.ts +59 -0
  654. package/src/to-connected-references.ts +77 -0
  655. package/src/types.ts +272 -0
  656. package/src/variant-job-id.ts +17 -0
  657. package/src/vehicles.ts +213 -0
  658. package/src/video-analysis-pricing.ts +74 -0
  659. package/src/video-analysis.ts +127 -0
  660. package/src/video-duration.ts +25 -0
  661. package/src/voice-changer-models.ts +36 -0
  662. package/src/voice-matcher-types.ts +37 -0
  663. package/src/voices.ts +92 -0
  664. package/src/weapons.ts +190 -0
  665. package/src/workflow-export.ts +153 -0
@@ -0,0 +1,204 @@
1
+ import { describe, it, expect } from "vitest"
2
+ import {
3
+ VIDEO_AUDIO_CAPABILITY,
4
+ getVideoAudioCapability,
5
+ videoModelSupportsAudio,
6
+ videoModelCanSpeakDialogue,
7
+ applyVideoAudioToggle,
8
+ AUDIO_ADDON_PROVIDERS,
9
+ VEO_PROVIDERS,
10
+ SEEDANCE_2_PROVIDERS,
11
+ isSeedance2Provider,
12
+ VIDEO_REF_LIMITS_BY_PROVIDER,
13
+ SEEDANCE_2_REF_LIMITS,
14
+ } from "../model-constants.js"
15
+
16
+ describe("getVideoAudioCapability", () => {
17
+ it("returns native_speech (always on) for the VEO family", () => {
18
+ for (const m of ["veo3", "veo3.1", "veo3_lite"]) {
19
+ const cap = getVideoAudioCapability(m)
20
+ expect(cap.mode, m).toBe("native_speech")
21
+ expect(cap.alwaysOn, m).toBe(true)
22
+ }
23
+ })
24
+
25
+ it("returns ambient (sound toggle, cost-affecting) for Kling", () => {
26
+ for (const m of ["kling", "kling-3.0"]) {
27
+ const cap = getVideoAudioCapability(m)
28
+ expect(cap.mode, m).toBe("ambient")
29
+ expect(cap.field, m).toBe("sound")
30
+ expect(cap.affectsCost, m).toBe(true)
31
+ }
32
+ })
33
+
34
+ it("returns audio_driven for Seedance 2.0", () => {
35
+ for (const m of ["seedance-2", "seedance-2-fast"]) {
36
+ const cap = getVideoAudioCapability(m)
37
+ expect(cap.mode, m).toBe("audio_driven")
38
+ expect(cap.field, m).toBe("generateAudio")
39
+ }
40
+ })
41
+
42
+ it("returns ambient (audio but not dialogue) for Seedance 1.x", () => {
43
+ const cap = getVideoAudioCapability("seedance")
44
+ expect(cap.mode).toBe("ambient")
45
+ expect(cap.field).toBe("generateAudio")
46
+ })
47
+
48
+ it("defaults to none for silent / unknown / undefined models", () => {
49
+ for (const m of [
50
+ "minimax",
51
+ "hailuo-2.3",
52
+ "wan-i2v",
53
+ "grok-i2v",
54
+ "gemini-omni-video",
55
+ "runway",
56
+ "pika",
57
+ "totally-unknown-model",
58
+ undefined,
59
+ ]) {
60
+ expect(getVideoAudioCapability(m).mode, String(m)).toBe("none")
61
+ }
62
+ })
63
+ })
64
+
65
+ describe("videoModelSupportsAudio", () => {
66
+ it("is true for any model with an audio mode, false for silent", () => {
67
+ expect(videoModelSupportsAudio("veo3")).toBe(true)
68
+ expect(videoModelSupportsAudio("kling-3.0")).toBe(true)
69
+ expect(videoModelSupportsAudio("seedance-2")).toBe(true)
70
+ expect(videoModelSupportsAudio("seedance")).toBe(true)
71
+ expect(videoModelSupportsAudio("minimax")).toBe(false)
72
+ expect(videoModelSupportsAudio(undefined)).toBe(false)
73
+ })
74
+ })
75
+
76
+ describe("videoModelCanSpeakDialogue", () => {
77
+ it("is true only for native_speech + audio_driven models", () => {
78
+ expect(videoModelCanSpeakDialogue("veo3")).toBe(true)
79
+ expect(videoModelCanSpeakDialogue("veo3_lite")).toBe(true)
80
+ expect(videoModelCanSpeakDialogue("seedance-2")).toBe(true)
81
+ expect(videoModelCanSpeakDialogue("seedance-2-fast")).toBe(true)
82
+ expect(videoModelCanSpeakDialogue("seedance-2-mini")).toBe(true)
83
+ // ambient-only models are NOT dialogue-capable — their audio is SFX/ambient
84
+ expect(videoModelCanSpeakDialogue("kling")).toBe(false)
85
+ expect(videoModelCanSpeakDialogue("kling-3.0")).toBe(false)
86
+ expect(videoModelCanSpeakDialogue("seedance")).toBe(false)
87
+ expect(videoModelCanSpeakDialogue("minimax")).toBe(false)
88
+ expect(videoModelCanSpeakDialogue(undefined)).toBe(false)
89
+ })
90
+ })
91
+
92
+ describe("seedance-2-mini is a full Seedance 2 family member", () => {
93
+ it("is in the family set — drives the Frames/References mode toggle", () => {
94
+ expect(SEEDANCE_2_PROVIDERS.has("seedance-2-mini")).toBe(true)
95
+ expect(isSeedance2Provider("seedance-2-mini")).toBe(true)
96
+ })
97
+ it("carries the full multimodal reference caps (9 images / 3 videos / 3 audio)", () => {
98
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["seedance-2-mini"]).toEqual(SEEDANCE_2_REF_LIMITS)
99
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["seedance-2-mini"]).toEqual({ images: 9, videos: 3, audio: 3 })
100
+ })
101
+ })
102
+
103
+ describe("VIDEO_AUDIO_CAPABILITY internal consistency", () => {
104
+ it("every Kling AUDIO_ADDON provider is ambient + affectsCost", () => {
105
+ for (const m of AUDIO_ADDON_PROVIDERS) {
106
+ const cap = getVideoAudioCapability(m)
107
+ expect(cap.mode, m).toBe("ambient")
108
+ expect(cap.affectsCost, m).toBe(true)
109
+ }
110
+ })
111
+
112
+ it("every VEO provider is native_speech", () => {
113
+ for (const m of VEO_PROVIDERS) {
114
+ expect(getVideoAudioCapability(m).mode, m).toBe("native_speech")
115
+ }
116
+ })
117
+
118
+ it("every Seedance-2 provider is audio_driven", () => {
119
+ for (const m of SEEDANCE_2_PROVIDERS) {
120
+ expect(getVideoAudioCapability(m).mode, m).toBe("audio_driven")
121
+ }
122
+ })
123
+
124
+ it("affectsCost is set only for AUDIO_ADDON providers", () => {
125
+ for (const [model, cap] of Object.entries(VIDEO_AUDIO_CAPABILITY)) {
126
+ if (cap.affectsCost) expect(AUDIO_ADDON_PROVIDERS.has(model), model).toBe(true)
127
+ }
128
+ })
129
+
130
+ it("a user-controllable mode declares which field carries the toggle", () => {
131
+ for (const [model, cap] of Object.entries(VIDEO_AUDIO_CAPABILITY)) {
132
+ // alwaysOn models (VEO) have no toggle; everything else with audio must
133
+ // name the provider option field so the UI + worker wire the right one.
134
+ if (cap.mode !== "none" && !cap.alwaysOn) {
135
+ expect(cap.field, model).toBeDefined()
136
+ }
137
+ }
138
+ })
139
+ })
140
+
141
+ describe("applyVideoAudioToggle — neutral audio intent → per-model KIE field", () => {
142
+ it("maps the neutral toggle onto Kling's `sound` field", () => {
143
+ const input: Record<string, unknown> = {}
144
+ applyVideoAudioToggle(input, "kling", { sound: true })
145
+ expect(input.sound).toBe(true)
146
+ expect(input.generate_audio).toBeUndefined()
147
+ })
148
+
149
+ it("maps the neutral toggle onto Seedance's `generate_audio` field (the Studio bug)", () => {
150
+ // Studio sends ONLY `sound`, but Seedance's lever is `generate_audio`.
151
+ // Pre-fix the toggle was silently dropped on Seedance; it must now reach
152
+ // generate_audio in BOTH directions.
153
+ const on: Record<string, unknown> = {}
154
+ applyVideoAudioToggle(on, "seedance-2", { sound: true })
155
+ expect(on.generate_audio).toBe(true)
156
+ expect(on.sound).toBeUndefined()
157
+
158
+ const off: Record<string, unknown> = {}
159
+ applyVideoAudioToggle(off, "seedance-2", { sound: false })
160
+ expect(off.generate_audio).toBe(false)
161
+
162
+ const v1: Record<string, unknown> = {}
163
+ applyVideoAudioToggle(v1, "seedance", { sound: true })
164
+ expect(v1.generate_audio).toBe(true)
165
+ })
166
+
167
+ it("accepts `generateAudio` as a legacy alias on FREE models (Seedance)", () => {
168
+ const input: Record<string, unknown> = {}
169
+ applyVideoAudioToggle(input, "seedance", { generateAudio: true })
170
+ expect(input.generate_audio).toBe(true)
171
+ })
172
+
173
+ it("IGNORES the `generateAudio` alias on cost-affecting Kling — only `sound` toggles it", () => {
174
+ // Kling's audio is a credit surcharge keyed off `sound`. If the model honoured
175
+ // `generateAudio` too, a generateAudio-driven enable would generate (cost-affecting)
176
+ // audio the `sound`-keyed surcharge never billed. So the alias is gated off here.
177
+ const aliasOnly: Record<string, unknown> = {}
178
+ applyVideoAudioToggle(aliasOnly, "kling", { generateAudio: true })
179
+ expect(aliasOnly).toEqual({}) // no enable from the alias alone
180
+
181
+ const canonical: Record<string, unknown> = {}
182
+ applyVideoAudioToggle(canonical, "kling", { sound: true, generateAudio: false })
183
+ expect(canonical.sound).toBe(true) // the canonical lever still works (and wins)
184
+ })
185
+
186
+ it("is a no-op for always-on VEO — there is no user toggle to honour", () => {
187
+ const input: Record<string, unknown> = {}
188
+ applyVideoAudioToggle(input, "veo3", { sound: false })
189
+ expect(input).toEqual({})
190
+ })
191
+
192
+ it("is a no-op for silent / unknown models (not in the capability table)", () => {
193
+ const input: Record<string, unknown> = {}
194
+ applyVideoAudioToggle(input, "minimax", { sound: true })
195
+ applyVideoAudioToggle(input, undefined, { sound: true })
196
+ expect(input).toEqual({})
197
+ })
198
+
199
+ it("leaves the model's own default untouched when no intent is expressed", () => {
200
+ const input: Record<string, unknown> = { generate_audio: true }
201
+ applyVideoAudioToggle(input, "seedance-2", {})
202
+ expect(input.generate_audio).toBe(true)
203
+ })
204
+ })
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import {
3
+ IMAGE_TO_VIDEO_PROVIDERS,
4
+ TEXT_TO_VIDEO_PROVIDERS,
5
+ VIDEO_GEN_PROVIDERS,
6
+ type VideoGenProvider,
7
+ } from "../model-constants.js"
8
+
9
+ describe("VIDEO_GEN_PROVIDERS", () => {
10
+ it("includes every IMAGE_TO_VIDEO_PROVIDERS entry", () => {
11
+ for (const p of IMAGE_TO_VIDEO_PROVIDERS) {
12
+ expect(VIDEO_GEN_PROVIDERS).toContain(p)
13
+ }
14
+ })
15
+ it("includes every TEXT_TO_VIDEO_PROVIDERS entry", () => {
16
+ for (const p of TEXT_TO_VIDEO_PROVIDERS) {
17
+ expect(VIDEO_GEN_PROVIDERS).toContain(p)
18
+ }
19
+ })
20
+ it("has no duplicates", () => {
21
+ const set = new Set(VIDEO_GEN_PROVIDERS)
22
+ expect(set.size).toBe(VIDEO_GEN_PROVIDERS.length)
23
+ })
24
+ it("VideoGenProvider type narrows correctly", () => {
25
+ const p: VideoGenProvider = "kling"
26
+ expect(VIDEO_GEN_PROVIDERS).toContain(p)
27
+ })
28
+ })
@@ -0,0 +1,150 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import {
3
+ IMAGE_TO_VIDEO_PROVIDERS,
4
+ TEXT_TO_VIDEO_PROVIDERS,
5
+ VIDEO_GEN_PROVIDERS,
6
+ VIDEO_MODE_ALIASES,
7
+ VIDEO_GEN_COLLAPSED_T2V_IDS,
8
+ VIDEO_PROVIDERS_REQUIRING_IMAGE,
9
+ resolveVideoProviderForMode,
10
+ } from "../model-constants.js"
11
+
12
+ const I2V = "image-to-video"
13
+ const T2V = "text-to-video"
14
+
15
+ describe("resolveVideoProviderForMode", () => {
16
+ it("maps the i2v id to itself in i2v mode and to the t2v id in t2v mode (grok)", () => {
17
+ expect(resolveVideoProviderForMode("grok-i2v", I2V)).toBe("grok-i2v")
18
+ expect(resolveVideoProviderForMode("grok-i2v", T2V)).toBe("grok")
19
+ })
20
+
21
+ it("maps the t2v id to the i2v id in i2v mode (fixes the t2v-id-plus-image footgun)", () => {
22
+ // Picking the t2v 'grok' and connecting an image used to send 'grok' to the
23
+ // i2v path where KIE_VIDEO_MODELS['grok'] is undefined → crash. Now it
24
+ // resolves to the real i2v id.
25
+ expect(resolveVideoProviderForMode("grok", I2V)).toBe("grok-i2v")
26
+ expect(resolveVideoProviderForMode("grok", T2V)).toBe("grok")
27
+ })
28
+
29
+ it("maps Wan 2.6 ids by mode", () => {
30
+ expect(resolveVideoProviderForMode("wan-i2v", I2V)).toBe("wan-i2v")
31
+ expect(resolveVideoProviderForMode("wan-i2v", T2V)).toBe("wan")
32
+ expect(resolveVideoProviderForMode("wan", I2V)).toBe("wan-i2v")
33
+ expect(resolveVideoProviderForMode("wan", T2V)).toBe("wan")
34
+ })
35
+
36
+ it("maps Wan 2.7 ids by mode", () => {
37
+ expect(resolveVideoProviderForMode("wan-2.7-i2v", I2V)).toBe("wan-2.7-i2v")
38
+ expect(resolveVideoProviderForMode("wan-2.7-i2v", T2V)).toBe("wan-2.7-t2v")
39
+ expect(resolveVideoProviderForMode("wan-2.7-t2v", I2V)).toBe("wan-2.7-i2v")
40
+ expect(resolveVideoProviderForMode("wan-2.7-t2v", T2V)).toBe("wan-2.7-t2v")
41
+ })
42
+
43
+ it("maps HappyHorse ids by mode", () => {
44
+ expect(resolveVideoProviderForMode("happyhorse-i2v", I2V)).toBe("happyhorse-i2v")
45
+ expect(resolveVideoProviderForMode("happyhorse-i2v", T2V)).toBe("happyhorse")
46
+ expect(resolveVideoProviderForMode("happyhorse", I2V)).toBe("happyhorse-i2v")
47
+ expect(resolveVideoProviderForMode("happyhorse", T2V)).toBe("happyhorse")
48
+ })
49
+
50
+ it("passes non-aliased providers through unchanged in both modes", () => {
51
+ for (const p of ["kling", "seedance", "veo3", "minimax", "ltx-2.3-pro"]) {
52
+ expect(resolveVideoProviderForMode(p, I2V)).toBe(p)
53
+ expect(resolveVideoProviderForMode(p, T2V)).toBe(p)
54
+ }
55
+ })
56
+
57
+ it("passes single-id i2v-only models (grok-imagine-video-1.5) through unchanged", () => {
58
+ // It is its own id in both arrays — never aliased, so no remap.
59
+ expect(resolveVideoProviderForMode("grok-imagine-video-1.5", I2V)).toBe("grok-imagine-video-1.5")
60
+ expect(resolveVideoProviderForMode("grok-imagine-video-1.5", T2V)).toBe("grok-imagine-video-1.5")
61
+ })
62
+ })
63
+
64
+ describe("VIDEO_MODE_ALIASES registry honesty", () => {
65
+ it("every group's i2v id is a real image-to-video provider", () => {
66
+ for (const g of VIDEO_MODE_ALIASES) {
67
+ expect(IMAGE_TO_VIDEO_PROVIDERS as readonly string[]).toContain(g.i2v)
68
+ }
69
+ })
70
+
71
+ it("every group's t2v id is a real text-to-video provider", () => {
72
+ for (const g of VIDEO_MODE_ALIASES) {
73
+ expect(TEXT_TO_VIDEO_PROVIDERS as readonly string[]).toContain(g.t2v)
74
+ }
75
+ })
76
+
77
+ it("every group's base id is one of its own mode ids", () => {
78
+ for (const g of VIDEO_MODE_ALIASES) {
79
+ expect([g.i2v, g.t2v]).toContain(g.base)
80
+ }
81
+ })
82
+ })
83
+
84
+ describe("VIDEO_GEN_COLLAPSED_T2V_IDS (picker collapse set)", () => {
85
+ it("contains exactly the t2v twins whose i2v sibling is the picker base", () => {
86
+ expect(VIDEO_GEN_COLLAPSED_T2V_IDS).toEqual(new Set(["grok", "wan", "wan-2.7-t2v", "happyhorse"]))
87
+ })
88
+
89
+ it("every collapsed id is a t2v provider that is NOT also an i2v provider (safe to hide)", () => {
90
+ for (const id of VIDEO_GEN_COLLAPSED_T2V_IDS) {
91
+ expect(TEXT_TO_VIDEO_PROVIDERS as readonly string[]).toContain(id)
92
+ expect(IMAGE_TO_VIDEO_PROVIDERS as readonly string[]).not.toContain(id)
93
+ }
94
+ })
95
+ })
96
+
97
+ // ─── Unified-node dispatch totality ─────────────────────────────────────────
98
+ // The unified Generate Video node can route ANY of its providers down EITHER
99
+ // mode path: t2v when no image is wired, i2v when one is. After the alias
100
+ // remap, the resolved id must therefore pass the target route's Zod enum in
101
+ // BOTH directions. A provider in only one list (and not aliased) reaches the
102
+ // other route as a raw Zod enum 400 — exactly the kling-3-omni /
103
+ // "received 'kling-3-omni'" production error. i2v-only providers satisfy the
104
+ // t2v direction by being listed in TEXT_TO_VIDEO_PROVIDERS and gated by
105
+ // VIDEO_PROVIDERS_REQUIRING_IMAGE (clean "image required" 400 at the route).
106
+ describe("unified generate-video dispatch totality", () => {
107
+ it("every VIDEO_GEN_PROVIDERS member resolves to a valid t2v route provider", () => {
108
+ const t2v = new Set<string>(TEXT_TO_VIDEO_PROVIDERS)
109
+ const broken = VIDEO_GEN_PROVIDERS.filter(
110
+ (p) => !t2v.has(resolveVideoProviderForMode(p, T2V)),
111
+ )
112
+ expect(
113
+ broken,
114
+ `These unified-picker providers crash /v1/text-to-video with a Zod enum error when run without an image — add them to TEXT_TO_VIDEO_PROVIDERS (i2v-only models get the friendly 400 via VIDEO_PROVIDERS_REQUIRING_IMAGE) or alias them to a t2v twin: ${broken.join(", ")}`,
115
+ ).toEqual([])
116
+ })
117
+
118
+ it("every VIDEO_GEN_PROVIDERS member resolves to a valid i2v route provider", () => {
119
+ const i2v = new Set<string>(IMAGE_TO_VIDEO_PROVIDERS)
120
+ const broken = VIDEO_GEN_PROVIDERS.filter(
121
+ (p) => !i2v.has(resolveVideoProviderForMode(p, I2V)),
122
+ )
123
+ expect(
124
+ broken,
125
+ `These unified-picker providers fail the /v1/generate-video path when an image IS wired — add them to IMAGE_TO_VIDEO_PROVIDERS or alias them to an i2v twin: ${broken.join(", ")}`,
126
+ ).toEqual([])
127
+ })
128
+ })
129
+
130
+ describe("VIDEO_PROVIDERS_REQUIRING_IMAGE (derived from MODEL_CATALOG modes)", () => {
131
+ it("contains exactly the unaliased i2v-only unified-picker providers", () => {
132
+ expect(new Set(VIDEO_PROVIDERS_REQUIRING_IMAGE)).toEqual(
133
+ new Set([
134
+ "grok-imagine-video-1.5",
135
+ "kling-3-omni",
136
+ "kling-master",
137
+ "hailuo-2.3",
138
+ "hailuo-2.3-pro",
139
+ "bytedance-pro-fast",
140
+ "happyhorse-ref2v",
141
+ ]),
142
+ )
143
+ })
144
+
145
+ it("never contains a provider with a real t2v path (would wrongly block it)", () => {
146
+ for (const p of VIDEO_PROVIDERS_REQUIRING_IMAGE) {
147
+ expect(resolveVideoProviderForMode(p, T2V), `${p} is aliased to a t2v twin — it must not be image-gated`).toBe(p)
148
+ }
149
+ })
150
+ })
@@ -0,0 +1,72 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import {
3
+ SEEDANCE_2_REF_LIMITS,
4
+ VIDEO_REF_LIMITS_BY_PROVIDER,
5
+ } from "../model-constants.js"
6
+ import { MODEL_CATALOG } from "../model-catalog.js"
7
+
8
+ describe("VIDEO_REF_LIMITS_BY_PROVIDER", () => {
9
+ it("seedance-2 providers get the SEEDANCE_2_REF_LIMITS shape", () => {
10
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["seedance-2"]).toEqual({
11
+ images: SEEDANCE_2_REF_LIMITS.images,
12
+ videos: SEEDANCE_2_REF_LIMITS.videos,
13
+ audio: SEEDANCE_2_REF_LIMITS.audio,
14
+ })
15
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["seedance-2-fast"]).toEqual({
16
+ images: SEEDANCE_2_REF_LIMITS.images,
17
+ videos: SEEDANCE_2_REF_LIMITS.videos,
18
+ audio: SEEDANCE_2_REF_LIMITS.audio,
19
+ })
20
+ })
21
+ it("non-seedance providers either have just an images cap or are absent", () => {
22
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["grok-i2v"]?.images).toBeGreaterThanOrEqual(1)
23
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["kling-turbo"]).toBeUndefined()
24
+ // Not verified reference-forwarders (2026-06-28 audit) → deliberately absent.
25
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["wan-i2v"]).toBeUndefined()
26
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["grok-imagine-video-1.5"]).toBeUndefined()
27
+ })
28
+ })
29
+
30
+ describe("VIDEO_REF_LIMITS_BY_PROVIDER ⇄ MODEL_CATALOG drift guard", () => {
31
+ // The catalog (kind:"video" + features:["reference-image"]) is the SINGLE
32
+ // authority on WHICH video models accept image references;
33
+ // VIDEO_REF_LIMITS_BY_PROVIDER holds the per-provider NUMERIC caps. These two
34
+ // MUST stay in 1:1 correspondence — a ref-capable video model with no cap entry
35
+ // (or a cap entry with no catalog flag) is exactly the drift that silently broke
36
+ // `connectedReferences` coverage (6 ref-capable models had no cap; 6 capped
37
+ // models weren't flagged). This invariant fails CI on any future divergence.
38
+ const catalogRefVideoIds = Object.values(MODEL_CATALOG)
39
+ .filter((m) => m.kind === "video" && m.features?.includes("reference-image"))
40
+ .map((m) => m.id)
41
+ .sort()
42
+ const mapIds = Object.keys(VIDEO_REF_LIMITS_BY_PROVIDER).sort()
43
+
44
+ it("every reference-capable video model in the catalog has a numeric cap entry", () => {
45
+ const missing = catalogRefVideoIds.filter((id) => !(id in VIDEO_REF_LIMITS_BY_PROVIDER))
46
+ expect(missing).toEqual([])
47
+ })
48
+
49
+ it("every numeric cap entry corresponds to a reference-capable video model in the catalog", () => {
50
+ const orphan = mapIds.filter((id) => !catalogRefVideoIds.includes(id))
51
+ expect(orphan).toEqual([])
52
+ })
53
+
54
+ it("the two sets are exactly equal (no drift in either direction)", () => {
55
+ expect(mapIds).toEqual(catalogRefVideoIds)
56
+ })
57
+ })
58
+
59
+ describe("VIDEO_REF_LIMITS_BY_PROVIDER caps for the newly-covered models", () => {
60
+ it("VEO family carries images:3 (the REFERENCE_2_VIDEO slice cap in kie/video.ts)", () => {
61
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["veo3"]).toEqual({ images: 3 })
62
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["veo3.1"]).toEqual({ images: 3 })
63
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["veo3_lite"]).toEqual({ images: 3 })
64
+ })
65
+ it("kling-3-omni and grok-i2v carry images:7", () => {
66
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["kling-3-omni"]).toEqual({ images: 7 })
67
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["grok-i2v"]).toEqual({ images: 7 })
68
+ })
69
+ it("happyhorse-ref2v carries images:9", () => {
70
+ expect(VIDEO_REF_LIMITS_BY_PROVIDER["happyhorse-ref2v"]).toEqual({ images: 9 })
71
+ })
72
+ })