@juspay/shooter 1.5.0 → 1.6.1

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 (478) hide show
  1. package/README.md +24 -20
  2. package/bin/shooter.cjs +68 -17
  3. package/build/client/_app/immutable/assets/2.Dk9NfqnS.css +1 -0
  4. package/build/client/_app/immutable/assets/2.Dk9NfqnS.css.br +0 -0
  5. package/build/client/_app/immutable/assets/2.Dk9NfqnS.css.gz +0 -0
  6. package/build/client/_app/immutable/assets/3.DHxQoulp.css +1 -0
  7. package/build/client/_app/immutable/assets/3.DHxQoulp.css.br +0 -0
  8. package/build/client/_app/immutable/assets/3.DHxQoulp.css.gz +0 -0
  9. package/build/client/_app/immutable/assets/{3.DGDHCVnW.css → 4.D5l1JxgO.css} +1 -1
  10. package/build/client/_app/immutable/assets/4.D5l1JxgO.css.br +0 -0
  11. package/build/client/_app/immutable/assets/4.D5l1JxgO.css.gz +0 -0
  12. package/build/client/_app/immutable/assets/5.C5qz-NeI.css +1 -0
  13. package/build/client/_app/immutable/assets/5.C5qz-NeI.css.br +0 -0
  14. package/build/client/_app/immutable/assets/5.C5qz-NeI.css.gz +0 -0
  15. package/build/client/_app/immutable/chunks/1mEchsPO.js +1 -0
  16. package/build/client/_app/immutable/chunks/1mEchsPO.js.br +0 -0
  17. package/build/client/_app/immutable/chunks/1mEchsPO.js.gz +0 -0
  18. package/build/client/_app/immutable/chunks/B7X-vhXI.js +1 -0
  19. package/build/client/_app/immutable/chunks/B7X-vhXI.js.br +0 -0
  20. package/build/client/_app/immutable/chunks/B7X-vhXI.js.gz +0 -0
  21. package/build/client/_app/immutable/chunks/BRkqKgVG.js +1 -0
  22. package/build/client/_app/immutable/chunks/BRkqKgVG.js.br +0 -0
  23. package/build/client/_app/immutable/chunks/BRkqKgVG.js.gz +0 -0
  24. package/build/client/_app/immutable/chunks/BfJ-f-Tu.js +1 -0
  25. package/build/client/_app/immutable/chunks/BfJ-f-Tu.js.br +2 -0
  26. package/build/client/_app/immutable/chunks/BfJ-f-Tu.js.gz +0 -0
  27. package/build/client/_app/immutable/chunks/CGMJxf7r.js +1 -0
  28. package/build/client/_app/immutable/chunks/CGMJxf7r.js.br +0 -0
  29. package/build/client/_app/immutable/chunks/CGMJxf7r.js.gz +0 -0
  30. package/build/client/_app/immutable/chunks/{CZHsSL_X.js → CJFjKwJ7.js} +1 -1
  31. package/build/client/_app/immutable/chunks/CJFjKwJ7.js.br +0 -0
  32. package/build/client/_app/immutable/chunks/CJFjKwJ7.js.gz +0 -0
  33. package/build/client/_app/immutable/chunks/CNH2HlKj.js +20 -0
  34. package/build/client/_app/immutable/chunks/CNH2HlKj.js.br +0 -0
  35. package/build/client/_app/immutable/chunks/CNH2HlKj.js.gz +0 -0
  36. package/build/client/_app/immutable/chunks/CR6bkGJW.js +6 -0
  37. package/build/client/_app/immutable/chunks/CR6bkGJW.js.br +0 -0
  38. package/build/client/_app/immutable/chunks/CR6bkGJW.js.gz +0 -0
  39. package/build/client/_app/immutable/chunks/CVtJ6yRM.js +1 -0
  40. package/build/client/_app/immutable/chunks/CVtJ6yRM.js.br +0 -0
  41. package/build/client/_app/immutable/chunks/CVtJ6yRM.js.gz +0 -0
  42. package/build/client/_app/immutable/chunks/{CSoRdFvv.js → CaiJSUi3.js} +1 -1
  43. package/build/client/_app/immutable/chunks/CaiJSUi3.js.br +0 -0
  44. package/build/client/_app/immutable/chunks/CaiJSUi3.js.gz +0 -0
  45. package/build/client/_app/immutable/chunks/{DjsDGxCa.js → CmczWE_d.js} +4 -4
  46. package/build/client/_app/immutable/chunks/CmczWE_d.js.br +0 -0
  47. package/build/client/_app/immutable/chunks/CmczWE_d.js.gz +0 -0
  48. package/build/client/_app/immutable/chunks/CsgHjHGZ.js +1 -0
  49. package/build/client/_app/immutable/chunks/CsgHjHGZ.js.br +0 -0
  50. package/build/client/_app/immutable/chunks/CsgHjHGZ.js.gz +0 -0
  51. package/build/client/_app/immutable/chunks/{UJOiqIYE.js → CtrCjGZT.js} +1 -1
  52. package/build/client/_app/immutable/chunks/CtrCjGZT.js.br +0 -0
  53. package/build/client/_app/immutable/chunks/CtrCjGZT.js.gz +0 -0
  54. package/build/client/_app/immutable/chunks/DDiOVAd8.js +61 -0
  55. package/build/client/_app/immutable/chunks/DDiOVAd8.js.br +0 -0
  56. package/build/client/_app/immutable/chunks/DDiOVAd8.js.gz +0 -0
  57. package/build/client/_app/immutable/chunks/DVl0sebP.js +2 -0
  58. package/build/client/_app/immutable/chunks/DVl0sebP.js.br +0 -0
  59. package/build/client/_app/immutable/chunks/DVl0sebP.js.gz +0 -0
  60. package/build/client/_app/immutable/chunks/{CiF38mQq.js → Dc_Gg2H6.js} +1 -1
  61. package/build/client/_app/immutable/chunks/Dc_Gg2H6.js.br +0 -0
  62. package/build/client/_app/immutable/chunks/Dc_Gg2H6.js.gz +0 -0
  63. package/build/client/_app/immutable/chunks/{CRbaG9cv.js → DlnAjkg1.js} +1 -1
  64. package/build/client/_app/immutable/chunks/DlnAjkg1.js.br +0 -0
  65. package/build/client/_app/immutable/chunks/{CRbaG9cv.js.gz → DlnAjkg1.js.gz} +0 -0
  66. package/build/client/_app/immutable/chunks/YKoRJzXZ.js +3 -0
  67. package/build/client/_app/immutable/chunks/YKoRJzXZ.js.br +0 -0
  68. package/build/client/_app/immutable/chunks/YKoRJzXZ.js.gz +0 -0
  69. package/build/client/_app/immutable/chunks/gQJcRhou.js +1 -0
  70. package/build/client/_app/immutable/chunks/gQJcRhou.js.br +0 -0
  71. package/build/client/_app/immutable/chunks/gQJcRhou.js.gz +0 -0
  72. package/build/client/_app/immutable/chunks/pRcLbE0d.js +1 -0
  73. package/build/client/_app/immutable/chunks/pRcLbE0d.js.br +0 -0
  74. package/build/client/_app/immutable/chunks/pRcLbE0d.js.gz +0 -0
  75. package/build/client/_app/immutable/entry/app.CFPgQOa8.js +2 -0
  76. package/build/client/_app/immutable/entry/app.CFPgQOa8.js.br +0 -0
  77. package/build/client/_app/immutable/entry/app.CFPgQOa8.js.gz +0 -0
  78. package/build/client/_app/immutable/entry/start.BnJOVqhI.js +1 -0
  79. package/build/client/_app/immutable/entry/start.BnJOVqhI.js.br +2 -0
  80. package/build/client/_app/immutable/entry/start.BnJOVqhI.js.gz +0 -0
  81. package/build/client/_app/immutable/nodes/0.DR-BBF5r.js +1 -0
  82. package/build/client/_app/immutable/nodes/0.DR-BBF5r.js.br +0 -0
  83. package/build/client/_app/immutable/nodes/0.DR-BBF5r.js.gz +0 -0
  84. package/build/client/_app/immutable/nodes/1.CNm6rAwf.js +1 -0
  85. package/build/client/_app/immutable/nodes/1.CNm6rAwf.js.br +0 -0
  86. package/build/client/_app/immutable/nodes/1.CNm6rAwf.js.gz +0 -0
  87. package/build/client/_app/immutable/nodes/2.B08usYzr.js +13 -0
  88. package/build/client/_app/immutable/nodes/2.B08usYzr.js.br +0 -0
  89. package/build/client/_app/immutable/nodes/2.B08usYzr.js.gz +0 -0
  90. package/build/client/_app/immutable/nodes/3.CsY6J5HS.js +9 -0
  91. package/build/client/_app/immutable/nodes/3.CsY6J5HS.js.br +0 -0
  92. package/build/client/_app/immutable/nodes/3.CsY6J5HS.js.gz +0 -0
  93. package/build/client/_app/immutable/nodes/4.B_pbOZoD.js +4 -0
  94. package/build/client/_app/immutable/nodes/4.B_pbOZoD.js.br +0 -0
  95. package/build/client/_app/immutable/nodes/4.B_pbOZoD.js.gz +0 -0
  96. package/build/client/_app/immutable/nodes/5.CdLPNo5-.js +1 -0
  97. package/build/client/_app/immutable/nodes/5.CdLPNo5-.js.br +0 -0
  98. package/build/client/_app/immutable/nodes/5.CdLPNo5-.js.gz +0 -0
  99. package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js +1 -0
  100. package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js.br +0 -0
  101. package/build/client/_app/immutable/nodes/6.CbQQ3FtZ.js.gz +0 -0
  102. package/build/client/_app/immutable/nodes/{5.DIkXVP4q.js → 7.CCKgiNNk.js} +3 -3
  103. package/build/client/_app/immutable/nodes/7.CCKgiNNk.js.br +0 -0
  104. package/build/client/_app/immutable/nodes/7.CCKgiNNk.js.gz +0 -0
  105. package/build/client/_app/immutable/nodes/8.C7AaheUD.js +2 -0
  106. package/build/client/_app/immutable/nodes/8.C7AaheUD.js.br +0 -0
  107. package/build/client/_app/immutable/nodes/8.C7AaheUD.js.gz +0 -0
  108. package/build/client/_app/immutable/nodes/9.DfL9kMC4.js +2 -0
  109. package/build/client/_app/immutable/nodes/9.DfL9kMC4.js.br +0 -0
  110. package/build/client/_app/immutable/nodes/9.DfL9kMC4.js.gz +0 -0
  111. package/build/client/_app/version.json +1 -1
  112. package/build/client/_app/version.json.br +0 -0
  113. package/build/client/_app/version.json.gz +0 -0
  114. package/build/server/chunks/0-DC2VLooL.js +23 -0
  115. package/build/server/chunks/0-DC2VLooL.js.map +1 -0
  116. package/build/server/chunks/1-XJaf8Jvf.js +9 -0
  117. package/build/server/chunks/{1-D0N7vVhH.js.map → 1-XJaf8Jvf.js.map} +1 -1
  118. package/build/server/chunks/2-D4Cx-1QL.js +21 -0
  119. package/build/server/chunks/2-D4Cx-1QL.js.map +1 -0
  120. package/build/server/chunks/3-CVhIEP-u.js +21 -0
  121. package/build/server/chunks/3-CVhIEP-u.js.map +1 -0
  122. package/build/server/chunks/4-0UE_6Ep-.js +23 -0
  123. package/build/server/chunks/4-0UE_6Ep-.js.map +1 -0
  124. package/build/server/chunks/5-BBIP1PzX.js +24 -0
  125. package/build/server/chunks/5-BBIP1PzX.js.map +1 -0
  126. package/build/server/chunks/6-QFSbzRMP.js +9 -0
  127. package/build/server/chunks/6-QFSbzRMP.js.map +1 -0
  128. package/build/server/chunks/7-CZ_YGjMV.js +9 -0
  129. package/build/server/chunks/7-CZ_YGjMV.js.map +1 -0
  130. package/build/server/chunks/8-Xe2Rugb4.js +9 -0
  131. package/build/server/chunks/8-Xe2Rugb4.js.map +1 -0
  132. package/build/server/chunks/9-IwHpC4SO.js +9 -0
  133. package/build/server/chunks/9-IwHpC4SO.js.map +1 -0
  134. package/build/server/chunks/{Button-Cs1aE6ka.js → Button-WKgiLWZI.js} +4 -9
  135. package/build/server/chunks/Button-WKgiLWZI.js.map +1 -0
  136. package/build/server/chunks/{EmptyState-DDFH1K8g.js → EmptyState-BUBqASsp.js} +3 -3
  137. package/build/server/chunks/{EmptyState-DDFH1K8g.js.map → EmptyState-BUBqASsp.js.map} +1 -1
  138. package/build/server/chunks/{Icon-CEUrotA6.js → Icon-BNBAg85a.js} +3 -3
  139. package/build/server/chunks/Icon-BNBAg85a.js.map +1 -0
  140. package/build/server/chunks/{Shimmer-DB8W1zt6.js → Shimmer-C4uBVwxz.js} +2 -2
  141. package/build/server/chunks/{Shimmer-DB8W1zt6.js.map → Shimmer-C4uBVwxz.js.map} +1 -1
  142. package/build/server/chunks/{_error.svelte-uCOJNxvr.js → _error.svelte-DkIwmECt.js} +5 -5
  143. package/build/server/chunks/{_error.svelte-uCOJNxvr.js.map → _error.svelte-DkIwmECt.js.map} +1 -1
  144. package/build/server/chunks/{_layout.svelte-CtWmEJwe.js → _layout.svelte-DllETxmJ.js} +13 -7
  145. package/build/server/chunks/_layout.svelte-DllETxmJ.js.map +1 -0
  146. package/build/server/chunks/_page.svelte-BZSdLKE_.js +118 -0
  147. package/build/server/chunks/_page.svelte-BZSdLKE_.js.map +1 -0
  148. package/build/server/chunks/{_page.svelte-CxWcQ0Am.js → _page.svelte-Cmuco1mC.js} +84 -199
  149. package/build/server/chunks/_page.svelte-Cmuco1mC.js.map +1 -0
  150. package/build/server/chunks/{_page.svelte-BgevQjq1.js → _page.svelte-Co5sF7W-.js} +12 -11
  151. package/build/server/chunks/{_page.svelte-BgevQjq1.js.map → _page.svelte-Co5sF7W-.js.map} +1 -1
  152. package/build/server/chunks/{_page.svelte-DO4oa_LY.js → _page.svelte-CpL3R-VI.js} +8 -8
  153. package/build/server/chunks/{_page.svelte-DO4oa_LY.js.map → _page.svelte-CpL3R-VI.js.map} +1 -1
  154. package/build/server/chunks/_page.svelte-DDSzYLUs.js +137 -0
  155. package/build/server/chunks/_page.svelte-DDSzYLUs.js.map +1 -0
  156. package/build/server/chunks/_page.svelte-JIkgFUFf.js +26 -0
  157. package/build/server/chunks/_page.svelte-JIkgFUFf.js.map +1 -0
  158. package/build/server/chunks/{_page.svelte-CVq6tRb3.js → _page.svelte-Y9-O5a5w.js} +10 -9
  159. package/build/server/chunks/_page.svelte-Y9-O5a5w.js.map +1 -0
  160. package/build/server/chunks/{_page.svelte-BcZaKdX9.js → _page.svelte-fcX09N4d.js} +9 -9
  161. package/build/server/chunks/{_page.svelte-BcZaKdX9.js.map → _page.svelte-fcX09N4d.js.map} +1 -1
  162. package/build/server/chunks/{_server.ts-DYpJImqd.js → _server.ts-0Xr2fWaq.js} +9 -5
  163. package/build/server/chunks/_server.ts-0Xr2fWaq.js.map +1 -0
  164. package/build/server/chunks/{_server.ts-CTpcLUH8.js → _server.ts-2ixC-X3K.js} +20 -5
  165. package/build/server/chunks/_server.ts-2ixC-X3K.js.map +1 -0
  166. package/build/server/chunks/{_server.ts-CAxsWKvS.js → _server.ts-40c_epk8.js} +20 -4
  167. package/build/server/chunks/_server.ts-40c_epk8.js.map +1 -0
  168. package/build/server/chunks/{_server.ts-WhTJBEJy.js → _server.ts-A9_tRR-K.js} +5 -4
  169. package/build/server/chunks/{_server.ts-WhTJBEJy.js.map → _server.ts-A9_tRR-K.js.map} +1 -1
  170. package/build/server/chunks/_server.ts-BRAzC6W1.js +98 -0
  171. package/build/server/chunks/_server.ts-BRAzC6W1.js.map +1 -0
  172. package/build/server/chunks/{_server.ts-DB_Kg97c.js → _server.ts-BScvgttw.js} +24 -4
  173. package/build/server/chunks/_server.ts-BScvgttw.js.map +1 -0
  174. package/build/server/chunks/{_server.ts-tSpgyl1D.js → _server.ts-Bjbr7glm.js} +4 -3
  175. package/build/server/chunks/_server.ts-Bjbr7glm.js.map +1 -0
  176. package/build/server/chunks/{_server.ts-COu0vNpd.js → _server.ts-BrqaMMAa.js} +7 -6
  177. package/build/server/chunks/_server.ts-BrqaMMAa.js.map +1 -0
  178. package/build/server/chunks/{_server.ts-vekTmWAx.js → _server.ts-BuYyCrnF.js} +6 -4
  179. package/build/server/chunks/_server.ts-BuYyCrnF.js.map +1 -0
  180. package/build/server/chunks/{_server.ts-DYvb9ijZ.js → _server.ts-ByPExYfO.js} +4 -3
  181. package/build/server/chunks/{_server.ts-DYvb9ijZ.js.map → _server.ts-ByPExYfO.js.map} +1 -1
  182. package/build/server/chunks/_server.ts-CjpQ10xh.js +123 -0
  183. package/build/server/chunks/_server.ts-CjpQ10xh.js.map +1 -0
  184. package/build/server/chunks/_server.ts-CyjDrcZN.js +21 -0
  185. package/build/server/chunks/_server.ts-CyjDrcZN.js.map +1 -0
  186. package/build/server/chunks/{_server.ts-DV8zTCF9.js → _server.ts-DOGUMzPx.js} +4 -3
  187. package/build/server/chunks/{_server.ts-DV8zTCF9.js.map → _server.ts-DOGUMzPx.js.map} +1 -1
  188. package/build/server/chunks/_server.ts-DZvfyuNj.js +15 -0
  189. package/build/server/chunks/_server.ts-DZvfyuNj.js.map +1 -0
  190. package/build/server/chunks/{_server.ts-XzT2UHM1.js → _server.ts-DkPPTUPo.js} +4 -3
  191. package/build/server/chunks/{_server.ts-XzT2UHM1.js.map → _server.ts-DkPPTUPo.js.map} +1 -1
  192. package/build/server/chunks/{_server.ts-Deok2y88.js → _server.ts-Ds_SUGC3.js} +184 -90
  193. package/build/server/chunks/_server.ts-Ds_SUGC3.js.map +1 -0
  194. package/build/server/chunks/{_server.ts-Ch-6iOHp.js → _server.ts-G8OeADGj.js} +141 -89
  195. package/build/server/chunks/_server.ts-G8OeADGj.js.map +1 -0
  196. package/build/server/chunks/{auth-DeCdZ83n.js → auth-DuunT7Cg.js} +2 -2
  197. package/build/server/chunks/{auth-DeCdZ83n.js.map → auth-DuunT7Cg.js.map} +1 -1
  198. package/build/server/chunks/{client-BdGHe_hY.js → client-DRtPDkMh.js} +4 -4
  199. package/build/server/chunks/{client-BdGHe_hY.js.map → client-DRtPDkMh.js.map} +1 -1
  200. package/build/server/chunks/client2-bqqmu0b7.js +7 -0
  201. package/build/server/chunks/{client2-CCBGA-2V.js.map → client2-bqqmu0b7.js.map} +1 -1
  202. package/build/server/chunks/close-BGlLztTb.js +192 -0
  203. package/build/server/chunks/close-BGlLztTb.js.map +1 -0
  204. package/build/server/chunks/events-handler-Dm1mNPQP.js +20 -0
  205. package/build/server/chunks/events-handler-Dm1mNPQP.js.map +1 -0
  206. package/build/server/chunks/html-FW6Ia4bL.js +8 -0
  207. package/build/server/chunks/html-FW6Ia4bL.js.map +1 -0
  208. package/build/server/chunks/{shared-server-sSGG17Df.js → index-CoD1IJuy.js} +2 -11
  209. package/build/server/chunks/index-CoD1IJuy.js.map +1 -0
  210. package/build/server/chunks/{index-DwaY1cAm.js → index-DP9bWJrR.js} +2 -2
  211. package/build/server/chunks/{index-DwaY1cAm.js.map → index-DP9bWJrR.js.map} +1 -1
  212. package/build/server/chunks/{index-server-CrDaL06Y.js → index-server-BUmV4MIG.js} +2 -2
  213. package/build/server/chunks/index-server-BUmV4MIG.js.map +1 -0
  214. package/build/server/chunks/index-server2-BJrT0wnA.js +5 -0
  215. package/build/server/chunks/index-server2-BJrT0wnA.js.map +1 -0
  216. package/build/server/chunks/{index2-CgclKpUj.js → index2-D5Y19GKR.js} +2 -2
  217. package/build/server/chunks/index2-D5Y19GKR.js.map +1 -0
  218. package/build/server/chunks/{library-apns-BqJbvSKh.js → library-apns-Cf-E-DhM.js} +5 -2
  219. package/build/server/chunks/library-apns-Cf-E-DhM.js.map +1 -0
  220. package/build/server/chunks/providers-DtstoHQ0.js +17 -0
  221. package/build/server/chunks/providers-DtstoHQ0.js.map +1 -0
  222. package/build/server/chunks/{pty-manager-BQVB7IVj.js → pty-manager-TyMUpDA9.js} +41 -9
  223. package/build/server/chunks/pty-manager-TyMUpDA9.js.map +1 -0
  224. package/build/server/chunks/{root-DDSnEAZv.js → root-CATOR_0t.js} +2 -2
  225. package/build/server/chunks/root-CATOR_0t.js.map +1 -0
  226. package/build/server/chunks/shared-server-DaWdgxVh.js +11 -0
  227. package/build/server/chunks/shared-server-DaWdgxVh.js.map +1 -0
  228. package/build/server/chunks/{state.svelte-hBbXlUak.js → state.svelte-CftllyvC.js} +3 -3
  229. package/build/server/chunks/state.svelte-CftllyvC.js.map +1 -0
  230. package/build/server/chunks/{stores-DHNzYNpX.js → stores-BjL57aOK.js} +4 -4
  231. package/build/server/chunks/{stores-DHNzYNpX.js.map → stores-BjL57aOK.js.map} +1 -1
  232. package/build/server/index.js +173 -6
  233. package/build/server/index.js.map +1 -1
  234. package/build/server/manifest.js +53 -30
  235. package/build/server/manifest.js.map +1 -1
  236. package/package.json +24 -6
  237. package/scripts/dev.mjs +361 -0
  238. package/scripts/install.sh +11 -3
  239. package/scripts/{fix-generated-types.sh → postgen-types.sh} +2 -2
  240. package/scripts/setup.cjs +219 -24
  241. package/scripts/vercel-env-commands.sh +3 -3
  242. package/server.ts +3 -3
  243. package/src/app.html +163 -0
  244. package/src/lib/modules/client/activity/ActivityFeed.svelte +279 -0
  245. package/src/lib/modules/client/activity/index.ts +8 -0
  246. package/src/lib/modules/client/activity/store.svelte.ts +478 -0
  247. package/src/lib/modules/client/activity/summarizer.ts +224 -0
  248. package/src/lib/modules/client/common/Card.svelte +2 -9
  249. package/src/lib/modules/client/common/EmptyState.svelte +2 -20
  250. package/src/lib/modules/client/common/Icon.svelte +3 -7
  251. package/src/lib/modules/client/common/StatusBadge.svelte +2 -4
  252. package/src/lib/modules/client/common/config-guard.ts +22 -2
  253. package/src/lib/modules/client/common/index.ts +1 -1
  254. package/src/lib/modules/client/common/time.ts +27 -9
  255. package/src/lib/modules/client/dashboard/DashboardCard.svelte +374 -0
  256. package/src/lib/modules/client/dashboard/DashboardView.svelte +66 -0
  257. package/src/lib/modules/client/dashboard/index.ts +12 -0
  258. package/src/lib/modules/client/dashboard/store.svelte.ts +663 -0
  259. package/src/lib/modules/client/dashboard/summarizer.ts +205 -0
  260. package/src/lib/modules/client/neurolink/fetch-proxy.ts +70 -0
  261. package/src/lib/modules/client/neurolink/provider-config.ts +111 -0
  262. package/src/lib/modules/client/terminal/ChatView.svelte +46 -43
  263. package/src/lib/modules/client/terminal/CommandPalette.svelte +3 -12
  264. package/src/lib/modules/client/terminal/ConnectionStatus.svelte +3 -6
  265. package/src/lib/modules/client/terminal/LaunchSheet.svelte +10 -21
  266. package/src/lib/modules/client/terminal/QuickKeys.svelte +4 -11
  267. package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +3 -6
  268. package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +5 -7
  269. package/src/lib/modules/client/terminal/xterm-wrapper.ts +27 -47
  270. package/src/lib/modules/server/apn/library-apns.ts +6 -3
  271. package/src/lib/modules/server/apn/notification-history.ts +2 -2
  272. package/src/lib/modules/server/apn/notification-sessions.ts +1 -3
  273. package/src/lib/modules/server/apn/pending-requests.ts +1 -1
  274. package/src/lib/modules/server/apn/types.ts +2 -52
  275. package/src/lib/modules/server/cli/index.ts +1 -30
  276. package/src/lib/modules/server/cli/runner.ts +7 -15
  277. package/src/lib/modules/server/fcm/fcm-service.ts +2 -2
  278. package/src/lib/modules/server/sessions/jsonl-parser.ts +97 -42
  279. package/src/lib/modules/server/sessions/jsonl-reader.ts +144 -76
  280. package/src/lib/modules/server/sessions/opencode-reader.ts +1 -1
  281. package/src/lib/modules/server/sessions/process-detector.ts +72 -31
  282. package/src/lib/modules/server/sessions/types.ts +2 -42
  283. package/src/lib/modules/server/terminal/holder-client.ts +11 -35
  284. package/src/lib/modules/server/terminal/opencode-watcher.ts +16 -24
  285. package/src/lib/modules/server/terminal/pty-manager.ts +40 -45
  286. package/src/lib/modules/server/terminal/session-watcher.ts +15 -17
  287. package/src/lib/modules/server/terminal/terminal-store.ts +1 -1
  288. package/src/lib/modules/server/ws/events-handler.ts +1 -16
  289. package/src/lib/modules/server/ws/keepalive.ts +1 -5
  290. package/src/lib/modules/server/ws/server.ts +1 -1
  291. package/src/lib/modules/server/ws/session-handler.ts +20 -86
  292. package/src/lib/modules/server/ws/terminal-handler.ts +28 -51
  293. package/src/lib/modules/server/ws/ticket-store.ts +1 -1
  294. package/src/lib/modules/shared/providers.ts +21 -0
  295. package/src/lib/types/activity.ts +18 -0
  296. package/src/lib/types/apn.ts +43 -0
  297. package/src/lib/types/cli.ts +39 -0
  298. package/src/lib/types/common.ts +39 -0
  299. package/src/lib/types/dashboard.ts +4 -0
  300. package/src/lib/types/generated/Client.ts +1656 -0
  301. package/src/{generated/types → lib/types/generated}/WsProtocol.ts +344 -2
  302. package/src/lib/types/index.ts +28 -0
  303. package/src/lib/types/neurolink.ts +4 -0
  304. package/src/lib/types/server.ts +93 -0
  305. package/src/lib/types/sessions.ts +59 -0
  306. package/src/lib/types/terminal-client.ts +132 -0
  307. package/src/lib/types/ws.ts +161 -0
  308. package/src/routes/+error.svelte +7 -2
  309. package/src/routes/+layout.server.ts +9 -0
  310. package/src/routes/+layout.svelte +36 -7
  311. package/src/routes/+page.server.ts +7 -0
  312. package/src/routes/+page.svelte +85 -35
  313. package/src/routes/activity/+page.server.ts +7 -0
  314. package/src/routes/activity/+page.svelte +58 -0
  315. package/src/routes/api/health/+server.ts +32 -19
  316. package/src/routes/api/neurolink-proxy/+server.ts +136 -0
  317. package/src/routes/api/notify/+server.ts +190 -87
  318. package/src/routes/api/sessions/+server.ts +1 -1
  319. package/src/routes/api/sessions/connect/+server.ts +10 -6
  320. package/src/routes/api/terminals/+server.ts +20 -1
  321. package/src/routes/api/terminals/[id]/+server.ts +16 -2
  322. package/src/routes/api/webhook/+server.ts +5 -33
  323. package/src/routes/api/ws-ticket/+server.ts +4 -4
  324. package/src/routes/config/+page.server.ts +9 -0
  325. package/src/routes/config/+page.svelte +118 -25
  326. package/src/routes/neurolink/+page.server.ts +10 -0
  327. package/src/routes/neurolink/+page.svelte +331 -0
  328. package/src/routes/project/+page.svelte +17 -12
  329. package/src/routes/session/[id]/+page.svelte +146 -62
  330. package/src/routes/terminals/+page.svelte +2 -2
  331. package/src/routes/terminals/[id]/+page.svelte +99 -88
  332. package/svelte.config.js +1 -3
  333. package/tsconfig.json +1 -0
  334. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css +0 -1
  335. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.br +0 -1
  336. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
  337. package/build/client/_app/immutable/assets/3.DGDHCVnW.css.br +0 -0
  338. package/build/client/_app/immutable/assets/3.DGDHCVnW.css.gz +0 -0
  339. package/build/client/_app/immutable/chunks/B5NAKyil.js +0 -20
  340. package/build/client/_app/immutable/chunks/B5NAKyil.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/B5NAKyil.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/B8XegpSE.js +0 -1
  343. package/build/client/_app/immutable/chunks/B8XegpSE.js.br +0 -0
  344. package/build/client/_app/immutable/chunks/B8XegpSE.js.gz +0 -0
  345. package/build/client/_app/immutable/chunks/B8zoBsv3.js +0 -6
  346. package/build/client/_app/immutable/chunks/B8zoBsv3.js.br +0 -0
  347. package/build/client/_app/immutable/chunks/B8zoBsv3.js.gz +0 -0
  348. package/build/client/_app/immutable/chunks/BIaXC2t9.js +0 -1
  349. package/build/client/_app/immutable/chunks/BIaXC2t9.js.br +0 -0
  350. package/build/client/_app/immutable/chunks/BIaXC2t9.js.gz +0 -0
  351. package/build/client/_app/immutable/chunks/BOYo8yTr.js +0 -1
  352. package/build/client/_app/immutable/chunks/BOYo8yTr.js.br +0 -0
  353. package/build/client/_app/immutable/chunks/BOYo8yTr.js.gz +0 -0
  354. package/build/client/_app/immutable/chunks/Bu1aqm5j.js +0 -1
  355. package/build/client/_app/immutable/chunks/Bu1aqm5j.js.br +0 -0
  356. package/build/client/_app/immutable/chunks/Bu1aqm5j.js.gz +0 -0
  357. package/build/client/_app/immutable/chunks/CQjSATpv.js +0 -61
  358. package/build/client/_app/immutable/chunks/CQjSATpv.js.br +0 -0
  359. package/build/client/_app/immutable/chunks/CQjSATpv.js.gz +0 -0
  360. package/build/client/_app/immutable/chunks/CRbaG9cv.js.br +0 -0
  361. package/build/client/_app/immutable/chunks/CSoRdFvv.js.br +0 -0
  362. package/build/client/_app/immutable/chunks/CSoRdFvv.js.gz +0 -0
  363. package/build/client/_app/immutable/chunks/CZHsSL_X.js.br +0 -0
  364. package/build/client/_app/immutable/chunks/CZHsSL_X.js.gz +0 -0
  365. package/build/client/_app/immutable/chunks/CiF38mQq.js.br +0 -0
  366. package/build/client/_app/immutable/chunks/CiF38mQq.js.gz +0 -0
  367. package/build/client/_app/immutable/chunks/DSU1n5N_.js +0 -1
  368. package/build/client/_app/immutable/chunks/DSU1n5N_.js.br +0 -0
  369. package/build/client/_app/immutable/chunks/DSU1n5N_.js.gz +0 -0
  370. package/build/client/_app/immutable/chunks/DVkn4r72.js +0 -1
  371. package/build/client/_app/immutable/chunks/DVkn4r72.js.br +0 -0
  372. package/build/client/_app/immutable/chunks/DVkn4r72.js.gz +0 -0
  373. package/build/client/_app/immutable/chunks/DjsDGxCa.js.br +0 -0
  374. package/build/client/_app/immutable/chunks/DjsDGxCa.js.gz +0 -0
  375. package/build/client/_app/immutable/chunks/UJOiqIYE.js.br +0 -0
  376. package/build/client/_app/immutable/chunks/UJOiqIYE.js.gz +0 -0
  377. package/build/client/_app/immutable/chunks/r0JawsZc.js +0 -2
  378. package/build/client/_app/immutable/chunks/r0JawsZc.js.br +0 -0
  379. package/build/client/_app/immutable/chunks/r0JawsZc.js.gz +0 -0
  380. package/build/client/_app/immutable/entry/app.CU7KVZja.js +0 -2
  381. package/build/client/_app/immutable/entry/app.CU7KVZja.js.br +0 -0
  382. package/build/client/_app/immutable/entry/app.CU7KVZja.js.gz +0 -0
  383. package/build/client/_app/immutable/entry/start.RAMZY19t.js +0 -1
  384. package/build/client/_app/immutable/entry/start.RAMZY19t.js.br +0 -2
  385. package/build/client/_app/immutable/entry/start.RAMZY19t.js.gz +0 -0
  386. package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js +0 -1
  387. package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js.br +0 -0
  388. package/build/client/_app/immutable/nodes/0.Bi3XYMSu.js.gz +0 -0
  389. package/build/client/_app/immutable/nodes/1.DTmfBFmm.js +0 -1
  390. package/build/client/_app/immutable/nodes/1.DTmfBFmm.js.br +0 -0
  391. package/build/client/_app/immutable/nodes/1.DTmfBFmm.js.gz +0 -0
  392. package/build/client/_app/immutable/nodes/2.Cm269yzt.js +0 -1
  393. package/build/client/_app/immutable/nodes/2.Cm269yzt.js.br +0 -0
  394. package/build/client/_app/immutable/nodes/2.Cm269yzt.js.gz +0 -0
  395. package/build/client/_app/immutable/nodes/3.3yohCM25.js +0 -3
  396. package/build/client/_app/immutable/nodes/3.3yohCM25.js.br +0 -0
  397. package/build/client/_app/immutable/nodes/3.3yohCM25.js.gz +0 -0
  398. package/build/client/_app/immutable/nodes/4.C25c5hMg.js +0 -1
  399. package/build/client/_app/immutable/nodes/4.C25c5hMg.js.br +0 -0
  400. package/build/client/_app/immutable/nodes/4.C25c5hMg.js.gz +0 -0
  401. package/build/client/_app/immutable/nodes/5.DIkXVP4q.js.br +0 -0
  402. package/build/client/_app/immutable/nodes/5.DIkXVP4q.js.gz +0 -0
  403. package/build/client/_app/immutable/nodes/6.BPL-HzUX.js +0 -2
  404. package/build/client/_app/immutable/nodes/6.BPL-HzUX.js.br +0 -0
  405. package/build/client/_app/immutable/nodes/6.BPL-HzUX.js.gz +0 -0
  406. package/build/client/_app/immutable/nodes/7.IgEqce53.js +0 -2
  407. package/build/client/_app/immutable/nodes/7.IgEqce53.js.br +0 -0
  408. package/build/client/_app/immutable/nodes/7.IgEqce53.js.gz +0 -0
  409. package/build/server/chunks/0-DiORznXb.js +0 -9
  410. package/build/server/chunks/0-DiORznXb.js.map +0 -1
  411. package/build/server/chunks/1-D0N7vVhH.js +0 -9
  412. package/build/server/chunks/2-DfSav7a7.js +0 -9
  413. package/build/server/chunks/2-DfSav7a7.js.map +0 -1
  414. package/build/server/chunks/3-Ck7ewhOX.js +0 -9
  415. package/build/server/chunks/3-Ck7ewhOX.js.map +0 -1
  416. package/build/server/chunks/4-DV5MZUz_.js +0 -9
  417. package/build/server/chunks/4-DV5MZUz_.js.map +0 -1
  418. package/build/server/chunks/5-DJhoAjb0.js +0 -9
  419. package/build/server/chunks/5-DJhoAjb0.js.map +0 -1
  420. package/build/server/chunks/6-Cp8CzYbr.js +0 -9
  421. package/build/server/chunks/6-Cp8CzYbr.js.map +0 -1
  422. package/build/server/chunks/7-BA4xzUj3.js +0 -9
  423. package/build/server/chunks/7-BA4xzUj3.js.map +0 -1
  424. package/build/server/chunks/Button-Cs1aE6ka.js.map +0 -1
  425. package/build/server/chunks/Icon-CEUrotA6.js.map +0 -1
  426. package/build/server/chunks/_layout.svelte-CtWmEJwe.js.map +0 -1
  427. package/build/server/chunks/_page.svelte-BdYynOck.js +0 -85
  428. package/build/server/chunks/_page.svelte-BdYynOck.js.map +0 -1
  429. package/build/server/chunks/_page.svelte-CVq6tRb3.js.map +0 -1
  430. package/build/server/chunks/_page.svelte-CxWcQ0Am.js.map +0 -1
  431. package/build/server/chunks/_server.ts-BStnNIcq.js +0 -34
  432. package/build/server/chunks/_server.ts-BStnNIcq.js.map +0 -1
  433. package/build/server/chunks/_server.ts-CAxsWKvS.js.map +0 -1
  434. package/build/server/chunks/_server.ts-COu0vNpd.js.map +0 -1
  435. package/build/server/chunks/_server.ts-CTpcLUH8.js.map +0 -1
  436. package/build/server/chunks/_server.ts-Cf84YIaW.js +0 -25
  437. package/build/server/chunks/_server.ts-Cf84YIaW.js.map +0 -1
  438. package/build/server/chunks/_server.ts-Ch-6iOHp.js.map +0 -1
  439. package/build/server/chunks/_server.ts-CtH0dhUp.js +0 -71
  440. package/build/server/chunks/_server.ts-CtH0dhUp.js.map +0 -1
  441. package/build/server/chunks/_server.ts-DB_Kg97c.js.map +0 -1
  442. package/build/server/chunks/_server.ts-DYpJImqd.js.map +0 -1
  443. package/build/server/chunks/_server.ts-Deok2y88.js.map +0 -1
  444. package/build/server/chunks/_server.ts-tSpgyl1D.js.map +0 -1
  445. package/build/server/chunks/_server.ts-vekTmWAx.js.map +0 -1
  446. package/build/server/chunks/client2-CCBGA-2V.js +0 -7
  447. package/build/server/chunks/index-server-CrDaL06Y.js.map +0 -1
  448. package/build/server/chunks/index2-CgclKpUj.js.map +0 -1
  449. package/build/server/chunks/library-apns-BqJbvSKh.js.map +0 -1
  450. package/build/server/chunks/pty-manager-BQVB7IVj.js.map +0 -1
  451. package/build/server/chunks/root-DDSnEAZv.js.map +0 -1
  452. package/build/server/chunks/shared-server-sSGG17Df.js.map +0 -1
  453. package/build/server/chunks/state.svelte-hBbXlUak.js.map +0 -1
  454. package/src/generated/types/Client.ts +0 -589
  455. package/src/lib/types/config.ts +0 -1
  456. /package/build/client/_app/immutable/assets/{4.BFUut--w.css → 6.BFUut--w.css} +0 -0
  457. /package/build/client/_app/immutable/assets/{4.BFUut--w.css.br → 6.BFUut--w.css.br} +0 -0
  458. /package/build/client/_app/immutable/assets/{4.BFUut--w.css.gz → 6.BFUut--w.css.gz} +0 -0
  459. /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css → 7.BTOx7yt7.css} +0 -0
  460. /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css.br → 7.BTOx7yt7.css.br} +0 -0
  461. /package/build/client/_app/immutable/assets/{5.BTOx7yt7.css.gz → 7.BTOx7yt7.css.gz} +0 -0
  462. /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css → 8.eZGZN-BF.css} +0 -0
  463. /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css.br → 8.eZGZN-BF.css.br} +0 -0
  464. /package/build/client/_app/immutable/assets/{6.eZGZN-BF.css.gz → 8.eZGZN-BF.css.gz} +0 -0
  465. /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css → 9.DwS5ZHBh.css} +0 -0
  466. /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css.br → 9.DwS5ZHBh.css.br} +0 -0
  467. /package/build/client/_app/immutable/assets/{7.DwS5ZHBh.css.gz → 9.DwS5ZHBh.css.gz} +0 -0
  468. /package/src/{generated/types → lib/types/generated}/API.ts +0 -0
  469. /package/src/{generated/types → lib/types/generated}/APN.ts +0 -0
  470. /package/src/{generated/types → lib/types/generated}/CLI.ts +0 -0
  471. /package/src/{generated/types → lib/types/generated}/Config.ts +0 -0
  472. /package/src/{generated/types → lib/types/generated}/Holder.ts +0 -0
  473. /package/src/{generated/types → lib/types/generated}/JWT.ts +0 -0
  474. /package/src/{generated/types → lib/types/generated}/Notification.ts +0 -0
  475. /package/src/{generated/types → lib/types/generated}/OpenCode.ts +0 -0
  476. /package/src/{generated/types → lib/types/generated}/Sessions.ts +0 -0
  477. /package/src/{generated/types → lib/types/generated}/Terminal.ts +0 -0
  478. /package/src/{generated/types → lib/types/generated}/index.ts +0 -0
