@juspay/shooter 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (488) hide show
  1. package/.claude/hooks/notifier.cjs +117 -33
  2. package/.claude/settings.json +14 -14
  3. package/README.md +116 -84
  4. package/bin/shooter.cjs +471 -102
  5. package/build/client/_app/immutable/assets/{0.CM9Hl6d-.css → 0.BhZOCxO4.css} +1 -1
  6. package/build/client/_app/immutable/assets/0.BhZOCxO4.css.br +0 -0
  7. package/build/client/_app/immutable/assets/0.BhZOCxO4.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/1.BYutk3aU.css +1 -0
  9. package/build/client/_app/immutable/assets/1.BYutk3aU.css.br +0 -0
  10. package/build/client/_app/immutable/assets/1.BYutk3aU.css.gz +0 -0
  11. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
  12. package/build/client/_app/immutable/assets/3.DGDHCVnW.css +1 -0
  13. package/build/client/_app/immutable/assets/3.DGDHCVnW.css.br +0 -0
  14. package/build/client/_app/immutable/assets/3.DGDHCVnW.css.gz +0 -0
  15. package/build/client/_app/immutable/assets/4.BFUut--w.css +1 -0
  16. package/build/client/_app/immutable/assets/4.BFUut--w.css.br +0 -0
  17. package/build/client/_app/immutable/assets/4.BFUut--w.css.gz +0 -0
  18. package/build/client/_app/immutable/assets/5.BTOx7yt7.css +1 -0
  19. package/build/client/_app/immutable/assets/5.BTOx7yt7.css.br +0 -0
  20. package/build/client/_app/immutable/assets/5.BTOx7yt7.css.gz +0 -0
  21. package/build/client/_app/immutable/assets/6.eZGZN-BF.css +1 -0
  22. package/build/client/_app/immutable/assets/6.eZGZN-BF.css.br +0 -0
  23. package/build/client/_app/immutable/assets/6.eZGZN-BF.css.gz +0 -0
  24. package/build/client/_app/immutable/assets/7.DwS5ZHBh.css +1 -0
  25. package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.br +0 -0
  26. package/build/client/_app/immutable/assets/7.DwS5ZHBh.css.gz +0 -0
  27. package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css +1 -0
  28. package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.br +0 -0
  29. package/build/client/_app/immutable/assets/ChatView.CwWbzIL-.css.gz +0 -0
  30. package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css +1 -0
  31. package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.br +0 -0
  32. package/build/client/_app/immutable/assets/Phone.FQEfwCX2.css.gz +0 -0
  33. package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css +1 -0
  34. package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.br +0 -0
  35. package/build/client/_app/immutable/assets/markdown.Dc-OSJWY.css.gz +0 -0
  36. package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css.gz +0 -0
  37. package/build/client/_app/immutable/chunks/B-K5Sh65.js +1 -0
  38. package/build/client/_app/immutable/chunks/B-K5Sh65.js.br +0 -0
  39. package/build/client/_app/immutable/chunks/B-K5Sh65.js.gz +0 -0
  40. package/build/client/_app/immutable/chunks/B5NAKyil.js +20 -0
  41. package/build/client/_app/immutable/chunks/B5NAKyil.js.br +0 -0
  42. package/build/client/_app/immutable/chunks/B5NAKyil.js.gz +0 -0
  43. package/build/client/_app/immutable/chunks/B8XegpSE.js +1 -0
  44. package/build/client/_app/immutable/chunks/B8XegpSE.js.br +0 -0
  45. package/build/client/_app/immutable/chunks/B8XegpSE.js.gz +0 -0
  46. package/build/client/_app/immutable/chunks/B8zoBsv3.js +6 -0
  47. package/build/client/_app/immutable/chunks/B8zoBsv3.js.br +0 -0
  48. package/build/client/_app/immutable/chunks/B8zoBsv3.js.gz +0 -0
  49. package/build/client/_app/immutable/chunks/BLszSzTT.js +1 -0
  50. package/build/client/_app/immutable/chunks/BLszSzTT.js.br +0 -0
  51. package/build/client/_app/immutable/chunks/BLszSzTT.js.gz +0 -0
  52. package/build/client/_app/immutable/chunks/BOYo8yTr.js +1 -0
  53. package/build/client/_app/immutable/chunks/BOYo8yTr.js.br +0 -0
  54. package/build/client/_app/immutable/chunks/BOYo8yTr.js.gz +0 -0
  55. package/build/client/_app/immutable/chunks/BTGVxaYV.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/BYqGCrTe.js +1 -0
  57. package/build/client/_app/immutable/chunks/BYqGCrTe.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/BYqGCrTe.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/BlxrFPDK.js.gz +0 -0
  60. package/build/client/_app/immutable/chunks/Bu1aqm5j.js +1 -0
  61. package/build/client/_app/immutable/chunks/Bu1aqm5j.js.br +0 -0
  62. package/build/client/_app/immutable/chunks/Bu1aqm5j.js.gz +0 -0
  63. package/build/client/_app/immutable/chunks/C4mLaWWx.js +1 -0
  64. package/build/client/_app/immutable/chunks/C4mLaWWx.js.br +0 -0
  65. package/build/client/_app/immutable/chunks/C4mLaWWx.js.gz +0 -0
  66. package/build/client/_app/immutable/chunks/CQjSATpv.js +61 -0
  67. package/build/client/_app/immutable/chunks/CQjSATpv.js.br +0 -0
  68. package/build/client/_app/immutable/chunks/CQjSATpv.js.gz +0 -0
  69. package/build/client/_app/immutable/chunks/CSoRdFvv.js +1 -0
  70. package/build/client/_app/immutable/chunks/CSoRdFvv.js.br +0 -0
  71. package/build/client/_app/immutable/chunks/CSoRdFvv.js.gz +0 -0
  72. package/build/client/_app/immutable/chunks/CZHsSL_X.js +1 -0
  73. package/build/client/_app/immutable/chunks/CZHsSL_X.js.br +0 -0
  74. package/build/client/_app/immutable/chunks/CZHsSL_X.js.gz +0 -0
  75. package/build/client/_app/immutable/chunks/DLu6yJIZ.js.gz +0 -0
  76. package/build/client/_app/immutable/chunks/DSU1n5N_.js +1 -0
  77. package/build/client/_app/immutable/chunks/DSU1n5N_.js.br +0 -0
  78. package/build/client/_app/immutable/chunks/DSU1n5N_.js.gz +0 -0
  79. package/build/client/_app/immutable/chunks/DVkn4r72.js +1 -0
  80. package/build/client/_app/immutable/chunks/DVkn4r72.js.br +0 -0
  81. package/build/client/_app/immutable/chunks/DVkn4r72.js.gz +0 -0
  82. package/build/client/_app/immutable/chunks/DjsDGxCa.js +41 -0
  83. package/build/client/_app/immutable/chunks/DjsDGxCa.js.br +0 -0
  84. package/build/client/_app/immutable/chunks/DjsDGxCa.js.gz +0 -0
  85. package/build/client/_app/immutable/chunks/PPVm8Dsz.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/UJOiqIYE.js +1 -0
  87. package/build/client/_app/immutable/chunks/UJOiqIYE.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/UJOiqIYE.js.gz +0 -0
  89. package/build/client/_app/immutable/chunks/r0JawsZc.js +2 -0
  90. package/build/client/_app/immutable/chunks/r0JawsZc.js.br +0 -0
  91. package/build/client/_app/immutable/chunks/r0JawsZc.js.gz +0 -0
  92. package/build/client/_app/immutable/entry/app.Z3zMnuSx.js +2 -0
  93. package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.br +0 -0
  94. package/build/client/_app/immutable/entry/app.Z3zMnuSx.js.gz +0 -0
  95. package/build/client/_app/immutable/entry/start.Dd-gIP4y.js +1 -0
  96. package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.br +2 -0
  97. package/build/client/_app/immutable/entry/start.Dd-gIP4y.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/0.D2YR8tTD.js +1 -0
  99. package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.br +0 -0
  100. package/build/client/_app/immutable/nodes/0.D2YR8tTD.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/1.B3m6rO4C.js +1 -0
  102. package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.br +0 -0
  103. package/build/client/_app/immutable/nodes/1.B3m6rO4C.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/2.CyRB2euU.js +1 -0
  105. package/build/client/_app/immutable/nodes/2.CyRB2euU.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/2.CyRB2euU.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/3.3yohCM25.js +3 -0
  108. package/build/client/_app/immutable/nodes/3.3yohCM25.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/3.3yohCM25.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/4.DEAcwl7l.js +1 -0
  111. package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/4.DEAcwl7l.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/5.C6bLGWQR.js +4 -0
  114. package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/5.C6bLGWQR.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/6.ByTzlA2D.js +2 -0
  117. package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.br +0 -0
  118. package/build/client/_app/immutable/nodes/6.ByTzlA2D.js.gz +0 -0
  119. package/build/client/_app/immutable/nodes/7.BPMfwzd2.js +2 -0
  120. package/build/client/_app/immutable/nodes/7.BPMfwzd2.js.br +0 -0
  121. package/build/client/_app/immutable/nodes/7.BPMfwzd2.js.gz +0 -0
  122. package/build/client/_app/version.json +1 -1
  123. package/build/client/_app/version.json.br +0 -0
  124. package/build/client/_app/version.json.gz +0 -0
  125. package/build/client/favicon.svg.gz +0 -0
  126. package/build/client/manifest.json +13 -0
  127. package/build/client/manifest.json.br +0 -0
  128. package/build/client/manifest.json.gz +0 -0
  129. package/build/pty-holder.cjs +37 -8
  130. package/build/server/chunks/0-Vk38tI2J.js +9 -0
  131. package/build/server/chunks/0-Vk38tI2J.js.map +1 -0
  132. package/build/server/chunks/1-BvYQX5MR.js +9 -0
  133. package/build/server/chunks/1-BvYQX5MR.js.map +1 -0
  134. package/build/server/chunks/2-Cl7R4Qk2.js +9 -0
  135. package/build/server/chunks/2-Cl7R4Qk2.js.map +1 -0
  136. package/build/server/chunks/3-Ck7ewhOX.js +9 -0
  137. package/build/server/chunks/3-Ck7ewhOX.js.map +1 -0
  138. package/build/server/chunks/4-CnDeRm2Z.js +9 -0
  139. package/build/server/chunks/4-CnDeRm2Z.js.map +1 -0
  140. package/build/server/chunks/5-IxitzEvN.js +9 -0
  141. package/build/server/chunks/5-IxitzEvN.js.map +1 -0
  142. package/build/server/chunks/6-CyZ3r1iS.js +9 -0
  143. package/build/server/chunks/6-CyZ3r1iS.js.map +1 -0
  144. package/build/server/chunks/7-BmI7du46.js +9 -0
  145. package/build/server/chunks/7-BmI7du46.js.map +1 -0
  146. package/build/server/chunks/Button-Cs1aE6ka.js +80 -0
  147. package/build/server/chunks/Button-Cs1aE6ka.js.map +1 -0
  148. package/build/server/chunks/EmptyState-DDFH1K8g.js +26 -0
  149. package/build/server/chunks/EmptyState-DDFH1K8g.js.map +1 -0
  150. package/build/server/chunks/Icon-CEUrotA6.js +36 -0
  151. package/build/server/chunks/Icon-CEUrotA6.js.map +1 -0
  152. package/build/server/chunks/Shimmer-DB8W1zt6.js +10 -0
  153. package/build/server/chunks/Shimmer-DB8W1zt6.js.map +1 -0
  154. package/build/server/chunks/_error.svelte-uCOJNxvr.js +39 -0
  155. package/build/server/chunks/_error.svelte-uCOJNxvr.js.map +1 -0
  156. package/build/server/chunks/_layout.svelte-CtWmEJwe.js +56 -0
  157. package/build/server/chunks/_layout.svelte-CtWmEJwe.js.map +1 -0
  158. package/build/server/chunks/_page.svelte-BcZaKdX9.js +45 -0
  159. package/build/server/chunks/_page.svelte-BcZaKdX9.js.map +1 -0
  160. package/build/server/chunks/_page.svelte-BdYynOck.js +85 -0
  161. package/build/server/chunks/_page.svelte-BdYynOck.js.map +1 -0
  162. package/build/server/chunks/_page.svelte-BgevQjq1.js +101 -0
  163. package/build/server/chunks/_page.svelte-BgevQjq1.js.map +1 -0
  164. package/build/server/chunks/_page.svelte-CVq6tRb3.js +550 -0
  165. package/build/server/chunks/_page.svelte-CVq6tRb3.js.map +1 -0
  166. package/build/server/chunks/_page.svelte-CxWcQ0Am.js +651 -0
  167. package/build/server/chunks/_page.svelte-CxWcQ0Am.js.map +1 -0
  168. package/build/server/chunks/_page.svelte-DO4oa_LY.js +44 -0
  169. package/build/server/chunks/_page.svelte-DO4oa_LY.js.map +1 -0
  170. package/build/server/chunks/{_server.ts-CbDRDIoP.js → _server.ts-BStnNIcq.js} +9 -11
  171. package/build/server/chunks/_server.ts-BStnNIcq.js.map +1 -0
  172. package/build/server/chunks/{_server.ts-DRVbgm6k.js → _server.ts-CAxsWKvS.js} +22 -25
  173. package/build/server/chunks/_server.ts-CAxsWKvS.js.map +1 -0
  174. package/build/server/chunks/{_server.ts-CPa6DgIt.js → _server.ts-COu0vNpd.js} +6 -6
  175. package/build/server/chunks/_server.ts-COu0vNpd.js.map +1 -0
  176. package/build/server/chunks/{_server.ts-C29xzfaw.js → _server.ts-CTpcLUH8.js} +10 -10
  177. package/build/server/chunks/_server.ts-CTpcLUH8.js.map +1 -0
  178. package/build/server/chunks/{_server.ts-D4MNi4cD.js → _server.ts-Cf84YIaW.js} +3 -3
  179. package/build/server/chunks/{_server.ts-D4MNi4cD.js.map → _server.ts-Cf84YIaW.js.map} +1 -1
  180. package/build/server/chunks/{_server.ts-BL2FGb5Z.js → _server.ts-Ch-6iOHp.js} +99 -53
  181. package/build/server/chunks/_server.ts-Ch-6iOHp.js.map +1 -0
  182. package/build/server/chunks/_server.ts-CtH0dhUp.js +71 -0
  183. package/build/server/chunks/_server.ts-CtH0dhUp.js.map +1 -0
  184. package/build/server/chunks/_server.ts-DB_Kg97c.js +73 -0
  185. package/build/server/chunks/_server.ts-DB_Kg97c.js.map +1 -0
  186. package/build/server/chunks/{_server.ts-DfajWaqh.js → _server.ts-DV8zTCF9.js} +7 -9
  187. package/build/server/chunks/_server.ts-DV8zTCF9.js.map +1 -0
  188. package/build/server/chunks/_server.ts-DYpJImqd.js +99 -0
  189. package/build/server/chunks/_server.ts-DYpJImqd.js.map +1 -0
  190. package/build/server/chunks/{_server.ts-ColfDHW8.js → _server.ts-DYvb9ijZ.js} +21 -10
  191. package/build/server/chunks/_server.ts-DYvb9ijZ.js.map +1 -0
  192. package/build/server/chunks/{_server.ts-Cv_OrRuL.js → _server.ts-Deok2y88.js} +209 -34
  193. package/build/server/chunks/_server.ts-Deok2y88.js.map +1 -0
  194. package/build/server/chunks/{_server.ts-y9-WYDMa.js → _server.ts-WhTJBEJy.js} +5 -4
  195. package/build/server/chunks/{_server.ts-y9-WYDMa.js.map → _server.ts-WhTJBEJy.js.map} +1 -1
  196. package/build/server/chunks/{_server.ts-BjOJsoy4.js → _server.ts-XzT2UHM1.js} +6 -5
  197. package/build/server/chunks/_server.ts-XzT2UHM1.js.map +1 -0
  198. package/build/server/chunks/{_server.ts-BgdjBZco.js → _server.ts-tSpgyl1D.js} +7 -5
  199. package/build/server/chunks/_server.ts-tSpgyl1D.js.map +1 -0
  200. package/build/server/chunks/{_server.ts-BihKSdj_.js → _server.ts-vekTmWAx.js} +8 -8
  201. package/build/server/chunks/_server.ts-vekTmWAx.js.map +1 -0
  202. package/build/server/chunks/{auth-CEgFis71.js → auth-DeCdZ83n.js} +2 -2
  203. package/build/server/chunks/{auth-CEgFis71.js.map → auth-DeCdZ83n.js.map} +1 -1
  204. package/build/server/chunks/client-BdGHe_hY.js +25 -0
  205. package/build/server/chunks/client-BdGHe_hY.js.map +1 -0
  206. package/build/server/chunks/client2-CCBGA-2V.js +7 -0
  207. package/build/server/chunks/client2-CCBGA-2V.js.map +1 -0
  208. package/build/server/chunks/error-DDXB3duW.js +12 -0
  209. package/build/server/chunks/error-DDXB3duW.js.map +1 -0
  210. package/build/server/chunks/{exports-CJ0Q5XmL.js → index-DwaY1cAm.js} +1111 -1634
  211. package/build/server/chunks/index-DwaY1cAm.js.map +1 -0
  212. package/build/server/chunks/index-server-CrDaL06Y.js +9 -0
  213. package/build/server/chunks/index-server-CrDaL06Y.js.map +1 -0
  214. package/build/server/chunks/index2-CgclKpUj.js +58 -0
  215. package/build/server/chunks/index2-CgclKpUj.js.map +1 -0
  216. package/build/server/chunks/{library-apns-BHxLmuIx.js → library-apns-BqJbvSKh.js} +4 -4
  217. package/build/server/chunks/library-apns-BqJbvSKh.js.map +1 -0
  218. package/build/server/chunks/markdown-W_mTBct0.js +8 -0
  219. package/build/server/chunks/markdown-W_mTBct0.js.map +1 -0
  220. package/build/server/chunks/opencode-db-path-DcfhJtJy.js +15 -0
  221. package/build/server/chunks/opencode-db-path-DcfhJtJy.js.map +1 -0
  222. package/build/server/chunks/{pty-manager-C0FhBiVq.js → pty-manager-BQVB7IVj.js} +155 -326
  223. package/build/server/chunks/pty-manager-BQVB7IVj.js.map +1 -0
  224. package/build/server/chunks/root-DDSnEAZv.js +1171 -0
  225. package/build/server/chunks/root-DDSnEAZv.js.map +1 -0
  226. package/build/server/chunks/{shared-server-BDY8jh20.js → shared-server-sSGG17Df.js} +2 -3
  227. package/build/server/chunks/{shared-server-BDY8jh20.js.map → shared-server-sSGG17Df.js.map} +1 -1
  228. package/build/server/chunks/state.svelte-hBbXlUak.js +11 -0
  229. package/build/server/chunks/state.svelte-hBbXlUak.js.map +1 -0
  230. package/build/server/chunks/stores-DHNzYNpX.js +28 -0
  231. package/build/server/chunks/stores-DHNzYNpX.js.map +1 -0
  232. package/build/server/index.js +1085 -2242
  233. package/build/server/index.js.map +1 -1
  234. package/build/server/manifest.js +39 -25
  235. package/build/server/manifest.js.map +1 -1
  236. package/package.json +32 -9
  237. package/scripts/fix-generated-types.sh +37 -0
  238. package/scripts/homebrew/shooter.rb +51 -0
  239. package/scripts/install.sh +348 -186
  240. package/scripts/setup.cjs +215 -45
  241. package/server.ts +114 -71
  242. package/src/app.css +12 -3
  243. package/src/app.d.ts +13 -20
  244. package/src/app.html +3 -2
  245. package/src/generated/types/API.ts +280 -0
  246. package/src/generated/types/APN.ts +186 -203
  247. package/src/generated/types/CLI.ts +18 -25
  248. package/src/generated/types/Client.ts +589 -0
  249. package/src/generated/types/Config.ts +53 -0
  250. package/src/generated/types/Holder.ts +638 -0
  251. package/src/generated/types/JWT.ts +39 -50
  252. package/src/generated/types/Notification.ts +426 -0
  253. package/src/generated/types/OpenCode.ts +356 -0
  254. package/src/generated/types/Sessions.ts +570 -0
  255. package/src/generated/types/Terminal.ts +2184 -2071
  256. package/src/generated/types/WsProtocol.ts +2004 -0
  257. package/src/generated/types/index.ts +9 -3
  258. package/src/lib/env.ts +29 -0
  259. package/src/lib/modules/client/common/cache.ts +10 -2
  260. package/src/lib/modules/client/common/config-guard.ts +37 -5
  261. package/src/lib/modules/client/common/error.ts +10 -0
  262. package/src/lib/modules/client/common/index.ts +6 -5
  263. package/src/lib/modules/client/common/markdown.ts +22 -1
  264. package/src/lib/modules/client/common/native-bridge.ts +28 -20
  265. package/src/lib/modules/client/common/time.ts +13 -11
  266. package/src/lib/modules/client/terminal/ChatView.svelte +354 -74
  267. package/src/lib/modules/client/terminal/CommandPalette.svelte +3 -2
  268. package/src/lib/modules/client/terminal/ConnectionStatus.svelte +7 -1
  269. package/src/lib/modules/client/terminal/LaunchSheet.svelte +147 -84
  270. package/src/lib/modules/client/terminal/QuickKeys.svelte +3 -1
  271. package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +2 -5
  272. package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +27 -24
  273. package/src/lib/modules/client/terminal/xterm-wrapper.ts +74 -45
  274. package/src/lib/modules/server/apn/library-apns.ts +3 -2
  275. package/src/lib/modules/server/apn/notification-history.ts +2 -13
  276. package/src/lib/modules/server/apn/notification-sessions.ts +3 -13
  277. package/src/lib/modules/server/apn/pending-requests.ts +3 -8
  278. package/src/lib/modules/server/apn/types.ts +5 -4
  279. package/src/lib/modules/server/cli/index.ts +3 -2
  280. package/src/lib/modules/server/fcm/fcm-service.ts +8 -6
  281. package/src/lib/modules/server/sessions/jsonl-parser.ts +3 -3
  282. package/src/lib/modules/server/sessions/jsonl-reader.ts +86 -26
  283. package/src/lib/modules/server/sessions/opencode-db-path.ts +26 -0
  284. package/src/lib/modules/server/sessions/opencode-reader.ts +13 -15
  285. package/src/lib/modules/server/sessions/process-detector.ts +103 -0
  286. package/src/lib/modules/server/sessions/types.ts +11 -22
  287. package/src/lib/modules/server/terminal/holder-client.ts +272 -248
  288. package/src/lib/modules/server/terminal/opencode-watcher.ts +547 -556
  289. package/src/lib/modules/server/terminal/pty-holder.cjs +37 -8
  290. package/src/lib/modules/server/terminal/pty-manager.ts +157 -115
  291. package/src/lib/modules/server/terminal/session-watcher.ts +6 -4
  292. package/src/lib/modules/server/terminal/terminal-store.ts +131 -128
  293. package/src/lib/modules/server/utils/error.ts +9 -0
  294. package/src/lib/modules/server/ws/events-handler.ts +12 -6
  295. package/src/lib/modules/server/ws/keepalive.ts +86 -69
  296. package/src/lib/modules/server/ws/server.ts +43 -37
  297. package/src/lib/modules/server/ws/session-handler.ts +332 -147
  298. package/src/lib/modules/server/ws/terminal-handler.ts +29 -17
  299. package/src/lib/modules/server/ws/ticket-store.ts +29 -26
  300. package/src/lib/theme.css +30 -0
  301. package/src/lib/types/config.ts +1 -6
  302. package/src/routes/+error.svelte +94 -0
  303. package/src/routes/+layout.svelte +66 -31
  304. package/src/routes/+page.svelte +25 -22
  305. package/src/routes/api/debug/+server.ts +3 -1
  306. package/src/routes/api/device-token/+server.ts +60 -60
  307. package/src/routes/api/health/+server.ts +81 -73
  308. package/src/routes/api/notify/+server.ts +115 -68
  309. package/src/routes/api/qr-config/+server.ts +30 -32
  310. package/src/routes/api/response/+server.ts +9 -4
  311. package/src/routes/api/sessions/+server.ts +15 -5
  312. package/src/routes/api/sessions/connect/+server.ts +125 -0
  313. package/src/routes/api/sessions/detect/+server.ts +27 -0
  314. package/src/routes/api/terminals/+server.ts +26 -24
  315. package/src/routes/api/terminals/[id]/+server.ts +13 -7
  316. package/src/routes/api/terminals/[id]/paste-image/+server.ts +54 -52
  317. package/src/routes/api/terminals/[id]/resize/+server.ts +6 -3
  318. package/src/routes/api/webhook/+server.ts +8 -10
  319. package/src/routes/api/ws-status/+server.ts +7 -5
  320. package/src/routes/api/ws-ticket/+server.ts +42 -41
  321. package/src/routes/config/+page.svelte +149 -75
  322. package/src/routes/project/+page.svelte +165 -35
  323. package/src/routes/session/[id]/+page.svelte +479 -283
  324. package/src/routes/terminals/+page.svelte +58 -45
  325. package/src/routes/terminals/[id]/+page.svelte +223 -91
  326. package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.br +0 -0
  327. package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.gz +0 -0
  328. package/build/client/_app/immutable/assets/3.C0uFg0IS.css +0 -1
  329. package/build/client/_app/immutable/assets/3.C0uFg0IS.css.br +0 -0
  330. package/build/client/_app/immutable/assets/3.C0uFg0IS.css.gz +0 -0
  331. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css +0 -1
  332. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.br +0 -0
  333. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.gz +0 -0
  334. package/build/client/_app/immutable/assets/5.DRjApZQW.css +0 -1
  335. package/build/client/_app/immutable/assets/5.DRjApZQW.css.br +0 -0
  336. package/build/client/_app/immutable/assets/5.DRjApZQW.css.gz +0 -0
  337. package/build/client/_app/immutable/assets/6.AraZrY8I.css +0 -1
  338. package/build/client/_app/immutable/assets/6.AraZrY8I.css.br +0 -0
  339. package/build/client/_app/immutable/assets/6.AraZrY8I.css.gz +0 -0
  340. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css +0 -1
  341. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.br +0 -0
  342. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.gz +0 -0
  343. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css +0 -1
  344. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.br +0 -0
  345. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.gz +0 -0
  346. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css +0 -1
  347. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.br +0 -0
  348. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.gz +0 -0
  349. package/build/client/_app/immutable/chunks/BNJphC1q.js +0 -56
  350. package/build/client/_app/immutable/chunks/BNJphC1q.js.br +0 -0
  351. package/build/client/_app/immutable/chunks/BNJphC1q.js.gz +0 -0
  352. package/build/client/_app/immutable/chunks/Bvk7mfPM.js +0 -1
  353. package/build/client/_app/immutable/chunks/Bvk7mfPM.js.br +0 -0
  354. package/build/client/_app/immutable/chunks/Bvk7mfPM.js.gz +0 -0
  355. package/build/client/_app/immutable/chunks/CAokzuPQ.js +0 -1
  356. package/build/client/_app/immutable/chunks/CAokzuPQ.js.br +0 -0
  357. package/build/client/_app/immutable/chunks/CAokzuPQ.js.gz +0 -0
  358. package/build/client/_app/immutable/chunks/CGLrx-H5.js +0 -1
  359. package/build/client/_app/immutable/chunks/CGLrx-H5.js.br +0 -0
  360. package/build/client/_app/immutable/chunks/CGLrx-H5.js.gz +0 -0
  361. package/build/client/_app/immutable/chunks/CgCpWzEA.js +0 -1
  362. package/build/client/_app/immutable/chunks/CgCpWzEA.js.br +0 -0
  363. package/build/client/_app/immutable/chunks/CgCpWzEA.js.gz +0 -0
  364. package/build/client/_app/immutable/chunks/Cjwk_cGO.js +0 -6
  365. package/build/client/_app/immutable/chunks/Cjwk_cGO.js.br +0 -0
  366. package/build/client/_app/immutable/chunks/Cjwk_cGO.js.gz +0 -0
  367. package/build/client/_app/immutable/chunks/CtQ8EED1.js +0 -11
  368. package/build/client/_app/immutable/chunks/CtQ8EED1.js.br +0 -0
  369. package/build/client/_app/immutable/chunks/CtQ8EED1.js.gz +0 -0
  370. package/build/client/_app/immutable/chunks/DERQCisl.js +0 -1
  371. package/build/client/_app/immutable/chunks/DERQCisl.js.br +0 -0
  372. package/build/client/_app/immutable/chunks/DERQCisl.js.gz +0 -0
  373. package/build/client/_app/immutable/chunks/DKrg8TQs.js +0 -1
  374. package/build/client/_app/immutable/chunks/DKrg8TQs.js.br +0 -0
  375. package/build/client/_app/immutable/chunks/DKrg8TQs.js.gz +0 -0
  376. package/build/client/_app/immutable/chunks/Dkkpz_4D.js +0 -126
  377. package/build/client/_app/immutable/chunks/Dkkpz_4D.js.br +0 -0
  378. package/build/client/_app/immutable/chunks/Dkkpz_4D.js.gz +0 -0
  379. package/build/client/_app/immutable/chunks/DoczjQhA.js +0 -1
  380. package/build/client/_app/immutable/chunks/DoczjQhA.js.br +0 -0
  381. package/build/client/_app/immutable/chunks/DoczjQhA.js.gz +0 -0
  382. package/build/client/_app/immutable/chunks/RpcNruLP.js +0 -2
  383. package/build/client/_app/immutable/chunks/RpcNruLP.js.br +0 -0
  384. package/build/client/_app/immutable/chunks/RpcNruLP.js.gz +0 -0
  385. package/build/client/_app/immutable/chunks/a-St0Zwo.js +0 -1
  386. package/build/client/_app/immutable/chunks/a-St0Zwo.js.br +0 -0
  387. package/build/client/_app/immutable/chunks/a-St0Zwo.js.gz +0 -0
  388. package/build/client/_app/immutable/chunks/bo70OQUZ.js +0 -1
  389. package/build/client/_app/immutable/chunks/bo70OQUZ.js.br +0 -0
  390. package/build/client/_app/immutable/chunks/bo70OQUZ.js.gz +0 -0
  391. package/build/client/_app/immutable/entry/app.QvGgdvTI.js +0 -2
  392. package/build/client/_app/immutable/entry/app.QvGgdvTI.js.br +0 -0
  393. package/build/client/_app/immutable/entry/app.QvGgdvTI.js.gz +0 -0
  394. package/build/client/_app/immutable/entry/start.BntDNRMC.js +0 -1
  395. package/build/client/_app/immutable/entry/start.BntDNRMC.js.br +0 -0
  396. package/build/client/_app/immutable/entry/start.BntDNRMC.js.gz +0 -0
  397. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js +0 -1
  398. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.br +0 -0
  399. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.gz +0 -0
  400. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js +0 -1
  401. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.br +0 -0
  402. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.gz +0 -0
  403. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js +0 -1
  404. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.br +0 -0
  405. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.gz +0 -0
  406. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js +0 -3
  407. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.br +0 -0
  408. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.gz +0 -0
  409. package/build/client/_app/immutable/nodes/4.D-cIe70D.js +0 -1
  410. package/build/client/_app/immutable/nodes/4.D-cIe70D.js.br +0 -0
  411. package/build/client/_app/immutable/nodes/4.D-cIe70D.js.gz +0 -0
  412. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js +0 -1
  413. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.br +0 -0
  414. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.gz +0 -0
  415. package/build/client/_app/immutable/nodes/6.BB7QE48r.js +0 -2
  416. package/build/client/_app/immutable/nodes/6.BB7QE48r.js.br +0 -0
  417. package/build/client/_app/immutable/nodes/6.BB7QE48r.js.gz +0 -0
  418. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js +0 -2
  419. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.br +0 -0
  420. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.gz +0 -0
  421. package/build/client/manifest.webmanifest +0 -1
  422. package/build/client/registerSW.js +0 -1
  423. package/build/client/registerSW.js.br +0 -0
  424. package/build/client/registerSW.js.gz +0 -0
  425. package/build/client/sw.js +0 -222
  426. package/build/client/sw.js.br +0 -0
  427. package/build/client/sw.js.gz +0 -0
  428. package/build/client/workbox-5119daf5.js +0 -3395
  429. package/build/client/workbox-5119daf5.js.br +0 -0
  430. package/build/client/workbox-5119daf5.js.gz +0 -0
  431. package/build/server/chunks/0-q2IUp76Y.js +0 -9
  432. package/build/server/chunks/0-q2IUp76Y.js.map +0 -1
  433. package/build/server/chunks/1-CU50G5wZ.js +0 -9
  434. package/build/server/chunks/1-CU50G5wZ.js.map +0 -1
  435. package/build/server/chunks/2-D01t9s8T.js +0 -9
  436. package/build/server/chunks/2-D01t9s8T.js.map +0 -1
  437. package/build/server/chunks/3-5PUQ04wC.js +0 -9
  438. package/build/server/chunks/3-5PUQ04wC.js.map +0 -1
  439. package/build/server/chunks/4-e7gywnSG.js +0 -9
  440. package/build/server/chunks/4-e7gywnSG.js.map +0 -1
  441. package/build/server/chunks/5-CA1SA6KZ.js +0 -9
  442. package/build/server/chunks/5-CA1SA6KZ.js.map +0 -1
  443. package/build/server/chunks/6-71H221sV.js +0 -9
  444. package/build/server/chunks/6-71H221sV.js.map +0 -1
  445. package/build/server/chunks/7-Bo-vmdyz.js +0 -9
  446. package/build/server/chunks/7-Bo-vmdyz.js.map +0 -1
  447. package/build/server/chunks/_layout.svelte-SFHOxs74.js +0 -132
  448. package/build/server/chunks/_layout.svelte-SFHOxs74.js.map +0 -1
  449. package/build/server/chunks/_page.svelte-B4w-2wD-.js +0 -120
  450. package/build/server/chunks/_page.svelte-B4w-2wD-.js.map +0 -1
  451. package/build/server/chunks/_page.svelte-B_qAXjkh.js +0 -213
  452. package/build/server/chunks/_page.svelte-B_qAXjkh.js.map +0 -1
  453. package/build/server/chunks/_page.svelte-CsF1_TRG.js +0 -50
  454. package/build/server/chunks/_page.svelte-CsF1_TRG.js.map +0 -1
  455. package/build/server/chunks/_page.svelte-DJC6U-P0.js +0 -68
  456. package/build/server/chunks/_page.svelte-DJC6U-P0.js.map +0 -1
  457. package/build/server/chunks/_page.svelte-DQ6HBtsz.js +0 -407
  458. package/build/server/chunks/_page.svelte-DQ6HBtsz.js.map +0 -1
  459. package/build/server/chunks/_page.svelte-LbhhjP21.js +0 -148
  460. package/build/server/chunks/_page.svelte-LbhhjP21.js.map +0 -1
  461. package/build/server/chunks/_server.ts-BL2FGb5Z.js.map +0 -1
  462. package/build/server/chunks/_server.ts-BgdjBZco.js.map +0 -1
  463. package/build/server/chunks/_server.ts-BihKSdj_.js.map +0 -1
  464. package/build/server/chunks/_server.ts-BjOJsoy4.js.map +0 -1
  465. package/build/server/chunks/_server.ts-C29xzfaw.js.map +0 -1
  466. package/build/server/chunks/_server.ts-CPa6DgIt.js.map +0 -1
  467. package/build/server/chunks/_server.ts-CbDRDIoP.js.map +0 -1
  468. package/build/server/chunks/_server.ts-Cl1OEWL4.js +0 -54
  469. package/build/server/chunks/_server.ts-Cl1OEWL4.js.map +0 -1
  470. package/build/server/chunks/_server.ts-ColfDHW8.js.map +0 -1
  471. package/build/server/chunks/_server.ts-Cv_OrRuL.js.map +0 -1
  472. package/build/server/chunks/_server.ts-DRVbgm6k.js.map +0 -1
  473. package/build/server/chunks/_server.ts-DfajWaqh.js.map +0 -1
  474. package/build/server/chunks/client-CxCatAKr.js +0 -255
  475. package/build/server/chunks/client-CxCatAKr.js.map +0 -1
  476. package/build/server/chunks/error.svelte-BqdwMWdK.js +0 -26
  477. package/build/server/chunks/error.svelte-BqdwMWdK.js.map +0 -1
  478. package/build/server/chunks/exports-CJ0Q5XmL.js.map +0 -1
  479. package/build/server/chunks/index2-DAxIoAO-.js +0 -36
  480. package/build/server/chunks/index2-DAxIoAO-.js.map +0 -1
  481. package/build/server/chunks/jsonl-parser-dmZU_Hyu.js +0 -137
  482. package/build/server/chunks/jsonl-parser-dmZU_Hyu.js.map +0 -1
  483. package/build/server/chunks/library-apns-BHxLmuIx.js.map +0 -1
  484. package/build/server/chunks/markdown-Bxrl3cCF.js +0 -1241
  485. package/build/server/chunks/markdown-Bxrl3cCF.js.map +0 -1
  486. package/build/server/chunks/pty-manager-C0FhBiVq.js.map +0 -1
  487. package/build/server/chunks/stores-D0HorpgL.js +0 -36
  488. package/build/server/chunks/stores-D0HorpgL.js.map +0 -1
