@openpalm/ui 0.11.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/README.md +129 -0
  2. package/build/.openpalm-ui-version +1 -0
  3. package/build/client/_app/immutable/assets/0.BK7X4bPu.css +1 -0
  4. package/build/client/_app/immutable/assets/0.BK7X4bPu.css.br +0 -0
  5. package/build/client/_app/immutable/assets/0.BK7X4bPu.css.gz +0 -0
  6. package/build/client/_app/immutable/assets/4.D9MwgTDo.css +1 -0
  7. package/build/client/_app/immutable/assets/4.D9MwgTDo.css.br +0 -0
  8. package/build/client/_app/immutable/assets/4.D9MwgTDo.css.gz +0 -0
  9. package/build/client/_app/immutable/assets/5.Cj0Mk9Gn.css +1 -0
  10. package/build/client/_app/immutable/assets/5.Cj0Mk9Gn.css.br +0 -0
  11. package/build/client/_app/immutable/assets/5.Cj0Mk9Gn.css.gz +0 -0
  12. package/build/client/_app/immutable/assets/6.DJenXolA.css +1 -0
  13. package/build/client/_app/immutable/assets/6.DJenXolA.css.br +0 -0
  14. package/build/client/_app/immutable/assets/6.DJenXolA.css.gz +0 -0
  15. package/build/client/_app/immutable/assets/7.BHUsSUvX.css +1 -0
  16. package/build/client/_app/immutable/assets/7.BHUsSUvX.css.br +0 -0
  17. package/build/client/_app/immutable/assets/7.BHUsSUvX.css.gz +0 -0
  18. package/build/client/_app/immutable/assets/8.DjrHy5wu.css +1 -0
  19. package/build/client/_app/immutable/assets/8.DjrHy5wu.css.br +0 -0
  20. package/build/client/_app/immutable/assets/8.DjrHy5wu.css.gz +0 -0
  21. package/build/client/_app/immutable/assets/AuthGate.BtJV-xXj.css +1 -0
  22. package/build/client/_app/immutable/assets/AuthGate.BtJV-xXj.css.br +0 -0
  23. package/build/client/_app/immutable/assets/AuthGate.BtJV-xXj.css.gz +0 -0
  24. package/build/client/_app/immutable/assets/VoiceProfileSelector.Dp7tWdKe.css +1 -0
  25. package/build/client/_app/immutable/assets/VoiceProfileSelector.Dp7tWdKe.css.br +0 -0
  26. package/build/client/_app/immutable/assets/VoiceProfileSelector.Dp7tWdKe.css.gz +0 -0
  27. package/build/client/_app/immutable/chunks/BuFlayix.js +1 -0
  28. package/build/client/_app/immutable/chunks/BuFlayix.js.br +0 -0
  29. package/build/client/_app/immutable/chunks/BuFlayix.js.gz +0 -0
  30. package/build/client/_app/immutable/chunks/BwTF6U35.js +3 -0
  31. package/build/client/_app/immutable/chunks/BwTF6U35.js.br +0 -0
  32. package/build/client/_app/immutable/chunks/BwTF6U35.js.gz +0 -0
  33. package/build/client/_app/immutable/chunks/C8qMxft1.js +1 -0
  34. package/build/client/_app/immutable/chunks/C8qMxft1.js.br +0 -0
  35. package/build/client/_app/immutable/chunks/C8qMxft1.js.gz +0 -0
  36. package/build/client/_app/immutable/chunks/Cb_i8bV9.js +1 -0
  37. package/build/client/_app/immutable/chunks/Cb_i8bV9.js.br +0 -0
  38. package/build/client/_app/immutable/chunks/Cb_i8bV9.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/CzXGhlNF.js +1 -0
  40. package/build/client/_app/immutable/chunks/CzXGhlNF.js.br +0 -0
  41. package/build/client/_app/immutable/chunks/CzXGhlNF.js.gz +0 -0
  42. package/build/client/_app/immutable/chunks/DYskO3Sk.js +5 -0
  43. package/build/client/_app/immutable/chunks/DYskO3Sk.js.br +0 -0
  44. package/build/client/_app/immutable/chunks/DYskO3Sk.js.gz +0 -0
  45. package/build/client/_app/immutable/chunks/ak2ISc8B.js +1 -0
  46. package/build/client/_app/immutable/chunks/ak2ISc8B.js.br +0 -0
  47. package/build/client/_app/immutable/chunks/ak2ISc8B.js.gz +0 -0
  48. package/build/client/_app/immutable/chunks/kNaey6uv.js +1 -0
  49. package/build/client/_app/immutable/chunks/kNaey6uv.js.br +0 -0
  50. package/build/client/_app/immutable/chunks/kNaey6uv.js.gz +0 -0
  51. package/build/client/_app/immutable/chunks/os2NZ37U.js +1 -0
  52. package/build/client/_app/immutable/chunks/os2NZ37U.js.br +1 -0
  53. package/build/client/_app/immutable/chunks/os2NZ37U.js.gz +0 -0
  54. package/build/client/_app/immutable/chunks/xihTtKlq.js +1 -0
  55. package/build/client/_app/immutable/chunks/xihTtKlq.js.br +1 -0
  56. package/build/client/_app/immutable/chunks/xihTtKlq.js.gz +0 -0
  57. package/build/client/_app/immutable/entry/app.C_eSlUyi.js +2 -0
  58. package/build/client/_app/immutable/entry/app.C_eSlUyi.js.br +0 -0
  59. package/build/client/_app/immutable/entry/app.C_eSlUyi.js.gz +0 -0
  60. package/build/client/_app/immutable/entry/start.BAta_Cih.js +1 -0
  61. package/build/client/_app/immutable/entry/start.BAta_Cih.js.br +0 -0
  62. package/build/client/_app/immutable/entry/start.BAta_Cih.js.gz +0 -0
  63. package/build/client/_app/immutable/nodes/0.Bi_of0So.js +1 -0
  64. package/build/client/_app/immutable/nodes/0.Bi_of0So.js.br +0 -0
  65. package/build/client/_app/immutable/nodes/0.Bi_of0So.js.gz +0 -0
  66. package/build/client/_app/immutable/nodes/1.qjZsjpWC.js +1 -0
  67. package/build/client/_app/immutable/nodes/1.qjZsjpWC.js.br +0 -0
  68. package/build/client/_app/immutable/nodes/1.qjZsjpWC.js.gz +0 -0
  69. package/build/client/_app/immutable/nodes/2.ojh8oE7F.js +1 -0
  70. package/build/client/_app/immutable/nodes/2.ojh8oE7F.js.br +0 -0
  71. package/build/client/_app/immutable/nodes/2.ojh8oE7F.js.gz +0 -0
  72. package/build/client/_app/immutable/nodes/3.DeAC3yVJ.js +1 -0
  73. package/build/client/_app/immutable/nodes/3.DeAC3yVJ.js.br +0 -0
  74. package/build/client/_app/immutable/nodes/3.DeAC3yVJ.js.gz +0 -0
  75. package/build/client/_app/immutable/nodes/4.BYtA2xx-.js +19 -0
  76. package/build/client/_app/immutable/nodes/4.BYtA2xx-.js.br +0 -0
  77. package/build/client/_app/immutable/nodes/4.BYtA2xx-.js.gz +0 -0
  78. package/build/client/_app/immutable/nodes/5.ChSoAFFd.js +4 -0
  79. package/build/client/_app/immutable/nodes/5.ChSoAFFd.js.br +0 -0
  80. package/build/client/_app/immutable/nodes/5.ChSoAFFd.js.gz +0 -0
  81. package/build/client/_app/immutable/nodes/6.BRG0vYmH.js +1 -0
  82. package/build/client/_app/immutable/nodes/6.BRG0vYmH.js.br +0 -0
  83. package/build/client/_app/immutable/nodes/6.BRG0vYmH.js.gz +0 -0
  84. package/build/client/_app/immutable/nodes/7.BVvy1f_p.js +15 -0
  85. package/build/client/_app/immutable/nodes/7.BVvy1f_p.js.br +0 -0
  86. package/build/client/_app/immutable/nodes/7.BVvy1f_p.js.gz +0 -0
  87. package/build/client/_app/immutable/nodes/8.Cb4MWMah.js +2 -0
  88. package/build/client/_app/immutable/nodes/8.Cb4MWMah.js.br +0 -0
  89. package/build/client/_app/immutable/nodes/8.Cb4MWMah.js.gz +0 -0
  90. package/build/client/_app/version.json +1 -0
  91. package/build/client/_app/version.json.br +0 -0
  92. package/build/client/_app/version.json.gz +0 -0
  93. package/build/client/banner.png +0 -0
  94. package/build/client/fu-128.png +0 -0
  95. package/build/client/fu.png +0 -0
  96. package/build/client/logo-128.png +0 -0
  97. package/build/client/logo.png +0 -0
  98. package/build/client/setup/wizard.css +1639 -0
  99. package/build/client/setup/wizard.css.br +0 -0
  100. package/build/client/setup/wizard.css.gz +0 -0
  101. package/build/client/wizard-128.png +0 -0
  102. package/build/client/wizard.png +0 -0
  103. package/build/env.js +94 -0
  104. package/build/handler.js +1494 -0
  105. package/build/index.js +345 -0
  106. package/build/server/chunks/0-Dk6RRhi2.js +9 -0
  107. package/build/server/chunks/0-Dk6RRhi2.js.map +1 -0
  108. package/build/server/chunks/1-CWcY3PRs.js +9 -0
  109. package/build/server/chunks/1-CWcY3PRs.js.map +1 -0
  110. package/build/server/chunks/2-C2y4ydWU.js +9 -0
  111. package/build/server/chunks/2-C2y4ydWU.js.map +1 -0
  112. package/build/server/chunks/3-BgeGdVvT.js +23 -0
  113. package/build/server/chunks/3-BgeGdVvT.js.map +1 -0
  114. package/build/server/chunks/4-DeAt_mYc.js +9 -0
  115. package/build/server/chunks/4-DeAt_mYc.js.map +1 -0
  116. package/build/server/chunks/5-qTXiNPEM.js +9 -0
  117. package/build/server/chunks/5-qTXiNPEM.js.map +1 -0
  118. package/build/server/chunks/6-C444Mr69.js +9 -0
  119. package/build/server/chunks/6-C444Mr69.js.map +1 -0
  120. package/build/server/chunks/7-Dg_sVly5.js +9 -0
  121. package/build/server/chunks/7-Dg_sVly5.js.map +1 -0
  122. package/build/server/chunks/8-CF5kn4AY.js +9 -0
  123. package/build/server/chunks/8-CF5kn4AY.js.map +1 -0
  124. package/build/server/chunks/AuthGate-keg7G6rX.js +707 -0
  125. package/build/server/chunks/AuthGate-keg7G6rX.js.map +1 -0
  126. package/build/server/chunks/_helpers-B_lb4-jB.js +74 -0
  127. package/build/server/chunks/_helpers-B_lb4-jB.js.map +1 -0
  128. package/build/server/chunks/_layout.svelte-B93aaRP_.js +11 -0
  129. package/build/server/chunks/_layout.svelte-B93aaRP_.js.map +1 -0
  130. package/build/server/chunks/_layout.svelte-BNWepgTx.js +58 -0
  131. package/build/server/chunks/_layout.svelte-BNWepgTx.js.map +1 -0
  132. package/build/server/chunks/_page.svelte-BP2EdQl3.js +5 -0
  133. package/build/server/chunks/_page.svelte-BP2EdQl3.js.map +1 -0
  134. package/build/server/chunks/_page.svelte-BdYSYjmj.js +67 -0
  135. package/build/server/chunks/_page.svelte-BdYSYjmj.js.map +1 -0
  136. package/build/server/chunks/_page.svelte-BiKY57wg.js +533 -0
  137. package/build/server/chunks/_page.svelte-BiKY57wg.js.map +1 -0
  138. package/build/server/chunks/_page.svelte-CtX_8pMq.js +5528 -0
  139. package/build/server/chunks/_page.svelte-CtX_8pMq.js.map +1 -0
  140. package/build/server/chunks/_page.svelte-D0gMlmzQ.js +104 -0
  141. package/build/server/chunks/_page.svelte-D0gMlmzQ.js.map +1 -0
  142. package/build/server/chunks/_page.svelte-DwMiUmq6.js +107 -0
  143. package/build/server/chunks/_page.svelte-DwMiUmq6.js.map +1 -0
  144. package/build/server/chunks/_server.ts-0FuXkx70.js +56 -0
  145. package/build/server/chunks/_server.ts-0FuXkx70.js.map +1 -0
  146. package/build/server/chunks/_server.ts-33LuQvHu.js +19 -0
  147. package/build/server/chunks/_server.ts-33LuQvHu.js.map +1 -0
  148. package/build/server/chunks/_server.ts-5Q0J3F4-.js +55 -0
  149. package/build/server/chunks/_server.ts-5Q0J3F4-.js.map +1 -0
  150. package/build/server/chunks/_server.ts-AJk0xBLJ.js +46 -0
  151. package/build/server/chunks/_server.ts-AJk0xBLJ.js.map +1 -0
  152. package/build/server/chunks/_server.ts-AQe1PIYE.js +68 -0
  153. package/build/server/chunks/_server.ts-AQe1PIYE.js.map +1 -0
  154. package/build/server/chunks/_server.ts-B0N2Nj7L.js +44 -0
  155. package/build/server/chunks/_server.ts-B0N2Nj7L.js.map +1 -0
  156. package/build/server/chunks/_server.ts-BDBJ6fxs.js +67 -0
  157. package/build/server/chunks/_server.ts-BDBJ6fxs.js.map +1 -0
  158. package/build/server/chunks/_server.ts-BEeaI665.js +79 -0
  159. package/build/server/chunks/_server.ts-BEeaI665.js.map +1 -0
  160. package/build/server/chunks/_server.ts-BM4QuGQf.js +53 -0
  161. package/build/server/chunks/_server.ts-BM4QuGQf.js.map +1 -0
  162. package/build/server/chunks/_server.ts-BSIZMZVn.js +50 -0
  163. package/build/server/chunks/_server.ts-BSIZMZVn.js.map +1 -0
  164. package/build/server/chunks/_server.ts-BV-6Mum8.js +54 -0
  165. package/build/server/chunks/_server.ts-BV-6Mum8.js.map +1 -0
  166. package/build/server/chunks/_server.ts-BdnJF23z.js +44 -0
  167. package/build/server/chunks/_server.ts-BdnJF23z.js.map +1 -0
  168. package/build/server/chunks/_server.ts-Bfy4RFhe.js +41 -0
  169. package/build/server/chunks/_server.ts-Bfy4RFhe.js.map +1 -0
  170. package/build/server/chunks/_server.ts-Bhh33s6N.js +149 -0
  171. package/build/server/chunks/_server.ts-Bhh33s6N.js.map +1 -0
  172. package/build/server/chunks/_server.ts-BiSuK8jN.js +41 -0
  173. package/build/server/chunks/_server.ts-BiSuK8jN.js.map +1 -0
  174. package/build/server/chunks/_server.ts-BjiyoKWK.js +41 -0
  175. package/build/server/chunks/_server.ts-BjiyoKWK.js.map +1 -0
  176. package/build/server/chunks/_server.ts-BnEeEd9g.js +57 -0
  177. package/build/server/chunks/_server.ts-BnEeEd9g.js.map +1 -0
  178. package/build/server/chunks/_server.ts-Bq2dkWvj.js +33 -0
  179. package/build/server/chunks/_server.ts-Bq2dkWvj.js.map +1 -0
  180. package/build/server/chunks/_server.ts-Br16AqpO.js +82 -0
  181. package/build/server/chunks/_server.ts-Br16AqpO.js.map +1 -0
  182. package/build/server/chunks/_server.ts-BsZrddQT.js +200 -0
  183. package/build/server/chunks/_server.ts-BsZrddQT.js.map +1 -0
  184. package/build/server/chunks/_server.ts-Btbzy89u.js +65 -0
  185. package/build/server/chunks/_server.ts-Btbzy89u.js.map +1 -0
  186. package/build/server/chunks/_server.ts-BudQlGOx.js +70 -0
  187. package/build/server/chunks/_server.ts-BudQlGOx.js.map +1 -0
  188. package/build/server/chunks/_server.ts-BxPYakCb.js +59 -0
  189. package/build/server/chunks/_server.ts-BxPYakCb.js.map +1 -0
  190. package/build/server/chunks/_server.ts-ByyRcwFy.js +79 -0
  191. package/build/server/chunks/_server.ts-ByyRcwFy.js.map +1 -0
  192. package/build/server/chunks/_server.ts-C7rtn3mH.js +103 -0
  193. package/build/server/chunks/_server.ts-C7rtn3mH.js.map +1 -0
  194. package/build/server/chunks/_server.ts-C88qd-ju.js +46 -0
  195. package/build/server/chunks/_server.ts-C88qd-ju.js.map +1 -0
  196. package/build/server/chunks/_server.ts-CD6LeslU.js +55 -0
  197. package/build/server/chunks/_server.ts-CD6LeslU.js.map +1 -0
  198. package/build/server/chunks/_server.ts-CDlWxA5S.js +60 -0
  199. package/build/server/chunks/_server.ts-CDlWxA5S.js.map +1 -0
  200. package/build/server/chunks/_server.ts-CGqrfNlv.js +514 -0
  201. package/build/server/chunks/_server.ts-CGqrfNlv.js.map +1 -0
  202. package/build/server/chunks/_server.ts-CGwYZUuw.js +759 -0
  203. package/build/server/chunks/_server.ts-CGwYZUuw.js.map +1 -0
  204. package/build/server/chunks/_server.ts-CHVs0yya.js +54 -0
  205. package/build/server/chunks/_server.ts-CHVs0yya.js.map +1 -0
  206. package/build/server/chunks/_server.ts-CMEY6oQe.js +121 -0
  207. package/build/server/chunks/_server.ts-CMEY6oQe.js.map +1 -0
  208. package/build/server/chunks/_server.ts-CS73tiTY.js +63 -0
  209. package/build/server/chunks/_server.ts-CS73tiTY.js.map +1 -0
  210. package/build/server/chunks/_server.ts-CWwgmo8z.js +33 -0
  211. package/build/server/chunks/_server.ts-CWwgmo8z.js.map +1 -0
  212. package/build/server/chunks/_server.ts-CXzZeGlQ.js +55 -0
  213. package/build/server/chunks/_server.ts-CXzZeGlQ.js.map +1 -0
  214. package/build/server/chunks/_server.ts-C_kseo_y.js +72 -0
  215. package/build/server/chunks/_server.ts-C_kseo_y.js.map +1 -0
  216. package/build/server/chunks/_server.ts-Cbk-UThV.js +73 -0
  217. package/build/server/chunks/_server.ts-Cbk-UThV.js.map +1 -0
  218. package/build/server/chunks/_server.ts-CboRRTK1.js +139 -0
  219. package/build/server/chunks/_server.ts-CboRRTK1.js.map +1 -0
  220. package/build/server/chunks/_server.ts-CgD8-EFl.js +52 -0
  221. package/build/server/chunks/_server.ts-CgD8-EFl.js.map +1 -0
  222. package/build/server/chunks/_server.ts-Ci-q0BiD.js +79 -0
  223. package/build/server/chunks/_server.ts-Ci-q0BiD.js.map +1 -0
  224. package/build/server/chunks/_server.ts-Cn7ahHlk.js +44 -0
  225. package/build/server/chunks/_server.ts-Cn7ahHlk.js.map +1 -0
  226. package/build/server/chunks/_server.ts-Cy36-qGT.js +60 -0
  227. package/build/server/chunks/_server.ts-Cy36-qGT.js.map +1 -0
  228. package/build/server/chunks/_server.ts-CyFZ9OZQ.js +97 -0
  229. package/build/server/chunks/_server.ts-CyFZ9OZQ.js.map +1 -0
  230. package/build/server/chunks/_server.ts-D-UAqhor.js +33 -0
  231. package/build/server/chunks/_server.ts-D-UAqhor.js.map +1 -0
  232. package/build/server/chunks/_server.ts-D1cb1hmF.js +90 -0
  233. package/build/server/chunks/_server.ts-D1cb1hmF.js.map +1 -0
  234. package/build/server/chunks/_server.ts-D33gvU5B.js +65 -0
  235. package/build/server/chunks/_server.ts-D33gvU5B.js.map +1 -0
  236. package/build/server/chunks/_server.ts-DDwiNChJ.js +88 -0
  237. package/build/server/chunks/_server.ts-DDwiNChJ.js.map +1 -0
  238. package/build/server/chunks/_server.ts-DEnxvwcJ.js +46 -0
  239. package/build/server/chunks/_server.ts-DEnxvwcJ.js.map +1 -0
  240. package/build/server/chunks/_server.ts-DHXmcRrP.js +41 -0
  241. package/build/server/chunks/_server.ts-DHXmcRrP.js.map +1 -0
  242. package/build/server/chunks/_server.ts-DQxY-pHZ.js +64 -0
  243. package/build/server/chunks/_server.ts-DQxY-pHZ.js.map +1 -0
  244. package/build/server/chunks/_server.ts-DXNJ2LJu.js +83 -0
  245. package/build/server/chunks/_server.ts-DXNJ2LJu.js.map +1 -0
  246. package/build/server/chunks/_server.ts-Dbly1Fe-.js +96 -0
  247. package/build/server/chunks/_server.ts-Dbly1Fe-.js.map +1 -0
  248. package/build/server/chunks/_server.ts-DffjWMNC.js +53 -0
  249. package/build/server/chunks/_server.ts-DffjWMNC.js.map +1 -0
  250. package/build/server/chunks/_server.ts-Di-8UJYw.js +40 -0
  251. package/build/server/chunks/_server.ts-Di-8UJYw.js.map +1 -0
  252. package/build/server/chunks/_server.ts-DsEzCr9k.js +109 -0
  253. package/build/server/chunks/_server.ts-DsEzCr9k.js.map +1 -0
  254. package/build/server/chunks/_server.ts-DwXd92Ow.js +63 -0
  255. package/build/server/chunks/_server.ts-DwXd92Ow.js.map +1 -0
  256. package/build/server/chunks/_server.ts-DwjjO7L5.js +41 -0
  257. package/build/server/chunks/_server.ts-DwjjO7L5.js.map +1 -0
  258. package/build/server/chunks/_server.ts-DyEbcQS0.js +62 -0
  259. package/build/server/chunks/_server.ts-DyEbcQS0.js.map +1 -0
  260. package/build/server/chunks/_server.ts-HxcM6xQA.js +70 -0
  261. package/build/server/chunks/_server.ts-HxcM6xQA.js.map +1 -0
  262. package/build/server/chunks/_server.ts-JItoNB1Z.js +57 -0
  263. package/build/server/chunks/_server.ts-JItoNB1Z.js.map +1 -0
  264. package/build/server/chunks/_server.ts-KpT_vKKo.js +77 -0
  265. package/build/server/chunks/_server.ts-KpT_vKKo.js.map +1 -0
  266. package/build/server/chunks/_server.ts-WbY7XmtT.js +157 -0
  267. package/build/server/chunks/_server.ts-WbY7XmtT.js.map +1 -0
  268. package/build/server/chunks/_server.ts-Yy0BWsSd.js +70 -0
  269. package/build/server/chunks/_server.ts-Yy0BWsSd.js.map +1 -0
  270. package/build/server/chunks/_server.ts-b9yNYKW6.js +49 -0
  271. package/build/server/chunks/_server.ts-b9yNYKW6.js.map +1 -0
  272. package/build/server/chunks/_server.ts-bAJXjaCc.js +42 -0
  273. package/build/server/chunks/_server.ts-bAJXjaCc.js.map +1 -0
  274. package/build/server/chunks/_server.ts-cwRl-tZ-.js +40 -0
  275. package/build/server/chunks/_server.ts-cwRl-tZ-.js.map +1 -0
  276. package/build/server/chunks/_server.ts-hMTx0DC3.js +159 -0
  277. package/build/server/chunks/_server.ts-hMTx0DC3.js.map +1 -0
  278. package/build/server/chunks/_server.ts-l_HoZ2_I.js +163 -0
  279. package/build/server/chunks/_server.ts-l_HoZ2_I.js.map +1 -0
  280. package/build/server/chunks/_server.ts-uLRX2uy0.js +107 -0
  281. package/build/server/chunks/_server.ts-uLRX2uy0.js.map +1 -0
  282. package/build/server/chunks/_server.ts-uWfb47S6.js +204 -0
  283. package/build/server/chunks/_server.ts-uWfb47S6.js.map +1 -0
  284. package/build/server/chunks/addon-helpers-Bnj3aKJ2.js +49 -0
  285. package/build/server/chunks/addon-helpers-Bnj3aKJ2.js.map +1 -0
  286. package/build/server/chunks/chunk-CLZ62Ad-.js +18 -0
  287. package/build/server/chunks/chunk-CLZ62Ad-.js.map +1 -0
  288. package/build/server/chunks/coercion-TNFJisCC.js +34 -0
  289. package/build/server/chunks/coercion-TNFJisCC.js.map +1 -0
  290. package/build/server/chunks/config-CEYPfvQh.js +121 -0
  291. package/build/server/chunks/config-CEYPfvQh.js.map +1 -0
  292. package/build/server/chunks/dev-DjANv7AF.js +4389 -0
  293. package/build/server/chunks/dev-DjANv7AF.js.map +1 -0
  294. package/build/server/chunks/docker-sGFTjRfy.js +20 -0
  295. package/build/server/chunks/docker-sGFTjRfy.js.map +1 -0
  296. package/build/server/chunks/endpoints-L7Wjvq44.js +340 -0
  297. package/build/server/chunks/endpoints-L7Wjvq44.js.map +1 -0
  298. package/build/server/chunks/environment-BnT49Gi3.js +36 -0
  299. package/build/server/chunks/environment-BnT49Gi3.js.map +1 -0
  300. package/build/server/chunks/error.svelte-PJnhZZCy.js +16 -0
  301. package/build/server/chunks/error.svelte-PJnhZZCy.js.map +1 -0
  302. package/build/server/chunks/exports-D1quPX8S.js +124 -0
  303. package/build/server/chunks/exports-D1quPX8S.js.map +1 -0
  304. package/build/server/chunks/helpers-5jd3ccud.js +226 -0
  305. package/build/server/chunks/helpers-5jd3ccud.js.map +1 -0
  306. package/build/server/chunks/hooks.server-Al9-eO5K.js +82 -0
  307. package/build/server/chunks/hooks.server-Al9-eO5K.js.map +1 -0
  308. package/build/server/chunks/http-D5xo_m60.js +31 -0
  309. package/build/server/chunks/http-D5xo_m60.js.map +1 -0
  310. package/build/server/chunks/internal-CJBOAkaQ.js +1544 -0
  311. package/build/server/chunks/internal-CJBOAkaQ.js.map +1 -0
  312. package/build/server/chunks/serial-queue-D9FEpYVv.js +22 -0
  313. package/build/server/chunks/serial-queue-D9FEpYVv.js.map +1 -0
  314. package/build/server/chunks/setup-deploy-UKTSVAC0.js +529 -0
  315. package/build/server/chunks/setup-deploy-UKTSVAC0.js.map +1 -0
  316. package/build/server/chunks/src-FpMyngcw.js +14064 -0
  317. package/build/server/chunks/src-FpMyngcw.js.map +1 -0
  318. package/build/server/chunks/state-BI-lJPhE.js +203 -0
  319. package/build/server/chunks/state-BI-lJPhE.js.map +1 -0
  320. package/build/server/chunks/utils-BSRjJDrZ.js +150 -0
  321. package/build/server/chunks/utils-BSRjJDrZ.js.map +1 -0
  322. package/build/server/chunks/voice-state.svelte-CQp8u0bn.js +437 -0
  323. package/build/server/chunks/voice-state.svelte-CQp8u0bn.js.map +1 -0
  324. package/build/server/index.js +4359 -0
  325. package/build/server/index.js.map +1 -0
  326. package/build/server/manifest.js +570 -0
  327. package/build/server/manifest.js.map +1 -0
  328. package/build/shims.js +32 -0
  329. package/package.json +61 -0