@@ -0,0 +1,136 @@
1
+ // Server-side proxy for AI providers that block direct browser requests (CORS).
2
+ // The browser NeuroLink bundle POSTs here; this endpoint forwards to the real API.
3
+ // Currently supports: anthropic (api.anthropic.com blocks browser fetch).
4
+
5
+ import { env } from '$env/dynamic/private';
6
+ import { validateAuth } from '$lib/modules/server/auth';
7
+ import { json } from '@sveltejs/kit';
8
+
9
+ import type { RequestHandler } from './$types';
10
+
11
+ // Per-provider allowlist of client-supplied headers that may be forwarded
12
+ // upstream. Everything else (including host, x-forwarded-*, content-type) is
13
+ // dropped so the browser can't influence provider behavior beyond what we
14
+ // explicitly permit.
15
+ const ALLOWED_CLIENT_HEADERS: Record<string, Set<string>> = {
16
+ anthropic: new Set(['anthropic-beta', 'anthropic-version']),
17
+ 'google-ai': new Set<string>([]),
18
+ mistral: new Set([]),
19
+ openai: new Set(['openai-organization', 'openai-project']),
20
+ };
21
+
22
+ export const POST: RequestHandler = async ({ request }) => {
23
+ const authError = validateAuth(request);
24
+ if (authError) {
25
+ return authError;
26
+ }
27
+
28
+ let payload: unknown;
29
+ try {
30
+ payload = await request.json();
31
+ } catch {
32
+ return json({ error: 'Invalid JSON body' }, { status: 400 });
33
+ }
34
+
35
+ if (
36
+ !payload ||
37
+ typeof payload !== 'object' ||
38
+ typeof (payload as { provider?: unknown }).provider !== 'string' ||
39
+ typeof (payload as { url?: unknown }).url !== 'string' ||
40
+ !(payload as { headers?: unknown }).headers ||
41
+ typeof (payload as { headers?: unknown }).headers !== 'object'
42
+ ) {
43
+ return json({ error: 'Invalid proxy payload' }, { status: 400 });
44
+ }
45
+
46
+ const {
47
+ body,
48
+ headers: reqHeaders,
49
+ provider,
50
+ url,
51
+ } = payload as {
52
+ body: unknown;
53
+ headers: Record<string, string>;
54
+ provider: string;
55
+ url: string;
56
+ };
57
+
58
+ // Only proxy known safe providers — never forward arbitrary URLs
59
+ const ALLOWED_PREFIXES: Record<string, string> = {
60
+ anthropic: 'https://api.anthropic.com/',
61
+ 'google-ai': 'https://generativelanguage.googleapis.com/',
62
+ mistral: 'https://api.mistral.ai/',
63
+ openai: 'https://api.openai.com/',
64
+ };
65
+
66
+ const allowedPrefix = ALLOWED_PREFIXES[provider];
67
+ if (!allowedPrefix || !url.startsWith(allowedPrefix)) {
68
+ return json({ error: `Provider "${provider}" or URL not allowed` }, { status: 403 });
69
+ }
70
+
71
+ // Inject the server-side API key so the browser never sees it
72
+ const apiKeyEnv: Record<string, string> = {
73
+ anthropic: env.ANTHROPIC_API_KEY ?? '',
74
+ 'google-ai': env.GOOGLE_AI_API_KEY ?? '',
75
+ mistral: env.MISTRAL_API_KEY ?? '',
76
+ openai: env.OPENAI_API_KEY ?? '',
77
+ };
78
+
79
+ // Copy only explicitly-allowed headers per provider. Everything else is
80
+ // dropped so the browser can't influence upstream behavior via host,
81
+ // x-forwarded-*, organization selectors, provider feature toggles, etc.
82
+ const allowedForProvider = ALLOWED_CLIENT_HEADERS[provider] ?? new Set<string>();
83
+ const normalizedReqHeaders: Record<string, string> = {};
84
+ for (const [k, v] of Object.entries(reqHeaders)) {
85
+ const key = k.toLowerCase();
86
+ if (allowedForProvider.has(key)) {
87
+ normalizedReqHeaders[key] = v;
88
+ }
89
+ }
90
+
91
+ const forwardHeaders: Record<string, string> = {
92
+ 'Content-Type': 'application/json',
93
+ ...normalizedReqHeaders,
94
+ };
95
+
96
+ // Override / set auth header with server-side key
97
+ if (provider === 'anthropic') {
98
+ forwardHeaders['x-api-key'] = apiKeyEnv.anthropic;
99
+ forwardHeaders['anthropic-version'] = forwardHeaders['anthropic-version'] ?? '2023-06-01';
100
+ } else if (provider === 'google-ai') {
101
+ forwardHeaders['x-goog-api-key'] = apiKeyEnv['google-ai'];
102
+ } else if (provider === 'openai') {
103
+ forwardHeaders.Authorization = `Bearer ${apiKeyEnv.openai}`;
104
+ } else if (provider === 'mistral') {
105
+ forwardHeaders.Authorization = `Bearer ${apiKeyEnv.mistral}`;
106
+ }
107
+
108
+ const controller = new AbortController();
109
+ const timeout = setTimeout(() => {
110
+ controller.abort();
111
+ }, 30_000);
112
+
113
+ let resp: Response;
114
+ try {
115
+ resp = await fetch(url, {
116
+ body: JSON.stringify(body),
117
+ headers: forwardHeaders,
118
+ method: 'POST',
119
+ signal: controller.signal,
120
+ });
121
+ } catch (err) {
122
+ clearTimeout(timeout);
123
+ const message = err instanceof Error ? err.message : 'Upstream request failed';
124
+ return json({ error: message }, { status: 502 });
125
+ }
126
+ clearTimeout(timeout);
127
+
128
+ let data: unknown;
129
+ try {
130
+ data = await resp.json();
131
+ } catch {
132
+ return json({ error: 'Upstream returned non-JSON response' }, { status: 502 });
133
+ }
134
+
135
+ return json(data, { status: resp.status });
136
+ };
@@ -1,4 +1,4 @@
1
- import type { NotificationData } from '$generated/types';
1
+ import type { NotificationData } from '$lib/types';
2
2
 