@@ -1,31 +1,23 @@
1
1
  <script lang="ts">
2
- import { Banner, Button, Choicebox, Input, Select, Sheet } from '@juspay/svelte-ui-components';
2
+ import type { CreateTerminalResponse } from '$generated/types';
3
+
4
+ import { Banner, Button, Choicebox, Input, Select } from '@juspay/svelte-ui-components';
3
5
  import { onMount } from 'svelte';
4
6
 
5
7
  interface Props {
6
8
  apiKey: string;
7
9
  onClose: () => void;
8
- onLaunch: (response: TerminalResponse) => void;
10
+ onLaunch: (response: CreateTerminalResponse) => void;
9
11
  open: boolean;
10
12
  }
11
13
 
12
- interface TerminalResponse {
13
- command: string;
14
- createdAt: string;
15
- cwd: string;
16
- id: string;
17
- pid: number;
18
- sessionWs: string;
19
- ws: string;
20
- }
21
-
22
14
  interface Preset {
23
15
  args: string[];
24
16
  command: string;
25
17
  label: string;
26
18
  }
27
19
 
28
- let { apiKey, onClose, onLaunch, open = $bindable() }: Props = $props();
20
+ const { apiKey, onClose, onLaunch, open }: Props = $props();
29
21
 
30
22
  const presets: Preset[] = [
31
23
  { args: [], command: 'claude', label: 'Claude Code' },
@@ -34,8 +26,7 @@
34
26
  { args: [], command: 'bash', label: 'Bash' },
35
27
  ];
