@openpalm/ui 0.13.0-beta.6 → 0.13.0-beta.8

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 (589) hide show
  1. package/README.md +3 -2
  2. package/build/.openpalm-ui-version +1 -1
  3. package/build/client/_app/immutable/assets/4.Cd3Y_8BZ.css +1 -0
  4. package/build/client/_app/immutable/assets/4.Cd3Y_8BZ.css.br +3 -0
  5. package/build/client/_app/immutable/assets/4.Cd3Y_8BZ.css.gz +0 -0
  6. package/build/client/_app/immutable/assets/6.BM7A1dW5.css +1 -0
  7. package/build/client/_app/immutable/assets/6.BM7A1dW5.css.br +0 -0
  8. package/build/client/_app/immutable/assets/6.BM7A1dW5.css.gz +0 -0
  9. package/build/client/_app/immutable/assets/7.DHMKw-HL.css +1 -0
  10. package/build/client/_app/immutable/assets/7.DHMKw-HL.css.br +0 -0
  11. package/build/client/_app/immutable/assets/7.DHMKw-HL.css.gz +0 -0
  12. package/build/client/_app/immutable/assets/9.CmCaAuiy.css +1 -0
  13. package/build/client/_app/immutable/assets/9.CmCaAuiy.css.br +0 -0
  14. package/build/client/_app/immutable/assets/9.CmCaAuiy.css.gz +0 -0
  15. package/build/client/_app/immutable/assets/QuestionCard.CSfD3z_X.css +1 -0
  16. package/build/client/_app/immutable/assets/QuestionCard.CSfD3z_X.css.br +0 -0
  17. package/build/client/_app/immutable/assets/QuestionCard.CSfD3z_X.css.gz +0 -0
  18. package/build/client/_app/immutable/chunks/1F1QVf3N.js +1 -0
  19. package/build/client/_app/immutable/chunks/1F1QVf3N.js.br +0 -0
  20. package/build/client/_app/immutable/chunks/1F1QVf3N.js.gz +0 -0
  21. package/build/client/_app/immutable/chunks/{DmFbAjwW.js → 92accNiq.js} +1 -1
  22. package/build/client/_app/immutable/chunks/92accNiq.js.br +0 -0
  23. package/build/client/_app/immutable/chunks/92accNiq.js.gz +0 -0
  24. package/build/client/_app/immutable/chunks/B9uMOgDZ.js +3 -0
  25. package/build/client/_app/immutable/chunks/B9uMOgDZ.js.br +0 -0
  26. package/build/client/_app/immutable/chunks/B9uMOgDZ.js.gz +0 -0
  27. package/build/client/_app/immutable/chunks/{SXdvPq3_.js → BBXQKGHA.js} +1 -1
  28. package/build/client/_app/immutable/chunks/BBXQKGHA.js.br +1 -0
  29. package/build/client/_app/immutable/chunks/BBXQKGHA.js.gz +0 -0
  30. package/build/client/_app/immutable/chunks/{CUa5ff3d.js → BGx9HO1u.js} +1 -1
  31. package/build/client/_app/immutable/chunks/BGx9HO1u.js.br +0 -0
  32. package/build/client/_app/immutable/chunks/BGx9HO1u.js.gz +0 -0
  33. package/build/client/_app/immutable/chunks/BwKrb5qD.js +1 -0
  34. package/build/client/_app/immutable/chunks/BwKrb5qD.js.br +2 -0
  35. package/build/client/_app/immutable/chunks/BwKrb5qD.js.gz +0 -0
  36. package/build/client/_app/immutable/chunks/{BDK50g8a.js → ByiipSaR.js} +1 -1
  37. package/build/client/_app/immutable/chunks/ByiipSaR.js.br +3 -0
  38. package/build/client/_app/immutable/chunks/ByiipSaR.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/C092q_Hl.js +1 -0
  40. package/build/client/_app/immutable/chunks/C092q_Hl.js.br +0 -0
  41. package/build/client/_app/immutable/chunks/C092q_Hl.js.gz +0 -0
  42. package/build/client/_app/immutable/chunks/{D5FtEngX.js → C4qTU5YY.js} +1 -1
  43. package/build/client/_app/immutable/chunks/C4qTU5YY.js.br +0 -0
  44. package/build/client/_app/immutable/chunks/C4qTU5YY.js.gz +0 -0
  45. package/build/client/_app/immutable/chunks/C6rMFkms.js +14 -0
  46. package/build/client/_app/immutable/chunks/C6rMFkms.js.br +0 -0
  47. package/build/client/_app/immutable/chunks/C6rMFkms.js.gz +0 -0
  48. package/build/client/_app/immutable/chunks/C7g46Pjm.js +1 -0
  49. package/build/client/_app/immutable/chunks/C7g46Pjm.js.br +0 -0
  50. package/build/client/_app/immutable/chunks/C7g46Pjm.js.gz +0 -0
  51. package/build/client/_app/immutable/chunks/{mG6HnNbi.js → CJc9QEdG.js} +1 -1
  52. package/build/client/_app/immutable/chunks/CJc9QEdG.js.br +2 -0
  53. package/build/client/_app/immutable/chunks/CJc9QEdG.js.gz +0 -0
  54. package/build/client/_app/immutable/chunks/CR3nChHO.js +3 -0
  55. package/build/client/_app/immutable/chunks/CR3nChHO.js.br +0 -0
  56. package/build/client/_app/immutable/chunks/CR3nChHO.js.gz +0 -0
  57. package/build/client/_app/immutable/chunks/CXv_deBx.js +1 -0
  58. package/build/client/_app/immutable/chunks/CXv_deBx.js.br +0 -0
  59. package/build/client/_app/immutable/chunks/CXv_deBx.js.gz +0 -0
  60. package/build/client/_app/immutable/chunks/CzKYnjEX.js +1 -0
  61. package/build/client/_app/immutable/chunks/CzKYnjEX.js.br +0 -0
  62. package/build/client/_app/immutable/chunks/CzKYnjEX.js.gz +0 -0
  63. package/build/client/_app/immutable/chunks/D-DB6zTo.js +9 -0
  64. package/build/client/_app/immutable/chunks/D-DB6zTo.js.br +0 -0
  65. package/build/client/_app/immutable/chunks/D-DB6zTo.js.gz +0 -0
  66. package/build/client/_app/immutable/chunks/D3d8Mm8X.js +1 -0
  67. package/build/client/_app/immutable/chunks/D3d8Mm8X.js.br +1 -0
  68. package/build/client/_app/immutable/chunks/D3d8Mm8X.js.gz +0 -0
  69. package/build/client/_app/immutable/chunks/DDSqq1hR.js +1 -0
  70. package/build/client/_app/immutable/chunks/DDSqq1hR.js.br +0 -0
  71. package/build/client/_app/immutable/chunks/DDSqq1hR.js.gz +0 -0
  72. package/build/client/_app/immutable/chunks/{NR-JVJz-.js → DTAO9S6h.js} +1 -1
  73. package/build/client/_app/immutable/chunks/DTAO9S6h.js.br +0 -0
  74. package/build/client/_app/immutable/chunks/DTAO9S6h.js.gz +0 -0
  75. package/build/client/_app/immutable/chunks/DTLQuSQp.js +3 -0
  76. package/build/client/_app/immutable/chunks/DTLQuSQp.js.br +0 -0
  77. package/build/client/_app/immutable/chunks/DTLQuSQp.js.gz +0 -0
  78. package/build/client/_app/immutable/chunks/{hSjQday7.js → _zkFsY4j.js} +1 -1
  79. package/build/client/_app/immutable/chunks/_zkFsY4j.js.br +0 -0
  80. package/build/client/_app/immutable/chunks/_zkFsY4j.js.gz +0 -0
  81. package/build/client/_app/immutable/chunks/d1cxvUgj.js +1 -0
  82. package/build/client/_app/immutable/chunks/d1cxvUgj.js.br +0 -0
  83. package/build/client/_app/immutable/chunks/d1cxvUgj.js.gz +0 -0
  84. package/build/client/_app/immutable/chunks/qrqTdjh7.js +1 -0
  85. package/build/client/_app/immutable/chunks/qrqTdjh7.js.br +0 -0
  86. package/build/client/_app/immutable/chunks/qrqTdjh7.js.gz +0 -0
  87. package/build/client/_app/immutable/entry/app.CXHi3StM.js +2 -0
  88. package/build/client/_app/immutable/entry/app.CXHi3StM.js.br +0 -0
  89. package/build/client/_app/immutable/entry/app.CXHi3StM.js.gz +0 -0
  90. package/build/client/_app/immutable/entry/start.eS_-xLIC.js +1 -0
  91. package/build/client/_app/immutable/entry/start.eS_-xLIC.js.br +1 -0
  92. package/build/client/_app/immutable/entry/start.eS_-xLIC.js.gz +0 -0
  93. package/build/client/_app/immutable/nodes/0.Bfv0aXoG.js +1 -0
  94. package/build/client/_app/immutable/nodes/0.Bfv0aXoG.js.br +0 -0
  95. package/build/client/_app/immutable/nodes/0.Bfv0aXoG.js.gz +0 -0
  96. package/build/client/_app/immutable/nodes/1.B8Ebge5I.js +1 -0
  97. package/build/client/_app/immutable/nodes/1.B8Ebge5I.js.br +0 -0
  98. package/build/client/_app/immutable/nodes/1.B8Ebge5I.js.gz +0 -0
  99. package/build/client/_app/immutable/nodes/10.Di4b61Rb.js +1 -0
  100. package/build/client/_app/immutable/nodes/10.Di4b61Rb.js.br +0 -0
  101. package/build/client/_app/immutable/nodes/10.Di4b61Rb.js.gz +0 -0
  102. package/build/client/_app/immutable/nodes/11.CUlazdDv.js +8 -0
  103. package/build/client/_app/immutable/nodes/11.CUlazdDv.js.br +0 -0
  104. package/build/client/_app/immutable/nodes/11.CUlazdDv.js.gz +0 -0
  105. package/build/client/_app/immutable/nodes/2.tmtk1Bjc.js +1 -0
  106. package/build/client/_app/immutable/nodes/2.tmtk1Bjc.js.br +0 -0
  107. package/build/client/_app/immutable/nodes/2.tmtk1Bjc.js.gz +0 -0
  108. package/build/client/_app/immutable/nodes/3.BEaeucAu.js +1 -0
  109. package/build/client/_app/immutable/nodes/3.BEaeucAu.js.br +0 -0
  110. package/build/client/_app/immutable/nodes/3.BEaeucAu.js.gz +0 -0
  111. package/build/client/_app/immutable/nodes/4.DQOL0qY_.js +1 -0
  112. package/build/client/_app/immutable/nodes/4.DQOL0qY_.js.br +0 -0
  113. package/build/client/_app/immutable/nodes/4.DQOL0qY_.js.gz +0 -0
  114. package/build/client/_app/immutable/nodes/{5.CIMkqYzP.js → 5.BGqmDWpO.js} +2 -2
  115. package/build/client/_app/immutable/nodes/5.BGqmDWpO.js.br +0 -0
  116. package/build/client/_app/immutable/nodes/5.BGqmDWpO.js.gz +0 -0
  117. package/build/client/_app/immutable/nodes/6.Cf2kRGl-.js +2 -0
  118. package/build/client/_app/immutable/nodes/6.Cf2kRGl-.js.br +0 -0
  119. package/build/client/_app/immutable/nodes/6.Cf2kRGl-.js.gz +0 -0
  120. package/build/client/_app/immutable/nodes/7.CvaILUo5.js +16 -0
  121. package/build/client/_app/immutable/nodes/7.CvaILUo5.js.br +0 -0
  122. package/build/client/_app/immutable/nodes/7.CvaILUo5.js.gz +0 -0
  123. package/build/client/_app/immutable/nodes/8.BANf4x1v.js +1 -0
  124. package/build/client/_app/immutable/nodes/8.BANf4x1v.js.br +0 -0
  125. package/build/client/_app/immutable/nodes/8.BANf4x1v.js.gz +0 -0
  126. package/build/client/_app/immutable/nodes/9.DvOR66Q0.js +128 -0
  127. package/build/client/_app/immutable/nodes/9.DvOR66Q0.js.br +0 -0
  128. package/build/client/_app/immutable/nodes/9.DvOR66Q0.js.gz +0 -0
  129. package/build/client/_app/version.json +1 -1
  130. package/build/client/_app/version.json.br +1 -1
  131. package/build/client/_app/version.json.gz +0 -0
  132. package/build/server/chunks/{0-BtezztJz.js → 0-D8UAPThv.js} +13 -7
  133. package/build/server/chunks/0-D8UAPThv.js.map +1 -0
  134. package/build/server/chunks/1-bS23Eg-d.js +9 -0
  135. package/build/server/chunks/{1-CvGA_TOi.js.map → 1-bS23Eg-d.js.map} +1 -1
  136. package/build/server/chunks/{10-D_ipl62-.js → 10-C5TUqG1t.js} +3 -3
  137. package/build/server/chunks/{10-D_ipl62-.js.map → 10-C5TUqG1t.js.map} +1 -1
  138. package/build/server/chunks/11-DSjZgp33.js +9 -0
  139. package/build/server/chunks/11-DSjZgp33.js.map +1 -0
  140. package/build/server/chunks/{2-CQSBaE_w.js → 2-KPMSLSlE.js} +2 -2
  141. package/build/server/chunks/{2-CQSBaE_w.js.map → 2-KPMSLSlE.js.map} +1 -1
  142. package/build/server/chunks/{3-CZdWulB3.js → 3-D0iTJ9v2.js} +10 -11
  143. package/build/server/chunks/3-D0iTJ9v2.js.map +1 -0
  144. package/build/server/chunks/4-CHJRF8qs.js +9 -0
  145. package/build/server/chunks/4-CHJRF8qs.js.map +1 -0
  146. package/build/server/chunks/{5-CeJvfCdk.js → 5-CwCiwnFt.js} +3 -3
  147. package/build/server/chunks/{5-CeJvfCdk.js.map → 5-CwCiwnFt.js.map} +1 -1
  148. package/build/server/chunks/6-raswytzE.js +9 -0
  149. package/build/server/chunks/6-raswytzE.js.map +1 -0
  150. package/build/server/chunks/7-NC4-KlW9.js +9 -0
  151. package/build/server/chunks/7-NC4-KlW9.js.map +1 -0
  152. package/build/server/chunks/{8-DiHmrGkL.js → 8-DFD8sNRI.js} +5 -7
  153. package/build/server/chunks/8-DFD8sNRI.js.map +1 -0
  154. package/build/server/chunks/9-rIsHxfiY.js +9 -0
  155. package/build/server/chunks/9-rIsHxfiY.js.map +1 -0
  156. package/build/server/chunks/{IconActivity-DrgUhxxi.js → ChatMessage-fWnwEF6b.js} +3 -57
  157. package/build/server/chunks/ChatMessage-fWnwEF6b.js.map +1 -0
  158. package/build/server/chunks/{ChatNavbar-FJW5r496.js → ChatNavbar-DqdxDR5U.js} +9 -9
  159. package/build/server/chunks/{ChatNavbar-FJW5r496.js.map → ChatNavbar-DqdxDR5U.js.map} +1 -1
  160. package/build/server/chunks/IconActivity-BU1QGLAZ.js +58 -0
  161. package/build/server/chunks/IconActivity-BU1QGLAZ.js.map +1 -0
  162. package/build/server/chunks/IconMic-CZN60P6B.js +10 -0
  163. package/build/server/chunks/IconMic-CZN60P6B.js.map +1 -0
  164. package/build/server/chunks/{IconServer-w-1K5jNR.js → IconServer-BwcRjcsS.js} +5 -5
  165. package/build/server/chunks/{IconServer-w-1K5jNR.js.map → IconServer-BwcRjcsS.js.map} +1 -1
  166. package/build/server/chunks/{IconSoundOn-DZGaQz_p.js → IconSoundOn-DTZuBn2-.js} +9 -12
  167. package/build/server/chunks/IconSoundOn-DTZuBn2-.js.map +1 -0
  168. package/build/server/chunks/{IconStop-BPbovgch.js → IconStop-BxUfqTaV.js} +173 -214
  169. package/build/server/chunks/IconStop-BxUfqTaV.js.map +1 -0
  170. package/build/server/chunks/QuestionCard-DOLuSSbI.js +128 -0
  171. package/build/server/chunks/QuestionCard-DOLuSSbI.js.map +1 -0
  172. package/build/server/chunks/Spinner-2WZW6r_I.js +12 -0
  173. package/build/server/chunks/Spinner-2WZW6r_I.js.map +1 -0
  174. package/build/server/chunks/{_layout.svelte-B-_IlE2E.js → _layout.svelte-CBBWJ3m3.js} +3 -4
  175. package/build/server/chunks/{_layout.svelte-B-_IlE2E.js.map → _layout.svelte-CBBWJ3m3.js.map} +1 -1
  176. package/build/server/chunks/{_page.svelte-K6kU7jIW.js → _page.svelte-CYzntFY4.js} +45 -136
  177. package/build/server/chunks/_page.svelte-CYzntFY4.js.map +1 -0
  178. package/build/server/chunks/_page.svelte-CysG6Te2.js +192 -0
  179. package/build/server/chunks/_page.svelte-CysG6Te2.js.map +1 -0
  180. package/build/server/chunks/{_page.svelte-CPZBh4-z.js → _page.svelte-D-_cPU8e.js} +3 -3
  181. package/build/server/chunks/{_page.svelte-CPZBh4-z.js.map → _page.svelte-D-_cPU8e.js.map} +1 -1
  182. package/build/server/chunks/{_page.svelte-CPo3vFZf.js → _page.svelte-D4hOWjfm.js} +64 -353
  183. package/build/server/chunks/_page.svelte-D4hOWjfm.js.map +1 -0
  184. package/build/server/chunks/_page.svelte-D9au75wl.js +183 -0
  185. package/build/server/chunks/_page.svelte-D9au75wl.js.map +1 -0
  186. package/build/server/chunks/{_page.svelte-GcuuPiXq.js → _page.svelte-DjldYxQn.js} +28 -136
  187. package/build/server/chunks/_page.svelte-DjldYxQn.js.map +1 -0
  188. package/build/server/chunks/{_page.svelte-DM96lwQ1.js → _page.svelte-DsJgu4mW.js} +3 -3
  189. package/build/server/chunks/{_page.svelte-DM96lwQ1.js.map → _page.svelte-DsJgu4mW.js.map} +1 -1
  190. package/build/server/chunks/_server.ts-1qbl_1NY.js +87 -0
  191. package/build/server/chunks/_server.ts-1qbl_1NY.js.map +1 -0
  192. package/build/server/chunks/{_server.ts-BLXzfOzW.js → _server.ts-2VPdIZFH.js} +7 -7
  193. package/build/server/chunks/{_server.ts-BLXzfOzW.js.map → _server.ts-2VPdIZFH.js.map} +1 -1
  194. package/build/server/chunks/{_server.ts-513m4Yqs.js → _server.ts-68MuZYx_.js} +8 -8
  195. package/build/server/chunks/{_server.ts-513m4Yqs.js.map → _server.ts-68MuZYx_.js.map} +1 -1
  196. package/build/server/chunks/{_server.ts-BaVwMXGu.js → _server.ts-8AfutA1j.js} +7 -7
  197. package/build/server/chunks/{_server.ts-BaVwMXGu.js.map → _server.ts-8AfutA1j.js.map} +1 -1
  198. package/build/server/chunks/{_server.ts-Cp8YnPjm.js → _server.ts-B-5y1hA4.js} +9 -9
  199. package/build/server/chunks/{_server.ts-Cp8YnPjm.js.map → _server.ts-B-5y1hA4.js.map} +1 -1
  200. package/build/server/chunks/{_server.ts-CVvUFmDd.js → _server.ts-B1CunPF7.js} +7 -7
  201. package/build/server/chunks/{_server.ts-CVvUFmDd.js.map → _server.ts-B1CunPF7.js.map} +1 -1
  202. package/build/server/chunks/{_server.ts-Cgdl0C1I.js → _server.ts-B1KGSkdl.js} +7 -7
  203. package/build/server/chunks/{_server.ts-Cgdl0C1I.js.map → _server.ts-B1KGSkdl.js.map} +1 -1
  204. package/build/server/chunks/{_server.ts-WZl_x3WY.js → _server.ts-B2NALEcR.js} +7 -7
  205. package/build/server/chunks/{_server.ts-WZl_x3WY.js.map → _server.ts-B2NALEcR.js.map} +1 -1
  206. package/build/server/chunks/{_server.ts-DnonNBWq.js → _server.ts-B2iUBxXh.js} +9 -9
  207. package/build/server/chunks/{_server.ts-DnonNBWq.js.map → _server.ts-B2iUBxXh.js.map} +1 -1
  208. package/build/server/chunks/{_server.ts-rVmsBymo.js → _server.ts-BN8EkPAZ.js} +8 -8
  209. package/build/server/chunks/{_server.ts-rVmsBymo.js.map → _server.ts-BN8EkPAZ.js.map} +1 -1
  210. package/build/server/chunks/{_server.ts-Cf_ZLxIl.js → _server.ts-BQJfEfl9.js} +12 -13
  211. package/build/server/chunks/_server.ts-BQJfEfl9.js.map +1 -0
  212. package/build/server/chunks/{_server.ts-CPiybiLB.js → _server.ts-BQSMacks.js} +10 -10
  213. package/build/server/chunks/{_server.ts-CPiybiLB.js.map → _server.ts-BQSMacks.js.map} +1 -1
  214. package/build/server/chunks/{_server.ts-DwGTXfsS.js → _server.ts-BYt64wi5.js} +3 -3
  215. package/build/server/chunks/{_server.ts-DwGTXfsS.js.map → _server.ts-BYt64wi5.js.map} +1 -1
  216. package/build/server/chunks/{_server.ts-ykET4T6s.js → _server.ts-Ba0MJSs9.js} +9 -9
  217. package/build/server/chunks/_server.ts-Ba0MJSs9.js.map +1 -0
  218. package/build/server/chunks/{_server.ts-CMOAhXEC.js → _server.ts-BdIM_pWg.js} +9 -9
  219. package/build/server/chunks/{_server.ts-CMOAhXEC.js.map → _server.ts-BdIM_pWg.js.map} +1 -1
  220. package/build/server/chunks/{_server.ts-DbvC6vbj.js → _server.ts-BfxTJHa-.js} +7 -7
  221. package/build/server/chunks/{_server.ts-DbvC6vbj.js.map → _server.ts-BfxTJHa-.js.map} +1 -1
  222. package/build/server/chunks/{_server.ts-Dw7F066C.js → _server.ts-BiVyFRNv.js} +7 -7
  223. package/build/server/chunks/{_server.ts-Dw7F066C.js.map → _server.ts-BiVyFRNv.js.map} +1 -1
  224. package/build/server/chunks/{_server.ts-WLMG4R7D.js → _server.ts-BrgEQhDo.js} +7 -7
  225. package/build/server/chunks/{_server.ts-WLMG4R7D.js.map → _server.ts-BrgEQhDo.js.map} +1 -1
  226. package/build/server/chunks/{_server.ts-Bwt_pOeg.js → _server.ts-BtZN_8lV.js} +7 -7
  227. package/build/server/chunks/{_server.ts-Bwt_pOeg.js.map → _server.ts-BtZN_8lV.js.map} +1 -1
  228. package/build/server/chunks/{_server.ts-CFrPK6QO.js → _server.ts-Bx0PXf1w.js} +7 -7
  229. package/build/server/chunks/{_server.ts-CFrPK6QO.js.map → _server.ts-Bx0PXf1w.js.map} +1 -1
  230. package/build/server/chunks/{_server.ts-DpnNS7XE.js → _server.ts-Byaj9iKd.js} +7 -7
  231. package/build/server/chunks/{_server.ts-DpnNS7XE.js.map → _server.ts-Byaj9iKd.js.map} +1 -1
  232. package/build/server/chunks/{_server.ts-DbWhKo2R.js → _server.ts-C1kDLq6m.js} +7 -7
  233. package/build/server/chunks/{_server.ts-DbWhKo2R.js.map → _server.ts-C1kDLq6m.js.map} +1 -1
  234. package/build/server/chunks/{_server.ts-JhxhiGGc.js → _server.ts-C28zIW49.js} +7 -7
  235. package/build/server/chunks/{_server.ts-JhxhiGGc.js.map → _server.ts-C28zIW49.js.map} +1 -1
  236. package/build/server/chunks/{_server.ts-Dim_lnRX.js → _server.ts-C2F80x6V.js} +8 -8
  237. package/build/server/chunks/{_server.ts-Dim_lnRX.js.map → _server.ts-C2F80x6V.js.map} +1 -1
  238. package/build/server/chunks/{_server.ts-Blmg0cXL.js → _server.ts-C70sKEjH.js} +8 -8
  239. package/build/server/chunks/{_server.ts-Blmg0cXL.js.map → _server.ts-C70sKEjH.js.map} +1 -1
  240. package/build/server/chunks/{_server.ts-iFah_o1y.js → _server.ts-C754EzJA.js} +7 -7
  241. package/build/server/chunks/{_server.ts-iFah_o1y.js.map → _server.ts-C754EzJA.js.map} +1 -1
  242. package/build/server/chunks/{_server.ts-D3G8ICxb.js → _server.ts-C8n83Xl1.js} +7 -7
  243. package/build/server/chunks/{_server.ts-D3G8ICxb.js.map → _server.ts-C8n83Xl1.js.map} +1 -1
  244. package/build/server/chunks/{_server.ts-BvtdTKYv.js → _server.ts-CC6Bt-9t.js} +8 -8
  245. package/build/server/chunks/{_server.ts-BvtdTKYv.js.map → _server.ts-CC6Bt-9t.js.map} +1 -1
  246. package/build/server/chunks/{_server.ts-DgoPOMEf.js → _server.ts-CJ76gcOX.js} +7 -7
  247. package/build/server/chunks/{_server.ts-DgoPOMEf.js.map → _server.ts-CJ76gcOX.js.map} +1 -1
  248. package/build/server/chunks/{_server.ts-CZMdC1Kd.js → _server.ts-CMW6wbwP.js} +7 -7
  249. package/build/server/chunks/{_server.ts-CZMdC1Kd.js.map → _server.ts-CMW6wbwP.js.map} +1 -1
  250. package/build/server/chunks/{_server.ts-m7rCPG1J.js → _server.ts-CNjG4x1a.js} +8 -8
  251. package/build/server/chunks/{_server.ts-m7rCPG1J.js.map → _server.ts-CNjG4x1a.js.map} +1 -1
  252. package/build/server/chunks/{_server.ts-CjfZfEOL.js → _server.ts-CRl7GqvU.js} +7 -7
  253. package/build/server/chunks/{_server.ts-CjfZfEOL.js.map → _server.ts-CRl7GqvU.js.map} +1 -1
  254. package/build/server/chunks/{_server.ts-DMUseo0C.js → _server.ts-CUBWjRlp.js} +8 -8
  255. package/build/server/chunks/{_server.ts-DMUseo0C.js.map → _server.ts-CUBWjRlp.js.map} +1 -1
  256. package/build/server/chunks/{_server.ts-DjIJCqkv.js → _server.ts-CYoKjlbj.js} +7 -7
  257. package/build/server/chunks/{_server.ts-DjIJCqkv.js.map → _server.ts-CYoKjlbj.js.map} +1 -1
  258. package/build/server/chunks/{_server.ts-DgtgUx0V.js → _server.ts-CafJDVBQ.js} +3 -3
  259. package/build/server/chunks/{_server.ts-DgtgUx0V.js.map → _server.ts-CafJDVBQ.js.map} +1 -1
  260. package/build/server/chunks/{_server.ts-C4Pel5kC.js → _server.ts-Cd9hDiKk.js} +7 -7
  261. package/build/server/chunks/{_server.ts-C4Pel5kC.js.map → _server.ts-Cd9hDiKk.js.map} +1 -1
  262. package/build/server/chunks/{_server.ts-BfL_49xD.js → _server.ts-CgQfVR3g.js} +8 -8
  263. package/build/server/chunks/{_server.ts-BfL_49xD.js.map → _server.ts-CgQfVR3g.js.map} +1 -1
  264. package/build/server/chunks/{_server.ts-CzEoO4z1.js → _server.ts-CilbVIRO.js} +3 -3
  265. package/build/server/chunks/{_server.ts-CzEoO4z1.js.map → _server.ts-CilbVIRO.js.map} +1 -1
  266. package/build/server/chunks/{_server.ts-BXPj75Y1.js → _server.ts-Ck25Xm32.js} +8 -8
  267. package/build/server/chunks/{_server.ts-BXPj75Y1.js.map → _server.ts-Ck25Xm32.js.map} +1 -1
  268. package/build/server/chunks/{_server.ts-CGTCLl7g.js → _server.ts-Cp-_qWC_.js} +8 -8
  269. package/build/server/chunks/{_server.ts-CGTCLl7g.js.map → _server.ts-Cp-_qWC_.js.map} +1 -1
  270. package/build/server/chunks/{_server.ts-ygmDTh5G.js → _server.ts-CuEFmJ07.js} +8 -8
  271. package/build/server/chunks/{_server.ts-ygmDTh5G.js.map → _server.ts-CuEFmJ07.js.map} +1 -1
  272. package/build/server/chunks/{_server.ts-B_dmjFtu.js → _server.ts-D5vc4lGC.js} +8 -8
  273. package/build/server/chunks/_server.ts-D5vc4lGC.js.map +1 -0
  274. package/build/server/chunks/{_server.ts-CqK78x99.js → _server.ts-DDLE66QT.js} +8 -8
  275. package/build/server/chunks/{_server.ts-CqK78x99.js.map → _server.ts-DDLE66QT.js.map} +1 -1
  276. package/build/server/chunks/{_server.ts-CfLVH8TI.js → _server.ts-DEF1ChPD.js} +7 -7
  277. package/build/server/chunks/{_server.ts-CfLVH8TI.js.map → _server.ts-DEF1ChPD.js.map} +1 -1
  278. package/build/server/chunks/{_server.ts-CU4SIH7_.js → _server.ts-DHUtPRWK.js} +5 -5
  279. package/build/server/chunks/{_server.ts-CU4SIH7_.js.map → _server.ts-DHUtPRWK.js.map} +1 -1
  280. package/build/server/chunks/{_server.ts-w4ncTcy1.js → _server.ts-DHoTyKXL.js} +15 -11
  281. package/build/server/chunks/_server.ts-DHoTyKXL.js.map +1 -0
  282. package/build/server/chunks/{_server.ts-CtGn47WI.js → _server.ts-DSB9Fzwa.js} +5 -5
  283. package/build/server/chunks/{_server.ts-CtGn47WI.js.map → _server.ts-DSB9Fzwa.js.map} +1 -1
  284. package/build/server/chunks/{_server.ts-D3FpBEaY.js → _server.ts-DW36Vbiq.js} +9 -9
  285. package/build/server/chunks/_server.ts-DW36Vbiq.js.map +1 -0
  286. package/build/server/chunks/{_server.ts-B5wBYGeP.js → _server.ts-DWG4CKWG.js} +7 -7
  287. package/build/server/chunks/{_server.ts-B5wBYGeP.js.map → _server.ts-DWG4CKWG.js.map} +1 -1
  288. package/build/server/chunks/{_server.ts-BcqSTHN5.js → _server.ts-DXxQIT2o.js} +8 -8
  289. package/build/server/chunks/{_server.ts-BcqSTHN5.js.map → _server.ts-DXxQIT2o.js.map} +1 -1
  290. package/build/server/chunks/{_server.ts-BcO0Zf4D.js → _server.ts-Da8_J1a4.js} +8 -8
  291. package/build/server/chunks/{_server.ts-BcO0Zf4D.js.map → _server.ts-Da8_J1a4.js.map} +1 -1
  292. package/build/server/chunks/{_server.ts-BrQJNRtC.js → _server.ts-DcH5edss.js} +7 -7
  293. package/build/server/chunks/{_server.ts-BrQJNRtC.js.map → _server.ts-DcH5edss.js.map} +1 -1
  294. package/build/server/chunks/{_server.ts-CsI99fk3.js → _server.ts-DiHLYNbQ.js} +8 -8
  295. package/build/server/chunks/{_server.ts-CsI99fk3.js.map → _server.ts-DiHLYNbQ.js.map} +1 -1
  296. package/build/server/chunks/{_server.ts-Dy7MOoFx.js → _server.ts-Dio2CslE.js} +8 -8
  297. package/build/server/chunks/_server.ts-Dio2CslE.js.map +1 -0
  298. package/build/server/chunks/{_server.ts-CZ3VVtAj.js → _server.ts-Dlt1obi9.js} +7 -7
  299. package/build/server/chunks/{_server.ts-CZ3VVtAj.js.map → _server.ts-Dlt1obi9.js.map} +1 -1
  300. package/build/server/chunks/{_server.ts-YcvtqJwd.js → _server.ts-Ds0U_zKR.js} +8 -8
  301. package/build/server/chunks/{_server.ts-YcvtqJwd.js.map → _server.ts-Ds0U_zKR.js.map} +1 -1
  302. package/build/server/chunks/{_server.ts-CuLEqJd2.js → _server.ts-DsVsFcf8.js} +16 -11
  303. package/build/server/chunks/_server.ts-DsVsFcf8.js.map +1 -0
  304. package/build/server/chunks/{_server.ts-V-MiUhz4.js → _server.ts-Du3PIYf8.js} +7 -7
  305. package/build/server/chunks/{_server.ts-V-MiUhz4.js.map → _server.ts-Du3PIYf8.js.map} +1 -1
  306. package/build/server/chunks/{_server.ts-s2Seq_VN.js → _server.ts-Duzj6Wm_.js} +7 -19
  307. package/build/server/chunks/_server.ts-Duzj6Wm_.js.map +1 -0
  308. package/build/server/chunks/{_server.ts-Df7bUUvM.js → _server.ts-DyaoaWIS.js} +8 -8
  309. package/build/server/chunks/{_server.ts-Df7bUUvM.js.map → _server.ts-DyaoaWIS.js.map} +1 -1
  310. package/build/server/chunks/{_server.ts-Dixj3o5E.js → _server.ts-EYtSo6HZ.js} +7 -7
  311. package/build/server/chunks/{_server.ts-Dixj3o5E.js.map → _server.ts-EYtSo6HZ.js.map} +1 -1
  312. package/build/server/chunks/{_server.ts-CoVlX74M.js → _server.ts-JvnkkOhX.js} +8 -8
  313. package/build/server/chunks/{_server.ts-CoVlX74M.js.map → _server.ts-JvnkkOhX.js.map} +1 -1
  314. package/build/server/chunks/{_server.ts-MBgNxLF2.js → _server.ts-N0u5ruZe.js} +7 -7
  315. package/build/server/chunks/{_server.ts-MBgNxLF2.js.map → _server.ts-N0u5ruZe.js.map} +1 -1
  316. package/build/server/chunks/{_server.ts-Bnzq20kw.js → _server.ts-NdCztCBP.js} +7 -7
  317. package/build/server/chunks/{_server.ts-Bnzq20kw.js.map → _server.ts-NdCztCBP.js.map} +1 -1
  318. package/build/server/chunks/{_server.ts-BNOepqUw.js → _server.ts-OGUKP5Tu.js} +7 -7
  319. package/build/server/chunks/{_server.ts-BNOepqUw.js.map → _server.ts-OGUKP5Tu.js.map} +1 -1
  320. package/build/server/chunks/{_server.ts-DZrKSBmK.js → _server.ts-Q1KEyBck.js} +7 -7
  321. package/build/server/chunks/{_server.ts-DZrKSBmK.js.map → _server.ts-Q1KEyBck.js.map} +1 -1
  322. package/build/server/chunks/{_server.ts-B2BUFCOJ.js → _server.ts-TIRuudir.js} +3 -3
  323. package/build/server/chunks/{_server.ts-B2BUFCOJ.js.map → _server.ts-TIRuudir.js.map} +1 -1
  324. package/build/server/chunks/{_server.ts-HHMqD_RA.js → _server.ts-WTZtC5sX.js} +12 -7
  325. package/build/server/chunks/_server.ts-WTZtC5sX.js.map +1 -0
  326. package/build/server/chunks/{_server.ts-Bvb9c_At.js → _server.ts-WsWoJE5V.js} +9 -9
  327. package/build/server/chunks/{_server.ts-Bvb9c_At.js.map → _server.ts-WsWoJE5V.js.map} +1 -1
  328. package/build/server/chunks/{_server.ts-Do0cbyyq.js → _server.ts-X8GX4ChJ.js} +8 -8
  329. package/build/server/chunks/_server.ts-X8GX4ChJ.js.map +1 -0
  330. package/build/server/chunks/{_server.ts-BCrEvrVb.js → _server.ts-XIc2PDRd.js} +8 -8
  331. package/build/server/chunks/{_server.ts-BCrEvrVb.js.map → _server.ts-XIc2PDRd.js.map} +1 -1
  332. package/build/server/chunks/{_server.ts-CPNIDSmd.js → _server.ts-YsFgaaVd.js} +7 -7
  333. package/build/server/chunks/{_server.ts-CPNIDSmd.js.map → _server.ts-YsFgaaVd.js.map} +1 -1
  334. package/build/server/chunks/{_server.ts-BFRCkpIB.js → _server.ts-bOcb37D9.js} +8 -8
  335. package/build/server/chunks/{_server.ts-BFRCkpIB.js.map → _server.ts-bOcb37D9.js.map} +1 -1
  336. package/build/server/chunks/{_server.ts-D3CUgai-.js → _server.ts-e_8LykNe.js} +8 -8
  337. package/build/server/chunks/{_server.ts-D3CUgai-.js.map → _server.ts-e_8LykNe.js.map} +1 -1
  338. package/build/server/chunks/{_server.ts-DVNN4NHW.js → _server.ts-hLimfy8i.js} +7 -7
  339. package/build/server/chunks/{_server.ts-DVNN4NHW.js.map → _server.ts-hLimfy8i.js.map} +1 -1
  340. package/build/server/chunks/{_server.ts-BJGOO9Nn.js → _server.ts-khI1sqja.js} +3 -3
  341. package/build/server/chunks/{_server.ts-BJGOO9Nn.js.map → _server.ts-khI1sqja.js.map} +1 -1
  342. package/build/server/chunks/{_server.ts-6QSsgi7N.js → _server.ts-p1Z3DBlr.js} +7 -7
  343. package/build/server/chunks/{_server.ts-6QSsgi7N.js.map → _server.ts-p1Z3DBlr.js.map} +1 -1
  344. package/build/server/chunks/{_server.ts-BQdhHsGb.js → _server.ts-uzB454LO.js} +8 -8
  345. package/build/server/chunks/{_server.ts-BQdhHsGb.js.map → _server.ts-uzB454LO.js.map} +1 -1
  346. package/build/server/chunks/{_server.ts-D3EHXo-L.js → _server.ts-wKSTgSwf.js} +7 -7
  347. package/build/server/chunks/{_server.ts-D3EHXo-L.js.map → _server.ts-wKSTgSwf.js.map} +1 -1
  348. package/build/server/chunks/addon-helpers-DaC3GR9u.js +153 -0
  349. package/build/server/chunks/addon-helpers-DaC3GR9u.js.map +1 -0
  350. package/build/server/chunks/{admin-update-lock-ZHLAwYiV.js → admin-update-lock-Bu3VvAoN.js} +3 -3
  351. package/build/server/chunks/{admin-update-lock-ZHLAwYiV.js.map → admin-update-lock-Bu3VvAoN.js.map} +1 -1
  352. package/build/server/chunks/{akm-DU_4Aa4m.js → akm-DsJ8_uuW.js} +3 -3
  353. package/build/server/chunks/{akm-DU_4Aa4m.js.map → akm-DsJ8_uuW.js.map} +1 -1
  354. package/build/server/chunks/{_server.ts-CT0jVfA6.js → bring-up-BBKMJltU.js} +30 -228
  355. package/build/server/chunks/bring-up-BBKMJltU.js.map +1 -0
  356. package/build/server/chunks/{catalog-B4QoA_I8.js → catalog-8d-U0FbY.js} +5 -5
  357. package/build/server/chunks/{catalog-B4QoA_I8.js.map → catalog-8d-U0FbY.js.map} +1 -1
  358. package/build/server/chunks/{client-Dn-H0hgG.js → client-CHoZA_w9.js} +2 -2
  359. package/build/server/chunks/{client-Dn-H0hgG.js.map → client-CHoZA_w9.js.map} +1 -1
  360. package/build/server/chunks/{compose-args2-BFOGDQne.js → compose-args2-C9sLS6QR.js} +3 -3
  361. package/build/server/chunks/compose-args2-C9sLS6QR.js.map +1 -0
  362. package/build/server/chunks/{config-DoYNsM1_.js → config-ChxZZk6h.js} +2 -2
  363. package/build/server/chunks/{config-DoYNsM1_.js.map → config-ChxZZk6h.js.map} +1 -1
  364. package/build/server/chunks/{constants-1vPYIIwP.js → constants-C8L-P-CF.js} +2 -2
  365. package/build/server/chunks/{constants-1vPYIIwP.js.map → constants-C8L-P-CF.js.map} +1 -1
  366. package/build/server/chunks/{docker2-BYFlumV1.js → docker2-DGq6J3Kp.js} +3 -3
  367. package/build/server/chunks/docker2-DGq6J3Kp.js.map +1 -0
  368. package/build/server/chunks/{docker3-CtXDh00O.js → docker3-DFlJ-o_d.js} +2 -2
  369. package/build/server/chunks/{docker3-CtXDh00O.js.map → docker3-DFlJ-o_d.js.map} +1 -1
  370. package/build/server/chunks/environment-BYp8JQYM.js.map +1 -1
  371. package/build/server/chunks/{error.svelte-DWK4R1_M.js → error.svelte-BXxIEYd4.js} +4 -4
  372. package/build/server/chunks/{error.svelte-DWK4R1_M.js.map → error.svelte-BXxIEYd4.js.map} +1 -1
  373. package/build/server/chunks/features-D8Ez2vwC.js +101 -0
  374. package/build/server/chunks/features-D8Ez2vwC.js.map +1 -0
  375. package/build/server/chunks/{helpers-DxodR6tq.js → helpers-BrD1e__f.js} +17 -22
  376. package/build/server/chunks/helpers-BrD1e__f.js.map +1 -0
  377. package/build/server/chunks/{hooks.server-Bzj8OieV.js → hooks.server-Blba-Qw7.js} +12 -12
  378. package/build/server/chunks/hooks.server-Blba-Qw7.js.map +1 -0
  379. package/build/server/chunks/{http-CfHMreaI.js → http-B4Us23Mo.js} +3 -3
  380. package/build/server/chunks/http-B4Us23Mo.js.map +1 -0
  381. package/build/server/chunks/{internal-BcbUGF7Z.js → internal-CSnzBDeT.js} +8 -4
  382. package/build/server/chunks/{internal-BcbUGF7Z.js.map → internal-CSnzBDeT.js.map} +1 -1
  383. package/build/server/chunks/{landing-DhaVkN2f.js → landing-DxFOhZxH.js} +10 -12
  384. package/build/server/chunks/landing-DxFOhZxH.js.map +1 -0
  385. package/build/server/chunks/{network-preset-CJ1RRnki.js → network-preset-BvVAoagy.js} +14 -13
  386. package/build/server/chunks/network-preset-BvVAoagy.js.map +1 -0
  387. package/build/server/chunks/opencode-target-D4BxXYHJ.js +203 -0
  388. package/build/server/chunks/opencode-target-D4BxXYHJ.js.map +1 -0
  389. package/build/server/chunks/{paths-Bgos728b.js → paths-6f-5gYkd.js} +2 -2
  390. package/build/server/chunks/{paths-Bgos728b.js.map → paths-6f-5gYkd.js.map} +1 -1
  391. package/build/server/chunks/{runtime-context.svelte-C5zNEC6u.js → runtime-context.svelte-CRT-b6Ae.js} +8 -11
  392. package/build/server/chunks/runtime-context.svelte-CRT-b6Ae.js.map +1 -0
  393. package/build/server/chunks/{session-cookie-C8DcD6bt.js → session-cookie-5J3xCH94.js} +2 -2
  394. package/build/server/chunks/{session-cookie-C8DcD6bt.js.map → session-cookie-5J3xCH94.js.map} +1 -1
  395. package/build/server/chunks/{setup-deploy-D9j0EGGd.js → setup-deploy-DUbX3fHm.js} +2 -2
  396. package/build/server/chunks/{setup-deploy-D9j0EGGd.js.map → setup-deploy-DUbX3fHm.js.map} +1 -1
  397. package/build/server/chunks/{src-DbArH65P.js → src-B2wHibme.js} +118 -143
  398. package/build/server/chunks/src-B2wHibme.js.map +1 -0
  399. package/build/server/chunks/{state-Bq8fep3F.js → state-JIy0tegD.js} +2 -2
  400. package/build/server/chunks/{state-Bq8fep3F.js.map → state-JIy0tegD.js.map} +1 -1
  401. package/build/server/chunks/{state2-Cna2OZrd.js → state2-Br2snAqo.js} +2 -2
  402. package/build/server/chunks/{state2-Cna2OZrd.js.map → state2-Br2snAqo.js.map} +1 -1
  403. package/build/server/chunks/voice-state.svelte-DU9g_xEh.js +1610 -0
  404. package/build/server/chunks/voice-state.svelte-DU9g_xEh.js.map +1 -0
  405. package/build/server/index.js +1 -1
  406. package/build/server/manifest.js +98 -140
  407. package/build/server/manifest.js.map +1 -1
  408. package/package.json +3 -3
  409. package/build/client/_app/immutable/assets/4.B2m7mOkq.css +0 -1
  410. package/build/client/_app/immutable/assets/4.B2m7mOkq.css.br +0 -0
  411. package/build/client/_app/immutable/assets/4.B2m7mOkq.css.gz +0 -0
  412. package/build/client/_app/immutable/assets/6.CmRPKjbq.css +0 -1
  413. package/build/client/_app/immutable/assets/6.CmRPKjbq.css.br +0 -0
  414. package/build/client/_app/immutable/assets/6.CmRPKjbq.css.gz +0 -0
  415. package/build/client/_app/immutable/assets/7.BTWb8aLW.css +0 -1
  416. package/build/client/_app/immutable/assets/7.BTWb8aLW.css.br +0 -0
  417. package/build/client/_app/immutable/assets/7.BTWb8aLW.css.gz +0 -0
  418. package/build/client/_app/immutable/assets/9.D8zTZB7v.css +0 -1
  419. package/build/client/_app/immutable/assets/9.D8zTZB7v.css.br +0 -0
  420. package/build/client/_app/immutable/assets/9.D8zTZB7v.css.gz +0 -0
  421. package/build/client/_app/immutable/chunks/BDK50g8a.js.br +0 -0
  422. package/build/client/_app/immutable/chunks/BDK50g8a.js.gz +0 -0
  423. package/build/client/_app/immutable/chunks/BX_cLEyR.js +0 -1
  424. package/build/client/_app/immutable/chunks/BX_cLEyR.js.br +0 -0
  425. package/build/client/_app/immutable/chunks/BX_cLEyR.js.gz +0 -0
  426. package/build/client/_app/immutable/chunks/ByFgZDEl.js +0 -1
  427. package/build/client/_app/immutable/chunks/ByFgZDEl.js.br +0 -0
  428. package/build/client/_app/immutable/chunks/ByFgZDEl.js.gz +0 -0
  429. package/build/client/_app/immutable/chunks/BzIvC31O.js +0 -3
  430. package/build/client/_app/immutable/chunks/BzIvC31O.js.br +0 -0
  431. package/build/client/_app/immutable/chunks/BzIvC31O.js.gz +0 -0
  432. package/build/client/_app/immutable/chunks/C718MJXm.js +0 -5
  433. package/build/client/_app/immutable/chunks/C718MJXm.js.br +0 -0
  434. package/build/client/_app/immutable/chunks/C718MJXm.js.gz +0 -0
  435. package/build/client/_app/immutable/chunks/CUa5ff3d.js.br +0 -0
  436. package/build/client/_app/immutable/chunks/CUa5ff3d.js.gz +0 -0
  437. package/build/client/_app/immutable/chunks/Cnz20Kyu.js +0 -3
  438. package/build/client/_app/immutable/chunks/Cnz20Kyu.js.br +0 -0
  439. package/build/client/_app/immutable/chunks/Cnz20Kyu.js.gz +0 -0
  440. package/build/client/_app/immutable/chunks/CoOosFtk.js +0 -3
  441. package/build/client/_app/immutable/chunks/CoOosFtk.js.br +0 -0
  442. package/build/client/_app/immutable/chunks/CoOosFtk.js.gz +0 -0
  443. package/build/client/_app/immutable/chunks/D5FtEngX.js.br +0 -0
  444. package/build/client/_app/immutable/chunks/D5FtEngX.js.gz +0 -0
  445. package/build/client/_app/immutable/chunks/DBHgGGCD.js +0 -1
  446. package/build/client/_app/immutable/chunks/DBHgGGCD.js.br +0 -0
  447. package/build/client/_app/immutable/chunks/DBHgGGCD.js.gz +0 -0
  448. package/build/client/_app/immutable/chunks/DBaSfL95.js +0 -1
  449. package/build/client/_app/immutable/chunks/DBaSfL95.js.br +0 -0
  450. package/build/client/_app/immutable/chunks/DBaSfL95.js.gz +0 -0
  451. package/build/client/_app/immutable/chunks/DfZbBavE.js +0 -1
  452. package/build/client/_app/immutable/chunks/DfZbBavE.js.br +0 -1
  453. package/build/client/_app/immutable/chunks/DfZbBavE.js.gz +0 -0
  454. package/build/client/_app/immutable/chunks/DmFbAjwW.js.br +0 -3
  455. package/build/client/_app/immutable/chunks/DmFbAjwW.js.gz +0 -0
  456. package/build/client/_app/immutable/chunks/NR-JVJz-.js.br +0 -0
  457. package/build/client/_app/immutable/chunks/NR-JVJz-.js.gz +0 -0
  458. package/build/client/_app/immutable/chunks/R6GPcDBF.js +0 -14
  459. package/build/client/_app/immutable/chunks/R6GPcDBF.js.br +0 -0
  460. package/build/client/_app/immutable/chunks/R6GPcDBF.js.gz +0 -0
  461. package/build/client/_app/immutable/chunks/SXdvPq3_.js.br +0 -0
  462. package/build/client/_app/immutable/chunks/SXdvPq3_.js.gz +0 -0
  463. package/build/client/_app/immutable/chunks/c0lkYAgh.js +0 -5
  464. package/build/client/_app/immutable/chunks/c0lkYAgh.js.br +0 -0
  465. package/build/client/_app/immutable/chunks/c0lkYAgh.js.gz +0 -0
  466. package/build/client/_app/immutable/chunks/hSjQday7.js.br +0 -0
  467. package/build/client/_app/immutable/chunks/hSjQday7.js.gz +0 -0
  468. package/build/client/_app/immutable/chunks/mG6HnNbi.js.br +0 -0
  469. package/build/client/_app/immutable/chunks/mG6HnNbi.js.gz +0 -0
  470. package/build/client/_app/immutable/chunks/ra5AJhOl.js +0 -1
  471. package/build/client/_app/immutable/chunks/ra5AJhOl.js.br +0 -2
  472. package/build/client/_app/immutable/chunks/ra5AJhOl.js.gz +0 -0
  473. package/build/client/_app/immutable/entry/app.SHrJgM4c.js +0 -2
  474. package/build/client/_app/immutable/entry/app.SHrJgM4c.js.br +0 -0
  475. package/build/client/_app/immutable/entry/app.SHrJgM4c.js.gz +0 -0
  476. package/build/client/_app/immutable/entry/start.CM0OuHkF.js +0 -1
  477. package/build/client/_app/immutable/entry/start.CM0OuHkF.js.br +0 -0
  478. package/build/client/_app/immutable/entry/start.CM0OuHkF.js.gz +0 -0
  479. package/build/client/_app/immutable/nodes/0.mcDF2Cfv.js +0 -1
  480. package/build/client/_app/immutable/nodes/0.mcDF2Cfv.js.br +0 -0
  481. package/build/client/_app/immutable/nodes/0.mcDF2Cfv.js.gz +0 -0
  482. package/build/client/_app/immutable/nodes/1.BRotfm1G.js +0 -1
  483. package/build/client/_app/immutable/nodes/1.BRotfm1G.js.br +0 -2
  484. package/build/client/_app/immutable/nodes/1.BRotfm1G.js.gz +0 -0
  485. package/build/client/_app/immutable/nodes/10.CtHRQW64.js +0 -1
  486. package/build/client/_app/immutable/nodes/10.CtHRQW64.js.br +0 -0
  487. package/build/client/_app/immutable/nodes/10.CtHRQW64.js.gz +0 -0
  488. package/build/client/_app/immutable/nodes/11.DViPDhJG.js +0 -8
  489. package/build/client/_app/immutable/nodes/11.DViPDhJG.js.br +0 -0
  490. package/build/client/_app/immutable/nodes/11.DViPDhJG.js.gz +0 -0
  491. package/build/client/_app/immutable/nodes/2.C-PzaHZx.js +0 -1
  492. package/build/client/_app/immutable/nodes/2.C-PzaHZx.js.br +0 -0
  493. package/build/client/_app/immutable/nodes/2.C-PzaHZx.js.gz +0 -0
  494. package/build/client/_app/immutable/nodes/3.26Z_fr6N.js +0 -1
  495. package/build/client/_app/immutable/nodes/3.26Z_fr6N.js.br +0 -0
  496. package/build/client/_app/immutable/nodes/3.26Z_fr6N.js.gz +0 -0
  497. package/build/client/_app/immutable/nodes/4.B1PIKbh6.js +0 -6
  498. package/build/client/_app/immutable/nodes/4.B1PIKbh6.js.br +0 -0
  499. package/build/client/_app/immutable/nodes/4.B1PIKbh6.js.gz +0 -0
  500. package/build/client/_app/immutable/nodes/5.CIMkqYzP.js.br +0 -0
  501. package/build/client/_app/immutable/nodes/5.CIMkqYzP.js.gz +0 -0
  502. package/build/client/_app/immutable/nodes/6.U9QsdKdj.js +0 -2
  503. package/build/client/_app/immutable/nodes/6.U9QsdKdj.js.br +0 -0
  504. package/build/client/_app/immutable/nodes/6.U9QsdKdj.js.gz +0 -0
  505. package/build/client/_app/immutable/nodes/7.Dvpg6Lol.js +0 -14
  506. package/build/client/_app/immutable/nodes/7.Dvpg6Lol.js.br +0 -0
  507. package/build/client/_app/immutable/nodes/7.Dvpg6Lol.js.gz +0 -0
  508. package/build/client/_app/immutable/nodes/8.NHp_bSVx.js +0 -1
  509. package/build/client/_app/immutable/nodes/8.NHp_bSVx.js.br +0 -0
  510. package/build/client/_app/immutable/nodes/8.NHp_bSVx.js.gz +0 -0
  511. package/build/client/_app/immutable/nodes/9.zlIImD-K.js +0 -128
  512. package/build/client/_app/immutable/nodes/9.zlIImD-K.js.br +0 -0
  513. package/build/client/_app/immutable/nodes/9.zlIImD-K.js.gz +0 -0
  514. package/build/server/chunks/0-BtezztJz.js.map +0 -1
  515. package/build/server/chunks/1-CvGA_TOi.js +0 -9
  516. package/build/server/chunks/11-Bp7zXIv8.js +0 -9
  517. package/build/server/chunks/11-Bp7zXIv8.js.map +0 -1
  518. package/build/server/chunks/3-CZdWulB3.js.map +0 -1
  519. package/build/server/chunks/4-4bobZFC9.js +0 -9
  520. package/build/server/chunks/4-4bobZFC9.js.map +0 -1
  521. package/build/server/chunks/6-sGxxEzTB.js +0 -9
  522. package/build/server/chunks/6-sGxxEzTB.js.map +0 -1
  523. package/build/server/chunks/7-mi0k2tJn.js +0 -9
  524. package/build/server/chunks/7-mi0k2tJn.js.map +0 -1
  525. package/build/server/chunks/8-DiHmrGkL.js.map +0 -1
  526. package/build/server/chunks/9-DB22e_yA.js +0 -9
  527. package/build/server/chunks/9-DB22e_yA.js.map +0 -1
  528. package/build/server/chunks/IconActivity-DrgUhxxi.js.map +0 -1
  529. package/build/server/chunks/IconMic-BbjkE_nG.js +0 -18
  530. package/build/server/chunks/IconMic-BbjkE_nG.js.map +0 -1
  531. package/build/server/chunks/IconSoundOn-DZGaQz_p.js.map +0 -1
  532. package/build/server/chunks/IconStop-BPbovgch.js.map +0 -1
  533. package/build/server/chunks/_page.svelte-CB1qUSpk.js +0 -95
  534. package/build/server/chunks/_page.svelte-CB1qUSpk.js.map +0 -1
  535. package/build/server/chunks/_page.svelte-CPo3vFZf.js.map +0 -1
  536. package/build/server/chunks/_page.svelte-F3gki1Uz.js +0 -155
  537. package/build/server/chunks/_page.svelte-F3gki1Uz.js.map +0 -1
  538. package/build/server/chunks/_page.svelte-GcuuPiXq.js.map +0 -1
  539. package/build/server/chunks/_page.svelte-K6kU7jIW.js.map +0 -1
  540. package/build/server/chunks/_server.ts-BQZ6mdSh.js +0 -93
  541. package/build/server/chunks/_server.ts-BQZ6mdSh.js.map +0 -1
  542. package/build/server/chunks/_server.ts-B_dmjFtu.js.map +0 -1
  543. package/build/server/chunks/_server.ts-BmRwgrKB.js +0 -67
  544. package/build/server/chunks/_server.ts-BmRwgrKB.js.map +0 -1
  545. package/build/server/chunks/_server.ts-CT0jVfA6.js.map +0 -1
  546. package/build/server/chunks/_server.ts-Cf_ZLxIl.js.map +0 -1
  547. package/build/server/chunks/_server.ts-CixURe5F.js +0 -49
  548. package/build/server/chunks/_server.ts-CixURe5F.js.map +0 -1
  549. package/build/server/chunks/_server.ts-CuLEqJd2.js.map +0 -1
  550. package/build/server/chunks/_server.ts-CvkF5YMt.js +0 -97
  551. package/build/server/chunks/_server.ts-CvkF5YMt.js.map +0 -1
  552. package/build/server/chunks/_server.ts-CyIO3STA.js +0 -73
  553. package/build/server/chunks/_server.ts-CyIO3STA.js.map +0 -1
  554. package/build/server/chunks/_server.ts-CzIZ-UYy.js +0 -113
  555. package/build/server/chunks/_server.ts-CzIZ-UYy.js.map +0 -1
  556. package/build/server/chunks/_server.ts-D3FpBEaY.js.map +0 -1
  557. package/build/server/chunks/_server.ts-Do0cbyyq.js.map +0 -1
  558. package/build/server/chunks/_server.ts-Dy7MOoFx.js.map +0 -1
  559. package/build/server/chunks/_server.ts-HHMqD_RA.js.map +0 -1
  560. package/build/server/chunks/_server.ts-s2Seq_VN.js.map +0 -1
  561. package/build/server/chunks/_server.ts-w4ncTcy1.js.map +0 -1
  562. package/build/server/chunks/_server.ts-ykET4T6s.js.map +0 -1
  563. package/build/server/chunks/addon-helpers-tZ_tAgFZ.js +0 -64
  564. package/build/server/chunks/addon-helpers-tZ_tAgFZ.js.map +0 -1
  565. package/build/server/chunks/compose-args2-BFOGDQne.js.map +0 -1
  566. package/build/server/chunks/connections-api-DlEoE3-k.js +0 -35
  567. package/build/server/chunks/connections-api-DlEoE3-k.js.map +0 -1
  568. package/build/server/chunks/docker2-BYFlumV1.js.map +0 -1
  569. package/build/server/chunks/endpoints-IFTldlrt.js +0 -473
  570. package/build/server/chunks/endpoints-IFTldlrt.js.map +0 -1
  571. package/build/server/chunks/features-BW-bVsl8.js +0 -118
  572. package/build/server/chunks/features-BW-bVsl8.js.map +0 -1
  573. package/build/server/chunks/helpers-DxodR6tq.js.map +0 -1
  574. package/build/server/chunks/hooks.server-Bzj8OieV.js.map +0 -1
  575. package/build/server/chunks/http-CfHMreaI.js.map +0 -1
  576. package/build/server/chunks/landing-DhaVkN2f.js.map +0 -1
  577. package/build/server/chunks/network-preset-CJ1RRnki.js.map +0 -1
  578. package/build/server/chunks/runtime-context.svelte-C5zNEC6u.js.map +0 -1
  579. package/build/server/chunks/speakable-text-BflxDDdY.js +0 -65
  580. package/build/server/chunks/speakable-text-BflxDDdY.js.map +0 -1
  581. package/build/server/chunks/src-DbArH65P.js.map +0 -1
  582. package/build/server/chunks/voice-state.svelte-2hAkP5Di.js +0 -539
  583. package/build/server/chunks/voice-state.svelte-2hAkP5Di.js.map +0 -1
  584. /package/build/client/_app/immutable/assets/{IconActivity.BdXOPwBm.css → ChatMessage.BdXOPwBm.css} +0 -0
  585. /package/build/client/_app/immutable/assets/{IconActivity.BdXOPwBm.css.br → ChatMessage.BdXOPwBm.css.br} +0 -0
  586. /package/build/client/_app/immutable/assets/{IconActivity.BdXOPwBm.css.gz → ChatMessage.BdXOPwBm.css.gz} +0 -0
  587. /package/build/client/_app/immutable/chunks/{DD22UF1L.js → DD22UF1L2.js} +0 -0
  588. /package/build/client/_app/immutable/chunks/{DD22UF1L.js.br → DD22UF1L2.js.br} +0 -0
  589. /package/build/client/_app/immutable/chunks/{DD22UF1L.js.gz → DD22UF1L2.js.gz} +0 -0
