@nodaro/sdk 2.28.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (716) hide show
  1. package/README.md +33 -2
  2. package/dist/chunk-2DZWWIJ4.cjs +32 -0
  3. package/dist/chunk-2DZWWIJ4.cjs.map +1 -0
  4. package/dist/chunk-34PU2DAT.cjs +118 -0
  5. package/dist/chunk-34PU2DAT.cjs.map +1 -0
  6. package/dist/chunk-37Y5QAVA.js +3 -0
  7. package/dist/chunk-37Y5QAVA.js.map +1 -0
  8. package/dist/chunk-37YCKZX4.cjs +4 -0
  9. package/dist/chunk-37YCKZX4.cjs.map +1 -0
  10. package/dist/chunk-3B47IHB3.cjs +65 -0
  11. package/dist/chunk-3B47IHB3.cjs.map +1 -0
  12. package/dist/chunk-3BELHJBN.cjs +4 -0
  13. package/dist/chunk-3BELHJBN.cjs.map +1 -0
  14. package/dist/chunk-3PPSGM5X.js +3 -0
  15. package/dist/chunk-3PPSGM5X.js.map +1 -0
  16. package/dist/chunk-3QBH2VE2.cjs +80 -0
  17. package/dist/chunk-3QBH2VE2.cjs.map +1 -0
  18. package/dist/chunk-3QFTP5P5.js +102 -0
  19. package/dist/chunk-3QFTP5P5.js.map +1 -0
  20. package/dist/chunk-43FVH6LJ.cjs +123 -0
  21. package/dist/chunk-43FVH6LJ.cjs.map +1 -0
  22. package/dist/chunk-43NO4SGC.cjs +4 -0
  23. package/dist/chunk-43NO4SGC.cjs.map +1 -0
  24. package/dist/chunk-45CK55BH.cjs +4 -0
  25. package/dist/chunk-45CK55BH.cjs.map +1 -0
  26. package/dist/chunk-4NLVBYMW.js +280 -0
  27. package/dist/chunk-4NLVBYMW.js.map +1 -0
  28. package/dist/chunk-4WRDR4GN.js +102 -0
  29. package/dist/chunk-4WRDR4GN.js.map +1 -0
  30. package/dist/chunk-4WWSHV5G.cjs +4 -0
  31. package/dist/chunk-4WWSHV5G.cjs.map +1 -0
  32. package/dist/chunk-53SXNN3A.js +80 -0
  33. package/dist/chunk-53SXNN3A.js.map +1 -0
  34. package/dist/chunk-5ALNFATQ.cjs +27 -0
  35. package/dist/chunk-5ALNFATQ.cjs.map +1 -0
  36. package/dist/chunk-5UQNMNUE.cjs +4 -0
  37. package/dist/chunk-5UQNMNUE.cjs.map +1 -0
  38. package/dist/chunk-5WAI7VGO.js +184 -0
  39. package/dist/chunk-5WAI7VGO.js.map +1 -0
  40. package/dist/chunk-65E3JBFZ.js +52 -0
  41. package/dist/chunk-65E3JBFZ.js.map +1 -0
  42. package/dist/chunk-6JFNBAKV.js +3 -0
  43. package/dist/chunk-6JFNBAKV.js.map +1 -0
  44. package/dist/chunk-6OC6OKLY.cjs +4 -0
  45. package/dist/chunk-6OC6OKLY.cjs.map +1 -0
  46. package/dist/chunk-6OGGJQVA.js +25 -0
  47. package/dist/chunk-6OGGJQVA.js.map +1 -0
  48. package/dist/chunk-7A7HYFGM.js +3 -0
  49. package/dist/chunk-7A7HYFGM.js.map +1 -0
  50. package/dist/chunk-7ISSKQ6S.cjs +106 -0
  51. package/dist/chunk-7ISSKQ6S.cjs.map +1 -0
  52. package/dist/chunk-7LSFG2AF.js +194 -0
  53. package/dist/chunk-7LSFG2AF.js.map +1 -0
  54. package/dist/chunk-7MYKT2L4.cjs +4 -0
  55. package/dist/chunk-7MYKT2L4.cjs.map +1 -0
  56. package/dist/chunk-7QOCWJKD.cjs +25 -0
  57. package/dist/chunk-7QOCWJKD.cjs.map +1 -0
  58. package/dist/chunk-A2ZAFAWC.cjs +4 -0
  59. package/dist/chunk-A2ZAFAWC.cjs.map +1 -0
  60. package/dist/chunk-A3S55XGF.cjs +54 -0
  61. package/dist/chunk-A3S55XGF.cjs.map +1 -0
  62. package/dist/chunk-A3THLBFG.js +3 -0
  63. package/dist/chunk-A3THLBFG.js.map +1 -0
  64. package/dist/chunk-AJVSMNPZ.js +78 -0
  65. package/dist/chunk-AJVSMNPZ.js.map +1 -0
  66. package/dist/chunk-ALSLZG3U.js +124 -0
  67. package/dist/chunk-ALSLZG3U.js.map +1 -0
  68. package/dist/chunk-ALUUBPDG.cjs +4 -0
  69. package/dist/chunk-ALUUBPDG.cjs.map +1 -0
  70. package/dist/chunk-AO3W45LT.cjs +4 -0
  71. package/dist/chunk-AO3W45LT.cjs.map +1 -0
  72. package/dist/chunk-AUDHV3OE.js +3 -0
  73. package/dist/chunk-AUDHV3OE.js.map +1 -0
  74. package/dist/chunk-BAL576G2.cjs +4 -0
  75. package/dist/chunk-BAL576G2.cjs.map +1 -0
  76. package/dist/chunk-BFMKPELU.cjs +212 -0
  77. package/dist/chunk-BFMKPELU.cjs.map +1 -0
  78. package/dist/chunk-BKP6F2IX.js +3 -0
  79. package/dist/chunk-BKP6F2IX.js.map +1 -0
  80. package/dist/chunk-BLA44UCM.js +32 -0
  81. package/dist/chunk-BLA44UCM.js.map +1 -0
  82. package/dist/chunk-BPWUWUZ3.cjs +20 -0
  83. package/dist/chunk-BPWUWUZ3.cjs.map +1 -0
  84. package/dist/chunk-BRV7Z4GD.cjs +17 -0
  85. package/dist/chunk-BRV7Z4GD.cjs.map +1 -0
  86. package/dist/chunk-BU5A6K4C.js +122 -0
  87. package/dist/chunk-BU5A6K4C.js.map +1 -0
  88. package/dist/chunk-C22RJDW3.js +3 -0
  89. package/dist/chunk-C22RJDW3.js.map +1 -0
  90. package/dist/chunk-CGNVHN4V.js +3 -0
  91. package/dist/chunk-CGNVHN4V.js.map +1 -0
  92. package/dist/chunk-CJFIOVBA.js +3 -0
  93. package/dist/chunk-CJFIOVBA.js.map +1 -0
  94. package/dist/chunk-CJLLIVSB.cjs +4 -0
  95. package/dist/chunk-CJLLIVSB.cjs.map +1 -0
  96. package/dist/chunk-CK3AMMSC.js +194 -0
  97. package/dist/chunk-CK3AMMSC.js.map +1 -0
  98. package/dist/chunk-COCKKMNP.cjs +205 -0
  99. package/dist/chunk-COCKKMNP.cjs.map +1 -0
  100. package/dist/chunk-CR5E2SF3.cjs +212 -0
  101. package/dist/chunk-CR5E2SF3.cjs.map +1 -0
  102. package/dist/chunk-CRCPRZFN.js +3 -0
  103. package/dist/chunk-CRCPRZFN.js.map +1 -0
  104. package/dist/chunk-CYRFD6KR.cjs +4 -0
  105. package/dist/chunk-CYRFD6KR.cjs.map +1 -0
  106. package/dist/chunk-D3PW7AHZ.js +3 -0
  107. package/dist/chunk-D3PW7AHZ.js.map +1 -0
  108. package/dist/chunk-DKEYSJCE.cjs +82 -0
  109. package/dist/chunk-DKEYSJCE.cjs.map +1 -0
  110. package/dist/chunk-DPSMVOM3.js +15 -0
  111. package/dist/chunk-DPSMVOM3.js.map +1 -0
  112. package/dist/chunk-E2ZXHS6E.js +20 -0
  113. package/dist/chunk-E2ZXHS6E.js.map +1 -0
  114. package/dist/chunk-E37CVHWW.js +33 -0
  115. package/dist/chunk-E37CVHWW.js.map +1 -0
  116. package/dist/chunk-E5BM4BLO.js +78 -0
  117. package/dist/chunk-E5BM4BLO.js.map +1 -0
  118. package/dist/chunk-EHRWTYGR.cjs +4 -0
  119. package/dist/chunk-EHRWTYGR.cjs.map +1 -0
  120. package/dist/chunk-EJSGJDZY.js +212 -0
  121. package/dist/chunk-EJSGJDZY.js.map +1 -0
  122. package/dist/chunk-ELSOVJPF.js +3 -0
  123. package/dist/chunk-ELSOVJPF.js.map +1 -0
  124. package/dist/chunk-ERLXU47J.js +29 -0
  125. package/dist/chunk-ERLXU47J.js.map +1 -0
  126. package/dist/chunk-ES2E65HT.js +3 -0
  127. package/dist/chunk-ES2E65HT.js.map +1 -0
  128. package/dist/chunk-EXLAHZKF.js +3 -0
  129. package/dist/chunk-EXLAHZKF.js.map +1 -0
  130. package/dist/chunk-FHEYAW5H.js +3 -0
  131. package/dist/chunk-FHEYAW5H.js.map +1 -0
  132. package/dist/chunk-GA4LZZKQ.cjs +104 -0
  133. package/dist/chunk-GA4LZZKQ.cjs.map +1 -0
  134. package/dist/chunk-GAZJ2PA3.js +3 -0
  135. package/dist/chunk-GAZJ2PA3.js.map +1 -0
  136. package/dist/chunk-GB6C5OEZ.cjs +32 -0
  137. package/dist/chunk-GB6C5OEZ.cjs.map +1 -0
  138. package/dist/chunk-GD24ZRFD.js +3 -0
  139. package/dist/chunk-GD24ZRFD.js.map +1 -0
  140. package/dist/chunk-GI7LROLL.cjs +4 -0
  141. package/dist/chunk-GI7LROLL.cjs.map +1 -0
  142. package/dist/chunk-GRFLPEM2.cjs +16 -0
  143. package/dist/chunk-GRFLPEM2.cjs.map +1 -0
  144. package/dist/chunk-GVIFLUYZ.cjs +40 -0
  145. package/dist/chunk-GVIFLUYZ.cjs.map +1 -0
  146. package/dist/chunk-H7VQTG4M.js +35 -0
  147. package/dist/chunk-H7VQTG4M.js.map +1 -0
  148. package/dist/chunk-HAKYPZLB.cjs +242 -0
  149. package/dist/chunk-HAKYPZLB.cjs.map +1 -0
  150. package/dist/chunk-HFBR6G36.js +3 -0
  151. package/dist/chunk-HFBR6G36.js.map +1 -0
  152. package/dist/chunk-HGCVWOGK.cjs +209 -0
  153. package/dist/chunk-HGCVWOGK.cjs.map +1 -0
  154. package/dist/chunk-HLHR3R4P.js +3 -0
  155. package/dist/chunk-HLHR3R4P.js.map +1 -0
  156. package/dist/chunk-HRXXGGSJ.js +3 -0
  157. package/dist/chunk-HRXXGGSJ.js.map +1 -0
  158. package/dist/chunk-I3TYBAOX.js +3 -0
  159. package/dist/chunk-I3TYBAOX.js.map +1 -0
  160. package/dist/chunk-I4A5VJRL.js +352 -0
  161. package/dist/chunk-I4A5VJRL.js.map +1 -0
  162. package/dist/chunk-I6CXC345.js +102 -0
  163. package/dist/chunk-I6CXC345.js.map +1 -0
  164. package/dist/chunk-IGOPUMEX.cjs +4 -0
  165. package/dist/chunk-IGOPUMEX.cjs.map +1 -0
  166. package/dist/chunk-IHKIYVZQ.js +30 -0
  167. package/dist/chunk-IHKIYVZQ.js.map +1 -0
  168. package/dist/chunk-IMC2M5YM.cjs +12 -0
  169. package/dist/chunk-IMC2M5YM.cjs.map +1 -0
  170. package/dist/chunk-IQ6KWSXP.js +3 -0
  171. package/dist/chunk-IQ6KWSXP.js.map +1 -0
  172. package/dist/chunk-IS26FJO7.cjs +4 -0
  173. package/dist/chunk-IS26FJO7.cjs.map +1 -0
  174. package/dist/chunk-J4WFSKY6.js +50 -0
  175. package/dist/chunk-J4WFSKY6.js.map +1 -0
  176. package/dist/chunk-J5LGGCAS.cjs +126 -0
  177. package/dist/chunk-J5LGGCAS.cjs.map +1 -0
  178. package/dist/chunk-JDEZHITT.js +43 -0
  179. package/dist/chunk-JDEZHITT.js.map +1 -0
  180. package/dist/chunk-JGS6YBDW.js +260 -0
  181. package/dist/chunk-JGS6YBDW.js.map +1 -0
  182. package/dist/chunk-JMOKD6ZP.js +46 -0
  183. package/dist/chunk-JMOKD6ZP.js.map +1 -0
  184. package/dist/chunk-JOX5BJ6K.cjs +4 -0
  185. package/dist/chunk-JOX5BJ6K.cjs.map +1 -0
  186. package/dist/chunk-JTAW54UM.js +116 -0
  187. package/dist/chunk-JTAW54UM.js.map +1 -0
  188. package/dist/chunk-K4RQOSJH.js +203 -0
  189. package/dist/chunk-K4RQOSJH.js.map +1 -0
  190. package/dist/chunk-KAIE6WJB.cjs +4 -0
  191. package/dist/chunk-KAIE6WJB.cjs.map +1 -0
  192. package/dist/chunk-KEDPGWIK.cjs +4 -0
  193. package/dist/chunk-KEDPGWIK.cjs.map +1 -0
  194. package/dist/chunk-KG4R454Z.js +18 -0
  195. package/dist/chunk-KG4R454Z.js.map +1 -0
  196. package/dist/chunk-KGKCAGRD.cjs +22 -0
  197. package/dist/chunk-KGKCAGRD.cjs.map +1 -0
  198. package/dist/chunk-KNMW722T.cjs +48 -0
  199. package/dist/chunk-KNMW722T.cjs.map +1 -0
  200. package/dist/chunk-KTTL7BND.cjs +4 -0
  201. package/dist/chunk-KTTL7BND.cjs.map +1 -0
  202. package/dist/chunk-KXEWTYS4.cjs +80 -0
  203. package/dist/chunk-KXEWTYS4.cjs.map +1 -0
  204. package/dist/chunk-KZQKFBRN.js +3 -0
  205. package/dist/chunk-KZQKFBRN.js.map +1 -0
  206. package/dist/chunk-LAWYFC4G.cjs +37 -0
  207. package/dist/chunk-LAWYFC4G.cjs.map +1 -0
  208. package/dist/chunk-LHP2CWHD.js +228 -0
  209. package/dist/chunk-LHP2CWHD.js.map +1 -0
  210. package/dist/chunk-LHRQXWI5.js +3 -0
  211. package/dist/chunk-LHRQXWI5.js.map +1 -0
  212. package/dist/chunk-LKH5M44B.cjs +114 -0
  213. package/dist/chunk-LKH5M44B.cjs.map +1 -0
  214. package/dist/chunk-LLNNHLCE.cjs +4 -0
  215. package/dist/chunk-LLNNHLCE.cjs.map +1 -0
  216. package/dist/chunk-LWZLWSXD.cjs +4 -0
  217. package/dist/chunk-LWZLWSXD.cjs.map +1 -0
  218. package/dist/chunk-M6Y5TOYE.js +3 -0
  219. package/dist/chunk-M6Y5TOYE.js.map +1 -0
  220. package/dist/chunk-MBFUMWI5.cjs +31 -0
  221. package/dist/chunk-MBFUMWI5.cjs.map +1 -0
  222. package/dist/chunk-MEKI37WI.js +3 -0
  223. package/dist/chunk-MEKI37WI.js.map +1 -0
  224. package/dist/chunk-MQ74AKA2.cjs +200 -0
  225. package/dist/chunk-MQ74AKA2.cjs.map +1 -0
  226. package/dist/chunk-N6GLZOE4.cjs +282 -0
  227. package/dist/chunk-N6GLZOE4.cjs.map +1 -0
  228. package/dist/chunk-NBVARNVA.cjs +38 -0
  229. package/dist/chunk-NBVARNVA.cjs.map +1 -0
  230. package/dist/chunk-NCCBS6GU.js +42 -0
  231. package/dist/chunk-NCCBS6GU.js.map +1 -0
  232. package/dist/chunk-NGKODS3J.cjs +52 -0
  233. package/dist/chunk-NGKODS3J.cjs.map +1 -0
  234. package/dist/chunk-NJVSKUL2.cjs +4 -0
  235. package/dist/chunk-NJVSKUL2.cjs.map +1 -0
  236. package/dist/chunk-NLQQHJ25.cjs +104 -0
  237. package/dist/chunk-NLQQHJ25.cjs.map +1 -0
  238. package/dist/chunk-NNHWH7ER.js +181 -0
  239. package/dist/chunk-NNHWH7ER.js.map +1 -0
  240. package/dist/chunk-NX67YIF3.js +3 -0
  241. package/dist/chunk-NX67YIF3.js.map +1 -0
  242. package/dist/chunk-OA6FWYZF.cjs +4 -0
  243. package/dist/chunk-OA6FWYZF.cjs.map +1 -0
  244. package/dist/chunk-OJDBSKC2.js +3 -0
  245. package/dist/chunk-OJDBSKC2.js.map +1 -0
  246. package/dist/chunk-OLPA44QJ.js +3 -0
  247. package/dist/chunk-OLPA44QJ.js.map +1 -0
  248. package/dist/chunk-OMH7ATOQ.js +3 -0
  249. package/dist/chunk-OMH7ATOQ.js.map +1 -0
  250. package/dist/chunk-OPR4TULG.js +3 -0
  251. package/dist/chunk-OPR4TULG.js.map +1 -0
  252. package/dist/chunk-OSX2GVZ2.cjs +34 -0
  253. package/dist/chunk-OSX2GVZ2.cjs.map +1 -0
  254. package/dist/chunk-OXQKE5EG.cjs +282 -0
  255. package/dist/chunk-OXQKE5EG.cjs.map +1 -0
  256. package/dist/chunk-P6E4QDJN.js +30 -0
  257. package/dist/chunk-P6E4QDJN.js.map +1 -0
  258. package/dist/chunk-PEMLIAPZ.cjs +64 -0
  259. package/dist/chunk-PEMLIAPZ.cjs.map +1 -0
  260. package/dist/chunk-PGYQ754I.js +3 -0
  261. package/dist/chunk-PGYQ754I.js.map +1 -0
  262. package/dist/chunk-PHKYIWE4.cjs +16 -0
  263. package/dist/chunk-PHKYIWE4.cjs.map +1 -0
  264. package/dist/chunk-PMTM26LL.js +3 -0
  265. package/dist/chunk-PMTM26LL.js.map +1 -0
  266. package/dist/chunk-PY4OEKNX.cjs +4 -0
  267. package/dist/chunk-PY4OEKNX.cjs.map +1 -0
  268. package/dist/chunk-PZS2EXDR.cjs +4 -0
  269. package/dist/chunk-PZS2EXDR.cjs.map +1 -0
  270. package/dist/chunk-QITJGSFA.js +210 -0
  271. package/dist/chunk-QITJGSFA.js.map +1 -0
  272. package/dist/chunk-QRHJEITQ.cjs +4 -0
  273. package/dist/chunk-QRHJEITQ.cjs.map +1 -0
  274. package/dist/chunk-QUFU5RJ7.cjs +4 -0
  275. package/dist/chunk-QUFU5RJ7.cjs.map +1 -0
  276. package/dist/chunk-QVQCKOBM.js +3 -0
  277. package/dist/chunk-QVQCKOBM.js.map +1 -0
  278. package/dist/chunk-R63TTR35.cjs +200 -0
  279. package/dist/chunk-R63TTR35.cjs.map +1 -0
  280. package/dist/chunk-RA42NMWV.cjs +4 -0
  281. package/dist/chunk-RA42NMWV.cjs.map +1 -0
  282. package/dist/chunk-RAZN6C5R.cjs +12 -0
  283. package/dist/chunk-RAZN6C5R.cjs.map +1 -0
  284. package/dist/chunk-REUFPWM7.cjs +233 -0
  285. package/dist/chunk-REUFPWM7.cjs.map +1 -0
  286. package/dist/chunk-RHETJOUM.cjs +4 -0
  287. package/dist/chunk-RHETJOUM.cjs.map +1 -0
  288. package/dist/chunk-RJIJVVXS.js +3 -0
  289. package/dist/chunk-RJIJVVXS.js.map +1 -0
  290. package/dist/chunk-RKVRCNMB.js +3 -0
  291. package/dist/chunk-RKVRCNMB.js.map +1 -0
  292. package/dist/chunk-SBV5MWEL.cjs +53 -0
  293. package/dist/chunk-SBV5MWEL.cjs.map +1 -0
  294. package/dist/chunk-SFB4YLCS.js +121 -0
  295. package/dist/chunk-SFB4YLCS.js.map +1 -0
  296. package/dist/chunk-SLPD47SR.js +3 -0
  297. package/dist/chunk-SLPD47SR.js.map +1 -0
  298. package/dist/chunk-SS3B6PHT.cjs +35 -0
  299. package/dist/chunk-SS3B6PHT.cjs.map +1 -0
  300. package/dist/chunk-SUCHGNYT.js +3 -0
  301. package/dist/chunk-SUCHGNYT.js.map +1 -0
  302. package/dist/chunk-SYVNY3AH.cjs +44 -0
  303. package/dist/chunk-SYVNY3AH.cjs.map +1 -0
  304. package/dist/chunk-T3SYREY4.js +29 -0
  305. package/dist/chunk-T3SYREY4.js.map +1 -0
  306. package/dist/chunk-T7N7DFQJ.js +198 -0
  307. package/dist/chunk-T7N7DFQJ.js.map +1 -0
  308. package/dist/chunk-TRCENAIY.cjs +4 -0
  309. package/dist/chunk-TRCENAIY.cjs.map +1 -0
  310. package/dist/chunk-TVENC6PH.js +186 -0
  311. package/dist/chunk-TVENC6PH.js.map +1 -0
  312. package/dist/chunk-U4T3Z3K7.cjs +325 -0
  313. package/dist/chunk-U4T3Z3K7.cjs.map +1 -0
  314. package/dist/chunk-UI2NXUML.cjs +187 -0
  315. package/dist/chunk-UI2NXUML.cjs.map +1 -0
  316. package/dist/chunk-UIFFNTUX.js +3 -0
  317. package/dist/chunk-UIFFNTUX.js.map +1 -0
  318. package/dist/chunk-V4GPQ6Y2.js +3 -0
  319. package/dist/chunk-V4GPQ6Y2.js.map +1 -0
  320. package/dist/chunk-VGTRKXF2.js +93 -0
  321. package/dist/chunk-VGTRKXF2.js.map +1 -0
  322. package/dist/chunk-VGWOIWRQ.cjs +202 -0
  323. package/dist/chunk-VGWOIWRQ.cjs.map +1 -0
  324. package/dist/chunk-VLCNNA76.cjs +4 -0
  325. package/dist/chunk-VLCNNA76.cjs.map +1 -0
  326. package/dist/chunk-VPAUN75Q.js +3 -0
  327. package/dist/chunk-VPAUN75Q.js.map +1 -0
  328. package/dist/chunk-VT237QF2.js +3 -0
  329. package/dist/chunk-VT237QF2.js.map +1 -0
  330. package/dist/chunk-VV4TZG5S.js +321 -0
  331. package/dist/chunk-VV4TZG5S.js.map +1 -0
  332. package/dist/chunk-VYK6MBL4.cjs +4 -0
  333. package/dist/chunk-VYK6MBL4.cjs.map +1 -0
  334. package/dist/chunk-W33CKW6Q.cjs +4 -0
  335. package/dist/chunk-W33CKW6Q.cjs.map +1 -0
  336. package/dist/chunk-W5VHATSR.cjs +31 -0
  337. package/dist/chunk-W5VHATSR.cjs.map +1 -0
  338. package/dist/chunk-W7YI5UT3.js +3 -0
  339. package/dist/chunk-W7YI5UT3.js.map +1 -0
  340. package/dist/chunk-WEQWU2IC.js +34 -0
  341. package/dist/chunk-WEQWU2IC.js.map +1 -0
  342. package/dist/chunk-WK4VXPPZ.cjs +104 -0
  343. package/dist/chunk-WK4VXPPZ.cjs.map +1 -0
  344. package/dist/chunk-WSA4LMWR.cjs +96 -0
  345. package/dist/chunk-WSA4LMWR.cjs.map +1 -0
  346. package/dist/chunk-WUIEZ6Z4.cjs +360 -0
  347. package/dist/chunk-WUIEZ6Z4.cjs.map +1 -0
  348. package/dist/chunk-WUKIJJG2.cjs +45 -0
  349. package/dist/chunk-WUKIJJG2.cjs.map +1 -0
  350. package/dist/chunk-WVFAQBS7.js +29 -0
  351. package/dist/chunk-WVFAQBS7.js.map +1 -0
  352. package/dist/chunk-X7RDNMN7.js +3 -0
  353. package/dist/chunk-X7RDNMN7.js.map +1 -0
  354. package/dist/chunk-X7XP5WBP.cjs +4 -0
  355. package/dist/chunk-X7XP5WBP.cjs.map +1 -0
  356. package/dist/chunk-XQAIEPAZ.js +104 -0
  357. package/dist/chunk-XQAIEPAZ.js.map +1 -0
  358. package/dist/chunk-XWKNE6DH.cjs +4 -0
  359. package/dist/chunk-XWKNE6DH.cjs.map +1 -0
  360. package/dist/chunk-Y6V6CBY5.js +23 -0
  361. package/dist/chunk-Y6V6CBY5.js.map +1 -0
  362. package/dist/chunk-Y6VDCZPB.js +62 -0
  363. package/dist/chunk-Y6VDCZPB.js.map +1 -0
  364. package/dist/chunk-YDRXBRW2.cjs +184 -0
  365. package/dist/chunk-YDRXBRW2.cjs.map +1 -0
  366. package/dist/chunk-YFS2LMG4.cjs +124 -0
  367. package/dist/chunk-YFS2LMG4.cjs.map +1 -0
  368. package/dist/chunk-YN6CBIIB.js +63 -0
  369. package/dist/chunk-YN6CBIIB.js.map +1 -0
  370. package/dist/chunk-YOJ2XNQX.cjs +4 -0
  371. package/dist/chunk-YOJ2XNQX.cjs.map +1 -0
  372. package/dist/chunk-YOOZB4RL.js +3 -0
  373. package/dist/chunk-YOOZB4RL.js.map +1 -0
  374. package/dist/chunk-YVU2M7MI.js +34 -0
  375. package/dist/chunk-YVU2M7MI.js.map +1 -0
  376. package/dist/chunk-YXBZRB5H.cjs +4 -0
  377. package/dist/chunk-YXBZRB5H.cjs.map +1 -0
  378. package/dist/chunk-Z3ZKFI2M.js +43 -0
  379. package/dist/chunk-Z3ZKFI2M.js.map +1 -0
  380. package/dist/chunk-Z5GLY4R3.js +112 -0
  381. package/dist/chunk-Z5GLY4R3.js.map +1 -0
  382. package/dist/chunk-Z5OMWAQX.js +3 -0
  383. package/dist/chunk-Z5OMWAQX.js.map +1 -0
  384. package/dist/chunk-Z7LGWNI7.js +38 -0
  385. package/dist/chunk-Z7LGWNI7.js.map +1 -0
  386. package/dist/chunk-ZCWKX4V6.cjs +38 -0
  387. package/dist/chunk-ZCWKX4V6.cjs.map +1 -0
  388. package/dist/chunk-ZE5RISBZ.cjs +4 -0
  389. package/dist/chunk-ZE5RISBZ.cjs.map +1 -0
  390. package/dist/chunk-ZH4F2P2G.js +3 -0
  391. package/dist/chunk-ZH4F2P2G.js.map +1 -0
  392. package/dist/chunk-ZJGFLJ2Z.cjs +4 -0
  393. package/dist/chunk-ZJGFLJ2Z.cjs.map +1 -0
  394. package/dist/chunk-ZKBHD27K.cjs +4 -0
  395. package/dist/chunk-ZKBHD27K.cjs.map +1 -0
  396. package/dist/chunk-ZQPLRNKX.cjs +4 -0
  397. package/dist/chunk-ZQPLRNKX.cjs.map +1 -0
  398. package/dist/chunk-ZQQABQMH.cjs +31 -0
  399. package/dist/chunk-ZQQABQMH.cjs.map +1 -0
  400. package/dist/chunk-ZXJQSFIA.js +200 -0
  401. package/dist/chunk-ZXJQSFIA.js.map +1 -0
  402. package/dist/developer-apps-zSQXWmEG.d.cts +294 -0
  403. package/dist/developer-apps-zSQXWmEG.d.ts +294 -0
  404. package/dist/entries/apps.cjs +13 -0
  405. package/dist/entries/apps.cjs.map +1 -0
  406. package/dist/entries/apps.d.cts +300 -0
  407. package/dist/entries/apps.d.ts +300 -0
  408. package/dist/entries/apps.js +4 -0
  409. package/dist/entries/apps.js.map +1 -0
  410. package/dist/entries/audio.cjs +13 -0
  411. package/dist/entries/audio.cjs.map +1 -0
  412. package/dist/entries/audio.d.cts +200 -0
  413. package/dist/entries/audio.d.ts +200 -0
  414. package/dist/entries/audio.js +4 -0
  415. package/dist/entries/audio.js.map +1 -0
  416. package/dist/entries/billing.cjs +13 -0
  417. package/dist/entries/billing.cjs.map +1 -0
  418. package/dist/entries/billing.d.cts +208 -0
  419. package/dist/entries/billing.d.ts +208 -0
  420. package/dist/entries/billing.js +4 -0
  421. package/dist/entries/billing.js.map +1 -0
  422. package/dist/entries/catalogs.cjs +13 -0
  423. package/dist/entries/catalogs.cjs.map +1 -0
  424. package/dist/entries/catalogs.d.cts +82 -0
  425. package/dist/entries/catalogs.d.ts +82 -0
  426. package/dist/entries/catalogs.js +4 -0
  427. package/dist/entries/catalogs.js.map +1 -0
  428. package/dist/entries/characters.cjs +45 -0
  429. package/dist/entries/characters.cjs.map +1 -0
  430. package/dist/entries/characters.d.cts +741 -0
  431. package/dist/entries/characters.d.ts +741 -0
  432. package/dist/entries/characters.js +4 -0
  433. package/dist/entries/characters.js.map +1 -0
  434. package/dist/entries/client.cjs +78 -0
  435. package/dist/entries/client.cjs.map +1 -0
  436. package/dist/entries/client.d.cts +147 -0
  437. package/dist/entries/client.d.ts +147 -0
  438. package/dist/entries/client.js +53 -0
  439. package/dist/entries/client.js.map +1 -0
  440. package/dist/entries/collections.cjs +13 -0
  441. package/dist/entries/collections.cjs.map +1 -0
  442. package/dist/entries/collections.d.cts +77 -0
  443. package/dist/entries/collections.d.ts +77 -0
  444. package/dist/entries/collections.js +4 -0
  445. package/dist/entries/collections.js.map +1 -0
  446. package/dist/entries/community.cjs +13 -0
  447. package/dist/entries/community.cjs.map +1 -0
  448. package/dist/entries/community.d.cts +87 -0
  449. package/dist/entries/community.d.ts +87 -0
  450. package/dist/entries/community.js +4 -0
  451. package/dist/entries/community.js.map +1 -0
  452. package/dist/entries/competitors.cjs +13 -0
  453. package/dist/entries/competitors.cjs.map +1 -0
  454. package/dist/entries/competitors.d.cts +96 -0
  455. package/dist/entries/competitors.d.ts +96 -0
  456. package/dist/entries/competitors.js +4 -0
  457. package/dist/entries/competitors.js.map +1 -0
  458. package/dist/entries/copilot.cjs +15 -0
  459. package/dist/entries/copilot.cjs.map +1 -0
  460. package/dist/entries/copilot.d.cts +296 -0
  461. package/dist/entries/copilot.d.ts +296 -0
  462. package/dist/entries/copilot.js +6 -0
  463. package/dist/entries/copilot.js.map +1 -0
  464. package/dist/entries/core.cjs +26 -0
  465. package/dist/entries/core.cjs.map +1 -0
  466. package/dist/entries/core.d.cts +3 -0
  467. package/dist/entries/core.d.ts +3 -0
  468. package/dist/entries/core.js +5 -0
  469. package/dist/entries/core.js.map +1 -0
  470. package/dist/entries/creatures.cjs +29 -0
  471. package/dist/entries/creatures.cjs.map +1 -0
  472. package/dist/entries/creatures.d.cts +594 -0
  473. package/dist/entries/creatures.d.ts +594 -0
  474. package/dist/entries/creatures.js +4 -0
  475. package/dist/entries/creatures.js.map +1 -0
  476. package/dist/entries/credits.cjs +13 -0
  477. package/dist/entries/credits.cjs.map +1 -0
  478. package/dist/entries/credits.d.cts +229 -0
  479. package/dist/entries/credits.d.ts +229 -0
  480. package/dist/entries/credits.js +4 -0
  481. package/dist/entries/credits.js.map +1 -0
  482. package/dist/entries/developer-apps.cjs +13 -0
  483. package/dist/entries/developer-apps.cjs.map +1 -0
  484. package/dist/entries/developer-apps.d.cts +3 -0
  485. package/dist/entries/developer-apps.d.ts +3 -0
  486. package/dist/entries/developer-apps.js +4 -0
  487. package/dist/entries/developer-apps.js.map +1 -0
  488. package/dist/entries/edit.cjs +34 -0
  489. package/dist/entries/edit.cjs.map +1 -0
  490. package/dist/entries/edit.d.cts +705 -0
  491. package/dist/entries/edit.d.ts +705 -0
  492. package/dist/entries/edit.js +5 -0
  493. package/dist/entries/edit.js.map +1 -0
  494. package/dist/entries/errors.cjs +93 -0
  495. package/dist/entries/errors.cjs.map +1 -0
  496. package/dist/entries/errors.d.cts +338 -0
  497. package/dist/entries/errors.d.ts +338 -0
  498. package/dist/entries/errors.js +4 -0
  499. package/dist/entries/errors.js.map +1 -0
  500. package/dist/entries/executions.cjs +21 -0
  501. package/dist/entries/executions.cjs.map +1 -0
  502. package/dist/entries/executions.d.cts +120 -0
  503. package/dist/entries/executions.d.ts +120 -0
  504. package/dist/entries/executions.js +4 -0
  505. package/dist/entries/executions.js.map +1 -0
  506. package/dist/entries/gallery.cjs +13 -0
  507. package/dist/entries/gallery.cjs.map +1 -0
  508. package/dist/entries/gallery.d.cts +85 -0
  509. package/dist/entries/gallery.d.ts +85 -0
  510. package/dist/entries/gallery.js +4 -0
  511. package/dist/entries/gallery.js.map +1 -0
  512. package/dist/entries/jobs.cjs +13 -0
  513. package/dist/entries/jobs.cjs.map +1 -0
  514. package/dist/entries/jobs.d.cts +252 -0
  515. package/dist/entries/jobs.d.ts +252 -0
  516. package/dist/entries/jobs.js +4 -0
  517. package/dist/entries/jobs.js.map +1 -0
  518. package/dist/entries/library.cjs +13 -0
  519. package/dist/entries/library.cjs.map +1 -0
  520. package/dist/entries/library.d.cts +109 -0
  521. package/dist/entries/library.d.ts +109 -0
  522. package/dist/entries/library.js +4 -0
  523. package/dist/entries/library.js.map +1 -0
  524. package/dist/entries/llm.cjs +13 -0
  525. package/dist/entries/llm.cjs.map +1 -0
  526. package/dist/entries/llm.d.cts +98 -0
  527. package/dist/entries/llm.d.ts +98 -0
  528. package/dist/entries/llm.js +4 -0
  529. package/dist/entries/llm.js.map +1 -0
  530. package/dist/entries/locations.cjs +25 -0
  531. package/dist/entries/locations.cjs.map +1 -0
  532. package/dist/entries/locations.d.cts +573 -0
  533. package/dist/entries/locations.d.ts +573 -0
  534. package/dist/entries/locations.js +4 -0
  535. package/dist/entries/locations.js.map +1 -0
  536. package/dist/entries/media.cjs +15 -0
  537. package/dist/entries/media.cjs.map +1 -0
  538. package/dist/entries/media.d.cts +548 -0
  539. package/dist/entries/media.d.ts +548 -0
  540. package/dist/entries/media.js +6 -0
  541. package/dist/entries/media.js.map +1 -0
  542. package/dist/entries/models.cjs +13 -0
  543. package/dist/entries/models.cjs.map +1 -0
  544. package/dist/entries/models.d.cts +92 -0
  545. package/dist/entries/models.d.ts +92 -0
  546. package/dist/entries/models.js +4 -0
  547. package/dist/entries/models.js.map +1 -0
  548. package/dist/entries/moodboards.cjs +21 -0
  549. package/dist/entries/moodboards.cjs.map +1 -0
  550. package/dist/entries/moodboards.d.cts +77 -0
  551. package/dist/entries/moodboards.d.ts +77 -0
  552. package/dist/entries/moodboards.js +4 -0
  553. package/dist/entries/moodboards.js.map +1 -0
  554. package/dist/entries/node-presets.cjs +13 -0
  555. package/dist/entries/node-presets.cjs.map +1 -0
  556. package/dist/entries/node-presets.d.cts +217 -0
  557. package/dist/entries/node-presets.d.ts +217 -0
  558. package/dist/entries/node-presets.js +4 -0
  559. package/dist/entries/node-presets.js.map +1 -0
  560. package/dist/entries/nodes.cjs +22 -0
  561. package/dist/entries/nodes.cjs.map +1 -0
  562. package/dist/entries/nodes.d.cts +18 -0
  563. package/dist/entries/nodes.d.ts +18 -0
  564. package/dist/entries/nodes.js +5 -0
  565. package/dist/entries/nodes.js.map +1 -0
  566. package/dist/entries/oauth.cjs +13 -0
  567. package/dist/entries/oauth.cjs.map +1 -0
  568. package/dist/entries/oauth.d.cts +69 -0
  569. package/dist/entries/oauth.d.ts +69 -0
  570. package/dist/entries/oauth.js +4 -0
  571. package/dist/entries/oauth.js.map +1 -0
  572. package/dist/entries/objects.cjs +29 -0
  573. package/dist/entries/objects.cjs.map +1 -0
  574. package/dist/entries/objects.d.cts +544 -0
  575. package/dist/entries/objects.d.ts +544 -0
  576. package/dist/entries/objects.js +4 -0
  577. package/dist/entries/objects.js.map +1 -0
  578. package/dist/entries/organizations.cjs +21 -0
  579. package/dist/entries/organizations.cjs.map +1 -0
  580. package/dist/entries/organizations.d.cts +164 -0
  581. package/dist/entries/organizations.d.ts +164 -0
  582. package/dist/entries/organizations.js +4 -0
  583. package/dist/entries/organizations.js.map +1 -0
  584. package/dist/entries/palettes.cjs +21 -0
  585. package/dist/entries/palettes.cjs.map +1 -0
  586. package/dist/entries/palettes.d.cts +69 -0
  587. package/dist/entries/palettes.d.ts +69 -0
  588. package/dist/entries/palettes.js +4 -0
  589. package/dist/entries/palettes.js.map +1 -0
  590. package/dist/entries/picker-catalogs.cjs +13 -0
  591. package/dist/entries/picker-catalogs.cjs.map +1 -0
  592. package/dist/entries/picker-catalogs.d.cts +148 -0
  593. package/dist/entries/picker-catalogs.d.ts +148 -0
  594. package/dist/entries/picker-catalogs.js +4 -0
  595. package/dist/entries/picker-catalogs.js.map +1 -0
  596. package/dist/entries/pipelines.cjs +13 -0
  597. package/dist/entries/pipelines.cjs.map +1 -0
  598. package/dist/entries/pipelines.d.cts +255 -0
  599. package/dist/entries/pipelines.d.ts +255 -0
  600. package/dist/entries/pipelines.js +4 -0
  601. package/dist/entries/pipelines.js.map +1 -0
  602. package/dist/entries/projects.cjs +13 -0
  603. package/dist/entries/projects.cjs.map +1 -0
  604. package/dist/entries/projects.d.cts +49 -0
  605. package/dist/entries/projects.d.ts +49 -0
  606. package/dist/entries/projects.js +4 -0
  607. package/dist/entries/projects.js.map +1 -0
  608. package/dist/entries/prompt-helper.cjs +13 -0
  609. package/dist/entries/prompt-helper.cjs.map +1 -0
  610. package/dist/entries/prompt-helper.d.cts +73 -0
  611. package/dist/entries/prompt-helper.d.ts +73 -0
  612. package/dist/entries/prompt-helper.js +4 -0
  613. package/dist/entries/prompt-helper.js.map +1 -0
  614. package/dist/entries/recast.cjs +17 -0
  615. package/dist/entries/recast.cjs.map +1 -0
  616. package/dist/entries/recast.d.cts +229 -0
  617. package/dist/entries/recast.d.ts +229 -0
  618. package/dist/entries/recast.js +4 -0
  619. package/dist/entries/recast.js.map +1 -0
  620. package/dist/entries/reduce.cjs +13 -0
  621. package/dist/entries/reduce.cjs.map +1 -0
  622. package/dist/entries/reduce.d.cts +56 -0
  623. package/dist/entries/reduce.d.ts +56 -0
  624. package/dist/entries/reduce.js +4 -0
  625. package/dist/entries/reduce.js.map +1 -0
  626. package/dist/entries/saved-posts.cjs +13 -0
  627. package/dist/entries/saved-posts.cjs.map +1 -0
  628. package/dist/entries/saved-posts.d.cts +33 -0
  629. package/dist/entries/saved-posts.d.ts +33 -0
  630. package/dist/entries/saved-posts.js +4 -0
  631. package/dist/entries/saved-posts.js.map +1 -0
  632. package/dist/entries/scene3d.cjs +17 -0
  633. package/dist/entries/scene3d.cjs.map +1 -0
  634. package/dist/entries/scene3d.d.cts +131 -0
  635. package/dist/entries/scene3d.d.ts +131 -0
  636. package/dist/entries/scene3d.js +4 -0
  637. package/dist/entries/scene3d.js.map +1 -0
  638. package/dist/entries/sessions.cjs +13 -0
  639. package/dist/entries/sessions.cjs.map +1 -0
  640. package/dist/entries/sessions.d.cts +122 -0
  641. package/dist/entries/sessions.d.ts +122 -0
  642. package/dist/entries/sessions.js +4 -0
  643. package/dist/entries/sessions.js.map +1 -0
  644. package/dist/entries/shots.cjs +13 -0
  645. package/dist/entries/shots.cjs.map +1 -0
  646. package/dist/entries/shots.d.cts +78 -0
  647. package/dist/entries/shots.d.ts +78 -0
  648. package/dist/entries/shots.js +4 -0
  649. package/dist/entries/shots.js.map +1 -0
  650. package/dist/entries/studio.cjs +22 -0
  651. package/dist/entries/studio.cjs.map +1 -0
  652. package/dist/entries/studio.d.cts +281 -0
  653. package/dist/entries/studio.d.ts +281 -0
  654. package/dist/entries/studio.js +5 -0
  655. package/dist/entries/studio.js.map +1 -0
  656. package/dist/entries/templates.cjs +13 -0
  657. package/dist/entries/templates.cjs.map +1 -0
  658. package/dist/entries/templates.d.cts +110 -0
  659. package/dist/entries/templates.d.ts +110 -0
  660. package/dist/entries/templates.js +4 -0
  661. package/dist/entries/templates.js.map +1 -0
  662. package/dist/entries/tutorials.cjs +13 -0
  663. package/dist/entries/tutorials.cjs.map +1 -0
  664. package/dist/entries/tutorials.d.cts +63 -0
  665. package/dist/entries/tutorials.d.ts +63 -0
  666. package/dist/entries/tutorials.js +4 -0
  667. package/dist/entries/tutorials.js.map +1 -0
  668. package/dist/entries/uploads.cjs +13 -0
  669. package/dist/entries/uploads.cjs.map +1 -0
  670. package/dist/entries/uploads.d.cts +44 -0
  671. package/dist/entries/uploads.d.ts +44 -0
  672. package/dist/entries/uploads.js +4 -0
  673. package/dist/entries/uploads.js.map +1 -0
  674. package/dist/entries/video-pro.cjs +13 -0
  675. package/dist/entries/video-pro.cjs.map +1 -0
  676. package/dist/entries/video-pro.d.cts +60 -0
  677. package/dist/entries/video-pro.d.ts +60 -0
  678. package/dist/entries/video-pro.js +4 -0
  679. package/dist/entries/video-pro.js.map +1 -0
  680. package/dist/entries/voices.cjs +13 -0
  681. package/dist/entries/voices.cjs.map +1 -0
  682. package/dist/entries/voices.d.cts +498 -0
  683. package/dist/entries/voices.d.ts +498 -0
  684. package/dist/entries/voices.js +4 -0
  685. package/dist/entries/voices.js.map +1 -0
  686. package/dist/entries/webhooks.cjs +21 -0
  687. package/dist/entries/webhooks.cjs.map +1 -0
  688. package/dist/entries/webhooks.d.cts +64 -0
  689. package/dist/entries/webhooks.d.ts +64 -0
  690. package/dist/entries/webhooks.js +4 -0
  691. package/dist/entries/webhooks.js.map +1 -0
  692. package/dist/entries/workflows.cjs +13 -0
  693. package/dist/entries/workflows.cjs.map +1 -0
  694. package/dist/entries/workflows.d.cts +393 -0
  695. package/dist/entries/workflows.d.ts +393 -0
  696. package/dist/entries/workflows.js +4 -0
  697. package/dist/entries/workflows.js.map +1 -0
  698. package/dist/entries/workspaces.cjs +13 -0
  699. package/dist/entries/workspaces.cjs.map +1 -0
  700. package/dist/entries/workspaces.d.cts +124 -0
  701. package/dist/entries/workspaces.d.ts +124 -0
  702. package/dist/entries/workspaces.js +4 -0
  703. package/dist/entries/workspaces.js.map +1 -0
  704. package/dist/index.cjs +501 -4618
  705. package/dist/index.cjs.map +1 -1
  706. package/dist/index.d.cts +66 -9651
  707. package/dist/index.d.ts +66 -9651
  708. package/dist/index.js +100 -4511
  709. package/dist/index.js.map +1 -1
  710. package/dist/nodes-BPvrAoUs.d.cts +1264 -0
  711. package/dist/nodes-C2zu3uqn.d.ts +1264 -0
  712. package/dist/studio-productions-DUHvdSvk.d.cts +572 -0
  713. package/dist/studio-productions-vbCNSbtf.d.ts +572 -0
  714. package/dist/webhooks-BJawEIz8.d.ts +198 -0
  715. package/dist/webhooks-Dn_DtNTD.d.cts +198 -0
  716. package/package.json +253 -3