36
28
 
37
- let selectedPreset = $state<number>(0);
38
- let customCommand = $state('');
29
+ let selectedPreset = $state(0);
39
30
  let projectPaths = $state<string[]>([]);
40
31
  let selectedCwd = $state('');
41
32
  let customCwd = $state('');
@@ -51,7 +42,9 @@
51
42
  const response = await fetch('/api/sessions?limit=50&offset=0', {
52
43
  headers: { Authorization: `Bearer ${apiKey}` },
53
44
  });
54
- if (!response.ok) {return;}
45
+ if (!response.ok) {
46
+ return;
47
+ }
55
48
  const data: { projects: { fullPath: string }[] } = await response.json();
56
49
  const paths = data.projects
57
50
  .map((p) => p.fullPath)
@@ -69,33 +62,30 @@
69
62
  selectedPreset = index;
70
63
  }
71
64
 
72
- function isCustom(): boolean {
73
- return presets[selectedPreset].command === '';
74
- }
75
-
76
65
  function getCommand(): string {
77
- if (isCustom()) {return customCommand.trim().split(/\s+/)[0] || '';}
78
66
  return presets[selectedPreset].command;
79
67
  }
80
68
 
81
69
  function getArgs(): string[] {
82
- if (isCustom()) {
83
- const parts = customCommand.trim().split(/\s+/);
84
- return parts.slice(1);
85
- }
86
70
  return presets[selectedPreset].args;
87
71
  }
