@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.
- package/README.md +33 -2
- package/dist/chunk-2DZWWIJ4.cjs +32 -0
- package/dist/chunk-2DZWWIJ4.cjs.map +1 -0
- package/dist/chunk-34PU2DAT.cjs +118 -0
- package/dist/chunk-34PU2DAT.cjs.map +1 -0
- package/dist/chunk-37Y5QAVA.js +3 -0
- package/dist/chunk-37Y5QAVA.js.map +1 -0
- package/dist/chunk-37YCKZX4.cjs +4 -0
- package/dist/chunk-37YCKZX4.cjs.map +1 -0
- package/dist/chunk-3B47IHB3.cjs +65 -0
- package/dist/chunk-3B47IHB3.cjs.map +1 -0
- package/dist/chunk-3BELHJBN.cjs +4 -0
- package/dist/chunk-3BELHJBN.cjs.map +1 -0
- package/dist/chunk-3PPSGM5X.js +3 -0
- package/dist/chunk-3PPSGM5X.js.map +1 -0
- package/dist/chunk-3QBH2VE2.cjs +80 -0
- package/dist/chunk-3QBH2VE2.cjs.map +1 -0
- package/dist/chunk-3QFTP5P5.js +102 -0
- package/dist/chunk-3QFTP5P5.js.map +1 -0
- package/dist/chunk-43FVH6LJ.cjs +123 -0
- package/dist/chunk-43FVH6LJ.cjs.map +1 -0
- package/dist/chunk-43NO4SGC.cjs +4 -0
- package/dist/chunk-43NO4SGC.cjs.map +1 -0
- package/dist/chunk-45CK55BH.cjs +4 -0
- package/dist/chunk-45CK55BH.cjs.map +1 -0
- package/dist/chunk-4NLVBYMW.js +280 -0
- package/dist/chunk-4NLVBYMW.js.map +1 -0
- package/dist/chunk-4WRDR4GN.js +102 -0
- package/dist/chunk-4WRDR4GN.js.map +1 -0
- package/dist/chunk-4WWSHV5G.cjs +4 -0
- package/dist/chunk-4WWSHV5G.cjs.map +1 -0
- package/dist/chunk-53SXNN3A.js +80 -0
- package/dist/chunk-53SXNN3A.js.map +1 -0
- package/dist/chunk-5ALNFATQ.cjs +27 -0
- package/dist/chunk-5ALNFATQ.cjs.map +1 -0
- package/dist/chunk-5UQNMNUE.cjs +4 -0
- package/dist/chunk-5UQNMNUE.cjs.map +1 -0
- package/dist/chunk-5WAI7VGO.js +184 -0
- package/dist/chunk-5WAI7VGO.js.map +1 -0
- package/dist/chunk-65E3JBFZ.js +52 -0
- package/dist/chunk-65E3JBFZ.js.map +1 -0
- package/dist/chunk-6JFNBAKV.js +3 -0
- package/dist/chunk-6JFNBAKV.js.map +1 -0
- package/dist/chunk-6OC6OKLY.cjs +4 -0
- package/dist/chunk-6OC6OKLY.cjs.map +1 -0
- package/dist/chunk-6OGGJQVA.js +25 -0
- package/dist/chunk-6OGGJQVA.js.map +1 -0
- package/dist/chunk-7A7HYFGM.js +3 -0
- package/dist/chunk-7A7HYFGM.js.map +1 -0
- package/dist/chunk-7ISSKQ6S.cjs +106 -0
- package/dist/chunk-7ISSKQ6S.cjs.map +1 -0
- package/dist/chunk-7LSFG2AF.js +194 -0
- package/dist/chunk-7LSFG2AF.js.map +1 -0
- package/dist/chunk-7MYKT2L4.cjs +4 -0
- package/dist/chunk-7MYKT2L4.cjs.map +1 -0
- package/dist/chunk-7QOCWJKD.cjs +25 -0
- package/dist/chunk-7QOCWJKD.cjs.map +1 -0
- package/dist/chunk-A2ZAFAWC.cjs +4 -0
- package/dist/chunk-A2ZAFAWC.cjs.map +1 -0
- package/dist/chunk-A3S55XGF.cjs +54 -0
- package/dist/chunk-A3S55XGF.cjs.map +1 -0
- package/dist/chunk-A3THLBFG.js +3 -0
- package/dist/chunk-A3THLBFG.js.map +1 -0
- package/dist/chunk-AJVSMNPZ.js +78 -0
- package/dist/chunk-AJVSMNPZ.js.map +1 -0
- package/dist/chunk-ALSLZG3U.js +124 -0
- package/dist/chunk-ALSLZG3U.js.map +1 -0
- package/dist/chunk-ALUUBPDG.cjs +4 -0
- package/dist/chunk-ALUUBPDG.cjs.map +1 -0
- package/dist/chunk-AO3W45LT.cjs +4 -0
- package/dist/chunk-AO3W45LT.cjs.map +1 -0
- package/dist/chunk-AUDHV3OE.js +3 -0
- package/dist/chunk-AUDHV3OE.js.map +1 -0
- package/dist/chunk-BAL576G2.cjs +4 -0
- package/dist/chunk-BAL576G2.cjs.map +1 -0
- package/dist/chunk-BFMKPELU.cjs +212 -0
- package/dist/chunk-BFMKPELU.cjs.map +1 -0
- package/dist/chunk-BKP6F2IX.js +3 -0
- package/dist/chunk-BKP6F2IX.js.map +1 -0
- package/dist/chunk-BLA44UCM.js +32 -0
- package/dist/chunk-BLA44UCM.js.map +1 -0
- package/dist/chunk-BPWUWUZ3.cjs +20 -0
- package/dist/chunk-BPWUWUZ3.cjs.map +1 -0
- package/dist/chunk-BRV7Z4GD.cjs +17 -0
- package/dist/chunk-BRV7Z4GD.cjs.map +1 -0
- package/dist/chunk-BU5A6K4C.js +122 -0
- package/dist/chunk-BU5A6K4C.js.map +1 -0
- package/dist/chunk-C22RJDW3.js +3 -0
- package/dist/chunk-C22RJDW3.js.map +1 -0
- package/dist/chunk-CGNVHN4V.js +3 -0
- package/dist/chunk-CGNVHN4V.js.map +1 -0
- package/dist/chunk-CJFIOVBA.js +3 -0
- package/dist/chunk-CJFIOVBA.js.map +1 -0
- package/dist/chunk-CJLLIVSB.cjs +4 -0
- package/dist/chunk-CJLLIVSB.cjs.map +1 -0
- package/dist/chunk-CK3AMMSC.js +194 -0
- package/dist/chunk-CK3AMMSC.js.map +1 -0
- package/dist/chunk-COCKKMNP.cjs +205 -0
- package/dist/chunk-COCKKMNP.cjs.map +1 -0
- package/dist/chunk-CR5E2SF3.cjs +212 -0
- package/dist/chunk-CR5E2SF3.cjs.map +1 -0
- package/dist/chunk-CRCPRZFN.js +3 -0
- package/dist/chunk-CRCPRZFN.js.map +1 -0
- package/dist/chunk-CYRFD6KR.cjs +4 -0
- package/dist/chunk-CYRFD6KR.cjs.map +1 -0
- package/dist/chunk-D3PW7AHZ.js +3 -0
- package/dist/chunk-D3PW7AHZ.js.map +1 -0
- package/dist/chunk-DKEYSJCE.cjs +82 -0
- package/dist/chunk-DKEYSJCE.cjs.map +1 -0
- package/dist/chunk-DPSMVOM3.js +15 -0
- package/dist/chunk-DPSMVOM3.js.map +1 -0
- package/dist/chunk-E2ZXHS6E.js +20 -0
- package/dist/chunk-E2ZXHS6E.js.map +1 -0
- package/dist/chunk-E37CVHWW.js +33 -0
- package/dist/chunk-E37CVHWW.js.map +1 -0
- package/dist/chunk-E5BM4BLO.js +78 -0
- package/dist/chunk-E5BM4BLO.js.map +1 -0
- package/dist/chunk-EHRWTYGR.cjs +4 -0
- package/dist/chunk-EHRWTYGR.cjs.map +1 -0
- package/dist/chunk-EJSGJDZY.js +212 -0
- package/dist/chunk-EJSGJDZY.js.map +1 -0
- package/dist/chunk-ELSOVJPF.js +3 -0
- package/dist/chunk-ELSOVJPF.js.map +1 -0
- package/dist/chunk-ERLXU47J.js +29 -0
- package/dist/chunk-ERLXU47J.js.map +1 -0
- package/dist/chunk-ES2E65HT.js +3 -0
- package/dist/chunk-ES2E65HT.js.map +1 -0
- package/dist/chunk-EXLAHZKF.js +3 -0
- package/dist/chunk-EXLAHZKF.js.map +1 -0
- package/dist/chunk-FHEYAW5H.js +3 -0
- package/dist/chunk-FHEYAW5H.js.map +1 -0
- package/dist/chunk-GA4LZZKQ.cjs +104 -0
- package/dist/chunk-GA4LZZKQ.cjs.map +1 -0
- package/dist/chunk-GAZJ2PA3.js +3 -0
- package/dist/chunk-GAZJ2PA3.js.map +1 -0
- package/dist/chunk-GB6C5OEZ.cjs +32 -0
- package/dist/chunk-GB6C5OEZ.cjs.map +1 -0
- package/dist/chunk-GD24ZRFD.js +3 -0
- package/dist/chunk-GD24ZRFD.js.map +1 -0
- package/dist/chunk-GI7LROLL.cjs +4 -0
- package/dist/chunk-GI7LROLL.cjs.map +1 -0
- package/dist/chunk-GRFLPEM2.cjs +16 -0
- package/dist/chunk-GRFLPEM2.cjs.map +1 -0
- package/dist/chunk-GVIFLUYZ.cjs +40 -0
- package/dist/chunk-GVIFLUYZ.cjs.map +1 -0
- package/dist/chunk-H7VQTG4M.js +35 -0
- package/dist/chunk-H7VQTG4M.js.map +1 -0
- package/dist/chunk-HAKYPZLB.cjs +242 -0
- package/dist/chunk-HAKYPZLB.cjs.map +1 -0
- package/dist/chunk-HFBR6G36.js +3 -0
- package/dist/chunk-HFBR6G36.js.map +1 -0
- package/dist/chunk-HGCVWOGK.cjs +209 -0
- package/dist/chunk-HGCVWOGK.cjs.map +1 -0
- package/dist/chunk-HLHR3R4P.js +3 -0
- package/dist/chunk-HLHR3R4P.js.map +1 -0
- package/dist/chunk-HRXXGGSJ.js +3 -0
- package/dist/chunk-HRXXGGSJ.js.map +1 -0
- package/dist/chunk-I3TYBAOX.js +3 -0
- package/dist/chunk-I3TYBAOX.js.map +1 -0
- package/dist/chunk-I4A5VJRL.js +352 -0
- package/dist/chunk-I4A5VJRL.js.map +1 -0
- package/dist/chunk-I6CXC345.js +102 -0
- package/dist/chunk-I6CXC345.js.map +1 -0
- package/dist/chunk-IGOPUMEX.cjs +4 -0
- package/dist/chunk-IGOPUMEX.cjs.map +1 -0
- package/dist/chunk-IHKIYVZQ.js +30 -0
- package/dist/chunk-IHKIYVZQ.js.map +1 -0
- package/dist/chunk-IMC2M5YM.cjs +12 -0
- package/dist/chunk-IMC2M5YM.cjs.map +1 -0
- package/dist/chunk-IQ6KWSXP.js +3 -0
- package/dist/chunk-IQ6KWSXP.js.map +1 -0
- package/dist/chunk-IS26FJO7.cjs +4 -0
- package/dist/chunk-IS26FJO7.cjs.map +1 -0
- package/dist/chunk-J4WFSKY6.js +50 -0
- package/dist/chunk-J4WFSKY6.js.map +1 -0
- package/dist/chunk-J5LGGCAS.cjs +126 -0
- package/dist/chunk-J5LGGCAS.cjs.map +1 -0
- package/dist/chunk-JDEZHITT.js +43 -0
- package/dist/chunk-JDEZHITT.js.map +1 -0
- package/dist/chunk-JGS6YBDW.js +260 -0
- package/dist/chunk-JGS6YBDW.js.map +1 -0
- package/dist/chunk-JMOKD6ZP.js +46 -0
- package/dist/chunk-JMOKD6ZP.js.map +1 -0
- package/dist/chunk-JOX5BJ6K.cjs +4 -0
- package/dist/chunk-JOX5BJ6K.cjs.map +1 -0
- package/dist/chunk-JTAW54UM.js +116 -0
- package/dist/chunk-JTAW54UM.js.map +1 -0
- package/dist/chunk-K4RQOSJH.js +203 -0
- package/dist/chunk-K4RQOSJH.js.map +1 -0
- package/dist/chunk-KAIE6WJB.cjs +4 -0
- package/dist/chunk-KAIE6WJB.cjs.map +1 -0
- package/dist/chunk-KEDPGWIK.cjs +4 -0
- package/dist/chunk-KEDPGWIK.cjs.map +1 -0
- package/dist/chunk-KG4R454Z.js +18 -0
- package/dist/chunk-KG4R454Z.js.map +1 -0
- package/dist/chunk-KGKCAGRD.cjs +22 -0
- package/dist/chunk-KGKCAGRD.cjs.map +1 -0
- package/dist/chunk-KNMW722T.cjs +48 -0
- package/dist/chunk-KNMW722T.cjs.map +1 -0
- package/dist/chunk-KTTL7BND.cjs +4 -0
- package/dist/chunk-KTTL7BND.cjs.map +1 -0
- package/dist/chunk-KXEWTYS4.cjs +80 -0
- package/dist/chunk-KXEWTYS4.cjs.map +1 -0
- package/dist/chunk-KZQKFBRN.js +3 -0
- package/dist/chunk-KZQKFBRN.js.map +1 -0
- package/dist/chunk-LAWYFC4G.cjs +37 -0
- package/dist/chunk-LAWYFC4G.cjs.map +1 -0
- package/dist/chunk-LHP2CWHD.js +228 -0
- package/dist/chunk-LHP2CWHD.js.map +1 -0
- package/dist/chunk-LHRQXWI5.js +3 -0
- package/dist/chunk-LHRQXWI5.js.map +1 -0
- package/dist/chunk-LKH5M44B.cjs +114 -0
- package/dist/chunk-LKH5M44B.cjs.map +1 -0
- package/dist/chunk-LLNNHLCE.cjs +4 -0
- package/dist/chunk-LLNNHLCE.cjs.map +1 -0
- package/dist/chunk-LWZLWSXD.cjs +4 -0
- package/dist/chunk-LWZLWSXD.cjs.map +1 -0
- package/dist/chunk-M6Y5TOYE.js +3 -0
- package/dist/chunk-M6Y5TOYE.js.map +1 -0
- package/dist/chunk-MBFUMWI5.cjs +31 -0
- package/dist/chunk-MBFUMWI5.cjs.map +1 -0
- package/dist/chunk-MEKI37WI.js +3 -0
- package/dist/chunk-MEKI37WI.js.map +1 -0
- package/dist/chunk-MQ74AKA2.cjs +200 -0
- package/dist/chunk-MQ74AKA2.cjs.map +1 -0
- package/dist/chunk-N6GLZOE4.cjs +282 -0
- package/dist/chunk-N6GLZOE4.cjs.map +1 -0
- package/dist/chunk-NBVARNVA.cjs +38 -0
- package/dist/chunk-NBVARNVA.cjs.map +1 -0
- package/dist/chunk-NCCBS6GU.js +42 -0
- package/dist/chunk-NCCBS6GU.js.map +1 -0
- package/dist/chunk-NGKODS3J.cjs +52 -0
- package/dist/chunk-NGKODS3J.cjs.map +1 -0
- package/dist/chunk-NJVSKUL2.cjs +4 -0
- package/dist/chunk-NJVSKUL2.cjs.map +1 -0
- package/dist/chunk-NLQQHJ25.cjs +104 -0
- package/dist/chunk-NLQQHJ25.cjs.map +1 -0
- package/dist/chunk-NNHWH7ER.js +181 -0
- package/dist/chunk-NNHWH7ER.js.map +1 -0
- package/dist/chunk-NX67YIF3.js +3 -0
- package/dist/chunk-NX67YIF3.js.map +1 -0
- package/dist/chunk-OA6FWYZF.cjs +4 -0
- package/dist/chunk-OA6FWYZF.cjs.map +1 -0
- package/dist/chunk-OJDBSKC2.js +3 -0
- package/dist/chunk-OJDBSKC2.js.map +1 -0
- package/dist/chunk-OLPA44QJ.js +3 -0
- package/dist/chunk-OLPA44QJ.js.map +1 -0
- package/dist/chunk-OMH7ATOQ.js +3 -0
- package/dist/chunk-OMH7ATOQ.js.map +1 -0
- package/dist/chunk-OPR4TULG.js +3 -0
- package/dist/chunk-OPR4TULG.js.map +1 -0
- package/dist/chunk-OSX2GVZ2.cjs +34 -0
- package/dist/chunk-OSX2GVZ2.cjs.map +1 -0
- package/dist/chunk-OXQKE5EG.cjs +282 -0
- package/dist/chunk-OXQKE5EG.cjs.map +1 -0
- package/dist/chunk-P6E4QDJN.js +30 -0
- package/dist/chunk-P6E4QDJN.js.map +1 -0
- package/dist/chunk-PEMLIAPZ.cjs +64 -0
- package/dist/chunk-PEMLIAPZ.cjs.map +1 -0
- package/dist/chunk-PGYQ754I.js +3 -0
- package/dist/chunk-PGYQ754I.js.map +1 -0
- package/dist/chunk-PHKYIWE4.cjs +16 -0
- package/dist/chunk-PHKYIWE4.cjs.map +1 -0
- package/dist/chunk-PMTM26LL.js +3 -0
- package/dist/chunk-PMTM26LL.js.map +1 -0
- package/dist/chunk-PY4OEKNX.cjs +4 -0
- package/dist/chunk-PY4OEKNX.cjs.map +1 -0
- package/dist/chunk-PZS2EXDR.cjs +4 -0
- package/dist/chunk-PZS2EXDR.cjs.map +1 -0
- package/dist/chunk-QITJGSFA.js +210 -0
- package/dist/chunk-QITJGSFA.js.map +1 -0
- package/dist/chunk-QRHJEITQ.cjs +4 -0
- package/dist/chunk-QRHJEITQ.cjs.map +1 -0
- package/dist/chunk-QUFU5RJ7.cjs +4 -0
- package/dist/chunk-QUFU5RJ7.cjs.map +1 -0
- package/dist/chunk-QVQCKOBM.js +3 -0
- package/dist/chunk-QVQCKOBM.js.map +1 -0
- package/dist/chunk-R63TTR35.cjs +200 -0
- package/dist/chunk-R63TTR35.cjs.map +1 -0
- package/dist/chunk-RA42NMWV.cjs +4 -0
- package/dist/chunk-RA42NMWV.cjs.map +1 -0
- package/dist/chunk-RAZN6C5R.cjs +12 -0
- package/dist/chunk-RAZN6C5R.cjs.map +1 -0
- package/dist/chunk-REUFPWM7.cjs +233 -0
- package/dist/chunk-REUFPWM7.cjs.map +1 -0
- package/dist/chunk-RHETJOUM.cjs +4 -0
- package/dist/chunk-RHETJOUM.cjs.map +1 -0
- package/dist/chunk-RJIJVVXS.js +3 -0
- package/dist/chunk-RJIJVVXS.js.map +1 -0
- package/dist/chunk-RKVRCNMB.js +3 -0
- package/dist/chunk-RKVRCNMB.js.map +1 -0
- package/dist/chunk-SBV5MWEL.cjs +53 -0
- package/dist/chunk-SBV5MWEL.cjs.map +1 -0
- package/dist/chunk-SFB4YLCS.js +121 -0
- package/dist/chunk-SFB4YLCS.js.map +1 -0
- package/dist/chunk-SLPD47SR.js +3 -0
- package/dist/chunk-SLPD47SR.js.map +1 -0
- package/dist/chunk-SS3B6PHT.cjs +35 -0
- package/dist/chunk-SS3B6PHT.cjs.map +1 -0
- package/dist/chunk-SUCHGNYT.js +3 -0
- package/dist/chunk-SUCHGNYT.js.map +1 -0
- package/dist/chunk-SYVNY3AH.cjs +44 -0
- package/dist/chunk-SYVNY3AH.cjs.map +1 -0
- package/dist/chunk-T3SYREY4.js +29 -0
- package/dist/chunk-T3SYREY4.js.map +1 -0
- package/dist/chunk-T7N7DFQJ.js +198 -0
- package/dist/chunk-T7N7DFQJ.js.map +1 -0
- package/dist/chunk-TRCENAIY.cjs +4 -0
- package/dist/chunk-TRCENAIY.cjs.map +1 -0
- package/dist/chunk-TVENC6PH.js +186 -0
- package/dist/chunk-TVENC6PH.js.map +1 -0
- package/dist/chunk-U4T3Z3K7.cjs +325 -0
- package/dist/chunk-U4T3Z3K7.cjs.map +1 -0
- package/dist/chunk-UI2NXUML.cjs +187 -0
- package/dist/chunk-UI2NXUML.cjs.map +1 -0
- package/dist/chunk-UIFFNTUX.js +3 -0
- package/dist/chunk-UIFFNTUX.js.map +1 -0
- package/dist/chunk-V4GPQ6Y2.js +3 -0
- package/dist/chunk-V4GPQ6Y2.js.map +1 -0
- package/dist/chunk-VGTRKXF2.js +93 -0
- package/dist/chunk-VGTRKXF2.js.map +1 -0
- package/dist/chunk-VGWOIWRQ.cjs +202 -0
- package/dist/chunk-VGWOIWRQ.cjs.map +1 -0
- package/dist/chunk-VLCNNA76.cjs +4 -0
- package/dist/chunk-VLCNNA76.cjs.map +1 -0
- package/dist/chunk-VPAUN75Q.js +3 -0
- package/dist/chunk-VPAUN75Q.js.map +1 -0
- package/dist/chunk-VT237QF2.js +3 -0
- package/dist/chunk-VT237QF2.js.map +1 -0
- package/dist/chunk-VV4TZG5S.js +321 -0
- package/dist/chunk-VV4TZG5S.js.map +1 -0
- package/dist/chunk-VYK6MBL4.cjs +4 -0
- package/dist/chunk-VYK6MBL4.cjs.map +1 -0
- package/dist/chunk-W33CKW6Q.cjs +4 -0
- package/dist/chunk-W33CKW6Q.cjs.map +1 -0
- package/dist/chunk-W5VHATSR.cjs +31 -0
- package/dist/chunk-W5VHATSR.cjs.map +1 -0
- package/dist/chunk-W7YI5UT3.js +3 -0
- package/dist/chunk-W7YI5UT3.js.map +1 -0
- package/dist/chunk-WEQWU2IC.js +34 -0
- package/dist/chunk-WEQWU2IC.js.map +1 -0
- package/dist/chunk-WK4VXPPZ.cjs +104 -0
- package/dist/chunk-WK4VXPPZ.cjs.map +1 -0
- package/dist/chunk-WSA4LMWR.cjs +96 -0
- package/dist/chunk-WSA4LMWR.cjs.map +1 -0
- package/dist/chunk-WUIEZ6Z4.cjs +360 -0
- package/dist/chunk-WUIEZ6Z4.cjs.map +1 -0
- package/dist/chunk-WUKIJJG2.cjs +45 -0
- package/dist/chunk-WUKIJJG2.cjs.map +1 -0
- package/dist/chunk-WVFAQBS7.js +29 -0
- package/dist/chunk-WVFAQBS7.js.map +1 -0
- package/dist/chunk-X7RDNMN7.js +3 -0
- package/dist/chunk-X7RDNMN7.js.map +1 -0
- package/dist/chunk-X7XP5WBP.cjs +4 -0
- package/dist/chunk-X7XP5WBP.cjs.map +1 -0
- package/dist/chunk-XQAIEPAZ.js +104 -0
- package/dist/chunk-XQAIEPAZ.js.map +1 -0
- package/dist/chunk-XWKNE6DH.cjs +4 -0
- package/dist/chunk-XWKNE6DH.cjs.map +1 -0
- package/dist/chunk-Y6V6CBY5.js +23 -0
- package/dist/chunk-Y6V6CBY5.js.map +1 -0
- package/dist/chunk-Y6VDCZPB.js +62 -0
- package/dist/chunk-Y6VDCZPB.js.map +1 -0
- package/dist/chunk-YDRXBRW2.cjs +184 -0
- package/dist/chunk-YDRXBRW2.cjs.map +1 -0
- package/dist/chunk-YFS2LMG4.cjs +124 -0
- package/dist/chunk-YFS2LMG4.cjs.map +1 -0
- package/dist/chunk-YN6CBIIB.js +63 -0
- package/dist/chunk-YN6CBIIB.js.map +1 -0
- package/dist/chunk-YOJ2XNQX.cjs +4 -0
- package/dist/chunk-YOJ2XNQX.cjs.map +1 -0
- package/dist/chunk-YOOZB4RL.js +3 -0
- package/dist/chunk-YOOZB4RL.js.map +1 -0
- package/dist/chunk-YVU2M7MI.js +34 -0
- package/dist/chunk-YVU2M7MI.js.map +1 -0
- package/dist/chunk-YXBZRB5H.cjs +4 -0
- package/dist/chunk-YXBZRB5H.cjs.map +1 -0
- package/dist/chunk-Z3ZKFI2M.js +43 -0
- package/dist/chunk-Z3ZKFI2M.js.map +1 -0
- package/dist/chunk-Z5GLY4R3.js +112 -0
- package/dist/chunk-Z5GLY4R3.js.map +1 -0
- package/dist/chunk-Z5OMWAQX.js +3 -0
- package/dist/chunk-Z5OMWAQX.js.map +1 -0
- package/dist/chunk-Z7LGWNI7.js +38 -0
- package/dist/chunk-Z7LGWNI7.js.map +1 -0
- package/dist/chunk-ZCWKX4V6.cjs +38 -0
- package/dist/chunk-ZCWKX4V6.cjs.map +1 -0
- package/dist/chunk-ZE5RISBZ.cjs +4 -0
- package/dist/chunk-ZE5RISBZ.cjs.map +1 -0
- package/dist/chunk-ZH4F2P2G.js +3 -0
- package/dist/chunk-ZH4F2P2G.js.map +1 -0
- package/dist/chunk-ZJGFLJ2Z.cjs +4 -0
- package/dist/chunk-ZJGFLJ2Z.cjs.map +1 -0
- package/dist/chunk-ZKBHD27K.cjs +4 -0
- package/dist/chunk-ZKBHD27K.cjs.map +1 -0
- package/dist/chunk-ZQPLRNKX.cjs +4 -0
- package/dist/chunk-ZQPLRNKX.cjs.map +1 -0
- package/dist/chunk-ZQQABQMH.cjs +31 -0
- package/dist/chunk-ZQQABQMH.cjs.map +1 -0
- package/dist/chunk-ZXJQSFIA.js +200 -0
- package/dist/chunk-ZXJQSFIA.js.map +1 -0
- package/dist/developer-apps-zSQXWmEG.d.cts +294 -0
- package/dist/developer-apps-zSQXWmEG.d.ts +294 -0
- package/dist/entries/apps.cjs +13 -0
- package/dist/entries/apps.cjs.map +1 -0
- package/dist/entries/apps.d.cts +300 -0
- package/dist/entries/apps.d.ts +300 -0
- package/dist/entries/apps.js +4 -0
- package/dist/entries/apps.js.map +1 -0
- package/dist/entries/audio.cjs +13 -0
- package/dist/entries/audio.cjs.map +1 -0
- package/dist/entries/audio.d.cts +200 -0
- package/dist/entries/audio.d.ts +200 -0
- package/dist/entries/audio.js +4 -0
- package/dist/entries/audio.js.map +1 -0
- package/dist/entries/billing.cjs +13 -0
- package/dist/entries/billing.cjs.map +1 -0
- package/dist/entries/billing.d.cts +208 -0
- package/dist/entries/billing.d.ts +208 -0
- package/dist/entries/billing.js +4 -0
- package/dist/entries/billing.js.map +1 -0
- package/dist/entries/catalogs.cjs +13 -0
- package/dist/entries/catalogs.cjs.map +1 -0
- package/dist/entries/catalogs.d.cts +82 -0
- package/dist/entries/catalogs.d.ts +82 -0
- package/dist/entries/catalogs.js +4 -0
- package/dist/entries/catalogs.js.map +1 -0
- package/dist/entries/characters.cjs +45 -0
- package/dist/entries/characters.cjs.map +1 -0
- package/dist/entries/characters.d.cts +741 -0
- package/dist/entries/characters.d.ts +741 -0
- package/dist/entries/characters.js +4 -0
- package/dist/entries/characters.js.map +1 -0
- package/dist/entries/client.cjs +78 -0
- package/dist/entries/client.cjs.map +1 -0
- package/dist/entries/client.d.cts +147 -0
- package/dist/entries/client.d.ts +147 -0
- package/dist/entries/client.js +53 -0
- package/dist/entries/client.js.map +1 -0
- package/dist/entries/collections.cjs +13 -0
- package/dist/entries/collections.cjs.map +1 -0
- package/dist/entries/collections.d.cts +77 -0
- package/dist/entries/collections.d.ts +77 -0
- package/dist/entries/collections.js +4 -0
- package/dist/entries/collections.js.map +1 -0
- package/dist/entries/community.cjs +13 -0
- package/dist/entries/community.cjs.map +1 -0
- package/dist/entries/community.d.cts +87 -0
- package/dist/entries/community.d.ts +87 -0
- package/dist/entries/community.js +4 -0
- package/dist/entries/community.js.map +1 -0
- package/dist/entries/competitors.cjs +13 -0
- package/dist/entries/competitors.cjs.map +1 -0
- package/dist/entries/competitors.d.cts +96 -0
- package/dist/entries/competitors.d.ts +96 -0
- package/dist/entries/competitors.js +4 -0
- package/dist/entries/competitors.js.map +1 -0
- package/dist/entries/copilot.cjs +15 -0
- package/dist/entries/copilot.cjs.map +1 -0
- package/dist/entries/copilot.d.cts +296 -0
- package/dist/entries/copilot.d.ts +296 -0
- package/dist/entries/copilot.js +6 -0
- package/dist/entries/copilot.js.map +1 -0
- package/dist/entries/core.cjs +26 -0
- package/dist/entries/core.cjs.map +1 -0
- package/dist/entries/core.d.cts +3 -0
- package/dist/entries/core.d.ts +3 -0
- package/dist/entries/core.js +5 -0
- package/dist/entries/core.js.map +1 -0
- package/dist/entries/creatures.cjs +29 -0
- package/dist/entries/creatures.cjs.map +1 -0
- package/dist/entries/creatures.d.cts +594 -0
- package/dist/entries/creatures.d.ts +594 -0
- package/dist/entries/creatures.js +4 -0
- package/dist/entries/creatures.js.map +1 -0
- package/dist/entries/credits.cjs +13 -0
- package/dist/entries/credits.cjs.map +1 -0
- package/dist/entries/credits.d.cts +229 -0
- package/dist/entries/credits.d.ts +229 -0
- package/dist/entries/credits.js +4 -0
- package/dist/entries/credits.js.map +1 -0
- package/dist/entries/developer-apps.cjs +13 -0
- package/dist/entries/developer-apps.cjs.map +1 -0
- package/dist/entries/developer-apps.d.cts +3 -0
- package/dist/entries/developer-apps.d.ts +3 -0
- package/dist/entries/developer-apps.js +4 -0
- package/dist/entries/developer-apps.js.map +1 -0
- package/dist/entries/edit.cjs +34 -0
- package/dist/entries/edit.cjs.map +1 -0
- package/dist/entries/edit.d.cts +705 -0
- package/dist/entries/edit.d.ts +705 -0
- package/dist/entries/edit.js +5 -0
- package/dist/entries/edit.js.map +1 -0
- package/dist/entries/errors.cjs +93 -0
- package/dist/entries/errors.cjs.map +1 -0
- package/dist/entries/errors.d.cts +338 -0
- package/dist/entries/errors.d.ts +338 -0
- package/dist/entries/errors.js +4 -0
- package/dist/entries/errors.js.map +1 -0
- package/dist/entries/executions.cjs +21 -0
- package/dist/entries/executions.cjs.map +1 -0
- package/dist/entries/executions.d.cts +120 -0
- package/dist/entries/executions.d.ts +120 -0
- package/dist/entries/executions.js +4 -0
- package/dist/entries/executions.js.map +1 -0
- package/dist/entries/gallery.cjs +13 -0
- package/dist/entries/gallery.cjs.map +1 -0
- package/dist/entries/gallery.d.cts +85 -0
- package/dist/entries/gallery.d.ts +85 -0
- package/dist/entries/gallery.js +4 -0
- package/dist/entries/gallery.js.map +1 -0
- package/dist/entries/jobs.cjs +13 -0
- package/dist/entries/jobs.cjs.map +1 -0
- package/dist/entries/jobs.d.cts +252 -0
- package/dist/entries/jobs.d.ts +252 -0
- package/dist/entries/jobs.js +4 -0
- package/dist/entries/jobs.js.map +1 -0
- package/dist/entries/library.cjs +13 -0
- package/dist/entries/library.cjs.map +1 -0
- package/dist/entries/library.d.cts +109 -0
- package/dist/entries/library.d.ts +109 -0
- package/dist/entries/library.js +4 -0
- package/dist/entries/library.js.map +1 -0
- package/dist/entries/llm.cjs +13 -0
- package/dist/entries/llm.cjs.map +1 -0
- package/dist/entries/llm.d.cts +98 -0
- package/dist/entries/llm.d.ts +98 -0
- package/dist/entries/llm.js +4 -0
- package/dist/entries/llm.js.map +1 -0
- package/dist/entries/locations.cjs +25 -0
- package/dist/entries/locations.cjs.map +1 -0
- package/dist/entries/locations.d.cts +573 -0
- package/dist/entries/locations.d.ts +573 -0
- package/dist/entries/locations.js +4 -0
- package/dist/entries/locations.js.map +1 -0
- package/dist/entries/media.cjs +15 -0
- package/dist/entries/media.cjs.map +1 -0
- package/dist/entries/media.d.cts +548 -0
- package/dist/entries/media.d.ts +548 -0
- package/dist/entries/media.js +6 -0
- package/dist/entries/media.js.map +1 -0
- package/dist/entries/models.cjs +13 -0
- package/dist/entries/models.cjs.map +1 -0
- package/dist/entries/models.d.cts +92 -0
- package/dist/entries/models.d.ts +92 -0
- package/dist/entries/models.js +4 -0
- package/dist/entries/models.js.map +1 -0
- package/dist/entries/moodboards.cjs +21 -0
- package/dist/entries/moodboards.cjs.map +1 -0
- package/dist/entries/moodboards.d.cts +77 -0
- package/dist/entries/moodboards.d.ts +77 -0
- package/dist/entries/moodboards.js +4 -0
- package/dist/entries/moodboards.js.map +1 -0
- package/dist/entries/node-presets.cjs +13 -0
- package/dist/entries/node-presets.cjs.map +1 -0
- package/dist/entries/node-presets.d.cts +217 -0
- package/dist/entries/node-presets.d.ts +217 -0
- package/dist/entries/node-presets.js +4 -0
- package/dist/entries/node-presets.js.map +1 -0
- package/dist/entries/nodes.cjs +22 -0
- package/dist/entries/nodes.cjs.map +1 -0
- package/dist/entries/nodes.d.cts +18 -0
- package/dist/entries/nodes.d.ts +18 -0
- package/dist/entries/nodes.js +5 -0
- package/dist/entries/nodes.js.map +1 -0
- package/dist/entries/oauth.cjs +13 -0
- package/dist/entries/oauth.cjs.map +1 -0
- package/dist/entries/oauth.d.cts +69 -0
- package/dist/entries/oauth.d.ts +69 -0
- package/dist/entries/oauth.js +4 -0
- package/dist/entries/oauth.js.map +1 -0
- package/dist/entries/objects.cjs +29 -0
- package/dist/entries/objects.cjs.map +1 -0
- package/dist/entries/objects.d.cts +544 -0
- package/dist/entries/objects.d.ts +544 -0
- package/dist/entries/objects.js +4 -0
- package/dist/entries/objects.js.map +1 -0
- package/dist/entries/organizations.cjs +21 -0
- package/dist/entries/organizations.cjs.map +1 -0
- package/dist/entries/organizations.d.cts +164 -0
- package/dist/entries/organizations.d.ts +164 -0
- package/dist/entries/organizations.js +4 -0
- package/dist/entries/organizations.js.map +1 -0
- package/dist/entries/palettes.cjs +21 -0
- package/dist/entries/palettes.cjs.map +1 -0
- package/dist/entries/palettes.d.cts +69 -0
- package/dist/entries/palettes.d.ts +69 -0
- package/dist/entries/palettes.js +4 -0
- package/dist/entries/palettes.js.map +1 -0
- package/dist/entries/picker-catalogs.cjs +13 -0
- package/dist/entries/picker-catalogs.cjs.map +1 -0
- package/dist/entries/picker-catalogs.d.cts +148 -0
- package/dist/entries/picker-catalogs.d.ts +148 -0
- package/dist/entries/picker-catalogs.js +4 -0
- package/dist/entries/picker-catalogs.js.map +1 -0
- package/dist/entries/pipelines.cjs +13 -0
- package/dist/entries/pipelines.cjs.map +1 -0
- package/dist/entries/pipelines.d.cts +255 -0
- package/dist/entries/pipelines.d.ts +255 -0
- package/dist/entries/pipelines.js +4 -0
- package/dist/entries/pipelines.js.map +1 -0
- package/dist/entries/projects.cjs +13 -0
- package/dist/entries/projects.cjs.map +1 -0
- package/dist/entries/projects.d.cts +49 -0
- package/dist/entries/projects.d.ts +49 -0
- package/dist/entries/projects.js +4 -0
- package/dist/entries/projects.js.map +1 -0
- package/dist/entries/prompt-helper.cjs +13 -0
- package/dist/entries/prompt-helper.cjs.map +1 -0
- package/dist/entries/prompt-helper.d.cts +73 -0
- package/dist/entries/prompt-helper.d.ts +73 -0
- package/dist/entries/prompt-helper.js +4 -0
- package/dist/entries/prompt-helper.js.map +1 -0
- package/dist/entries/recast.cjs +17 -0
- package/dist/entries/recast.cjs.map +1 -0
- package/dist/entries/recast.d.cts +229 -0
- package/dist/entries/recast.d.ts +229 -0
- package/dist/entries/recast.js +4 -0
- package/dist/entries/recast.js.map +1 -0
- package/dist/entries/reduce.cjs +13 -0
- package/dist/entries/reduce.cjs.map +1 -0
- package/dist/entries/reduce.d.cts +56 -0
- package/dist/entries/reduce.d.ts +56 -0
- package/dist/entries/reduce.js +4 -0
- package/dist/entries/reduce.js.map +1 -0
- package/dist/entries/saved-posts.cjs +13 -0
- package/dist/entries/saved-posts.cjs.map +1 -0
- package/dist/entries/saved-posts.d.cts +33 -0
- package/dist/entries/saved-posts.d.ts +33 -0
- package/dist/entries/saved-posts.js +4 -0
- package/dist/entries/saved-posts.js.map +1 -0
- package/dist/entries/scene3d.cjs +17 -0
- package/dist/entries/scene3d.cjs.map +1 -0
- package/dist/entries/scene3d.d.cts +131 -0
- package/dist/entries/scene3d.d.ts +131 -0
- package/dist/entries/scene3d.js +4 -0
- package/dist/entries/scene3d.js.map +1 -0
- package/dist/entries/sessions.cjs +13 -0
- package/dist/entries/sessions.cjs.map +1 -0
- package/dist/entries/sessions.d.cts +122 -0
- package/dist/entries/sessions.d.ts +122 -0
- package/dist/entries/sessions.js +4 -0
- package/dist/entries/sessions.js.map +1 -0
- package/dist/entries/shots.cjs +13 -0
- package/dist/entries/shots.cjs.map +1 -0
- package/dist/entries/shots.d.cts +78 -0
- package/dist/entries/shots.d.ts +78 -0
- package/dist/entries/shots.js +4 -0
- package/dist/entries/shots.js.map +1 -0
- package/dist/entries/studio.cjs +22 -0
- package/dist/entries/studio.cjs.map +1 -0
- package/dist/entries/studio.d.cts +281 -0
- package/dist/entries/studio.d.ts +281 -0
- package/dist/entries/studio.js +5 -0
- package/dist/entries/studio.js.map +1 -0
- package/dist/entries/templates.cjs +13 -0
- package/dist/entries/templates.cjs.map +1 -0
- package/dist/entries/templates.d.cts +110 -0
- package/dist/entries/templates.d.ts +110 -0
- package/dist/entries/templates.js +4 -0
- package/dist/entries/templates.js.map +1 -0
- package/dist/entries/tutorials.cjs +13 -0
- package/dist/entries/tutorials.cjs.map +1 -0
- package/dist/entries/tutorials.d.cts +63 -0
- package/dist/entries/tutorials.d.ts +63 -0
- package/dist/entries/tutorials.js +4 -0
- package/dist/entries/tutorials.js.map +1 -0
- package/dist/entries/uploads.cjs +13 -0
- package/dist/entries/uploads.cjs.map +1 -0
- package/dist/entries/uploads.d.cts +44 -0
- package/dist/entries/uploads.d.ts +44 -0
- package/dist/entries/uploads.js +4 -0
- package/dist/entries/uploads.js.map +1 -0
- package/dist/entries/video-pro.cjs +13 -0
- package/dist/entries/video-pro.cjs.map +1 -0
- package/dist/entries/video-pro.d.cts +60 -0
- package/dist/entries/video-pro.d.ts +60 -0
- package/dist/entries/video-pro.js +4 -0
- package/dist/entries/video-pro.js.map +1 -0
- package/dist/entries/voices.cjs +13 -0
- package/dist/entries/voices.cjs.map +1 -0
- package/dist/entries/voices.d.cts +498 -0
- package/dist/entries/voices.d.ts +498 -0
- package/dist/entries/voices.js +4 -0
- package/dist/entries/voices.js.map +1 -0
- package/dist/entries/webhooks.cjs +21 -0
- package/dist/entries/webhooks.cjs.map +1 -0
- package/dist/entries/webhooks.d.cts +64 -0
- package/dist/entries/webhooks.d.ts +64 -0
- package/dist/entries/webhooks.js +4 -0
- package/dist/entries/webhooks.js.map +1 -0
- package/dist/entries/workflows.cjs +13 -0
- package/dist/entries/workflows.cjs.map +1 -0
- package/dist/entries/workflows.d.cts +393 -0
- package/dist/entries/workflows.d.ts +393 -0
- package/dist/entries/workflows.js +4 -0
- package/dist/entries/workflows.js.map +1 -0
- package/dist/entries/workspaces.cjs +13 -0
- package/dist/entries/workspaces.cjs.map +1 -0
- package/dist/entries/workspaces.d.cts +124 -0
- package/dist/entries/workspaces.d.ts +124 -0
- package/dist/entries/workspaces.js +4 -0
- package/dist/entries/workspaces.js.map +1 -0
- package/dist/index.cjs +501 -4618
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -9651
- package/dist/index.d.ts +66 -9651
- package/dist/index.js +100 -4511
- package/dist/index.js.map +1 -1
- package/dist/nodes-BPvrAoUs.d.cts +1264 -0
- package/dist/nodes-C2zu3uqn.d.ts +1264 -0
- package/dist/studio-productions-DUHvdSvk.d.cts +572 -0
- package/dist/studio-productions-vbCNSbtf.d.ts +572 -0
- package/dist/webhooks-BJawEIz8.d.ts +198 -0
- package/dist/webhooks-Dn_DtNTD.d.cts +198 -0
- package/package.json +253 -3
package/dist/index.js
CHANGED
|
@@ -1,4513 +1,102 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|