@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,52 @@
1
+ /**
2
+ * Evaluate a dot-notation path against a JSON value.
3
+ *
4
+ * Auto-iterates arrays at any depth: if the current value is an array,
5
+ * the evaluator iterates and applies the remaining path to each element,
6
+ * flattening results. This lets simple paths like "caption" work on a
7
+ * top-level array and "pages.markdown" work on a nested array without
8
+ * any wildcard syntax.
9
+ *
10
+ * Returns an array of values. Missing properties are skipped (empty for
11
+ * that branch). Null/undefined leaf values are included — callers coerce.
12
+ * Empty path returns `[value]` (a single-element array wrapping the
13
+ * value) when the value is scalar/object, or the array elements flat
14
+ * when the root is an array.
15
+ */
16
+ export function evaluateJsonPath(value: unknown, path: string): unknown[] {
17
+ const segments = path.length === 0 ? [] : path.split(".")
18
+ return walk(value, segments, 0)
19
+ }
20
+
21
+ /**
22
+ * Coerce an array of unknown values (typically from evaluateJsonPath) to
23
+ * strings, skipping null/undefined. Primitives are stringified; objects
24
+ * are JSON-encoded.
25
+ */
26
+ export function stringifyPathResults(raw: unknown[]): string[] {
27
+ const out: string[] = []
28
+ for (const v of raw) {
29
+ if (v === null || v === undefined) continue
30
+ if (typeof v === "string") out.push(v)
31
+ else if (typeof v === "number" || typeof v === "boolean") out.push(String(v))
32
+ else out.push(JSON.stringify(v))
33
+ }
34
+ return out
35
+ }
36
+
37
+ function walk(value: unknown, segments: string[], offset: number): unknown[] {
38
+ if (Array.isArray(value)) {
39
+ const results: unknown[] = []
40
+ for (const item of value) {
41
+ for (const v of walk(item, segments, offset)) results.push(v)
42
+ }
43
+ return results
44
+ }
45
+ if (offset >= segments.length) return [value]
46
+ if (value !== null && typeof value === "object") {
47
+ const head = segments[offset]
48
+ if (!Object.hasOwn(value as object, head)) return []
49
+ return walk((value as Record<string, unknown>)[head], segments, offset + 1)
50
+ }
51
+ return []
52
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Lip-sync per-second pricing helpers.
3
+ *
4
+ * KIE.ai Kling AI Avatar 2.0 (May 2026) raised the max input audio from 15s
5
+ * to 5 minutes and bills per-second. We bucket the requested audio duration
6
+ * into discrete tiers and use composite credit identifiers
7
+ * (e.g. `kling-avatar:60s`) so credit reservation scales with input length.
8
+ *
9
+ * InfiniTalk still enforces a 15s upstream cap.
10
+ */
11
+
12
+ export const LIP_SYNC_DURATION_BUCKETS = [15, 30, 60, 120, 300] as const
13
+
14
+ export type LipSyncDurationBucket = typeof LIP_SYNC_DURATION_BUCKETS[number]
15
+
16
+ /** Round a measured audio duration up to the next supported bucket. */
17
+ export function pickLipSyncBucket(seconds: number): LipSyncDurationBucket {
18
+ if (!Number.isFinite(seconds) || seconds <= 0) return LIP_SYNC_DURATION_BUCKETS[0]
19
+ for (const b of LIP_SYNC_DURATION_BUCKETS) {
20
+ if (seconds <= b) return b
21
+ }
22
+ return 300
23
+ }
24
+
25
+ /**
26
+ * Upper audio-duration limit per lip-sync provider, in seconds.
27
+ * Anything longer must be trimmed (server-side) before sending upstream.
28
+ */
29
+ export const LIP_SYNC_MAX_AUDIO_SECONDS: Record<string, number> = {
30
+ "kling-avatar": 300,
31
+ "kling-avatar-pro": 300,
32
+ "infinitalk": 15,
33
+ // OmniHuman 1.5 — KIE hard limit is < 60s; audio is auto-trimmed to this cap.
34
+ "omnihuman-1-5": 60,
35
+ // HeyGen Lipsync Precision + Sync Lipsync 2 Pro — billed per output second.
36
+ // 5-min ceiling for credit bucketing (mirrors kling-avatar). MUST be set:
37
+ // the default fallback below is 15s, which would clamp every request to the
38
+ // 15s bucket and silently under-charge long clips.
39
+ "heygen-lipsync-precision": 300,
40
+ "lipsync-2-pro": 300,
41
+ // Sync Lipsync v3 (fal.ai) — per-second dubbing, 5-min ceiling for bucketing.
42
+ "sync-lipsync-v3": 300,
43
+ // Volcengine (KIE) — video-to-video dubbing, per-second, 5-min ceiling.
44
+ "volcengine-lipsync": 300,
45
+ }
46
+
47
+ export function getLipSyncMaxAudioSeconds(provider: string): number {
48
+ return LIP_SYNC_MAX_AUDIO_SECONDS[provider] ?? 15
49
+ }
50
+
51
+ /** Providers whose credit cost varies with audio duration. */
52
+ const PER_SECOND_LIP_SYNC_PROVIDERS = new Set([
53
+ "kling-avatar",
54
+ "kling-avatar-pro",
55
+ // OmniHuman 1.5 — /sec, bucketed by audio length (60s cap).
56
+ "omnihuman-1-5",
57
+ "heygen-lipsync-precision",
58
+ "lipsync-2-pro",
59
+ // Sync Lipsync v3 (fal.ai) — billed per output second (/min).
60
+ "sync-lipsync-v3",
61
+ // Volcengine (KIE) — video-to-video dubbing, billed per output second.
62
+ "volcengine-lipsync",
63
+ ])
64
+
65
+ export function isPerSecondLipSyncProvider(provider: string): boolean {
66
+ return PER_SECOND_LIP_SYNC_PROVIDERS.has(provider)
67
+ }
68
+
69
+ /**
70
+ * Build the credit identifier for a lip-sync request.
71
+ *
72
+ * For kling-avatar / kling-avatar-pro, returns `<provider>:<bucket>s`.
73
+ * For other providers, returns the bare provider name (caller appends
74
+ * any extra dimensions like resolution).
75
+ *
76
+ * If `audioDurationSec` is missing, defaults to the provider's max cap so
77
+ * credit reservation covers the worst case and any overage is refunded
78
+ * after the worker reconciles the actual KIE cost.
79
+ */
80
+ export function buildLipSyncCreditId(
81
+ provider: string,
82
+ audioDurationSec: number | undefined,
83
+ ): string {
84
+ if (!isPerSecondLipSyncProvider(provider)) return provider
85
+ const cap = getLipSyncMaxAudioSeconds(provider)
86
+ const requested = audioDurationSec === undefined || audioDurationSec <= 0
87
+ ? cap
88
+ : Math.min(audioDurationSec, cap)
89
+ return `${provider}:${pickLipSyncBucket(requested)}s`
90
+ }
@@ -0,0 +1,40 @@
1
+ import { tryParseJson } from "./filter-condition.js"
2
+
3
+ /**
4
+ * Element-wise merge across upstream lists with modulo-wrap.
5
+ *
6
+ * Used by the `merge-lists` node's "zip" mode. Each output position i takes
7
+ * `lists[j][i % lists[j].length]` from every input; JSON objects are spread
8
+ * into a single object (later sources override earlier ones on key conflicts),
9
+ * non-object items are stringified and concatenated.
10
+ *
11
+ * Length semantics mirror the DAG's existing fan-out behavior: the result
12
+ * length equals `max(len)` across non-empty inputs. Shorter inputs cycle.
13
+ * This means a single-item upstream (e.g. a JSON-process node emitting one
14
+ * object, or a list with one row) is automatically injected into every
15
+ * element of a longer list.
16
+ */
17
+ export function zipMergeLists(lists: ReadonlyArray<ReadonlyArray<string>>): string[] {
18
+ const nonEmpty = lists.filter((l) => l.length > 0)
19
+ if (nonEmpty.length === 0) return []
20
+ if (nonEmpty.length === 1) return [...nonEmpty[0]]
21
+
22
+ const maxLen = Math.max(...nonEmpty.map((l) => l.length))
23
+ const out: string[] = []
24
+ for (let i = 0; i < maxLen; i++) {
25
+ const merged: Record<string, unknown> = {}
26
+ const rawItems: string[] = []
27
+ let hasObject = false
28
+ for (const list of nonEmpty) {
29
+ const item = list[i % list.length]
30
+ rawItems.push(item)
31
+ const parsed = tryParseJson(item)
32
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33
+ hasObject = true
34
+ Object.assign(merged, parsed as Record<string, unknown>)
35
+ }
36
+ }
37
+ out.push(hasObject ? JSON.stringify(merged) : rawItems.join(""))
38
+ }
39
+ return out
40
+ }
@@ -0,0 +1,122 @@
1
+ /** Pure sort helper shared by the frontend DAG executor and the backend
2
+ * orchestrator. Contract: reorder stringified list items (as produced by
3
+ * `collectUpstreamListItems` peers) by an optional dot-path field, with
4
+ * Auto/Text/Number/Date comparison and asc/desc direction. Items whose
5
+ * key is missing, empty, or uncoerceable under the chosen type are always
6
+ * appended last — regardless of direction. */
7
+
8
+ import { evaluateJsonPath } from "./json-path.js"
9
+ import { tryParseJson } from "./filter-condition.js"
10
+
11
+ export type SortType = "auto" | "text" | "number" | "date"
12
+ export type SortDirection = "asc" | "desc"
13
+
14
+ export interface SortListOptions {
15
+ field: string
16
+ sortType: SortType
17
+ direction: SortDirection
18
+ }
19
+
20
+ // Natural numeric-aware, case-insensitive locale compare. Declared once so
21
+ // both the Text branch and the Auto fallback reuse the same Collator.
22
+ const textCollator = new Intl.Collator(undefined, {
23
+ sensitivity: "base",
24
+ numeric: true,
25
+ })
26
+
27
+ interface KeyedItem {
28
+ item: string
29
+ key: number | string
30
+ keyKind: "number" | "text" | "invalid"
31
+ }
32
+
33
+ function extractRawKey(item: string, field: string): unknown {
34
+ if (field === "") return item
35
+ const parsed = tryParseJson(item)
36
+ const matches = evaluateJsonPath(parsed, field)
37
+ return matches.length > 0 ? matches[0] : undefined
38
+ }
39
+
40
+ function isMissing(v: unknown): boolean {
41
+ if (v === undefined || v === null) return true
42
+ if (typeof v === "string" && v.trim() === "") return true
43
+ return false
44
+ }
45
+
46
+ function toNumberKey(v: unknown): number | undefined {
47
+ if (typeof v === "number") return Number.isFinite(v) ? v : undefined
48
+ if (typeof v === "boolean") return v ? 1 : 0
49
+ if (typeof v === "string") {
50
+ const trimmed = v.trim()
51
+ if (trimmed === "") return undefined
52
+ const n = Number(trimmed)
53
+ return Number.isFinite(n) ? n : undefined
54
+ }
55
+ return undefined
56
+ }
57
+
58
+ function toDateKey(v: unknown): number | undefined {
59
+ if (v instanceof Date) {
60
+ const t = v.getTime()
61
+ return Number.isFinite(t) ? t : undefined
62
+ }
63
+ if (typeof v === "number") return Number.isFinite(v) ? v : undefined
64
+ if (typeof v === "string") {
65
+ const t = Date.parse(v)
66
+ return Number.isFinite(t) ? t : undefined
67
+ }
68
+ return undefined
69
+ }
70
+
71
+ function coerceKey(raw: unknown, sortType: SortType): Pick<KeyedItem, "key" | "keyKind"> {
72
+ if (isMissing(raw)) return { key: "", keyKind: "invalid" }
73
+
74
+ if (sortType === "number") {
75
+ const n = toNumberKey(raw)
76
+ return n === undefined
77
+ ? { key: "", keyKind: "invalid" }
78
+ : { key: n, keyKind: "number" }
79
+ }
80
+
81
+ if (sortType === "date") {
82
+ const d = toDateKey(raw)
83
+ return d === undefined
84
+ ? { key: "", keyKind: "invalid" }
85
+ : { key: d, keyKind: "number" }
86
+ }
87
+
88
+ if (sortType === "text") {
89
+ return { key: typeof raw === "string" ? raw : JSON.stringify(raw), keyKind: "text" }
90
+ }
91
+
92
+ // auto: try number → date → text.
93
+ const asNum = toNumberKey(raw)
94
+ if (asNum !== undefined) return { key: asNum, keyKind: "number" }
95
+ const asDate = toDateKey(raw)
96
+ if (asDate !== undefined) return { key: asDate, keyKind: "number" }
97
+ return { key: typeof raw === "string" ? raw : JSON.stringify(raw), keyKind: "text" }
98
+ }
99
+
100
+ export function sortListItems(items: readonly string[], opts: SortListOptions): string[] {
101
+ const { field, sortType, direction } = opts
102
+ const keyed: KeyedItem[] = items.map((item) => {
103
+ const raw = extractRawKey(item, field)
104
+ const { key, keyKind } = coerceKey(raw, sortType)
105
+ return { item, key, keyKind }
106
+ })
107
+
108
+ const sortable = keyed.filter((k) => k.keyKind !== "invalid")
109
+ const invalid = keyed.filter((k) => k.keyKind === "invalid")
110
+
111
+ const factor = direction === "desc" ? -1 : 1
112
+ // Array.prototype.sort is guaranteed stable since ES2019 — equal keys
113
+ // preserve their relative input order.
114
+ sortable.sort((a, b) => {
115
+ if (a.keyKind === "number" && b.keyKind === "number") {
116
+ return ((a.key as number) - (b.key as number)) * factor
117
+ }
118
+ return textCollator.compare(String(a.key), String(b.key)) * factor
119
+ })
120
+
121
+ return [...sortable.map((k) => k.item), ...invalid.map((k) => k.item)]
122
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Follow a list node's `in` edge chain to its effective upstream source.
3
+ *
4
+ * When a `list` node has no manual rows but an incoming connection, the UI
5
+ * renders its upstream's items (see list-node.tsx's `connectedItems ??
6
+ * staticItems`). Without this helper, downstream readers would see an empty
7
+ * list because `extractSourceNodeOutput` for `list` only reads `data.rows`.
8
+ *
9
+ * Shared between the frontend DAG executor (`node-input-resolver.ts`) and
10
+ * the backend orchestrator (`inline-executor.ts`) so both paths resolve
11
+ * list-connected-mode identically.
12
+ */
13
+
14
+ type EdgeShape = {
15
+ source: string
16
+ target: string
17
+ sourceHandle?: string | null
18
+ targetHandle?: string | null
19
+ }
20
+
21
+ type NodeShape = {
22
+ id: string
23
+ type?: string
24
+ data: Record<string, unknown>
25
+ }
26
+
27
+ function hasAnyRow(rows: string[][]): boolean {
28
+ return rows.some((r) => r.some((v) => v?.trim()))
29
+ }
30
+
31
+ export function resolveSourceThroughConnectedList<
32
+ E extends EdgeShape,
33
+ N extends NodeShape,
34
+ >(edge: E, nodes: ReadonlyArray<N>, edges: ReadonlyArray<E>): E {
35
+ const visited = new Set<string>()
36
+ let current = edge
37
+ while (true) {
38
+ const src = nodes.find((n) => n.id === current.source)
39
+ if (!src || src.type !== "list") return current
40
+ if (visited.has(src.id)) return current
41
+ visited.add(src.id)
42
+ const rows = (src.data.rows as string[][] | undefined) ?? []
43
+ if (hasAnyRow(rows)) return current
44
+ const inEdge = edges.find(
45
+ (e) => e.target === src.id && e.targetHandle === "in",
46
+ )
47
+ if (!inEdge) return current
48
+ current = inEdge
49
+ }
50
+ }
@@ -0,0 +1,245 @@
1
+ /**
2
+ * LLM Model Registry — shared between frontend and backend.
3
+ *
4
+ * Single source of truth for available chat/LLM models routed through KIE.ai,
5
+ * with direct Anthropic SDK fallback for Claude models. This is the
6
+ * NON-monetary side of the registry (model ids, capabilities, tiers,
7
+ * feature defaults). The provider-$ per-token rate table and the
8
+ * `calculateLlmCost` formula derived from it live in
9
+ * `backend/src/lib/pricing/llm-cost.ts` (core, not ee/ — internal LLM cost
10
+ * logging needs them regardless of edition). They were moved out of this
11
+ * package (published Apache-2.0 on npm — an irrevocable grant) per the
12
+ * 2026-07-06 public-flip IP audit, S5: "Keep the model-id enum; strip prices
13
+ * + measurement notes."
14
+ */
15
+
16
+ export type LlmTier = "economy" | "standard" | "premium"
17
+ export type KieApiFormat = "chat-completions" | "messages" | "responses"
18
+
19
+ export interface LlmModelDef {
20
+ id: string
21
+ displayName: string
22
+ desc: string
23
+ tier: LlmTier
24
+ kieFormat: KieApiFormat
25
+ /** For chat-completions: the slug prefix (e.g. "gemini-3-flash").
26
+ * For messages: the model id sent in the body (e.g. "claude-haiku-4-5-v1messages").
27
+ * For responses: the model id sent in the body (e.g. "gpt-5-4"). */
28
+ kieSlugOrModel: string
29
+ vendor: "anthropic" | "google" | "openai"
30
+ supportsImages: boolean
31
+ maxOutputTokens: number
32
+ /**
33
+ * How this model can be forced into schema-valid structured output.
34
+ * - "anthropic-tool" → direct Anthropic SDK forced tool_choice (guaranteed).
35
+ * - "kie-response-format" → KIE chat-completions `response_format: json_schema`
36
+ * (verified enforced for Gemini via KIE).
37
+ * - undefined → no native structured mode (GPT-via-KIE doesn't honor
38
+ * response_format); callers fall back to parse + retry.
39
+ * Capability-driven so `llmCompleteStructured` never hardcodes provider ids.
40
+ */
41
+ structuredOutputMode?: "anthropic-tool" | "kie-response-format"
42
+ /** If set, fallback to direct Anthropic SDK with this model ID when KIE.ai fails */
43
+ directFallbackModel?: string
44
+ }
45
+
46
+ export const LLM_MODELS: readonly LlmModelDef[] = [
47
+ {
48
+ id: "gemini-3-flash",
49
+ displayName: "Gemini 3 Flash",
50
+ desc: "Fast and cheap, good for simple tasks",
51
+ tier: "economy",
52
+ kieFormat: "chat-completions",
53
+ kieSlugOrModel: "gemini-3-flash",
54
+ vendor: "google",
55
+ structuredOutputMode: "kie-response-format",
56
+ supportsImages: true,
57
+ maxOutputTokens: 8192,
58
+ },
59
+ {
60
+ id: "claude-haiku-4.5",
61
+ displayName: "Claude Haiku 4.5",
62
+ desc: "Fast economy, good reasoning",
63
+ tier: "economy",
64
+ kieFormat: "messages",
65
+ kieSlugOrModel: "claude-haiku-4-5",
66
+ vendor: "anthropic",
67
+ structuredOutputMode: "anthropic-tool",
68
+ supportsImages: true,
69
+ maxOutputTokens: 8192,
70
+ directFallbackModel: "claude-haiku-4-5-20251001",
71
+ },
72
+ {
73
+ id: "claude-sonnet-4.6",
74
+ displayName: "Claude Sonnet 4.6",
75
+ desc: "Balanced quality and speed",
76
+ tier: "standard",
77
+ kieFormat: "messages",
78
+ kieSlugOrModel: "claude-sonnet-4-6",
79
+ vendor: "anthropic",
80
+ structuredOutputMode: "anthropic-tool",
81
+ supportsImages: true,
82
+ maxOutputTokens: 16384,
83
+ directFallbackModel: "claude-sonnet-4-6",
84
+ },
85
+ {
86
+ id: "gpt-5.2",
87
+ displayName: "GPT-5.2",
88
+ desc: "Strong general purpose",
89
+ tier: "standard",
90
+ kieFormat: "chat-completions",
91
+ kieSlugOrModel: "gpt-5-2",
92
+ vendor: "openai",
93
+ supportsImages: true,
94
+ maxOutputTokens: 16384,
95
+ },
96
+ {
97
+ id: "gemini-3.1-pro",
98
+ displayName: "Gemini 3.1 Pro",
99
+ desc: "Advanced reasoning, large context",
100
+ tier: "premium",
101
+ kieFormat: "chat-completions",
102
+ kieSlugOrModel: "gemini-3.1-pro",
103
+ vendor: "google",
104
+ structuredOutputMode: "kie-response-format",
105
+ supportsImages: true,
106
+ maxOutputTokens: 16384,
107
+ },
108
+ {
109
+ id: "claude-opus-4.7",
110
+ displayName: "Claude Opus 4.7",
111
+ desc: "Highest quality, complex tasks",
112
+ tier: "premium",
113
+ kieFormat: "messages",
114
+ kieSlugOrModel: "claude-opus-4-7",
115
+ vendor: "anthropic",
116
+ structuredOutputMode: "anthropic-tool",
117
+ supportsImages: true,
118
+ maxOutputTokens: 16384,
119
+ directFallbackModel: "claude-opus-4-7",
120
+ },
121
+ {
122
+ id: "gpt-5.4",
123
+ displayName: "GPT-5.4",
124
+ desc: "Latest GPT, premium quality",
125
+ tier: "premium",
126
+ kieFormat: "responses",
127
+ kieSlugOrModel: "gpt-5-4",
128
+ vendor: "openai",
129
+ supportsImages: true,
130
+ maxOutputTokens: 16384,
131
+ },
132
+ ] as const
133
+
134
+ export const LLM_MODEL_IDS = LLM_MODELS.map((m) => m.id)
135
+
136
+ /** Vision models that can return GUARANTEED structured output — the
137
+ * describe-to-picker analyzer forces a schema over an image, so its model
138
+ * pickers AND the backend route gate offer exactly these: Anthropic (forced
139
+ * tool) + Gemini (KIE `response_format`). GPT-via-KIE has no native structured
140
+ * mode (parse+retry only), so it's excluded. Single source of truth so the
141
+ * picker, the config panel, and the route gate can't drift. */
142
+ export const STRUCTURED_VISION_MODELS = LLM_MODELS.filter(
143
+ (m) => m.supportsImages && m.structuredOutputMode != null,
144
+ )
145
+
146
+ export type LlmFeature =
147
+ | "ai-writer"
148
+ | "llm-chat"
149
+ | "prompt-helper"
150
+ | "scene-graph-ai"
151
+ | "after-effects"
152
+ | "motion-graphics"
153
+ | "motion-graphics-lottie"
154
+ | "lottie-overlay"
155
+ | "3d-title"
156
+ | "image-to-text"
157
+ | "describe-to-picker"
158
+ | "qa-check"
159
+ | "generate-script"
160
+ | "translate"
161
+ | "image-critic"
162
+
163
+ /** Engine-dependent LlmFeature for the motion-graphics node (design §8: every credit-id site must branch on engine). */
164
+ export function motionGraphicsFeature(engine?: string): LlmFeature {
165
+ return engine === "lottie" ? "motion-graphics-lottie" : "motion-graphics"
166
+ }
167
+
168
+ /** Feature → default model when user hasn't selected one */
169
+ export const LLM_FEATURE_DEFAULTS: Record<LlmFeature, string> = {
170
+ "ai-writer": "claude-sonnet-4.6",
171
+ "llm-chat": "gemini-3-flash",
172
+ "prompt-helper": "gemini-3-flash",
173
+ "scene-graph-ai": "claude-sonnet-4.6",
174
+ "after-effects": "claude-sonnet-4.6",
175
+ "motion-graphics": "claude-sonnet-4.6",
176
+ "motion-graphics-lottie": "claude-sonnet-4.6",
177
+ "lottie-overlay": "claude-sonnet-4.6",
178
+ "3d-title": "claude-sonnet-4.6",
179
+ "image-to-text": "claude-sonnet-4.6",
180
+ "describe-to-picker": "claude-opus-4.7",
181
+ "qa-check": "claude-sonnet-4.6",
182
+ "generate-script": "gemini-3-flash",
183
+ "translate": "gemini-3-flash",
184
+ "image-critic": "claude-sonnet-4.6",
185
+ }
186
+
187
+ /**
188
+ * Per-model multimodal input capabilities. Drives both frontend UI gating
189
+ * and backend route-level filtering for the LLM Chat node references.
190
+ *
191
+ * As of 2026-05: Claude Messages API supports text + image only (no audio,
192
+ * no video). Gemini 2/3 family supports image + video + audio natively.
193
+ * GPT-5.x via KIE chat-completions / responses supports image only — audio
194
+ * input requires a separate audio-capable model we don't route to today.
195
+ */
196
+ export const LLM_MODALITY_CAPS: Record<string, { image: boolean; video: boolean; audio: boolean }> = {
197
+ "gemini-3-flash": { image: true, video: true, audio: true },
198
+ "gemini-3.1-pro": { image: true, video: true, audio: true },
199
+ "claude-haiku-4.5": { image: true, video: false, audio: false },
200
+ "claude-sonnet-4.6": { image: true, video: false, audio: false },
201
+ "claude-opus-4.7": { image: true, video: false, audio: false },
202
+ "gpt-5.2": { image: true, video: false, audio: false },
203
+ "gpt-5.4": { image: true, video: false, audio: false },
204
+ }
205
+
206
+ /** Capability lookup with safe default — unknown models get image-only. */
207
+ export function getLlmModalityCaps(modelId: string | undefined): { image: boolean; video: boolean; audio: boolean } {
208
+ if (!modelId) return { image: true, video: false, audio: false }
209
+ return LLM_MODALITY_CAPS[modelId] ?? { image: true, video: false, audio: false }
210
+ }
211
+
212
+ export function getLlmModel(id: string): LlmModelDef | undefined {
213
+ return LLM_MODELS.find((m) => m.id === id)
214
+ }
215
+
216
+ export function getLlmTier(id: string): LlmTier {
217
+ return getLlmModel(id)?.tier ?? "standard"
218
+ }
219
+
220
+ /**
221
+ * Build a composite credit identifier for an LLM feature.
222
+ * - economy tier → "ai-writer:economy"
223
+ * - standard tier → "ai-writer" (no suffix — backward compatible)
224
+ * - premium tier → "ai-writer:premium"
225
+ */
226
+ export function buildLlmCreditIdentifier(feature: string, modelId?: string): string {
227
+ if (!modelId) return feature
228
+ const tier = getLlmTier(modelId)
229
+ if (tier === "standard") return feature
230
+ return `${feature}:${tier}`
231
+ }
232
+
233
+ /**
234
+ * Resolve llmModel from raw body for creditGuard preHandler (before Zod parsing).
235
+ * Returns the credit identifier for the given feature + optional model.
236
+ */
237
+ export function resolveLlmCreditId(feature: string, body: unknown): string {
238
+ const llmModel = (body as Record<string, unknown>)?.llmModel as string | undefined
239
+ return buildLlmCreditIdentifier(feature, llmModel)
240
+ }
241
+
242
+ /** Models capable of video-analysis: capability-derived, never hand-listed (route-enum-sync convention). */
243
+ export const VIDEO_ANALYSIS_LLM_MODELS: string[] = LLM_MODELS
244
+ .filter((m) => getLlmModalityCaps(m.id).video && getLlmModalityCaps(m.id).audio)
245
+ .map((m) => m.id)