88
72
 
89
73
  function getEffectiveCwd(): string {
90
74
  const custom = customCwd.trim();
91
- if (custom) {return custom;}
92
- if (selectedCwd) {return selectedCwd;}
75
+ if (custom) {
76
+ return custom;
77
+ }
78
+ if (selectedCwd) {
79
+ return selectedCwd;
80
+ }
93
81
  return '/tmp';
94
82
  }
95
83
 
96
84
  async function handleLaunch(): Promise<void> {
97
85
  const command = getCommand();
98
- if (!command) {return;}
86
+ if (!command) {
87
+ return;
88
+ }
99
89
 
100
90
  launching = true;
101
91
  launchError = '';
@@ -119,7 +109,7 @@
119
109
  return;
120
110
  }
121
111
 
122
- const result: TerminalResponse = await response.json();
112
+ const result: CreateTerminalResponse = await response.json();
123
113
  onLaunch(result);
124
114
  } catch {
125
115
  launchError = 'Network error — is the server running?';
@@ -127,17 +117,34 @@
127
117
  launching = false;
128
118
  }
129
119
  }
120
+
121
+ function handleBackdropClick(event: MouseEvent): void {
122
+ if (event.target === event.currentTarget) {
123
+ onClose();
124
+ }
125
+ }
126
+
127
+ function handleKeydown(event: KeyboardEvent): void {
128
+ if (!open) {
129
+ return;
130
+ }
131
+ if (event.key === 'Escape') {
132
+ onClose();
133
+ }
134
+ }
130
135
  </script>