3
3
  import { env } from '$env/dynamic/private';
4
4
  import { LibraryAPNsService } from '$lib/modules/server/apn/library-apns';
@@ -7,10 +7,33 @@ import { createPendingRequest } from '$lib/modules/server/apn/pending-requests';
7
7
  import { validateAuth } from '$lib/modules/server/auth';
8
8
  import { isFCMConfigured, sendFCMNotification } from '$lib/modules/server/fcm/fcm-service.js';
9
9
  import { toErrorMessage } from '$lib/modules/server/utils/error';
10
+ import { broadcastEvent } from '$lib/modules/server/ws/server';
10
11
  import { json } from '@sveltejs/kit';
12
+ import { existsSync, readFileSync } from 'fs';
13
+ import { homedir } from 'os';
14
+ import { join } from 'path';
11
15
 
12
16
  import type { RequestHandler } from './$types';
13
17
 
18
+ // Reads tokens persisted by /api/device-token — populated automatically when
19
+ // the Android or iOS app registers on first launch.
20
+ function readPersistedDeviceToken(platform: 'android' | 'ios'): string | undefined {
21
+ const tokensFile = join(homedir(), '.shooter', 'device-tokens.json');
22
+ if (!existsSync(tokensFile)) {
23
+ return undefined;
24
+ }
25
+ try {
26
+ const parsed: unknown = JSON.parse(readFileSync(tokensFile, 'utf-8'));
27
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
28
+ const value = (parsed as Record<string, unknown>)[platform];
29
+ return typeof value === 'string' && value ? value : undefined;
30
+ }
31
+ } catch {
32
+ // corrupt / unreadable — fall through
33
+ }
34
+ return undefined;
35
+ }
36
+
14
37
  // Singleton APNs client - reuses HTTP/2 connection across requests