@@ -0,0 +1,759 @@
1
+ import { aa as readStackEnv, b as annotateAddonProfileAvailability, R as getAddonProfiles, Q as getAddonProfileSelection, a as addonProfileId, aw as writeVoiceVars, a0 as listEnabledAddonIds, w as composeStop, k as buildComposeOptions, an as setAddonProfileSelection, am as setAddonEnabled, P as getAddonProfileAvailability, x as composeUp, a3 as parseComposeStderr } from './src-FpMyngcw.js';
2
+ import { b as getState } from './endpoints-L7Wjvq44.js';
3
+ import { d as getRequestId, r as requireAdmin, h as jsonResponse, e as errorResponse } from './helpers-5jd3ccud.js';
4
+ import { w as withSerialQueue } from './serial-queue-D9FEpYVv.js';
5
+ import { existsSync, writeFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { execFile } from 'node:child_process';
8
+ import { connect } from 'node:net';
9
+ import './chunk-CLZ62Ad-.js';
10
+ import 'node:module';
11
+ import 'node:os';
12
+ import 'buffer';
13
+ import 'node:url';
14
+ import 'node:crypto';
15
+ import 'events';
16
+ import 'fs';
17
+ import 'node:events';
18
+ import 'node:stream';
19
+ import 'node:string_decoder';
20
+ import 'path';
21
+ import 'assert';
22
+ import 'zlib';
23
+ import 'node:assert';
24
+ import 'node:fs/promises';
25
+
26
+ //#region src/lib/server/voice-errors.ts
27
+ /**
28
+ * Translate raw docker / compose stderr into operator-actionable copy.
29
+ *
30
+ * Lives in $lib/server so the route can import it without violating
31
+ * SvelteKit's +server.ts export rules (handlers + `_`-prefixed only).
32
+ *
33
+ * Pattern matches are intentionally case-insensitive and tolerant of
34
+ * compose-CLI prefix decoration. Order matters: more specific patterns
35
+ * first.
36
+ */
37
+ function translateDockerError(stderr) {
38
+ const raw = (stderr ?? "").trim();
39
+ if (!raw) return "Docker reported an unknown error (no stderr).";
40
+ if (/spawn .*docker.*ENOENT|no such file or directory.*docker|docker:\s*command not found/i.test(raw)) return "Docker isn't installed on this host. Install Docker Engine or Docker Desktop, then retry.";
41
+ if (/pull access denied|manifest unknown|repository does not exist|not found: manifest unknown/i.test(raw)) return "The voice image for this profile isn't published yet. Try the CPU profile.";
42
+ if (/failed to resolve reference|dial tcp.*lookup .+docker\.io|i\/o timeout.*registry|connection refused.*registry/i.test(raw)) return "Can't reach Docker Hub. Check your internet connection, corporate firewall, or configure a registry mirror.";
43
+ if (/no space left on device|insufficient.*disk space|ENOSPC|write.*disk full/i.test(raw)) return "Out of disk space. Free space and try again, or run `docker image prune -a` to reclaim unused images.";
44
+ if (/port is already allocated|bind.*address already in use|address already in use|failed to bind host port/i.test(raw)) return "Port 8880 is already in use on this host. Free it or change the host port (set OP_VOICE_PORT_HOST).";
45
+ if (/unknown[^\n]*runtime[^\n]*nvidia|runtime\s+"nvidia"\s+not\s+found|nvidia.*runtime.*not[^a-z]+(found|registered)/i.test(raw)) return "The NVIDIA Docker runtime isn't registered on this machine. Try the CPU profile, or install nvidia-container-toolkit.";
46
+ if (/invoking the NVIDIA Container Runtime Hook/i.test(raw)) return "Docker is in CDI mode but no CDI spec is registered. Try the CPU profile.";
47
+ return raw.length > 300 ? raw.slice(0, 297) + "…" : raw;
48
+ }
49
+ //#endregion
50
+ //#region src/routes/admin/voice/+server.ts
51
+ /**
52
+ * GET /admin/voice — Return current TTS/STT env vars from stack.env plus
53
+ * an `availability` block (best-effort reachability of
54
+ * the configured remote endpoints).
55
+ * PUT /admin/voice — Write TTS/STT env vars to stack.env. Auto-enables
56
+ * the openpalm-voice addon, brings the chosen profile
57
+ * up, waits for /health, and translates Docker errors
58
+ * to operator-actionable copy.
59
+ */
60
+ var VOICE_ADDON = "voice";
61
+ var VOICE_PROBE_TIMEOUT_MS = 18e4;
62
+ var VOICE_PROBE_INTERVAL_MS = 1e3;
63
+ var JOB_RETAIN_MS = 5 * 6e4;
64
+ var activeJobs = /* @__PURE__ */ new Map();
65
+ function setJob(addon, patch) {
66
+ const existing = activeJobs.get(addon);
67
+ const next = existing ? {
68
+ ...existing,
69
+ ...patch
70
+ } : {
71
+ state: "pulling",
72
+ steps: [],
73
+ startedAt: Date.now(),
74
+ ...patch
75
+ };
76
+ activeJobs.set(addon, next);
77
+ return next;
78
+ }
79
+ function getActiveJob(addon) {
80
+ const job = activeJobs.get(addon);
81
+ if (!job) return void 0;
82
+ if (Date.now() - (job.finishedAt ?? job.startedAt) > JOB_RETAIN_MS) {
83
+ activeJobs.delete(addon);
84
+ return;
85
+ }
86
+ return job;
87
+ }
88
+ var REACHABILITY_TIMEOUT_MS = 1500;
89
+ var PORT_PROBE_TIMEOUT_MS = 750;
90
+ async function probeReachable(baseURL) {
91
+ if (!baseURL) return false;
92
+ const url = baseURL.replace(/\/+$/, "") + "/v1/models";
93
+ try {
94
+ return (await fetch(url, {
95
+ method: "GET",
96
+ signal: AbortSignal.timeout(REACHABILITY_TIMEOUT_MS)
97
+ })).status < 500;
98
+ } catch {
99
+ return false;
100
+ }
101
+ }
102
+ /**
103
+ * Pick the best profile for this host. Prefers the first available GPU
104
+ * profile (anything that isn't the canonical CPU profile) so operators with NVIDIA/AMD hardware
105
+ * get the accelerated variant auto-selected. Falls back to the labelled
106
+ * default, then first available, then first profile.
107
+ */
108
+ function resolveDefaultProfile(profiles) {
109
+ if (profiles.length === 0) return null;
110
+ const availableGpu = profiles.find((p) => p.id !== addonProfileId(VOICE_ADDON, "cpu") && p.available !== false);
111
+ if (availableGpu) return availableGpu.id;
112
+ const labelledDefault = profiles.find((p) => p.default);
113
+ if (labelledDefault && labelledDefault.available !== false) return labelledDefault.id;
114
+ const firstAvailable = profiles.find((p) => p.available !== false);
115
+ if (firstAvailable) return firstAvailable.id;
116
+ return profiles[0].id;
117
+ }
118
+ var GET = async (event) => {
119
+ const requestId = getRequestId(event);
120
+ const authError = requireAdmin(event, requestId);
121
+ if (authError) return authError;
122
+ const state = getState();
123
+ const env = readStackEnv(state.stackDir);
124
+ const ttsBaseURL = env["OP_TTS_BASE_URL"] ?? "";
125
+ const sttBaseURL = env["OP_STT_BASE_URL"] ?? "";
126
+ const profiles = await annotateAddonProfileAvailability(getAddonProfiles(state.homeDir, VOICE_ADDON));
127
+ const selectedProfile = getAddonProfileSelection(state.stackDir, VOICE_ADDON) ?? resolveDefaultProfile(profiles);
128
+ const [sttReachable, ttsReachable] = await Promise.all([probeReachable(sttBaseURL), probeReachable(ttsBaseURL)]);
129
+ return jsonResponse(200, {
130
+ tts: {
131
+ enabled: true,
132
+ engine: env["OP_TTS_ENGINE"] ?? "",
133
+ provider: env["OP_TTS_PROVIDER"] ?? "",
134
+ baseURL: ttsBaseURL,
135
+ model: env["OP_TTS_MODEL"] ?? "",
136
+ voice: env["OP_TTS_VOICE"] ?? ""
137
+ },
138
+ stt: {
139
+ enabled: true,
140
+ engine: env["OP_STT_ENGINE"] ?? "",
141
+ provider: env["OP_STT_PROVIDER"] ?? "",
142
+ baseURL: sttBaseURL,
143
+ model: env["OP_STT_MODEL"] ?? "",
144
+ language: env["OP_STT_LANGUAGE"] ?? ""
145
+ },
146
+ availability: {
147
+ stt: {
148
+ remoteConfigured: Boolean(sttBaseURL),
149
+ remoteReachable: sttReachable
150
+ },
151
+ tts: {
152
+ remoteConfigured: Boolean(ttsBaseURL),
153
+ remoteReachable: ttsReachable
154
+ }
155
+ },
156
+ addon: {
157
+ profiles,
158
+ selectedProfile,
159
+ ...getActiveJob(VOICE_ADDON) ? { activeJob: getActiveJob(VOICE_ADDON) } : {}
160
+ }
161
+ }, requestId);
162
+ };
163
+ function readSection(raw, kind) {
164
+ if (!raw || typeof raw !== "object") return null;
165
+ const section = {
166
+ enabled: raw.enabled !== false,
167
+ engine: typeof raw.engine === "string" ? raw.engine : void 0,
168
+ provider: typeof raw.provider === "string" ? raw.provider : void 0,
169
+ baseURL: typeof raw.baseURL === "string" ? raw.baseURL : void 0,
170
+ model: typeof raw.model === "string" ? raw.model : void 0
171
+ };
172
+ if (kind === "tts" && typeof raw.voice === "string") section.voice = raw.voice;
173
+ if (kind === "stt" && typeof raw.language === "string") section.language = raw.language;
174
+ return section;
175
+ }
176
+ function voiceHostPort() {
177
+ const raw = process.env.OP_VOICE_PORT_HOST?.trim();
178
+ const n = raw ? Number(raw) : NaN;
179
+ return Number.isFinite(n) && n > 0 ? n : 8880;
180
+ }
181
+ function openpalmVoiceBaseURL() {
182
+ return `http://127.0.0.1:${voiceHostPort()}`;
183
+ }
184
+ var OPENPALM_VOICE_TTS_MODEL = "kokoro";
185
+ var OPENPALM_VOICE_STT_MODEL = "whisper-1";
186
+ var OPENPALM_VOICE_DEFAULT_VOICE = "bf_isabella";
187
+ /**
188
+ * For `engine === 'openpalm-voice'`, fill in baseURL/model with the addon's
189
+ * preset values when the user didn't provide them. This is the auto-config
190
+ * that makes "select OpenPalm Voice → Save" Just Work as long as the addon
191
+ * is enabled. The user can still override (e.g. point at a different
192
+ * voice host on the LAN).
193
+ */
194
+ function applyOpenPalmVoicePreset(section, kind) {
195
+ if (section.engine !== "openpalm-voice") return;
196
+ if (!section.baseURL || !section.baseURL.trim()) section.baseURL = openpalmVoiceBaseURL();
197
+ if (!section.model || !section.model.trim()) section.model = kind === "tts" ? OPENPALM_VOICE_TTS_MODEL : OPENPALM_VOICE_STT_MODEL;
198
+ if (kind === "tts" && (!section.voice || !section.voice.trim())) section.voice = OPENPALM_VOICE_DEFAULT_VOICE;
199
+ }
200
+ function validateSection(section, kind) {
201
+ if (!section || !section.engine) return null;
202
+ if (section.engine === "browser" || section.engine === "browser-stt" || section.engine === "browser-tts") return null;
203
+ if (section.engine.startsWith("skip-")) return null;
204
+ if (!section.baseURL || !section.baseURL.trim()) return `Remote ${kind.toUpperCase()} requires an endpoint URL.`;
205
+ return null;
206
+ }
207
+ function execFileNoThrow(cmd, args, timeoutMs) {
208
+ return new Promise((resolve) => {
209
+ execFile(cmd, args, { timeout: timeoutMs }, (error, stdout, stderr) => {
210
+ let mergedStderr = stderr?.toString() ?? "";
211
+ const code = error?.code;
212
+ if (code && !mergedStderr) if (code === "ENOENT") mergedStderr = `spawn ${cmd} ENOENT: command not found`;
213
+ else mergedStderr = `spawn ${cmd} ${code}`;
214
+ resolve({
215
+ ok: !error,
216
+ stdout: stdout?.toString() ?? "",
217
+ stderr: mergedStderr
218
+ });
219
+ });
220
+ });
221
+ }
222
+ /**
223
+ * True when the local docker daemon already has the named image cached.
224
+ * `docker image inspect` exits 0 only when the image is present locally.
225
+ */
226
+ async function dockerImagePresent(imageRef) {
227
+ if (!imageRef) return true;
228
+ return (await execFileNoThrow("docker", [
229
+ "image",
230
+ "inspect",
231
+ imageRef
232
+ ], 5e3)).ok;
233
+ }
234
+ /**
235
+ * Heuristic: image tags that include `-cu121` / `-rocm6` / `-cpu` are the
236
+ * multi-GB voice images. Show the "this may take a few minutes" toast for
237
+ * first pulls so the operator knows the upcoming compose-up isn't stuck.
238
+ */
239
+ function isLargeImageTag(imageRef) {
240
+ return /(-cu\d+|-rocm\d+|-cpu)(\s|$|@|\b)/i.test(imageRef);
241
+ }
242
+ /**
243
+ * Read the resolved image for a service from the merged compose config.
244
+ * Best-effort — returns "" on any failure so callers can skip the pre-pull
245
+ * check rather than blocking save.
246
+ */
247
+ async function resolveServiceImage(composeFiles, service) {
248
+ const args = ["compose"];
249
+ for (const f of composeFiles) args.push("-f", f);
250
+ args.push("--project-name", resolveProjectName(), "config", "--format", "json");
251
+ const res = await execFileNoThrow("docker", args, 15e3);
252
+ if (!res.ok) return "";
253
+ try {
254
+ return JSON.parse(res.stdout).services?.[service]?.image ?? "";
255
+ } catch {
256
+ return "";
257
+ }
258
+ }
259
+ function resolveProjectName() {
260
+ return process.env.OP_PROJECT_NAME?.trim() || process.env.COMPOSE_PROJECT_NAME?.trim() || "openpalm";
261
+ }
262
+ /**
263
+ * Probe a TCP port on 127.0.0.1. Resolves true when the connect succeeds
264
+ * within PORT_PROBE_TIMEOUT_MS — meaning something is already listening.
265
+ */
266
+ function isPortListening(port) {
267
+ return new Promise((resolve) => {
268
+ const socket = connect({
269
+ host: "127.0.0.1",
270
+ port
271
+ });
272
+ let done = false;
273
+ const finish = (listening) => {
274
+ if (done) return;
275
+ done = true;
276
+ try {
277
+ socket.destroy();
278
+ } catch {}
279
+ resolve(listening);
280
+ };
281
+ socket.setTimeout(PORT_PROBE_TIMEOUT_MS, () => finish(false));
282
+ socket.once("connect", () => finish(true));
283
+ socket.once("error", () => finish(false));
284
+ });
285
+ }
286
+ /**
287
+ * True when a docker container whose name matches openpalm-voice* is
288
+ * already running and presumably owns the host port. Used by the port
289
+ * pre-flight to avoid false positives when our own voice container is
290
+ * the listener.
291
+ */
292
+ async function ourVoiceContainerRunning() {
293
+ const res = await execFileNoThrow("docker", [
294
+ "ps",
295
+ "--filter",
296
+ "name=openpalm-voice",
297
+ "--format",
298
+ "{{.Names}}"
299
+ ], 5e3);
300
+ if (!res.ok) return false;
301
+ return res.stdout.trim().length > 0;
302
+ }
303
+ /**
304
+ * Read the Docker healthcheck state of a container.
305
+ * Returns "starting" while compose's start_period grace window is in
306
+ * effect; "healthy" / "unhealthy" / "none" / "" otherwise.
307
+ */
308
+ async function readContainerHealthStatus(containerNamePrefix) {
309
+ const name = (await execFileNoThrow("docker", [
310
+ "ps",
311
+ "--filter",
312
+ `name=${containerNamePrefix}`,
313
+ "--format",
314
+ "{{.Names}}"
315
+ ], 5e3)).stdout.split("\n").map((s) => s.trim()).find(Boolean);
316
+ if (!name) return "";
317
+ return (await execFileNoThrow("docker", [
318
+ "inspect",
319
+ name,
320
+ "--format",
321
+ "{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}"
322
+ ], 5e3)).stdout.trim();
323
+ }
324
+ /**
325
+ * Write a sibling compose overlay that switches `voice-cuda` from the
326
+ * legacy `runtime: nvidia` form to the CDI `driver: cdi` form. Caller
327
+ * includes it in the composeUp file list ONLY when the host probe
328
+ * indicates the runtime is missing but a CDI spec exists.
329
+ *
330
+ * The canonical compose.yml stays as the runtime-nvidia form (the case
331
+ * that needs no manual setup beyond installing nvidia-container-toolkit).
332
+ *
333
+ * Returns the absolute path of the overlay, or null when there is no
334
+ * enabled voice addon directory to write into.
335
+ */
336
+ function writeCdiOverlayIfNeeded(homeDir) {
337
+ const addonDir = join(homeDir, "config", "stack", "addons", VOICE_ADDON);
338
+ if (!existsSync(addonDir)) return null;
339
+ const overlayPath = join(addonDir, "compose.cdi.yml");
340
+ writeFileSync(overlayPath, [
341
+ "# Generated overlay — switches voice-cuda from runtime:nvidia to CDI.",
342
+ "# Applied only when the host probe shows the legacy NVIDIA runtime is",
343
+ "# missing but /etc/cdi/nvidia.yaml is present.",
344
+ "services:",
345
+ " voice-cuda:",
346
+ " runtime: \"\"",
347
+ " deploy:",
348
+ " resources:",
349
+ " reservations:",
350
+ " devices:",
351
+ " - driver: cdi",
352
+ " device_ids:",
353
+ " - nvidia.com/gpu=all",
354
+ ""
355
+ ].join("\n"));
356
+ return overlayPath;
357
+ }
358
+ /**
359
+ * Detect rootless Docker. The compose `user: "${OP_UID:-1000}:${OP_GID:-1000}"`
360
+ * directive bakes the host UID into the container — but on a rootless
361
+ * daemon the bind-mount UID inside the container is subuid-remapped, so
362
+ * the resulting container UID has no write permission against
363
+ * `${OP_HOME}/data/voice/models`. Removing the `user:` directive lets
364
+ * Docker pick whatever UID the rootless mapping translates to inside the
365
+ * user namespace, which DOES have write access to the bind-mount.
366
+ *
367
+ * `docker info` is the authoritative source: rootless daemons advertise
368
+ * `SecurityOptions: ... name=rootless` and `CgroupDriver: ... rootless`.
369
+ * We accept either signal.
370
+ */
371
+ async function detectRootlessDocker() {
372
+ const res = await execFileNoThrow("docker", [
373
+ "info",
374
+ "--format",
375
+ "{{json .}}"
376
+ ], 5e3);
377
+ if (!res.ok || !res.stdout) return false;
378
+ try {
379
+ const parsed = JSON.parse(res.stdout);
380
+ if ((Array.isArray(parsed.SecurityOptions) ? parsed.SecurityOptions.map((s) => String(s)) : []).some((s) => /name=rootless/i.test(s))) return true;
381
+ if (typeof parsed.CgroupDriver === "string" && /rootless/i.test(parsed.CgroupDriver)) return true;
382
+ return false;
383
+ } catch {
384
+ return /name=rootless|cgroup\s*driver:.*rootless/i.test(res.stdout);
385
+ }
386
+ }
387
+ /**
388
+ * Write a sibling overlay that drops the `user:` directive from each
389
+ * voice service. Mirrors writeCdiOverlayIfNeeded: caller includes the
390
+ * returned path in composeUp's file list. Returns null when there is
391
+ * no enabled voice addon directory to write into (so the file list
392
+ * stays valid and Docker doesn't blow up on a missing -f arg).
393
+ */
394
+ function writeRootlessOverlayIfNeeded(homeDir) {
395
+ const addonDir = join(homeDir, "config", "stack", "addons", VOICE_ADDON);
396
+ if (!existsSync(addonDir)) return null;
397
+ const overlayPath = join(addonDir, "compose.rootless.yml");
398
+ writeFileSync(overlayPath, [
399
+ "# Generated overlay — removes the `user:` directive from voice services.",
400
+ "# Applied only when `docker info` reports a rootless daemon. On rootless",
401
+ "# Docker the compose-baked UID has no write access to the bind-mounted",
402
+ "# state directory; letting Docker pick the namespaced UID restores it.",
403
+ "services:",
404
+ " voice:",
405
+ " user: null",
406
+ " voice-cuda:",
407
+ " user: null",
408
+ " voice-rocm:",
409
+ " user: null",
410
+ ""
411
+ ].join("\n"));
412
+ return overlayPath;
413
+ }
414
+ var PUT = (event) => {
415
+ return withSerialQueue("admin:voice:put", () => handlePut(event));
416
+ };
417
+ async function handlePut(event) {
418
+ const requestId = getRequestId(event);
419
+ const authError = requireAdmin(event, requestId);
420
+ if (authError) return authError;
421
+ const state = getState();
422
+ let body;
423
+ try {
424
+ body = await event.request.json();
425
+ } catch {
426
+ return errorResponse(400, "Bad Request", "Invalid JSON body", {}, requestId);
427
+ }
428
+ if (!body || typeof body !== "object") return errorResponse(400, "Bad Request", "Body must be an object", {}, requestId);
429
+ const b = body;
430
+ const ttsSection = readSection(b.tts, "tts");
431
+ const sttSection = readSection(b.stt, "stt");
432
+ if (ttsSection) applyOpenPalmVoicePreset(ttsSection, "tts");
433
+ if (sttSection) applyOpenPalmVoicePreset(sttSection, "stt");
434
+ const ttsErr = validateSection(ttsSection, "tts");
435
+ if (ttsErr) return errorResponse(400, "invalid_tts", ttsErr, {}, requestId);
436
+ const sttErr = validateSection(sttSection, "stt");
437
+ if (sttErr) return errorResponse(400, "invalid_stt", sttErr, {}, requestId);
438
+ const config = {};
439
+ if (ttsSection) config.tts = {
440
+ enabled: ttsSection.enabled,
441
+ engine: ttsSection.engine,
442
+ provider: ttsSection.provider,
443
+ baseURL: ttsSection.baseURL,
444
+ model: ttsSection.model,
445
+ voice: ttsSection.voice
446
+ };
447
+ if (sttSection) config.stt = {
448
+ enabled: sttSection.enabled,
449
+ engine: sttSection.engine,
450
+ provider: sttSection.provider,
451
+ baseURL: sttSection.baseURL,
452
+ model: sttSection.model,
453
+ language: sttSection.language
454
+ };
455
+ writeVoiceVars(config, state.stackDir);
456
+ if (!(ttsSection?.engine === "openpalm-voice" || sttSection?.engine === "openpalm-voice")) {
457
+ if (listEnabledAddonIds(state.homeDir).includes(VOICE_ADDON)) try {
458
+ const voiceServiceNames = getAddonProfiles(state.homeDir, VOICE_ADDON).flatMap((p) => p.services);
459
+ const unique = Array.from(new Set(voiceServiceNames));
460
+ if (unique.length > 0) await composeStop(unique, buildComposeOptions(state));
461
+ } catch (e) {
462
+ console.warn("[voice] composeStop on disengage failed:", e);
463
+ }
464
+ return jsonResponse(200, { ok: true }, requestId);
465
+ }
466
+ const availableProfiles = await annotateAddonProfileAvailability(getAddonProfiles(state.homeDir, VOICE_ADDON));
467
+ const requestedProfile = typeof b.profile === "string" ? b.profile.trim() : "";
468
+ let activeProfile = null;
469
+ if (requestedProfile) {
470
+ if (!availableProfiles.some((p) => p.id === requestedProfile)) return errorResponse(400, "invalid_profile", `Unknown voice profile "${requestedProfile}". Available: ${availableProfiles.map((p) => p.id).join(", ") || "(none)"}`, {}, requestId);
471
+ activeProfile = requestedProfile;
472
+ setAddonProfileSelection(state.stackDir, VOICE_ADDON, activeProfile);
473
+ } else activeProfile = getAddonProfileSelection(state.stackDir, VOICE_ADDON) ?? resolveDefaultProfile(availableProfiles);
474
+ const wasAlreadyEnabled = listEnabledAddonIds(state.homeDir).includes(VOICE_ADDON);
475
+ const steps = [];
476
+ if (!wasAlreadyEnabled) try {
477
+ setAddonEnabled(state.homeDir, state.stackDir, VOICE_ADDON, true, state);
478
+ steps.push({
479
+ step: "enable",
480
+ ok: true
481
+ });
482
+ } catch (e) {
483
+ const detail = e instanceof Error ? e.message : String(e);
484
+ steps.push({
485
+ step: "enable",
486
+ ok: false,
487
+ detail
488
+ });
489
+ return jsonResponse(502, {
490
+ ok: false,
491
+ voiceAddon: {
492
+ wasAlreadyEnabled,
493
+ steps,
494
+ error: `Could not enable voice addon: ${detail}`
495
+ }
496
+ }, requestId);
497
+ }
498
+ else steps.push({
499
+ step: "enable",
500
+ ok: true,
501
+ detail: "already enabled"
502
+ });
503
+ const hostPort = voiceHostPort();
504
+ const inVitest = !!process.env.VITEST;
505
+ if (inVitest ? false : await isPortListening(hostPort)) {
506
+ if (!await ourVoiceContainerRunning()) {
507
+ const msg = translateDockerError(`Bind for 127.0.0.1:${hostPort} failed: port is already allocated`);
508
+ steps.push({
509
+ step: "port-check",
510
+ ok: false,
511
+ detail: msg
512
+ });
513
+ return jsonResponse(502, {
514
+ ok: false,
515
+ voiceAddon: {
516
+ wasAlreadyEnabled,
517
+ steps,
518
+ error: msg
519
+ }
520
+ }, requestId);
521
+ }
522
+ steps.push({
523
+ step: "port-check",
524
+ ok: true,
525
+ detail: "our container is the listener"
526
+ });
527
+ } else steps.push({
528
+ step: "port-check",
529
+ ok: true
530
+ });
531
+ const profileServices = activeProfile ? availableProfiles.find((p) => p.id === activeProfile)?.services ?? [] : [];
532
+ const services = profileServices.length > 0 ? profileServices : [VOICE_ADDON];
533
+ const composeFilesBase = buildComposeOptions(state).files;
534
+ const primaryService = services[0];
535
+ let backgroundPull = false;
536
+ if (primaryService && !inVitest) {
537
+ const imageRef = await resolveServiceImage(composeFilesBase, primaryService);
538
+ if (imageRef && isLargeImageTag(imageRef)) {
539
+ if (!await dockerImagePresent(imageRef)) {
540
+ backgroundPull = true;
541
+ steps.push({
542
+ step: "pulling",
543
+ ok: true,
544
+ detail: "first-time download — several minutes for several GB"
545
+ });
546
+ }
547
+ }
548
+ }
549
+ const extraFiles = [];
550
+ const cdiFallbackSupported = process.platform !== "win32";
551
+ if (activeProfile === addonProfileId(VOICE_ADDON, "cuda") && !inVitest && cdiFallbackSupported) {
552
+ const runtimeMissing = (await getAddonProfileAvailability({ id: addonProfileId(VOICE_ADDON, "cuda") })).available === false || !await dockerHasNvidiaRuntime();
553
+ const cdiSpecPresent = existsSync("/etc/cdi/nvidia.yaml");
554
+ if (runtimeMissing && cdiSpecPresent) {
555
+ const overlay = writeCdiOverlayIfNeeded(state.homeDir);
556
+ if (overlay) {
557
+ extraFiles.push(overlay);
558
+ steps.push({
559
+ step: "cdi-fallback",
560
+ ok: true,
561
+ detail: "using CDI device reservation"
562
+ });
563
+ }
564
+ }
565
+ }
566
+ if (!inVitest) try {
567
+ if (await detectRootlessDocker()) {
568
+ const overlay = writeRootlessOverlayIfNeeded(state.homeDir);
569
+ if (overlay) {
570
+ extraFiles.push(overlay);
571
+ steps.push({
572
+ step: "rootless-fallback",
573
+ ok: true,
574
+ detail: "dropping user: directive for rootless Docker"
575
+ });
576
+ }
577
+ }
578
+ } catch (e) {
579
+ console.warn("[voice] rootless detection failed:", e);
580
+ }
581
+ if (backgroundPull) {
582
+ setJob(VOICE_ADDON, {
583
+ state: "pulling",
584
+ steps: [...steps],
585
+ startedAt: Date.now(),
586
+ profile: activeProfile ?? void 0,
587
+ finishedAt: void 0,
588
+ error: void 0
589
+ });
590
+ runBringUpJob({
591
+ state,
592
+ services,
593
+ activeProfile,
594
+ extraFiles,
595
+ availableProfiles,
596
+ baseSteps: [...steps]
597
+ });
598
+ return jsonResponse(202, {
599
+ ok: true,
600
+ voiceAddon: {
601
+ wasAlreadyEnabled,
602
+ status: "pulling",
603
+ steps,
604
+ message: "Voice image is downloading in the background (~2–8 GB). Poll GET /admin/voice for progress; UI auto-refreshes."
605
+ }
606
+ }, requestId);
607
+ }
608
+ const outcome = await runBringUp({
609
+ state,
610
+ services,
611
+ activeProfile,
612
+ extraFiles,
613
+ availableProfiles,
614
+ steps
615
+ });
616
+ if (!outcome.composeOk) return jsonResponse(502, {
617
+ ok: false,
618
+ voiceAddon: {
619
+ wasAlreadyEnabled,
620
+ steps: outcome.steps,
621
+ error: `Voice addon failed to start: ${outcome.composeErr ?? "unknown error"}`
622
+ }
623
+ }, requestId);
624
+ return jsonResponse(outcome.healthy || outcome.warming ? 200 : 502, {
625
+ ok: outcome.healthy || outcome.warming,
626
+ voiceAddon: {
627
+ wasAlreadyEnabled,
628
+ steps: outcome.steps,
629
+ ...outcome.warming ? { warming: true } : {},
630
+ ...outcome.healthy || outcome.warming ? {} : { error: "Voice addon is starting but did not become healthy in time." }
631
+ }
632
+ }, requestId);
633
+ }
634
+ /**
635
+ * Inline composeStop-other-profiles + composeUp + /health poll. Returns
636
+ * the terminal state. Pushed `steps` get mutated in place so the caller
637
+ * (sync or background) can read progress as it happens.
638
+ */
639
+ async function runBringUp(input) {
640
+ const { state, services, activeProfile, extraFiles, availableProfiles, steps } = input;
641
+ let composeOk = true;
642
+ let composeErr;
643
+ try {
644
+ const otherProfileServices = availableProfiles.filter((p) => p.id !== activeProfile).flatMap((p) => p.services).filter((svc) => !services.includes(svc));
645
+ if (otherProfileServices.length > 0) try {
646
+ await composeStop(otherProfileServices, buildComposeOptions(state));
647
+ } catch (e) {
648
+ console.warn("[voice] composeStop other profiles failed:", e);
649
+ }
650
+ const baseOpts = buildComposeOptions(state);
651
+ const result = await composeUp({
652
+ ...baseOpts,
653
+ files: [...baseOpts.files, ...extraFiles],
654
+ services,
655
+ forceRecreate: true,
656
+ ...activeProfile ? { profiles: [activeProfile] } : {}
657
+ });
658
+ composeOk = result.ok;
659
+ if (!result.ok) composeErr = translateDockerError(parseComposeStderr(result.stderr).find((f) => services.includes(f.service))?.reason ?? result.stderr ?? `compose up exited ${result.code}`);
660
+ } catch (e) {
661
+ composeOk = false;
662
+ composeErr = translateDockerError(e instanceof Error ? e.message : String(e));
663
+ }
664
+ steps.push({
665
+ step: "compose-up",
666
+ ok: composeOk,
667
+ ...composeErr ? { detail: composeErr.slice(0, 500) } : {}
668
+ });
669
+ if (!composeOk) return {
670
+ composeOk,
671
+ composeErr,
672
+ healthy: false,
673
+ warming: false,
674
+ steps
675
+ };
676
+ const probeUrl = `${openpalmVoiceBaseURL()}/health`;
677
+ const deadline = Date.now() + VOICE_PROBE_TIMEOUT_MS;
678
+ let healthy = false;
679
+ while (Date.now() < deadline) {
680
+ try {
681
+ if ((await fetch(probeUrl, { signal: AbortSignal.timeout(1500) })).ok) {
682
+ healthy = true;
683
+ break;
684
+ }
685
+ } catch {}
686
+ await new Promise((r) => setTimeout(r, VOICE_PROBE_INTERVAL_MS));
687
+ }
688
+ let warming = false;
689
+ if (!healthy) try {
690
+ if (await readContainerHealthStatus("openpalm-voice") === "starting") warming = true;
691
+ } catch {}
692
+ steps.push({
693
+ step: "healthy",
694
+ ok: healthy || warming,
695
+ ...healthy ? {} : warming ? { detail: "still warming up — refresh in a moment" } : { detail: `did not respond at ${probeUrl} within ${VOICE_PROBE_TIMEOUT_MS / 1e3}s` }
696
+ });
697
+ return {
698
+ composeOk,
699
+ healthy,
700
+ warming,
701
+ steps
702
+ };
703
+ }
704
+ /**
705
+ * Background variant: runs runBringUp and persists state transitions
706
+ * into the activeJobs map. Returns nothing — the UI polls GET
707
+ * /admin/voice to observe completion.
708
+ */
709
+ async function runBringUpJob(input) {
710
+ const steps = [...input.baseSteps];
711
+ try {
712
+ setJob(VOICE_ADDON, {
713
+ state: "starting",
714
+ steps
715
+ });
716
+ const outcome = await runBringUp({
717
+ ...input,
718
+ steps
719
+ });
720
+ if (!outcome.composeOk) {
721
+ setJob(VOICE_ADDON, {
722
+ state: "error",
723
+ steps: outcome.steps,
724
+ error: `Voice addon failed to start: ${outcome.composeErr ?? "unknown error"}`,
725
+ finishedAt: Date.now()
726
+ });
727
+ return;
728
+ }
729
+ setJob(VOICE_ADDON, {
730
+ state: outcome.healthy ? "healthy" : outcome.warming ? "starting" : "error",
731
+ steps: outcome.steps,
732
+ ...outcome.healthy || outcome.warming ? { error: void 0 } : { error: "Voice addon is starting but did not become healthy in time." },
733
+ finishedAt: Date.now()
734
+ });
735
+ } catch (e) {
736
+ setJob(VOICE_ADDON, {
737
+ state: "error",
738
+ steps,
739
+ error: e instanceof Error ? e.message : String(e),
740
+ finishedAt: Date.now()
741
+ });
742
+ }
743
+ }
744
+ /**
745
+ * Lightweight wrapper around `docker info` to check whether the
746
+ * `nvidia` runtime is registered. Used as a second signal alongside the
747
+ * cached canonical CUDA profile availability result.
748
+ */
749
+ async function dockerHasNvidiaRuntime() {
750
+ const res = await execFileNoThrow("docker", [
751
+ "info",
752
+ "--format",
753
+ "{{json .Runtimes}}"
754
+ ], 2e3);
755
+ return res.ok && res.stdout.includes("\"nvidia\"");
756
+ }
757
+
758
+ export { GET, PUT };
759
+ //# sourceMappingURL=_server.ts-CGwYZUuw.js.map