@juspay/shooter 1.0.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 (327) hide show
  1. package/.claude/hooks/notifier.cjs +1431 -0
  2. package/.claude/settings.json +162 -0
  3. package/README.md +515 -0
  4. package/bin/shooter.cjs +141 -0
  5. package/build/client/_app/immutable/assets/0.CM9Hl6d-.css +1 -0
  6. package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.br +0 -0
  7. package/build/client/_app/immutable/assets/0.CM9Hl6d-.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css +1 -0
  9. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.br +1 -0
  10. package/build/client/_app/immutable/assets/2.CAShZ7lQ.css.gz +0 -0
  11. package/build/client/_app/immutable/assets/3.C0uFg0IS.css +1 -0
  12. package/build/client/_app/immutable/assets/3.C0uFg0IS.css.br +0 -0
  13. package/build/client/_app/immutable/assets/3.C0uFg0IS.css.gz +0 -0
  14. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css +1 -0
  15. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.br +0 -0
  16. package/build/client/_app/immutable/assets/4.cJuCkJKZ.css.gz +0 -0
  17. package/build/client/_app/immutable/assets/5.DRjApZQW.css +1 -0
  18. package/build/client/_app/immutable/assets/5.DRjApZQW.css.br +0 -0
  19. package/build/client/_app/immutable/assets/5.DRjApZQW.css.gz +0 -0
  20. package/build/client/_app/immutable/assets/6.AraZrY8I.css +1 -0
  21. package/build/client/_app/immutable/assets/6.AraZrY8I.css.br +0 -0
  22. package/build/client/_app/immutable/assets/6.AraZrY8I.css.gz +0 -0
  23. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css +1 -0
  24. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.br +0 -0
  25. package/build/client/_app/immutable/assets/7.BCJ1IuMx.css.gz +0 -0
  26. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css +1 -0
  27. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.br +0 -0
  28. package/build/client/_app/immutable/assets/ChatView.CsdBAOKx.css.gz +0 -0
  29. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css +1 -0
  30. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.br +0 -0
  31. package/build/client/_app/immutable/assets/markdown.B0b5w2tq.css.gz +0 -0
  32. package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css +1 -0
  33. package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css.br +0 -0
  34. package/build/client/_app/immutable/assets/xterm.DFuMZ0ql.css.gz +0 -0
  35. package/build/client/_app/immutable/chunks/BNJphC1q.js +56 -0
  36. package/build/client/_app/immutable/chunks/BNJphC1q.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/BNJphC1q.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/BTGVxaYV.js +9 -0
  39. package/build/client/_app/immutable/chunks/BTGVxaYV.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/BTGVxaYV.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/BlxrFPDK.js +1 -0
  42. package/build/client/_app/immutable/chunks/BlxrFPDK.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/BlxrFPDK.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/Bvk7mfPM.js +1 -0
  45. package/build/client/_app/immutable/chunks/Bvk7mfPM.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/Bvk7mfPM.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/CAokzuPQ.js +1 -0
  48. package/build/client/_app/immutable/chunks/CAokzuPQ.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/CAokzuPQ.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/CGLrx-H5.js +1 -0
  51. package/build/client/_app/immutable/chunks/CGLrx-H5.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/CGLrx-H5.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/CgCpWzEA.js +1 -0
  54. package/build/client/_app/immutable/chunks/CgCpWzEA.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/CgCpWzEA.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/Cjwk_cGO.js +6 -0
  57. package/build/client/_app/immutable/chunks/Cjwk_cGO.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/Cjwk_cGO.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/CtQ8EED1.js +11 -0
  60. package/build/client/_app/immutable/chunks/CtQ8EED1.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/CtQ8EED1.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/DERQCisl.js +1 -0
  63. package/build/client/_app/immutable/chunks/DERQCisl.js.br +0 -0
  64. package/build/client/_app/immutable/chunks/DERQCisl.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/DKrg8TQs.js +1 -0
  66. package/build/client/_app/immutable/chunks/DKrg8TQs.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/DKrg8TQs.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/DLu6yJIZ.js +1 -0
  69. package/build/client/_app/immutable/chunks/DLu6yJIZ.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/DLu6yJIZ.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/Dkkpz_4D.js +126 -0
  72. package/build/client/_app/immutable/chunks/Dkkpz_4D.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/Dkkpz_4D.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/DoczjQhA.js +1 -0
  75. package/build/client/_app/immutable/chunks/DoczjQhA.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/DoczjQhA.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/PPVm8Dsz.js +1 -0
  78. package/build/client/_app/immutable/chunks/PPVm8Dsz.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/PPVm8Dsz.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/RpcNruLP.js +2 -0
  81. package/build/client/_app/immutable/chunks/RpcNruLP.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/RpcNruLP.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/a-St0Zwo.js +1 -0
  84. package/build/client/_app/immutable/chunks/a-St0Zwo.js.br +0 -0
  85. package/build/client/_app/immutable/chunks/a-St0Zwo.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/bo70OQUZ.js +1 -0
  87. package/build/client/_app/immutable/chunks/bo70OQUZ.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/bo70OQUZ.js.gz +0 -0
  89. package/build/client/_app/immutable/entry/app.QvGgdvTI.js +2 -0
  90. package/build/client/_app/immutable/entry/app.QvGgdvTI.js.br +0 -0
  91. package/build/client/_app/immutable/entry/app.QvGgdvTI.js.gz +0 -0
  92. package/build/client/_app/immutable/entry/start.BntDNRMC.js +1 -0
  93. package/build/client/_app/immutable/entry/start.BntDNRMC.js.br +0 -0
  94. package/build/client/_app/immutable/entry/start.BntDNRMC.js.gz +0 -0
  95. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js +1 -0
  96. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.br +0 -0
  97. package/build/client/_app/immutable/nodes/0.CzkdvJ7j.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js +1 -0
  99. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.br +0 -0
  100. package/build/client/_app/immutable/nodes/1.MG1QhfrI.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js +1 -0
  102. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.br +0 -0
  103. package/build/client/_app/immutable/nodes/2.B4MlOSh6.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js +3 -0
  105. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/3.DIwYkjDn.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/4.D-cIe70D.js +1 -0
  108. package/build/client/_app/immutable/nodes/4.D-cIe70D.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/4.D-cIe70D.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js +1 -0
  111. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/5.D7zPRe3L.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/6.BB7QE48r.js +2 -0
  114. package/build/client/_app/immutable/nodes/6.BB7QE48r.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/6.BB7QE48r.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js +2 -0
  117. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.br +0 -0
  118. package/build/client/_app/immutable/nodes/7.D8mqsrZG.js.gz +0 -0
  119. package/build/client/_app/version.json +1 -0
  120. package/build/client/_app/version.json.br +0 -0
  121. package/build/client/_app/version.json.gz +0 -0
  122. package/build/client/app-icon.png +0 -0
  123. package/build/client/apple-touch-icon.png +0 -0
  124. package/build/client/favicon.png +0 -0
  125. package/build/client/favicon.svg +10 -0
  126. package/build/client/favicon.svg.br +0 -0
  127. package/build/client/favicon.svg.gz +0 -0
  128. package/build/client/manifest.webmanifest +1 -0
  129. package/build/client/pwa-192x192.png +0 -0
  130. package/build/client/pwa-512x512.png +0 -0
  131. package/build/client/registerSW.js +1 -0
  132. package/build/client/registerSW.js.br +0 -0
  133. package/build/client/registerSW.js.gz +0 -0
  134. package/build/client/sw.js +222 -0
  135. package/build/client/sw.js.br +0 -0
  136. package/build/client/sw.js.gz +0 -0
  137. package/build/client/workbox-5119daf5.js +3395 -0
  138. package/build/client/workbox-5119daf5.js.br +0 -0
  139. package/build/client/workbox-5119daf5.js.gz +0 -0
  140. package/build/env.js +94 -0
  141. package/build/handler.js +1494 -0
  142. package/build/index.js +345 -0
  143. package/build/pty-holder.cjs +510 -0
  144. package/build/server/chunks/0-q2IUp76Y.js +9 -0
  145. package/build/server/chunks/0-q2IUp76Y.js.map +1 -0
  146. package/build/server/chunks/1-CU50G5wZ.js +9 -0
  147. package/build/server/chunks/1-CU50G5wZ.js.map +1 -0
  148. package/build/server/chunks/2-D01t9s8T.js +9 -0
  149. package/build/server/chunks/2-D01t9s8T.js.map +1 -0
  150. package/build/server/chunks/3-5PUQ04wC.js +9 -0
  151. package/build/server/chunks/3-5PUQ04wC.js.map +1 -0
  152. package/build/server/chunks/4-e7gywnSG.js +9 -0
  153. package/build/server/chunks/4-e7gywnSG.js.map +1 -0
  154. package/build/server/chunks/5-CA1SA6KZ.js +9 -0
  155. package/build/server/chunks/5-CA1SA6KZ.js.map +1 -0
  156. package/build/server/chunks/6-71H221sV.js +9 -0
  157. package/build/server/chunks/6-71H221sV.js.map +1 -0
  158. package/build/server/chunks/7-Bo-vmdyz.js +9 -0
  159. package/build/server/chunks/7-Bo-vmdyz.js.map +1 -0
  160. package/build/server/chunks/_layout.svelte-SFHOxs74.js +132 -0
  161. package/build/server/chunks/_layout.svelte-SFHOxs74.js.map +1 -0
  162. package/build/server/chunks/_page.svelte-B4w-2wD-.js +120 -0
  163. package/build/server/chunks/_page.svelte-B4w-2wD-.js.map +1 -0
  164. package/build/server/chunks/_page.svelte-B_qAXjkh.js +213 -0
  165. package/build/server/chunks/_page.svelte-B_qAXjkh.js.map +1 -0
  166. package/build/server/chunks/_page.svelte-CsF1_TRG.js +50 -0
  167. package/build/server/chunks/_page.svelte-CsF1_TRG.js.map +1 -0
  168. package/build/server/chunks/_page.svelte-DJC6U-P0.js +68 -0
  169. package/build/server/chunks/_page.svelte-DJC6U-P0.js.map +1 -0
  170. package/build/server/chunks/_page.svelte-DQ6HBtsz.js +407 -0
  171. package/build/server/chunks/_page.svelte-DQ6HBtsz.js.map +1 -0
  172. package/build/server/chunks/_page.svelte-LbhhjP21.js +148 -0
  173. package/build/server/chunks/_page.svelte-LbhhjP21.js.map +1 -0
  174. package/build/server/chunks/_server.ts-BL2FGb5Z.js +387 -0
  175. package/build/server/chunks/_server.ts-BL2FGb5Z.js.map +1 -0
  176. package/build/server/chunks/_server.ts-BgdjBZco.js +47 -0
  177. package/build/server/chunks/_server.ts-BgdjBZco.js.map +1 -0
  178. package/build/server/chunks/_server.ts-BihKSdj_.js +59 -0
  179. package/build/server/chunks/_server.ts-BihKSdj_.js.map +1 -0
  180. package/build/server/chunks/_server.ts-BjOJsoy4.js +63 -0
  181. package/build/server/chunks/_server.ts-BjOJsoy4.js.map +1 -0
  182. package/build/server/chunks/_server.ts-C29xzfaw.js +77 -0
  183. package/build/server/chunks/_server.ts-C29xzfaw.js.map +1 -0
  184. package/build/server/chunks/_server.ts-CPa6DgIt.js +71 -0
  185. package/build/server/chunks/_server.ts-CPa6DgIt.js.map +1 -0
  186. package/build/server/chunks/_server.ts-CbDRDIoP.js +36 -0
  187. package/build/server/chunks/_server.ts-CbDRDIoP.js.map +1 -0
  188. package/build/server/chunks/_server.ts-Cl1OEWL4.js +54 -0
  189. package/build/server/chunks/_server.ts-Cl1OEWL4.js.map +1 -0
  190. package/build/server/chunks/_server.ts-ColfDHW8.js +60 -0
  191. package/build/server/chunks/_server.ts-ColfDHW8.js.map +1 -0
  192. package/build/server/chunks/_server.ts-Cv_OrRuL.js +494 -0
  193. package/build/server/chunks/_server.ts-Cv_OrRuL.js.map +1 -0
  194. package/build/server/chunks/_server.ts-D4MNi4cD.js +25 -0
  195. package/build/server/chunks/_server.ts-D4MNi4cD.js.map +1 -0
  196. package/build/server/chunks/_server.ts-DRVbgm6k.js +125 -0
  197. package/build/server/chunks/_server.ts-DRVbgm6k.js.map +1 -0
  198. package/build/server/chunks/_server.ts-DfajWaqh.js +39 -0
  199. package/build/server/chunks/_server.ts-DfajWaqh.js.map +1 -0
  200. package/build/server/chunks/_server.ts-y9-WYDMa.js +35 -0
  201. package/build/server/chunks/_server.ts-y9-WYDMa.js.map +1 -0
  202. package/build/server/chunks/auth-CEgFis71.js +32 -0
  203. package/build/server/chunks/auth-CEgFis71.js.map +1 -0
  204. package/build/server/chunks/client-CxCatAKr.js +255 -0
  205. package/build/server/chunks/client-CxCatAKr.js.map +1 -0
  206. package/build/server/chunks/error.svelte-BqdwMWdK.js +26 -0
  207. package/build/server/chunks/error.svelte-BqdwMWdK.js.map +1 -0
  208. package/build/server/chunks/exports-CJ0Q5XmL.js +4081 -0
  209. package/build/server/chunks/exports-CJ0Q5XmL.js.map +1 -0
  210. package/build/server/chunks/index2-DAxIoAO-.js +36 -0
  211. package/build/server/chunks/index2-DAxIoAO-.js.map +1 -0
  212. package/build/server/chunks/jsonl-parser-dmZU_Hyu.js +137 -0
  213. package/build/server/chunks/jsonl-parser-dmZU_Hyu.js.map +1 -0
  214. package/build/server/chunks/library-apns-BHxLmuIx.js +104 -0
  215. package/build/server/chunks/library-apns-BHxLmuIx.js.map +1 -0
  216. package/build/server/chunks/markdown-Bxrl3cCF.js +1241 -0
  217. package/build/server/chunks/markdown-Bxrl3cCF.js.map +1 -0
  218. package/build/server/chunks/pending-requests-D8UiTw7L.js +44 -0
  219. package/build/server/chunks/pending-requests-D8UiTw7L.js.map +1 -0
  220. package/build/server/chunks/pty-manager-C0FhBiVq.js +1697 -0
  221. package/build/server/chunks/pty-manager-C0FhBiVq.js.map +1 -0
  222. package/build/server/chunks/shared-server-BDY8jh20.js +200 -0
  223. package/build/server/chunks/shared-server-BDY8jh20.js.map +1 -0
  224. package/build/server/chunks/stores-D0HorpgL.js +36 -0
  225. package/build/server/chunks/stores-D0HorpgL.js.map +1 -0
  226. package/build/server/index.js +6466 -0
  227. package/build/server/index.js.map +1 -0
  228. package/build/server/manifest.js +184 -0
  229. package/build/server/manifest.js.map +1 -0
  230. package/build/shims.js +32 -0
  231. package/package.json +94 -0
  232. package/scripts/clipboard-shims/wl-paste +48 -0
  233. package/scripts/clipboard-shims/xclip +31 -0
  234. package/scripts/install.sh +477 -0
  235. package/scripts/setup-node-pty.sh +63 -0
  236. package/scripts/setup.cjs +571 -0
  237. package/scripts/test-runner.ts +243 -0
  238. package/scripts/vercel-env-commands.sh +60 -0
  239. package/server.ts +139 -0
  240. package/src/app.css +1835 -0
  241. package/src/app.d.ts +31 -0
  242. package/src/app.html +24 -0
  243. package/src/generated/types/APN.ts +305 -0
  244. package/src/generated/types/CLI.ts +52 -0
  245. package/src/generated/types/JWT.ts +92 -0
  246. package/src/generated/types/Terminal.ts +2736 -0
  247. package/src/generated/types/index.ts +6 -0
  248. package/src/lib/assets/icons/alert-triangle.svg +5 -0
  249. package/src/lib/assets/icons/bell.svg +4 -0
  250. package/src/lib/assets/icons/check-circle.svg +4 -0
  251. package/src/lib/assets/icons/file.svg +4 -0
  252. package/src/lib/assets/icons/folder.svg +3 -0
  253. package/src/lib/assets/icons/play.svg +3 -0
  254. package/src/lib/assets/icons/refresh.svg +4 -0
  255. package/src/lib/assets/icons/settings.svg +4 -0
  256. package/src/lib/assets/icons/terminal.svg +1 -0
  257. package/src/lib/assets/icons/tool.svg +3 -0
  258. package/src/lib/assets/icons/x-circle.svg +5 -0
  259. package/src/lib/modules/client/common/Card.svelte +26 -0
  260. package/src/lib/modules/client/common/EmptyState.svelte +36 -0
  261. package/src/lib/modules/client/common/Icon.svelte +61 -0
  262. package/src/lib/modules/client/common/StatusBadge.svelte +38 -0
  263. package/src/lib/modules/client/common/cache.ts +31 -0
  264. package/src/lib/modules/client/common/config-guard.ts +18 -0
  265. package/src/lib/modules/client/common/index.ts +12 -0
  266. package/src/lib/modules/client/common/markdown.ts +23 -0
  267. package/src/lib/modules/client/common/native-bridge.ts +50 -0
  268. package/src/lib/modules/client/common/time.ts +22 -0
  269. package/src/lib/modules/client/common/tool-title.ts +28 -0
  270. package/src/lib/modules/client/terminal/ChatView.svelte +400 -0
  271. package/src/lib/modules/client/terminal/CommandPalette.svelte +60 -0
  272. package/src/lib/modules/client/terminal/ConnectionStatus.svelte +99 -0
  273. package/src/lib/modules/client/terminal/LaunchSheet.svelte +294 -0
  274. package/src/lib/modules/client/terminal/QuickKeys.svelte +71 -0
  275. package/src/lib/modules/client/terminal/ShortcutsHelp.svelte +79 -0
  276. package/src/lib/modules/client/terminal/keyboard-shortcuts.ts +70 -0
  277. package/src/lib/modules/client/terminal/xterm-wrapper.ts +243 -0
  278. package/src/lib/modules/server/apn/library-apns.ts +137 -0
  279. package/src/lib/modules/server/apn/notification-history.ts +35 -0
  280. package/src/lib/modules/server/apn/notification-sessions.ts +117 -0
  281. package/src/lib/modules/server/apn/pending-requests.ts +65 -0
  282. package/src/lib/modules/server/apn/types.ts +51 -0
  283. package/src/lib/modules/server/auth.ts +34 -0
  284. package/src/lib/modules/server/cli/index.ts +79 -0
  285. package/src/lib/modules/server/cli/runner.ts +162 -0
  286. package/src/lib/modules/server/fcm/fcm-service.ts +72 -0
  287. package/src/lib/modules/server/sessions/jsonl-parser.ts +197 -0
  288. package/src/lib/modules/server/sessions/jsonl-reader.ts +301 -0
  289. package/src/lib/modules/server/sessions/opencode-reader.ts +264 -0
  290. package/src/lib/modules/server/sessions/types.ts +53 -0
  291. package/src/lib/modules/server/terminal/holder-client.ts +273 -0
  292. package/src/lib/modules/server/terminal/opencode-watcher.ts +661 -0
  293. package/src/lib/modules/server/terminal/pty-holder.cjs +510 -0
  294. package/src/lib/modules/server/terminal/pty-manager.ts +1012 -0
  295. package/src/lib/modules/server/terminal/session-watcher.ts +320 -0
  296. package/src/lib/modules/server/terminal/terminal-store.ts +198 -0
  297. package/src/lib/modules/server/ws/events-handler.ts +73 -0
  298. package/src/lib/modules/server/ws/keepalive.ts +108 -0
  299. package/src/lib/modules/server/ws/server.ts +93 -0
  300. package/src/lib/modules/server/ws/session-handler.ts +462 -0
  301. package/src/lib/modules/server/ws/terminal-handler.ts +197 -0
  302. package/src/lib/modules/server/ws/ticket-store.ts +58 -0
  303. package/src/lib/theme.css +529 -0
  304. package/src/lib/types/config.ts +6 -0
  305. package/src/routes/+layout.svelte +218 -0
  306. package/src/routes/+page.svelte +261 -0
  307. package/src/routes/api/debug/+server.ts +33 -0
  308. package/src/routes/api/device-token/+server.ts +85 -0
  309. package/src/routes/api/health/+server.ts +100 -0
  310. package/src/routes/api/notify/+server.ts +418 -0
  311. package/src/routes/api/qr-config/+server.ts +45 -0
  312. package/src/routes/api/response/+server.ts +73 -0
  313. package/src/routes/api/sessions/+server.ts +120 -0
  314. package/src/routes/api/terminals/+server.ts +141 -0
  315. package/src/routes/api/terminals/[id]/+server.ts +75 -0
  316. package/src/routes/api/terminals/[id]/paste-image/+server.ts +61 -0
  317. package/src/routes/api/terminals/[id]/resize/+server.ts +60 -0
  318. package/src/routes/api/webhook/+server.ts +42 -0
  319. package/src/routes/api/ws-status/+server.ts +23 -0
  320. package/src/routes/api/ws-ticket/+server.ts +86 -0
  321. package/src/routes/config/+page.svelte +600 -0
  322. package/src/routes/project/+page.svelte +274 -0
  323. package/src/routes/session/[id]/+page.svelte +434 -0
  324. package/src/routes/terminals/+page.svelte +618 -0
  325. package/src/routes/terminals/[id]/+page.svelte +968 -0
  326. package/svelte.config.js +18 -0
  327. package/tsconfig.json +14 -0