15
38
  let apnsSingleton: LibraryAPNsService | null = null;
16
39
  function getAPNsClient(): LibraryAPNsService {
@@ -24,15 +47,118 @@ function getAPNsClient(): LibraryAPNsService {
24
47
  const notificationCache = new Map<string, number>();
25
48
  const DEDUP_WINDOW = 10000; // 10 seconds deduplication window
26
49
 
50
+ function broadcastHookEvent(body: Record<string, unknown>): void {
51
+ const data = (body.data ?? {}) as Record<string, unknown>;
52
+ const eventType =
53
+ typeof data.eventType === 'string'
54
+ ? data.eventType
55
+ : typeof body.eventType === 'string'
56
+ ? body.eventType
57
+ : '';
58
+ const tool = typeof data.tool === 'string' ? data.tool : '';
59
+ const terminalId = typeof data.terminalId === 'string' ? data.terminalId : undefined;
60
+ const sessionId = typeof data.sessionId === 'string' ? data.sessionId : undefined;
61
+
62
+ switch (eventType) {
63
+ case 'error':
64
+ broadcastEvent({
65
+ error:
66
+ typeof data.error === 'string'
67
+ ? data.error
68
+ : typeof data.message === 'string'
69
+ ? data.message
70
+ : 'Unknown error',
71
+ terminalId,
72
+ tool,
73
+ type: 'tool-failed',
74
+ });
75
+ break;
76
+ case 'idle_input':
77
+ case 'session.idle':
78
+ broadcastEvent({
79
+ message: typeof data.message === 'string' ? data.message : '',
80
+ sessionId,
81
+ terminalId,
82
+ type: 'agent-idle',
83
+ });
84
+ break;
85
+ case 'permission':
86
+ case 'permission_notification':
87
+ if (data.requestId && data.toolName) {
88
+ broadcastEvent({
89
+ input:
90
+ typeof data.toolInput === 'object' && data.toolInput !== null
91
+ ? (data.toolInput as Record<string, unknown>)
92
+ : {},
93
+ requestId: data.requestId as string,
94
+ tool: data.toolName as string,
95
+ type: 'permission-requested',
96
+ });
97
+ }
98
+ break;
99
+ case 'question':
100
+ broadcastEvent({
101
+ message: typeof data.message === 'string' ? data.message : '',
102
+ sessionId,
103
+ terminalId,
104
+ type: 'agent-question',
105
+ });
106
+ break;
107
+ case 'tool.after':
108
+ broadcastEvent({ success: true, terminalId, tool, type: 'tool-completed' });
109
+ break;
110
+ case 'tool.before':
111
+ broadcastEvent({
112
+ command: typeof data.command === 'string' ? data.command : '',
113
+ filePath:
114
+ typeof data.filePath === 'string'
115
+ ? data.filePath
116
+ : typeof data.files === 'string'
117
+ ? data.files
118
+ : '',
119
+ terminalId,
120
+ tool,
121
+ type: 'tool-started',
122
+ });
123
+ break;
124
+ // session.status, intervention — skip or use existing types
125
+ }
126
+ }
127
+
128
+ /** Build a notification history record from common fields. */
129
+ function buildNotificationRecord(
130
+ id: string,
131
+ title: string,
132
+ message: string,
133
+ status: 'failed' | 'filtered' | 'sent' | 'skipped',
134
+ data?: NotificationData,
135
+ error?: null | string
136
+ ): Parameters<typeof addNotification>[0] {
137
+ return {
138
+ category: data?.category ?? null,
139
+ data: (data as Record<string, unknown>) ?? null,
140
+ error: error ?? null,
141
+ id,
142
+ message,
143
+ project: data?.project ?? null,
144
+ source: data?.source ?? null,
145
+ status,
146
+ timestamp: new Date().toISOString(),
147
+ title,
148
+ tool: data?.tool ?? null,
149
+ };
150
+ }
151
+
27
152
  function intelligentNotificationFilter(
28
153
  title: string,
29
154
  message: string,
30
- data?: NotificationData
155
+ data?: NotificationData,
156
+ waitForResponse = false
31
157
  ): { reason: string; send: boolean } {
32
158
  const source = data?.source || 'unknown';
33
159
 
34
160
  // Check for duplicate notifications first
35
- if (isDuplicateNotification(title, message, data)) {
161
+ if (isDuplicateNotification(title, message, data, waitForResponse)) {
36
162
  return {
37
163
  reason: 'Duplicate notification within 10-second window',
38
164
  send: false,
@@ -100,12 +226,23 @@ function intelligentNotificationFilter(
100
226
  };
101
227
  }
102
228
 
103
- function isDuplicateNotification(title: string, message: string, data?: NotificationData): boolean {
229
+ function isDuplicateNotification(
230
+ title: string,
231
+ message: string,
232
+ data?: NotificationData,
233
+ waitForResponse = false
234
+ ): boolean {
235
+ // Never deduplicate bidirectional permission requests — each one creates a
236
+ // unique pending request that the hook polls by requestId.
237
+ if (waitForResponse) {
238
+ return false;
239
+ }
240
+
104
241
  const key = `${title}|${message}|${data?.category || 'unknown'}`;
105
242
  const now = Date.now();
106
243
 
107
244
  if (notificationCache.has(key)) {
108
- const lastSent = notificationCache.get(key)!;
245
+ const lastSent = notificationCache.get(key) ?? 0;
109
246
  if (now - lastSent < DEDUP_WINDOW) {
110
247
  return true; // Duplicate within time window
111
248
  }
@@ -159,6 +296,13 @@ export const POST: RequestHandler = async ({ request }) => {
159
296
  const waitForResponse =
160
297
  typeof body.waitForResponse === 'boolean' ? body.waitForResponse : false;
161
298
 
299
+ // Broadcast to /ws/events for real-time activity feed
300
+ try {
301
+ broadcastHookEvent(body);
302
+ } catch {
303
+ // Best-effort broadcast — don't fail the notify request
304
+ }
305
+
162
306
  if (!title || typeof title !== 'string' || !message || typeof message !== 'string') {
163
307
  return json({ error: 'Title and message are required and must be strings' }, { status: 400 });
164
308
  }
@@ -171,22 +315,24 @@ export const POST: RequestHandler = async ({ request }) => {
171
315
  const requestId = Math.random().toString(36).substring(2, 15);
172
316
  const dataRequestId = typeof data?.requestId === 'string' ? data.requestId : undefined;
173
317
  const canonicalRequestId = dataRequestId || requestId;
174
- const shouldSendNotification = intelligentNotificationFilter(title, message, data);
318
+ const shouldSendNotification = intelligentNotificationFilter(
319
+ title,
320
+ message,
321
+ data,
322
+ waitForResponse
323
+ );
175
324
 
176
325
  if (!shouldSendNotification.send) {
177
- addNotification({
178
- category: data?.category ?? null,
179
- data: (data as Record<string, unknown>) ?? null,
180
- error: shouldSendNotification.reason,
181
- id: canonicalRequestId,
182
- message,
183
- project: data?.project ?? null,
184
- source: data?.source ?? null,
185
- status: 'filtered',
186
- timestamp: new Date().toISOString(),
187
- title,
188
- tool: data?.tool ?? null,
189
- });
326
+ addNotification(
327
+ buildNotificationRecord(
328
+ canonicalRequestId,
329
+ title,
330
+ message,
331
+ 'filtered',
332
+ data,
333
+ shouldSendNotification.reason
334
+ )
335
+ );
190
336
 
191
337
  return json({
192
338
  message: 'Notification filtered (not sent)',
@@ -209,19 +355,7 @@ export const POST: RequestHandler = async ({ request }) => {
209
355
  });
210
356
  }
211
357
 
212
- addNotification({
213
- category: data?.category ?? null,
214
- data: (data as Record<string, unknown>) ?? null,
215
- error: null,
216
- id: canonicalRequestId,
217
- message,
218
- project: data?.project ?? null,
219
- source: data?.source ?? null,
220
- status: 'skipped',
221
- timestamp: new Date().toISOString(),
222
- title,
223
- tool: data?.tool ?? null,
224
- });
358
+ addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'skipped', data));
225
359
 
226
360
  return json({
227
361
  message: 'Push skipped (WebSocket clients connected)',
@@ -264,15 +398,21 @@ export const POST: RequestHandler = async ({ request }) => {
264
398
  );
265
399
  }
266
400
 
267
- // Honor request-scoped deviceToken, falling back to environment variables.
401
+ // Honor request-scoped deviceToken, then the Android-specific env var,
402
+ // then the token auto-registered by the Android app via /api/device-token.
403
+ // env.DEVICE_TOKEN is intentionally NOT in this chain: the iOS branch
404
+ // treats it as an APNs token (see below), and letting it bleed into the
405
+ // FCM path would ship an APNs token to FCM in mixed-platform setups.
268
406
  const androidToken =
269
- requestDeviceToken?.trim() || (env.ANDROID_DEVICE_TOKEN || env.DEVICE_TOKEN)?.trim();
407
+ requestDeviceToken?.trim() ||
408
+ env.ANDROID_DEVICE_TOKEN?.trim() ||
409
+ readPersistedDeviceToken('android');
270
410
 
271
411
  if (!androidToken) {
272
412
  return json(
273
413
  {
274
414
  details:
275
- 'ANDROID_DEVICE_TOKEN or DEVICE_TOKEN environment variable is missing and no deviceToken in request body',
415
+ 'No Android device token available set ANDROID_DEVICE_TOKEN, pass deviceToken in the request body, or open the Android app so it can auto-register its FCM token.',
276
416
  error: 'No device token configured',
277
417
  },
278
418
  { status: 500 }
@@ -293,19 +433,7 @@ export const POST: RequestHandler = async ({ request }) => {
293
433
  });
294
434
  }
295
435
 
296
- addNotification({
297
- category: data?.category ?? null,
298
- data: (data as Record<string, unknown>) ?? null,
299
- error: null,
300
- id: canonicalRequestId,
301
- message,
302
- project: data?.project ?? null,
303
- source: data?.source ?? null,
304
- status: 'sent',
305
- timestamp: new Date().toISOString(),
306
- title,
307
- tool: data?.tool ?? null,
308
- });
436
+ addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'sent', data));
309
437
 
310
438
  return json({
311
439
  message: 'Notification sent successfully',
@@ -317,19 +445,16 @@ export const POST: RequestHandler = async ({ request }) => {
317
445
  } else {
318
446
  console.error(`[notify] FCM delivery failed: ${fcmResult.error}`);
319
447
 
320
- addNotification({
321
- category: data?.category ?? null,
322
- data: (data as Record<string, unknown>) ?? null,
323
- error: fcmResult.error ?? null,
324
- id: canonicalRequestId,
325
- message,
326
- project: data?.project ?? null,
327
- source: data?.source ?? null,
328
- status: 'failed',
329
- timestamp: new Date().toISOString(),
330
- title,
331
- tool: data?.tool ?? null,
332
- });
448
+ addNotification(
449
+ buildNotificationRecord(
450
+ canonicalRequestId,
451
+ title,
452
+ message,
453
+ 'failed',
454
+ data,
455
+ fcmResult.error
456
+ )
457
+ );
333
458
 
334
459
  return json(
335
460
  {
@@ -384,19 +509,7 @@ export const POST: RequestHandler = async ({ request }) => {
384
509
  });
385
510
  }
386
511
 
387
- addNotification({
388
- category: data?.category ?? null,
389
- data: (data as Record<string, unknown>) ?? null,
390
- error: null,
391
- id: canonicalRequestId,
392
- message,
393
- project: data?.project ?? null,
394
- source: data?.source ?? null,
395
- status: 'sent',
396
- timestamp: new Date().toISOString(),
397
- title,
398
- tool: data?.tool ?? null,
399
- });
512
+ addNotification(buildNotificationRecord(canonicalRequestId, title, message, 'sent', data));
400
513
 
401
514
  return json({
402
515
  message: 'Notification sent successfully',
@@ -409,19 +522,9 @@ export const POST: RequestHandler = async ({ request }) => {
409
522
  const notifErrMsg = toErrorMessage(notificationError);
410
523
  console.error(`[notify] APNs delivery failed: ${notifErrMsg}`);
411
524
 
412
- addNotification({
413
- category: data?.category ?? null,
414
- data: (data as Record<string, unknown>) ?? null,
415
- error: notifErrMsg,
416
- id: canonicalRequestId,
417
- message,
418
- project: data?.project ?? null,
419
- source: data?.source ?? null,
420
- status: 'failed',
421
- timestamp: new Date().toISOString(),
422
- title,
423
- tool: data?.tool ?? null,
424
- });
525
+ addNotification(
526
+ buildNotificationRecord(canonicalRequestId, title, message, 'failed', data, notifErrMsg)
527
+ );
425
528
 
426
529
  return json(
427
530
  {
@@ -1,4 +1,4 @@
1
- import type { ProjectGroup } from '$lib/modules/server/sessions/types';
1
+ import type { ProjectGroup } from '$lib/types';
2
2
 
3
3
  import { validateAuth } from '$lib/modules/server/auth';
4
4
  import {
@@ -65,9 +65,11 @@ export const POST: RequestHandler = async ({ request }) => {
65
65
 
66
66
  const existing = ptyManager
67
67
  .list()
68
- .find((t) => t.status === 'running' && (
69
- t.sessionFile?.endsWith(`/${sessionId}.jsonl`) || t.openCodeSessionId === sessionId
70
- ));
68
+ .find(
69
+ (t) =>
70
+ t.status === 'running' &&
71
+ (t.sessionFile?.endsWith(`/${sessionId}.jsonl`) || t.openCodeSessionId === sessionId)
72
+ );
71
73
 
72
74
  if (existing) {
73
75
  console.log(
@@ -94,8 +96,7 @@ export const POST: RequestHandler = async ({ request }) => {
94
96
 
95
97
  // --- Build args based on command ---
96
98
 
97
- const args: string[] =
98
- command === 'claude' ? ['--resume', sessionId] : ['--session', sessionId];
99
+ const args: string[] = command === 'claude' ? ['--resume', sessionId] : ['--session', sessionId];
99
100
 
100
101
  try {
101
102
  const terminal = await ptyManager.create(command, args, realCwd, 120, 40);
@@ -107,7 +108,10 @@ export const POST: RequestHandler = async ({ request }) => {
107
108
  return json(
108
109
  {
109
110
  command: terminal.command,
110
- createdAt: terminal.createdAt instanceof Date ? terminal.createdAt.toISOString() : terminal.createdAt,
111
+ createdAt:
112
+ terminal.createdAt instanceof Date
113
+ ? terminal.createdAt.toISOString()
114
+ : terminal.createdAt,
111
115
  cwd: terminal.cwd,
112
116
  id: terminal.id,
113
117
  pid: terminal.pid,
@@ -9,6 +9,21 @@ import type { RequestHandler } from './$types';
9
9
 
10
10
  const ALLOWED_COMMANDS = ['zsh', 'bash', 'sh', 'fish', 'claude', 'opencode'];
11
11
 
12
+ /** Extract the last non-empty line from a scrollback string. */
13
+ function lastScrollbackLine(scrollback: string): null | string {
14
+ if (!scrollback) {
15
+ return null;
16
+ }
17
+ const lines = scrollback.trimEnd().split('\n');
18
+ for (let i = lines.length - 1; i >= 0; i--) {
19
+ const line = lines[i].trim();
20
+ if (line) {
21
+ return line.slice(0, 200);
22
+ }
23
+ }
24
+ return null;
25
+ }
26
+
12
27
  // GET /api/terminals — List all terminals (active + recently exited)
13
28
  export const GET: RequestHandler = ({ request }) => {
14
29
  const authError = validateAuth(request);
@@ -28,6 +43,7 @@ export const GET: RequestHandler = ({ request }) => {
28
43
  exitedAt: t.exitedAt?.toISOString() ?? null,
29
44
  id: t.id,
30
45
  isActive: t.isActive,
46
+ lastOutput: lastScrollbackLine(t.scrollback),
31
47
  pid: t.pid,
32
48
  status: t.status,
33
49
  }));
@@ -127,7 +143,10 @@ export const POST: RequestHandler = async ({ request }) => {
127
143
  return json(
128
144
  {
129
145
  command: terminal.command,
130
- createdAt: terminal.createdAt instanceof Date ? terminal.createdAt.toISOString() : terminal.createdAt,
146
+ createdAt:
147
+ terminal.createdAt instanceof Date
148
+ ? terminal.createdAt.toISOString()
149
+ : terminal.createdAt,
131
150
  cwd: terminal.cwd,
132
151
  id: terminal.id,
133
152
  pid: terminal.pid,
@@ -5,6 +5,21 @@ import { json } from '@sveltejs/kit';
5
5
 
6
6
  import type { RequestHandler } from './$types';
7
7
 
8
+ /** Extract the last non-empty line from a scrollback string. */
9
+ function lastScrollbackLine(scrollback: string): null | string {
10
+ if (!scrollback) {
11
+ return null;
12
+ }
13
+ const lines = scrollback.trimEnd().split('\n');
14
+ for (let i = lines.length - 1; i >= 0; i--) {
15
+ const line = lines[i].trim();
16
+ if (line) {
17
+ return line.slice(0, 200);
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
8
23
  // GET /api/terminals/:id — Get terminal details by ID
9
24
  export const GET: RequestHandler = ({ params, request }) => {
10
25
  const authError = validateAuth(request);
@@ -28,8 +43,7 @@ export const GET: RequestHandler = ({ params, request }) => {
28
43
  exitCode: terminal.exitCode,
29
44
  exitedAt: terminal.exitedAt?.toISOString() ?? null,
30
45
  id: terminal.id,
31
- lastOutput:
32
- terminal.scrollback.length > 0 ? terminal.scrollback[terminal.scrollback.length - 1] : null,
46
+ lastOutput: lastScrollbackLine(terminal.scrollback),
33
47
  pid: terminal.pid,
34
48
  sessionWs: `/ws/session/${terminal.id}`,
35
49
  status: terminal.status,
@@ -1,40 +1,12 @@
1
1
  import { validateAuth } from '$lib/modules/server/auth';
2
- import { toErrorMessage } from '$lib/modules/server/utils/error';
3
2
  import { json } from '@sveltejs/kit';
4
3
 
5
4
  import type { RequestHandler } from './$types';
6
5
 
7
- // TODO: Add HMAC signature validation for webhook payloads.
8
- // This is currently a stub endpoint — no signature verification is performed.
9
- export const POST: RequestHandler = async ({ request }) => {
10
- try {
11
- const authError = validateAuth(request);
12
- if (authError) {
13
- return authError;
14
- }
15
-
16
- const body = (await request.json()) as Record<string, unknown>;
17
-
18
- console.log('Webhook received:', {
19
- body,
20
- timestamp: new Date().toISOString(),
21
- });
22
-
23
- // In a full implementation, this would forward to Claude Code
24
- // For now, just log and acknowledge
25
-
26
- return json({
27
- message: 'Webhook received successfully',
28
- success: true,
29
- timestamp: new Date().toISOString(),
30
- });
31
- } catch (error) {
32
- console.error('[webhook] Failed to process webhook:', toErrorMessage(error));
33
- return json(
34
- {
35
- error: 'Failed to process webhook',
36
- },
37
- { status: 500 }
38
- );
6
+ export const POST: RequestHandler = ({ request }) => {
7
+ const authError = validateAuth(request);
8
+ if (authError) {
9
+ return authError;
39
10
  }
11
+ return json({ error: 'Webhook endpoint not implemented' }, { status: 501 });
40
12
  };