@@ -0,0 +1,1610 @@
1
+ //#region src/lib/notifications.svelte.ts
2
+ var DEFAULT_TIMEOUTS = {
3
+ info: 4e3,
4
+ success: 5e3,
5
+ error: 8e3
6
+ };
7
+ var Notifications = class {
8
+ toasts = [];
9
+ timers = /* @__PURE__ */ new Map();
10
+ push(kind, message, opts = {}) {
11
+ const id = opts.replaceId ?? (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `t-${Date.now()}-${Math.random().toString(36).slice(2)}`);
12
+ const ttlMs = opts.sticky ? null : opts.ttlMs ?? DEFAULT_TIMEOUTS[kind];
13
+ const toast = {
14
+ id,
15
+ kind,
16
+ message,
17
+ ttlMs
18
+ };
19
+ const existingTimer = this.timers.get(id);
20
+ if (existingTimer) {
21
+ clearTimeout(existingTimer);
22
+ this.timers.delete(id);
23
+ }
24
+ const existingIdx = this.toasts.findIndex((t) => t.id === id);
25
+ if (existingIdx >= 0) {
26
+ const next = [...this.toasts];
27
+ next[existingIdx] = toast;
28
+ this.toasts = next;
29
+ } else this.toasts = [...this.toasts, toast];
30
+ if (ttlMs !== null) {
31
+ const timer = setTimeout(() => this.dismiss(id), ttlMs);
32
+ this.timers.set(id, timer);
33
+ }
34
+ return id;
35
+ }
36
+ dismiss(id) {
37
+ const timer = this.timers.get(id);
38
+ if (timer) {
39
+ clearTimeout(timer);
40
+ this.timers.delete(id);
41
+ }
42
+ this.toasts = this.toasts.filter((t) => t.id !== id);
43
+ }
44
+ clear() {
45
+ for (const timer of this.timers.values()) clearTimeout(timer);
46
+ this.timers.clear();
47
+ this.toasts = [];
48
+ }
49
+ };
50
+ var notifications = new Notifications();
51
+ //#endregion
52
+ //#region src/lib/theme-state.svelte.ts
53
+ var THEME_STORAGE_KEY = "openpalm.theme";
54
+ var THEME_ATTR = "data-theme";
55
+ var DARK_THEME_COLOR = "#161c22";
56
+ var LIGHT_THEME_COLOR = "#f9fafb";
57
+ function isThemePreference(value) {
58
+ return value === "light" || value === "dark" || value === "system";
59
+ }
60
+ var ThemeService = class {
61
+ preference = "system";
62
+ resolved = "light";
63
+ initialized = false;
64
+ #mediaQuery = null;
65
+ #mediaChangeHandler = () => {
66
+ if (this.preference !== "system") return;
67
+ this.resolved = this.#resolvePreference("system");
68
+ this.#applyResolvedTheme();
69
+ };
70
+ init() {
71
+ if (typeof window === "undefined" || this.initialized) return;
72
+ this.preference = this.#readStoredPreference();
73
+ this.resolved = this.#resolvePreference(this.preference);
74
+ this.#subscribeToSystemTheme();
75
+ this.#applyResolvedTheme();
76
+ this.initialized = true;
77
+ }
78
+ setPreference(preference) {
79
+ this.preference = preference;
80
+ this.resolved = this.#resolvePreference(preference);
81
+ this.#writeStoredPreference(preference);
82
+ this.#applyResolvedTheme();
83
+ }
84
+ toggle() {
85
+ const next = this.preference === "system" ? "light" : this.preference === "light" ? "dark" : "system";
86
+ this.setPreference(next);
87
+ }
88
+ dispose() {
89
+ if (this.#mediaQuery) if (typeof this.#mediaQuery.removeEventListener === "function") this.#mediaQuery.removeEventListener("change", this.#mediaChangeHandler);
90
+ else this.#mediaQuery.removeListener(this.#mediaChangeHandler);
91
+ this.#mediaQuery = null;
92
+ this.initialized = false;
93
+ }
94
+ #readStoredPreference() {
95
+ if (typeof window === "undefined") return "system";
96
+ try {
97
+ const stored = window.localStorage.getItem(THEME_STORAGE_KEY);
98
+ return isThemePreference(stored) ? stored : "system";
99
+ } catch {
100
+ return "system";
101
+ }
102
+ }
103
+ #writeStoredPreference(preference) {
104
+ if (typeof window === "undefined") return;
105
+ try {
106
+ window.localStorage.setItem(THEME_STORAGE_KEY, preference);
107
+ } catch {}
108
+ }
109
+ #resolvePreference(preference) {
110
+ if (preference === "light" || preference === "dark") return preference;
111
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return "light";
112
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
113
+ }
114
+ #subscribeToSystemTheme() {
115
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
116
+ const nextQuery = window.matchMedia("(prefers-color-scheme: dark)");
117
+ if (this.#mediaQuery === nextQuery) return;
118
+ if (this.#mediaQuery) if (typeof this.#mediaQuery.removeEventListener === "function") this.#mediaQuery.removeEventListener("change", this.#mediaChangeHandler);
119
+ else this.#mediaQuery.removeListener(this.#mediaChangeHandler);
120
+ this.#mediaQuery = nextQuery;
121
+ if (typeof nextQuery.addEventListener === "function") nextQuery.addEventListener("change", this.#mediaChangeHandler);
122
+ else nextQuery.addListener(this.#mediaChangeHandler);
123
+ }
124
+ #applyResolvedTheme() {
125
+ if (typeof document === "undefined") return;
126
+ const root = document.documentElement;
127
+ root.setAttribute(THEME_ATTR, this.resolved);
128
+ root.style.colorScheme = this.resolved;
129
+ const themeColorMeta = document.querySelector("meta[name=\"theme-color\"]");
130
+ if (themeColorMeta) themeColorMeta.content = this.resolved === "dark" ? DARK_THEME_COLOR : LIGHT_THEME_COLOR;
131
+ const colorSchemeMeta = document.querySelector("meta[name=\"color-scheme\"]");
132
+ if (colorSchemeMeta) colorSchemeMeta.content = this.resolved;
133
+ }
134
+ };
135
+ var themeService = new ThemeService();
136
+ //#endregion
137
+ //#region src/lib/random-id.ts
138
+ /**
139
+ * Random id generation that works in EVERY browsing context.
140
+ *
141
+ * `crypto.randomUUID()` is secure-context-only: on a plain-http LAN origin
142
+ * (the LAN-served tier) it is undefined and calling it throws. Every
143
+ * browser-side id mint (connection ids, secret refs, request ids, local chat
144
+ * entry ids) must go through this guard instead of bare `crypto.randomUUID()`
145
+ * — the fallback builds a v4 UUID from `crypto.getRandomValues`, which IS
146
+ * available in insecure contexts.
147
+ *
148
+ * Zero-import leaf module so any $lib code can use it without cycles.
149
+ */
150
+ function randomId() {
151
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
152
+ const b = crypto.getRandomValues(new Uint8Array(16));
153
+ b[6] = b[6] & 15 | 64;
154
+ b[8] = b[8] & 63 | 128;
155
+ const h = Array.from(b, (x) => x.toString(16).padStart(2, "0")).join("");
156
+ return `${h.slice(0, 8)}-${h.slice(8, 12)}-${h.slice(12, 16)}-${h.slice(16, 20)}-${h.slice(20)}`;
157
+ }
158
+ //#endregion
159
+ //#region src/lib/connections/url-policy.ts
160
+ /**
161
+ * Browser-owned connection URL policy (Phase 3a — "One UI, delete the split").
162
+ *
163
+ * A leaf module with zero imports so both the direct transport
164
+ * (`probeHealth()` short-circuit) and the connections form can consult it
165
+ * without pulling in the IndexedDB store module. There is no guardian
166
+ * `/oc`-appending helper — Guardian is a transparent OpenCode proxy now, so
167
+ * the user provides the exact baseUrl and no path inference is performed.
168
+ *
169
+ * The ONLY refusal trigger: a plain-http, non-loopback connection URL is
170
+ * refused iff the app itself runs on an https: origin. This is exactly the
171
+ * platform mixed-content rule (an https origin cannot `fetch()` a plain-http
172
+ * cross-origin target — the request would never leave the browser), not a
173
+ * broader "https or non-loopback origin" check. Preserves:
174
+ * - loopback TARGETS from any origin (mixed-content loopback exemption —
175
+ * `http://127.0.0.1`/`localhost`/`::1` are "potentially trustworthy"),
176
+ * - plain-http LAN targets from a loopback-origin client (the zero-TLS
177
+ * desktop default — a `http://127.0.0.1` origin is a secure context),
178
+ * - plain-http LAN targets from a non-loopback http ORIGIN (the LAN-served
179
+ * tier: `rewriteLoopbackUrlForBrowserHost` in `./store.ts`).
180
+ */
181
+ /** Canonical deep link to the TLS integration guide. Pinned by a test that
182
+ * the path segment names a real file, so a docs rename breaks CI instead of
183
+ * shipping a dead link. */
184
+ var TLS_GUIDE_URL = "https://github.com/itlackey/openpalm/blob/main/docs/remote-access-tls.md";
185
+ function isLoopbackHost(hostname) {
186
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]";
187
+ }
188
+ /** Remove legacy URL-embedded credentials before a URL reaches UI or storage. */
189
+ function redactUrlUserinfo(rawUrl) {
190
+ try {
191
+ const url = new URL(rawUrl);
192
+ url.username = "";
193
+ url.password = "";
194
+ return url.toString().replace(/\/$/, url.pathname === "/" && !rawUrl.endsWith("/") ? "" : "/");
195
+ } catch {
196
+ return rawUrl;
197
+ }
198
+ }
199
+ /**
200
+ * Refuse a plain-http non-loopback connection URL iff the app's own origin is
201
+ * https: (mixed content — the request could never succeed, so refuse up front
202
+ * with guidance instead of a generic fetch failure).
203
+ *
204
+ * `origin` defaults to `globalThis.location`; a null/undefined origin
205
+ * (non-browser context — tests, SSR) always allows, since there is no browser
206
+ * mixed-content policy to enforce there.
207
+ */
208
+ function validateConnectionUrl(rawUrl, origin = globalThis.location ?? null) {
209
+ let url;
210
+ try {
211
+ url = new URL(rawUrl);
212
+ } catch {
213
+ return {
214
+ ok: false,
215
+ reason: "invalid-url",
216
+ message: "Enter a valid URL."
217
+ };
218
+ }
219
+ if (url.protocol !== "http:" && url.protocol !== "https:") return {
220
+ ok: false,
221
+ reason: "invalid-url",
222
+ message: "The URL must use http:// or https://."
223
+ };
224
+ if (url.username || url.password) return {
225
+ ok: false,
226
+ reason: "userinfo-not-allowed",
227
+ message: "Do not put credentials in the URL. Use the Authentication fields instead."
228
+ };
229
+ if (url.protocol === "https:") return { ok: true };
230
+ if (isLoopbackHost(url.hostname)) return { ok: true };
231
+ if (origin?.protocol !== "https:") return { ok: true };
232
+ return {
233
+ ok: false,
234
+ reason: "insecure-remote",
235
+ message: "This app runs on a secure (https) origin, so browsers block plain-HTTP connections to remote servers. Use an https:// URL — see the TLS setup guide.",
236
+ guideUrl: TLS_GUIDE_URL
237
+ };
238
+ }
239
+ //#endregion
240
+ //#region src/lib/connections/store.ts
241
+ /**
242
+ * Browser-owned connection store (Phase 3a — "One UI, delete the split").
243
+ *
244
+ * Connection records persist behind a storage abstraction so the same store
245
+ * logic runs over IndexedDB in the browser (offline-readable) and over an
246
+ * in-memory backend in tests. The store API is async throughout (IndexedDB is
247
+ * async) and keeps NO state in store-instance fields — a page reload
248
+ * constructs a new store over the same backend and must see identical state.
249
+ *
250
+ * Locked/default entries are seeded from a runtime-config.json fetched from
251
+ * the app's own origin at boot. Absent file = no default connection.
252
+ *
253
+ * The Connection shape is `{ id, label, baseUrl, auth }` with auth narrowed to
254
+ * none | basic (Guardian is a transparent OpenCode proxy — Basic is the only
255
+ * connection credential model).
256
+ */
257
+ function rewriteLoopbackUrlForBrowserHost(rawUrl) {
258
+ const locationLike = globalThis.location;
259
+ const redactedUrl = redactUrlUserinfo(rawUrl);
260
+ if (!locationLike || isLoopbackHost(locationLike.hostname)) return redactedUrl;
261
+ try {
262
+ const url = new URL(redactedUrl);
263
+ if (!isLoopbackHost(url.hostname)) return redactedUrl;
264
+ url.hostname = locationLike.hostname;
265
+ return url.toString();
266
+ } catch {
267
+ return redactedUrl;
268
+ }
269
+ }
270
+ function redactEntryUrl(entry) {
271
+ const baseUrl = redactUrlUserinfo(entry.baseUrl);
272
+ return baseUrl === entry.baseUrl ? entry : {
273
+ ...entry,
274
+ baseUrl
275
+ };
276
+ }
277
+ function assertUrlHasNoUserinfo(rawUrl) {
278
+ let url;
279
+ try {
280
+ url = new URL(rawUrl);
281
+ } catch {
282
+ return;
283
+ }
284
+ if (url.username || url.password) throw new Error("Credentials must use the Authentication fields, not the connection URL.");
285
+ }
286
+ function adaptRuntimeConfigForBrowser(config) {
287
+ return { connections: config.connections.map((entry) => ({
288
+ ...redactEntryUrl(entry),
289
+ baseUrl: entry.locked ? rewriteLoopbackUrlForBrowserHost(entry.baseUrl) : redactUrlUserinfo(entry.baseUrl)
290
+ })) };
291
+ }
292
+ var ACTIVE_ID_KEY = "activeId";
293
+ function clone(value) {
294
+ return structuredClone(value);
295
+ }
296
+ /** In-memory storage backend — same semantics as the IndexedDB one. */
297
+ function createMemoryStorage() {
298
+ const entries = /* @__PURE__ */ new Map();
299
+ const meta = /* @__PURE__ */ new Map();
300
+ let cryptoKey = null;
301
+ return {
302
+ async getAll() {
303
+ return [...entries.values()].map(clone);
304
+ },
305
+ async get(id) {
306
+ const entry = entries.get(id);
307
+ return entry ? clone(entry) : null;
308
+ },
309
+ async put(entry) {
310
+ entries.set(entry.id, clone(redactEntryUrl(entry)));
311
+ },
312
+ async delete(id) {
313
+ entries.delete(id);
314
+ },
315
+ async getMeta(key) {
316
+ return meta.get(key) ?? null;
317
+ },
318
+ async setMeta(key, value) {
319
+ if (value === null) meta.delete(key);
320
+ else meta.set(key, value);
321
+ },
322
+ async getCryptoKey() {
323
+ return cryptoKey;
324
+ },
325
+ async setCryptoKey(key) {
326
+ cryptoKey = key;
327
+ }
328
+ };
329
+ }
330
+ var IDB_NAME = "openpalm-ui-connections";
331
+ var IDB_VERSION = 1;
332
+ var STORE_CONNECTIONS = "connections";
333
+ var STORE_META = "meta";
334
+ var STORE_KEYS = "keys";
335
+ var CRYPTO_KEY_ID = "secret-store-aes-gcm-key";
336
+ function idbRequest(request) {
337
+ return new Promise((resolve, reject) => {
338
+ request.onsuccess = () => resolve(request.result);
339
+ request.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error("IndexedDB request failed"));
340
+ });
341
+ }
342
+ /**
343
+ * F11 hardening: an IDB version bump with no `onblocked` handler and no
344
+ * `versionchange` listener can leave a boot hung forever with no error
345
+ * surfaced anywhere. `onblocked` rejects the open promise; `onVersionChange`
346
+ * is invoked once a successfully-opened connection later receives its OWN
347
+ * `versionchange` event (some other tab needs an upgrade): the connection
348
+ * closes itself immediately so it can't go on to block that upgrade in turn,
349
+ * and the caller uses the callback to drop its cached db promise so the NEXT
350
+ * storage operation reopens fresh.
351
+ */
352
+ function openDatabase(onVersionChange) {
353
+ return new Promise((resolve, reject) => {
354
+ const request = indexedDB.open(IDB_NAME, IDB_VERSION);
355
+ request.onupgradeneeded = () => {
356
+ const db = request.result;
357
+ if (!db.objectStoreNames.contains(STORE_CONNECTIONS)) db.createObjectStore(STORE_CONNECTIONS, { keyPath: "id" });
358
+ if (!db.objectStoreNames.contains(STORE_META)) db.createObjectStore(STORE_META);
359
+ if (!db.objectStoreNames.contains(STORE_KEYS)) db.createObjectStore(STORE_KEYS);
360
+ };
361
+ request.onsuccess = () => {
362
+ const db = request.result;
363
+ db.onversionchange = () => {
364
+ db.close();
365
+ onVersionChange();
366
+ };
367
+ resolve(db);
368
+ };
369
+ request.onerror = () => reject(request.error ?? /* @__PURE__ */ new Error("IndexedDB open failed"));
370
+ request.onblocked = () => reject(/* @__PURE__ */ new Error("IndexedDB upgrade blocked by another open connection (close other tabs of this app and retry)"));
371
+ });
372
+ }
373
+ /**
374
+ * IndexedDB storage backend (raw IDB API, no deps). Lazily opens the database
375
+ * on first use; each operation runs in its own short transaction.
376
+ */
377
+ function createIndexedDbStorage() {
378
+ let db = null;
379
+ const invalidate = () => {
380
+ db = null;
381
+ };
382
+ const database = () => {
383
+ db ??= openDatabase(invalidate);
384
+ return db;
385
+ };
386
+ const store = async (name, mode) => (await database()).transaction(name, mode).objectStore(name);
387
+ return {
388
+ async getAll() {
389
+ return idbRequest((await store(STORE_CONNECTIONS, "readonly")).getAll());
390
+ },
391
+ async get(id) {
392
+ return await idbRequest((await store(STORE_CONNECTIONS, "readonly")).get(id)) ?? null;
393
+ },
394
+ async put(entry) {
395
+ await idbRequest((await store(STORE_CONNECTIONS, "readwrite")).put(redactEntryUrl(entry)));
396
+ },
397
+ async delete(id) {
398
+ await idbRequest((await store(STORE_CONNECTIONS, "readwrite")).delete(id));
399
+ },
400
+ async getMeta(key) {
401
+ return await idbRequest((await store(STORE_META, "readonly")).get(key)) ?? null;
402
+ },
403
+ async setMeta(key, value) {
404
+ const metaStore = await store(STORE_META, "readwrite");
405
+ if (value === null) await idbRequest(metaStore.delete(key));
406
+ else await idbRequest(metaStore.put(value, key));
407
+ },
408
+ async getCryptoKey() {
409
+ return await idbRequest((await store(STORE_KEYS, "readonly")).get(CRYPTO_KEY_ID)) ?? null;
410
+ },
411
+ async setCryptoKey(key) {
412
+ await idbRequest((await store(STORE_KEYS, "readwrite")).put(key, CRYPTO_KEY_ID));
413
+ }
414
+ };
415
+ }
416
+ function createConnectionStore(options) {
417
+ const { storage } = options;
418
+ async function readEntry(id) {
419
+ const stored = await storage.get(id);
420
+ if (!stored) return null;
421
+ const entry = redactEntryUrl(stored);
422
+ if (entry.baseUrl !== stored.baseUrl) await storage.put(entry);
423
+ return entry;
424
+ }
425
+ async function requireEntry(id) {
426
+ const entry = await readEntry(id);
427
+ if (!entry) throw new Error(`Unknown connection: ${id}`);
428
+ return entry;
429
+ }
430
+ return {
431
+ async list() {
432
+ const stored = await storage.getAll();
433
+ const entries = stored.map(redactEntryUrl);
434
+ await Promise.all(entries.map((entry, index) => entry.baseUrl === stored[index]?.baseUrl ? Promise.resolve() : storage.put(entry)));
435
+ return entries;
436
+ },
437
+ get(id) {
438
+ return readEntry(id);
439
+ },
440
+ async add(input) {
441
+ assertUrlHasNoUserinfo(input.baseUrl);
442
+ const id = input.id ?? randomId();
443
+ if (await readEntry(id)) throw new Error(`Connection already exists: ${id}`);
444
+ const entry = {
445
+ ...input,
446
+ id
447
+ };
448
+ await storage.put(entry);
449
+ return clone(entry);
450
+ },
451
+ async update(id, patch) {
452
+ if (patch.baseUrl !== void 0) assertUrlHasNoUserinfo(patch.baseUrl);
453
+ const entry = await requireEntry(id);
454
+ if (entry.locked) throw new Error(`Connection is locked (config-owned): ${id}`);
455
+ const updated = {
456
+ ...entry,
457
+ ...patch,
458
+ id
459
+ };
460
+ await storage.put(updated);
461
+ return clone(updated);
462
+ },
463
+ async remove(id) {
464
+ if ((await requireEntry(id)).locked) throw new Error(`Connection is locked (config-owned): ${id}`);
465
+ await storage.delete(id);
466
+ if (await storage.getMeta(ACTIVE_ID_KEY) === id) await storage.setMeta(ACTIVE_ID_KEY, null);
467
+ },
468
+ async setSecretRef(id, auth) {
469
+ const updated = {
470
+ ...await requireEntry(id),
471
+ auth,
472
+ id
473
+ };
474
+ await storage.put(updated);
475
+ return clone(updated);
476
+ },
477
+ getActiveId() {
478
+ return storage.getMeta(ACTIVE_ID_KEY);
479
+ },
480
+ async getActive() {
481
+ const id = await storage.getMeta(ACTIVE_ID_KEY);
482
+ return id === null ? null : readEntry(id);
483
+ },
484
+ async setActive(id) {
485
+ await requireEntry(id);
486
+ await storage.setMeta(ACTIVE_ID_KEY, id);
487
+ },
488
+ async clearActive() {
489
+ await storage.setMeta(ACTIVE_ID_KEY, null);
490
+ },
491
+ async seedFromRuntimeConfig(config) {
492
+ if (!config) return;
493
+ const activeId = await storage.getMeta(ACTIVE_ID_KEY);
494
+ const configIds = new Set(config.connections.map((entry) => entry.id));
495
+ for (const existing of await storage.getAll()) {
496
+ if (!existing.locked || configIds.has(existing.id)) continue;
497
+ await storage.delete(existing.id);
498
+ if (activeId === existing.id) await storage.setMeta(ACTIVE_ID_KEY, null);
499
+ }
500
+ for (const entry of config.connections) {
501
+ const seededEntry = redactEntryUrl(entry);
502
+ const existing = await readEntry(entry.id);
503
+ if (!existing) await storage.put(clone(seededEntry));
504
+ else if (existing.locked) {
505
+ const seeded = clone(seededEntry);
506
+ const preserveAuth = existing.auth && existing.auth.mode !== "none";
507
+ await storage.put(preserveAuth ? {
508
+ ...seeded,
509
+ auth: existing.auth
510
+ } : seeded);
511
+ }
512
+ }
513
+ if (await storage.getMeta(ACTIVE_ID_KEY) !== null) return;
514
+ const fallback = config.connections.find((entry) => entry.isDefault);
515
+ if (fallback && await storage.get(fallback.id)) await storage.setMeta(ACTIVE_ID_KEY, fallback.id);
516
+ }
517
+ };
518
+ }
519
+ /**
520
+ * Fetch '/runtime-config.json' from the app's OWN origin (relative URL — the
521
+ * static server ships the file beside the build; the app holds no other
522
+ * trusted origin at boot). Absent (404), unreachable (offline), or malformed
523
+ * -> null; never throws, so an offline PWA boot still reaches the stored
524
+ * connection list.
525
+ */
526
+ async function loadRuntimeConfig(fetchImpl = globalThis.fetch) {
527
+ try {
528
+ const response = await fetchImpl("/runtime-config.json", {
529
+ method: "GET",
530
+ headers: { accept: "application/json" },
531
+ credentials: "omit"
532
+ });
533
+ if (!response.ok) return null;
534
+ const parsed = await response.json();
535
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.connections)) return null;
536
+ return adaptRuntimeConfigForBrowser(parsed);
537
+ } catch {
538
+ return null;
539
+ }
540
+ }
541
+ //#endregion
542
+ //#region src/lib/connections/secrets.ts
543
+ var META_PREFIX = "secret:";
544
+ var ENCRYPTED_MARKER = 2;
545
+ var AES_GCM_LENGTH = 256;
546
+ var IV_BYTES = 12;
547
+ /**
548
+ * WebCrypto's `SubtleCrypto` is secure-context-only: on a plain-http LAN origin
549
+ * (the LAN-served tier) `crypto.subtle` is undefined, so encryption is simply
550
+ * not available there. Callers degrade to the legacy plaintext record shape —
551
+ * which `readMaterial` already reads — rather than throwing and blocking the
552
+ * user from saving a credential at all.
553
+ */
554
+ function subtleAvailable() {
555
+ return typeof crypto !== "undefined" && !!crypto.subtle;
556
+ }
557
+ function isEncryptedRecord(value) {
558
+ return !!value && typeof value === "object" && value.v === ENCRYPTED_MARKER && typeof value.iv === "string" && typeof value.ciphertext === "string";
559
+ }
560
+ function bytesToBase64(bytes) {
561
+ let binary = "";
562
+ for (const byte of bytes) binary += String.fromCharCode(byte);
563
+ return btoa(binary);
564
+ }
565
+ function base64ToBytes(b64) {
566
+ const binary = atob(b64);
567
+ const bytes = new Uint8Array(binary.length);
568
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
569
+ return bytes;
570
+ }
571
+ var pendingKeys = /* @__PURE__ */ new WeakMap();
572
+ /** Generate-once, reuse-forever non-extractable AES-GCM key for this storage backend. */
573
+ async function getOrCreateKey(storage) {
574
+ const existing = await storage.getCryptoKey();
575
+ if (existing) return existing;
576
+ let pending = pendingKeys.get(storage);
577
+ if (!pending) {
578
+ pending = (async () => {
579
+ const key = await crypto.subtle.generateKey({
580
+ name: "AES-GCM",
581
+ length: AES_GCM_LENGTH
582
+ }, false, ["encrypt", "decrypt"]);
583
+ await storage.setCryptoKey(key);
584
+ return key;
585
+ })();
586
+ pendingKeys.set(storage, pending);
587
+ pending.catch(() => {
588
+ pendingKeys.delete(storage);
589
+ });
590
+ }
591
+ return pending;
592
+ }
593
+ async function encryptMaterial(key, material) {
594
+ const iv = crypto.getRandomValues(new Uint8Array(IV_BYTES));
595
+ const plaintext = new TextEncoder().encode(JSON.stringify(material));
596
+ const ciphertext = new Uint8Array(await crypto.subtle.encrypt({
597
+ name: "AES-GCM",
598
+ iv
599
+ }, key, plaintext));
600
+ return {
601
+ v: ENCRYPTED_MARKER,
602
+ iv: bytesToBase64(iv),
603
+ ciphertext: bytesToBase64(ciphertext)
604
+ };
605
+ }
606
+ async function decryptRecord(key, record) {
607
+ const iv = base64ToBytes(record.iv);
608
+ const ciphertext = base64ToBytes(record.ciphertext);
609
+ const plaintext = await crypto.subtle.decrypt({
610
+ name: "AES-GCM",
611
+ iv
612
+ }, key, ciphertext);
613
+ return JSON.parse(new TextDecoder().decode(plaintext));
614
+ }
615
+ async function writeMaterial(storage, ref, material) {
616
+ if (!subtleAvailable()) {
617
+ await storage.setMeta(META_PREFIX + ref, JSON.stringify(material));
618
+ return;
619
+ }
620
+ const record = await encryptMaterial(await getOrCreateKey(storage), material);
621
+ await storage.setMeta(META_PREFIX + ref, JSON.stringify(record));
622
+ }
623
+ /**
624
+ * Read+decrypt a stored secret. Transparently migrates a legacy plaintext
625
+ * record by re-encrypting it in place before returning. Returns null for a
626
+ * missing ref or anything that can't be parsed/decrypted — the caller degrades
627
+ * gracefully rather than throwing.
628
+ */
629
+ async function readMaterial(storage, ref) {
630
+ const raw = await storage.getMeta(META_PREFIX + ref);
631
+ if (raw === null) return null;
632
+ let parsed;
633
+ try {
634
+ parsed = JSON.parse(raw);
635
+ } catch {
636
+ return null;
637
+ }
638
+ if (isEncryptedRecord(parsed)) try {
639
+ return await decryptRecord(await getOrCreateKey(storage), parsed);
640
+ } catch {
641
+ return null;
642
+ }
643
+ const material = parsed;
644
+ if (subtleAvailable()) try {
645
+ await writeMaterial(storage, ref, material);
646
+ } catch {}
647
+ return material;
648
+ }
649
+ function createSecretStore(storage) {
650
+ return {
651
+ async set(ref, material) {
652
+ await writeMaterial(storage, ref, material);
653
+ },
654
+ async delete(ref) {
655
+ await storage.setMeta(META_PREFIX + ref, null);
656
+ },
657
+ get(ref) {
658
+ return readMaterial(storage, ref);
659
+ },
660
+ async resolveAuth(entry) {
661
+ if (entry.auth.mode !== "basic" || !entry.auth.secretRef) return { mode: "none" };
662
+ const material = await readMaterial(storage, entry.auth.secretRef);
663
+ if (!material || typeof material.password !== "string") return { mode: "none" };
664
+ const username = entry.auth.username || material.username;
665
+ return username ? {
666
+ mode: "basic",
667
+ username,
668
+ password: material.password
669
+ } : {
670
+ mode: "basic",
671
+ password: material.password
672
+ };
673
+ },
674
+ async updateUsername(ref, username) {
675
+ const material = await readMaterial(storage, ref);
676
+ if (!material) return;
677
+ const updated = { ...material };
678
+ if (username === void 0) delete updated.username;
679
+ else updated.username = username;
680
+ await writeMaterial(storage, ref, updated);
681
+ }
682
+ };
683
+ }
684
+ //#endregion
685
+ //#region src/lib/chat/session-events.ts
686
+ /**
687
+ * SSE consumer for OpenCode's `/event` stream.
688
+ *
689
+ * Phase 3b ("One UI, delete the split"): the underlying stream is now opened by
690
+ * the browser-owned direct transport (`$lib/connections/boot.getTransport()`
691
+ * → `subscribeEvents(onFrame, signal)`), which talks to the active connection's
692
+ * OpenCode/Guardian base URL directly (no host proxy, no admin cookie) and
693
+ * REUSES this module's `parseFrame`. Reconnect/backoff, session-scoped dispatch,
694
+ * and abort semantics stay here — the chat layer's concern, not the transport's.
695
+ *
696
+ * Phase D of docs/technical/multi-endpoint-session-ux.md.
697
+ */
698
+ var INITIAL_BACKOFF_MS = 1e3;
699
+ var MAX_BACKOFF_MS = 3e4;
700
+ /**
701
+ * Parse one `\n\n`-delimited SSE frame. Multi-line `data:` fields are
702
+ * concatenated with `\n` per the SSE spec. Reused by the direct transport.
703
+ */
704
+ function parseFrame(chunk) {
705
+ const frame = {};
706
+ const dataLines = [];
707
+ for (const rawLine of chunk.split("\n")) {
708
+ if (!rawLine || rawLine.startsWith(":")) continue;
709
+ if (rawLine.startsWith("data:")) dataLines.push(rawLine.replace(/^data:\s?/, ""));
710
+ else if (rawLine.startsWith("event:")) frame.event = rawLine.replace(/^event:\s?/, "");
711
+ else if (rawLine.startsWith("id:")) frame.id = rawLine.replace(/^id:\s?/, "");
712
+ }
713
+ if (dataLines.length > 0) frame.data = dataLines.join("\n");
714
+ return frame;
715
+ }
716
+ function dispatch(handlers, payload) {
717
+ const info = payload.properties?.info;
718
+ const id = info?.id ?? payload.sessionID;
719
+ if (!id) return;
720
+ switch (payload.type) {
721
+ case "session.created":
722
+ handlers.onCreated(id);
723
+ return;
724
+ case "session.updated":
725
+ handlers.onUpdated(id, {
726
+ title: info?.title,
727
+ updatedAt: info?.time?.updated
728
+ });
729
+ return;
730
+ case "session.deleted":
731
+ handlers.onDeleted(id);
732
+ return;
733
+ default: return;
734
+ }
735
+ }
736
+ /**
737
+ * Open the active connection's `/event` SSE stream (via the direct transport)
738
+ * and dispatch session-scoped events. Returns an unsubscribe function that
739
+ * aborts the stream and prevents reconnection.
740
+ *
741
+ * `onConnect` fires on the first frame of each (re)connected stream — the point
742
+ * at which live updates are demonstrably flowing. The transport owns the fetch;
743
+ * this loop owns exponential-backoff reconnect and abort.
744
+ */
745
+ function subscribeSessionEvents(handlers) {
746
+ let stopped = false;
747
+ let controller = new AbortController();
748
+ const sleep = (ms) => new Promise((resolve) => {
749
+ const timer = setTimeout(resolve, ms);
750
+ controller.signal.addEventListener("abort", () => {
751
+ clearTimeout(timer);
752
+ resolve();
753
+ }, { once: true });
754
+ });
755
+ async function readStream() {
756
+ let connected = false;
757
+ await getTransport().subscribeEvents((event) => {
758
+ if (!connected) {
759
+ connected = true;
760
+ handlers.onConnect?.();
761
+ }
762
+ const payload = event;
763
+ handlers.onEvent?.(payload);
764
+ dispatch(handlers, payload);
765
+ }, controller.signal);
766
+ }
767
+ (async () => {
768
+ let attempt = 0;
769
+ while (!stopped) try {
770
+ attempt++;
771
+ await readStream();
772
+ attempt = 0;
773
+ if (!stopped) await sleep(500);
774
+ } catch (err) {
775
+ if (stopped) return;
776
+ const error = err instanceof Error ? err : new Error(String(err));
777
+ if (error.name !== "AbortError") {
778
+ console.warn("[session-events] SSE error, reconnecting", error);
779
+ handlers.onDisconnect?.(error);
780
+ }
781
+ await sleep(Math.min(INITIAL_BACKOFF_MS * 2 ** Math.max(0, attempt - 1), MAX_BACKOFF_MS));
782
+ if (controller.signal.aborted && !stopped) controller = new AbortController();
783
+ }
784
+ })();
785
+ return () => {
786
+ stopped = true;
787
+ try {
788
+ controller.abort();
789
+ } catch {}
790
+ };
791
+ }
792
+ //#endregion
793
+ //#region src/lib/transport/direct.ts
794
+ /**
795
+ * Minimal browser-owned direct transport (Phase 3a — "One UI, delete the
796
+ * split").
797
+ *
798
+ * Talks to a connection's OpenCode/Guardian base URL directly from the
799
+ * browser — no proxy, NO COOKIES (`credentials: 'omit'`). This is deliberately
800
+ * small: it exposes only the calls the ui chat layer needs and REUSES ui's
801
+ * existing SSE frame parser (`$lib/chat/session-events.ts` `parseFrame`) and
802
+ * event envelope type (`$lib/chat/oc-events.ts` `RawEvent`) rather than
803
+ * re-implementing them. Reconnect/backoff and session-scoped filtering are the
804
+ * chat layer's concern, not this transport's.
805
+ */
806
+ var PROBE_TIMEOUT_MS = 5e3;
807
+ /**
808
+ * UTF-8-encode before base64ing: `btoa()` alone only accepts Latin-1 code
809
+ * points and throws a synchronous `InvalidCharacterError` for any password
810
+ * containing e.g. Cyrillic/CJK/emoji characters, before any network I/O.
811
+ */
812
+ function base64Utf8(value) {
813
+ const bytes = new TextEncoder().encode(value);
814
+ let binary = "";
815
+ for (const byte of bytes) binary += String.fromCharCode(byte);
816
+ return btoa(binary);
817
+ }
818
+ /**
819
+ * Build the `Authorization` header value for a resolved auth, or null for
820
+ * `{ mode: 'none' }`. Basic username defaults to `'opencode'` (OpenCode's own
821
+ * server default and what the host app sends).
822
+ */
823
+ function authorizationHeader(auth) {
824
+ if (auth.mode === "basic") return `Basic ${base64Utf8(`${auth.username ?? "opencode"}:${auth.password}`)}`;
825
+ return null;
826
+ }
827
+ function createDirectTransport(getConnection, resolveAuth, fetchImpl = globalThis.fetch) {
828
+ function requireConnection() {
829
+ const connection = getConnection();
830
+ if (!connection) throw new Error("No active connection");
831
+ return connection;
832
+ }
833
+ /** Trailing-slash and path-prefix safe: reverse-proxied instances keep their prefix. */
834
+ function baseFor(connection) {
835
+ return connection.baseUrl.replace(/\/+$/, "");
836
+ }
837
+ async function authHeaders(connection) {
838
+ const { authorization } = await resolveAuth(connection);
839
+ return authorization ? { authorization } : {};
840
+ }
841
+ return {
842
+ async request(method, path, body) {
843
+ const connection = requireConnection();
844
+ const init = {
845
+ method,
846
+ headers: {
847
+ ...body === void 0 ? {} : { "content-type": "application/json" },
848
+ ...await authHeaders(connection)
849
+ },
850
+ credentials: "omit"
851
+ };
852
+ if (body !== void 0) init.body = JSON.stringify(body);
853
+ const response = await fetchImpl(`${baseFor(connection)}${path}`, init);
854
+ if (!response.ok) throw Object.assign(/* @__PURE__ */ new Error(`HTTP ${response.status}`), { status: response.status });
855
+ return response;
856
+ },
857
+ async subscribeEvents(onFrame, signal) {
858
+ const connection = requireConnection();
859
+ const response = await fetchImpl(`${baseFor(connection)}/event`, {
860
+ method: "GET",
861
+ headers: {
862
+ accept: "text/event-stream",
863
+ ...await authHeaders(connection)
864
+ },
865
+ credentials: "omit",
866
+ signal
867
+ });
868
+ if (!response.ok || !response.body) throw Object.assign(/* @__PURE__ */ new Error(`SSE stream failed: HTTP ${response.status}`), { status: response.status });
869
+ const reader = response.body.getReader();
870
+ const decoder = new TextDecoder();
871
+ let buffer = "";
872
+ try {
873
+ while (true) {
874
+ const { done, value } = await reader.read();
875
+ if (done) break;
876
+ buffer += decoder.decode(value, { stream: true });
877
+ const chunks = buffer.split("\n\n");
878
+ buffer = chunks.pop() ?? "";
879
+ for (const chunk of chunks) {
880
+ if (!chunk) continue;
881
+ const frame = parseFrame(chunk);
882
+ if (!frame.data) continue;
883
+ let event;
884
+ try {
885
+ event = JSON.parse(frame.data);
886
+ } catch {
887
+ continue;
888
+ }
889
+ onFrame(event);
890
+ }
891
+ }
892
+ } finally {
893
+ try {
894
+ reader.releaseLock();
895
+ } catch {}
896
+ }
897
+ },
898
+ async probeHealth() {
899
+ const connection = getConnection();
900
+ if (!connection) return { status: "unreachable" };
901
+ const base = baseFor(connection);
902
+ const verdict = validateConnectionUrl(base);
903
+ if (!verdict.ok && verdict.reason === "insecure-remote") return { status: "insecure" };
904
+ try {
905
+ const response = await fetchImpl(`${base}/`, {
906
+ method: "GET",
907
+ headers: await authHeaders(connection),
908
+ credentials: "omit",
909
+ cache: "no-store",
910
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
911
+ });
912
+ if (response.status === 401 || response.status === 403) return { status: "unauthorized" };
913
+ if (response.ok || response.status >= 300 && response.status < 400) return { status: "accessible" };
914
+ return { status: "unreachable" };
915
+ } catch {
916
+ return { status: "unreachable" };
917
+ }
918
+ }
919
+ };
920
+ }
921
+ //#endregion
922
+ //#region src/lib/connections/boot.ts
923
+ /**
924
+ * Browser connection boot (Phase 3b — "One UI, delete the split").
925
+ *
926
+ * One storage backend + one ConnectionStore + one SecretStore + one direct
927
+ * transport per browsing session, created lazily on first access. The chat
928
+ * layer (`$lib/api/chat.ts`, `$lib/chat/session-events.ts`) and the connection
929
+ * switcher (`$lib/endpoints-state.svelte.ts`) all share these singletons so the
930
+ * browser owns connections and talks to OpenCode/Guardian DIRECTLY — no host
931
+ * proxy, no admin cookie.
932
+ *
933
+ * The transport reads the active connection SYNCHRONOUSLY from a snapshot the
934
+ * connection store owner (`endpoints-state`) keeps in sync via
935
+ * `setActiveConnection()`. The store's own `getActive()` is async (IndexedDB),
936
+ * so it can't back the transport's synchronous `getConnection` directly.
937
+ *
938
+ * IndexedDB is the persistent backend; private-browsing modes that refuse it
939
+ * degrade to an in-memory backend (session-only) rather than a blank page —
940
+ * mirroring the client's `pickStorage`.
941
+ */
942
+ var store = null;
943
+ var secrets = null;
944
+ var transport = null;
945
+ /** Synchronous snapshot of the active connection for the transport. */
946
+ var activeConnection = null;
947
+ /**
948
+ * Some private-browsing modes refuse IndexedDB entirely; degrade to a
949
+ * session-only in-memory backend rather than a blank page (mirrors the
950
+ * client's pickStorage).
951
+ */
952
+ function pickStorage() {
953
+ try {
954
+ if (typeof indexedDB !== "undefined") return createIndexedDbStorage();
955
+ } catch {}
956
+ return createMemoryStorage();
957
+ }
958
+ function ensure() {
959
+ if (store && secrets && transport) return;
960
+ const storage = pickStorage();
961
+ const connectionStore = createConnectionStore({ storage });
962
+ const secretStore = createSecretStore(storage);
963
+ const directTransport = createDirectTransport(() => activeConnection, async (connection) => {
964
+ return { authorization: authorizationHeader(await secretStore.resolveAuth(connection)) ?? void 0 };
965
+ });
966
+ store = connectionStore;
967
+ secrets = secretStore;
968
+ transport = directTransport;
969
+ }
970
+ function getConnectionStore() {
971
+ ensure();
972
+ return store;
973
+ }
974
+ function getSecretStore() {
975
+ ensure();
976
+ return secrets;
977
+ }
978
+ function getTransport() {
979
+ ensure();
980
+ return transport;
981
+ }
982
+ /**
983
+ * Point the direct transport at `connection` (or clear it). Called by the
984
+ * connection-store owner (`endpoints-state`) on load/activate — a plain
985
+ * function, no `$effect`, so the transport's synchronous `getConnection`
986
+ * always sees the current active connection.
987
+ */
988
+ function setActiveConnection(connection) {
989
+ activeConnection = connection;
990
+ }
991
+ //#endregion
992
+ //#region src/lib/voice/settings-store.ts
993
+ var STORAGE_KEY = "openpalm.voice.settings";
994
+ var PROVIDER_IDS = [
995
+ "disabled",
996
+ "browser",
997
+ "openpalm-voice",
998
+ "openai-compatible"
999
+ ];
1000
+ function safeLocalStorage() {
1001
+ try {
1002
+ return globalThis.localStorage ?? null;
1003
+ } catch {
1004
+ return null;
1005
+ }
1006
+ }
1007
+ function readSection(raw) {
1008
+ if (!raw || typeof raw !== "object") return null;
1009
+ const r = raw;
1010
+ if (!PROVIDER_IDS.includes(r.provider)) return null;
1011
+ const section = { provider: r.provider };
1012
+ for (const key of [
1013
+ "baseURL",
1014
+ "model",
1015
+ "language",
1016
+ "voice",
1017
+ "secretRef"
1018
+ ]) if (typeof r[key] === "string" && r[key]) section[key] = r[key];
1019
+ return section;
1020
+ }
1021
+ /** Read + validate the persisted settings. Null = never saved / unreadable
1022
+ * (callers fall back to capability-based defaults). */
1023
+ function loadVoiceSettings() {
1024
+ const raw = safeLocalStorage()?.getItem(STORAGE_KEY);
1025
+ if (!raw) return null;
1026
+ try {
1027
+ const parsed = JSON.parse(raw);
1028
+ const stt = readSection(parsed.stt);
1029
+ const tts = readSection(parsed.tts);
1030
+ if (!stt || !tts) return null;
1031
+ return {
1032
+ version: 1,
1033
+ stt,
1034
+ tts
1035
+ };
1036
+ } catch {
1037
+ return null;
1038
+ }
1039
+ }
1040
+ //#endregion
1041
+ //#region src/lib/voice/providers.ts
1042
+ /**
1043
+ * Browser-side speech-provider transport.
1044
+ *
1045
+ * The chat client owns its TTS/STT provider choice and calls the provider's
1046
+ * OpenAI-shaped /v1/audio endpoints from the browser — there is no
1047
+ * config-holding relay anymore (the old /api/speak and /api/transcribe
1048
+ * proxies read host-global stack.env config, which conflated per-device
1049
+ * preference with host state). Two transports:
1050
+ *
1051
+ * - 'openpalm-voice' → the SAME-ORIGIN `/voice` pass-through the host
1052
+ * advertises in the runtime handshake. Same-origin
1053
+ * means no CORS and no exposed container port; the
1054
+ * session cookie rides along automatically
1055
+ * (fetch's default same-origin credentials mode).
1056
+ * - 'openai-compatible' → the user's configured endpoint, called directly
1057
+ * with the API key held in the browser's encrypted
1058
+ * secret store — the same trust model as
1059
+ * connection passwords.
1060
+ *
1061
+ * "OpenPalm Voice" resolution: the handshake's `voice.url` (present when the
1062
+ * host process can serve the pass-through and the addon is enabled). We
1063
+ * fetch the handshake lazily (once per page load; `refreshAdvertisedVoiceUrl`
1064
+ * re-probes) instead of reading the reactive runtime-context store, so
1065
+ * resolution works regardless of layout-mount ordering and in non-component
1066
+ * callers.
1067
+ */
1068
+ var OPENPALM_VOICE_TTS_MODEL = "kokoro";
1069
+ var OPENPALM_VOICE_STT_MODEL = "whisper-1";
1070
+ var UPSTREAM_TIMEOUT_MS = 6e4;
1071
+ var HANDSHAKE_TIMEOUT_MS = 5e3;
1072
+ var advertisedUrl;
1073
+ var advertisedFetch = null;
1074
+ async function fetchAdvertisedUrl() {
1075
+ try {
1076
+ const res = await fetch("/api/runtime", {
1077
+ headers: { accept: "application/json" },
1078
+ credentials: "omit",
1079
+ cache: "no-store",
1080
+ signal: AbortSignal.timeout(HANDSHAKE_TIMEOUT_MS)
1081
+ });
1082
+ if (!res.ok) return null;
1083
+ const data = await res.json();
1084
+ return typeof data.voice?.url === "string" && data.voice.url ? data.voice.url : null;
1085
+ } catch {
1086
+ return null;
1087
+ }
1088
+ }
1089
+ function startAdvertisedFetch() {
1090
+ const inFlight = fetchAdvertisedUrl().then((url) => {
1091
+ {
1092
+ advertisedUrl = url;
1093
+ advertisedFetch = null;
1094
+ }
1095
+ return url;
1096
+ });
1097
+ advertisedFetch = inFlight;
1098
+ return inFlight;
1099
+ }
1100
+ /**
1101
+ * The host's advertised voice pass-through URL, or null when the voice addon
1102
+ * is disabled / the handshake is unreachable. Cached between refreshes;
1103
+ * concurrent callers share one fetch. `initVoice` refreshes on every run (a
1104
+ * cheap same-origin GET), so an addon toggle is picked up on the next chat
1105
+ * mount without a hard reload.
1106
+ */
1107
+ function advertisedVoiceUrl() {
1108
+ if (advertisedUrl !== void 0) return Promise.resolve(advertisedUrl);
1109
+ return advertisedFetch ?? startAdvertisedFetch();
1110
+ }
1111
+ async function apiKeyFor(secretRef) {
1112
+ if (!secretRef) return void 0;
1113
+ try {
1114
+ return (await getSecretStore().get(secretRef))?.password || void 0;
1115
+ } catch {
1116
+ return;
1117
+ }
1118
+ }
1119
+ /**
1120
+ * The advertised OpenPalm Voice pass-through target, or null when the host
1121
+ * offers none. Model is fixed by the container; `voice` is deliberately
1122
+ * omitted so the host's configured default (OP_VOICE_KOKORO_VOICE) applies.
1123
+ */
1124
+ async function openpalmVoiceTarget(section, kind) {
1125
+ const url = await advertisedVoiceUrl();
1126
+ if (!url) return null;
1127
+ return {
1128
+ baseURL: url,
1129
+ model: kind === "tts" ? OPENPALM_VOICE_TTS_MODEL : OPENPALM_VOICE_STT_MODEL,
1130
+ language: kind === "stt" ? section?.language : void 0
1131
+ };
1132
+ }
1133
+ async function resolveTarget(section, kind) {
1134
+ const provider = section?.provider;
1135
+ if (!provider) return openpalmVoiceTarget(section, kind);
1136
+ if (provider === "openpalm-voice") return openpalmVoiceTarget(section, kind);
1137
+ if (provider === "openai-compatible") {
1138
+ const baseURL = section?.baseURL?.trim();
1139
+ if (!baseURL) return null;
1140
+ return {
1141
+ baseURL,
1142
+ model: section?.model?.trim() || (kind === "tts" ? "tts-1" : "whisper-1"),
1143
+ voice: kind === "tts" ? section?.voice?.trim() : void 0,
1144
+ language: kind === "stt" ? section?.language : void 0,
1145
+ apiKey: await apiKeyFor(section?.secretRef)
1146
+ };
1147
+ }
1148
+ return null;
1149
+ }
1150
+ function resolveTtsTarget() {
1151
+ return resolveTarget(loadVoiceSettings()?.tts, "tts");
1152
+ }
1153
+ /**
1154
+ * Resolve the OpenAI-shaped API base from the user's configured endpoint.
1155
+ *
1156
+ * OpenAI and every compatible service (OpenRouter, Groq, LM Studio, vLLM,
1157
+ * Ollama, …) document a `base_url` that already ends in a version segment —
1158
+ * almost always `/v1`. We respect a version the user supplied and add `/v1`
1159
+ * only when absent, so pasting the provider's documented base URL Just
1160
+ * Works whether or not it includes `/v1` (no double `/v1/v1`, no hint to
1161
+ * remember). The openpalm-voice pass-through base (`/voice`) has no version,
1162
+ * so it also gets `/v1`, matching the container's `/v1/audio/*` surface.
1163
+ *
1164
+ * Sub-paths are then appended WITHOUT a leading `/v1` (e.g. `/audio/speech`).
1165
+ */
1166
+ function openaiApiBase(baseURL) {
1167
+ const trimmed = baseURL.replace(/\/+$/, "");
1168
+ return /\/v\d+$/.test(trimmed) ? trimmed : `${trimmed}/v1`;
1169
+ }
1170
+ /**
1171
+ * Synthesize speech for `text` against the configured TTS provider
1172
+ * (OpenAI-shape POST /v1/audio/speech). Returns the raw Response (audio
1173
+ * bytes on 200) or null when no server-side TTS provider is configured;
1174
+ * network failures reject.
1175
+ */
1176
+ async function synthesize(text, opts) {
1177
+ const target = await resolveTtsTarget();
1178
+ if (!target) return null;
1179
+ const headers = { "content-type": "application/json" };
1180
+ if (target.apiKey) headers.authorization = `Bearer ${target.apiKey}`;
1181
+ return fetch(`${openaiApiBase(target.baseURL)}/audio/speech`, {
1182
+ method: "POST",
1183
+ headers,
1184
+ body: JSON.stringify({
1185
+ model: target.model,
1186
+ input: text,
1187
+ ...target.voice ? { voice: target.voice } : {},
1188
+ response_format: "wav"
1189
+ }),
1190
+ signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS)
1191
+ });
1192
+ }
1193
+ //#endregion
1194
+ //#region src/lib/voice/speakable-text.ts
1195
+ /**
1196
+ * Deterministic markdown-to-speech text stripping. Pure and dependency-free
1197
+ * so both the browser TTS fallback (audio-playback.ts) and the server TTS
1198
+ * provider transport (voice/providers.ts) can run the exact same rules without
1199
+ * ever handing raw markdown syntax to a speech engine.
1200
+ *
1201
+ * Order matters: fenced code blocks and inline code are handled before any
1202
+ * other markdown stripping so their contents are never mistaken for
1203
+ * headings/emphasis/list markers. Whitespace collapsing runs last.
1204
+ */
1205
+ var HTML_ENTITIES = {
1206
+ "&amp;": "&",
1207
+ "&lt;": "<",
1208
+ "&gt;": ">",
1209
+ "&quot;": "\"",
1210
+ "&#39;": "'"
1211
+ };
1212
+ function decodeEntities(text) {
1213
+ return text.replace(/&amp;|&lt;|&gt;|&quot;|&#39;/g, (match) => HTML_ENTITIES[match] ?? match);
1214
+ }
1215
+ function urlToHostname(url) {
1216
+ try {
1217
+ return new URL(url).hostname;
1218
+ } catch {
1219
+ return url;
1220
+ }
1221
+ }
1222
+ function toSpeakableText(text) {
1223
+ let out = text;
1224
+ out = out.replace(/```[\s\S]*?```/g, " Code omitted. ");
1225
+ out = out.replace(/`([^`]+)`/g, "$1");
1226
+ out = out.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
1227
+ out = out.replace(/\[([^\]]*)\]\([^)]*\)/g, "$1");
1228
+ out = out.replace(/https?:\/\/[^\s)<>"']+/g, (match) => urlToHostname(match));
1229
+ out = out.replace(/<[^>]+>/g, "");
1230
+ out = out.replace(/^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/gm, "");
1231
+ const keptLines = [];
1232
+ for (const line of out.split("\n")) {
1233
+ let l = line;
1234
+ if (/^\s*\|?[\s:|-]+\|?\s*$/.test(l) && l.includes("-") && l.includes("|")) continue;
1235
+ l = l.replace(/^\s*>\s?/, "");
1236
+ l = l.replace(/^\s*#{1,6}\s+/, "");
1237
+ const wasListItem = /^\s*(?:[-*+]|\d+\.)\s+/.test(l);
1238
+ l = l.replace(/^\s*(?:[-*+]|\d+\.)\s+/, "");
1239
+ if (l.includes("|")) l = l.replace(/^\s*\|/, "").replace(/\|\s*$/, "").split("|").map((cell) => cell.trim()).join(", ");
1240
+ l = l.trim();
1241
+ if (wasListItem && l && !/[.!?:]$/.test(l)) l += ".";
1242
+ keptLines.push(l);
1243
+ }
1244
+ out = keptLines.join("\n");
1245
+ out = out.replace(/~~(.+?)~~/g, "$1");
1246
+ out = out.replace(/\*\*(.+?)\*\*/g, "$1");
1247
+ out = out.replace(/__(.+?)__/g, "$1");
1248
+ out = out.replace(/\*(.+?)\*/g, "$1");
1249
+ out = out.replace(/(?<![A-Za-z0-9_])_(.+?)_(?![A-Za-z0-9_])/g, "$1");
1250
+ out = decodeEntities(out);
1251
+ out = out.replace(/<\/?[A-Za-z][A-Za-z0-9-]*(?:\s[^<>]*)?\/?>/g, "");
1252
+ out = out.replace(/\n{3,}/g, "\n\n");
1253
+ out = out.replace(/[^\S\n]{2,}/g, " ");
1254
+ return out.trim();
1255
+ }
1256
+ //#endregion
1257
+ //#region src/lib/voice/audio-playback.ts
1258
+ /**
1259
+ * AudioPlaybackController — the imperative TTS audio engine extracted from
1260
+ * voice-state.svelte.ts. Owns the speak queue, the HTMLAudioElement +
1261
+ * blob-URL lifecycle, the browser autoplay-policy fallback, and the
1262
+ * per-utterance playback (playOne). The reactive `voiceState` store
1263
+ * composes an instance of this and delegates speak/resume/stop to it.
1264
+ *
1265
+ * The controller never holds reactive `$state` itself — it mutates the
1266
+ * host store's reactive fields (status / errorMessage / autoplayBlocked)
1267
+ * through the `AudioPlaybackHost` it is constructed with, exactly as the
1268
+ * old module-global engine mutated `voiceState` directly.
1269
+ *
1270
+ * Only touch browser APIs (window, Audio, AudioContext, speechSynthesis)
1271
+ * from methods — never at construction — for SSR safety.
1272
+ */
1273
+ var SPEAK_QUEUE_MAX = 20;
1274
+ var AudioPlaybackController = class {
1275
+ host;
1276
+ /**
1277
+ * Optional hook fired when the speak queue fully drains (the last
1278
+ * utterance reached a terminal state with nothing queued behind it).
1279
+ * Conversation mode uses this to re-arm listening — an explicit
1280
+ * callback instead of polling reactive status. Deliberately NOT fired
1281
+ * from stop(): an explicit stop (barge-in, toggle off) must not re-arm
1282
+ * anything by itself.
1283
+ */
1284
+ onQueueDrained = null;
1285
+ activeAudio = null;
1286
+ activeAudioUrl = null;
1287
+ speakQueue = [];
1288
+ busy = false;
1289
+ generation = 0;
1290
+ overflowNoticed = false;
1291
+ pendingAutoplayAudio = null;
1292
+ pendingAutoplayUrl = null;
1293
+ constructor(host) {
1294
+ this.host = host;
1295
+ }
1296
+ /**
1297
+ * Play a 1-frame silent AudioBuffer through a transient AudioContext to
1298
+ * register the current user gesture with the browser's autoplay policy.
1299
+ * Safe to call repeatedly; failures are swallowed.
1300
+ */
1301
+ primeForAutoplay() {
1302
+ if (typeof window === "undefined") return;
1303
+ const Ctor = window.AudioContext ?? window.webkitAudioContext;
1304
+ if (!Ctor) return;
1305
+ try {
1306
+ const ctx = new Ctor();
1307
+ const buffer = ctx.createBuffer(1, 1, 22050);
1308
+ const source = ctx.createBufferSource();
1309
+ source.buffer = buffer;
1310
+ source.connect(ctx.destination);
1311
+ source.start(0);
1312
+ setTimeout(() => {
1313
+ ctx.close().catch(() => {});
1314
+ }, 100);
1315
+ } catch {}
1316
+ }
1317
+ teardownActiveAudio() {
1318
+ if (this.activeAudio) {
1319
+ this.activeAudio.onerror = null;
1320
+ this.activeAudio.onended = null;
1321
+ try {
1322
+ this.activeAudio.pause();
1323
+ } catch {}
1324
+ this.activeAudio.src = "";
1325
+ this.activeAudio = null;
1326
+ }
1327
+ if (this.activeAudioUrl) {
1328
+ URL.revokeObjectURL(this.activeAudioUrl);
1329
+ this.activeAudioUrl = null;
1330
+ }
1331
+ }
1332
+ teardownPendingAutoplay() {
1333
+ if (this.pendingAutoplayAudio) {
1334
+ this.pendingAutoplayAudio.onerror = null;
1335
+ this.pendingAutoplayAudio.onended = null;
1336
+ try {
1337
+ this.pendingAutoplayAudio.pause();
1338
+ } catch {}
1339
+ this.pendingAutoplayAudio.src = "";
1340
+ this.pendingAutoplayAudio = null;
1341
+ }
1342
+ if (this.pendingAutoplayUrl) {
1343
+ URL.revokeObjectURL(this.pendingAutoplayUrl);
1344
+ this.pendingAutoplayUrl = null;
1345
+ }
1346
+ this.host.autoplayBlocked = false;
1347
+ }
1348
+ /**
1349
+ * User clicked the "click to resume" banner — promote the stashed audio
1350
+ * to the active slot and play. Called from VoiceControl's banner button;
1351
+ * the click on the button itself satisfies the autoplay-policy gesture
1352
+ * requirement.
1353
+ */
1354
+ resume() {
1355
+ const a = this.pendingAutoplayAudio;
1356
+ if (!a) {
1357
+ this.host.autoplayBlocked = false;
1358
+ return;
1359
+ }
1360
+ this.host.autoplayBlocked = false;
1361
+ this.host.errorMessage = "";
1362
+ this.host.status = "speaking";
1363
+ this.busy = true;
1364
+ this.activeAudio = a;
1365
+ this.activeAudioUrl = this.pendingAutoplayUrl;
1366
+ this.pendingAutoplayAudio = null;
1367
+ this.pendingAutoplayUrl = null;
1368
+ a.play().catch(() => {
1369
+ this.host.status = "idle";
1370
+ this.host.errorMessage = "Audio playback failed.";
1371
+ this.teardownActiveAudio();
1372
+ this.drainNext();
1373
+ });
1374
+ }
1375
+ /**
1376
+ * Read text aloud. Tries server-side TTS via the provider transport first (when the
1377
+ * configured engine is openpalm-voice or remote); falls back to browser
1378
+ * speech synthesis. Silent no-op if neither path is available.
1379
+ *
1380
+ * If a previous utterance is still synthesizing, playing, or stashed
1381
+ * behind an autoplay block, queues this one (FIFO, cap 20) instead of
1382
+ * cutting it off mid-sentence.
1383
+ */
1384
+ async speak(text) {
1385
+ if (typeof window === "undefined" || !text.trim()) return;
1386
+ if (this.busy) {
1387
+ this.speakQueue.push(text);
1388
+ let dropped = 0;
1389
+ while (this.speakQueue.length > SPEAK_QUEUE_MAX) {
1390
+ this.speakQueue.shift();
1391
+ dropped += 1;
1392
+ }
1393
+ if (dropped > 0 && !this.overflowNoticed) {
1394
+ this.overflowNoticed = true;
1395
+ notifications.push("info", `Skipped ${dropped} spoken ${dropped === 1 ? "reply" : "replies"} — too much overlap. Lower the auto-speak chat rate.`);
1396
+ }
1397
+ return;
1398
+ }
1399
+ await this.playOne(text);
1400
+ }
1401
+ /**
1402
+ * Advance the pump: play the next queued utterance, or release the busy
1403
+ * flag so a future speak() can start a fresh burst. Every terminal path
1404
+ * of an utterance must land here (or hold `busy` deliberately, as the
1405
+ * autoplay-block stash does).
1406
+ */
1407
+ drainNext() {
1408
+ const next = this.speakQueue.shift();
1409
+ if (next) this.playOne(next);
1410
+ else {
1411
+ this.busy = false;
1412
+ this.overflowNoticed = false;
1413
+ this.onQueueDrained?.();
1414
+ }
1415
+ }
1416
+ /** Internal: actually trigger the audio for one text chunk. */
1417
+ async playOne(text) {
1418
+ if (typeof window === "undefined") return;
1419
+ this.busy = true;
1420
+ const gen = this.generation;
1421
+ const speakableText = toSpeakableText(text);
1422
+ if (!speakableText) {
1423
+ this.drainNext();
1424
+ return;
1425
+ }
1426
+ this.teardownActiveAudio();
1427
+ if ("speechSynthesis" in window) window.speechSynthesis.cancel();
1428
+ this.host.errorMessage = "";
1429
+ const engine = this.host.ttsEngine;
1430
+ const useServer = engine === "openpalm-voice" || engine === "remote";
1431
+ if (useServer) {
1432
+ let res;
1433
+ try {
1434
+ res = await synthesize(speakableText);
1435
+ } catch {}
1436
+ if (gen !== this.generation) return;
1437
+ if (res?.ok && res.headers.get("content-type")?.startsWith("audio/")) {
1438
+ const blob = await res.blob();
1439
+ if (gen !== this.generation) return;
1440
+ const url = URL.createObjectURL(blob);
1441
+ const audio = new Audio(url);
1442
+ this.activeAudio = audio;
1443
+ this.activeAudioUrl = url;
1444
+ audio.onended = () => {
1445
+ this.host.status = "idle";
1446
+ this.teardownActiveAudio();
1447
+ this.drainNext();
1448
+ };
1449
+ audio.onerror = () => {
1450
+ this.host.status = "idle";
1451
+ this.host.errorMessage = "Audio playback failed.";
1452
+ this.teardownActiveAudio();
1453
+ this.drainNext();
1454
+ };
1455
+ this.host.status = "speaking";
1456
+ try {
1457
+ await audio.play();
1458
+ } catch {
1459
+ this.host.status = "idle";
1460
+ this.pendingAutoplayAudio = audio;
1461
+ this.pendingAutoplayUrl = url;
1462
+ this.activeAudio = null;
1463
+ this.activeAudioUrl = null;
1464
+ this.host.autoplayBlocked = true;
1465
+ }
1466
+ return;
1467
+ }
1468
+ if (res && !res.ok) {
1469
+ const errMsg = await this.extractSpeakError(res);
1470
+ this.host.errorMessage = errMsg;
1471
+ }
1472
+ }
1473
+ if (!("speechSynthesis" in window)) {
1474
+ this.drainNext();
1475
+ return;
1476
+ }
1477
+ if (useServer) this.host.errorMessage = "";
1478
+ const utterance = new SpeechSynthesisUtterance(speakableText);
1479
+ utterance.onstart = () => {
1480
+ if (gen !== this.generation) return;
1481
+ this.host.status = "speaking";
1482
+ };
1483
+ utterance.onend = () => {
1484
+ if (gen !== this.generation) return;
1485
+ this.host.status = "idle";
1486
+ this.drainNext();
1487
+ };
1488
+ utterance.onerror = () => {
1489
+ if (gen !== this.generation) return;
1490
+ this.host.status = "idle";
1491
+ this.drainNext();
1492
+ };
1493
+ window.speechSynthesis.speak(utterance);
1494
+ }
1495
+ /**
1496
+ * Convert a non-OK synthesis response into a human-readable string.
1497
+ * Recognises the /voice pass-through's structured codes; any other 5xx
1498
+ * (a provider whose model is still loading) reads as "warming up".
1499
+ */
1500
+ async extractSpeakError(res) {
1501
+ let code;
1502
+ try {
1503
+ const data = await res.clone().json();
1504
+ if (typeof data.error === "string") code = data.error;
1505
+ } catch {}
1506
+ if (code === "voice_unavailable") return "OpenPalm Voice is not enabled on this host.";
1507
+ if (code === "voice_unreachable" || res.status >= 500) return "Voice engine is warming up — try again in a moment.";
1508
+ return `TTS failed (HTTP ${res.status}).`;
1509
+ }
1510
+ /** Cancel speech synthesis. Drops the entire queue. */
1511
+ stop() {
1512
+ this.speakQueue.length = 0;
1513
+ this.busy = false;
1514
+ this.generation += 1;
1515
+ this.overflowNoticed = false;
1516
+ this.teardownPendingAutoplay();
1517
+ this.teardownActiveAudio();
1518
+ if (typeof window !== "undefined" && "speechSynthesis" in window) window.speechSynthesis.cancel();
1519
+ this.host.status = "idle";
1520
+ }
1521
+ };
1522
+ var VoiceState = class {
1523
+ status = "idle";
1524
+ /** True when the configured STT engine is actually usable from this browser. */
1525
+ sttSupported = false;
1526
+ ttsSupported = false;
1527
+ errorMessage = "";
1528
+ /** Partial transcript text while browser STT is mid-utterance. Cleared on stop/error. */
1529
+ interimTranscript = "";
1530
+ /** Active engine resolved from the client-owned voice settings. */
1531
+ sttEngine = "disabled";
1532
+ ttsEngine = "disabled";
1533
+ /** Optional language hint (forwarded to the STT provider). */
1534
+ sttLanguage = "";
1535
+ /** Global toggle: when true, assistant chat replies are spoken automatically. */
1536
+ ttsAutoEnabled = false;
1537
+ /**
1538
+ * True when an audio.play() was rejected by the browser's autoplay
1539
+ * policy and we have a pending utterance waiting for a user gesture.
1540
+ * The chat UI renders a small "click to resume" banner; clicking it
1541
+ * calls resumeAutoplay() to actually play.
1542
+ */
1543
+ autoplayBlocked = false;
1544
+ /**
1545
+ * True while hands-free conversation mode owns the mic (the chat page's
1546
+ * listen → deliver → speak → listen loop). `status` keeps cycling
1547
+ * through the normal VoiceStatus values while this is set.
1548
+ */
1549
+ conversationActive = false;
1550
+ /**
1551
+ * Set when the configured STT engine is technically present in the
1552
+ * window but known to fail at runtime on this UA (e.g. iOS Safari
1553
+ * exposes SpeechRecognition but `start()` immediately errors with
1554
+ * `service-not-allowed`). The Voice settings tab uses this to hide or
1555
+ * disable the Browser STT card with the reason as a tooltip.
1556
+ */
1557
+ browserSttUnsupportedReason = "";
1558
+ };
1559
+ var voiceState = new VoiceState();
1560
+ /**
1561
+ * The imperative TTS audio engine (speak queue, blob-URL lifecycle,
1562
+ * autoplay fallback, playOne). The reactive store composes it and
1563
+ * delegates the exported speak/resume/stop wrappers below to it; the
1564
+ * controller mutates `voiceState`'s reactive fields in place.
1565
+ */
1566
+ var audioPlayback = new AudioPlaybackController(voiceState);
1567
+ audioPlayback.onQueueDrained = () => {
1568
+ if (voiceState.conversationActive && voiceState.status === "idle") voiceState.status = "recording";
1569
+ };
1570
+ /** Exit conversation mode and tear down the listening loop (whichever engine). */
1571
+ function stopConversation() {
1572
+ if (!voiceState.conversationActive) return;
1573
+ voiceState.conversationActive = false;
1574
+ voiceState.interimTranscript = "";
1575
+ if (voiceState.status === "recording" || voiceState.status === "transcribing") voiceState.status = "idle";
1576
+ }
1577
+ /**
1578
+ * Read text aloud. Tries server-side TTS via the provider transport first (when the
1579
+ * configured engine is openpalm-voice or remote); falls back to browser
1580
+ * speech synthesis. Silent no-op if neither path is available.
1581
+ *
1582
+ * If a previous utterance is still playing, queues this one (FIFO, cap 20)
1583
+ * instead of cutting it off mid-sentence.
1584
+ */
1585
+ function speakText(text) {
1586
+ return audioPlayback.speak(text);
1587
+ }
1588
+ /** Cancel speech synthesis. Drops the entire queue. */
1589
+ function stopSpeaking() {
1590
+ audioPlayback.stop();
1591
+ }
1592
+ /**
1593
+ * Tear down per-component voice resources on unmount. Only cancels
1594
+ * any in-flight recording / recognition (including the conversation
1595
+ * loop).
1596
+ *
1597
+ * Deliberately does NOT cancel `speechSynthesis` — that queue is a
1598
+ * window-level singleton and the user's auto-TTS toggle is persistent,
1599
+ * so a page navigation must not interrupt the assistant mid-utterance.
1600
+ * Explicit user actions (logout, mic click, toggle off) call
1601
+ * `stopSpeaking` directly.
1602
+ */
1603
+ function destroyVoice() {
1604
+ stopConversation();
1605
+ voiceState.interimTranscript = "";
1606
+ voiceState.status = "idle";
1607
+ }
1608
+
1609
+ export { getTransport as a, speakText as b, stopSpeaking as c, destroyVoice as d, subscribeSessionEvents as e, getConnectionStore as g, isLoopbackHost as i, loadRuntimeConfig as l, notifications as n, randomId as r, setActiveConnection as s, themeService as t, voiceState as v };
1610
+ //# sourceMappingURL=voice-state.svelte-DU9g_xEh.js.map