@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,249 @@
1
+ import { z } from "zod"
2
+ import { ImageCriticVerdictSchema } from "./image-critic-types.js"
3
+ import { ShotSpecSchema } from "./scene-node-types.js"
4
+
5
+ /**
6
+ * All 10 helpers — 7 text/planning helpers shipped in Phase 1B.3 +
7
+ * 3 vision-keyframe helpers activated in Phase 1C.1.
8
+ * Names match the §6.11 spec sub-section labels (URL-safe form).
9
+ */
10
+ export const SCENE_HELPER_NAMES = [
11
+ // Text/planning-only — shipped in 1B.3
12
+ "audit_prompt",
13
+ "improve_prompt",
14
+ "generate_motion",
15
+ "optimize_for_model",
16
+ "add_broll",
17
+ "bridge_to_next_scene",
18
+ "anchor_scene_style",
19
+ // Vision-keyframe — activated in Phase 1C.1
20
+ "audit_images",
21
+ "fix_continuity",
22
+ "validate_match_cut",
23
+ ] as const
24
+
25
+ export const SceneHelperNameSchema = z.enum(SCENE_HELPER_NAMES)
26
+ export type SceneHelperName = z.infer<typeof SceneHelperNameSchema>
27
+
28
+ /**
29
+ * UI-gating set used by `scene-helper-buttons.tsx` to render active vs disabled
30
+ * buttons. Phase 1C.1 promoted the 3 vision-keyframe helpers from disabled →
31
+ * active; the constant name is preserved for compat (it remains "the set of
32
+ * helpers currently shipped"), and {@link ACTIVE_SCENE_HELPERS} is a clearer
33
+ * alias for new code.
34
+ */
35
+ export const HELPERS_SHIPPED_IN_1B3: ReadonlySet<SceneHelperName> = new Set([
36
+ "audit_prompt",
37
+ "improve_prompt",
38
+ "generate_motion",
39
+ "optimize_for_model",
40
+ "add_broll",
41
+ "bridge_to_next_scene",
42
+ "anchor_scene_style",
43
+ // Phase 1C.1 — activated
44
+ "audit_images",
45
+ "fix_continuity",
46
+ "validate_match_cut",
47
+ ])
48
+
49
+ /** Cleaner-named alias for {@link HELPERS_SHIPPED_IN_1B3}. */
50
+ export const ACTIVE_SCENE_HELPERS = HELPERS_SHIPPED_IN_1B3
51
+
52
+ // ─── 6.11.2 Audit Prompt — Haiku, text-only ────────────────────────────────────
53
+
54
+ export const AuditPromptIssueSchema = z.object({
55
+ shot_id: z.string(),
56
+ severity: z.enum(["blocking", "warning", "info"]),
57
+ issue_type: z.enum([
58
+ "contradiction",
59
+ "missing_beat",
60
+ "off_format",
61
+ "camera_motion_mismatch",
62
+ ]),
63
+ message: z.string(),
64
+ suggested_fix: z.string(),
65
+ })
66
+
67
+ export const AuditPromptResultSchema = z.object({
68
+ scene_id: z.string(),
69
+ ok: z.boolean(),
70
+ issues_per_shot: z.array(AuditPromptIssueSchema),
71
+ scene_level_notes: z.string().max(400),
72
+ })
73
+ export type AuditPromptResult = z.infer<typeof AuditPromptResultSchema>
74
+
75
+ // ─── 6.11.3 Improve Prompt — Sonnet, target enum ────────────────────────────────
76
+
77
+ export const ImprovePromptInputSchema = z.object({
78
+ shot_ids: z.array(z.string()).min(1),
79
+ field_targets: z.array(z.enum(["action", "motion_prompt", "dialogue"])).min(1),
80
+ })
81
+ export type ImprovePromptInput = z.infer<typeof ImprovePromptInputSchema>
82
+
83
+ export const ImprovePromptResultSchema = z.object({
84
+ scene_id: z.string(),
85
+ shots: z.array(
86
+ z.object({
87
+ shot_id: z.string(),
88
+ action: z.string().max(300).optional(),
89
+ motion_prompt: z.string().max(200).optional(),
90
+ dialogue_line: z.string().max(200).optional(),
91
+ reasoning: z.string().max(300),
92
+ }),
93
+ ),
94
+ })
95
+ export type ImprovePromptResult = z.infer<typeof ImprovePromptResultSchema>
96
+
97
+ // ─── 6.11.5 Generate Motion — Haiku, fills motion_prompt ───────────────────────
98
+
99
+ export const GenerateMotionInputSchema = z.object({
100
+ shot_ids: z.array(z.string()).min(1),
101
+ })
102
+
103
+ export const GenerateMotionResultSchema = z.object({
104
+ scene_id: z.string(),
105
+ shots: z.array(
106
+ z.object({
107
+ shot_id: z.string(),
108
+ motion_prompt: z.string().max(200),
109
+ }),
110
+ ),
111
+ })
112
+ export type GenerateMotionResult = z.infer<typeof GenerateMotionResultSchema>
113
+
114
+ // ─── 6.11.6 Optimize for Model — Sonnet, rewrites for new prompting_style ─────
115
+
116
+ export const OptimizeForModelInputSchema = z.object({
117
+ target_model: z.string(),
118
+ })
119
+
120
+ export const OptimizeForModelResultSchema = z.object({
121
+ scene_id: z.string(),
122
+ target_model: z.string(),
123
+ shots: z.array(
124
+ z.object({
125
+ shot_id: z.string(),
126
+ action: z.string().max(300),
127
+ motion_prompt: z.string().max(200),
128
+ }),
129
+ ),
130
+ rationale: z.string().max(300),
131
+ })
132
+ export type OptimizeForModelResult = z.infer<typeof OptimizeForModelResultSchema>
133
+
134
+ // ─── 6.11.7 Add B-Roll — Sonnet, proposes new shots ────────────────────────────
135
+
136
+ export const AddBRollResultSchema = z.object({
137
+ scene_id: z.string(),
138
+ candidates: z
139
+ .array(
140
+ z.object({
141
+ proposed_insert_after_shot_id: z.string(),
142
+ insert_kind: z.enum(["reaction_shot", "cutaway", "establishing", "transition"]),
143
+ shot: ShotSpecSchema,
144
+ rationale: z.string().max(200),
145
+ }),
146
+ )
147
+ .min(1)
148
+ .max(4),
149
+ scene_duration_delta: z.number(),
150
+ })
151
+ export type AddBRollResult = z.infer<typeof AddBRollResultSchema>
152
+
153
+ // ─── 6.11.10 Bridge to Next Scene — Sonnet, generates bridge_image_prompt ──────
154
+
155
+ export const BridgeToNextSceneInputSchema = z.object({
156
+ target_shot_id: z.string(),
157
+ })
158
+
159
+ export const BridgeToNextSceneResultSchema = z.object({
160
+ scene_id: z.string(),
161
+ target_shot_id: z.string(),
162
+ bridge_image_prompt: z.string().max(500),
163
+ reasoning: z.string().max(300),
164
+ })
165
+ export type BridgeToNextSceneResult = z.infer<typeof BridgeToNextSceneResultSchema>
166
+
167
+ // ─── 6.11.11 Anchor Scene Style — Sonnet plans + image_model generates ─────────
168
+
169
+ export const AnchorSceneStyleResultSchema = z.object({
170
+ scene_id: z.string(),
171
+ anchor_prompt: z.string().max(800),
172
+ asset_id: z.string().uuid(),
173
+ asset_url: z.string().url(),
174
+ credits_spent: z.number(),
175
+ })
176
+ export type AnchorSceneStyleResult = z.infer<typeof AnchorSceneStyleResultSchema>
177
+
178
+ // ─── 6.11.12 Audit Images — Sonnet vision, per-shot keyframe critic loop ──────
179
+ //
180
+ // Runs `runImageCritic` over every shot's keyframe_url in the scene (no body
181
+ // inputs). Aggregates verdicts into a per-shot issue list. `ok` rolls up to
182
+ // scene-level: false when any shot has a blocking issue.
183
+
184
+ export const AuditImagesShotEntrySchema = z.object({
185
+ shot_id: z.string(),
186
+ ok: z.boolean(),
187
+ /** Verdict body — empty when the shot has no `keyframe_url` yet (skipped). */
188
+ verdict: ImageCriticVerdictSchema.nullable(),
189
+ /** True when the shot had no keyframe to audit. */
190
+ skipped: z.boolean(),
191
+ })
192
+ export type AuditImagesShotEntry = z.infer<typeof AuditImagesShotEntrySchema>
193
+
194
+ export const AuditImagesResultSchema = z.object({
195
+ scene_id: z.string(),
196
+ ok: z.boolean(),
197
+ shot_issues: z.array(AuditImagesShotEntrySchema),
198
+ /** Roll-up summary suitable for in-app display ("3 of 5 shots have issues"). */
199
+ summary: z.string().max(400),
200
+ })
201
+ export type AuditImagesResult = z.infer<typeof AuditImagesResultSchema>
202
+
203
+ // ─── 6.11.13 Fix Continuity — Sonnet vision + i2i regen ──────────────────────
204
+ //
205
+ // Body: { target_shot_id }. Runs Image Critic against the target shot's
206
+ // keyframe with its PRIOR shot's `last_frame_url`. If a `continuity_break`
207
+ // blocking issue is found, regenerates the keyframe via
208
+ // `pipelineGenerateImage` using the prior last_frame as a strong reference,
209
+ // and persists the new keyframe_url back to the scene's shots[target].
210
+
211
+ export const FixContinuityInputSchema = z.object({
212
+ target_shot_id: z.string(),
213
+ })
214
+ export type FixContinuityInput = z.infer<typeof FixContinuityInputSchema>
215
+
216
+ export const FixContinuityResultSchema = z.object({
217
+ scene_id: z.string(),
218
+ target_shot_id: z.string(),
219
+ action: z.enum(["regenerated", "no_action_needed"]),
220
+ critic_verdict: ImageCriticVerdictSchema,
221
+ /** Populated only when `action === "regenerated"`. */
222
+ new_keyframe_url: z.string().url().optional(),
223
+ new_keyframe_asset_id: z.string().uuid().optional(),
224
+ })
225
+ export type FixContinuityResult = z.infer<typeof FixContinuityResultSchema>
226
+
227
+ // ─── 6.11.14 Validate Match Cut — Sonnet vision ──────────────────────────────
228
+ //
229
+ // Body: { target_shot_id }. Loads the target shot's keyframe + the NEXT shot's
230
+ // keyframe and asks the Image Critic to evaluate the match-cut quality.
231
+ // Returns a `match_strength` summary + the critic's full verdict. Returns 400
232
+ // `not_a_match_cut` from the route layer when `shot_intent.is_match_cut`
233
+ // is false on the target shot (pre-flight check before credit reservation).
234
+
235
+ export const ValidateMatchCutInputSchema = z.object({
236
+ target_shot_id: z.string(),
237
+ })
238
+ export type ValidateMatchCutInput = z.infer<typeof ValidateMatchCutInputSchema>
239
+
240
+ export const ValidateMatchCutResultSchema = z.object({
241
+ scene_id: z.string(),
242
+ /** Tuple [shot_id_a, shot_id_b] — the target shot + the next shot. */
243
+ shot_pair: z.tuple([z.string(), z.string()]),
244
+ match_strength: z.enum(["strong", "moderate", "weak", "break"]),
245
+ critic_verdict: ImageCriticVerdictSchema,
246
+ /** Optional follow-up actions the user could take (free-form, ≤300 chars). */
247
+ suggested_adjustments: z.string().max(300),
248
+ })
249
+ export type ValidateMatchCutResult = z.infer<typeof ValidateMatchCutResultSchema>
@@ -0,0 +1,281 @@
1
+ import { z } from "zod"
2
+
3
+ // SceneInputMode lives in model-constants.ts — re-export so all SceneNodeData
4
+ // consumers import from one place.
5
+ import { SceneInputModeSchema } from "./model-constants.js"
6
+
7
+ /**
8
+ * TransitionType — the set of allowed shot-to-shot transitions emitted by the
9
+ * Editor LLM stage. Single source of truth shared across:
10
+ * - ShotSpec.cut_decision.transition_to_next (this file)
11
+ * - backend/src/ee/pipelines/llms/editor.ts (LLM result schema)
12
+ * - backend/src/ee/pipelines/services/pipeline-final-merge.ts
13
+ * - backend/src/ee/pipelines/freecut-export.ts
14
+ */
15
+ export const TransitionTypeSchema = z.enum([
16
+ "hard_cut",
17
+ "dissolve",
18
+ "match_cut",
19
+ "overlap",
20
+ ])
21
+ export type TransitionType = z.infer<typeof TransitionTypeSchema>
22
+
23
+ /**
24
+ * ShotSpec — one shot inside a SceneNodeData.
25
+ * Mirrors Architecture §6.9.1 + v4.1 Method-2/3/5/7/8/10 field additions.
26
+ */
27
+ export const ShotSpecSchema = z.object({
28
+ shot_id: z.string().regex(/^shot_\d{2,3}$/, "shot_id must be shot_NN or shot_NNN"),
29
+ camera: z.object({
30
+ shot_type: z.enum([
31
+ "wide", "medium", "close_up", "extreme_close_up", "pov", "over_shoulder",
32
+ ]),
33
+ angle: z.enum(["eye_level", "low", "high", "dutch", "birds_eye"]),
34
+ motion: z.enum(["static", "pan", "tilt", "dolly", "tracking", "handheld"]),
35
+ }),
36
+ shot_intensity_kind: z.enum([
37
+ "establishing_shot", "action_shot", "dialogue_shot",
38
+ "reaction_shot", "climactic_shot", "transition_shot",
39
+ ]),
40
+
41
+ action: z.string().max(300),
42
+ dialogue_line: z.string().max(200).nullable(),
43
+ duration_seconds: z.number().min(0.3).max(8),
44
+
45
+ motion_prompt: z.string().max(200),
46
+
47
+ // Internal continuity within this scene
48
+ start_state: z.string().max(200),
49
+ end_state: z.string().max(200),
50
+ continuity_with_previous: z.string().max(200).nullable(),
51
+
52
+ // Provider-neutral intent — engine maps to provider-specific directives at call time
53
+ shot_intent: z.object({
54
+ needs_multishot_reference: z.boolean().default(false),
55
+ is_loopable: z.boolean().default(false),
56
+ needs_music_suppression: z.boolean().default(true),
57
+ is_match_cut: z.boolean().default(false), // v4.1 Method 7
58
+ }),
59
+
60
+ visual_keyframe_prompt: z.string().min(1).max(1000),
61
+
62
+ // v4.1 Method 2 — pre-planned paired keyframes (required when shot_input_mode='first_last_frame')
63
+ end_keyframe_prompt: z.string().max(1000).optional(),
64
+
65
+ // v4.1 Method 3 — video continuation (this shot extends extends_shot_id's clip)
66
+ extends_shot_id: z.string().optional(),
67
+
68
+ // v4.1 Method 5 — i2i bridge applied to prior last_frame before this shot animates
69
+ bridge_image_prompt: z.string().max(500).optional(),
70
+
71
+ // v4.1 Method 8 — sparse keyframes for interpolation models
72
+ interpolation_keyframes: z
73
+ .array(
74
+ z.object({
75
+ timestamp_sec: z.number().nonnegative(),
76
+ prompt: z.string().min(10).max(1000),
77
+ }),
78
+ )
79
+ .max(16)
80
+ .optional(),
81
+
82
+ // Phase 1C.3 Method 8 — generated R2 URLs of the sub-keyframes, one per
83
+ // `interpolation_keyframes[N].prompt`. Stage 6 writes these BEFORE Stage 7
84
+ // runs so the animate step can pass them to the interpolation provider.
85
+ // Length MUST equal `interpolation_keyframes.length` when populated.
86
+ interpolation_keyframe_urls: z.array(z.string().url()).max(16).optional(),
87
+
88
+ // v4.1 Method 10 — parametric 3D camera path
89
+ camera_path_directive: z
90
+ .object({
91
+ path_kind: z.enum(["orbit", "dolly", "crane", "arc", "reveal"]),
92
+ parameters: z.record(z.unknown()).optional(),
93
+ })
94
+ .optional(),
95
+
96
+ // ─── Execution state (engine writes; null on planning) ─────────────────────
97
+ // Phase 1C.1: per-shot execution state lands directly on the shot record so
98
+ // the SceneNode internal pipeline + continuity chain can read/write them in
99
+ // one place. All optional — planning-time ShotSpec carries none of these.
100
+
101
+ // Stage 6 (scene_images) writes these after keyframe generation.
102
+ keyframe_asset_id: z.string().uuid().optional(),
103
+ keyframe_url: z.string().url().optional(),
104
+
105
+ // Stage 7 (animate_audio_edit) step 3 (animate) writes these after the
106
+ // image-to-video / text-to-video call succeeds.
107
+ video_asset_id: z.string().uuid().optional(),
108
+ video_url: z.string().url().optional(),
109
+
110
+ // Stage 7 step 3 (extract_frame chain — sequential mode only) writes these
111
+ // after each shot's last frame is extracted at duration - 0.1s. Used by the
112
+ // next shot's continuity chain (Method 1).
113
+ last_frame_asset_id: z.string().uuid().optional(),
114
+ last_frame_url: z.string().url().optional(),
115
+
116
+ // Stage 7 step 4 (speech) writes these per shot with dialogue_line.
117
+ audio_asset_id: z.string().uuid().optional(),
118
+ audio_url: z.string().url().optional(),
119
+
120
+ // Stage 7 step 5 (lip-sync) writes these when lipsync_enabled and the shot
121
+ // has dialogue. The lipsynced clip replaces the shot's video_url in the
122
+ // step-6 combine call.
123
+ lipsynced_asset_id: z.string().uuid().optional(),
124
+ lipsynced_url: z.string().url().optional(),
125
+
126
+ // Phase 1C.3 — bridged frame (Method 5). Defensive placeholder; never set
127
+ // in 1C.1 (continuity.applyContinuityToStartFrame already reads this).
128
+ bridged_frame_url: z.string().url().optional(),
129
+
130
+ // Phase 1D.1 Method 7 — set true when the user accepts a MatchCutCritic
131
+ // 'break' verdict for this shot's pair. Stage 6 reads this to know the
132
+ // break is resolved and the scene can advance to Stage 7.
133
+ accepted_match_cut_break: z.boolean().optional(),
134
+
135
+ // ─── Phase 1C.2 — dialogue + editor cut metadata ───────────────────────────
136
+ // All optional; planning-time ShotSpec carries none of these. Populated by
137
+ // the Editor LLM (Stage 7) and the silent-cut-preview sub-gate handler.
138
+
139
+ // True when `dialogue_line` is non-null AND the speech generator produced
140
+ // an audio track. The Editor LLM uses this to gate cut-in / cut-out into
141
+ // the dialogue_no_cut_zone (Method 5.13.1 — never trim a syllable).
142
+ has_dialogue: z.boolean().default(false),
143
+
144
+ // Measured length of the per-shot speech audio (Stage 7 step 4 writes this).
145
+ // Separate from `duration_seconds` (the planning intent) — the actual
146
+ // recording can run longer/shorter than the spec.
147
+ actual_audio_duration_sec: z.number().optional(),
148
+
149
+ // Inclusive [start, end] window (seconds, relative to the shot's video clip)
150
+ // during which the Editor LLM MUST NOT cut. Computed from
151
+ // `actual_audio_duration_sec` + small padding by the Editor LLM stage.
152
+ // null when has_dialogue=false (no zone to protect).
153
+ dialogue_no_cut_zone: z
154
+ .object({ start: z.number(), end: z.number() })
155
+ .nullable()
156
+ .optional(),
157
+
158
+ // Editor LLM output (Phase 1C.2). Populated by the Editor LLM stage; the
159
+ // silent-cut-preview sub-gate may patch it via user-applied overrides.
160
+ // Mirrors the editor_decisions audit row shape (migration 135).
161
+ cut_decision: z
162
+ .object({
163
+ in_offset_sec: z.number().min(0).max(2).default(0),
164
+ out_offset_sec: z.number().min(0).max(2).default(0),
165
+ transition_to_next: TransitionTypeSchema,
166
+ transition_duration_sec: z.number().min(0).max(2).optional(),
167
+ beat_snap_seconds: z.number().nullable().optional(),
168
+ })
169
+ .optional(),
170
+ })
171
+ export type ShotSpec = z.infer<typeof ShotSpecSchema>
172
+
173
+ /**
174
+ * AssetRef — minimal asset reference shape for execution-state fields.
175
+ * Phase 1B.2 doesn't populate these (Stage 6+ work) but the schema must accept them
176
+ * for parse round-trips.
177
+ */
178
+ export const AssetRefSchema = z.object({
179
+ asset_id: z.string().uuid(),
180
+ url: z.string().url(),
181
+ })
182
+ export type AssetRef = z.infer<typeof AssetRefSchema>
183
+
184
+ /**
185
+ * SceneNodeData — what the Scene Director emits, what the SceneNode renders,
186
+ * what the engine persists on `pipeline_entities.metadata` (for entity_type='scene').
187
+ * Mirrors Architecture §6.9.1.
188
+ */
189
+ export const SceneNodeDataSchema = z.object({
190
+ // Plan fields (Scene Director fills; user editable)
191
+ scene_index: z.number().int().min(1),
192
+ description: z.string().max(500),
193
+ emotional_beat: z.string(),
194
+ duration_seconds: z.number().positive(),
195
+
196
+ // Input mode — gates which video_model values are valid
197
+ shot_input_mode: SceneInputModeSchema,
198
+
199
+ // Echoed inputs (Scene Director copies from SceneSpec)
200
+ cast_keys: z.array(z.string()),
201
+ location_key: z.string(),
202
+ object_keys: z.array(z.string()),
203
+ continuity_from_prev: z.enum(["hard_cut", "match_last_frame", "dissolve"]),
204
+
205
+ // Model picks
206
+ image_model: z.string(),
207
+ video_model: z.string(),
208
+
209
+ // Shot list
210
+ shots: z.array(ShotSpecSchema).min(1).max(8),
211
+
212
+ // v4.1 Method 6 — pre-generated master keyframe (set in 1C; Phase 1B.2 always null)
213
+ scene_anchor_keyframe: AssetRefSchema.nullable().default(null),
214
+
215
+ // Optional per-scene style override
216
+ style_directives: z
217
+ .object({
218
+ visualStyle: z.string().optional(),
219
+ colorPalette: z.string().optional(),
220
+ lighting: z.string().optional(),
221
+ cameraLanguage: z.string().optional(),
222
+ avoid: z.string().optional(),
223
+ })
224
+ .partial()
225
+ .optional(),
226
+
227
+ // Execution state (engine writes; null on planning — Phase 1C populates)
228
+ generated_keyframes: z.array(AssetRefSchema).default([]),
229
+ generated_clips: z.array(AssetRefSchema).default([]),
230
+ composite_video: AssetRefSchema.nullable().default(null),
231
+ last_frame: AssetRefSchema.nullable().default(null),
232
+ scene_audio_track: AssetRefSchema.nullable().default(null),
233
+
234
+ // Phase 1C.1 Stage 7 result — composite video assembled from the per-shot
235
+ // clips inside this scene. Optional flat fields kept alongside
236
+ // `composite_video` (AssetRefSchema) so consumers can read either shape.
237
+ composite_video_asset_id: z.string().uuid().optional(),
238
+ composite_video_url: z.string().url().optional(),
239
+ })
240
+ export type SceneNodeData = z.infer<typeof SceneNodeDataSchema>
241
+
242
+ /**
243
+ * SceneMetadataSchema — what gets persisted on `pipeline_entities.metadata`
244
+ * for entity_type='scene'. The discriminated union in pipeline-types.ts already has
245
+ * Character/Object/Location entries from 1A; this Phase 1B.2 task extends it.
246
+ */
247
+ export const SceneMetadataSchema = z.object({
248
+ entity_type: z.literal("scene"),
249
+ scene_id: z.string(),
250
+ shot_ids: z.array(z.string()),
251
+ emotional_beat: z.string(),
252
+ // Canonical pointer to the canvas SceneNode (workflows.nodes[i].id)
253
+ scene_node_id: z.string(),
254
+ // Opt-in Explode tracking (Phase 2 — null in 1B.2)
255
+ exploded_to_workflow_id: z.string().uuid().nullable().default(null),
256
+ // Phase 1B.2 stashes the full SceneNodeData here so the orchestrator + panel UI
257
+ // don't have to re-resolve it from canvas state.
258
+ // Optional because Stage 5 inserts the entity row BEFORE the Scene Director runs
259
+ // (status='pending' / 'generating') — the field lands after the Scene Director succeeds.
260
+ scene_node_data: SceneNodeDataSchema.optional(),
261
+ })
262
+ export type SceneMetadata = z.infer<typeof SceneMetadataSchema>
263
+
264
+ /**
265
+ * MatchCutVerdictSchema — Phase 1D.1 Method 7.
266
+ *
267
+ * What Stage 6 persists in `pipeline_stages.output.match_cut_verdicts` for
268
+ * each match-cut shot pair. Keyed by the TARGET shot_id (the shot with
269
+ * `shot_intent.is_match_cut=true`). The pair is [target, next-shot].
270
+ *
271
+ * Stage 6 runs `runValidateMatchCut` for every eligible target and stores
272
+ * one MatchCutVerdict per pair. The `pendingBreaks` list in the orchestrator
273
+ * result identifies shots the user must explicitly accept before Stage 7 runs.
274
+ */
275
+ export const MatchCutVerdictSchema = z.object({
276
+ shot_pair: z.tuple([z.string(), z.string()]),
277
+ match_strength: z.enum(["strong", "moderate", "weak", "break"]),
278
+ suggested_adjustments: z.string().max(300),
279
+ checked_at: z.string().datetime(),
280
+ })
281
+ export type MatchCutVerdict = z.infer<typeof MatchCutVerdictSchema>
@@ -0,0 +1,57 @@
1
+ export const SCRAPER_ACTOR_IDS = [
2
+ "content-crawler",
3
+ "google-search",
4
+ "instagram",
5
+ "tiktok",
6
+ "rss",
7
+ ] as const
8
+
9
+ export type ScraperActorId = (typeof SCRAPER_ACTOR_IDS)[number]
10
+
11
+ export const SCRAPER_ACTOR_LABELS: Record<ScraperActorId, string> = {
12
+ "content-crawler": "Website Content (Markdown)",
13
+ "google-search": "Google Search",
14
+ "instagram": "Instagram",
15
+ "tiktok": "TikTok",
16
+ "rss": "RSS Feed",
17
+ }
18
+
19
+ /** Credit costs per composite SKU — must stay in sync with STATIC_CREDIT_COSTS in backend. */
20
+ export const SCRAPER_CREDIT_COSTS: Record<string, number> = {
21
+ "web-scrape": 2,
22
+ "web-scrape:google-search": 3,
23
+ "web-scrape:content-crawler": 1,
24
+ "web-scrape:content-crawler:site": 5,
25
+ "web-scrape:instagram": 1,
26
+ "web-scrape:tiktok": 1,
27
+ "web-scrape:rss": 1,
28
+ }
29
+
30
+ export function isScraperActor(value: unknown): value is ScraperActorId {
31
+ return typeof value === "string" && (SCRAPER_ACTOR_IDS as readonly string[]).includes(value)
32
+ }
33
+
34
+ export interface ScraperCreditInput {
35
+ actor: ScraperActorId
36
+ mode?: "page" | "site"
37
+ }
38
+
39
+ export function buildScraperCreditId(input: ScraperCreditInput): string {
40
+ if (input.actor === "content-crawler") {
41
+ const mode = input.mode ?? "page"
42
+ return mode === "site" ? "web-scrape:content-crawler:site" : "web-scrape:content-crawler"
43
+ }
44
+ return `web-scrape:${input.actor}`
45
+ }
46
+
47
+ /**
48
+ * Resolve the credit identifier from an unvalidated request body.
49
+ * Falls back to a fixed default SKU (google-search) on missing/invalid actor
50
+ * so misrouted requests reserve a known mid-tier price, not the max-cost tier.
51
+ */
52
+ export function resolveScraperCreditId(body: unknown): string {
53
+ const raw = body as { actor?: unknown; mode?: unknown } | undefined
54
+ if (!raw || !isScraperActor(raw.actor)) return "web-scrape:google-search"
55
+ const mode = raw.mode === "site" ? "site" : "page"
56
+ return buildScraperCreditId({ actor: raw.actor, mode })
57
+ }
@@ -0,0 +1,25 @@
1
+ import type { ScraperActorId } from "./scraper-actors.js"
2
+
3
+ /**
4
+ * Scalar fields exposed in the Extract Field dropdown when the direct
5
+ * upstream is a web-scrape node. Nested / non-scalar fields (authorMeta,
6
+ * musicMeta) are intentionally omitted — users access them via the
7
+ * "Custom path..." option.
8
+ *
9
+ * content-crawler paths are pre-dotted (`pages.url`, `pages.markdown`)
10
+ * because its root shape is `{ pages: [...] }`, not a top-level array.
11
+ */
12
+ export const SCRAPER_OUTPUT_FIELDS: Record<ScraperActorId, readonly string[]> = {
13
+ "content-crawler": ["pages.url", "pages.markdown"],
14
+ "google-search": ["title", "url", "description"],
15
+ "instagram": [
16
+ "url", "shortCode", "caption", "displayUrl", "videoUrl",
17
+ "timestamp", "likesCount", "commentsCount", "ownerUsername", "type",
18
+ "childPosts",
19
+ ],
20
+ "tiktok": [
21
+ "id", "webVideoUrl", "videoUrl", "text", "createTime",
22
+ "diggCount", "shareCount", "playCount", "commentCount",
23
+ ],
24
+ "rss": ["title", "url", "description", "pubDate", "guid"],
25
+ } as const
package/src/seasons.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Canonical catalog of seasons.
3
+ *
4
+ * 4 universal seasonal labels — used by the Location Studio's Seasons tab
5
+ * and (in the future) by any season-picker parameter node. Independent of
6
+ * lighting (time-of-day), atmosphere (weather), and color/look.
7
+ *
8
+ * Northern-hemisphere reference is implicit. Promp t hints describe the
9
+ * visual hallmarks of each season so downstream generators reproduce them
10
+ * faithfully across diverse settings (interior, exterior, character, etc.).
11
+ */
12
+
13
+ export interface Season {
14
+ readonly id: string
15
+ readonly label: string
16
+ readonly description: string
17
+ readonly promptHint: string
18
+ }
19
+
20
+ export const SEASONS: ReadonlyArray<Season> = [
21
+ {
22
+ id: "spring",
23
+ label: "Spring",
24
+ description: "Fresh growth, blossoms, mild weather",
25
+ promptHint: "spring season, fresh new growth with green buds and emerging foliage, blossoming flowers, mild fresh air, soft directional sunlight, occasional light rain, pastel color palette of pale greens and pinks",
26
+ },
27
+ {
28
+ id: "summer",
29
+ label: "Summer",
30
+ description: "Full bloom, warm light, lush green",
31
+ promptHint: "summer season, lush full foliage in deep saturated greens, warm bright sunlight with strong overhead sun, deep shadows, vibrant warm color palette, clear blue skies or scattered cumulus clouds",
32
+ },
33
+ {
34
+ id: "autumn",
35
+ label: "Autumn",
36
+ description: "Falling leaves, warm amber palette",
37
+ promptHint: "autumn season, foliage transitioning to warm amber tones — red, orange, yellow, and rust — falling leaves drifting on the breeze, soft golden directional light, crisp cool air with low sun angles",
38
+ },
39
+ {
40
+ id: "winter",
41
+ label: "Winter",
42
+ description: "Bare branches, snow, cool palette",
43
+ promptHint: "winter season, bare branches against a cold sky, snow accumulation on every surface, breath visible in cold air, desaturated cool color palette of blues and grays with isolated warm artificial light sources",
44
+ },
45
+ ]