131
136
 
132
- <Sheet
133
- bind:open
134
- title="New Terminal"
135
- side="bottom"
136
- onclose={onClose}
137
- classes="launch-sheet"
138
- >
139
- {#snippet content()}
140
- <div class="launch-form">
137
+ <svelte:window onkeydown={handleKeydown} />
138
+
139
+ {#if open}
140
+ <div class="overlay" role="presentation" onclick={handleBackdropClick}>
141
+ <div class="sheet" role="dialog" aria-modal="true" aria-label="New Terminal">
142
+ <div class="handle-bar">
143
+ <div class="handle"></div>
144
+ </div>
145
+
146
+ <h2 class="sheet-title">New Terminal</h2>
147
+
141
148
  <div class="section">
142
149
  <span class="section-label">Quick Launch</span>
143
150
  <div class="preset-grid">
@@ -145,7 +152,9 @@
145
152
  <Choicebox
146
153
  mode="radio"
147
154
  selected={selectedPreset === i}
148
- onclick={() => selectPreset(i)}
155
+ onclick={() => {
156
+ selectPreset(i);
157
+ }}
149
158
  classes="preset-choice"
150
159
  >
151
160
  {preset.label}
@@ -157,10 +166,14 @@
157
166
  <div class="section">
158
167
  <span class="section-label">Working Directory</span>
159
168
  <Select
160
- items={projectPaths.length > 0 ? projectPaths.map((p) => ({ id: p, label: p })) : [{ id: '', label: 'No recent projects' }]}
161
- value={selectedCwd ? [selectedCwd] : (projectPaths.length > 0 ? [projectPaths[0]] : [''])}
169
+ items={projectPaths.length > 0
170
+ ? projectPaths.map((p) => ({ id: p, label: p }))
171
+ : [{ id: '', label: 'No recent projects' }]}
172
+ value={selectedCwd ? [selectedCwd] : projectPaths.length > 0 ? [projectPaths[0]] : ['']}
162
173
  placeholder="Select a project"
163
- onchange={(value) => { selectedCwd = value[0] || ''; }}
174
+ onchange={(value) => {
175
+ selectedCwd = value[0] || '';
176
+ }}
164
177
  classes="launch-select"
165
178
  />
166
179
  <div class="custom-cwd-group">
@@ -174,21 +187,9 @@
174
187
  </div>
175
188
  </div>
176
189
 
177
- {#if isCustom()}
178
- <div class="section">
179
- <Input
180
- label="Custom Command"
181
- bind:value={customCommand}
182
- dataType="text"
183
- placeholder="e.g. node server.js"
184
- classes="input-mono launch-input"
185
- />
186
- </div>
187
- {/if}
188
-
189
190
  <Button
190
191
  classes="btn-launch"
191
- disabled={launching || (!isCustom() ? false : !customCommand.trim())}
192
+ disabled={launching}
192
193
  onclick={handleLaunch}
193
194
  showLoader={launching}
194
195
  text={launching ? 'Launching...' : 'Launch Terminal'}
@@ -198,47 +199,95 @@
198
199
  <Banner text={launchError} classes="banner-error launch-error-banner" />
199
200
  {/if}
200
201
  </div>
201
- {/snippet}
202
- </Sheet>
202
+ </div>
203
+ {/if}
203
204
 
204
205
  <style>
205
- :global(.launch-sheet) {
206
- --sheet-background: var(--ds-gray-100);
207
- --sheet-overlay-background: rgba(0, 0, 0, 0.6);
208
- --sheet-overlay-z-index: 200;
209
- --sheet-z-index: 201;
210
- --sheet-height: auto;
211
- --sheet-max-height: 90vh;
212
- --sheet-box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);
213
- --sheet-header-padding: var(--space-4) var(--space-5);
214
- --sheet-header-background: var(--ds-gray-100);
215
- --sheet-header-border-bottom: none;
216
- --sheet-title-font-size: var(--text-xl);
217
- --sheet-title-font-weight: 600;
218
- --sheet-title-color: var(--text-primary);
219
- --sheet-content-padding: 0 var(--space-5) calc(var(--space-8, 32px) + env(safe-area-inset-bottom, 0px));
220
- --sheet-close-button-color: var(--text-secondary);
221
- --sheet-close-button-hover-background: var(--component-bg-hover);
222
- --sheet-border: none;
206
+ .overlay {
207
+ position: fixed;
208
+ inset: 0;
209
+ background: rgba(0, 0, 0, 0.6);
210
+ z-index: 200;
211
+ display: flex;
212
+ align-items: flex-end;
213
+ justify-content: center;
214
+ }
215
+
216
+ .sheet {
217
+ background: var(--ds-gray-100);
218
+ border-top-left-radius: var(--radius-xl);
219
+ border-top-right-radius: var(--radius-xl);
220
+ width: 100%;
221
+ max-height: 90vh;
222
+ overflow-y: auto;
223
+ padding: var(--space-4) var(--space-5)
224
+ calc(var(--space-8, 32px) + env(safe-area-inset-bottom, 0px));
225
+ animation: slideUp 0.25s ease;
223
226
  }
224
227
 
225
- /* Desktop: max width */
228
+ @keyframes slideUp {
229
+ from {
230
+ transform: translateY(100%);
231
+ }
232
+ to {
233
+ transform: translateY(0);
234
+ }
235
+ }
236
+
237
+ /* Desktop: centered modal */
226
238
  @media (min-width: 768px) {
227
- :global(.launch-sheet) {
228
- --sheet-max-width: 480px;
239
+ .overlay {
240
+ align-items: center;
241
+ }
242
+
243
+ .sheet {
244
+ max-width: 480px;
245
+ border-radius: var(--radius-xl);
246
+ animation: fadeScale 0.2s ease;
247
+ }
248
+
249
+ @keyframes fadeScale {
250
+ from {
251
+ opacity: 0;
252
+ transform: scale(0.96);
253
+ }
254
+ to {
255
+ opacity: 1;
256
+ transform: scale(1);
257
+ }
229
258
  }
230
259
  }
231
260
 
232
- .launch-form {
261
+ .handle-bar {
233
262
  display: flex;
234
- flex-direction: column;
235
- gap: var(--space-4);
263
+ justify-content: center;
264
+ padding-bottom: var(--space-3);
265
+ }
266
+
267
+ .handle {
268
+ width: 36px;
269
+ height: 4px;
270
+ border-radius: var(--radius-full);
271
+ background: var(--ds-gray-500);
272
+ }
273
+
274
+ /* Hide handle bar on desktop */
275
+ @media (min-width: 768px) {
276
+ .handle-bar {
277
+ display: none;
278
+ }
279
+ }
280
+
281
+ .sheet-title {
282
+ font-size: var(--text-xl);
283
+ font-weight: 600;
284
+ color: var(--text-primary);
285
+ margin-bottom: var(--space-5);
286
+ letter-spacing: var(--tracking-tight);
236
287
  }
237
288
 
238
289
  .section {
239
- display: flex;
240
- flex-direction: column;
241
- gap: var(--space-2);
290
+ margin-bottom: var(--space-4);
242
291
  }
243
292
 
244
293
  .section-label {
@@ -248,6 +297,7 @@
248
297
  color: var(--text-secondary);
249
298
  text-transform: uppercase;
250
299
  letter-spacing: 0.05em;
300
+ margin-bottom: var(--space-2);
251
301
  }
252
302
 
253
303
  .preset-grid {
@@ -271,6 +321,19 @@
271
321
 
272
322
  :global(.launch-select) {
273
323
  --select-height: 44px;
324
+ --select-trigger-background: var(--component-bg);
325
+ --select-trigger-border: 1px solid var(--border);
326
+ --select-trigger-hover-border-color: var(--border-hover);
327
+ --select-color: var(--text-primary);
328
+ --select-placeholder-color: var(--text-tertiary);
329
+ --select-arrow-color: var(--text-secondary);
330
+ --select-dropdown-background: var(--component-bg);
331
+ --select-dropdown-border: 1px solid var(--border);
332
+ --select-dropdown-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
333
+ --select-option-color: var(--text-primary);
334
+ --select-option-hover-background: var(--component-bg-hover);
335
+ --select-option-selected-background: var(--component-bg-active);
336
+ margin-bottom: var(--space-2);
274
337
  }
275
338
 
276
339
  :global(.launch-input) {
@@ -27,7 +27,9 @@
27
27
  {#each keys as k (k.label)}
28
28
  <Button
29
29
  classes="btn-quick-key"
30
- onclick={() => { onKey(k.escape); }}
30
+ onclick={() => {
31
+ onKey(k.escape);
32
+ }}
31
33
  text={k.label}
32
34
  />
33
35
  {/each}
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { KeyboardInput, Modal } from '@juspay/svelte-ui-components';
3
+
3
4
  import { getShortcutList } from './keyboard-shortcuts';
4
5
 
5
6
  interface Props {
@@ -12,11 +13,7 @@
12
13
  </script>
13
14
 
14
15
  {#if open}
15
- <Modal
16
- header={{ text: 'Keyboard Shortcuts' }}
17
- onoverlayClick={onClose}
18
- classes="shortcuts-modal"
19
- >
16
+ <Modal header={{ text: 'Keyboard Shortcuts' }} onoverlayClick={onClose} classes="shortcuts-modal">
20
17
  {#snippet content()}
21
18
  <div class="shortcuts-list">
22
19
  {#each shortcuts as shortcut (shortcut.keys)}
@@ -6,42 +6,25 @@
6
6
  */
7
7
 
8
8
  export const isMac =
9
- typeof navigator !== 'undefined' &&
10
- /Mac|iPhone|iPad/.test(navigator.userAgent);
9
+ typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.userAgent);
11
10
 
12
11
  export const modLabel = isMac ? '⌘' : 'Ctrl';
13
12
 
14
- export interface ShortcutAction {
15
- action: () => void;
16
- description: string;
17
- key: string;
18
- label: string;
19
- shift?: boolean;
20
- }
21
-
22
13
  interface ShortcutManagerOptions {
23
14
  onHelp: () => void;
24
15
  }
25
16
 
26
- /** Returns true when focus is inside a text input, textarea, or contenteditable. */
27
- function isTextInputFocused(): boolean {
28
- const el = document.activeElement;
29
- if (!el) { return false; }
30
- const tag = el.tagName;
31
- if (tag === 'INPUT' || tag === 'TEXTAREA') { return true; }
32
- if ((el as HTMLElement).isContentEditable) { return true; }
33
- // xterm's terminal container
34
- if (el.closest('.xterm')) { return true; }
35
- return false;
36
- }
37
-
38
17
  export function createShortcutManager(options: ShortcutManagerOptions) {
39
18
  function handler(e: KeyboardEvent) {
40
19
  const mod = isMac ? e.metaKey : e.ctrlKey;
41
- if (!mod) { return; }
20
+ if (!mod) {
21
+ return;
22
+ }
42
23
 
43
24
  // Don't intercept when a text input or the terminal is focused
44
- if (isTextInputFocused()) { return; }
25
+ if (isTextInputFocused()) {
26
+ return;
27
+ }
45
28
 
46
29
  // Cmd+/ — show help overlay
47
30
  if (e.key === '/') {
@@ -68,3 +51,23 @@ export function getShortcutList(): { description: string; keys: string }[] {
68
51
  { description: 'Keyboard shortcuts', keys: `${modLabel}+/` },
69
52
  ];
70
53
  }
54
+
55
+ /** Returns true when focus is inside a text input, textarea, or contenteditable. */
56
+ function isTextInputFocused(): boolean {
57
+ const el = document.activeElement;
58
+ if (!el) {
59
+ return false;
60
+ }
61
+ const tag = el.tagName;
62
+ if (tag === 'INPUT' || tag === 'TEXTAREA') {
63
+ return true;
64
+ }
65
+ if ((el as HTMLElement).isContentEditable) {
66
+ return true;
67
+ }
68
+ // xterm's terminal container
69
+ if (el.closest('.xterm')) {
70
+ return true;
71
+ }
72
+ return false;
73
+ }
@@ -1,11 +1,12 @@
1
1
  // IMPORTANT: This module must NEVER be imported at module top level in a Svelte component.
2
2
  // Always call createTerminal() inside onMount() only.
3
3
 
4
+ import type { FitAddon } from '@xterm/addon-fit';
4
5
  import type { Terminal } from '@xterm/xterm';
5
6
 
6
7
  interface TerminalInstance {
7
8
  dispose: () => void;
8
- fitAddon: any; // FitAddon type
9
+ fitAddon: FitAddon | null;
9
10
  sendInput: (data: string) => void;
10
11
  term: Terminal;
11
12
  }
@@ -73,12 +74,17 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
73
74
 
74
75
  // Block browser-level Cmd/Ctrl shortcuts from reaching the PTY.
75
76
  // Allow Ctrl+<letter> terminal signals (Ctrl+C/D/L/R/Z etc.) through.
76
- const browserShortcuts = new Set(['s', 'w', 't', 'n', 'p', 'q', 'h', 'j', 'f', 'g', 'o', 'u']);
77
+ const browserShortcuts = new Set(['f', 'g', 'h', 'j', 'n', 'o', 'p', 'q', 's', 't', 'u', 'w']);
77
78
  term.attachCustomKeyEventHandler((e) => {
79
+ const key = e.key.toLowerCase();
78
80
  // Cmd+key on Mac: block known browser shortcuts, allow the rest
79
81
  if (e.metaKey) {
80
- if (e.key === 'c' || e.key === 'v') { return true; } // allow copy/paste
81
- if (browserShortcuts.has(e.key)) { return false; } // block browser shortcuts
82
+ if (key === 'c' || key === 'v') {
83
+ return true;
84
+ } // allow copy/paste
85
+ if (browserShortcuts.has(key)) {
86
+ return false;
87
+ } // block browser shortcuts
82
88
  return true;
83
89
  }
84
90
  // Ctrl+key (non-Mac modifier): allow all through to PTY (Ctrl+C/D/L/R/Z etc.)
@@ -91,42 +97,52 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
91
97
  const pasteTermId = options.terminalId;
92
98
  const pasteApiKey = options.apiKey;
93
99
 
94
- pasteListener = async (e: ClipboardEvent) => {
95
- try {
96
- if (!e.clipboardData) return;
97
- const items = Array.from(e.clipboardData.items);
98
- const imageItem = items.find(item => item.type.startsWith('image/'));
99
- if (!imageItem) return; // No image — let normal paste proceed
100
-
101
- e.preventDefault();
102
- const blob = imageItem.getAsFile();
103
- if (!blob) return;
104
-
105
- // Read image as base64
106
- const reader = new FileReader();
107
- const base64 = await new Promise<string>((resolve, reject) => {
108
- reader.onload = () => resolve(reader.result as string);
109
- reader.onerror = reject;
110
- reader.readAsDataURL(blob);
111
- });
112
-
113
- // Upload to server
114
- const res = await fetch(`/api/terminals/${pasteTermId}/paste-image`, {
115
- method: 'POST',
116
- headers: {
117
- 'Authorization': `Bearer ${pasteApiKey}`,
118
- 'Content-Type': 'application/json',
119
- },
120
- body: JSON.stringify({ image: base64 }),
121
- });
122
-
123
- // Send Ctrl+V (0x16) to PTY only after a successful upload
124
- if (res.ok && ws?.readyState === WebSocket.OPEN) {
125
- ws.send(JSON.stringify({ data: '\x16', type: 'input' }));
100
+ pasteListener = (e: ClipboardEvent) => {
101
+ void (async () => {
102
+ try {
103
+ if (!e.clipboardData) {
104
+ return;
105
+ }
106
+ const items = Array.from(e.clipboardData.items);
107
+ const imageItem = items.find((item) => item.type.startsWith('image/'));
108
+ if (!imageItem) {
109
+ return;
110
+ } // No image — let normal paste proceed
111
+
112
+ const blob = imageItem.getAsFile();
113
+ if (!blob) {
114
+ return;
115
+ }
116
+ e.preventDefault();
117
+
118
+ // Read image as base64
119
+ const reader = new FileReader();
120
+ const base64 = await new Promise<string>((resolve, reject) => {
121
+ reader.onload = () => {
122
+ resolve(reader.result as string);
123
+ };
124
+ reader.onerror = reject;
125
+ reader.readAsDataURL(blob);
126
+ });
127
+
128
+ // Upload to server
129
+ const res = await fetch(`/api/terminals/${pasteTermId}/paste-image`, {
130
+ body: JSON.stringify({ image: base64 }),
131
+ headers: {
132
+ Authorization: `Bearer ${pasteApiKey}`,
133
+ 'Content-Type': 'application/json',
134
+ },
135
+ method: 'POST',
136
+ });
137
+
138
+ // Send Ctrl+V (0x16) to PTY only after a successful upload
139
+ if (res.ok && ws?.readyState === WebSocket.OPEN) {
140
+ ws.send(JSON.stringify({ data: '\x16', type: 'input' }));
141
+ }
142
+ } catch {
143
+ // Silent failure — don't break text paste
126
144
  }
127
- } catch {
128
- // Silent failure — don't break text paste
129
- }
145
+ })();
130
146
  };
131
147
 
132
148
  options.container.addEventListener('paste', pasteListener as EventListener);
@@ -139,7 +155,9 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
139
155
  let disposed = false;
140
156
 
141
157
  async function connect() {
142
- if (disposed) {return;}
158
+ if (disposed) {
159
+ return;
160
+ }
143
161
 
144
162
  let ticket: string;
145
163
  try {
@@ -156,7 +174,9 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
156
174
  return;
157
175
  }
158
176
 
159
- if (disposed) {return;}
177
+ if (disposed) {
178
+ return;
179
+ }
160
180
 
161
181
  ws = new WebSocket(`${options.wsUrl}?ticket=${ticket}`);
162
182
 
@@ -175,7 +195,9 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
175
195
  term.write(`\r\n\x1b[90m[Process exited with code ${msg.code}]\x1b[0m\r\n`);
176
196
  // Process exited — stop reconnection and notify parent
177
197
  disposed = true;
178
- if (reconnectTimer) {clearTimeout(reconnectTimer);}
198
+ if (reconnectTimer) {
199
+ clearTimeout(reconnectTimer);
200
+ }
179
201
  options.onExit?.(msg.code);
180
202
  } else if (msg.type === 'output-dropped') {
181
203
  term.write(`\r\n\x1b[33m[${msg.bytes} bytes dropped]\x1b[0m\r\n`);
@@ -187,7 +209,9 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
187
209
  };
188
210
 
189
211
  ws.onclose = () => {
190
- if (disposed) {return;}
212
+ if (disposed) {
213
+ return;
214
+ }
191
215
  options.onDisconnect?.();
192
216
  // Exponential backoff reconnect
193
217
  reconnectTimer = setTimeout(() => {
@@ -206,8 +230,11 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
206
230
  }
207
231
  });
208
232
 
209
- // Handle resize
233
+ // Handle resize — skip when container is hidden (display:none → size 0)
210
234
  const resizeObserver = new ResizeObserver(() => {
235
+ if (!options.container.offsetWidth || !options.container.offsetHeight) {
236
+ return;
237
+ }
211
238
  fitAddon.fit();
212
239
  if (ws?.readyState === WebSocket.OPEN) {
213
240
  ws.send(JSON.stringify({ cols: term.cols, rows: term.rows, type: 'resize' }));
@@ -217,7 +244,9 @@ export async function createTerminal(options: TerminalOptions): Promise<Terminal
217
244
 
218
245
  function dispose() {
219
246
  disposed = true;
220
- if (reconnectTimer) {clearTimeout(reconnectTimer);}
247
+ if (reconnectTimer) {
248
+ clearTimeout(reconnectTimer);
249
+ }
221
250
  if (pasteListener) {
222
251
  options.container.removeEventListener('paste', pasteListener as EventListener);
223
252
  }
@@ -4,6 +4,8 @@ import apn from '@parse/node-apn';
4
4
 
5
5
  import type { LibraryResult as APNsLibraryResult, NotificationPayload } from './types';
6
6
 
7
+ import { toErrorMessage } from '../utils/error';
8
+
7
9
  export class LibraryAPNsService {
8
10
  private bundleId: string | undefined;
9
11
  private configured = false;
@@ -41,8 +43,7 @@ export class LibraryAPNsService {
41
43
  this.configured = true;
42
44
  console.log(`[apns] Provider initialized (${production ? 'production' : 'sandbox'} mode)`);
43
45
  } catch (error) {
44
- const err = error as Error;
45
- console.error('[apns] Failed to create provider:', err.message);
46
+ console.error('[apns] Failed to create provider:', toErrorMessage(error));
46
47
  this.configured = false;
47
48
  }
48
49
  }