@@ -0,0 +1,301 @@
1
+ import * as crypto from 'crypto';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+
5
+ import type { ConversationMessage, MessagePart, ProjectGroup, SessionInfo } from './types';
6
+
7
+ import { parseJsonlText } from './jsonl-parser';
8
+
9
+ // Short hash for project IDs (8 chars from SHA-256)
10
+ function shortHash(input: string): string {
11
+ return crypto.createHash('sha256').update(input).digest('hex').slice(0, 8);
12
+ }
13
+
14
+ // Path to Claude Code's project session data
15
+ const CLAUDE_PROJECTS_DIR = path.join(process.env.HOME || '', '.claude', 'projects');
16
+
17
+ export function getSessionConversation(
18
+ sessionId: string,
19
+ offset = 0,
20
+ limit = 100,
21
+ projectId?: string
22
+ ): ConversationMessage[] {
23
+ const projectDir = projectId ? path.join(CLAUDE_PROJECTS_DIR, projectId) : getProjectDir();
24
+ const jsonlPath = path.join(projectDir, `${sessionId}.jsonl`);
25
+
26
+ if (!fs.existsSync(jsonlPath)) {
27
+ return [];
28
+ }
29
+
30
+ try {
31
+ const raw = fs.readFileSync(jsonlPath, 'utf-8');
32
+ const assistantTurns = new Map<string, { parts: MessagePart[]; timestamp: string }>();
33
+ const messages = parseJsonlText(raw, assistantTurns, 0);
34
+
35
+ // Flush any remaining assistant turns
36
+ for (const [msgId, turn] of assistantTurns) {
37
+ if (turn.parts.length > 0) {
38
+ messages.push({
39
+ id: msgId,
40
+ parts: turn.parts,
41
+ role: 'assistant',
42
+ timestamp: turn.timestamp,
43
+ });
44
+ }
45
+ }
46
+
47
+ return messages.slice(offset, offset + limit);
48
+ } catch (error) {
49
+ console.error('[sessions] Failed to parse session JSONL:', error);
50
+ return [];
51
+ }
52
+ }
53
+
54
+ export function listProjectsWithSessions(): ProjectGroup[] {
55
+ if (!fs.existsSync(CLAUDE_PROJECTS_DIR)) {
56
+ return [];
57
+ }
58
+
59
+ let projectDirs: string[];
60
+ try {
61
+ projectDirs = fs.readdirSync(CLAUDE_PROJECTS_DIR).filter((d) => {
62
+ const fullPath = path.join(CLAUDE_PROJECTS_DIR, d);
63
+ try {
64
+ return fs.statSync(fullPath).isDirectory();
65
+ } catch {
66
+ return false;
67
+ }
68
+ });
69
+ } catch {
70
+ return [];
71
+ }
72
+
73
+ const projects: ProjectGroup[] = [];
74
+
75
+ for (const dir of projectDirs) {
76
+ const projectDir = path.join(CLAUDE_PROJECTS_DIR, dir);
77
+ // Decode project path (fallback, prefer session's projectPath)
78
+ const decodedPath = dir.startsWith('-') ? dir.replace(/-/g, '/') : `/${dir.replace(/-/g, '/')}`;
79
+
80
+ // Get sessions for this project
81
+ const sessions = listSessionsForProject(projectDir);
82
+ if (sessions.length === 0) {
83
+ continue;
84
+ }
85
+
86
+ // Sort sessions by modified desc
87
+ sessions.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
88
+
89
+ // Get real project path from session data instead of decoding directory name
90
+ const realPath =
91
+ sessions.find((s) => s.projectPath && !s.projectPath.includes('.claude/projects'))
92
+ ?.projectPath || decodedPath;
93
+ const pathSegments = realPath.split('/').filter(Boolean);
94
+ const projectName = pathSegments.slice(-2).join('/');
95
+
96
+ projects.push({
97
+ fullPath: realPath,
98
+ id: shortHash(realPath),
99
+ lastModified: sessions[0]?.modified || '',
100
+ name: projectName,
101
+ sessionCount: sessions.length,
102
+ sessions,
103
+ });
104
+ }
105
+
106
+ return projects.sort(
107
+ (a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime()
108
+ );
109
+ }
110
+
111
+ export function listSessions(): SessionInfo[] {
112
+ const projectDir = getProjectDir();
113
+ return listSessionsForProject(projectDir);
114
+ }
115
+
116
+ function cleanTitle(prompt: string): string {
117
+ // Strip internal Claude Code XML markup tags, then remove ALL angle-bracket content.
118
+ // Use a loop to handle nested/reconstructed tags (satisfies CodeQL multi-char sanitization).
119
+ let cleaned = prompt
120
+ .replace(/<command-message>.*?<\/command-message>/gs, '')
121
+ .replace(/<command-name>.*?<\/command-name>/gs, '')
122
+ .replace(/<command-args>.*?<\/command-args>/gs, '')
123
+ .replace(/<local-command-caveat>.*?<\/local-command-caveat>/gs, '')
124
+ .replace(/<local-command-stdout>.*?<\/local-command-stdout>/gs, '')
125
+ .replace(/<system-reminder>.*?<\/system-reminder>/gs, '');
126
+
127
+ // Iteratively strip tags until none remain (prevents reconstructed tags like "<scr" + "ipt>")
128
+ let prev = '';
129
+ while (prev !== cleaned) {
130
+ prev = cleaned;
131
+ cleaned = cleaned.replace(/<[^>]*>/g, '').replace(/</g, '');
132
+ }
133
+ cleaned = cleaned.trim();
134
+
135
+ if (!cleaned) {
136
+ return 'Untitled Session';
137
+ }
138
+
139
+ // Take first line, trim, cap at 80 chars
140
+ const firstLine = cleaned.split('\n')[0].trim();
141
+ if (!firstLine) {
142
+ return 'Untitled Session';
143
+ }
144
+ if (firstLine.length > 80) {
145
+ return `${firstLine.slice(0, 77)}...`;
146
+ }
147
+ return firstLine;
148
+ }
149
+
150
+ function getProjectDir(): string {
151
+ // Encode project path: /Users/sachinsharma/Developer/Personal/shooter -> -Users-sachinsharma-Developer-Personal-shooter
152
+ const projectPath = process.cwd();
153
+ const encoded = projectPath.replace(/\//g, '-');
154
+ return path.join(CLAUDE_PROJECTS_DIR, encoded);
155
+ }
156
+
157
+ function listSessionsForProject(projectDir: string): SessionInfo[] {
158
+ const indexPath = path.join(projectDir, 'sessions-index.json');
159
+
160
+ if (!fs.existsSync(indexPath)) {
161
+ return [];
162
+ }
163
+
164
+ try {
165
+ const raw = fs.readFileSync(indexPath, 'utf-8');
166
+ const index = JSON.parse(raw) as {
167
+ entries: {
168
+ created?: string;
169
+ firstPrompt?: string;
170
+ gitBranch?: string;
171
+ isSidechain?: boolean;
172
+ messageCount?: number;
173
+ modified?: string;
174
+ projectPath?: string;
175
+ sessionId: string;
176
+ summary?: string;
177
+ }[];
178
+ };
179
+
180
+ const indexedIds = new Set<string>();
181
+ const sessions: SessionInfo[] = index.entries
182
+ .filter((e) => !e.isSidechain)
183
+ .filter((e) => {
184
+ const jsonlFile = path.join(projectDir, `${e.sessionId}.jsonl`);
185
+ return fs.existsSync(jsonlFile);
186
+ })
187
+ .map((entry) => {
188
+ indexedIds.add(entry.sessionId);
189
+ return {
190
+ created: entry.created || '',
191
+ gitBranch: entry.gitBranch || '',
192
+ id: entry.sessionId,
193
+ messageCount: entry.messageCount || 0,
194
+ modified: entry.modified || '',
195
+ projectPath: entry.projectPath || '',
196
+ source: 'claude-code' as const,
197
+ summary: entry.summary || '',
198
+ title: cleanTitle(entry.firstPrompt || entry.summary || 'Untitled Session'),
199
+ };
200
+ });
201
+
202
+ // Also scan for JSONL files not in the index (e.g., active sessions)
203
+ try {
204
+ const files = fs.readdirSync(projectDir);
205
+ for (const file of files) {
206
+ if (!file.endsWith('.jsonl')) {
207
+ continue;
208
+ }
209
+ const sessionId = file.replace('.jsonl', '');
210
+ if (indexedIds.has(sessionId)) {
211
+ continue;
212
+ }
213
+ // Read first user message as title
214
+ const filePath = path.join(projectDir, file);
215
+ const stat = fs.statSync(filePath);
216
+ let firstPrompt = 'Active Session';
217
+ let messageCount = 0;
218
+ try {
219
+ const content = fs.readFileSync(filePath, 'utf-8');
220
+ // Count user + assistant messages for the message count
221
+ const lines = content.split('\n');
222
+ for (const line of lines) {
223
+ if (!line.trim()) { continue; }
224
+ try {
225
+ const entry = JSON.parse(line);
226
+ if (entry.type === 'user' || entry.type === 'assistant') {
227
+ messageCount++;
228
+ }
229
+ } catch {
230
+ // skip malformed lines
231
+ }
232
+ }
233
+ // Find the first real user message (skip system caveats, commands, tool results)
234
+ for (const line of lines) {
235
+ if (!line.trim()) { continue; }
236
+ try {
237
+ const entry = JSON.parse(line);
238
+ if (entry.type !== 'user') { continue; }
239
+ const msg = entry.message;
240
+ if (!msg?.content) { continue; }
241
+
242
+ // Extract text from content (can be string or array of blocks)
243
+ let text = '';
244
+ if (typeof msg.content === 'string') {
245
+ text = msg.content.trim();
246
+ } else if (Array.isArray(msg.content)) {
247
+ for (const b of msg.content) {
248
+ if (typeof b === 'string' && b.trim()) {
249
+ text = b.trim();
250
+ break;
251
+ }
252
+ if (typeof b === 'object' && b !== null && b.type === 'text' && b.text?.trim()) {
253
+ text = b.text.trim();
254
+ break;
255
+ }
256
+ }
257
+ }
258
+
259
+ if (!text) { continue; }
260
+
261
+ // Skip system-injected caveats and command outputs
262
+ if (text.startsWith('<local-command') ||
263
+ text.startsWith('<command-name>') ||
264
+ text.startsWith('<local-command-stdout>') ||
265
+ text.startsWith('<system-reminder>') ||
266
+ text.startsWith('<task-notification>')) {
267
+ continue;
268
+ }
269
+
270
+ firstPrompt = text;
271
+ break;
272
+ } catch {
273
+ continue;
274
+ }
275
+ }
276
+ } catch {
277
+ // ignore read errors
278
+ }
279
+
280
+ sessions.push({
281
+ created: stat.birthtime.toISOString(),
282
+ gitBranch: '',
283
+ id: sessionId,
284
+ messageCount,
285
+ modified: stat.mtime.toISOString(),
286
+ projectPath: '',
287
+ source: 'claude-code' as const,
288
+ summary: '',
289
+ title: cleanTitle(firstPrompt),
290
+ });
291
+ }
292
+ } catch {
293
+ // ignore scan errors
294
+ }
295
+
296
+ return sessions.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
297
+ } catch (error) {
298
+ console.error('[sessions] Failed to read sessions index:', error);
299
+ return [];
300
+ }
301
+ }
@@ -0,0 +1,264 @@
1
+ import Database from 'better-sqlite3';
2
+ import * as crypto from 'crypto';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ function shortHash(input: string): string {
7
+ return crypto.createHash('sha256').update(input).digest('hex').slice(0, 8);
8
+ }
9
+
10
+ import type { ConversationMessage, MessagePart, ProjectGroup, SessionInfo } from './types';
11
+
12
+ const OPENCODE_DB_PATH = path.join(
13
+ process.env.HOME || '',
14
+ '.local',
15
+ 'share',
16
+ 'opencode',
17
+ 'opencode.db'
18
+ );
19
+
20
+ export function getOpenCodeConversation(
21
+ sessionId: string,
22
+ offset = 0,
23
+ limit = 100
24
+ ): ConversationMessage[] {
25
+ const db = getDb();
26
+ if (!db) {
27
+ return [];
28
+ }
29
+
30
+ try {
31
+ // Get messages for this session
32
+ const messages = db
33
+ .prepare(
34
+ `
35
+ SELECT id, session_id, time_created, data
36
+ FROM message
37
+ WHERE session_id = ?
38
+ ORDER BY time_created ASC
39
+ LIMIT ? OFFSET ?
40
+ `
41
+ )
42
+ .all(sessionId, limit, offset) as {
43
+ data: string;
44
+ id: string;
45
+ session_id: string;
46
+ time_created: number;
47
+ }[];
48
+
49
+ // Get parts for these messages
50
+ const messageIds = messages.map((m) => m.id);
51
+ if (messageIds.length === 0) {
52
+ return [];
53
+ }
54
+
55
+ const placeholders = messageIds.map(() => '?').join(',');
56
+ const parts = db
57
+ .prepare(
58
+ `
59
+ SELECT id, message_id, time_created, data
60
+ FROM part
61
+ WHERE message_id IN (${placeholders})
62
+ ORDER BY time_created ASC
63
+ `
64
+ )
65
+ .all(...messageIds) as {
66
+ data: string;
67
+ id: string;
68
+ message_id: string;
69
+ time_created: number;
70
+ }[];
71
+
72
+ // Group parts by message
73
+ const partsByMessage = new Map<string, typeof parts>();
74
+ for (const part of parts) {
75
+ if (!partsByMessage.has(part.message_id)) {
76
+ partsByMessage.set(part.message_id, []);
77
+ }
78
+ const bucket = partsByMessage.get(part.message_id);
79
+ if (bucket) {
80
+ bucket.push(part);
81
+ }
82
+ }
83
+
84
+ // Build ConversationMessage array
85
+ const result: ConversationMessage[] = [];
86
+
87
+ for (const msg of messages) {
88
+ let msgData: { agent?: string; role?: string } = {};
89
+ try {
90
+ msgData = JSON.parse(msg.data) as typeof msgData;
91
+ } catch {
92
+ // skip unparseable message data
93
+ }
94
+
95
+ const role = msgData.role === 'user' ? 'user' : 'assistant';
96
+ const msgParts = partsByMessage.get(msg.id) || [];
97
+ const convertedParts: MessagePart[] = [];
98
+
99
+ for (const part of msgParts) {
100
+ let partData: Record<string, unknown> = {};
101
+ try {
102
+ partData = JSON.parse(part.data) as Record<string, unknown>;
103
+ } catch {
104
+ continue;
105
+ }
106
+
107
+ const converted = convertOpenCodePart(partData);
108
+ if (converted) {
109
+ convertedParts.push(converted);
110
+ }
111
+ }
112
+
113
+ if (convertedParts.length > 0) {
114
+ result.push({
115
+ id: msg.id,
116
+ parts: convertedParts,
117
+ role: role as 'assistant' | 'system' | 'user',
118
+ timestamp: new Date(msg.time_created).toISOString(),
119
+ });
120
+ }
121
+ }
122
+
123
+ return result;
124
+ } catch (error) {
125
+ console.error('[opencode] Failed to read conversation:', error);
126
+ return [];
127
+ } finally {
128
+ db.close();
129
+ }
130
+ }
131
+
132
+ export function listOpenCodeProjects(): ProjectGroup[] {
133
+ const db = getDb();
134
+ if (!db) {
135
+ return [];
136
+ }
137
+
138
+ try {
139
+ // Get all sessions with their directories
140
+ const sessions = db
141
+ .prepare(
142
+ `
143
+ SELECT id, directory, title, slug, time_created, time_updated, parent_id
144
+ FROM session
145
+ WHERE time_archived IS NULL OR time_archived = 0
146
+ ORDER BY time_updated DESC
147
+ `
148
+ )
149
+ .all() as {
150
+ directory: string;
151
+ id: string;
152
+ parent_id: null | string;
153
+ slug: null | string;
154
+ time_created: number;
155
+ time_updated: number;
156
+ title: null | string;
157
+ }[];
158
+
159
+ // Get message counts per session
160
+ const msgCounts = db
161
+ .prepare(`SELECT session_id, COUNT(*) as count FROM message GROUP BY session_id`)
162
+ .all() as { count: number; session_id: string }[];
163
+ const msgCountMap = new Map(msgCounts.map((r) => [r.session_id, r.count]));
164
+
165
+ // Group by directory (project)
166
+ const projectMap = new Map<string, SessionInfo[]>();
167
+
168
+ for (const row of sessions) {
169
+ const dir = row.directory || 'unknown';
170
+ if (!projectMap.has(dir)) {
171
+ projectMap.set(dir, []);
172
+ }
173
+
174
+ const sessionInfo: SessionInfo = {
175
+ created: new Date(row.time_created).toISOString(),
176
+ gitBranch: '',
177
+ id: row.id,
178
+ messageCount: msgCountMap.get(row.id) || 0,
179
+ modified: new Date(row.time_updated).toISOString(),
180
+ projectPath: dir,
181
+ source: 'opencode' as const,
182
+ summary: '',
183
+ title: row.title || row.slug || 'Untitled Session',
184
+ };
185
+
186
+ const bucket = projectMap.get(dir);
187
+ if (bucket) {
188
+ bucket.push(sessionInfo);
189
+ }
190
+ }
191
+
192
+ // Build ProjectGroup array
193
+ const projects: ProjectGroup[] = [];
194
+
195
+ for (const [dir, dirSessions] of projectMap) {
196
+ const pathSegments = dir.split('/').filter(Boolean);
197
+ const projectName = pathSegments.slice(-2).join('/');
198
+
199
+ // Sort sessions by modified desc
200
+ dirSessions.sort((a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime());
201
+
202
+ projects.push({
203
+ fullPath: dir,
204
+ id: shortHash(dir),
205
+ lastModified: dirSessions[0]?.modified || '',
206
+ name: `${projectName} (OpenCode)`,
207
+ sessionCount: dirSessions.length,
208
+ sessions: dirSessions,
209
+ });
210
+ }
211
+
212
+ return projects.sort(
213
+ (a, b) => new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime()
214
+ );
215
+ } catch (error) {
216
+ console.error('[opencode] Failed to read sessions:', error);
217
+ return [];
218
+ } finally {
219
+ db.close();
220
+ }
221
+ }
222
+
223
+ function convertOpenCodePart(data: Record<string, unknown>): MessagePart | null {
224
+ const type = data.type as string;
225
+
226
+ switch (type) {
227
+ case 'reasoning':
228
+ return {
229
+ content: (data.text as string) || '',
230
+ type: 'thinking',
231
+ };
232
+
233
+ case 'text':
234
+ return {
235
+ content: (data.text as string) || '',
236
+ type: 'text',
237
+ };
238
+
239
+ case 'tool': {
240
+ const state = data.state as Record<string, unknown> | undefined;
241
+ return {
242
+ id: (data.callID as string) || (data.id as string) || '',
243
+ input: (state?.input as Record<string, unknown>) || {},
244
+ toolName: (data.tool as string) || 'Unknown',
245
+ type: 'tool_use',
246
+ };
247
+ }
248
+
249
+ default:
250
+ // Skip snapshot, patch, step-start, step-finish, subtask, retry, compaction
251
+ return null;
252
+ }
253
+ }
254
+
255
+ function getDb(): Database.Database | null {
256
+ if (!fs.existsSync(OPENCODE_DB_PATH)) {
257
+ return null;
258
+ }
259
+ try {
260
+ return new Database(OPENCODE_DB_PATH, { readonly: true });
261
+ } catch {
262
+ return null;
263
+ }
264
+ }
@@ -0,0 +1,53 @@
1
+ export interface ConversationMessage {
2
+ id: string;
3
+ parts: MessagePart[];
4
+ role: 'assistant' | 'system' | 'user';
5
+ timestamp: string;
6
+ }
7
+
8
+ export type MessagePart = TextPart | ThinkingPart | ToolResultPart | ToolUsePart;
9
+
10
+ export interface ProjectGroup {
11
+ fullPath: string;
12
+ id: string;
13
+ lastModified: string;
14
+ name: string;
15
+ sessionCount: number;
16
+ sessions: SessionInfo[];
17
+ }
18
+
19
+ export interface SessionInfo {
20
+ created: string;
21
+ gitBranch: string;
22
+ id: string;
23
+ messageCount: number;
24
+ modified: string;
25
+ projectPath: string;
26
+ source: 'claude-code' | 'opencode';
27
+ summary: string;
28
+ title: string;
29
+ }
30
+
31
+ export interface TextPart {
32
+ content: string;
33
+ type: 'text';
34
+ }
35
+
36
+ export interface ThinkingPart {
37
+ content: string;
38
+ type: 'thinking';
39
+ }
40
+
41
+ export interface ToolResultPart {
42
+ isError: boolean;
43
+ output: string;
44
+ toolUseId: string;
45
+ type: 'tool_result';
46
+ }
47
+
48
+ export interface ToolUsePart {
49
+ id: string;
50
+ input: Record<string, unknown>;
51
+ toolName: string;
52
+ type: 'tool_use';
53
+ }