package/dist/index.js CHANGED
@@ -1,4513 +1,102 @@
1
- export { OUTPUT_BEARING_NODE_STATUSES, nodeStateMayCarryOutput } from '@nodaro/shared/workflow';
2
- import { nodeRunRoute, NODE_TYPES_WITHOUT_RUN_ROUTE, NODE_RUN_ROUTES } from '@nodaro/shared/nodes';
3
- export { PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY } from '@nodaro/shared/nodes';
4
- import { SOCIAL_POST_NODE_PLATFORM } from '@nodaro/shared/social';
5
- import { SCENE3D_V2_LIMITS } from '@nodaro/shared/scene3d';
6
- import { buildPersonHints } from '@nodaro/prompts/person';
7
- export { PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, buildPersonHints } from '@nodaro/prompts/person';
8
- export { CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_STYLES, OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, CREATURE_ATTACH_COLUMNS, LOCATION_ASSET_TYPES, LOCATION_ATTACH_COLUMNS, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, SURROUND_DIRECTIONS } from '@nodaro/shared/entities';
9
- import { resolveEditPlanSources, describeAudioSyncOffsetIssue, transcriptSpeakerLabels, remapTranscriptThroughEdl } from '@nodaro/shared/edl';
10
- export { unwrapEditPlanOutput } from '@nodaro/shared/edl';
11
- import { WORKSPACE_HEADER } from '@nodaro/shared/organizations';
12
- export { USAGE_GROUP_BYS, WORKSPACE_HEADER } from '@nodaro/shared/organizations';
13
- export { RECAST_SEGMENT_PACKS } from '@nodaro/shared/apps';
14
-
15
- // src/binary-response.ts
16
- async function readBinaryResponse(response, maxBytes) {
17
- const advertised = response.headers.get("content-length");
18
- if (advertised !== null && (!/^\d+$/.test(advertised) || Number(advertised) > maxBytes)) {
19
- await response.body?.cancel();
20
- throw new Error("Binary response exceeds its declared size limit");
21
- }
22
- if (!response.body) return new ArrayBuffer(0);
23
- const reader = response.body.getReader();
24
- const chunks = [];
25
- let length = 0;
26
- try {
27
- while (true) {
28
- const next = await reader.read();
29
- if (next.done) break;
30
- length += next.value.byteLength;
31
- if (length > maxBytes) {
32
- await reader.cancel();
33
- throw new Error("Binary response exceeds its declared size limit");
34
- }
35
- chunks.push(next.value);
36
- }
37
- } finally {
38
- reader.releaseLock();
39
- }
40
- const bytes = new Uint8Array(length);
41
- let offset = 0;
42
- for (const chunk of chunks) {
43
- bytes.set(chunk, offset);
44
- offset += chunk.byteLength;
45
- }
46
- return bytes.buffer;
47
- }
48
-
49
- // src/errors.ts
50
- var NodaroError = class extends Error {
51
- constructor(message, code, status) {
52
- super(message);
53
- this.code = code;
54
- this.status = status;
55
- this.name = "NodaroError";
56
- }
57
- code;
58
- status;
59
- };
60
- var UnauthorizedError = class extends NodaroError {
61
- constructor(message = "Authentication required") {
62
- super(message, "unauthorized", 401);
63
- this.name = "UnauthorizedError";
64
- }
65
- };
66
- var ForbiddenError = class extends NodaroError {
67
- constructor(message = "Forbidden", missingScope) {
68
- super(message, "forbidden", 403);
69
- this.missingScope = missingScope;
70
- this.name = "ForbiddenError";
71
- }
72
- missingScope;
73
- };
74
- var NotFoundError = class extends NodaroError {
75
- constructor(message = "Not found") {
76
- super(message, "not_found", 404);
77
- this.name = "NotFoundError";
78
- }
79
- };
80
- var RateLimitedError = class extends NodaroError {
81
- constructor(message = "Rate limited") {
82
- super(message, "rate_limited", 429);
83
- this.name = "RateLimitedError";
84
- }
85
- };
86
- var InsufficientCreditsError = class extends NodaroError {
87
- constructor(message = "Insufficient credits", required, available) {
88
- super(message, "insufficient_credits", 402);
89
- this.required = required;
90
- this.available = available;
91
- this.name = "InsufficientCreditsError";
92
- }
93
- required;
94
- available;
95
- };
96
- var StorageExceededError = class extends NodaroError {
97
- constructor(message = "Storage exceeded", limitBytes) {
98
- super(message, "storage_exceeded", 413);
99
- this.limitBytes = limitBytes;
100
- this.name = "StorageExceededError";
101
- }
102
- limitBytes;
103
- };
104
- var WorkflowConflictError = class extends NodaroError {
105
- constructor(message = "Workflow was updated by another writer", currentUpdatedAt, currentVersion, currentRecord, code = "workflow_conflict") {
106
- super(message, code, 409);
107
- this.currentUpdatedAt = currentUpdatedAt;
108
- this.currentVersion = currentVersion;
109
- this.currentRecord = currentRecord;
110
- this.name = "WorkflowConflictError";
111
- }
112
- currentUpdatedAt;
113
- currentVersion;
114
- currentRecord;
115
- };
116
- var StudioOpError = class extends NodaroError {
117
- constructor(message, code, status, opIndex) {
118
- super(message, code, status);
119
- this.opIndex = opIndex;
120
- this.name = "StudioOpError";
121
- }
122
- opIndex;
123
- };
124
- var CONTINUATION_REFUSAL_CODES = /* @__PURE__ */ new Set([
125
- "already_running",
126
- "continuation_superseded",
127
- "render_final_already_rendered"
128
- ]);
129
- var ContinuationRefusedError = class extends NodaroError {
130
- constructor(message, code, jobId) {
131
- super(message, code, 409);
132
- this.jobId = jobId;
133
- this.name = "ContinuationRefusedError";
134
- }
135
- jobId;
136
- };
137
- var JobBlockedError = class extends NodaroError {
138
- constructor(message = "Blocked by this deployment's content policy") {
139
- super(message, "job_blocked", 422);
140
- this.name = "JobBlockedError";
141
- }
142
- };
143
- var JobFailedError = class extends NodaroError {
144
- constructor(message, jobId, jobStatus = "failed") {
145
- super(message, "job_failed", 0);
146
- this.jobId = jobId;
147
- this.jobStatus = jobStatus;
148
- this.name = "JobFailedError";
149
- }
150
- jobId;
151
- jobStatus;
152
- };
153
- var JobTimeoutError = class extends NodaroError {
154
- constructor(message, jobId, timeoutMs) {
155
- super(message, "job_timeout", 0);
156
- this.jobId = jobId;
157
- this.timeoutMs = timeoutMs;
158
- this.name = "JobTimeoutError";
159
- }
160
- jobId;
161
- timeoutMs;
162
- };
163
- var JobAbortedError = class extends NodaroError {
164
- constructor(message = "Aborted", jobId) {
165
- super(message, "job_aborted", 0);
166
- this.jobId = jobId;
167
- this.name = "JobAbortedError";
168
- }
169
- jobId;
170
- };
171
- var StudioPreviewUnavailable = class extends NodaroError {
172
- constructor(message = "This deployment does not preview operation batches; nothing was sent") {
173
- super(message, "studio_preview_unavailable", 0);
174
- this.name = "StudioPreviewUnavailable";
175
- }
176
- };
177
- var StudioPreviewAppliedError = class extends NodaroError {
178
- constructor(applied, message = applied ? "Asked for a preview and this deployment APPLIED the batch; the change is written \u2014 see `applied`" : "Asked for a preview and this deployment answered with neither one nor a body to read; the batch may have been applied \u2014 re-read the production before deciding anything") {
179
- super(message, "studio_preview_applied", 0);
180
- this.applied = applied;
181
- this.name = "StudioPreviewAppliedError";
182
- }
183
- applied;
184
- };
185
- var JobHeldError = class extends NodaroError {
186
- constructor(message, jobId) {
187
- super(message, "job_held", 0);
188
- this.jobId = jobId;
189
- this.name = "JobHeldError";
190
- }
191
- jobId;
192
- };
193
- function throwFromResponse(status, body) {
194
- const code = body.error?.code ?? "internal_error";
195
- const message = body.error?.message ?? "Request failed";
196
- if (status === 401) throw new UnauthorizedError(message);
197
- if (status === 409 && (code === "workflow_conflict" || code === "production_busy")) {
198
- throw new WorkflowConflictError(
199
- message,
200
- body.error?.currentUpdatedAt,
201
- body.error?.currentVersion,
202
- body.error?.currentRecord,
203
- code
204
- );
205
- }
206
- if (status >= 400 && status < 500 && typeof body.error?.opIndex === "number") {
207
- throw new StudioOpError(message, code, status, body.error.opIndex);
208
- }
209
- if (status === 409 && CONTINUATION_REFUSAL_CODES.has(code) && typeof body.jobId === "string") {
210
- throw new ContinuationRefusedError(message, code, body.jobId);
211
- }
212
- if (status === 422 && code === "job_blocked") throw new JobBlockedError(message);
213
- if (status === 403 && code === "insufficient_scope") {
214
- throw new ForbiddenError(message, body.error?.missingScope);
215
- }
216
- if (status === 403) throw new ForbiddenError(message);
217
- if (status === 404) throw new NotFoundError(body.error?.message ?? (typeof body.message === "string" ? body.message : void 0));
218
- if (status === 429) throw new RateLimitedError(message);
219
- if (status === 402) {
220
- throw new InsufficientCreditsError(message, body.error?.required, body.error?.available);
221
- }
222
- if (status === 413) throw new StorageExceededError(message, body.error?.limitBytes);
223
- throw new NodaroError(message, code, status);
224
- }
225
-
226
- // src/resources/workflows.ts
227
- var WorkflowCollaboratorsResource = class {
228
- constructor(client) {
229
- this.client = client;
230
- }
231
- client;
232
- /** List a workflow's collaborators (id, name, avatar, role — never email). */
233
- list(workflowId) {
234
- return this.client.request(
235
- "GET",
236
- `/v1/workflows/${encodeURIComponent(workflowId)}/collaborators`
237
- );
238
- }
239
- /** Add a collaborator by `userId` OR `email` (exactly one), at the given role. */
240
- add(workflowId, input) {
241
- return this.client.request(
242
- "POST",
243
- `/v1/workflows/${encodeURIComponent(workflowId)}/collaborators`,
244
- { body: input }
245
- );
246
- }
247
- /** Change a collaborator's role. */
248
- update(workflowId, userId, input) {
249
- return this.client.request(
250
- "PATCH",
251
- `/v1/workflows/${encodeURIComponent(workflowId)}/collaborators/${encodeURIComponent(userId)}`,
252
- { body: input }
253
- );
254
- }
255
- /** Remove a collaborator — or yourself. Returns `{ success: true }`. */
256
- remove(workflowId, userId) {
257
- return this.client.request(
258
- "DELETE",
259
- `/v1/workflows/${encodeURIComponent(workflowId)}/collaborators/${encodeURIComponent(userId)}`
260
- );
261
- }
262
- };
263
- var WorkflowsResource = class {
264
- constructor(client) {
265
- this.client = client;
266
- this.collaborators = new WorkflowCollaboratorsResource(client);
267
- }
268
- client;
269
- /** The people this workflow is shared with. See {@link WorkflowCollaboratorsResource}. */
270
- collaborators;
271
- /** List workflows for a project. Returns metadata only — `nodes`/`edges` are not included. */
272
- list(params) {
273
- return this.client.request(
274
- "GET",
275
- `/v1/projects/${encodeURIComponent(params.projectId)}/workflows`
276
- );
277
- }
278
- /** Get a workflow including its full nodes/edges/settings. */
279
- get(id) {
280
- return this.client.request("GET", `/v1/workflows/${encodeURIComponent(id)}`);
281
- }
282
- /**
283
- * Get a PUBLICLY-SHARED workflow by id (`GET /v1/public/workflows/:id`) — the
284
- * unauthenticated share-by-link read. Returns the workflow's nodes/edges/
285
- * settings ONLY when it's opted into sharing server-side (`settings.studio.shared
286
- * === true`); otherwise the route 404s (→ `NotFoundError`). No auth required —
287
- * a share viewer has no session; the SDK omits the bearer when no token exists.
288
- */
289
- getPublic(id) {
290
- return this.client.request("GET", `/v1/public/workflows/${encodeURIComponent(id)}`);
291
- }
292
- /**
293
- * Create a workflow under a project. Returns the full record.
294
- * NOTE: server route is `POST /v1/projects/:projectId/workflows`.
295
- */
296
- create(input) {
297
- const { projectId, ...body } = input;
298
- return this.client.request(
299
- "POST",
300
- `/v1/projects/${encodeURIComponent(projectId)}/workflows`,
301
- { body }
302
- );
303
- }
304
- /** Patch a workflow. Returns the full updated record. */
305
- update(id, input) {
306
- return this.client.request(
307
- "PATCH",
308
- `/v1/workflows/${encodeURIComponent(id)}`,
309
- { body: input }
310
- );
311
- }
312
- /** Delete a workflow. Returns `{ success: true }`. Throws `NotFoundError`
313
- * when the id doesn't exist or isn't yours (the delete is not silent). */
314
- delete(id) {
315
- return this.client.request("DELETE", `/v1/workflows/${encodeURIComponent(id)}`);
316
- }
317
- /**
318
- * Run a workflow. Returns the executionId for polling via
319
- * `client.executions.get(executionId)`.
320
- */
321
- run(id, params = {}) {
322
- return this.client.request(
323
- "POST",
324
- `/v1/workflows/${encodeURIComponent(id)}/run`,
325
- { body: params }
326
- );
327
- }
328
- /**
329
- * Render final (`renderFinal` on `POST /v1/workflows/:id/run`): run the
330
- * render at Final for this run only, and every node after it, continuing the
331
- * execution that stopped at its preview. The server derives the nodes and
332
- * the override — send nothing else. Quote it first with
333
- * {@link estimateRenderFinal}. Refused with `render_final_node_not_found`,
334
- * `render_final_not_a_render`, or a continuation code (see `run`); a run
335
- * its payer cannot cover throws `InsufficientCreditsError` (with `required`
336
- * and, when it is yours to see, `available`) before any execution exists.
337
- */
338
- renderFinal(id, params) {
339
- return this.client.request("POST", `/v1/workflows/${encodeURIComponent(id)}/run`, {
340
- body: {
341
- renderFinal: { renderNodeId: params.renderNodeId },
342
- continueFromExecutionId: params.continueFromExecutionId
343
- }
344
- });
345
- }
346
- /**
347
- * Quote a Render final (`POST /v1/workflows/:id/render-final/estimate`): the
348
- * nodes it will run, the override it runs with and its estimated credits.
349
- * Nothing is created or charged.
350
- */
351
- estimateRenderFinal(id, params) {
352
- return this.client.request("POST", `/v1/workflows/${encodeURIComponent(id)}/render-final/estimate`, {
353
- body: { renderNodeId: params.renderNodeId, continueFromExecutionId: params.continueFromExecutionId }
354
- });
355
- }
356
- /**
357
- * Export a workflow as a portable JSON bundle.
358
- * Pass `opts.assets = true` to include character/object/location entity data.
359
- */
360
- export(workflowId, opts) {
361
- return this.client.request(
362
- "GET",
363
- `/v1/workflows/${encodeURIComponent(workflowId)}/export`,
364
- { query: { assets: opts?.assets ?? false } }
365
- );
366
- }
367
- /**
368
- * Import a `WorkflowExport` bundle into the specified project.
369
- * Re-creates any bundled assets (characters, objects, creatures, locations)
370
- * under your account, and re-points BOTH the entity nodes and every `@`-chip
371
- * (`ConnectedReference`) bound in the graph at the rows it created.
372
- * Media the bundle references on other hosts is copied onto this instance's
373
- * storage where reachable; a bundled entity's images are copied whoever
374
- * hosts them, because they are the exporter's bytes and their lifecycle is
375
- * not yours. `importReport` says what was copied, what could not be reached
376
- * and what was skipped (and why); `assetIdMap` maps each bundled entity id
377
- * to the row created for it (for chips you hold outside the graph), and
378
- * `assetsSkipped` names the entities your storage quota left uncreated —
379
- * the workflow itself still lands.
380
- */
381
- import(input) {
382
- const { projectId, ...workflowJson } = input;
383
- return this.client.request("POST", "/v1/workflows/import", {
384
- body: { projectId, workflow_json: workflowJson }
385
- });
386
- }
387
- /**
388
- * Set a workflow's visibility — `"private"` (creator + explicit collaborators)
389
- * or `"workspace"` (everyone in its workspace). Only the creator or a workspace
390
- * admin may change it; anyone else gets HTTP 403. Thin wrapper over `update()`:
391
- * the visibility lever lives on `PATCH /v1/workflows/:id`.
392
- */
393
- setVisibility(id, visibility) {
394
- return this.client.request("PATCH", `/v1/workflows/${encodeURIComponent(id)}`, {
395
- body: { visibility }
396
- });
397
- }
398
- /**
399
- * Move a workflow to another project (`POST /v1/workflows/:id/move`); its folder
400
- * is cleared. When the move takes the workflow out of a workspace, collaborator
401
- * grants that came from that workspace are dropped and returned as
402
- * `droppedCollaborators`.
403
- */
404
- move(id, params) {
405
- return this.client.request("POST", `/v1/workflows/${encodeURIComponent(id)}/move`, {
406
- body: params
407
- });
408
- }
409
- /**
410
- * Workflows other people shared with you (`GET /v1/workflows/shared-with-me`) —
411
- * grants on work that is NOT in a workspace you belong to (workspace work already
412
- * shows in that workspace's own lists). Each carries the `grantedRole` you hold.
413
- * Empty when the organizations feature is off server-side.
414
- */
415
- sharedWithMe() {
416
- return this.client.request("GET", "/v1/workflows/shared-with-me");
417
- }
418
- };
419
-
420
- // src/resources/projects.ts
421
- var ProjectsResource = class {
422
- constructor(client) {
423
- this.client = client;
424
- }
425
- client;
426
- /** List the authenticated user's projects. */
427
- list() {
428
- return this.client.request("GET", "/v1/projects");
429
- }
430
- /** Get a project by ID. */
431
- get(id) {
432
- return this.client.request("GET", `/v1/projects/${encodeURIComponent(id)}`);
433
- }
434
- /** Create a new project. */
435
- create(input) {
436
- return this.client.request("POST", "/v1/projects", { body: input });
437
- }
438
- /** Update a project. At least one field must be provided. */
439
- update(id, input) {
440
- return this.client.request(
441
- "PATCH",
442
- `/v1/projects/${encodeURIComponent(id)}`,
443
- { body: input }
444
- );
445
- }
446
- /** Delete a project. Returns `{ success: true }`. */
447
- delete(id) {
448
- return this.client.request("DELETE", `/v1/projects/${encodeURIComponent(id)}`);
449
- }
450
- };
451
-
452
- // src/resources/sessions.ts
453
- var SessionsResource = class {
454
- constructor(client) {
455
- this.client = client;
456
- }
457
- client;
458
- /**
459
- * Create a session. Send its `id` as `sessionId` on a generation request
460
- * (`nodes.run("generate-image", { sessionId, … })`, video, speech, music) and
461
- * the job is born in it.
462
- */
463
- create(input) {
464
- return this.client.request("POST", "/v1/sessions", { body: input });
465
- }
466
- /** Your sessions, newest first. */
467
- list(params = {}) {
468
- const query = {};
469
- if (params.projectId) query.projectId = params.projectId;
470
- if (params.tool) query.tool = params.tool;
471
- if (params.includeArchived) query.includeArchived = "true";
472
- if (params.limit !== void 0) query.limit = String(params.limit);
473
- if (params.cursor) query.cursor = params.cursor;
474
- return this.client.request("GET", "/v1/sessions", { query });
475
- }
476
- get(id) {
477
- return this.client.request("GET", `/v1/sessions/${encodeURIComponent(id)}`);
478
- }
479
- /** Rename or archive a session. Its project cannot change. */
480
- update(id, input) {
481
- return this.client.request("PATCH", `/v1/sessions/${encodeURIComponent(id)}`, { body: input });
482
- }
483
- /** Delete a session and its links. Its jobs are kept, and stay in every other session holding them. */
484
- delete(id) {
485
- return this.client.request("DELETE", `/v1/sessions/${encodeURIComponent(id)}`);
486
- }
487
- /** The session's items, born-in and imported, newest first. */
488
- items(id, params = {}) {
489
- const query = {};
490
- if (params.limit !== void 0) query.limit = String(params.limit);
491
- if (params.cursor) query.cursor = params.cursor;
492
- return this.client.request("GET", `/v1/sessions/${encodeURIComponent(id)}/items`, { query });
493
- }
494
- /**
495
- * Import some of your own jobs into a session — a link, not a copy (up to 100
496
- * a call). All-or-nothing: if any id is not one of your jobs, nothing is
497
- * imported and the call fails with 404. Items already there are left as they are.
498
- */
499
- importItems(id, input) {
500
- return this.client.request("POST", `/v1/sessions/${encodeURIComponent(id)}/items`, { body: input });
501
- }
502
- /** Remove one item from a session. Only the link goes: the job, and every other session holding it, stay. */
503
- removeItem(id, jobId) {
504
- return this.client.request(
505
- "DELETE",
506
- `/v1/sessions/${encodeURIComponent(id)}/items/${encodeURIComponent(jobId)}`
507
- );
508
- }
509
- };
510
-
511
- // src/resources/jobs.ts
512
- var JobsResource = class {
513
- constructor(client) {
514
- this.client = client;
515
- }
516
- client;
517
- /** Get a single job by ID. */
518
- get(id) {
519
- return this.client.request("GET", `/v1/jobs/${encodeURIComponent(id)}`);
520
- }
521
- /**
522
- * Your jobs, newest first (`GET /v1/jobs`), cursor-paginated. `type` and
523
- * `origin` filter on the job's own `input_data`, which every job carries —
524
- * a client app lists its runs with `{ type: "llm-structured", origin: "studio" }`.
525
- */
526
- list(params = {}) {
527
- return this.client.request("GET", "/v1/jobs", { query: { ...params } });
528
- }
529
- /**
530
- * Get the lean status of a single job (poll-loop friendly).
531
- * Hits `GET /v1/jobs/:id/status` — returns only id/status/progress/
532
- * output_data/error_message, with far less wire/CPU cost than `get()`.
533
- * Same auth + ownership semantics as {@link get}.
534
- */
535
- getStatus(id) {
536
- return this.client.request(
537
- "GET",
538
- `/v1/jobs/${encodeURIComponent(id)}/status`
539
- );
540
- }
541
- /**
542
- * Cancel a job. Server route is `POST /v1/jobs/:jobId/cancel`.
543
- * Refunds any reserved credit holds.
544
- */
545
- cancel(id) {
546
- return this.client.request(
547
- "POST",
548
- `/v1/jobs/${encodeURIComponent(id)}/cancel`
549
- );
550
- }
551
- /**
552
- * Delete a job and the private media it produced. Server route is
553
- * `DELETE /v1/jobs/:jobId`. Only the job's owner (or an admin) may delete it;
554
- * a job that is still running is deleted as-is — cancel it first when its
555
- * worker should stop ({@link cancel}).
556
- */
557
- delete(id) {
558
- return this.client.request(
559
- "DELETE",
560
- `/v1/jobs/${encodeURIComponent(id)}`
561
- );
562
- }
563
- };
564
-
565
- // src/resources/video-pro.ts
566
- var VideoProResource = class {
567
- constructor(client) {
568
- this.client = client;
569
- }
570
- client;
571
- /** Gracefully stop a running generate-video-pro job (keep + deliver the
572
- * completed segments; refund the rest). */
573
- stop(jobId) {
574
- return this.client.request(
575
- "POST",
576
- `/v1/generate-video-pro/${encodeURIComponent(jobId)}/stop`
577
- );
578
- }
579
- /** Continue a stopped/failed/completed run from a segment (a NEW job).
580
- * Named `continueRun` because `continue` is a reserved word. */
581
- continueRun(jobId, opts) {
582
- return this.client.request("POST", "/v1/generate-video-pro/continue", {
583
- body: {
584
- fromJobId: jobId,
585
- ...opts?.fromSegment !== void 0 ? { fromSegment: opts.fromSegment } : {}
586
- }
587
- });
588
- }
589
- };
590
- var ExecutionsResource = class {
591
- constructor(client) {
592
- this.client = client;
593
- }
594
- client;
595
- /** Get an execution by ID. Falls back to standalone single-node jobs server-side. */
596
- get(id) {
597
- return this.client.request(
598
- "GET",
599
- `/v1/workflow-executions/${encodeURIComponent(id)}`
600
- );
601
- }
602
- /** List executions for a workflow. Merges workflow_executions + standalone single-node jobs. */
603
- listForWorkflow(workflowId, params = {}) {
604
- return this.client.request(
605
- "GET",
606
- `/v1/workflows/${encodeURIComponent(workflowId)}/executions`,
607
- {
608
- query: {
609
- limit: params.limit,
610
- cursor: params.cursor,
611
- status: params.status,
612
- source: params.source
613
- }
614
- }
615
- );
616
- }
617
- /** Cancel an execution. Returns `{ success: true }`. */
618
- cancel(id, params = {}) {
619
- return this.client.request(
620
- "POST",
621
- `/v1/workflow-executions/${encodeURIComponent(id)}/cancel`,
622
- { body: params }
623
- );
624
- }
625
- };
626
- var DEFAULT_POLL_MS = 2e3;
627
- var DEFAULT_MAX_MS = 15 * 60 * 1e3;
628
- var sleep = (ms, signal) => new Promise((resolve, reject) => {
629
- if (signal?.aborted) {
630
- reject(new JobAbortedError());
631
- return;
632
- }
633
- const timer = setTimeout(() => {
634
- signal?.removeEventListener("abort", onAbort);
635
- resolve();
636
- }, ms);
637
- function onAbort() {
638
- clearTimeout(timer);
639
- reject(new JobAbortedError());
640
- }
641
- signal?.addEventListener("abort", onAbort, { once: true });
642
- });
643
- function notRunnable(type, why) {
644
- return new NodaroError(`Node type "${type}" has no route of its own to run it directly: ${why}.`, "node_not_runnable", 0);
645
- }
646
- var isRouteNotFound = (err) => err instanceof NotFoundError && /^Route\b.*\bnot found\b/i.test(err.message);
647
- function extractJobId(result, label) {
648
- if (result && typeof result === "object" && "jobId" in result) {
649
- const jobId = result.jobId;
650
- if (typeof jobId === "string") return jobId;
651
- }
652
- throw new JobFailedError(`${label} did not return a jobId`, "");
653
- }
654
- var NodesResource = class {
655
- constructor(client) {
656
- this.client = client;
657
- }
658
- client;
659
- /** List all known node descriptors. Server caches publicly for 5 minutes. */
660
- list() {
661
- return this.client.request("GET", "/v1/nodes");
662
- }
663
- /** Get a single node descriptor by type slug (e.g. "generate-image"). */
664
- get(type) {
665
- return this.client.request("GET", `/v1/nodes/${encodeURIComponent(type)}`);
666
- }
667
- run(type, params = {}, options = {}) {
668
- const route = type === "render-video" && typeof params.planType === "string" ? "/v1/render-video/plan" : nodeRunRoute(type);
669
- if (!route) return Promise.reject(notRunnable(type, NODE_TYPES_WITHOUT_RUN_ROUTE[type]));
670
- const platform = SOCIAL_POST_NODE_PLATFORM[type];
671
- const body = platform && params.platform === void 0 ? { ...params, platform } : params;
672
- const conventional = !Object.prototype.hasOwnProperty.call(NODE_RUN_ROUTES, type);
673
- return this.client.request("POST", route, {
674
- body,
675
- // Transport-level retry safety, opt-in per call. The platform reads the
676
- // standard header, so a caller that reuses a key on a retry gets the
677
- // same run back instead of a second charge.
678
- ...options.idempotencyKey ? { headers: { "Idempotency-Key": options.idempotencyKey } } : {}
679
- }).catch((err) => {
680
- if (conventional && isRouteNotFound(err)) throw notRunnable(type, "it runs only inside a workflow (client.workflows.run)");
681
- throw err;
682
- });
683
- }
684
- async runAndWait(type, params = {}, opts = {}) {
685
- if (opts.signal?.aborted) throw new JobAbortedError();
686
- const result = await this.run(type, params, { idempotencyKey: opts.idempotencyKey });
687
- const jobId = extractJobId(result, type);
688
- return this.pollJob(jobId, type, opts);
689
- }
690
- /**
691
- * Fan out N async runs of the same node `type` to completion concurrently —
692
- * the candidate-grid path (generate N stills/clips in parallel). Each runs
693
- * via {@link runAndWait}; resolves once ALL settle, to an array of
694
- * `{ jobId, output }` in input order. Rejects (and the rejection wins) if any
695
- * single run rejects — same typed errors as {@link runAndWait}, including
696
- * {@link JobHeldError} when one candidate is held for review while the
697
- * others complete. A shared `signal` aborts the whole batch.
698
- *
699
- * @param type Node type slug, applied to every entry.
700
- * @param paramsList One request body per candidate.
701
- * @param opts Shared `signal` / `cancelOnAbort` / `onProgress` / `pollMs` / `maxMs`.
702
- */
703
- async runMany(type, paramsList, opts = {}) {
704
- if (opts.signal?.aborted) throw new JobAbortedError();
705
- return Promise.all(
706
- paramsList.map(async (params) => {
707
- if (opts.signal?.aborted) throw new JobAbortedError();
708
- const result = await this.run(type, params);
709
- const jobId = extractJobId(result, type);
710
- const output = await this.pollJob(jobId, type, opts);
711
- return { jobId, output };
712
- })
713
- );
714
- }
715
- /** {@link pollUntilSettled}, plus what an abort does to the job: it keeps
716
- * running unless `cancelOnAbort` asks to cancel it too, and the rejection
717
- * always names it (an abort landing mid-sleep carries no id of its own). */
718
- async pollJob(jobId, label, opts) {
719
- try {
720
- return await this.pollUntilSettled(jobId, label, opts);
721
- } catch (err) {
722
- if (!(err instanceof JobAbortedError)) throw err;
723
- if (opts.cancelOnAbort) await this.client.jobs.cancel(jobId).catch(() => void 0);
724
- throw err.jobId ? err : new JobAbortedError(err.message, jobId);
725
- }
726
- }
727
- /** Poll an already-kicked job id until it stops moving; resolve output_data
728
- * or throw. Two non-terminal statuses end the loop: an abort, and
729
- * `pending_review` (a job policy held the output for a human — see
730
- * {@link JobHeldError}). */
731
- async pollUntilSettled(jobId, label, opts) {
732
- const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;
733
- const maxMs = opts.maxMs ?? DEFAULT_MAX_MS;
734
- const deadline = Date.now() + maxMs;
735
- for (; ; ) {
736
- if (opts.signal?.aborted) throw new JobAbortedError(void 0, jobId);
737
- const { data } = await this.client.jobs.getStatus(jobId);
738
- opts.onProgress?.(data);
739
- if (data.status === "completed") {
740
- return data.output_data ?? {};
741
- }
742
- if (data.status === "failed" || data.status === "cancelled") {
743
- throw new JobFailedError(
744
- data.error_message ?? `${label} ${data.status}`,
745
- jobId,
746
- data.status
747
- );
748
- }
749
- if (data.status === "pending_review") {
750
- throw new JobHeldError(`${label} is awaiting review`, jobId);
751
- }
752
- if (Date.now() > deadline) {
753
- throw new JobTimeoutError(`${label} timed out`, jobId, maxMs);
754
- }
755
- await sleep(pollMs, opts.signal);
756
- }
757
- }
758
- };
759
-
760
- // src/resources/scene3d-types.ts
761
- var SCENE3D_DELIVERY_ASSET_USAGE = {
762
- poster: "poster",
763
- "validation-report": "validation",
764
- "shot-still": "shot-still",
765
- /** The recipe a run that never compiled was refused for. See {@link Scene3DDeliveryAsset}. */
766
- "source-json": "checkpoint"
767
- };
768
-
769
- // src/resources/scene3d.ts
770
- function newIdempotencyKey() {
771
- const random = globalThis.crypto?.randomUUID?.();
772
- return `sdk-pro3d-${random ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`}`;
773
- }
774
- var Scene3DResource = class {
775
- constructor(client) {
776
- this.client = client;
777
- }
778
- client;
779
- capabilities() {
780
- return this.client.request("GET", "/v1/3d-scene/capabilities");
781
- }
782
- /** Current access to both the delivery and its source is required on every read. */
783
- getDelivery(jobId) {
784
- return this.client.request("GET", `/v1/3d-scene/deliveries/${encodeURIComponent(jobId)}`);
785
- }
786
- /**
787
- * The bytes of one descriptor the delivery listed.
788
- *
789
- * Checked against {@link SCENE3D_DELIVERY_ASSET_USAGE} rather than a hardcoded pair, which
790
- * is why a `shot-still` now works: the route has served stills since they existed, and this
791
- * guard refused them. `source-json` — the recipe a refused run was kept for — is on the same
792
- * map; the server still decides whether THIS caller may read it.
793
- */
794
- deliveryAssetBytes(jobId, asset, options) {
795
- if (SCENE3D_DELIVERY_ASSET_USAGE[asset.kind] !== asset.usage) {
796
- throw new Error("This asset is not available through the delivery endpoint");
797
- }
798
- if (!Number.isSafeInteger(asset.byteLength) || asset.byteLength < 1 || asset.byteLength > SCENE3D_V2_LIMITS.maxRendererAssetBytes) {
799
- throw new Error("Invalid scene delivery asset byte length");
800
- }
801
- return this.client.requestBytes("GET", `/v1/3d-scene/deliveries/${encodeURIComponent(jobId)}/assets/${encodeURIComponent(asset.assetId)}`, {
802
- signal: options?.signal,
803
- maxBytes: asset.byteLength
804
- });
805
- }
806
- /**
807
- * The recipe a 3D Render Pro run was refused for, parsed — or `null` when there is none.
808
- *
809
- * The one thing such a run leaves behind. Its recipe never compiled, so there is no scene
810
- * revision, no poster and no `.blend`: `output_data` carries a `deliveryId`, the compiler's
811
- * reasons, and `validation.sourceRetained` saying whether the recipe itself was kept. This
812
- * fetches it in one call — delivery, then the `source-json` descriptor's bytes.
813
- *
814
- * `null` means the delivery has no retained recipe to hand back: no pass ever cleared
815
- * admission, or this caller holds less than `edit` on the job's workflow and the descriptor
816
- * is therefore not listed for them.
817
- *
818
- * Read it to see what was attempted and to inform the next prompt. There is no input that
819
- * takes a recipe back: a refused run published no revision, so there is no `{kind:"scene"}`
820
- * source to re-run it from.
821
- */
822
- async retainedRecipe(jobId, options) {
823
- const delivery = await this.getDelivery(jobId);
824
- const asset = delivery.assets.find((item) => item.kind === "source-json");
825
- if (!asset) return null;
826
- const bytes = await this.deliveryAssetBytes(jobId, asset, options);
827
- return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
828
- }
829
- /** Persist deterministic overlays without an LLM or a generation charge. */
830
- applyEdits(revisionId, params) {
831
- return this.client.request("POST", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/edits`, { body: params });
832
- }
833
- /** Asset access is scoped to an exact retained revision, with fresh authentication. */
834
- assetBytes(revisionId, asset, options) {
835
- if (!["glb", "camera-track-json", "poster", "validation-report"].includes(asset.kind)) {
836
- throw new Error("This asset is not available through the playback endpoint");
837
- }
838
- if (!Number.isSafeInteger(asset.byteLength) || asset.byteLength < 1 || asset.byteLength > SCENE3D_V2_LIMITS.maxRendererAssetBytes) {
839
- throw new Error("Invalid scene asset byte length");
840
- }
841
- return this.client.requestBytes("GET", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/assets/${encodeURIComponent(asset.assetId)}`, {
842
- signal: options?.signal,
843
- maxBytes: asset.byteLength
844
- });
845
- }
846
- /** The editable native file has its own authorization lane. */
847
- sourceBytes(revisionId, options) {
848
- return this.client.requestBytes("GET", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/source`, {
849
- signal: options?.signal,
850
- maxBytes: SCENE3D_V2_LIMITS.maxBlendSourceBytes
851
- });
852
- }
853
- generate(params) {
854
- return this.client.nodes.run("generate-3d-scene", params);
855
- }
856
- generateAndWait(params, options) {
857
- return this.client.nodes.runAndWait("generate-3d-scene", params, options);
858
- }
859
- edit(params) {
860
- return this.client.nodes.run("edit-3d-scene", params);
861
- }
862
- editAndWait(params, options) {
863
- return this.client.nodes.runAndWait("edit-3d-scene", params, options);
864
- }
865
- /**
866
- * Price a 3D Render Pro request WITHOUT starting it.
867
- *
868
- * Takes the same body a run takes, minus the `quoteId`, and answers a
869
- * ceiling (`maxCredits`), a `breakdown` to show, and the
870
- * `normalizedInputHash` admission re-checks. It reserves nothing and spends
871
- * nothing — a quote is a price, not a purchase.
872
- */
873
- quotePro(params) {
874
- return this.client.request("POST", "/v1/pro-3d-render/quote", { body: params });
875
- }
876
- /**
877
- * Submit a quoted 3D Render Pro run.
878
- *
879
- * Requires the `quoteId` from {@link quotePro}: no run starts at a price
880
- * nobody showed. Sends an `Idempotency-Key` — a fresh one per call unless you
881
- * supply your own, which you should when retrying a call that timed out.
882
- *
883
- * Availability is a property of the deployment: `capabilities().pro` says
884
- * whether this install can serve it, and which controls you may offer.
885
- */
886
- runPro(params, options) {
887
- return this.client.nodes.run("pro-3d-render", params, {
888
- idempotencyKey: options?.idempotencyKey ?? newIdempotencyKey()
889
- });
890
- }
891
- /**
892
- * Quote if needed, run, and wait — the whole operation in one call.
893
- *
894
- * Two HTTP requests at most, still ONE paid job: when `quoteId` is absent
895
- * this quotes the identical body first, so the run is admitted against a
896
- * hash of exactly what was priced. Pass a `quoteId` to run against a quote
897
- * you already showed the user.
898
- *
899
- * Resolves with the settled result — `videoUrl` (the MP4) and `scenePlan`
900
- * (the exact composition it was rendered from), plus the revision, poster,
901
- * validation and renderer metadata. A run that AUTHORED also reports its own
902
- * account of the answer — `metadata.summary`, `repairPasses`,
903
- * `admissionRetries`, `mechanicalPasses` (repairs the engine applied from
904
- * the compiler's own remedy with no planner call, counted APART from
905
- * `repairPasses` on their own quoted allowance), `restoredAssertions`, and
906
- * any `SCENE_AUTHORING_ASSUMPTION` warnings. A
907
- * completed result whose `metadata.review` is present passed every mandatory
908
- * assertion but did NOT get the visual reviewer's approval: `verdict:
909
- * "refused"` means it objected, each objection also a `SCENE_REVIEW_REFUSED`
910
- * warning; `verdict: "unavailable"` means the review produced no usable
911
- * verdict in `attempts` asks (`reason: "provider"` — never reached its
912
- * provider; `"unusable"` — it answered, unusably), so nobody judged the scene and
913
- * `SCENE_REVIEW_UNAVAILABLE` leads the warnings. Re-render that same
914
- * `scenePlan` later with {@link render}, or with a `{kind:'scene'}` source;
915
- * that costs no authoring.
916
- */
917
- async renderProAndWait(params, options) {
918
- const quoteId = typeof params.quoteId === "string" ? params.quoteId : (await this.quotePro(params)).quoteId;
919
- return this.client.nodes.runAndWait("pro-3d-render", { ...params, quoteId }, {
920
- ...options,
921
- idempotencyKey: options?.idempotencyKey ?? newIdempotencyKey()
922
- });
923
- }
924
- /**
925
- * Uses the supplied immutable revision; never starts authoring or a rebuild.
926
- *
927
- * Priced by the plan's frame size — see {@link RenderScene3DParams}.
928
- */
929
- render(params) {
930
- return this.client.nodes.run("render-video", params);
931
- }
932
- renderAndWait(params, options) {
933
- return this.client.nodes.runAndWait("render-video", params, options);
934
- }
935
- };
936
-
937
- // src/resources/developer-apps.ts
938
- var DeveloperAppsResource = class {
939
- constructor(client) {
940
- this.client = client;
941
- }
942
- client;
943
- /** List the authenticated user's developer apps. */
944
- list() {
945
- return this.client.request("GET", "/v1/developer-apps");
946
- }
947
- /** Get a developer app by ID. */
948
- get(id) {
949
- return this.client.request("GET", `/v1/developer-apps/${encodeURIComponent(id)}`);
950
- }
951
- /**
952
- * Create a new developer app. Returns the app PLUS a one-time `clientSecret`
953
- * — store it now, the secret hash is the only copy kept server-side.
954
- */
955
- create(input) {
956
- return this.client.request("POST", "/v1/developer-apps", { body: input });
957
- }
958
- /** Update a developer app's metadata, redirect URIs, origins, or requested scopes. */
959
- update(id, input) {
960
- return this.client.request(
961
- "PATCH",
962
- `/v1/developer-apps/${encodeURIComponent(id)}`,
963
- { body: input }
964
- );
965
- }
966
- /** Delete a developer app. Returns `{ success: true }`. Throws
967
- * `NotFoundError` when the id doesn't exist or isn't yours. */
968
- delete(id) {
969
- return this.client.request(
970
- "DELETE",
971
- `/v1/developer-apps/${encodeURIComponent(id)}`
972
- );
973
- }
974
- /**
975
- * Generate a new `clientSecret`. The previous secret is invalidated.
976
- * Server returns ONLY the new secret, not the full app record.
977
- */
978
- rotateSecret(id) {
979
- return this.client.request(
980
- "POST",
981
- `/v1/developer-apps/${encodeURIComponent(id)}/rotate-secret`
982
- );
983
- }
984
- };
985
-
986
- // src/resources/oauth.ts
987
- var OAuthResource = class {
988
- constructor(client) {
989
- this.client = client;
990
- }
991
- client;
992
- /**
993
- * Server-side authorization-code exchange. Sends the standard OAuth 2.0
994
- * `application/json` body to `POST /v1/oauth/token`.
995
- *
996
- * NEVER call this from a browser — `client_secret` must stay on the server.
997
- */
998
- exchangeCode(input) {
999
- return this.client.request("POST", "/v1/oauth/token", {
1000
- body: { grant_type: "authorization_code", ...input }
1001
- });
1002
- }
1003
- /**
1004
- * Revoke an access token (RFC 7009). Always returns `{ success: true }`,
1005
- * even for unknown tokens — the spec forbids leaking token validity.
1006
- */
1007
- revoke(token) {
1008
- return this.client.request("POST", "/v1/oauth/revoke", { body: { token } });
1009
- }
1010
- /**
1011
- * Get public app metadata for a consent screen.
1012
- * `GET /v1/oauth/app-info?client_id=<id>`. Public route — no auth needed.
1013
- */
1014
- getAppInfo(clientId, redirectUri) {
1015
- return this.client.request("GET", "/v1/oauth/app-info", {
1016
- query: redirectUri ? { client_id: clientId, redirect_uri: redirectUri } : { client_id: clientId }
1017
- });
1018
- }
1019
- };
1020
-
1021
- // src/resources/apps.ts
1022
- var AppsResource = class {
1023
- constructor(client) {
1024
- this.client = client;
1025
- }
1026
- client;
1027
- /** List published apps. Public — no auth required for community apps. */
1028
- list(params = {}) {
1029
- const qs = new URLSearchParams();
1030
- if (params.search) qs.set("search", params.search);
1031
- if (params.limit !== void 0) qs.set("limit", String(params.limit));
1032
- if (params.cursor) qs.set("cursor", params.cursor);
1033
- if (params.category) qs.set("category", params.category);
1034
- const query = qs.toString();
1035
- return this.client.request("GET", `/v1/apps/browse${query ? `?${query}` : ""}`);
1036
- }
1037
- /** Get one app's metadata + input schema by slug. */
1038
- get(slug) {
1039
- return this.client.request("GET", `/v1/app/${encodeURIComponent(slug)}`);
1040
- }
1041
- /**
1042
- * Trigger an app run with the given input values. The keys in `inputs` must
1043
- * match the app's input-schema field names (see `get(slug).inputSchema`).
1044
- * `opts.inputOverrides` adds raw per-node overrides (see {@link RunAppOptions}).
1045
- * Returns the execution-id for status polling via client.executions.get().
1046
- */
1047
- run(slug, inputs = {}, opts = {}) {
1048
- return this.client.request("POST", `/v1/app/${encodeURIComponent(slug)}/run`, {
1049
- body: { inputs, ...opts.inputOverrides ? { inputOverrides: opts.inputOverrides } : {} }
1050
- });
1051
- }
1052
- /** List past runs for an app (the caller must own the app or the runs). */
1053
- listRuns(slug, params = {}) {
1054
- const qs = new URLSearchParams();
1055
- if (params.limit !== void 0) qs.set("limit", String(params.limit));
1056
- if (params.cursor) qs.set("cursor", params.cursor);
1057
- const query = qs.toString();
1058
- return this.client.request(
1059
- "GET",
1060
- `/v1/app/${encodeURIComponent(slug)}/runs${query ? `?${query}` : ""}`
1061
- );
1062
- }
1063
- /** Get one app-run by id. */
1064
- getRun(slug, runId) {
1065
- return this.client.request(
1066
- "GET",
1067
- `/v1/app/${encodeURIComponent(slug)}/runs/${encodeURIComponent(runId)}`
1068
- );
1069
- }
1070
- /**
1071
- * Archive (soft-delete) a published-app run. The run is hidden from the
1072
- * default run list and can be restored or permanently deleted from the
1073
- * archive view at https://app.nodaro.ai/archived-runs.
1074
- *
1075
- * @param slug The published app's slug (the last path segment of its URL).
1076
- * @param runId The run's UUID.
1077
- */
1078
- deleteRun(slug, runId) {
1079
- return this.client.request(
1080
- "DELETE",
1081
- `/v1/app/${encodeURIComponent(slug)}/runs/${encodeURIComponent(runId)}`
1082
- );
1083
- }
1084
- };
1085
- var CharactersResource = class {
1086
- constructor(client) {
1087
- this.client = client;
1088
- }
1089
- client;
1090
- /**
1091
- * List the caller's characters. By default returns active characters only;
1092
- * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1093
- * When `projectId` is set, only characters belonging to that project are
1094
- * returned.
1095
- *
1096
- * Cursor-paginated: a response carrying a non-null `nextCursor` means more
1097
- * rows exist. Pass it back as `cursor` to fetch the next page, and keep going
1098
- * until `nextCursor` is `null` — a single call returns at most `limit` rows
1099
- * (default 100), so treating one call as "all characters" silently truncates
1100
- * the list for anyone past that count.
1101
- *
1102
- * ```ts
1103
- * const all: Character[] = []
1104
- * let cursor: string | undefined
1105
- * do {
1106
- * const page = await client.characters.list({ cursor })
1107
- * all.push(...page.characters)
1108
- * cursor = page.nextCursor ?? undefined
1109
- * } while (cursor)
1110
- * ```
1111
- */
1112
- list(params = {}) {
1113
- const query = {};
1114
- if (params.projectId) query.projectId = params.projectId;
1115
- if (params.archived) query.archived = "true";
1116
- if (params.limit !== void 0) query.limit = String(params.limit);
1117
- if (params.cursor) query.cursor = params.cursor;
1118
- return this.client.request("GET", "/v1/characters", { query });
1119
- }
1120
- /**
1121
- * Fetch a single character including in-flight portrait / asset job state.
1122
- * Soft-deleted (archived) rows are returned by id intentionally so canvas
1123
- * nodes that hold a stale `characterDbId` keep loading. Pass
1124
- * `{ candidates: "all" }` to also get the current portrait's own take in
1125
- * `previousCandidates` (flagged `isPortrait: true`).
1126
- */
1127
- get(id, options = {}) {
1128
- const query = {};
1129
- if (options.candidates) query.candidates = options.candidates;
1130
- return this.client.request("GET", `/v1/characters/${encodeURIComponent(id)}`, { query });
1131
- }
1132
- /**
1133
- * Create or update a character. Omit `id` to create; supply it to update
1134
- * (only the fields you pass get written — undefined keys are untouched).
1135
- *
1136
- * If the caller-supplied `name` collides with an existing active character
1137
- * for this user, the request returns 409 `name_taken`. To auto-number a
1138
- * placeholder, pass the placeholder name from `@nodaro/shared` and the
1139
- * server will derive "Untitled character 2", "Untitled character 3", etc.
1140
- */
1141
- upsert(input) {
1142
- return this.client.request("POST", "/v1/characters", { body: input });
1143
- }
1144
- /**
1145
- * Convenience wrapper around `upsert()` for creating new characters.
1146
- * Equivalent to `upsert({ ...input, id: undefined })`. `name` is REQUIRED
1147
- * on create — the route 400s on INSERT-without-name; we narrow the type
1148
- * here so callers fail at compile-time rather than runtime.
1149
- */
1150
- create(input) {
1151
- return this.upsert(input);
1152
- }
1153
- /**
1154
- * Convenience wrapper around `upsert()` for updating an existing character.
1155
- * Equivalent to `upsert({ ...input, id })`.
1156
- */
1157
- update(id, input) {
1158
- return this.upsert({ ...input, id });
1159
- }
1160
- /**
1161
- * Soft-delete (archive) a character. The row is hidden from `list()` by
1162
- * default but still loadable via `get(id)` so canvas nodes pointing at it
1163
- * keep working. Restore with `restore(id)`.
1164
- */
1165
- delete(id) {
1166
- return this.client.request("DELETE", `/v1/characters/${encodeURIComponent(id)}`);
1167
- }
1168
- /**
1169
- * Un-archive a character. If the original name now collides with an
1170
- * active row, the server auto-suffixes "(restored)" and returns the
1171
- * effective name.
1172
- */
1173
- restore(id) {
1174
- return this.client.request("POST", `/v1/characters/${encodeURIComponent(id)}/restore`);
1175
- }
1176
- /**
1177
- * Duplicate (fork) a character to a new row with a `"(copy)"` suffix.
1178
- * Asset URLs are shared by reference — the new row can diverge by
1179
- * regenerating any of them.
1180
- */
1181
- duplicate(id, input = {}) {
1182
- return this.client.request(
1183
- "POST",
1184
- `/v1/characters/${encodeURIComponent(id)}/duplicate`,
1185
- { body: input }
1186
- );
1187
- }
1188
- /**
1189
- * Count of the caller's workflows that reference this character. Powers the
1190
- * library "Archive" confirmation modal in the editor.
1191
- */
1192
- usage(id) {
1193
- return this.client.request("GET", `/v1/characters/${encodeURIComponent(id)}/usage`);
1194
- }
1195
- /**
1196
- * Fire `POST /v1/generate-character` to produce one or more portrait
1197
- * candidates. With `count > 1`, all jobs are reserved up-front before any
1198
- * is enqueued — mid-batch failures roll back atomically.
1199
- *
1200
- * When `attachToCharacterId` is set, the worker writes the result directly
1201
- * to the row's `source_image_url` (unless `attachPortrait: false`);
1202
- * otherwise you must call `approvePortrait()` after picking a candidate.
1203
- */
1204
- generate(input) {
1205
- return this.client.request("POST", "/v1/generate-character", { body: input });
1206
- }
1207
- /**
1208
- * Fire `POST /v1/generate-character-asset` to produce a single
1209
- * expression / pose / angle / lighting variant. When the studio path is
1210
- * set (`attachToCharacterId` + `attachToColumn` + `attachName`), the
1211
- * worker appends `{ name: attachName, url: <result> }` to the named
1212
- * JSONB array column on completion.
1213
- */
1214
- generateAsset(input) {
1215
- return this.client.request("POST", "/v1/generate-character-asset", { body: input });
1216
- }
1217
- /**
1218
- * Fire `POST /v1/generate-character-motion` to animate the character's
1219
- * portrait into a motion clip. The result is appended to the character's
1220
- * `motions[]` bucket when `attachToCharacterId` is set.
1221
- */
1222
- generateMotion(input) {
1223
- return this.client.request("POST", "/v1/generate-character-motion", { body: input });
1224
- }
1225
- /**
1226
- * Approve a completed `generate-character` job as the character's portrait.
1227
- * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)
1228
- * inline. Returns the new portrait URL plus the caption — `canonicalDescription`
1229
- * is `null` if the LLM call sub-failed (portrait still set; retry via `recaption()`).
1230
- */
1231
- approvePortrait(id, candidateJobId) {
1232
- return this.client.request(
1233
- "POST",
1234
- `/v1/characters/${encodeURIComponent(id)}/approve-portrait`,
1235
- { body: { candidateJobId } }
1236
- );
1237
- }
1238
- /**
1239
- * Re-fire the LLM caption against the character's current portrait. 502s on
1240
- * LLM failure; returns 400 `no_portrait` if no portrait is set yet.
1241
- */
1242
- recaption(id) {
1243
- return this.client.request(
1244
- "POST",
1245
- `/v1/characters/${encodeURIComponent(id)}/llm-caption`
1246
- );
1247
- }
1248
- };
1249
- function buildPersonSeedPrompt(value) {
1250
- return buildPersonHints(value).join(", ");
1251
- }
1252
- var LocationsResource = class {
1253
- constructor(client) {
1254
- this.client = client;
1255
- }
1256
- client;
1257
- /**
1258
- * List the caller's locations. By default returns active locations only;
1259
- * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1260
- */
1261
- list(params = {}) {
1262
- const query = {};
1263
- if (params.archived) query.archived = "true";
1264
- if (params.limit !== void 0) query.limit = String(params.limit);
1265
- if (params.cursor) query.cursor = params.cursor;
1266
- return this.client.request("GET", "/v1/locations", { query });
1267
- }
1268
- /**
1269
- * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted
1270
- * rows so callers can drive a UI "Archived" tab without re-encoding the
1271
- * query param. Mirrors `ObjectsResource.listArchived`.
1272
- *
1273
- * `archived` is omitted from the param type — it's always set to `true` here.
1274
- */
1275
- listArchived(params = {}) {
1276
- return this.list({ ...params, archived: true });
1277
- }
1278
- /**
1279
- * Fetch a single location including in-flight asset job state. Soft-deleted
1280
- * (archived) rows are returned by id intentionally so canvas nodes that
1281
- * hold a stale `locationDbId` keep loading.
1282
- */
1283
- async get(id) {
1284
- const res = await this.client.request(
1285
- "GET",
1286
- `/v1/locations/${encodeURIComponent(id)}`
1287
- );
1288
- return { ...res, canonicalDescription: res.canonicalDescription || null };
1289
- }
1290
- /**
1291
- * Create a new location. `name` + `nodeId` are required — the route 400s
1292
- * otherwise. Returns the new row's id.
1293
- *
1294
- * Note: the underlying route is the same `POST /v1/locations` upsert that
1295
- * powers `update()`. This convenience wrapper enforces the INSERT-required
1296
- * fields at the type level and never sends an `id`.
1297
- */
1298
- create(data) {
1299
- return this.client.request("POST", "/v1/locations", { body: data });
1300
- }
1301
- /**
1302
- * Update a location. Only the fields you pass are written — undefined keys
1303
- * are NOT touched on the row. Worker-owned asset buckets are intentionally
1304
- * not exposed on this surface (see `UpdateLocationInput` for the rationale).
1305
- *
1306
- * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's
1307
- * `updated_at` still matches; on mismatch the route returns 409
1308
- * `concurrent_modification`. The SDK surfaces that as a generic
1309
- * `NodaroError` with the same code.
1310
- */
1311
- update(id, data) {
1312
- return this.client.request("POST", "/v1/locations", {
1313
- body: { id, ...data }
1314
- });
1315
- }
1316
- /**
1317
- * Soft-delete (archive) a location. The row is hidden from `list()` by
1318
- * default but still loadable via `get(id)` so canvas nodes pointing at it
1319
- * keep working. Restore with `restore(id)`.
1320
- */
1321
- delete(id) {
1322
- return this.client.request("DELETE", `/v1/locations/${encodeURIComponent(id)}`);
1323
- }
1324
- /**
1325
- * Un-archive a location. If the original name now collides (case-
1326
- * insensitive) with an active row, the server auto-suffixes "(restored)"
1327
- * and returns the effective name.
1328
- */
1329
- restore(id) {
1330
- return this.client.request("POST", `/v1/locations/${encodeURIComponent(id)}/restore`);
1331
- }
1332
- /**
1333
- * Fire `POST /v1/generate-location` to produce one or more candidate main
1334
- * images. With `count > 1`, all jobs are reserved up-front before any
1335
- * is enqueued — mid-batch failures roll back atomically.
1336
- *
1337
- * When `attachToLocationId` is set AND `count === 1`, the worker writes
1338
- * the result directly to the row's `source_image_url`; otherwise you must
1339
- * call `approveMainImage()` after picking a candidate.
1340
- */
1341
- async generate(data) {
1342
- const res = await this.client.request(
1343
- "POST",
1344
- "/v1/generate-location",
1345
- { body: data }
1346
- );
1347
- const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : []);
1348
- return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds };
1349
- }
1350
- /**
1351
- * Fire `POST /v1/generate-location-asset` to produce a single variant.
1352
- * When the studio path is set (`attachToLocationId` + `attachToColumn` +
1353
- * `attachName`), the worker appends `{ name: attachName, url: <result> }`
1354
- * to the named JSONB array column on completion.
1355
- */
1356
- generateAsset(data) {
1357
- return this.client.request("POST", "/v1/generate-location-asset", { body: data });
1358
- }
1359
- /**
1360
- * Fire `POST /v1/generate-surround-continuation` to produce one seamless 360°
1361
- * ring view as an i2i continuation of `referenceImageUrl`. The platform builds
1362
- * the half-carry composite, paints the missing half, and color-harmonizes it
1363
- * to the carried half (no tonal seam; carried half stays pixel-exact). When the
1364
- * studio path is set, the worker appends the result to the location's bucket.
1365
- */
1366
- generateSurroundContinuation(data) {
1367
- return this.client.request("POST", "/v1/generate-surround-continuation", { body: data });
1368
- }
1369
- /**
1370
- * Fire `POST /v1/generate-location-motion` to animate the location's
1371
- * establishing shot into an atmospheric motion clip. Image-to-video, single
1372
- * clip per call; the attach column is hardcoded to `atmosphere_motions`
1373
- * server-side (locations have a single motion bucket so the caller doesn't
1374
- * supply `attachToColumn`). When the studio path is set
1375
- * (`attachToLocationId` + `attachName`), the worker appends
1376
- * `{ name: attachName, url: <result> }` to the row's `atmosphere_motions`
1377
- * column on completion.
1378
- */
1379
- generateMotion(data) {
1380
- return this.client.request("POST", "/v1/generate-location-motion", { body: data });
1381
- }
1382
- /**
1383
- * Atomically remove ONE asset take (every entry matching `url`) from a
1384
- * worker-owned bucket column — `POST /v1/locations/:id/remove-asset`. The
1385
- * worker-owned buckets are deliberately not writable through `update()`
1386
- * (a stale snapshot would race concurrent worker appends), so deleting a
1387
- * take — e.g. a 360° surround view being regenerated — goes through this
1388
- * single-statement server-side filter instead. 404s (`NotFoundError`) when
1389
- * the url isn't in that bucket or the location isn't yours.
1390
- */
1391
- removeAsset(id, data) {
1392
- return this.client.request(
1393
- "POST",
1394
- `/v1/locations/${encodeURIComponent(id)}/remove-asset`,
1395
- { body: data }
1396
- );
1397
- }
1398
- /**
1399
- * Approve a completed `generate-location` job as the location's main image.
1400
- * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)
1401
- * inline. Returns the new main-image URL plus the caption.
1402
- *
1403
- * Caption-failure semantics: the route still sends `""` on LLM sub-failure,
1404
- * but the SDK normalizes `""` → `null` here so `canonicalDescription` carries
1405
- * the same `string | null` semantics as characters. The main image is still
1406
- * set; call `recaption()` to retry.
1407
- */
1408
- async approveMainImage(id, candidateJobId) {
1409
- const res = await this.client.request(
1410
- "POST",
1411
- `/v1/locations/${encodeURIComponent(id)}/approve-main-image`,
1412
- { body: { candidateJobId } }
1413
- );
1414
- return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null };
1415
- }
1416
- /**
1417
- * Re-fire the LLM caption against the location's current main image. 502s
1418
- * on LLM failure (unlike `approveMainImage` which preserves the side-effect
1419
- * and returns ""); returns 400 `no_source_image` if no main image is set
1420
- * yet.
1421
- */
1422
- recaption(id) {
1423
- return this.client.request(
1424
- "POST",
1425
- `/v1/locations/${encodeURIComponent(id)}/llm-caption`
1426
- );
1427
- }
1428
- };
1429
- var ObjectsResource = class {
1430
- constructor(client) {
1431
- this.client = client;
1432
- }
1433
- client;
1434
- /**
1435
- * List the caller's objects. By default returns active objects only;
1436
- * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1437
- * Optional `projectId` scopes the result to a single project.
1438
- */
1439
- list(params = {}) {
1440
- const query = {};
1441
- if (params.archived) query.archived = "true";
1442
- if (params.projectId) query.projectId = params.projectId;
1443
- if (params.limit !== void 0) query.limit = String(params.limit);
1444
- if (params.cursor) query.cursor = params.cursor;
1445
- return this.client.request("GET", "/v1/objects", { query });
1446
- }
1447
- /**
1448
- * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted
1449
- * rows so callers can drive a UI "Archived" tab without re-encoding the
1450
- * query param.
1451
- *
1452
- * `archived` is omitted from the param type — it's always set to `true` here.
1453
- */
1454
- listArchived(params = {}) {
1455
- return this.list({ ...params, archived: true });
1456
- }
1457
- /**
1458
- * Fetch a single object including in-flight asset job state. Soft-deleted
1459
- * (archived) rows are NOT returned by id — the route enforces
1460
- * `deleted_at IS NULL` so archived objects 404 (uniform Pass 10 F-90b
1461
- * "not_found" — does not leak the deleted vs non-existent distinction).
1462
- */
1463
- async get(id) {
1464
- const res = await this.client.request(
1465
- "GET",
1466
- `/v1/objects/${encodeURIComponent(id)}`
1467
- );
1468
- return { ...res, canonicalDescription: res.canonicalDescription || null };
1469
- }
1470
- /**
1471
- * Create a new object. `name` + `nodeId` are required — the route 400s
1472
- * otherwise. Returns the new row's id.
1473
- *
1474
- * Note: the underlying route is the same `POST /v1/objects` upsert that
1475
- * powers `update()`. This convenience wrapper enforces the INSERT-required
1476
- * fields at the type level and never sends an `id`.
1477
- */
1478
- create(data) {
1479
- return this.client.request("POST", "/v1/objects", { body: data });
1480
- }
1481
- /**
1482
- * Update an object. Only the fields you pass are written — undefined keys
1483
- * are NOT touched on the row. Worker-owned asset buckets are intentionally
1484
- * not exposed on this surface (see `UpdateObjectInput` for the rationale).
1485
- *
1486
- * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's
1487
- * `updated_at` still matches; on mismatch the route returns 409
1488
- * `concurrent_modification` carrying the fresh `updatedAt`. The SDK
1489
- * surfaces that as a generic `NodaroError` with the same code (per Phase
1490
- * E1 calibration finding — error centralization in `throwApiError`).
1491
- */
1492
- update(id, data) {
1493
- return this.client.request("POST", "/v1/objects", {
1494
- body: { id, ...data }
1495
- });
1496
- }
1497
- /**
1498
- * Soft-delete (archive) an object. The row is hidden from `list()` by
1499
- * default but recoverable via `restore(id)` or visible under
1500
- * `listArchived()`. Idempotent — repeating a delete on an already-archived
1501
- * row is a no-op.
1502
- */
1503
- delete(id) {
1504
- return this.client.request("DELETE", `/v1/objects/${encodeURIComponent(id)}`);
1505
- }
1506
- /**
1507
- * Hard-delete (permanent) an object — the row + every R2 asset it
1508
- * references. Archived rows ONLY: active objects return 400 `not_archived`.
1509
- * Call `delete()` first to archive, then `permanentDelete()` to destroy.
1510
- *
1511
- * Mirrors the `app_runs` permanent-delete pattern (archive-first) so a
1512
- * stray SDK / curl caller cannot bypass the studio's archive-first UI
1513
- * flow.
1514
- */
1515
- permanentDelete(id) {
1516
- return this.client.request("DELETE", `/v1/objects/${encodeURIComponent(id)}`, {
1517
- query: { permanent: "true" }
1518
- });
1519
- }
1520
- /**
1521
- * Un-archive an object. If the original name now collides (case-
1522
- * insensitive) with an active row, the server auto-suffixes "(restored)"
1523
- * and returns the effective name.
1524
- */
1525
- restore(id) {
1526
- return this.client.request("POST", `/v1/objects/${encodeURIComponent(id)}/restore`);
1527
- }
1528
- /**
1529
- * Fire `POST /v1/generate-object` to produce one or more candidate main
1530
- * images. With `count > 1`, all jobs are reserved up-front before any
1531
- * is enqueued — mid-batch failures roll back atomically.
1532
- *
1533
- * When `attachToObjectId` is set AND `count === 1`, the worker writes
1534
- * the result directly to the row's `source_image_url`; otherwise you must
1535
- * call `approveMainImage()` after picking a candidate.
1536
- */
1537
- async generate(data) {
1538
- const res = await this.client.request(
1539
- "POST",
1540
- "/v1/generate-object",
1541
- { body: data }
1542
- );
1543
- const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : []);
1544
- return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds };
1545
- }
1546
- /**
1547
- * Fire `POST /v1/generate-object-asset` to produce a single variant.
1548
- * When the studio path is set (`attachToObjectId` + `attachToColumn` +
1549
- * `attachName`), the worker appends `{ name: attachName, url: <result> }`
1550
- * to the named JSONB array column on completion.
1551
- *
1552
- * Note: `attachToColumn` is REQUIRED for `assetType === "custom"` — the
1553
- * worker can't infer the bucket from the asset type. For canonical asset
1554
- * types (`angles` / `materials` / `variations` / `motion`), the column is
1555
- * derived automatically by the route.
1556
- */
1557
- generateAsset(data) {
1558
- return this.client.request("POST", "/v1/generate-object-asset", { body: data });
1559
- }
1560
- /**
1561
- * Fire `POST /v1/generate-object-motion` to animate the object's main
1562
- * image into a motion clip. Image-to-video, single clip per call; the
1563
- * attach column is hardcoded to `motion_clips` server-side (objects have a
1564
- * single motion bucket so the caller doesn't supply `attachToColumn`).
1565
- * When the studio path is set (`attachToObjectId` + `attachName`), the
1566
- * worker appends `{ name: attachName, url: <result> }` to the row's
1567
- * `motion_clips` column on completion.
1568
- *
1569
- * Defaults: `provider` → `"kling-turbo"`, `aspectRatio` → `"1:1"` (set
1570
- * server-side via `resolveObjectAspectRatio({ assetType: "motion" })`).
1571
- */
1572
- generateMotion(data) {
1573
- return this.client.request("POST", "/v1/generate-object-motion", { body: data });
1574
- }
1575
- /**
1576
- * Approve a completed `generate-object` job as the object's main image.
1577
- * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)
1578
- * inline. Returns the new main-image URL plus the caption.
1579
- *
1580
- * Caption-failure semantics: the route still sends `""` on LLM sub-failure,
1581
- * but the SDK normalizes `""` → `null` here so `canonicalDescription` carries
1582
- * the same `string | null` semantics as characters. The main image is still
1583
- * set; call `recaption()` to retry.
1584
- *
1585
- * Optimistic-concurrency: pass `expectedUpdatedAt` to gate the update on
1586
- * the row's current `updated_at`; on mismatch the route returns 409
1587
- * `concurrent_modification` carrying the fresh token.
1588
- */
1589
- async approveMainImage(id, candidateJobId, expectedUpdatedAt) {
1590
- const res = await this.client.request(
1591
- "POST",
1592
- `/v1/objects/${encodeURIComponent(id)}/approve-main-image`,
1593
- { body: { candidateJobId, expectedUpdatedAt } }
1594
- );
1595
- return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null };
1596
- }
1597
- /**
1598
- * Re-fire the LLM caption against the object's current main image. 502s
1599
- * on LLM failure (unlike `approveMainImage` which preserves the side-effect
1600
- * and returns ""); returns 400 `main_image_required` if no main image is
1601
- * set yet.
1602
- *
1603
- * The route is a pure idempotent retry — it does NOT accept an
1604
- * `expectedUpdatedAt` token (per Phase E1 calibration finding: backend
1605
- * route is idempotent retry, not gated on optimistic-concurrency).
1606
- */
1607
- recaption(id) {
1608
- return this.client.request(
1609
- "POST",
1610
- `/v1/objects/${encodeURIComponent(id)}/llm-caption`
1611
- );
1612
- }
1613
- };
1614
- var CREATURE_ASSET_TYPES = ["angles", "poses", "variations", "custom"];
1615
- var CreaturesResource = class {
1616
- constructor(client) {
1617
- this.client = client;
1618
- }
1619
- client;
1620
- /**
1621
- * List the caller's creatures. By default returns active creatures only;
1622
- * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1623
- * Optional `projectId` scopes the result to a single project.
1624
- */
1625
- list(params = {}) {
1626
- const query = {};
1627
- if (params.archived) query.archived = "true";
1628
- if (params.projectId) query.projectId = params.projectId;
1629
- if (params.limit !== void 0) query.limit = String(params.limit);
1630
- if (params.cursor) query.cursor = params.cursor;
1631
- return this.client.request("GET", "/v1/creatures", { query });
1632
- }
1633
- /**
1634
- * Convenience wrapper for `list({ archived: true })`. Returns soft-deleted
1635
- * rows so callers can drive a UI "Archived" tab without re-encoding the
1636
- * query param.
1637
- *
1638
- * `archived` is omitted from the param type — it's always set to `true` here.
1639
- */
1640
- listArchived(params = {}) {
1641
- return this.list({ ...params, archived: true });
1642
- }
1643
- /**
1644
- * Fetch a single creature including in-flight asset job state. Soft-deleted
1645
- * (archived) rows are NOT returned by id — the route enforces
1646
- * `deleted_at IS NULL` so archived creatures 404 (uniform "not_found" — does
1647
- * not leak the deleted vs non-existent distinction).
1648
- */
1649
- async get(id) {
1650
- const res = await this.client.request(
1651
- "GET",
1652
- `/v1/creatures/${encodeURIComponent(id)}`
1653
- );
1654
- return { ...res, canonicalDescription: res.canonicalDescription || null };
1655
- }
1656
- /**
1657
- * Create a new creature. `name` + `nodeId` are required — the route 400s
1658
- * otherwise. Returns the new row's id.
1659
- *
1660
- * Note: the underlying route is the same `POST /v1/creatures` upsert that
1661
- * powers `update()`. This convenience wrapper enforces the INSERT-required
1662
- * fields at the type level and never sends an `id`.
1663
- */
1664
- create(data) {
1665
- return this.client.request("POST", "/v1/creatures", { body: data });
1666
- }
1667
- /**
1668
- * Update a creature. Only the fields you pass are written — undefined keys
1669
- * are NOT touched on the row. Worker-owned asset buckets are intentionally
1670
- * not exposed on this surface (see `UpdateCreatureInput` for the rationale).
1671
- *
1672
- * Optimistic-concurrency: pass `expectedUpdatedAt` to require the row's
1673
- * `updated_at` still matches; on mismatch the route returns 409
1674
- * `concurrent_modification` carrying the fresh `updatedAt`. The SDK
1675
- * surfaces that as a generic `NodaroError` with the same code.
1676
- */
1677
- update(id, data) {
1678
- return this.client.request("POST", "/v1/creatures", {
1679
- body: { id, ...data }
1680
- });
1681
- }
1682
- /**
1683
- * Soft-delete (archive) a creature. The row is hidden from `list()` by
1684
- * default but recoverable via `restore(id)` or visible under
1685
- * `listArchived()`. Idempotent — repeating a delete on an already-archived
1686
- * row is a no-op.
1687
- */
1688
- delete(id) {
1689
- return this.client.request("DELETE", `/v1/creatures/${encodeURIComponent(id)}`);
1690
- }
1691
- /**
1692
- * Hard-delete (permanent) a creature — the row + every R2 asset it
1693
- * references. Archived rows ONLY: active creatures return 400 `not_archived`.
1694
- * Call `delete()` first to archive, then `permanentDelete()` to destroy.
1695
- *
1696
- * Mirrors the `app_runs` permanent-delete pattern (archive-first) so a
1697
- * stray SDK / curl caller cannot bypass the studio's archive-first UI
1698
- * flow.
1699
- */
1700
- permanentDelete(id) {
1701
- return this.client.request("DELETE", `/v1/creatures/${encodeURIComponent(id)}`, {
1702
- query: { permanent: "true" }
1703
- });
1704
- }
1705
- /**
1706
- * Un-archive a creature. If the original name now collides (case-
1707
- * insensitive) with an active row, the server auto-suffixes "(restored)"
1708
- * and returns the effective name.
1709
- */
1710
- restore(id) {
1711
- return this.client.request("POST", `/v1/creatures/${encodeURIComponent(id)}/restore`);
1712
- }
1713
- /**
1714
- * Fire `POST /v1/generate-creature` to produce one or more candidate main
1715
- * images. With `count > 1`, all jobs are reserved up-front before any
1716
- * is enqueued — mid-batch failures roll back atomically.
1717
- *
1718
- * When `attachToCreatureId` is set AND `count === 1`, the worker writes
1719
- * the result directly to the row's `source_image_url`; otherwise you must
1720
- * call `approveMainImage()` after picking a candidate.
1721
- */
1722
- async generate(data) {
1723
- const res = await this.client.request(
1724
- "POST",
1725
- "/v1/generate-creature",
1726
- { body: data }
1727
- );
1728
- const jobIds = res.jobIds ?? (res.jobId ? [res.jobId] : []);
1729
- return res.jobId ? { jobIds, jobId: res.jobId } : { jobIds };
1730
- }
1731
- /**
1732
- * Fire `POST /v1/generate-creature-asset` to produce a single variant.
1733
- * When the studio path is set (`attachToCreatureId` + `attachToColumn` +
1734
- * `attachName`), the worker appends `{ name: attachName, url: <result> }`
1735
- * to the named JSONB array column on completion.
1736
- *
1737
- * Note: `attachToColumn` is REQUIRED for `assetType === "custom"` — the
1738
- * worker can't infer the bucket from the asset type. For canonical asset
1739
- * types (`angles` / `poses` / `variations`), the column is derived
1740
- * automatically by the route.
1741
- */
1742
- generateAsset(data) {
1743
- return this.client.request("POST", "/v1/generate-creature-asset", { body: data });
1744
- }
1745
- /**
1746
- * Fire `POST /v1/generate-creature-motion` to animate the creature's main
1747
- * image into a motion clip. Image-to-video, single clip per call; the
1748
- * attach column is hardcoded to `motion_clips` server-side (creatures have a
1749
- * single motion bucket so the caller doesn't supply `attachToColumn`).
1750
- * When the studio path is set (`attachToCreatureId` + `attachName`), the
1751
- * worker appends `{ name: attachName, url: <result> }` to the row's
1752
- * `motion_clips` column on completion.
1753
- *
1754
- * Defaults: `provider` → `"kling-turbo"`, `aspectRatio` → `"1:1"` (set
1755
- * server-side via `resolveObjectAspectRatio({ assetType: "motion" })`).
1756
- */
1757
- generateMotion(data) {
1758
- return this.client.request("POST", "/v1/generate-creature-motion", { body: data });
1759
- }
1760
- /**
1761
- * Approve a completed `generate-creature` job as the creature's main image.
1762
- * Sets `source_image_url` and fires the LLM caption (Claude Sonnet vision)
1763
- * inline. Returns the new main-image URL plus the caption.
1764
- *
1765
- * Caption-failure semantics: the route still sends `""` on LLM sub-failure,
1766
- * but the SDK normalizes `""` → `null` here so `canonicalDescription` carries
1767
- * the same `string | null` semantics as characters. The main image is still
1768
- * set; call `recaption()` to retry.
1769
- *
1770
- * Optimistic-concurrency: pass `expectedUpdatedAt` to gate the update on
1771
- * the row's current `updated_at`; on mismatch the route returns 409
1772
- * `concurrent_modification` carrying the fresh token.
1773
- */
1774
- async approveMainImage(id, candidateJobId, expectedUpdatedAt) {
1775
- const res = await this.client.request(
1776
- "POST",
1777
- `/v1/creatures/${encodeURIComponent(id)}/approve-main-image`,
1778
- { body: { candidateJobId, expectedUpdatedAt } }
1779
- );
1780
- return { sourceImageUrl: res.sourceImageUrl, canonicalDescription: res.canonicalDescription || null };
1781
- }
1782
- /**
1783
- * Re-fire the LLM caption against the creature's current main image. 502s
1784
- * on LLM failure (unlike `approveMainImage` which preserves the side-effect
1785
- * and returns ""); returns 400 `main_image_required` if no main image is
1786
- * set yet.
1787
- *
1788
- * The route is a pure idempotent retry — it does NOT accept an
1789
- * `expectedUpdatedAt` token (backend route is idempotent retry, not gated on
1790
- * optimistic-concurrency).
1791
- */
1792
- recaption(id) {
1793
- return this.client.request(
1794
- "POST",
1795
- `/v1/creatures/${encodeURIComponent(id)}/llm-caption`
1796
- );
1797
- }
1798
- };
1799
-
1800
- // src/resources/pipelines.ts
1801
- var PipelinesResource = class {
1802
- constructor(client) {
1803
- this.client = client;
1804
- }
1805
- client;
1806
- /**
1807
- * Start a new pipeline (headless film generation) — the programmatic
1808
- * equivalent of the studio's "Create film". In Auto mode the engine
1809
- * self-advances to completion; poll {@link get} for status and
1810
- * {@link getTimeline} for the assembled output. In manual/guided mode, drive
1811
- * it with {@link pendingApprovals} + {@link approveStage} /
1812
- * {@link approveSubGate} / {@link acceptMatchCutBreak}.
1813
- *
1814
- * Requires `pipelines:execute` scope. Returns the new pipeline id.
1815
- */
1816
- create(input) {
1817
- return this.client.request("POST", "/v1/pipelines", { body: input });
1818
- }
1819
- /**
1820
- * Fetch current pipeline state: `status`, `current_stage`, credit counters,
1821
- * `mode`, and `failure_reason` (set when `status='failed'`). Poll this to
1822
- * track a headless Auto run to completion. Requires `pipelines:read`.
1823
- */
1824
- get(id) {
1825
- return this.client.request(
1826
- "GET",
1827
- `/v1/pipelines/${encodeURIComponent(id)}`
1828
- );
1829
- }
1830
- /** List the caller's pipelines (most recent first). Requires `pipelines:read`. */
1831
- list() {
1832
- return this.client.request("GET", "/v1/pipelines");
1833
- }
1834
- /**
1835
- * Cancel a running pipeline. Unspent reserved credits refund. Idempotent on
1836
- * an already-terminal pipeline. Requires `pipelines:execute`.
1837
- */
1838
- cancel(id) {
1839
- return this.client.request(
1840
- "POST",
1841
- `/v1/pipelines/${encodeURIComponent(id)}/cancel`,
1842
- { body: {} }
1843
- );
1844
- }
1845
- /**
1846
- * Stages currently `awaiting_approval`. Empty in a clean Auto run (the engine
1847
- * self-approves); populated in manual/guided mode at each gate. Requires
1848
- * `pipelines:read`.
1849
- */
1850
- pendingApprovals(id) {
1851
- return this.client.request(
1852
- "GET",
1853
- `/v1/pipelines/${encodeURIComponent(id)}/pending-approvals`
1854
- );
1855
- }
1856
- /**
1857
- * Approve a stage so the engine advances to the next one. An optional `edits`
1858
- * JSON-Patch is applied to the stage output before approval. Requires
1859
- * `pipelines:approve`.
1860
- */
1861
- approveStage(id, stage, edits) {
1862
- return this.client.request(
1863
- "POST",
1864
- `/v1/pipelines/${encodeURIComponent(id)}/stages/${encodeURIComponent(stage)}/approve`,
1865
- { body: edits ? { edits } : {} }
1866
- );
1867
- }
1868
- /**
1869
- * Reject a stage with feedback; the engine re-runs it incorporating the note.
1870
- * Requires `pipelines:approve`.
1871
- */
1872
- rejectStage(id, stage, feedback) {
1873
- return this.client.request(
1874
- "POST",
1875
- `/v1/pipelines/${encodeURIComponent(id)}/stages/${encodeURIComponent(stage)}/reject`,
1876
- { body: { feedback } }
1877
- );
1878
- }
1879
- /**
1880
- * Approve a Stage 7 (`animate_audio_edit`) sub-gate — `silent_cut_preview`
1881
- * or `dialogue_recheck` — so the orchestrator resumes from the next
1882
- * sub-step. Stage 6's `match_cut_break_pending` is not approved here: accept
1883
- * each break with {@link acceptMatchCutBreak}. Requires `pipelines:approve`.
1884
- */
1885
- approveSubGate(id, gate) {
1886
- return this.client.request(
1887
- "POST",
1888
- `/v1/pipelines/${encodeURIComponent(id)}/sub-gates/${encodeURIComponent(gate)}/approve`,
1889
- { body: {} }
1890
- );
1891
- }
1892
- /**
1893
- * Accept one match-cut break Stage 6 (`scene_images`) flagged. While any
1894
- * break is pending, the stage pauses at the `match_cut_break_pending`
1895
- * sub-gate, and its output lists the pending shot ids; accepting the last
1896
- * one resumes the stage. `sceneId` is the scene entity that holds the shot.
1897
- * Requires `pipelines:approve`.
1898
- */
1899
- acceptMatchCutBreak(id, sceneId, shotId) {
1900
- return this.client.request(
1901
- "POST",
1902
- `/v1/pipelines/${encodeURIComponent(id)}/entities/${encodeURIComponent(sceneId)}/helpers/accept_match_cut_break`,
1903
- { body: { shotId } }
1904
- );
1905
- }
1906
- /**
1907
- * Read a single stage's `status`, `output`, and `critic_feedback`. Useful for
1908
- * inspecting the script/plan before approving. Requires `pipelines:read`.
1909
- */
1910
- getStage(id, stage) {
1911
- return this.client.request(
1912
- "GET",
1913
- `/v1/pipelines/${encodeURIComponent(id)}/stages/${encodeURIComponent(stage)}`
1914
- );
1915
- }
1916
- /**
1917
- * Assembled timeline — ordered scene composites + durations + audio URLs +
1918
- * live animate progress. The output a headless caller renders or hands to a
1919
- * downstream editor. Requires `pipelines:read`.
1920
- */
1921
- getTimeline(id) {
1922
- return this.client.request(
1923
- "GET",
1924
- `/v1/pipelines/${encodeURIComponent(id)}/timeline`
1925
- );
1926
- }
1927
- /**
1928
- * Branch a completed pipeline into a new pipeline that re-runs from the
1929
- * given stage. The original pipeline's upstream stages and entities are
1930
- * cloned into the new pipeline; downstream stages are created by the
1931
- * orchestrator as it advances.
1932
- *
1933
- * Requires `pipelines:execute` scope.
1934
- * The source pipeline must have `status='completed'`.
1935
- *
1936
- * @returns 201 with `{ pipelineId, clonedStages, clonedEntities }`.
1937
- */
1938
- branch(id, input) {
1939
- return this.client.request(
1940
- "POST",
1941
- `/v1/pipelines/${encodeURIComponent(id)}/branch`,
1942
- { body: input }
1943
- );
1944
- }
1945
- /**
1946
- * Send a chat message to the Showrunner Refinement Director (Guided Mode).
1947
- * Persists user + assistant turns; returns the assistant's reply and an
1948
- * optional `proposed_change` the user can `applyChatProposal` to commit.
1949
- *
1950
- * Requires `pipelines:approve` scope. The pipeline must have
1951
- * `mode='guided'` and the stage must be `awaiting_approval`.
1952
- *
1953
- * Only the Script stage ships a wired specialist in Phase 1D.2b — the other
1954
- * chat-enabled stages (`shot_list`, `post_merge`) return 501 until 1D.2d.
1955
- */
1956
- chatStage(pipelineId, stage, message) {
1957
- return this.client.request(
1958
- "POST",
1959
- `/v1/pipelines/${encodeURIComponent(pipelineId)}/stages/${encodeURIComponent(stage)}/chat`,
1960
- { body: { message } }
1961
- );
1962
- }
1963
- /**
1964
- * Accept a proposed change from a prior assistant turn. Routes through
1965
- * `applyStageEdit` (validates JSON Patch + per-stage schema +
1966
- * reference-integrity, inserts a new pipeline_stage_attempts row, CAS-flips
1967
- * the stage to approved, emits `chat:proposal_applied` SSE).
1968
- *
1969
- * Requires `pipelines:approve` scope.
1970
- *
1971
- * Returns `{ applied: true, attemptId, newOutput }` on success, or
1972
- * `{ applied: false, error }` on recoverable failures (the backend already
1973
- * inserted a follow-up assistant turn with a hint). Hard failures
1974
- * (`patch_invalid`, `stage_not_awaiting`) throw via the standard error
1975
- * pipeline (HTTP 409).
1976
- */
1977
- applyChatProposal(pipelineId, stage, turnId) {
1978
- return this.client.request(
1979
- "POST",
1980
- `/v1/pipelines/${encodeURIComponent(pipelineId)}/stages/${encodeURIComponent(stage)}/chat/turns/${encodeURIComponent(turnId)}/apply`,
1981
- { body: {} }
1982
- );
1983
- }
1984
- /**
1985
- * Fetch the chat history for a stage. Returns an empty array when no turns
1986
- * exist yet (e.g., stage has not been started or the user hasn't sent any
1987
- * messages). Used by the frontend chat panel on initial mount; subsequent
1988
- * updates arrive via SSE (`chat:turn` events).
1989
- *
1990
- * Requires `pipelines:read` scope.
1991
- */
1992
- getStageChat(pipelineId, stage) {
1993
- return this.client.request(
1994
- "GET",
1995
- `/v1/pipelines/${encodeURIComponent(pipelineId)}/stages/${encodeURIComponent(stage)}/chat`
1996
- );
1997
- }
1998
- };
1999
-
2000
- // src/resources/reduce.ts
2001
- var ReduceResource = class {
2002
- constructor(client) {
2003
- this.client = client;
2004
- }
2005
- client;
2006
- /**
2007
- * Run the Reduce (fan-in) node directly — useful for scripted batch
2008
- * scoring, picking the best of N generations outside a workflow, or
2009
- * one-shot programmatic merges.
2010
- *
2011
- * Throws `NodaroError` on 4xx/5xx responses (e.g. `code: "no_valid_inputs"`
2012
- * with status 400 when every input is empty / whitespace; the underlying
2013
- * `EmptyInputError` is mapped to a 400 server-side).
2014
- */
2015
- run(input) {
2016
- return this.client.request("POST", "/v1/reduce", {
2017
- body: {
2018
- strategyId: input.strategyId,
2019
- strategyConfig: input.strategyConfig ?? {},
2020
- inputs: input.inputs,
2021
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
2022
- }
2023
- });
2024
- }
2025
- };
2026
-
2027
- // src/resources/prompt-helper.ts
2028
- var PromptHelperResource = class {
2029
- constructor(client) {
2030
- this.client = client;
2031
- }
2032
- client;
2033
- analyze(input) {
2034
- return this.client.request("POST", "/v1/prompt-helper/wizard", { body: { action: "analyze", ...input } });
2035
- }
2036
- generate(input) {
2037
- return this.client.request("POST", "/v1/prompt-helper/wizard", { body: { action: "generate", ...input } });
2038
- }
2039
- enhance(input) {
2040
- return this.client.request("POST", "/v1/prompt-helper/wizard", { body: { action: "enhance", ...input } });
2041
- }
2042
- };
2043
-
2044
- // src/resources/voices.ts
2045
- var VoicesResource = class {
2046
- constructor(client) {
2047
- this.client = client;
2048
- }
2049
- client;
2050
- /**
2051
- * List the premade ElevenLabs voices (`GET /v1/voices`). Falls back to a
2052
- * curated set server-side when no ElevenLabs API key is configured.
2053
- */
2054
- async list() {
2055
- const res = await this.client.request("GET", "/v1/voices");
2056
- return res.voices;
2057
- }
2058
- /**
2059
- * Search the shared/community Voice Library (`GET /v1/voices/library`). All
2060
- * params are optional and forwarded as a querystring; `undefined` / `null` /
2061
- * empty-string values are omitted so the server defaults apply. `hasMore`
2062
- * drives "load more" pagination.
2063
- */
2064
- searchLibrary(params = {}) {
2065
- const query = {};
2066
- for (const [k, v] of Object.entries(params)) {
2067
- if (v !== void 0 && v !== null && v !== "") query[k] = v;
2068
- }
2069
- return this.client.request("GET", "/v1/voices/library", { query });
2070
- }
2071
- /**
2072
- * List the signed-in user's voice clones (`GET /v1/voice-clones`). The route
2073
- * wraps the rows in `{ voiceClones }`; we unwrap to the bare array.
2074
- */
2075
- async listClones() {
2076
- const res = await this.client.request("GET", "/v1/voice-clones");
2077
- return res.voiceClones;
2078
- }
2079
- /**
2080
- * @deprecated Voice cloning is no longer offered on Nodaro (retired
2081
- * 2026-09-15). The route answers `410 voice_cloning_retired` and this call
2082
- * rejects with that error. Clones created before the retirement are still
2083
- * listed by {@link VoicesResource.listClones} and still work as voice ids.
2084
- * For a new custom voice use {@link VoicesResource.design}.
2085
- */
2086
- createClone(input) {
2087
- return this.client.request("POST", "/v1/voice-clones/from-url", { body: input });
2088
- }
2089
- /** Delete one of the user's voice clones (`DELETE /v1/voice-clones/:id`). */
2090
- async deleteClone(id) {
2091
- await this.client.request("DELETE", `/v1/voice-clones/${encodeURIComponent(id)}`);
2092
- }
2093
- /**
2094
- * Replace the voice in a recording — or in a whole talking video — with a
2095
- * different voice (`POST /v1/voice-changer`). Pass `audioUrl` to revoice
2096
- * audio→audio, or `videoUrl` to revoice an entire clip (the server demuxes
2097
- * the audio, runs speech-to-speech, and remuxes onto the original video,
2098
- * returning the video plus the new audio track). Exactly one of `audioUrl` /
2099
- * `videoUrl` is required; when both are sent, video wins. `removeBackgroundNoise`
2100
- * off keeps the music/SFX bed under the new voice; on yields a clean voice-only
2101
- * result. Costs credits and runs async — poll `jobs.get(jobId)` for the result
2102
- * (`output_data.videoUrl` + `output_data.audioUrl` in video mode).
2103
- */
2104
- change(input) {
2105
- return this.client.request("POST", "/v1/voice-changer", { body: input });
2106
- }
2107
- /**
2108
- * Recast each detected speaker in a multi-speaker recording to a different
2109
- * voice (`POST /v1/voice-changer-pro`). `orderedVoices` maps speaker positions to
2110
- * voices in detection order — speaker 0 → `orderedVoices[0]`, speaker 1 →
2111
- * `orderedVoices[1]`, etc. Speakers beyond the end of `orderedVoices` keep
2112
- * their original voice. Each entry is EITHER a bare voice id (premade name or
2113
- * ElevenLabs UUID) OR a {@link VoiceChangerProVoice} object carrying per-voice
2114
- * ElevenLabs speech-to-speech settings (stability / similarityBoost / style /
2115
- * useSpeakerBoost / `seed`) plus a loudness `volumeMode` (and a manual
2116
- * `volume`) — OR `null`, meaning keep this speaker's original voice (requires
2117
- * a platform running cloud-plugins with keep-slot support). At least one
2118
- * entry must be non-null. A per-voice `seed` makes that speaker's recast
2119
- * reproducible.
2120
- *
2121
- * Pass `audioUrl` for audio-only recast or `videoUrl` to recast the audio
2122
- * track of a video clip (the server demuxes, recasts, and remuxes).
2123
- *
2124
- * Voice and music are ALWAYS separated first — before recasting, the source
2125
- * is split into an isolated vocal stem and a music/SFX stem.
2126
- * `preserveBackground` (default `true`) only controls whether that
2127
- * music/instrumental stem is mixed back under the new voices; set it `false`
2128
- * for a clean voice-only result. `separationQuality` selects the quality of
2129
- * the voice/music separation: `"fast"` (default, quicker — preserves more of
2130
- * the voice) or `"best"` (finer voice/music separation).
2131
- * `removeBackgroundNoise` additionally denoises the result.
2132
- * `musicVolumeMode` sets the level of that preserved background (only relevant
2133
- * when `preserveBackground` is on): `"match"` (default) keeps the original
2134
- * level, `"normalize"` loudnorms it, `"manual"` uses `musicVolume`%.
2135
- * `voiceFx` applies a reverb/echo to the COMBINED recast voices BEFORE the
2136
- * background is mixed back in (effect sits on the voices, not the music bed).
2137
- *
2138
- * Cloud-only — costs credits and runs async; poll `jobs.get(jobId)` for the
2139
- * result (`output_data.videoUrl` + `output_data.audioUrl` in video mode).
2140
- */
2141
- recast(input) {
2142
- return this.client.request("POST", "/v1/voice-changer-pro", { body: input });
2143
- }
2144
- /**
2145
- * Detect the speakers in a clip WITHOUT recasting yet
2146
- * (`POST /v1/voice-changer-pro/analyze`) — the first step of the interactive
2147
- * flow. Separates voice from music once and diarizes the vocals, returning the
2148
- * speaker list so a user (or agent) can choose a voice per speaker before
2149
- * committing to a paid recast. Poll `jobs.get(jobId)`: the completed job's
2150
- * `output_data` carries the separated stem urls + the detected `speakers`
2151
- * (each with `id`, time `segments`, `firstStartSec`, `wordCount`, `snippet`)
2152
- * and the detected language — reshape it into a {@link VcpAnalysis} and pass it
2153
- * as `recast({ ..., analysis })` to skip re-detection. With `suggestTitle`,
2154
- * `output_data.suggestedTitle` also carries an LLM-proposed title.
2155
- *
2156
- * Cloud-only; costs credits and runs async.
2157
- */
2158
- analyze(input) {
2159
- return this.client.request("POST", "/v1/voice-changer-pro/analyze", { body: input });
2160
- }
2161
- /**
2162
- * Render a final video from a mixed set of stems
2163
- * (`POST /v1/voice-changer-pro/export`) — the last step of the interactive
2164
- * flow. After `recast({ output: "stems" })` hands back the dry per-track stems
2165
- * and the user has set levels / mutes / an effect in your editor, pass those
2166
- * `tracks` (plus the source `videoUrl`) here to mix and remux into the finished
2167
- * video. The video is stream-copied (never re-encoded), so the export is
2168
- * bit-identical to your preview. At least one track must be un-muted (all-muted
2169
- * is a 400); `voiceFx` is applied to the voice tracks at render time.
2170
- *
2171
- * Cloud-only; costs credits and runs async — poll `jobs.get(jobId)` for the
2172
- * result (`output_data.videoUrl`).
2173
- */
2174
- exportMix(input) {
2175
- return this.client.request("POST", "/v1/voice-changer-pro/export", { body: input });
2176
- }
2177
- /**
2178
- * Design a brand-new synthetic voice from a text description
2179
- * (`POST /v1/voice-design`) — ElevenLabs text-to-voice. `text` (100–1000 chars)
2180
- * is a preview line spoken in the designed voice; `voiceDescription` describes
2181
- * the voice to create. Costs credits and runs async — poll `jobs.get(jobId)`
2182
- * for the preview + the reusable voice id.
2183
- */
2184
- design(input) {
2185
- return this.client.request("POST", "/v1/voice-design", { body: input });
2186
- }
2187
- /**
2188
- * Generate speech in a voice described in natural language, without cloning
2189
- * (`POST /v1/voice-remix`). `text` (1–5000 chars) is spoken in a voice matching
2190
- * `voiceDescription`. Costs credits and runs async — poll `jobs.get(jobId)`.
2191
- */
2192
- remix(input) {
2193
- return this.client.request("POST", "/v1/voice-remix", { body: input });
2194
- }
2195
- /**
2196
- * Dub an audio clip into another language while preserving each speaker's voice
2197
- * (`POST /v1/dubbing`). `targetLanguage` is an ISO code (e.g. `"es"`, `"fr"`);
2198
- * `sourceLanguage` is auto-detected when omitted. Costs credits and runs async
2199
- * — poll `jobs.get(jobId)`.
2200
- */
2201
- dub(input) {
2202
- return this.client.request("POST", "/v1/dubbing", { body: input });
2203
- }
2204
- /**
2205
- * Voice a multi-speaker script as ONE audio file
2206
- * (`POST /v1/text-to-dialogue`) on ElevenLabs Dialogue v3 — the default — or
2207
- * Dialogue v4 (`provider: "elevenlabs-dialogue-v4"`). Each `dialogue` line is
2208
- * `{ text, voice }` in speaking order — `voice` is a premade voice name or an
2209
- * ElevenLabs voice UUID (cloned/library voices work too; mixed casts are
2210
- * fine). At most 5,000 characters total across lines on Dialogue v3 and
2211
- * 10,000 on Dialogue v4 (≤2,000 recommended for best quality) and 10 unique
2212
- * voices. Line text may
2213
- * carry `[audio tags]` like `[laughs]`. Costs credits and runs async — poll
2214
- * `jobs.get(jobId)` for `output_data.audioUrl` and — on every dialogue model,
2215
- * since both return timings at no extra credits — `output_data.transcript`, a
2216
- * `Transcript` (`@nodaro/shared`): `words[]` with `startMs` / `endMs` /
2217
- * `speaker` and one `segments[]` entry per line, `speaker` being the line's
2218
- * `voice` as you sent it. Pass `transcript.words` to
2219
- * `addCaptions({ captions, autoTranscribe: false })` to caption the dialogue
2220
- * without a second transcription.
2221
- */
2222
- textToDialogue(input) {
2223
- return this.client.request("POST", "/v1/text-to-dialogue", { body: input });
2224
- }
2225
- /**
2226
- * @deprecated Voice cloning is no longer offered on Nodaro (retired
2227
- * 2026-09-15). The route answers `410 voice_cloning_retired` and this call
2228
- * rejects with that error. See {@link VoicesResource.createClone}.
2229
- */
2230
- createCloneFromFile(input) {
2231
- const form = new FormData();
2232
- form.append("name", input.name);
2233
- const blob = input.file instanceof Blob ? input.file : new Blob([input.file], { type: input.contentType ?? "audio/mpeg" });
2234
- form.append("file", blob, input.filename ?? "sample");
2235
- return this.client.request("POST", "/v1/voice-clones", { body: form });
2236
- }
2237
- };
2238
-
2239
- // src/resources/llm.ts
2240
- var LlmResource = class {
2241
- constructor(client) {
2242
- this.client = client;
2243
- }
2244
- client;
2245
- /**
2246
- * Synchronous forced-schema completion (`POST /v1/llm/structured`). A call
2247
- * can run several minutes — longer than the client's default 60 s
2248
- * `timeoutMs`; construct the client with a larger `timeoutMs` for this
2249
- * call, or use {@link LlmResource.structuredJob}.
2250
- */
2251
- structured(input) {
2252
- return this.client.request("POST", "/v1/llm/structured", { body: input });
2253
- }
2254
- /**
2255
- * The same call as a job (`POST /v1/llm/structured/jobs`): answers `{ jobId }`
2256
- * at once. Poll `jobs.getStatus(jobId)` — `output_data` is an
2257
- * {@link LlmStructuredJobOutput}; `error_message` says why a run failed.
2258
- * `jobs.list({ type: "llm-structured", origin })` finds every run later.
2259
- * Throws `NotFoundError` on a platform that predates the route. An instance
2260
- * that proxies its LLM calls to nodaro.ai answers `503 provider_unavailable`
2261
- * permanently — the SDK surfaces that as a generic `NodaroError` with the
2262
- * same code; treat it as unavailable here, not as transient.
2263
- */
2264
- structuredJob(input) {
2265
- return this.client.request("POST", "/v1/llm/structured/jobs", { body: input });
2266
- }
2267
- };
2268
-
2269
- // src/sse.ts
2270
- async function* readSseStream(res, opts = {}) {
2271
- if (!res.ok) {
2272
- let errBody = {};
2273
- try {
2274
- errBody = await res.json();
2275
- } catch {
2276
- }
2277
- throwFromResponse(res.status, errBody);
2278
- }
2279
- if (!res.body) {
2280
- throw new NodaroError(`${opts.label ?? "event stream"} has no response body`, "empty_stream", res.status);
2281
- }
2282
- const reader = res.body.getReader();
2283
- const decoder = new TextDecoder();
2284
- let buffer = "";
2285
- try {
2286
- for (; ; ) {
2287
- const { done, value } = await reader.read();
2288
- if (done) break;
2289
- buffer += decoder.decode(value, { stream: true });
2290
- let sep;
2291
- while ((sep = buffer.indexOf("\n\n")) >= 0) {
2292
- const frame = buffer.slice(0, sep);
2293
- buffer = buffer.slice(sep + 2);
2294
- for (const line of frame.split("\n")) {
2295
- if (!line.startsWith("data:")) continue;
2296
- try {
2297
- yield JSON.parse(line.slice(5).trim());
2298
- } catch {
2299
- }
2300
- }
2301
- }
2302
- }
2303
- } finally {
2304
- reader.releaseLock();
2305
- await res.body.cancel().catch(() => {
2306
- });
2307
- }
2308
- }
2309
-
2310
- // src/resources/media.ts
2311
- var MediaResource = class {
2312
- constructor(client) {
2313
- this.client = client;
2314
- }
2315
- client;
2316
- /**
2317
- * Download a social video (YouTube / TikTok / Instagram / X / Facebook) into
2318
- * your storage (`POST /v1/download-video`). `maxHeight` caps the resolution
2319
- * (default "best"); `sectionStartSec` + `sectionEndSec` (both-or-neither) fetch
2320
- * ONLY that time range instead of the whole video. A download that arrives
2321
- * with no audio stream FAILS by default (it is usually a degraded source
2322
- * response, and is retried through other routes first); pass
2323
- * `requireAudio: false` to accept a clip that really has no sound. Returns a
2324
- * `downloadId`; progress streams from
2325
- * `GET /v1/download-video/progress/:downloadId` (server-sent events) and the
2326
- * finished file lands in your library.
2327
- */
2328
- downloadVideo(input) {
2329
- return this.client.request("POST", "/v1/download-video", { body: input });
2330
- }
2331
- /**
2332
- * Stream the live progress of a {@link MediaResource.downloadVideo} import
2333
- * (`GET /v1/download-video/progress/:downloadId`, server-sent events) as an
2334
- * async iterable. Yields a {@link DownloadVideoProgress} roughly every 500ms
2335
- * until the download reaches `completed` (its event carries the stored
2336
- * `videoUrl`) or `failed` (its event carries `error`), then ends. The progress
2337
- * state expires server-side shortly after the download starts existing, so
2338
- * start iterating promptly after `downloadVideo` returns.
2339
- *
2340
- * No request timeout is applied (a large import legitimately takes minutes) —
2341
- * pass an `AbortSignal` to cancel from the caller.
2342
- */
2343
- async *downloadVideoProgress(downloadId, opts = {}) {
2344
- const url = `${this.client.baseUrl}/v1/download-video/progress/${encodeURIComponent(downloadId)}`;
2345
- const token = await this.client.auth.getToken();
2346
- const res = await this.client.fetch(url, {
2347
- headers: token ? { Authorization: `Bearer ${token}` } : {},
2348
- signal: opts.signal
2349
- });
2350
- yield* readSseStream(res, { label: "progress stream" });
2351
- }
2352
- /**
2353
- * Copy an external media URL into your Nodaro storage (`POST /v1/save-to-storage`)
2354
- * — a server-side fetch, so nothing round-trips through the client. Poll
2355
- * `jobs.get(jobId)`.
2356
- */
2357
- saveToStorage(input) {
2358
- return this.client.request("POST", "/v1/save-to-storage", { body: input });
2359
- }
2360
- /**
2361
- * Composite 2–30 images into ONE large 2K/4K collage (`POST /v1/image-collage`).
2362
- * `layout` `"smart"` (default — justified rows at each image's exact aspect
2363
- * ratio, no cropping; the output height floats) or `"grid"` (uniform,
2364
- * letterboxed cells). `imageSizes` is index-aligned with `imageUrls` and
2365
- * gives per-image RELATIVE size hints for the smart layout: `0` auto
2366
- * ("don't care", default), `1` big (~2× linear vs medium), `2` medium,
2367
- * `3` small (~½ linear). All-equal hints change nothing; grid ignores them.
2368
- * For storyboards, set `numbered` to stamp a 1-based sequence badge at each
2369
- * image's corner (top-left by default; `badgePosition: "top-right"` moves it;
2370
- * in `imageUrls` order) and pass `imageLabels`
2371
- * (index-aligned with `imageUrls`; `null`/`""`/omitted = no caption for that
2372
- * image) to caption images after the number, e.g. `3 · Close-up`. Badges are
2373
- * an overlay only — they never change the layout, the output size or the
2374
- * credit cost. Poll `jobs.get(jobId)` for the finished image.
2375
- */
2376
- imageCollage(input) {
2377
- return this.client.request("POST", "/v1/image-collage", { body: input });
2378
- }
2379
- /**
2380
- * Place 1–12 layers — pictures, real text, QR codes, shapes — on a base image,
2381
- * pixel-exactly (`POST /v1/image-overlay`) — local, deterministic, no AI.
2382
- * Every layer position/size is a PERCENT of the base image: `anchor` (nine
2383
- * positions, default `"center"`), `x`/`y` (offset from the anchor in % of
2384
- * the base width/height; negative on a right/bottom anchor moves inward),
2385
- * `width` (% of the base width, default 25 — height follows the layer's
2386
- * aspect unless `height` is set). Plus `opacity` (0..1), `rotation`
2387
- * (degrees), `blend` (`"over"` | `"multiply"` | `"screen"`), `fit`,
2388
- * `shadow` and `roundedCorners`. The output keeps the base's pixel size
2389
- * unless `canvas` is set. Flat credit cost. Poll `jobs.get(jobId)` for the
2390
- * finished image.
2391
- */
2392
- imageOverlay(input) {
2393
- return this.client.request("POST", "/v1/image-overlay", { body: input });
2394
- }
2395
- /**
2396
- * Ask a vision model WHERE one overlay layer should sit on a base image
2397
- * (`POST /v1/image-overlay/suggest-placement`) — it reads the picture and
2398
- * keeps the element off the faces, the subject and the busiest texture.
2399
- * The answer comes back in {@link MediaResource.imageOverlay}'s own percent
2400
- * units — `anchor`, `x`/`y` offsets, `width` — so it drops straight onto a
2401
- * layer (`const { reason, ...box } = placement`), plus a one-sentence
2402
- * `reason` you can show a user. Nothing is composited here: apply the
2403
- * placement yourself.
2404
- *
2405
- * `layerAspect` is the element's width / height (1 = square, the default) so
2406
- * the proposed box stays in proportion; `intent` says what the element is
2407
- * ("a logo", "a price badge"); `safeArea` is the always-visible region as
2408
- * fractions of the canvas (a platform preset's safe area), which the
2409
- * placement is kept inside. Unlike the other media calls this one answers
2410
- * synchronously — there is nothing to poll; `jobId` is the billing record
2411
- * (one image-to-text call).
2412
- */
2413
- suggestOverlayPlacement(input) {
2414
- return this.client.request(
2415
- "POST",
2416
- "/v1/image-overlay/suggest-placement",
2417
- { body: input }
2418
- );
2419
- }
2420
- /**
2421
- * Trim a video to a range (`POST /v1/trim-video`). Give the range in whichever
2422
- * unit fits: `startTime`/`endTime` seconds, `trim*Frames`, `trim*Seconds`, or
2423
- * `keepFirst`/`keepLastSeconds`. Poll `jobs.get(jobId)`.
2424
- */
2425
- trimVideo(input) {
2426
- return this.client.request("POST", "/v1/trim-video", { body: input });
2427
- }
2428
- /**
2429
- * Burn captions into a video (`POST /v1/add-captions`). Give the words as
2430
- * `text`, word-timed `captions[]`, or let it transcribe (`autoTranscribe`,
2431
- * the default when neither is set).
2432
- *
2433
- * `style: "subtitle"` renders statically (FFmpeg) UNLESS it carries a styling
2434
- * lever, in which case it — like the KINETIC styles (`word-highlight` /
2435
- * `karaoke` / `tiktok-words` / `word-pop` / `bouncy`) — renders via Remotion.
2436
- * `look` picks a preset — `outline` (Montserrat 900, UPPERCASE, black outline,
2437
- * yellow spoken word — the TikTok/Reels read) or `clean`; an UNSET look renders
2438
- * as `outline`. The explicit STYLING levers (`fontFamily`, `fontWeight`,
2439
- * `strokeColor`/`strokeWidth`, `uppercase`, `positionY`, `maxWordsPerLine`)
2440
- * override individual fields of it and now apply to `subtitle` too. Only
2441
- * `highlightColor` (the spoken-word cursor) and `animate` stay kinetic-only
2442
- * and are REJECTED on `subtitle`.
2443
- *
2444
- * `animate` (default true) freezes the per-word MOTION on the kinetic styles
2445
- * when set to false — the grouping, line-holding and spoken-word highlight
2446
- * stay; only the movement stops.
2447
- *
2448
- * `maxWordsPerLine` (1-20) caps how many words a line — or a `tiktok-words`
2449
- * page — may hold, on top of the width budget / sentence ends / pauses that
2450
- * already close one; it is inert on `word-pop`, which is always one word.
2451
- * Like every lever here it exists top-level AND per segment, and a segment
2452
- * that does not name its own inherits the top-level value.
2453
- *
2454
- * `segments[]` applies DIFFERENT treatments to non-overlapping time ranges in
2455
- * one call (e.g. a large top intro, then a small bottom body); a segment that
2456
- * names its own `look` starts fresh from that preset and does not inherit the
2457
- * top-level explicit levers. Poll `jobs.get(jobId)`.
2458
- *
2459
- * `word-highlight` shows ONE held line at a time and a word's
2460
- * `startMs`/`endMs` is its SPOKEN window (what times the highlight, not how
2461
- * long the text is on screen) — so `captions[]` can be handed over verbatim
2462
- * from an `audio.transcribe()` job's `output_data.words`, with
2463
- * `autoTranscribe: false`.
2464
- */
2465
- addCaptions(input) {
2466
- const { autoTranscribe, transcribeProvider, ...rest } = input;
2467
- const body = {
2468
- ...rest,
2469
- ...autoTranscribe !== void 0 ? { auto_transcribe: autoTranscribe } : {},
2470
- ...transcribeProvider !== void 0 ? { transcribe_provider: transcribeProvider } : {}
2471
- };
2472
- return this.client.request("POST", "/v1/add-captions", { body });
2473
- }
2474
- /**
2475
- * Trim (and extract) audio from a video or audio source
2476
- * (`POST /v1/trim-audio`) to `[startTime, endTime]` seconds, in `audioFormat`
2477
- * (`mp3` default / `wav` / `aac`). Poll `jobs.get(jobId)`.
2478
- */
2479
- trimAudio(input) {
2480
- return this.client.request("POST", "/v1/trim-audio", { body: input });
2481
- }
2482
- /**
2483
- * Cut a video and/or an audio file into consecutive parts
2484
- * (`POST /v1/split-media`). Every part is at most `chunkDuration` seconds and
2485
- * at least `minPartDuration` (default 4, never above `chunkDuration`) — a
2486
- * short leftover is evened out with the parts before it. Video is cut on
2487
- * whole frames with each part's sound matching its picture; audio parts are
2488
- * sample-exact, in `audioFormat` (`mp3` default / `wav` / `aac`). With both
2489
- * sources each is split on its own. At most 200 parts per input. Poll
2490
- * `jobs.get(jobId)`; the parts are on the completed job's `output_data` —
2491
- * see {@link SplitMediaOutput}.
2492
- */
2493
- splitMedia(input) {
2494
- return this.client.request("POST", "/v1/split-media", { body: input });
2495
- }
2496
- /**
2497
- * Turn one still image + one audio track into an MP4
2498
- * (`POST /v1/still-to-video`) — locally rendered (FFmpeg), no AI model,
2499
- * zero credits. The output duration IS the audio's duration; there is no
2500
- * duration field. Optional `motion` animates the still (zoom / pan /
2501
- * ken-burns) at `intensity` 1–10. `fit: "contain"` letterboxes with
2502
- * `padColor` instead of cropping. Poll `jobs.get(jobId)`.
2503
- */
2504
- stillToVideo(input) {
2505
- return this.client.request("POST", "/v1/still-to-video", { body: input });
2506
- }
2507
- /**
2508
- * Turn 2–100 images + one optional audio track into an MP4 slideshow
2509
- * (`POST /v1/slideshow`) — locally rendered (FFmpeg), zero credits. With
2510
- * audio, the output duration IS the audio's duration (equal split unless
2511
- * `imageDurations` pins rows — null entries = auto; mismatched pinned sums
2512
- * scale proportionally and the factor is disclosed in the job output).
2513
- * Without audio: N × `perImageDuration`, silent output. Transitions
2514
- * consume the outgoing slide, so totals stay exact. For a single image use
2515
- * `stillToVideo`. Poll `jobs.get(jobId)`.
2516
- */
2517
- slideshow(input) {
2518
- return this.client.request("POST", "/v1/slideshow", { body: input });
2519
- }
2520
- /**
2521
- * Place 1–20 timed image layers over a video (`POST /v1/video-overlay`) —
2522
- * rendered locally (FFmpeg) in one pass, no AI; the base audio is kept
2523
- * untouched. Each layer has an `imageUrl`, a `start` and an optional `end`
2524
- * in seconds (no `end` = to the end of the video) and a placement: a
2525
- * `preset` (`"card"`, `"corner-badge"` with a `corner`, `"full-frame"`) or
2526
- * an explicit box in {@link MediaResource.imageOverlay}'s percent vocabulary
2527
- * (`anchor`, `x`, `y`, `width`, `height`, `fit`) — an explicit box field
2528
- * overrides the preset, and a layer with neither is a corner badge
2529
- * (bottom-right, or the `corner` it names). `outputAspect` renders onto a
2530
- * 16:9 / 9:16 / 1:1 / 4:5 canvas
2531
- * (`baseFit` cover by default; `backgroundColor` pads `contain`). Poll
2532
- * `jobs.get(jobId)`: the output carries `videoUrl`, `thumbnailUrl`, `width`,
2533
- * `height`, `durationSec` and `warnings[]` (a layer clipped or skipped at the
2534
- * video's end, an animated image's first frame, re-encoded audio).
2535
- */
2536
- videoOverlay(input) {
2537
- return this.client.request("POST", "/v1/video-overlay", { body: input });
2538
- }
2539
- /**
2540
- * Track a subject described in plain text through a video and get a
2541
- * black-and-white MASK VIDEO back (`POST /v1/video-mask`, SAM 3.1 by default,
2542
- * or `provider: "sam-3"` at half the price) — white = the subject. Clips up
2543
- * to 5 minutes at 30 fps (a faster clip counts
2544
- * proportionally longer), priced by the clip's length. Poll
2545
- * `jobs.get(jobId)`: the output carries `videoUrl` (the mask), `width`,
2546
- * `height`, `frames` and `coverage` (the fraction of pixels selected). Feed
2547
- * the mask to {@link MediaResource.maskComposite}.
2548
- */
2549
- videoMask(input) {
2550
- return this.client.request("POST", "/v1/video-mask", { body: input });
2551
- }
2552
- /**
2553
- * Place a foreground video over a background video through a mask video
2554
- * (`POST /v1/mask-composite`; white = foreground) — local FFmpeg, no AI.
2555
- * The result follows the foreground's size, frame rate and length; the
2556
- * background is fitted (`backgroundFit`, default cover) and loops when
2557
- * shorter; the mask holds its last frame when shorter. Optional
2558
- * `invertMask`, `feather` (0–20 px), `grow` (−10–10 px) and `audioSource`
2559
- * (foreground / background / mix / none). Priced per started 5 seconds of
2560
- * the result (foreground up to 300 s). Poll `jobs.get(jobId)` for `videoUrl`.
2561
- */
2562
- maskComposite(input) {
2563
- return this.client.request("POST", "/v1/mask-composite", { body: input });
2564
- }
2565
- /**
2566
- * Probe a social video's metadata (`POST /v1/video-metadata`) — duration,
2567
- * dimensions, title, live status — WITHOUT downloading it. A direct read, not a
2568
- * job. Use it to decide whether to trim before importing.
2569
- */
2570
- videoMetadata(input) {
2571
- return this.client.request("POST", "/v1/video-metadata", { body: input });
2572
- }
2573
- /**
2574
- * Cut or crop a stored file (`POST /v1/media/process`) — synchronous and
2575
- * free, the source-preparation sibling of the priced `trimVideo` node.
2576
- * `trim` is `[startTime, endTime]` in seconds; `deleteSource: true` removes
2577
- * the source object afterwards when it is yours and nothing else references
2578
- * it ("the cut replaces the original"). Answers the stored file.
2579
- */
2580
- process(input) {
2581
- return this.client.request("POST", "/v1/media/process", { body: input });
2582
- }
2583
- };
2584
-
2585
- // src/resources/audio.ts
2586
- var AudioResource = class {
2587
- constructor(client) {
2588
- this.client = client;
2589
- }
2590
- client;
2591
- /**
2592
- * Separate an audio track into stems (`POST /v1/audio-separation`, Demucs).
2593
- * `mode` `"vocal_instrumental"` (default) splits voice from music/SFX;
2594
- * `"stems"` returns the full drums/bass/other/… breakdown. `quality`
2595
- * `auto` (default) / `fast` / `best`.
2596
- */
2597
- separate(input) {
2598
- return this.client.request("POST", "/v1/audio-separation", { body: input });
2599
- }
2600
- /** Isolate the primary voice and strip background noise (`POST /v1/audio-isolation`, ElevenLabs). */
2601
- isolate(input) {
2602
- return this.client.request("POST", "/v1/audio-isolation", { body: input });
2603
- }
2604
- /**
2605
- * Apply a reverb / echo / telephone / megaphone effect to an audio track
2606
- * (`POST /v1/audio-fx`) — the same presets VCP's `voiceFx` uses, standalone.
2607
- * `mix` (0–100) is the reverb wet/dry; `delayMs` + `decay` drive `echo`/`custom`;
2608
- * `eqLow`/`eqHigh` (dB) shape telephone/megaphone.
2609
- */
2610
- applyFx(input) {
2611
- return this.client.request("POST", "/v1/audio-fx", { body: input });
2612
- }
2613
- /**
2614
- * Layer multiple audio tracks into one (`POST /v1/mix-audio`). `audioUrls`
2615
- * (2–20) are summed; optional `trackVolumes` (0–200% each, positionally) set
2616
- * per-track level. `duck` puts a music bed under speech: every track EXCEPT
2617
- * `duck.under` (the 0-based index of the voice track) dips while that track
2618
- * is loud and rises back in its pauses (sidechain compression). `amount`
2619
- * (0–100, default 75) is how hard; `thresholdDb` (-60–0, default -30),
2620
- * `ratio` (1–20, overrides `amount`), `attackMs` (1–2000, default 20) and
2621
- * `releaseMs` (10–9000, default 500) are optional fine controls. A ducked mix
2622
- * sums its tracks rather than averaging them, so the voice keeps its level;
2623
- * the price is the same with or without a duck. `endAt` (`"longest"`, the
2624
- * default, or `"voice"`) says where the mix ends: `"voice"` ends it when the
2625
- * voice (the `duck.under` track) ends (needs `duck`). A video URL is a track
2626
- * too: its audio is mixed, and a video with no sound is a silent track.
2627
- */
2628
- mix(input) {
2629
- return this.client.request("POST", "/v1/mix-audio", { body: input });
2630
- }
2631
- /**
2632
- * Adjust an audio (or a video's audio) level (`POST /v1/adjust-volume`):
2633
- * `volume` % (default 100), `normalize` to loudnorm, and `fadeIn`/`fadeOut`
2634
- * seconds. Provide `audioUrl` or `videoUrl`.
2635
- */
2636
- adjustVolume(input) {
2637
- return this.client.request("POST", "/v1/adjust-volume", { body: input });
2638
- }
2639
- /**
2640
- * Shift pitch and/or change tempo with Rubber Band (`POST /v1/pitch-tempo`):
2641
- * `semitones` −12…+12 (default 0), `tempo` 0.5…2 with the pitch kept
2642
- * (default 1; fixed at 1 for a video), `preserveFormants` (default true).
2643
- * Provide exactly one of `audioUrl` or `videoUrl` — a video keeps its picture.
2644
- * Input up to 30 minutes, priced per started minute.
2645
- */
2646
- pitchTempo(input) {
2647
- return this.client.request("POST", "/v1/pitch-tempo", { body: input });
2648
- }
2649
- /**
2650
- * Concatenate audio segments end-to-end (`POST /v1/combine-audio`). Each
2651
- * segment is a `url` with an optional `[startTime, endTime]` sub-range.
2652
- */
2653
- combine(input) {
2654
- return this.client.request("POST", "/v1/combine-audio", { body: input });
2655
- }
2656
- /**
2657
- * Transcribe an audio (or video) track to text (`POST /v1/transcribe`).
2658
- *
2659
- * Three engines are accepted. `elevenlabs-stt` (Scribe) is always word-level,
2660
- * flag or not, and is the only lane that honours `diarize` (who spoke) and
2661
- * `tagAudioEvents` (laughter, applause, …); `incredibly-fast-whisper` returns
2662
- * word timings when you ask for them. `whisper` returns NO word timings at
2663
- * all — named explicitly or reached by OMITTING `provider`, which still falls
2664
- * back to it — so asking it for them (`wordTimestamps: true`) is rejected with
2665
- * a `400 validation_error` at ingress, before any credit is spent. A kinetic
2666
- * caption render therefore has to name one of the other two.
2667
- *
2668
- * Poll `jobs.get(jobId)`; the finished job's `output_data` is a
2669
- * {@link TranscribeJobOutput}: `text` (the whole transcript), `words`
2670
- * (caption-shaped, in MILLISECONDS), `json` (the normalized
2671
- * {@link Transcript}, also ms) — and a top-level `segments` array that is in
2672
- * SECONDS, not ms.
2673
- *
2674
- * `words` is the caption source for a kinetic burn-in: hand it to
2675
- * `media.addCaptions()` as `captions` with `autoTranscribe: false` and the
2676
- * render uses those exact words (correct the `text` of an entry in between
2677
- * and the fix is what burns in).
2678
- */
2679
- transcribe(input) {
2680
- return this.client.request("POST", "/v1/transcribe", { body: input });
2681
- }
2682
- };
2683
-
2684
- // src/resources/credits.ts
2685
- var MODEL_COSTS_LIMIT = 50;
2686
- var CreditsResource = class {
2687
- constructor(client) {
2688
- this.client = client;
2689
- }
2690
- client;
2691
- /**
2692
- * `GET /v1/user/credits` → the authenticated user's credit balance and tier
2693
- * info. Throws `UnauthorizedError` (401) when signed out, and the SDK's
2694
- * other typed errors on the usual statuses.
2695
- */
2696
- async balance() {
2697
- const res = await this.client.request(
2698
- "GET",
2699
- "/v1/user/credits"
2700
- );
2701
- return res.data;
2702
- }
2703
- /**
2704
- * `GET /v1/credits/transactions` → one page of the caller's credit
2705
- * transactions, newest first, with `nextCursor` for the next page (`null`
2706
- * at the end). Read `credits_charged` for what each run cost — it can be
2707
- * below the hold (`credits_reserved`) and is `null` while the hold is open.
2708
- * Cloud-only route: a self-hosted instance answers 404.
2709
- */
2710
- transactions(options = {}) {
2711
- return this.client.request("GET", "/v1/credits/transactions", {
2712
- query: { limit: options.limit, cursor: options.cursor }
2713
- });
2714
- }
2715
- /**
2716
- * `POST /v1/credits/model-costs` → per-identifier credit cost, for editor
2717
- * cost previews. Capped at the first {@link MODEL_COSTS_LIMIT} identifiers
2718
- * (the route's request limit). Preserves the `{ data, missing, errors }`
2719
- * fault-isolation shape verbatim (see {@link ModelCostsResult}).
2720
- */
2721
- modelCosts(ids) {
2722
- return this.client.request("POST", "/v1/credits/model-costs", {
2723
- body: { models: ids.slice(0, MODEL_COSTS_LIMIT) }
2724
- });
2725
- }
2726
- /**
2727
- * `POST /v1/credits/claim-signup-grant` → claims the account's free signup
2728
- * grant, once, with the browser signals of the page making the claim.
2729
- *
2730
- * Call it once per page load as soon as the session is known, and never
2731
- * wait on it for rendering: it is idempotent (a decided account answers
2732
- * with its state and `granted: false`), it costs the user nothing when it
2733
- * fails (the next load asks again), and the signals are what make the
2734
- * claim worth sending — collect them with `collectSignupKeys()` from
2735
- * `@nodaro/sdk/signup-signals` and pass whatever came back, `{}` included.
2736
- * Cloud-only route: a self-hosted instance answers 404.
2737
- */
2738
- claimSignupGrant(keys = {}) {
2739
- return this.client.request("POST", "/v1/credits/claim-signup-grant", {
2740
- body: keys
2741
- });
2742
- }
2743
- // NOTE: no `estimate(...)` helper. The backend exposes
2744
- // `POST /v1/credits/estimate-workflow` (body `{ nodes }` → `{ data: {
2745
- // totalCredits, nodeCount } }`), but no consumer has a settled shape for it
2746
- // yet (studio pre-checks `balance >= Σ modelCosts` client-side rather than
2747
- // calling an estimate endpoint). Adding it now would be inventing an API
2748
- // surface ahead of a real caller, so it's deliberately omitted — add it when
2749
- // a consumer needs it, shaped to that need.
2750
- };
2751
-
2752
- // src/resources/uploads.ts
2753
- var UploadsResource = class {
2754
- constructor(client) {
2755
- this.client = client;
2756
- }
2757
- client;
2758
- /**
2759
- * Upload one file (`POST /v1/upload`, multipart — the file rides the `file`
2760
- * field). The SDK's `request` detects the `FormData` body and lets the
2761
- * runtime set the multipart boundary. Returns the persisted asset's public
2762
- * URL + storage metadata (unwraps the `{ data }` envelope). Throws
2763
- * `StorageExceededError` (413) over the storage cap and the SDK's other typed
2764
- * errors on the usual statuses.
2765
- */
2766
- async upload(file) {
2767
- const form = new FormData();
2768
- form.append("file", file);
2769
- const res = await this.client.request(
2770
- "POST",
2771
- "/v1/upload",
2772
- { body: form }
2773
- );
2774
- return res.data;
2775
- }
2776
- };
2777
-
2778
- // src/resources/library.ts
2779
- var LibraryResource = class {
2780
- constructor(client) {
2781
- this.client = client;
2782
- }
2783
- client;
2784
- /**
2785
- * `GET /v1/library` → a page of the caller's media assets (newest first) plus
2786
- * a `nextCursor`. Pass the returned `nextCursor` back as `cursor` for the next
2787
- * page. Filter by `type` and a filename `search`; `owned: true` returns the
2788
- * full Storage set (uploads + generations), the default only library-saved +
2789
- * shared items.
2790
- */
2791
- list(params = {}) {
2792
- const qs = new URLSearchParams();
2793
- if (params.type) qs.set("type", params.type);
2794
- if (params.search) qs.set("search", params.search);
2795
- if (params.limit !== void 0) qs.set("limit", String(params.limit));
2796
- if (params.cursor) qs.set("cursor", params.cursor);
2797
- if (params.owned !== void 0) qs.set("owned", String(params.owned));
2798
- if (params.source) qs.set("source", params.source);
2799
- const query = qs.toString();
2800
- return this.client.request("GET", `/v1/library${query ? `?${query}` : ""}`);
2801
- }
2802
- };
2803
-
2804
- // src/resources/node-presets.ts
2805
- var PresetsResource = class {
2806
- constructor(client) {
2807
- this.client = client;
2808
- }
2809
- client;
2810
- /**
2811
- * `GET /v1/node-presets` → your custom presets, newest first. Pass `nodeType`
2812
- * (e.g. `"generate-image"`) to filter to one node type.
2813
- */
2814
- async list(nodeType) {
2815
- const qs = nodeType ? `?nodeType=${encodeURIComponent(nodeType)}` : "";
2816
- const res = await this.client.request("GET", `/v1/node-presets${qs}`);
2817
- return res.data;
2818
- }
2819
- /**
2820
- * `GET /v1/node-preset-groups` → your preset folders/sections, in display
2821
- * order. Pass `nodeType` to filter to one node type.
2822
- */
2823
- async listGroups(nodeType) {
2824
- const qs = nodeType ? `?nodeType=${encodeURIComponent(nodeType)}` : "";
2825
- const res = await this.client.request("GET", `/v1/node-preset-groups${qs}`);
2826
- return res.data;
2827
- }
2828
- /**
2829
- * `GET /v1/node-presets/factory` → the built-in catalog for `nodeType`. These
2830
- * ship with the app (no account needed to exist), so they're a good starting
2831
- * point for "what configs are available".
2832
- */
2833
- listFactory(nodeType) {
2834
- return this.client.request(
2835
- "GET",
2836
- `/v1/node-presets/factory?nodeType=${encodeURIComponent(nodeType)}`
2837
- );
2838
- }
2839
- };
2840
-
2841
- // src/resources/saved-posts.ts
2842
- var SavedPostsResource = class {
2843
- constructor(client) {
2844
- this.client = client;
2845
- }
2846
- client;
2847
- /** `GET /v1/saved-posts` → your saves, newest first. Page with `nextCursor`. */
2848
- list(params = {}) {
2849
- return this.client.request("GET", "/v1/saved-posts", {
2850
- query: {
2851
- platform: params.platform,
2852
- tag: params.tag,
2853
- q: params.q,
2854
- cursor: params.cursor,
2855
- limit: params.limit
2856
- }
2857
- });
2858
- }
2859
- /**
2860
- * `POST /v1/saved-posts` → save a post. Saving a post that is already saved
2861
- * updates its note and tags (when given) and returns the existing save.
2862
- */
2863
- save(input) {
2864
- return this.client.request("POST", "/v1/saved-posts", { body: input });
2865
- }
2866
- /** `POST /v1/saved-posts/lookup` → which of these post ids (`SocialPost.id`) you saved. */
2867
- lookup(postIds) {
2868
- return this.client.request("POST", "/v1/saved-posts/lookup", { body: { postIds } });
2869
- }
2870
- /** `PATCH /v1/saved-posts/:id` → change a save's note or tags. */
2871
- update(id, input) {
2872
- return this.client.request("PATCH", `/v1/saved-posts/${encodeURIComponent(id)}`, { body: input });
2873
- }
2874
- /** `DELETE /v1/saved-posts/:id` → remove a save and its copied still. */
2875
- async delete(id) {
2876
- await this.client.request("DELETE", `/v1/saved-posts/${encodeURIComponent(id)}`);
2877
- }
2878
- };
2879
-
2880
- // src/resources/collections.ts
2881
- var CollectionsResource = class {
2882
- constructor(client) {
2883
- this.client = client;
2884
- }
2885
- client;
2886
- /** `GET /v1/collections` → your collections with their record counts, whether the server has collections at all, and your caps. */
2887
- list() {
2888
- return this.client.request("GET", "/v1/collections");
2889
- }
2890
- /** `GET /v1/collections/:id` → one collection. */
2891
- get(id) {
2892
- return this.client.request("GET", `/v1/collections/${encodeURIComponent(id)}`);
2893
- }
2894
- /** `POST /v1/collections` → a new collection (`409 name_taken` when you have one by that name, `403 collection_limit_reached` at your cap). */
2895
- create(input) {
2896
- return this.client.request("POST", "/v1/collections", { body: input });
2897
- }
2898
- /** `PATCH /v1/collections/:id` → rename or re-describe a collection. */
2899
- update(id, input) {
2900
- return this.client.request("PATCH", `/v1/collections/${encodeURIComponent(id)}`, { body: input });
2901
- }
2902
- /** `DELETE /v1/collections/:id` → remove a collection and every record in it. */
2903
- async delete(id) {
2904
- await this.client.request("DELETE", `/v1/collections/${encodeURIComponent(id)}`);
2905
- }
2906
- /**
2907
- * `GET /v1/collections/:id/records` → the records, newest first (`order: "oldest"`
2908
- * flips it). Narrow with `q` (words), `since` / `until` (ISO) and `usage`
2909
- * (`all`, `unused` — not used yet — or `used`); page with `cursor` / `limit`
2910
- * (1-100, default 50). Each record carries `usedAt` / `usedBy`, and its
2911
- * `source` the saving workflow's name and project when it is yours.
2912
- */
2913
- records(id, params = {}) {
2914
- return this.client.request("GET", `/v1/collections/${encodeURIComponent(id)}/records`, {
2915
- query: {
2916
- q: params.q,
2917
- since: params.since,
2918
- until: params.until,
2919
- usage: params.usage,
2920
- status: params.status,
2921
- order: params.order,
2922
- cursor: params.cursor,
2923
- offset: params.offset,
2924
- limit: params.limit
2925
- }
2926
- });
2927
- }
2928
- /** `POST /v1/collections/:id/records/:recordId/restore` → bring a record back from the Trash; the record. */
2929
- restoreRecord(id, recordId) {
2930
- return this.client.request("POST", `/v1/collections/${encodeURIComponent(id)}/records/${encodeURIComponent(recordId)}/restore`);
2931
- }
2932
- /** `POST /v1/collections/:id/records/bulk` → move up to 100 records to the Trash, bring them back, or delete records already in the Trash for good, in one call. */
2933
- bulkRecords(id, input) {
2934
- return this.client.request("POST", `/v1/collections/${encodeURIComponent(id)}/records/bulk`, { body: input });
2935
- }
2936
- /**
2937
- * `PATCH /v1/collections/:id/records/:recordId` → mark a record used (or not
2938
- * used again). `source` says who is marking it (defaults to the API). A
2939
- * server before the usage release answers `503 not_available`.
2940
- */
2941
- setUsed(id, recordId, used, source) {
2942
- return this.client.request("PATCH", `/v1/collections/${encodeURIComponent(id)}/records/${encodeURIComponent(recordId)}`, {
2943
- body: { used, ...source ? { source } : {} }
2944
- });
2945
- }
2946
- /**
2947
- * `POST /v1/collections/:id/records` → save one record. Give the fields, or
2948
- * `item` (any JSON — a feed post, a search result) and let the server map it;
2949
- * explicit fields win. `outcome` is `inserted`, `duplicate` (the same link or
2950
- * dedupe key is already there — the existing record comes back) or `replayed`
2951
- * (a write with the same `idempotencyKey` already happened).
2952
- */
2953
- addRecord(id, input, opts = {}) {
2954
- return this.client.request("POST", `/v1/collections/${encodeURIComponent(id)}/records`, {
2955
- body: input,
2956
- ...opts.idempotencyKey ? { headers: { "Idempotency-Key": opts.idempotencyKey } } : {}
2957
- });
2958
- }
2959
- /**
2960
- * `DELETE /v1/collections/:id/records/:recordId` → the record moves to the
2961
- * collection's Trash (`restoreRecord` brings it back; `deleteRecordForever`
2962
- * removes it for good).
2963
- */
2964
- async deleteRecord(id, recordId) {
2965
- await this.client.request("DELETE", `/v1/collections/${encodeURIComponent(id)}/records/${encodeURIComponent(recordId)}`);
2966
- }
2967
- /** `DELETE /v1/collections/:id/records/:recordId/permanent` → a record already in the Trash is deleted for good (`409 not_in_trash` for a live one). */
2968
- async deleteRecordForever(id, recordId) {
2969
- await this.client.request("DELETE", `/v1/collections/${encodeURIComponent(id)}/records/${encodeURIComponent(recordId)}/permanent`);
2970
- }
2971
- /** `GET /v1/collections/:id/export` → the whole collection as CSV (default) or JSON text, newest first; `since`, `until`, `usage` and `q` narrow it. */
2972
- export(id, params = {}) {
2973
- return this.client.requestText("GET", `/v1/collections/${encodeURIComponent(id)}/export`, {
2974
- query: { format: params.format, since: params.since, until: params.until, usage: params.usage, q: params.q }
2975
- });
2976
- }
2977
- };
2978
-
2979
- // src/resources/competitors.ts
2980
- var CompetitorsResource = class {
2981
- constructor(client) {
2982
- this.client = client;
2983
- }
2984
- client;
2985
- /** `GET /v1/competitors` → every tracked brand. */
2986
- async list() {
2987
- const res = await this.listWithPlan();
2988
- return [...res.data];
2989
- }
2990
- /** `GET /v1/competitors` → every tracked brand, with how many months of scans your plan keeps. */
2991
- listWithPlan() {
2992
- return this.client.request("GET", "/v1/competitors");
2993
- }
2994
- /**
2995
- * `GET /v1/competitors/:id` → one brand with its latest scan (posts and
2996
- * cards) and its scan history; with `scan`, the brand as of that scan.
2997
- */
2998
- get(id, options = {}) {
2999
- const query = options.scan ? `?scan=${encodeURIComponent(options.scan)}` : "";
3000
- return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}${query}`);
3001
- }
3002
- /** `GET /v1/competitors/:id/history` → the brand's scans oldest first, per platform what each found and read (free). */
3003
- history(id) {
3004
- return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}/history`);
3005
- }
3006
- /**
3007
- * `GET /v1/competitors/:id/compare` → the brand over a period, and over a
3008
- * second one to compare with (free). A post belongs to a period by its
3009
- * publish date; a period is at most a year.
3010
- */
3011
- compare(id, input) {
3012
- const params = new URLSearchParams({ from: input.from, to: input.to });
3013
- if (input.vsFrom !== void 0 && input.vsTo !== void 0) {
3014
- params.set("vsFrom", input.vsFrom);
3015
- params.set("vsTo", input.vsTo);
3016
- }
3017
- return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}/compare?${params.toString()}`);
3018
- }
3019
- /** `POST /v1/competitors` → track a brand. Accounts take handles or links. */
3020
- create(input) {
3021
- return this.client.request("POST", "/v1/competitors", { body: input });
3022
- }
3023
- /**
3024
- * `PATCH /v1/competitors/:id` → change its accounts, platforms, name or schedule.
3025
- * `accounts` replaces the whole set: pass every account to keep. Send
3026
- * `schedule` only to change it (it restarts the brand's schedule). While a
3027
- * scan of the brand runs, a change to its name, accounts, platforms or
3028
- * `isOwn` is refused with `409 scan_running`.
3029
- */
3030
- update(id, input) {
3031
- return this.client.request("PATCH", `/v1/competitors/${encodeURIComponent(id)}`, { body: input });
3032
- }
3033
- /** `DELETE /v1/competitors/:id` → stop tracking it (its scans go too). */
3034
- async delete(id) {
3035
- await this.client.request("DELETE", `/v1/competitors/${encodeURIComponent(id)}`);
3036
- }
3037
- /** `GET /v1/competitors/cards` → every action card, most urgent first, with the posts they rest on. */
3038
- cards() {
3039
- return this.client.request("GET", "/v1/competitors/cards");
3040
- }
3041
- /**
3042
- * `GET /v1/competitors/:id/lessons` → what works for a brand: per platform,
3043
- * what its best posts share, measured on its own posts across every stored
3044
- * scan, with the posts each lesson rests on (free). "What works for you" on
3045
- * the brand marked as yours.
3046
- */
3047
- lessons(id) {
3048
- return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}/lessons`);
3049
- }
3050
- /**
3051
- * `GET /v1/competitors/actions` → the cards you marked "I did this", newest
3052
- * first, each with how it went (`outcome`), and your track record per
3053
- * family of advice (free). Each scan of your own brand judges the post that
3054
- * came of a card once it is a few days old; the first verdict stays.
3055
- */
3056
- tried() {
3057
- return this.client.request("GET", "/v1/competitors/actions");
3058
- }
3059
- /**
3060
- * `POST /v1/competitors/actions` → "I did this" on a card on your wall (its
3061
- * `id` from `cards()`), optionally with the link to your post that came of
3062
- * it. Only cards whose advice ends in a post of yours can be marked
3063
- * (`400 not_measurable`). Marking a marked card returns its mark
3064
- * (`created: false`).
3065
- */
3066
- markDone(cardId, options = {}) {
3067
- return this.client.request("POST", "/v1/competitors/actions", { body: { cardId, ...options.postUrl ? { postUrl: options.postUrl } : {} } });
3068
- }
3069
- /**
3070
- * `PATCH /v1/competitors/actions/:id` → link the post that came of a marked
3071
- * card (the post's full link; a short link is refused with `400
3072
- * short_link`), or `null` to remove the link. Another post is judged afresh.
3073
- */
3074
- linkPost(markId, postUrl) {
3075
- return this.client.request("PATCH", `/v1/competitors/actions/${encodeURIComponent(markId)}`, { body: { postUrl } });
3076
- }
3077
- /** `PATCH /v1/competitors/actions/:id` with `seen: true` → you have seen its verdict (the app stops announcing it). */
3078
- markSeen(markId) {
3079
- return this.client.request("PATCH", `/v1/competitors/actions/${encodeURIComponent(markId)}`, { body: { seen: true } });
3080
- }
3081
- /** `DELETE /v1/competitors/actions/:id` → undo "I did this" (its verdict leaves your track record). */
3082
- async unmark(markId) {
3083
- await this.client.request("DELETE", `/v1/competitors/actions/${encodeURIComponent(markId)}`);
3084
- }
3085
- /** `POST /v1/competitor-discover` → a brand's accounts found from its website (free; guesses are marked). */
3086
- discover(website) {
3087
- return this.client.request("POST", "/v1/competitor-discover", { body: { website } });
3088
- }
3089
- /**
3090
- * `POST /v1/competitor-scan` → scan a brand now. Answers with a job id;
3091
- * poll `client.jobs.getStatus(jobId)`, then read `get(id)` or `cards()`.
3092
- */
3093
- scan(id) {
3094
- return this.client.request("POST", "/v1/competitor-scan", { body: { competitorId: id } });
3095
- }
3096
- };
3097
-
3098
- // src/resources/picker-catalogs.ts
3099
- var PickerCatalogsResource = class {
3100
- constructor(client) {
3101
- this.client = client;
3102
- }
3103
- client;
3104
- /** List every parameter-picker node type + its option count. Cached publicly 5 min. */
3105
- list() {
3106
- return this.client.request("GET", "/v1/picker-catalogs");
3107
- }
3108
- /** Fill pickers from a free-text description (Cine "AI Fill"): returns the
3109
- * same pickerJson shape as describe-to-picker, keyed by picker node type. */
3110
- analyzeText(params) {
3111
- return this.client.request("POST", "/v1/text-to-picker", { body: params });
3112
- }
3113
- /** Get one picker's catalog of valid values. */
3114
- get(nodeType, opts = {}) {
3115
- const qs = new URLSearchParams();
3116
- if (opts.detail) qs.set("detail", opts.detail);
3117
- if (opts.category) qs.set("category", opts.category);
3118
- if (opts.field) qs.set("field", opts.field);
3119
- const query = qs.toString();
3120
- return this.client.request(
3121
- "GET",
3122
- `/v1/picker-catalogs/${encodeURIComponent(nodeType)}${query ? `?${query}` : ""}`
3123
- );
3124
- }
3125
- };
3126
-
3127
- // src/resources/catalogs.ts
3128
- var CatalogsResource = class {
3129
- constructor(client) {
3130
- this.client = client;
3131
- }
3132
- client;
3133
- /** Every catalog, projected & pack-composed (honors the deployment's
3134
- * registered vendored packs). Cached publicly 5 min. `data` is absent
3135
- * when the deployment registered no packs (`curated: false`). */
3136
- list(opts = {}) {
3137
- const qs = opts.detail ? `?detail=${opts.detail}` : "";
3138
- return this.client.request("GET", `/v1/catalogs${qs}`);
3139
- }
3140
- };
3141
-
3142
- // src/resources/models.ts
3143
- var ModelsResource = class {
3144
- constructor(client) {
3145
- this.client = client;
3146
- }
3147
- client;
3148
- /** Browse the models available on this instance — capability sheets,
3149
- * per-variant credit pricing, prompt tips, and the `doctrineCovered`
3150
- * truth flag. Public endpoint; cached 5 minutes. */
3151
- list(opts = {}) {
3152
- const qs = new URLSearchParams();
3153
- if (opts.kind) qs.set("kind", opts.kind);
3154
- if (opts.mode) qs.set("mode", opts.mode);
3155
- if (opts.family) qs.set("family", opts.family);
3156
- if (opts.featuredOnly) qs.set("featuredOnly", "true");
3157
- const query = qs.toString();
3158
- return this.client.request("GET", `/v1/models${query ? `?${query}` : ""}`);
3159
- }
3160
- };
3161
-
3162
- // src/resources/shots.ts
3163
- var ShotsResource = class {
3164
- constructor(client) {
3165
- this.client = client;
3166
- }
3167
- client;
3168
- /** Create a shot record. Returns the new shot's id — an unguessable
3169
- * capability string that doubles as the share-link path segment. */
3170
- create(input = {}) {
3171
- return this.client.request("POST", "/v1/shots", { body: input });
3172
- }
3173
- /** Read a shot. Public shots are readable by anyone holding the id;
3174
- * private shots resolve only for their owner (404 otherwise). */
3175
- get(id) {
3176
- return this.client.request("GET", `/v1/shots/${encodeURIComponent(id)}`);
3177
- }
3178
- /** Update an owned shot (any subset of fields, e.g. a visibility toggle). */
3179
- update(id, input) {
3180
- return this.client.request("PATCH", `/v1/shots/${encodeURIComponent(id)}`, { body: input });
3181
- }
3182
- /** Delete an owned shot. */
3183
- async delete(id) {
3184
- await this.client.request("DELETE", `/v1/shots/${encodeURIComponent(id)}`);
3185
- }
3186
- };
3187
-
3188
- // src/resources/recast.ts
3189
- var RecastResource = class {
3190
- constructor(client) {
3191
- this.client = client;
3192
- }
3193
- client;
3194
- // ── Authored-script lane (all three endpoints are free) ────────────────
3195
- /** The generated authoring guide (markdown): document contract, enum
3196
- * vocabularies, bounds, audio rules, and a validated worked example. */
3197
- async authoringSkill() {
3198
- const res = await this.client.request(
3199
- "GET",
3200
- "/v1/video-analysis/authoring-skill"
3201
- );
3202
- return res.markdown ?? "";
3203
- }
3204
- /** FREE validation of an authored script. Loop until `valid: true`. */
3205
- validateScript(script) {
3206
- return this.client.request("POST", "/v1/video-analysis/import/validate", {
3207
- body: { script }
3208
- });
3209
- }
3210
- /**
3211
- * Import a VALIDATED authored script as a completed analysis job.
3212
- * `rightsAttested: true` is required (403 otherwise) — authored recasts
3213
- * render Faithful, exactly as written, so only import work you own.
3214
- */
3215
- importScript(script, opts) {
3216
- return this.client.request("POST", "/v1/video-analysis/import", {
3217
- body: { script, rightsAttested: opts.rightsAttested }
3218
- });
3219
- }
3220
- // ── Run lane ───────────────────────────────────────────────────────────
3221
- /** Quote a run (credits) before buying the plan. */
3222
- estimate(input) {
3223
- return this.client.request("POST", "/v1/recast/estimate", { body: input });
3224
- }
3225
- /** Create a run (buys the plan). Returns `{ recastId }`. */
3226
- create(input) {
3227
- return this.client.request("POST", "/v1/recast", { body: input });
3228
- }
3229
- /** Poll the run — status plus any pending interactive step. */
3230
- get(recastId) {
3231
- return this.client.request("GET", `/v1/recast/${encodeURIComponent(recastId)}`);
3232
- }
3233
- /** Quote a revisioned Music replacement and/or complete desired mix. Free. */
3234
- estimateRescore(recastId, input) {
3235
- return this.client.request(
3236
- "POST",
3237
- `/v1/recast/${encodeURIComponent(recastId)}/estimate-rescore`,
3238
- { body: input }
3239
- );
3240
- }
3241
- /** Apply a quoted audio operation. Reuse its request id only for a transport retry. */
3242
- rescore(recastId, input) {
3243
- return this.client.request(
3244
- "POST",
3245
- `/v1/recast/${encodeURIComponent(recastId)}/rescore`,
3246
- { body: input }
3247
- );
3248
- }
3249
- /** Start rendering a `planned` run. Idempotent server-side. */
3250
- start(recastId, opts = {}) {
3251
- return this.client.request("POST", `/v1/recast/${encodeURIComponent(recastId)}/start`, {
3252
- body: opts
3253
- });
3254
- }
3255
- /** Answer a pending interactive gate (the pick itself is free). */
3256
- resolveGate(recastId, input) {
3257
- return this.client.request("POST", `/v1/recast/${encodeURIComponent(recastId)}/select`, {
3258
- body: input
3259
- });
3260
- }
3261
- };
3262
-
3263
- // src/resources/studio-productions.ts
3264
- function isStudioGenerateEstimate(result) {
3265
- return result.dryRun === true;
3266
- }
3267
- var StudioProductionsResource = class {
3268
- constructor(client) {
3269
- this.client = client;
3270
- }
3271
- client;
3272
- path(productionId, suffix = "") {
3273
- return `/v1/studio/productions/${encodeURIComponent(productionId)}${suffix}`;
3274
- }
3275
- // ── reads ────────────────────────────────────────────────────────────────
3276
- /**
3277
- * The authoring guide, the full catalog, the plan's JSON Schema and the
3278
- * operating guide — rendered server-side from the version that is live, so
3279
- * they describe the platform you are actually talking to. Free.
3280
- */
3281
- async skill() {
3282
- const res = await this.client.request(
3283
- "GET",
3284
- "/v1/studio/productions/skill"
3285
- );
3286
- return res.data;
3287
- }
3288
- /**
3289
- * Check a plan before it becomes anything. Free, persists nothing, and
3290
- * resolves cast names against YOUR library — loop on `errors` until
3291
- * `valid: true`, then `create({ plan })`.
3292
- */
3293
- async validatePlan(plan) {
3294
- const res = await this.client.request(
3295
- "POST",
3296
- "/v1/studio/productions/validate",
3297
- { body: { plan } }
3298
- );
3299
- return res.data;
3300
- }
3301
- /** Your productions, newest first. Archived rows are hidden unless asked for. */
3302
- async list(opts = {}) {
3303
- const res = await this.client.request(
3304
- "GET",
3305
- "/v1/studio/productions",
3306
- {
3307
- query: {
3308
- limit: opts.limit,
3309
- cursor: opts.cursor,
3310
- includeArchived: opts.includeArchived
3311
- }
3312
- }
3313
- );
3314
- return res.data;
3315
- }
3316
- /**
3317
- * One production. A pure read — it never lands a finished job, so call
3318
- * {@link reconcile} first if you are waiting on one.
3319
- */
3320
- async get(productionId, opts = {}) {
3321
- const res = await this.client.request(
3322
- "GET",
3323
- this.path(productionId),
3324
- { query: { detail: opts.detail, shot_id: opts.shotId } }
3325
- );
3326
- return res.data.production;
3327
- }
3328
- /**
3329
- * The ordered steps that assemble the film, with what they will cost. Run
3330
- * them yourself with the ordinary verbs — nothing here blocks for minutes,
3331
- * and nothing here spends.
3332
- */
3333
- async exportPlan(productionId, opts = {}) {
3334
- const res = await this.client.request(
3335
- "GET",
3336
- this.path(productionId, "/export-plan"),
3337
- { query: { upscale: opts.upscale } }
3338
- );
3339
- return res.data;
3340
- }
3341
- // ── writes ───────────────────────────────────────────────────────────────
3342
- /** A new production, optionally landed from a plan in the same call. */
3343
- async create(input = {}) {
3344
- const res = await this.client.request(
3345
- "POST",
3346
- "/v1/studio/productions",
3347
- { body: input }
3348
- );
3349
- return res.data;
3350
- }
3351
- async ops(productionId, input) {
3352
- if (input.dryRun !== true) {
3353
- const res2 = await this.client.request(
3354
- "POST",
3355
- this.path(productionId, "/ops"),
3356
- { body: input }
3357
- );
3358
- return res2.data;
3359
- }
3360
- const ping = await this.client.request(
3361
- "POST",
3362
- this.path(productionId, "/ops"),
3363
- { body: { ops: [], dryRun: true } }
3364
- );
3365
- if (ping?.data?.dryRun !== true) throw new StudioPreviewUnavailable();
3366
- const res = await this.client.request("POST", this.path(productionId, "/ops"), { body: input });
3367
- const data = res?.data;
3368
- if (data?.dryRun !== true) {
3369
- throw new StudioPreviewAppliedError(data);
3370
- }
3371
- return data;
3372
- }
3373
- /**
3374
- * Land every generation that has finished since you last looked, and report
3375
- * what is still running. The one call that turns finished jobs into results
3376
- * without a browser open. It writes only when something actually landed.
3377
- */
3378
- async reconcile(productionId) {
3379
- const res = await this.client.request(
3380
- "POST",
3381
- this.path(productionId, "/reconcile")
3382
- );
3383
- return res.data;
3384
- }
3385
- /** Add a plan's scenes to a production that already exists. */
3386
- async importPlan(productionId, plan, opts = {}) {
3387
- const res = await this.client.request(
3388
- "POST",
3389
- this.path(productionId, "/import"),
3390
- { body: { plan, mode: opts.mode ?? "append" } }
3391
- );
3392
- return res.data;
3393
- }
3394
- /**
3395
- * Turn a brief into scenes. The run is a platform job: poll it, and its
3396
- * scenes land through {@link reconcile}. The production comes back with the
3397
- * run recorded on it as a pending draft.
3398
- */
3399
- async describe(productionId, input) {
3400
- const res = await this.client.request(
3401
- "POST",
3402
- this.path(productionId, "/describe"),
3403
- { body: input }
3404
- );
3405
- return res.data;
3406
- }
3407
- async generate(productionId, input) {
3408
- const res = await this.client.request(
3409
- "POST",
3410
- this.path(productionId, "/generate"),
3411
- { body: input }
3412
- );
3413
- return res.data;
3414
- }
3415
- generateStill(productionId, shotId, opts = {}) {
3416
- return this.generate(productionId, { ...opts, kind: "still", shotId });
3417
- }
3418
- generateClip(productionId, shotId, opts = {}) {
3419
- return this.generate(productionId, { ...opts, kind: "clip", shotId });
3420
- }
3421
- // ── media on one shot ────────────────────────────────────────────────────
3422
- /**
3423
- * Extract a frame from a shot's active clip and put it where `target` says —
3424
- * a new shot after this one (the default), this shot's sticky start or end
3425
- * frame, or another still of the same shot. Seconds, not minutes: this one
3426
- * waits for the job and answers with the changed production.
3427
- */
3428
- async frame(productionId, input) {
3429
- const res = await this.client.request(
3430
- "POST",
3431
- this.path(productionId, "/frame"),
3432
- { body: input }
3433
- );
3434
- return res.data;
3435
- }
3436
- /** Synthesize a shot's spoken line and record it. Waits for the job. */
3437
- async voice(productionId, input) {
3438
- const res = await this.client.request(
3439
- "POST",
3440
- this.path(productionId, "/voice"),
3441
- { body: input }
3442
- );
3443
- return res.data;
3444
- }
3445
- /**
3446
- * Recast the voices of a shot's active clip. Minutes of work, so it answers
3447
- * `jobId` and the new clip lands as a result through its own marker.
3448
- */
3449
- async revoice(productionId, input) {
3450
- const res = await this.client.request(
3451
- "POST",
3452
- this.path(productionId, "/revoice"),
3453
- { body: input }
3454
- );
3455
- return res.data;
3456
- }
3457
- /** Score the film. The finished track lands through its pending marker. */
3458
- async music(productionId, input) {
3459
- const res = await this.client.request(
3460
- "POST",
3461
- this.path(productionId, "/music"),
3462
- { body: input }
3463
- );
3464
- return res.data;
3465
- }
3466
- // ── audience and copies ──────────────────────────────────────────────────
3467
- /**
3468
- * Open the share-by-link read. Deliberately its own route rather than an
3469
- * operation: who may see the work is decided by the owner, never as a side
3470
- * effect of a batch that was editing something else.
3471
- */
3472
- async share(productionId) {
3473
- const res = await this.client.request(
3474
- "POST",
3475
- this.path(productionId, "/share"),
3476
- { body: { shared: true } }
3477
- );
3478
- return res.data.production;
3479
- }
3480
- /** Close it again. Sharing is opt-in AND reversible. */
3481
- async unshare(productionId) {
3482
- const res = await this.client.request(
3483
- "POST",
3484
- this.path(productionId, "/unshare")
3485
- );
3486
- return res.data.production;
3487
- }
3488
- /**
3489
- * Copy a production you own or can see into your own Studio project. The
3490
- * copy starts PRIVATE and visible — sharing and archiving never travel — and
3491
- * it is copied through YOUR view of the source, so somebody else's bin does
3492
- * not come with it.
3493
- */
3494
- async clone(productionId, input = {}) {
3495
- const res = await this.client.request(
3496
- "POST",
3497
- this.path(productionId, "/clone"),
3498
- { body: input }
3499
- );
3500
- return res.data.production;
3501
- }
3502
- };
3503
-
3504
- // src/resources/studio.ts
3505
- var root = "/v1/studio/productions";
3506
- var path = (id) => `${root}/${encodeURIComponent(id)}`;
3507
- var StudioResource = class {
3508
- constructor(client) {
3509
- this.client = client;
3510
- this.productions = new StudioProductionsResource(client);
3511
- }
3512
- client;
3513
- productions;
3514
- capabilities() {
3515
- return this.client.request("GET", `${root}/capabilities`);
3516
- }
3517
- skill() {
3518
- return this.client.request("GET", `${root}/skill`);
3519
- }
3520
- list(options = {}) {
3521
- return this.client.request("GET", root, { query: options });
3522
- }
3523
- get(id, options = {}) {
3524
- return this.client.request("GET", path(id), { query: { detail: options.detail, shot_id: options.shotId } });
3525
- }
3526
- validatePlan(plan) {
3527
- return this.client.request("POST", `${root}/validate`, { body: { plan } });
3528
- }
3529
- create(input) {
3530
- return this.client.request("POST", root, { body: input });
3531
- }
3532
- /** Import a portable document through the compatible server writer.
3533
- * Retained frame media requires an authorized source; acceptance never transfers. */
3534
- importBundle(input) {
3535
- return this.client.request("POST", `${root}/import-bundle`, { body: input });
3536
- }
3537
- /** Append a bundle's scenes and frame closure under an exact destination revision. */
3538
- appendBundle(id, input) {
3539
- return this.client.request("POST", `${path(id)}/import-bundle`, { body: input });
3540
- }
3541
- /** Copy a saved production. Linked copies retain verified inputs, remap
3542
- * dependencies and require fresh frame acceptance; they start no media jobs. */
3543
- clone(id, input = {}) {
3544
- return this.client.request("POST", `${path(id)}/clone`, { body: input });
3545
- }
3546
- edit(id, input) {
3547
- return this.client.request("POST", `${path(id)}/ops`, { body: input });
3548
- }
3549
- /** Audience-authorized sharing; an expected revision prevents publication
3550
- * of concurrent edits the caller has not reviewed. */
3551
- setShared(id, input) {
3552
- return this.client.request("POST", `${path(id)}/share`, { body: input });
3553
- }
3554
- /** Save ordinary editor fields against the loaded revision. Protected frame
3555
- * and job state can only change through their dedicated semantic actions. */
3556
- saveEditorState(id, input) {
3557
- return this.edit(id, {
3558
- baseVersion: input.expectedVersion,
3559
- strict: true,
3560
- ...input.clientRequestId ? { clientRequestId: input.clientRequestId } : {},
3561
- ops: [{ op: "save_editor_state", expectedVersion: input.expectedVersion, graph: input.graph }]
3562
- });
3563
- }
3564
- generateKeyframe(id, input) {
3565
- return this.client.request("POST", `${path(id)}/generate`, { body: { ...input, kind: "keyframe" } });
3566
- }
3567
- generateShot(id, input) {
3568
- return this.client.request("POST", `${path(id)}/generate`, { body: input });
3569
- }
3570
- /** A separate explicit review action; generation never calls this method. */
3571
- acceptKeyframe(id, input, concurrency = {}) {
3572
- return this.edit(id, { ...concurrency, ops: [{ ...input, op: "accept_keyframe_result" }] });
3573
- }
3574
- reconcile(id) {
3575
- return this.client.request("POST", `${path(id)}/reconcile`, { body: {} });
3576
- }
3577
- };
3578
-
3579
- // src/resources/copilot.ts
3580
- var COPILOT_FRAME_TYPES = /* @__PURE__ */ new Set([
3581
- "metadata",
3582
- "token",
3583
- "tool_call",
3584
- "workflow_updated",
3585
- "workflow_created",
3586
- "run_proposed",
3587
- "memory_saved",
3588
- "usage",
3589
- "done",
3590
- "error"
3591
- ]);
3592
- function isCopilotFrame(value) {
3593
- if (typeof value !== "object" || value === null) return false;
3594
- const type = value.type;
3595
- return typeof type === "string" && COPILOT_FRAME_TYPES.has(type);
3596
- }
3597
- var CopilotResource = class {
3598
- constructor(client) {
3599
- this.client = client;
3600
- }
3601
- client;
3602
- /**
3603
- * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on
3604
- * a workflow the server creates from `prompt`. Re-opening a workflow that
3605
- * already has an active thread answers THAT thread rather than a second one.
3606
- */
3607
- create(input) {
3608
- return this.client.request("POST", "/v1/copilot/threads", { body: input });
3609
- }
3610
- /**
3611
- * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),
3612
- * or `null` when the user has none open on it.
3613
- */
3614
- list(params) {
3615
- return this.client.request("GET", "/v1/copilot/threads", { query: { workflowId: params.workflowId } });
3616
- }
3617
- /**
3618
- * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads
3619
- * only what followed that sequence number (the panel's catch-up); `limit`
3620
- * caps the page at the server's own ceiling.
3621
- */
3622
- get(id, opts = {}) {
3623
- return this.client.request("GET", `/v1/copilot/threads/${encodeURIComponent(id)}`, {
3624
- query: { ...opts.after !== void 0 ? { after: opts.after } : {}, ...opts.limit !== void 0 ? { limit: opts.limit } : {} }
3625
- });
3626
- }
3627
- /**
3628
- * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not
3629
- * deletion — the messages stay readable. Refused while a turn is running.
3630
- */
3631
- archive(id) {
3632
- return this.client.request("DELETE", `/v1/copilot/threads/${encodeURIComponent(id)}`);
3633
- }
3634
- /**
3635
- * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the
3636
- * turn it asked to stop; the turn's own stream ends with a `done` frame.
3637
- */
3638
- cancel(id) {
3639
- return this.client.request("POST", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`);
3640
- }
3641
- /**
3642
- * Send one message and iterate the turn's frames
3643
- * (`POST /v1/copilot/threads/:id/messages`, server-sent events).
3644
- *
3645
- * Deliberately NOT routed through `client.request`: that path arms an abort
3646
- * timer around the whole exchange, and a turn legitimately runs for minutes —
3647
- * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller
3648
- * owns the lifetime instead: pass `signal` to end the stream, or stop
3649
- * iterating (the reader cancels the body, which ends the request).
3650
- *
3651
- * A frame kind this package does not model is skipped rather than thrown, so
3652
- * a newer server cannot break an older caller.
3653
- */
3654
- async *stream(threadId, opts) {
3655
- const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`;
3656
- const token = await this.client.auth.getToken();
3657
- const res = await this.client.fetch(url, {
3658
- method: "POST",
3659
- headers: {
3660
- "Content-Type": "application/json",
3661
- ...token ? { Authorization: `Bearer ${token}` } : {}
3662
- },
3663
- body: JSON.stringify({
3664
- message: opts.message,
3665
- ...opts.baseVersion !== void 0 ? { baseVersion: opts.baseVersion } : {},
3666
- ...opts.tier ? { tier: opts.tier } : {}
3667
- }),
3668
- signal: opts.signal
3669
- });
3670
- for await (const value of readSseStream(res, { label: "copilot stream" })) {
3671
- if (isCopilotFrame(value)) yield value;
3672
- }
3673
- }
3674
- };
3675
-
3676
- // src/resources/community.ts
3677
- var CommunityResource = class {
3678
- constructor(client) {
3679
- this.client = client;
3680
- }
3681
- client;
3682
- /**
3683
- * `GET /v1/community/browse` → a page of public listings plus a `nextCursor`.
3684
- * Pass the returned `nextCursor` back as `cursor` to fetch the next page.
3685
- */
3686
- browse(params = {}) {
3687
- const qs = new URLSearchParams();
3688
- if (params.entityType) qs.set("entityType", params.entityType);
3689
- if (params.q) qs.set("q", params.q);
3690
- if (params.category) qs.set("category", params.category);
3691
- if (params.sort) qs.set("sort", params.sort);
3692
- if (params.cursor) qs.set("cursor", params.cursor);
3693
- if (params.limit !== void 0) qs.set("limit", String(params.limit));
3694
- const query = qs.toString();
3695
- return this.client.request(
3696
- "GET",
3697
- `/v1/community/browse${query ? `?${query}` : ""}`
3698
- );
3699
- }
3700
- /** `GET /v1/community/detail/:slug` → a single listing by its slug. */
3701
- get(slug) {
3702
- return this.client.request(
3703
- "GET",
3704
- `/v1/community/detail/${encodeURIComponent(slug)}`
3705
- );
3706
- }
3707
- /**
3708
- * `GET /v1/community/detail/:slug/full` → the full read-only detail (card
3709
- * identity + the stored public snapshot). Like {@link get}, but includes the
3710
- * snapshot asset/voice/text blob needed to render the full cross-user view.
3711
- */
3712
- getFull(slug) {
3713
- return this.client.request(
3714
- "GET",
3715
- `/v1/community/detail/${encodeURIComponent(slug)}/full`
3716
- );
3717
- }
3718
- /** `GET /v1/community/favorites` → the listings you've favorited. */
3719
- favorites() {
3720
- return this.client.request("GET", "/v1/community/favorites");
3721
- }
3722
- /**
3723
- * `POST /v1/community/listings/:id/clone` → copy a listing into your library.
3724
- * Returns the new asset's `entityType` and `id`. Requires the `assets:write`
3725
- * scope when called with an OAuth app token.
3726
- */
3727
- clone(id, entityType) {
3728
- return this.client.request(
3729
- "POST",
3730
- `/v1/community/listings/${encodeURIComponent(id)}/clone`,
3731
- { body: { entityType } }
3732
- );
3733
- }
3734
- /**
3735
- * `POST /v1/community/listings/:id/favorite` → toggle a favorite. Returns the
3736
- * resulting `favorited` state (`true` after adding, `false` after removing).
3737
- */
3738
- favorite(id) {
3739
- return this.client.request(
3740
- "POST",
3741
- `/v1/community/listings/${encodeURIComponent(id)}/favorite`
3742
- );
3743
- }
3744
- /**
3745
- * `POST /v1/community/listings/:id/report` → flag a listing for moderation.
3746
- * `reason` must be one of {@link CommunityReportReason}.
3747
- */
3748
- report(id, reason) {
3749
- return this.client.request(
3750
- "POST",
3751
- `/v1/community/listings/${encodeURIComponent(id)}/report`,
3752
- { body: { reason } }
3753
- );
3754
- }
3755
- /**
3756
- * `POST /v1/admin/community/:entityType/:id/publish` → share one of YOUR
3757
- * entities to the community, returning the new listing's `slug` + `id`.
3758
- *
3759
- * **Requires an admin token** (the route is `requireAdmin`) AND the caller
3760
- * must own the source entity. Personal/OAuth tokens without admin role get a
3761
- * 401. For `character` listings, `params.likenessAttestation` must be `true`.
3762
- */
3763
- publish(entityType, entityId, params) {
3764
- return this.client.request(
3765
- "POST",
3766
- `/v1/admin/community/${encodeURIComponent(entityType)}/${encodeURIComponent(entityId)}/publish`,
3767
- { body: params }
3768
- );
3769
- }
3770
- /**
3771
- * `DELETE /v1/admin/community/listings/:id` → unshare (deactivate) a listing
3772
- * you published. **Requires an admin token** (the route is `requireAdmin`).
3773
- */
3774
- unpublish(listingId) {
3775
- return this.client.request(
3776
- "DELETE",
3777
- `/v1/admin/community/listings/${encodeURIComponent(listingId)}`
3778
- );
3779
- }
3780
- /**
3781
- * `GET /v1/admin/community/by-source/:entityType/:sourceId` → look up YOUR
3782
- * existing listing (if any) for a source entity. Returns `{ data: null }`
3783
- * when the entity hasn't been shared. **Requires an admin token** (the route
3784
- * is `requireAdmin`); only returns listings created by the caller.
3785
- */
3786
- sharedListing(entityType, sourceId) {
3787
- return this.client.request(
3788
- "GET",
3789
- `/v1/admin/community/by-source/${encodeURIComponent(entityType)}/${encodeURIComponent(sourceId)}`
3790
- );
3791
- }
3792
- };
3793
-
3794
- // src/resources/templates.ts
3795
- var TemplatesResource = class {
3796
- constructor(client) {
3797
- this.client = client;
3798
- }
3799
- client;
3800
- /** Browse the public template marketplace (cursor-paginated, no auth required). */
3801
- browse(params = {}) {
3802
- return this.client.request("GET", "/v1/templates/browse", { query: { ...params } });
3803
- }
3804
- /** Fetch one public template by slug, including its full workflow snapshot. */
3805
- get(slug) {
3806
- return this.client.request("GET", `/v1/templates/${encodeURIComponent(slug)}`);
3807
- }
3808
- /** Clone a template into one of the caller's projects. Free — no credits charged. */
3809
- clone(slug, params) {
3810
- return this.client.request("POST", `/v1/templates/${encodeURIComponent(slug)}/clone`, {
3811
- body: params
3812
- });
3813
- }
3814
- };
3815
-
3816
- // src/resources/tutorials.ts
3817
- var TutorialsResource = class {
3818
- constructor(client) {
3819
- this.client = client;
3820
- }
3821
- client;
3822
- /** All enabled tutorial categories with their videos and flow tutorials. Public. */
3823
- list() {
3824
- return this.client.request("GET", "/v1/tutorials");
3825
- }
3826
- };
3827
-
3828
- // src/resources/organizations.ts
3829
- var OrganizationsResource = class {
3830
- constructor(client) {
3831
- this.client = client;
3832
- }
3833
- client;
3834
- /** The organizations this account belongs to. */
3835
- list() {
3836
- return this.client.request("GET", "/v1/orgs");
3837
- }
3838
- get(id) {
3839
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(id)}`);
3840
- }
3841
- /**
3842
- * Create an organization. On instances that require it, `acceptTerms` must
3843
- * be true or the server answers `terms_required` — the SDK does not decide
3844
- * whether terms apply, because only the instance knows.
3845
- *
3846
- * A new organization may come back `pending`: some instances hold new
3847
- * organizations for a platform admin to approve, and a pending one grants
3848
- * nothing until it is active.
3849
- */
3850
- create(input) {
3851
- return this.client.request("POST", "/v1/orgs", { body: input });
3852
- }
3853
- update(id, input) {
3854
- return this.client.request("PATCH", `/v1/orgs/${encodeURIComponent(id)}`, { body: input });
3855
- }
3856
- /** Soft-delete. The organization stops granting context; nothing is destroyed. */
3857
- delete(id) {
3858
- return this.client.request("DELETE", `/v1/orgs/${encodeURIComponent(id)}`);
3859
- }
3860
- /** Hand the organization to another member. The caller becomes an admin. */
3861
- transferOwnership(id, userId) {
3862
- return this.client.request("POST", `/v1/orgs/${encodeURIComponent(id)}/transfer-ownership`, {
3863
- body: { userId }
3864
- });
3865
- }
3866
- /** Leave. An owner cannot — transfer ownership first (`owner_cannot_leave`). */
3867
- leave(id) {
3868
- return this.client.request("POST", `/v1/orgs/${encodeURIComponent(id)}/leave`);
3869
- }
3870
- // -- members --------------------------------------------------------------
3871
- listMembers(orgId, opts = {}) {
3872
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/members`, { query: { ...opts } });
3873
- }
3874
- updateMember(orgId, userId, input) {
3875
- return this.client.request(
3876
- "PATCH",
3877
- `/v1/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(userId)}`,
3878
- { body: input }
3879
- );
3880
- }
3881
- removeMember(orgId, userId) {
3882
- return this.client.request(
3883
- "DELETE",
3884
- `/v1/orgs/${encodeURIComponent(orgId)}/members/${encodeURIComponent(userId)}`
3885
- );
3886
- }
3887
- // -- invitations ----------------------------------------------------------
3888
- /**
3889
- * Invite by email. Returns ONE ROW PER ADDRESS, and a row whose `status` is
3890
- * not `sent` carries a `link` instead.
3891
- *
3892
- * Surface that link. An install with no mail provider — every fresh
3893
- * self-host — delivers nothing, and an integration that reports "invited"
3894
- * without showing the link creates invitations nobody can ever reach.
3895
- */
3896
- invite(orgId, input) {
3897
- return this.client.request("POST", `/v1/orgs/${encodeURIComponent(orgId)}/invitations`, { body: input });
3898
- }
3899
- listInvitations(orgId, opts = {}) {
3900
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/invitations`, {
3901
- query: { ...opts }
3902
- });
3903
- }
3904
- revokeInvitation(id) {
3905
- return this.client.request("DELETE", `/v1/invitations/${encodeURIComponent(id)}`);
3906
- }
3907
- resendInvitation(id) {
3908
- return this.client.request("POST", `/v1/invitations/${encodeURIComponent(id)}/resend`);
3909
- }
3910
- /**
3911
- * What an invitee sees before signing in — the one organization read that
3912
- * needs no token, so it works while the recipient is still signed out.
3913
- */
3914
- previewInvitation(token) {
3915
- return this.client.request("GET", `/v1/invitations/by-token/${encodeURIComponent(token)}`);
3916
- }
3917
- /** Accept. Requires an authenticated caller whose email matches the invite. */
3918
- acceptInvitation(token) {
3919
- return this.client.request("POST", `/v1/invitations/${encodeURIComponent(token)}/accept`);
3920
- }
3921
- // -- audit ----------------------------------------------------------------
3922
- /**
3923
- * The organization's audit log, newest first. Owner and admins only, and
3924
- * readable while the organization is suspended — the record of what
3925
- * happened is exactly what someone needs when things have gone wrong.
3926
- */
3927
- audit(orgId, opts = {}) {
3928
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/audit`, { query: { ...opts } });
3929
- }
3930
- // -- usage ----------------------------------------------------------------
3931
- /**
3932
- * Credits by workspace, member, model or day. Owner and org admins only.
3933
- * Inclusive dates (`from`/`to`), IANA `tz` (default UTC), ≤ 366 days
3934
- * (default last 30).
3935
- */
3936
- usage(orgId, opts = {}) {
3937
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/usage`, { query: { ...opts } });
3938
- }
3939
- /** The individual runs behind a report, newest first, cursor-paged. */
3940
- usageRows(orgId, opts = {}) {
3941
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/usage`, { query: { ...opts, groupBy: "none" } });
3942
- }
3943
- /** The same report (or the rows, with `groupBy: "none"`) as CSV text. */
3944
- usageCsv(orgId, opts = {}) {
3945
- return this.client.requestText("GET", `/v1/orgs/${encodeURIComponent(orgId)}/usage`, { query: { ...opts, format: "csv" } });
3946
- }
3947
- };
3948
-
3949
- // src/resources/workspaces.ts
3950
- var WorkspacesResource = class {
3951
- constructor(client) {
3952
- this.client = client;
3953
- }
3954
- client;
3955
- /**
3956
- * Every workspace this account belongs to, across all its organizations.
3957
- *
3958
- * An identity read: a stale workspace binding cannot lock a caller out of
3959
- * it, which is what makes it safe to call when a selection has gone bad.
3960
- *
3961
- * Byte-for-byte the list `GET /v1/me` carries, so a client reconciles
3962
- * against one truth rather than two. That is why these are SUMMARIES —
3963
- * enough to render a switcher, not the full view; use {@link get} for that.
3964
- */
3965
- list() {
3966
- return this.client.request("GET", "/v1/workspaces");
3967
- }
3968
- listForOrg(orgId, opts = {}) {
3969
- return this.client.request("GET", `/v1/orgs/${encodeURIComponent(orgId)}/workspaces`, {
3970
- query: { includeArchived: opts.includeArchived }
3971
- });
3972
- }
3973
- get(id) {
3974
- return this.client.request("GET", `/v1/workspaces/${encodeURIComponent(id)}`);
3975
- }
3976
- create(orgId, input) {
3977
- return this.client.request("POST", `/v1/orgs/${encodeURIComponent(orgId)}/workspaces`, { body: input });
3978
- }
3979
- update(id, input) {
3980
- return this.client.request("PATCH", `/v1/workspaces/${encodeURIComponent(id)}`, { body: input });
3981
- }
3982
- /**
3983
- * Archive or restore. Archiving is REVERSIBLE and destroys nothing: the
3984
- * workspace stops accepting new work and stays fully readable, which is
3985
- * what a finished class term needs and a delete would not survive.
3986
- */
3987
- setArchived(id, archived) {
3988
- return this.client.request(
3989
- "POST",
3990
- `/v1/workspaces/${encodeURIComponent(id)}/${archived ? "archive" : "unarchive"}`
3991
- );
3992
- }
3993
- // -- members --------------------------------------------------------------
3994
- listMembers(id, opts = {}) {
3995
- return this.client.request("GET", `/v1/workspaces/${encodeURIComponent(id)}/members`, {
3996
- query: { ...opts }
3997
- });
3998
- }
3999
- /** Add someone who is ALREADY in the organization. To bring in a new person, invite them. */
4000
- addMember(id, input) {
4001
- return this.client.request("POST", `/v1/workspaces/${encodeURIComponent(id)}/members`, { body: input });
4002
- }
4003
- updateMember(id, userId, input) {
4004
- return this.client.request(
4005
- "PATCH",
4006
- `/v1/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`,
4007
- { body: input }
4008
- );
4009
- }
4010
- removeMember(id, userId) {
4011
- return this.client.request(
4012
- "DELETE",
4013
- `/v1/workspaces/${encodeURIComponent(id)}/members/${encodeURIComponent(userId)}`
4014
- );
4015
- }
4016
- // -- join codes -----------------------------------------------------------
4017
- /** The workspace's join code, or `null` if none has been created. Admins only. */
4018
- getJoinCode(id) {
4019
- return this.client.request("GET", `/v1/workspaces/${encodeURIComponent(id)}/join-code`);
4020
- }
4021
- /**
4022
- * Rotate, enable or disable the code. Rotating invalidates the old one
4023
- * immediately — that is the point of it, and anyone still holding a link
4024
- * with the old code will be refused.
4025
- */
4026
- actOnJoinCode(id, action) {
4027
- return this.client.request("POST", `/v1/workspaces/${encodeURIComponent(id)}/join-code`, {
4028
- body: { action }
4029
- });
4030
- }
4031
- /**
4032
- * Join by code. Another way IN, so a stale workspace binding must not block
4033
- * it — the server treats this as an identity route for that reason.
4034
- */
4035
- join(code) {
4036
- return this.client.request("POST", "/v1/workspaces/join", { body: { code } });
4037
- }
4038
- // -- usage ----------------------------------------------------------------
4039
- /**
4040
- * Credits by member, model or day for this workspace. A plain member sees
4041
- * their OWN runs (the report is self-narrowed and `groupBy: "member"` is
4042
- * refused); a workspace admin sees everyone and may filter `userId`.
4043
- * Inclusive dates, IANA `tz` (default UTC), ≤ 366 days (default last 30).
4044
- */
4045
- usage(id, opts = {}) {
4046
- return this.client.request("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts } });
4047
- }
4048
- /** The individual runs behind a report, newest first, cursor-paged. */
4049
- usageRows(id, opts = {}) {
4050
- return this.client.request("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, groupBy: "none" } });
4051
- }
4052
- /** The same report (or the rows, with `groupBy: "none"`) as CSV text. */
4053
- usageCsv(id, opts = {}) {
4054
- return this.client.requestText("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, format: "csv" } });
4055
- }
4056
- };
4057
- function tightenBody(input) {
4058
- const { mediaUrl, ...rest } = input;
4059
- return { mediaUrls: [mediaUrl], ...Object.fromEntries(Object.entries(rest).filter(([, v]) => v !== void 0)) };
4060
- }
4061
- function idempotencyHeaders(options) {
4062
- return options?.idempotencyKey ? { headers: { "Idempotency-Key": options.idempotencyKey } } : {};
4063
- }
4064
- var EditResource = class {
4065
- constructor(client) {
4066
- this.client = client;
4067
- }
4068
- client;
4069
- /**
4070
- * Detect silence ranges in an audio/video source (`POST /v1/silence-detect`).
4071
- * Keyless — one ffmpeg pass over the source's audio proxy.
4072
- */
4073
- silenceDetect(input) {
4074
- return this.client.request("POST", "/v1/silence-detect", {
4075
- body: {
4076
- audioUrl: input.audioUrl,
4077
- ...input.thresholdDb !== void 0 ? { thresholdDb: input.thresholdDb } : {},
4078
- ...input.minSilenceMs !== void 0 ? { minSilenceMs: input.minSilenceMs } : {},
4079
- ...input.padMs !== void 0 ? { padMs: input.padMs } : {},
4080
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
4081
- }
4082
- });
4083
- }
4084
- /**
4085
- * Measure how far apart the clocks of 2–6 recordings of one conversation are
4086
- * (`POST /v1/audio-sync`), by cross-correlating their audio — keyless, one
4087
- * ffmpeg decode per source. The finished job's `output_data.json` is an
4088
- * {@link AudioSyncResult}. A malformed request (fewer than 2 or more than 6
4089
- * sources, a repeated id, a `reference` that is not one of the ids) throws a
4090
- * typed `NodaroError` (400, `code: "validation_error"`) before any credits
4091
- * are reserved.
4092
- */
4093
- audioSync(input) {
4094
- return this.client.request("POST", "/v1/audio-sync", {
4095
- body: {
4096
- sources: input.sources.map((s) => ({ id: s.id, url: s.url })),
4097
- ...input.reference !== void 0 ? { reference: input.reference } : {},
4098
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
4099
- }
4100
- });
4101
- }
4102
- /**
4103
- * Render an edit decision list into a video or audio cut (`POST /v1/apply-edl`).
4104
- * The EDL is validated at ingress — an unresolvable source or a picture-less
4105
- * segment on a video edit throws a typed `NodaroError` (400, `code:
4106
- * "invalid_edl"`) before any credits are reserved.
4107
- */
4108
- applyEdl(input) {
4109
- return this.client.request("POST", "/v1/apply-edl", {
4110
- body: {
4111
- edl: input.edl,
4112
- ...input.sources !== void 0 ? { sources: input.sources } : {},
4113
- ...input.transcript !== void 0 ? { transcript: input.transcript } : {},
4114
- ...input.output !== void 0 ? { output: input.output } : {},
4115
- ...input.quality !== void 0 ? { quality: input.quality } : {},
4116
- ...input.crossfadeMs !== void 0 ? { crossfadeMs: input.crossfadeMs } : {},
4117
- ...input.clipKey !== void 0 ? { clipKey: input.clipKey } : {},
4118
- ...input.planBasis !== void 0 ? { planBasis: input.planBasis } : {},
4119
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
4120
- }
4121
- });
4122
- }
4123
- /**
4124
- * Tighten Episode (`POST /v1/tighten-episode`): tighten a podcast recording
4125
- * in one call — transcribe, cut the silences and filler, render, with
4126
- * optional captions, music and framing. Answers the run's job to poll; its
4127
- * `output_data` holds the episode. The run is priced as its steps at their own
4128
- * rates plus the listed per-run fee. Quote it first with
4129
- * {@link estimateTightenEpisode}.
4130
- */
4131
- tightenEpisode(input, options) {
4132
- return this.client.request("POST", "/v1/tighten-episode", { body: tightenBody(input), ...idempotencyHeaders(options) });
4133
- }
4134
- /**
4135
- * What a Tighten Episode run is estimated at (`POST /v1/tighten-episode/estimate`):
4136
- * its steps at their own rates plus its per-run fee. Nothing is created or
4137
- * charged. The estimate leans high: the render is priced at the recording's
4138
- * full length, while the charge follows the minutes actually rendered.
4139
- */
4140
- estimateTightenEpisode(input) {
4141
- return this.client.request("POST", "/v1/tighten-episode/estimate", { body: tightenBody(input) });
4142
- }
4143
- /**
4144
- * Continue a Tighten Episode run as a new job (`POST /v1/tighten-episode/continue`):
4145
- * `"from-failed"` keeps the steps that finished and runs the rest (the fee is
4146
- * held again; the failed run's was refunded); `"render-final"` renders the
4147
- * full-quality episode after a review-on preview, with the preview's
4148
- * settings and no fee. A refusal that names another job
4149
- * (`already_running`, `continuation_superseded`,
4150
- * `render_final_already_rendered`) throws a `ContinuationRefusedError`
4151
- * carrying that `jobId`.
4152
- */
4153
- continueUseCase(input, options) {
4154
- return this.client.request("POST", "/v1/tighten-episode/continue", {
4155
- body: { jobId: input.jobId, mode: input.mode, ...input.editedEdl !== void 0 ? { editedEdl: input.editedEdl } : {} },
4156
- ...idempotencyHeaders(options)
4157
- });
4158
- }
4159
- /**
4160
- * Plan a transcript-driven cut (`POST /v1/edit-plan`). Reads a timed
4161
- * transcript (plus optional silence ranges) and the media sources, and plans
4162
- * the edit. The finished job's `output_data` holds the plan: an `Edl`
4163
- * (`"tighten"` or `"trailer"`), an {@link EdlClipSet} (`"clips"`), or a
4164
- * {@link ChapterSet} (`"chapters"`) — normalize it with {@link unwrapEditPlanOutput}.
4165
- *
4166
- * On a self-hosted install the request relays to nodaro.ai and needs the
4167
- * install connected (a 503 `code: "nodaro_connection_required"` otherwise);
4168
- * on nodaro.ai it runs directly.
4169
- */
4170
- editPlan(input) {
4171
- const planned = resolveEditPlanSources(input.sources, {
4172
- offsets: input.offsets,
4173
- transcriptSourceId: input.transcriptSourceId
4174
- });
4175
- if (!planned.ok) {
4176
- const message = planned.issues.map((issue) => describeAudioSyncOffsetIssue(issue)).join("; ");
4177
- return Promise.reject(new NodaroError(`editPlan: ${message}`, "edit_plan_sources", 400));
4178
- }
4179
- const transcript = planned.transcriptSourceId ? { ...input.transcript, sourceId: planned.transcriptSourceId } : input.transcript;
4180
- return this.client.request("POST", "/v1/edit-plan", {
4181
- body: {
4182
- mode: input.mode,
4183
- planTier: input.planTier,
4184
- transcript,
4185
- sources: planned.sources,
4186
- ...input.silence !== void 0 ? { silence: input.silence } : {},
4187
- ...input.instructions !== void 0 ? { instructions: input.instructions } : {},
4188
- ...input.styleGuide !== void 0 ? { styleGuide: input.styleGuide } : {},
4189
- ...input.count !== void 0 ? { count: input.count } : {},
4190
- ...input.targetDurationSec !== void 0 ? { targetDurationSec: input.targetDurationSec } : {},
4191
- ...input.targetAspect !== void 0 ? { targetAspect: input.targetAspect } : {},
4192
- ...input.platform !== void 0 ? { platform: input.platform } : {},
4193
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
4194
- }
4195
- });
4196
- }
4197
- /**
4198
- * Camera Switch (podcast B5): choose which camera shows each cut of `edl`
4199
- * by who is speaking — the sound never changes. Cloud edition; a flat
4200
- * price. The finished job's `output_data.json` is the switched EDL (feed it
4201
- * to {@link applyEdl}) and `output_data.transcript` the transcript with
4202
- * `speakerNames` applied. A transcript with no speaker labels rejects with
4203
- * a {@link NodaroError} (`code: "no_speakers"`) before any request or charge.
4204
- */
4205
- cameraSwitch(input) {
4206
- if (transcriptSpeakerLabels(input.transcript).length === 0) {
4207
- return Promise.reject(new NodaroError(
4208
- "cameraSwitch: the transcript has no speaker labels \u2014 transcribe with speaker detection on",
4209
- "no_speakers",
4210
- 422
4211
- ));
4212
- }
4213
- return this.client.request("POST", "/v1/camera-switch", {
4214
- body: {
4215
- edl: input.edl,
4216
- transcript: input.transcript,
4217
- ...input.speakerMap !== void 0 ? { speakerMap: input.speakerMap } : {},
4218
- ...input.speakerNames !== void 0 ? { speakerNames: input.speakerNames } : {},
4219
- ...input.minShotMs !== void 0 ? { minShotMs: input.minShotMs } : {},
4220
- ...input.leadMs !== void 0 ? { leadMs: input.leadMs } : {},
4221
- ...input.maxShotMs !== void 0 ? { maxShotMs: input.maxShotMs } : {},
4222
- ...input.wideEvery !== void 0 ? { wideEvery: input.wideEvery } : {},
4223
- ...input.layoutHints !== void 0 ? { layoutHints: input.layoutHints } : {},
4224
- ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
4225
- }
4226
- });
4227
- }
4228
- /**
4229
- * Remap a transcript through an EDL — a PURE client-side transform (NO
4230
- * request). Returns a new transcript whose word (and segment) timings are on
4231
- * the EDL's rendered output clock, dropping words that fall in cut regions and
4232
- * clipping straddlers. Runs `@nodaro/shared`'s canonical
4233
- * `remapTranscriptThroughEdl`, the same remap `applyEdl` performs server-side.
4234
- */
4235
- remapTranscript(edl, transcript) {
4236
- return remapTranscriptThroughEdl(edl, transcript);
4237
- }
4238
- };
4239
- var SDK_VERSION = "2.28.0" ;
4240
- var CLIENT_HEADER = "X-Nodaro-Client";
4241
- var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
4242
- var NodaroClient = class _NodaroClient {
4243
- baseUrl;
4244
- auth;
4245
- timeoutMs;
4246
- /** Value sent as `X-Nodaro-Client`; recorded by the backend as job provenance. */
4247
- clientLabel;
4248
- /** Whether to actually send it — see the note on {@link CLIENT_HEADER}. */
4249
- sendClientHeader;
4250
- fetchOverride;
4251
- /**
4252
- * Resolved lazily so consumers can swap `globalThis.fetch` after the
4253
- * client has been constructed (e.g. test mocks). Always rebound to the
4254
- * global object — native fetch throws "Illegal invocation" when its
4255
- * `this` is anything else.
4256
- */
4257
- get fetch() {
4258
- return this.fetchOverride ?? globalThis.fetch.bind(globalThis);
4259
- }
4260
- workflows;
4261
- projects;
4262
- /** Generation sessions inside projects (Create Image / Video / Music). */
4263
- sessions;
4264
- jobs;
4265
- videoPro;
4266
- executions;
4267
- nodes;
4268
- scene3d;
4269
- developerApps;
4270
- oauth;
4271
- apps;
4272
- characters;
4273
- locations;
4274
- objects;
4275
- creatures;
4276
- pipelines;
4277
- reduce;
4278
- promptHelper;
4279
- voices;
4280
- llm;
4281
- media;
4282
- audio;
4283
- credits;
4284
- uploads;
4285
- library;
4286
- presets;
4287
- savedPosts;
4288
- collections;
4289
- competitors;
4290
- pickerCatalogs;
4291
- catalogs;
4292
- models;
4293
- shots;
4294
- recast;
4295
- studio;
4296
- copilot;
4297
- community;
4298
- templates;
4299
- tutorials;
4300
- organizations;
4301
- workspaces;
4302
- edit;
4303
- /** The workspace this client acts in; undefined = the personal space. */
4304
- workspaceId;
4305
- constructor(opts) {
4306
- this.baseUrl = opts.baseUrl.replace(/\/$/, "");
4307
- this.auth = opts.auth;
4308
- this.fetchOverride = opts.fetch;
4309
- this.timeoutMs = opts.timeoutMs ?? 6e4;
4310
- this.clientLabel = opts.clientLabel ?? `sdk/${SDK_VERSION}`;
4311
- this.workspaceId = opts.workspaceId;
4312
- this.sendClientHeader = opts.clientLabel !== void 0 || !isBrowser();
4313
- this.workflows = new WorkflowsResource(this);
4314
- this.projects = new ProjectsResource(this);
4315
- this.sessions = new SessionsResource(this);
4316
- this.jobs = new JobsResource(this);
4317
- this.videoPro = new VideoProResource(this);
4318
- this.executions = new ExecutionsResource(this);
4319
- this.nodes = new NodesResource(this);
4320
- this.scene3d = new Scene3DResource(this);
4321
- this.developerApps = new DeveloperAppsResource(this);
4322
- this.oauth = new OAuthResource(this);
4323
- this.apps = new AppsResource(this);
4324
- this.characters = new CharactersResource(this);
4325
- this.locations = new LocationsResource(this);
4326
- this.objects = new ObjectsResource(this);
4327
- this.creatures = new CreaturesResource(this);
4328
- this.pipelines = new PipelinesResource(this);
4329
- this.reduce = new ReduceResource(this);
4330
- this.promptHelper = new PromptHelperResource(this);
4331
- this.voices = new VoicesResource(this);
4332
- this.llm = new LlmResource(this);
4333
- this.media = new MediaResource(this);
4334
- this.audio = new AudioResource(this);
4335
- this.credits = new CreditsResource(this);
4336
- this.uploads = new UploadsResource(this);
4337
- this.library = new LibraryResource(this);
4338
- this.presets = new PresetsResource(this);
4339
- this.savedPosts = new SavedPostsResource(this);
4340
- this.collections = new CollectionsResource(this);
4341
- this.competitors = new CompetitorsResource(this);
4342
- this.pickerCatalogs = new PickerCatalogsResource(this);
4343
- this.catalogs = new CatalogsResource(this);
4344
- this.models = new ModelsResource(this);
4345
- this.shots = new ShotsResource(this);
4346
- this.recast = new RecastResource(this);
4347
- this.studio = new StudioResource(this);
4348
- this.copilot = new CopilotResource(this);
4349
- this.community = new CommunityResource(this);
4350
- this.templates = new TemplatesResource(this);
4351
- this.tutorials = new TutorialsResource(this);
4352
- this.organizations = new OrganizationsResource(this);
4353
- this.workspaces = new WorkspacesResource(this);
4354
- this.edit = new EditResource(this);
4355
- }
4356
- /**
4357
- * A client that acts in `workspaceId`, sharing this one's auth and config.
4358
- *
4359
- * A NEW client rather than a setter, deliberately. A mutable selection is
4360
- * the bug this whole axis exists to prevent: two concurrent operations
4361
- * against one client would race over which workspace they were in, and the
4362
- * loser would create work in the wrong place with nothing failing. A
4363
- * per-workspace client cannot be raced.
4364
- *
4365
- * Pass `null` for the personal space.
4366
- */
4367
- withWorkspace(workspaceId) {
4368
- return new _NodaroClient({
4369
- baseUrl: this.baseUrl,
4370
- auth: this.auth,
4371
- timeoutMs: this.timeoutMs,
4372
- ...this.fetchOverride ? { fetch: this.fetchOverride } : {},
4373
- ...this.sendClientHeader ? { clientLabel: this.clientLabel } : {},
4374
- ...workspaceId ? { workspaceId } : {}
4375
- });
4376
- }
4377
- /**
4378
- * The transport: build the request, send it, throw the typed error on a
4379
- * non-2xx via {@link throwFromResponse}, then read the body via `read` — all
4380
- * inside the abort timer, so `timeoutMs` bounds the body download too (a
4381
- * stalled CSV stream aborts, it does not hang forever). Both the JSON path
4382
- * ({@link request}) and the text path ({@link requestText}) go through here.
4383
- */
4384
- async send(method, path2, options, read) {
4385
- const url = this.buildUrl(path2, options.query);
4386
- const token = await this.auth.getToken();
4387
- const isFormData = typeof FormData !== "undefined" && options.body instanceof FormData;
4388
- const headers = {
4389
- ...isFormData ? {} : { "Content-Type": "application/json" },
4390
- ...this.sendClientHeader ? { [CLIENT_HEADER]: this.clientLabel } : {},
4391
- // Before per-request headers: a resource that needs to reach outside
4392
- // this client's workspace says so explicitly and wins.
4393
- ...this.workspaceId ? { [WORKSPACE_HEADER]: this.workspaceId } : {},
4394
- ...options.headers ?? {}
4395
- };
4396
- if (token) headers["Authorization"] = `Bearer ${token}`;
4397
- const ac = new AbortController();
4398
- const timeoutId = setTimeout(() => ac.abort(), this.timeoutMs);
4399
- const abort = () => ac.abort(options.signal?.reason);
4400
- options.signal?.addEventListener("abort", abort, { once: true });
4401
- if (options.signal?.aborted) abort();
4402
- try {
4403
- ac.signal.throwIfAborted();
4404
- const res = await this.fetch(url, {
4405
- method,
4406
- headers,
4407
- body: options.body === void 0 ? void 0 : isFormData ? options.body : JSON.stringify(options.body),
4408
- signal: ac.signal
4409
- });
4410
- if (!res.ok) {
4411
- let errBody = {};
4412
- try {
4413
- errBody = await res.json();
4414
- } catch {
4415
- }
4416
- throwFromResponse(res.status, errBody);
4417
- }
4418
- return await read(res);
4419
- } finally {
4420
- clearTimeout(timeoutId);
4421
- options.signal?.removeEventListener("abort", abort);
4422
- }
4423
- }
4424
- /** Authenticated, bounded binary reads through the normal timeout/error transport. */
4425
- async requestBytes(method, path2, options) {
4426
- if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 1) throw new Error("maxBytes must be a positive integer");
4427
- return this.send(method, path2, options, (response) => readBinaryResponse(response, options.maxBytes));
4428
- }
4429
- async request(method, path2, options = {}) {
4430
- return this.send(
4431
- method,
4432
- path2,
4433
- options,
4434
- async (res) => (
4435
- // 204 No Content
4436
- res.status === 204 ? void 0 : await res.json()
4437
- )
4438
- );
4439
- }
4440
- /**
4441
- * Like {@link request}, for endpoints that answer text (CSV exports). Errors
4442
- * are still the JSON envelope and throw the same typed errors, and the read is
4443
- * bounded by the same timeout as the request.
4444
- */
4445
- async requestText(method, path2, options = {}) {
4446
- return this.send(method, path2, options, (res) => res.text());
4447
- }
4448
- /**
4449
- * `GET /v1/me` → the authenticated user's identity (see {@link UserIdentity}).
4450
- * Unwraps the `{ data }` envelope. Throws `UnauthorizedError` (401) when the
4451
- * token is missing/invalid, and the SDK's other typed errors as usual.
4452
- *
4453
- * On an instance with organizations it also carries what the caller belongs
4454
- * to. THREE states, and collapsing them is wrong in a way users feel: the
4455
- * organization fields ABSENT means this instance has no organizations at
4456
- * all; present and empty means the account belongs to none; and
4457
- * `organizationsUnavailable` means the lookup failed — keep whatever
4458
- * selection you already had rather than concluding the person was removed
4459
- * from everything.
4460
- */
4461
- async me() {
4462
- const res = await this.request("GET", "/v1/me");
4463
- return res.data;
4464
- }
4465
- buildUrl(path2, query) {
4466
- const base = this.baseUrl || (typeof window !== "undefined" ? window.location.origin : "http://placeholder");
4467
- const url = new URL(path2, base);
4468
- const fullUrl = this.baseUrl ? url.toString() : url.pathname + url.search;
4469
- if (query) {
4470
- const u = new URL(this.baseUrl ? fullUrl : fullUrl, base);
4471
- for (const [k, v] of Object.entries(query)) {
4472
- if (v !== void 0) u.searchParams.set(k, String(v));
4473
- }
4474
- return this.baseUrl ? u.toString() : u.pathname + u.search;
4475
- }
4476
- return fullUrl;
4477
- }
4478
- };
4479
- function createClient(opts) {
4480
- return new NodaroClient(opts);
4481
- }
4482
-
4483
- // src/auth.ts
4484
- var StaticTokenAuth = class {
4485
- constructor(token) {
4486
- this.token = token;
4487
- }
4488
- token;
4489
- async getToken() {
4490
- return this.token;
4491
- }
4492
- };
4493
- var CallbackAuth = class {
4494
- constructor(fn) {
4495
- this.fn = fn;
4496
- }
4497
- fn;
4498
- async getToken() {
4499
- return this.fn();
4500
- }
4501
- };
4502
- function supabaseAuth(supabase) {
4503
- return {
4504
- async getToken() {
4505
- const { data } = await supabase.auth.getSession();
4506
- return data.session?.access_token ?? null;
4507
- }
4508
- };
4509
- }
4510
-
4511
- export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CollectionsResource, CommunityResource, CompetitorsResource, ContinuationRefusedError, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, EditResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, SCENE3D_DELIVERY_ASSET_USAGE, SavedPostsResource, Scene3DResource, SessionsResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
1
+ export { WebhookSignatureError, verifyWebhookSignature } from './chunk-VGTRKXF2.js';
2
+ import './chunk-PGYQ754I.js';
3
+ import './chunk-FHEYAW5H.js';
4
+ import './chunk-D3PW7AHZ.js';
5
+ import './chunk-BKP6F2IX.js';
6
+ import './chunk-PMTM26LL.js';
7
+ import './chunk-LHRQXWI5.js';
8
+ import './chunk-VT237QF2.js';
9
+ import './chunk-CGNVHN4V.js';
10
+ import './chunk-VPAUN75Q.js';
11
+ import './chunk-MEKI37WI.js';
12
+ import './chunk-QVQCKOBM.js';
13
+ import './chunk-IQ6KWSXP.js';
14
+ import './chunk-KZQKFBRN.js';
15
+ import './chunk-7A7HYFGM.js';
16
+ export { RECAST_SEGMENT_PACKS } from './chunk-RJIJVVXS.js';
17
+ import './chunk-6JFNBAKV.js';
18
+ import './chunk-OJDBSKC2.js';
19
+ import './chunk-CRCPRZFN.js';
20
+ import './chunk-OMH7ATOQ.js';
21
+ import './chunk-37Y5QAVA.js';
22
+ import './chunk-NX67YIF3.js';
23
+ export { PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY } from './chunk-W7YI5UT3.js';
24
+ import './chunk-X7RDNMN7.js';
25
+ import './chunk-OLPA44QJ.js';
26
+ export { USAGE_GROUP_BYS, WORKSPACE_HEADER } from './chunk-RKVRCNMB.js';
27
+ import './chunk-HLHR3R4P.js';
28
+ import './chunk-CJFIOVBA.js';
29
+ import './chunk-OPR4TULG.js';
30
+ import './chunk-C22RJDW3.js';
31
+ import './chunk-I3TYBAOX.js';
32
+ import './chunk-A3THLBFG.js';
33
+ import './chunk-UIFFNTUX.js';
34
+ import './chunk-HFBR6G36.js';
35
+ import './chunk-ES2E65HT.js';
36
+ import './chunk-GAZJ2PA3.js';
37
+ import './chunk-GD24ZRFD.js';
38
+ import './chunk-ELSOVJPF.js';
39
+ import './chunk-AUDHV3OE.js';
40
+ import './chunk-EXLAHZKF.js';
41
+ import './chunk-V4GPQ6Y2.js';
42
+ import './chunk-YOOZB4RL.js';
43
+ export { unwrapEditPlanOutput } from './chunk-ZH4F2P2G.js';
44
+ import './chunk-3PPSGM5X.js';
45
+ import './chunk-HRXXGGSJ.js';
46
+ import './chunk-M6Y5TOYE.js';
47
+ import './chunk-SUCHGNYT.js';
48
+ import './chunk-SLPD47SR.js';
49
+ export { NodaroClient, createClient } from './chunk-5WAI7VGO.js';
50
+ export { WebhooksResource } from './chunk-YN6CBIIB.js';
51
+ export { WorkflowsResource } from './chunk-ZXJQSFIA.js';
52
+ export { WorkspacesResource } from './chunk-Z5GLY4R3.js';
53
+ export { SessionsResource } from './chunk-Y6VDCZPB.js';
54
+ export { ShotsResource } from './chunk-WVFAQBS7.js';
55
+ export { StudioProductionsResource, StudioResource, isStudioGenerateEstimate } from './chunk-VV4TZG5S.js';
56
+ export { TemplatesResource } from './chunk-6OGGJQVA.js';
57
+ export { TutorialsResource } from './chunk-DPSMVOM3.js';
58
+ export { UploadsResource } from './chunk-T3SYREY4.js';
59
+ export { VideoProResource } from './chunk-ERLXU47J.js';
60
+ export { VoicesResource } from './chunk-T7N7DFQJ.js';
61
+ export { PickerCatalogsResource } from './chunk-BLA44UCM.js';
62
+ export { PipelinesResource } from './chunk-K4RQOSJH.js';
63
+ export { ProjectsResource } from './chunk-H7VQTG4M.js';
64
+ export { PromptHelperResource } from './chunk-E2ZXHS6E.js';
65
+ export { RecastResource } from './chunk-AJVSMNPZ.js';
66
+ export { ReduceResource } from './chunk-IHKIYVZQ.js';
67
+ export { SavedPostsResource } from './chunk-NCCBS6GU.js';
68
+ export { SCENE3D_DELIVERY_ASSET_USAGE, Scene3DResource } from './chunk-NNHWH7ER.js';
69
+ export { ModelsResource } from './chunk-Y6V6CBY5.js';
70
+ export { MOODBOARD_DIRECTION_PREFIX, MoodboardsResource, moodboardDirectionId } from './chunk-YVU2M7MI.js';
71
+ export { PresetsResource } from './chunk-JTAW54UM.js';
72
+ export { NodesResource } from './chunk-QITJGSFA.js';
73
+ export { OAuthResource } from './chunk-Z7LGWNI7.js';
74
+ export { OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, ObjectsResource } from './chunk-7LSFG2AF.js';
75
+ export { OrganizationsResource } from './chunk-ALSLZG3U.js';
76
+ export { PALETTE_DIRECTION_PREFIX, PalettesResource, paletteDirectionId } from './chunk-WEQWU2IC.js';
77
+ export { ExecutionsResource, OUTPUT_BEARING_NODE_STATUSES, nodeStateMayCarryOutput } from './chunk-Z3ZKFI2M.js';
78
+ export { GalleryResource } from './chunk-JDEZHITT.js';
79
+ export { JobsResource } from './chunk-E5BM4BLO.js';
80
+ export { LibraryResource } from './chunk-P6E4QDJN.js';
81
+ export { LlmResource } from './chunk-E37CVHWW.js';
82
+ export { LOCATION_ASSET_TYPES, LOCATION_ATTACH_COLUMNS, LocationsResource, SURROUND_DIRECTIONS } from './chunk-TVENC6PH.js';
83
+ export { MediaResource } from './chunk-4NLVBYMW.js';
84
+ export { CommunityResource } from './chunk-SFB4YLCS.js';
85
+ export { CompetitorsResource } from './chunk-BU5A6K4C.js';
86
+ export { CopilotResource } from './chunk-I6CXC345.js';
87
+ import './chunk-JMOKD6ZP.js';
88
+ export { CallbackAuth, NodaroClientCore, StaticTokenAuth, supabaseAuth } from './chunk-LHP2CWHD.js';
89
+ export { OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, CREATURE_ASSET_TYPES, CREATURE_ATTACH_COLUMNS, CreaturesResource } from './chunk-CK3AMMSC.js';
90
+ export { CreditsResource } from './chunk-XQAIEPAZ.js';
91
+ export { DeveloperAppsResource } from './chunk-65E3JBFZ.js';
92
+ export { CLIP_PACK_MAX_TARGET_SEC, CLIP_PACK_MIN_TARGET_SEC, EditResource, TRAILER_FORMATS, USE_CASE_NODE_TYPES } from './chunk-I4A5VJRL.js';
93
+ export { AlreadyRunningError, AppRunVersionChangedError, ContinuationPreviewPendingError, ContinuationRefusedError, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, NodaroError, NotFoundError, RateLimitedError, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, UnauthorizedError, WorkflowConflictError, throwFromResponse } from './chunk-JGS6YBDW.js';
94
+ export { AppsResource } from './chunk-53SXNN3A.js';
95
+ export { AudioResource } from './chunk-3QFTP5P5.js';
96
+ export { BillingResource } from './chunk-J4WFSKY6.js';
97
+ export { CatalogsResource } from './chunk-KG4R454Z.js';
98
+ export { CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_STYLES, CharactersResource, PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, buildPersonHints, buildPersonSeedPrompt } from './chunk-EJSGJDZY.js';
99
+ import './chunk-Z5OMWAQX.js';
100
+ export { CollectionsResource } from './chunk-4WRDR4GN.js';
4512
101
  //# sourceMappingURL=index.js.map
4513
102
  //# sourceMappingURL=index.js.map