@juspay/shooter 1.18.0 → 1.19.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 (305) hide show
  1. package/build/client/_app/immutable/assets/{0.NV8k8wxG.css → 0.BwNtE8TX.css} +1 -1
  2. package/build/client/_app/immutable/assets/0.BwNtE8TX.css.br +0 -0
  3. package/build/client/_app/immutable/assets/{0.NV8k8wxG.css.gz → 0.BwNtE8TX.css.gz} +0 -0
  4. package/build/client/_app/immutable/assets/8.BYgAX7hR.css +1 -0
  5. package/build/client/_app/immutable/assets/8.BYgAX7hR.css.br +0 -0
  6. package/build/client/_app/immutable/assets/8.BYgAX7hR.css.gz +0 -0
  7. package/build/client/_app/immutable/assets/9.DV6pZunn.css +1 -0
  8. package/build/client/_app/immutable/assets/9.DV6pZunn.css.br +0 -0
  9. package/build/client/_app/immutable/assets/9.DV6pZunn.css.gz +0 -0
  10. package/build/client/_app/immutable/chunks/{DZQMsHM5.js → 2rBV5OkJ.js} +1 -1
  11. package/build/client/_app/immutable/chunks/2rBV5OkJ.js.br +0 -0
  12. package/build/client/_app/immutable/chunks/2rBV5OkJ.js.gz +0 -0
  13. package/build/client/_app/immutable/chunks/{B9WQy_3X.js → BB2l8o4X.js} +1 -1
  14. package/build/client/_app/immutable/chunks/BB2l8o4X.js.br +0 -0
  15. package/build/client/_app/immutable/chunks/BB2l8o4X.js.gz +0 -0
  16. package/build/client/_app/immutable/chunks/{Cg3dlX05.js → BPDiEZo0.js} +2 -2
  17. package/build/client/_app/immutable/chunks/BPDiEZo0.js.br +0 -0
  18. package/build/client/_app/immutable/chunks/BPDiEZo0.js.gz +0 -0
  19. package/build/client/_app/immutable/chunks/{C_9BZILB.js → BcpydfqI.js} +1 -1
  20. package/build/client/_app/immutable/chunks/BcpydfqI.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/BcpydfqI.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/{nWG9RHyB.js → BcqA7eKM.js} +2 -2
  23. package/build/client/_app/immutable/chunks/BcqA7eKM.js.br +0 -0
  24. package/build/client/_app/immutable/chunks/BcqA7eKM.js.gz +0 -0
  25. package/build/client/_app/immutable/chunks/{BRqaaL5D.js → BvmdJful.js} +1 -1
  26. package/build/client/_app/immutable/chunks/BvmdJful.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/BvmdJful.js.gz +0 -0
  28. package/build/client/_app/immutable/chunks/{C5VOyQCG.js → ClIPTXf3.js} +1 -1
  29. package/build/client/_app/immutable/chunks/ClIPTXf3.js.br +0 -0
  30. package/build/client/_app/immutable/chunks/ClIPTXf3.js.gz +0 -0
  31. package/build/client/_app/immutable/chunks/{8lO1IL7u.js → DA4Zt9Me.js} +1 -1
  32. package/build/client/_app/immutable/chunks/DA4Zt9Me.js.br +0 -0
  33. package/build/client/_app/immutable/chunks/{8lO1IL7u.js.gz → DA4Zt9Me.js.gz} +0 -0
  34. package/build/client/_app/immutable/chunks/{DJvX78LW.js → DCDL_9ys.js} +1 -1
  35. package/build/client/_app/immutable/chunks/DCDL_9ys.js.br +0 -0
  36. package/build/client/_app/immutable/chunks/DCDL_9ys.js.gz +0 -0
  37. package/build/client/_app/immutable/chunks/{DYuMZGL5.js → DWmC0QM7.js} +1 -1
  38. package/build/client/_app/immutable/chunks/DWmC0QM7.js.br +0 -0
  39. package/build/client/_app/immutable/chunks/DWmC0QM7.js.gz +0 -0
  40. package/build/client/_app/immutable/chunks/{DZvnhU_8.js → ZS5XYDx_.js} +2 -2
  41. package/build/client/_app/immutable/chunks/ZS5XYDx_.js.br +0 -0
  42. package/build/client/_app/immutable/chunks/ZS5XYDx_.js.gz +0 -0
  43. package/build/client/_app/immutable/entry/app.D4TXlu7A.js +2 -0
  44. package/build/client/_app/immutable/entry/app.D4TXlu7A.js.br +0 -0
  45. package/build/client/_app/immutable/entry/app.D4TXlu7A.js.gz +0 -0
  46. package/build/client/_app/immutable/entry/start.BBQhtURO.js +1 -0
  47. package/build/client/_app/immutable/entry/start.BBQhtURO.js.br +0 -0
  48. package/build/client/_app/immutable/entry/start.BBQhtURO.js.gz +0 -0
  49. package/build/client/_app/immutable/nodes/0.1zylwAPT.js +10 -0
  50. package/build/client/_app/immutable/nodes/0.1zylwAPT.js.br +0 -0
  51. package/build/client/_app/immutable/nodes/0.1zylwAPT.js.gz +0 -0
  52. package/build/client/_app/immutable/nodes/{1.C4eFlqSB.js → 1.BVnLUSs-.js} +1 -1
  53. package/build/client/_app/immutable/nodes/1.BVnLUSs-.js.br +0 -0
  54. package/build/client/_app/immutable/nodes/1.BVnLUSs-.js.gz +0 -0
  55. package/build/client/_app/immutable/nodes/{8.Bs362gyb.js → 10.D1wl2wPX.js} +2 -2
  56. package/build/client/_app/immutable/nodes/10.D1wl2wPX.js.br +0 -0
  57. package/build/client/_app/immutable/nodes/10.D1wl2wPX.js.gz +0 -0
  58. package/build/client/_app/immutable/nodes/{9.Cf7_3uqT.js → 11.C18nMGmp.js} +1 -1
  59. package/build/client/_app/immutable/nodes/11.C18nMGmp.js.br +0 -0
  60. package/build/client/_app/immutable/nodes/11.C18nMGmp.js.gz +0 -0
  61. package/build/client/_app/immutable/nodes/{2.CdC092Za.js → 2.D1Mm0DUX.js} +2 -2
  62. package/build/client/_app/immutable/nodes/2.D1Mm0DUX.js.br +0 -0
  63. package/build/client/_app/immutable/nodes/2.D1Mm0DUX.js.gz +0 -0
  64. package/build/client/_app/immutable/nodes/{3.Dhf4ZWW0.js → 3.Wfz3TcJd.js} +3 -3
  65. package/build/client/_app/immutable/nodes/3.Wfz3TcJd.js.br +0 -0
  66. package/build/client/_app/immutable/nodes/3.Wfz3TcJd.js.gz +0 -0
  67. package/build/client/_app/immutable/nodes/{4.BSVqdrrD.js → 4.CBX9A3ka.js} +2 -2
  68. package/build/client/_app/immutable/nodes/4.CBX9A3ka.js.br +0 -0
  69. package/build/client/_app/immutable/nodes/4.CBX9A3ka.js.gz +0 -0
  70. package/build/client/_app/immutable/nodes/{5.Cfj35gpY.js → 5.DIVKuZc9.js} +1 -1
  71. package/build/client/_app/immutable/nodes/5.DIVKuZc9.js.br +0 -0
  72. package/build/client/_app/immutable/nodes/5.DIVKuZc9.js.gz +0 -0
  73. package/build/client/_app/immutable/nodes/{6.B3SEB_li.js → 6.DtZAEPXb.js} +1 -1
  74. package/build/client/_app/immutable/nodes/6.DtZAEPXb.js.br +0 -0
  75. package/build/client/_app/immutable/nodes/6.DtZAEPXb.js.gz +0 -0
  76. package/build/client/_app/immutable/nodes/{7.DV8cJ1lX.js → 7.MfBRh32I.js} +1 -1
  77. package/build/client/_app/immutable/nodes/7.MfBRh32I.js.br +0 -0
  78. package/build/client/_app/immutable/nodes/7.MfBRh32I.js.gz +0 -0
  79. package/build/client/_app/immutable/nodes/8.DVE6LnOC.js +1 -0
  80. package/build/client/_app/immutable/nodes/8.DVE6LnOC.js.br +0 -0
  81. package/build/client/_app/immutable/nodes/8.DVE6LnOC.js.gz +0 -0
  82. package/build/client/_app/immutable/nodes/9.BCel5OqI.js +2 -0
  83. package/build/client/_app/immutable/nodes/9.BCel5OqI.js.br +0 -0
  84. package/build/client/_app/immutable/nodes/9.BCel5OqI.js.gz +0 -0
  85. package/build/client/_app/version.json +1 -1
  86. package/build/client/_app/version.json.br +0 -0
  87. package/build/client/_app/version.json.gz +0 -0
  88. package/build/server/chunks/{0-Cd7jY0a7.js → 0-DJqyZZTr.js} +4 -4
  89. package/build/server/chunks/{0-Cd7jY0a7.js.map → 0-DJqyZZTr.js.map} +1 -1
  90. package/build/server/chunks/1-2YUVen1F.js +9 -0
  91. package/build/server/chunks/{1-C4BOGoJY.js.map → 1-2YUVen1F.js.map} +1 -1
  92. package/build/server/chunks/10-D1X7LB3v.js +9 -0
  93. package/build/server/chunks/10-D1X7LB3v.js.map +1 -0
  94. package/build/server/chunks/11-qXSPdF5j.js +9 -0
  95. package/build/server/chunks/11-qXSPdF5j.js.map +1 -0
  96. package/build/server/chunks/{2-Ba0mNwJ6.js → 2-BD7kj1mt.js} +3 -3
  97. package/build/server/chunks/{2-Ba0mNwJ6.js.map → 2-BD7kj1mt.js.map} +1 -1
  98. package/build/server/chunks/{3-Pg8t1uJU.js → 3-oNjv-BhZ.js} +3 -3
  99. package/build/server/chunks/{3-Pg8t1uJU.js.map → 3-oNjv-BhZ.js.map} +1 -1
  100. package/build/server/chunks/{4-BtYdKCVW.js → 4-Bb5VFhsO.js} +3 -3
  101. package/build/server/chunks/{4-BtYdKCVW.js.map → 4-Bb5VFhsO.js.map} +1 -1
  102. package/build/server/chunks/{5-CvJK3PiH.js → 5-oNoWuIsn.js} +3 -3
  103. package/build/server/chunks/{5-CvJK3PiH.js.map → 5-oNoWuIsn.js.map} +1 -1
  104. package/build/server/chunks/6-DRJGUqHG.js +9 -0
  105. package/build/server/chunks/{6-D8xbnTSo.js.map → 6-DRJGUqHG.js.map} +1 -1
  106. package/build/server/chunks/7-_giJiu0L.js +9 -0
  107. package/build/server/chunks/{7-CkVK06S0.js.map → 7-_giJiu0L.js.map} +1 -1
  108. package/build/server/chunks/8-zvWAVNT5.js +9 -0
  109. package/build/server/chunks/8-zvWAVNT5.js.map +1 -0
  110. package/build/server/chunks/9-DVyDL445.js +9 -0
  111. package/build/server/chunks/9-DVyDL445.js.map +1 -0
  112. package/build/server/chunks/Banner-BgaAs1rs.js +90 -0
  113. package/build/server/chunks/Banner-BgaAs1rs.js.map +1 -0
  114. package/build/server/chunks/{Button-B5dU-ntz.js → Button-D0hZ7JYt.js} +2 -2
  115. package/build/server/chunks/Button-D0hZ7JYt.js.map +1 -0
  116. package/build/server/chunks/{Icon-C7Ml3GX6.js → Icon-D0GBnDcs.js} +3 -3
  117. package/build/server/chunks/Icon-D0GBnDcs.js.map +1 -0
  118. package/build/server/chunks/{Input-CPGO0sbS.js → Input-OmIiydSx.js} +2 -2
  119. package/build/server/chunks/Input-OmIiydSx.js.map +1 -0
  120. package/build/server/chunks/{Pill-CcrtCejm.js → Pill-4xJ-VhAA.js} +3 -3
  121. package/build/server/chunks/Pill-4xJ-VhAA.js.map +1 -0
  122. package/build/server/chunks/{Shimmer-C5jkvGr1.js → Shimmer-Dw2uvTC1.js} +2 -2
  123. package/build/server/chunks/Shimmer-Dw2uvTC1.js.map +1 -0
  124. package/build/server/chunks/{_error.svelte-CSIxs-ab.js → _error.svelte-CZnkxeLr.js} +8 -8
  125. package/build/server/chunks/{_error.svelte-CSIxs-ab.js.map → _error.svelte-CZnkxeLr.js.map} +1 -1
  126. package/build/server/chunks/{_layout.svelte-noB4j-v2.js → _layout.svelte-DfgNGGiM.js} +16 -11
  127. package/build/server/chunks/_layout.svelte-DfgNGGiM.js.map +1 -0
  128. package/build/server/chunks/{_page.svelte-DnTpPnPR.js → _page.svelte-BLo2v_8E.js} +7 -88
  129. package/build/server/chunks/_page.svelte-BLo2v_8E.js.map +1 -0
  130. package/build/server/chunks/_page.svelte-BTlfUsBp.js +43 -0
  131. package/build/server/chunks/_page.svelte-BTlfUsBp.js.map +1 -0
  132. package/build/server/chunks/{_page.svelte-C60lAagP.js → _page.svelte-BUBLUSGo.js} +8 -8
  133. package/build/server/chunks/_page.svelte-BUBLUSGo.js.map +1 -0
  134. package/build/server/chunks/{_page.svelte-BV0XyYJZ.js → _page.svelte-BX2FMgSg.js} +4 -4
  135. package/build/server/chunks/{_page.svelte-BV0XyYJZ.js.map → _page.svelte-BX2FMgSg.js.map} +1 -1
  136. package/build/server/chunks/{_page.svelte-BUkm2304.js → _page.svelte-C7B0qdrC.js} +5 -5
  137. package/build/server/chunks/{_page.svelte-BUkm2304.js.map → _page.svelte-C7B0qdrC.js.map} +1 -1
  138. package/build/server/chunks/{_page.svelte-Dmg-RFCg.js → _page.svelte-CE7COWnF.js} +7 -7
  139. package/build/server/chunks/{_page.svelte-Dmg-RFCg.js.map → _page.svelte-CE7COWnF.js.map} +1 -1
  140. package/build/server/chunks/{_page.svelte-BfB8maoc.js → _page.svelte-CWsjjd4l.js} +9 -9
  141. package/build/server/chunks/{_page.svelte-BfB8maoc.js.map → _page.svelte-CWsjjd4l.js.map} +1 -1
  142. package/build/server/chunks/_page.svelte-D5S2hkBk.js +104 -0
  143. package/build/server/chunks/_page.svelte-D5S2hkBk.js.map +1 -0
  144. package/build/server/chunks/{_page.svelte-B6qyh-K-.js → _page.svelte-D_Ey8QRG.js} +11 -11
  145. package/build/server/chunks/{_page.svelte-B6qyh-K-.js.map → _page.svelte-D_Ey8QRG.js.map} +1 -1
  146. package/build/server/chunks/{_page.svelte-DuzZr5dA.js → _page.svelte-tBuIq8Pg.js} +11 -11
  147. package/build/server/chunks/{_page.svelte-DuzZr5dA.js.map → _page.svelte-tBuIq8Pg.js.map} +1 -1
  148. package/build/server/chunks/_server.ts-BaaY7Z9D.js +77 -0
  149. package/build/server/chunks/_server.ts-BaaY7Z9D.js.map +1 -0
  150. package/build/server/chunks/{_server.ts-Bu3s5hfv.js → _server.ts-Bi0Oe4PF.js} +6 -3
  151. package/build/server/chunks/_server.ts-Bi0Oe4PF.js.map +1 -0
  152. package/build/server/chunks/_server.ts-C0317RBD.js +57 -0
  153. package/build/server/chunks/_server.ts-C0317RBD.js.map +1 -0
  154. package/build/server/chunks/{_server.ts-CwAjt91u.js → _server.ts-CRVNEOd2.js} +5 -3
  155. package/build/server/chunks/{_server.ts-CwAjt91u.js.map → _server.ts-CRVNEOd2.js.map} +1 -1
  156. package/build/server/chunks/_server.ts-CVPZOpiv.js +23 -0
  157. package/build/server/chunks/_server.ts-CVPZOpiv.js.map +1 -0
  158. package/build/server/chunks/{_server.ts-CyjDrcZN.js → _server.ts-C_OOUqsd.js} +9 -1
  159. package/build/server/chunks/_server.ts-C_OOUqsd.js.map +1 -0
  160. package/build/server/chunks/{_server.ts-DZgfQKiH.js → _server.ts-D9ir7u24.js} +2 -2
  161. package/build/server/chunks/{_server.ts-DZgfQKiH.js.map → _server.ts-D9ir7u24.js.map} +1 -1
  162. package/build/server/chunks/{_server.ts-DZ5naqSL.js → _server.ts-DMm0hBP4.js} +5 -1
  163. package/build/server/chunks/_server.ts-DMm0hBP4.js.map +1 -0
  164. package/build/server/chunks/{_server.ts-DZP2lhaY.js → _server.ts-DhJx0DLr.js} +6 -3
  165. package/build/server/chunks/_server.ts-DhJx0DLr.js.map +1 -0
  166. package/build/server/chunks/_server.ts-DkZX_O9a.js +39 -0
  167. package/build/server/chunks/_server.ts-DkZX_O9a.js.map +1 -0
  168. package/build/server/chunks/{_server.ts-BA_uWcPw.js → _server.ts-DxT9IlZF.js} +5 -3
  169. package/build/server/chunks/_server.ts-DxT9IlZF.js.map +1 -0
  170. package/build/server/chunks/_server.ts-Mttr0-Sl.js +48 -0
  171. package/build/server/chunks/_server.ts-Mttr0-Sl.js.map +1 -0
  172. package/build/server/chunks/_server.ts-jtqWDWcf.js +45 -0
  173. package/build/server/chunks/_server.ts-jtqWDWcf.js.map +1 -0
  174. package/build/server/chunks/{cache-Me3zUAaD.js → cache-BlMaDsHi.js} +2 -2
  175. package/build/server/chunks/{cache-Me3zUAaD.js.map → cache-BlMaDsHi.js.map} +1 -1
  176. package/build/server/chunks/{client-CfNnl32g.js → client-Ds1brw-8.js} +4 -4
  177. package/build/server/chunks/{client-CfNnl32g.js.map → client-Ds1brw-8.js.map} +1 -1
  178. package/build/server/chunks/client2-DngLdcUc.js +7 -0
  179. package/build/server/chunks/{client2-DDP30_vY.js.map → client2-DngLdcUc.js.map} +1 -1
  180. package/build/server/chunks/coordinator-DMU_ADXf.js +530 -0
  181. package/build/server/chunks/coordinator-DMU_ADXf.js.map +1 -0
  182. package/build/server/chunks/{index-CJrGuxuM.js → index-CoYB03g7.js} +2 -2
  183. package/build/server/chunks/{index-CJrGuxuM.js.map → index-CoYB03g7.js.map} +1 -1
  184. package/build/server/chunks/{index-server--49oHtA0.js → index-server-Bq3cnK69.js} +2 -2
  185. package/build/server/chunks/{index-server--49oHtA0.js.map → index-server-Bq3cnK69.js.map} +1 -1
  186. package/build/server/chunks/{index2-MY7PXeAc.js → index2-dSGQ9Eaa.js} +2 -2
  187. package/build/server/chunks/{index2-MY7PXeAc.js.map → index2-dSGQ9Eaa.js.map} +1 -1
  188. package/build/server/chunks/{pty-manager-DmNSCKAr.js → pty-manager-41h3IK8K.js} +2 -1
  189. package/build/server/chunks/pty-manager-41h3IK8K.js.map +1 -0
  190. package/build/server/chunks/qwen-reader-DGfUbKaJ.js.map +1 -1
  191. package/build/server/chunks/{registry-Kcw2UCMv.js → registry-D4J_CuzW.js} +2 -2
  192. package/build/server/chunks/registry-D4J_CuzW.js.map +1 -0
  193. package/build/server/chunks/{root-xvQIR1Bt.js → root-D4IoFC8F.js} +2 -2
  194. package/build/server/chunks/root-D4IoFC8F.js.map +1 -0
  195. package/build/server/chunks/{state.svelte-RCtlkrNH.js → state.svelte-CmHqngc_.js} +3 -3
  196. package/build/server/chunks/{state.svelte-RCtlkrNH.js.map → state.svelte-CmHqngc_.js.map} +1 -1
  197. package/build/server/chunks/{stores-C-LqoonT.js → stores-CRYxfF0o.js} +4 -4
  198. package/build/server/chunks/stores-CRYxfF0o.js.map +1 -0
  199. package/build/server/chunks/super-session-handler-DPyxFgmz.js +22 -0
  200. package/build/server/chunks/super-session-handler-DPyxFgmz.js.map +1 -0
  201. package/build/server/index.js +4 -4
  202. package/build/server/index.js.map +1 -1
  203. package/build/server/manifest.js +78 -20
  204. package/build/server/manifest.js.map +1 -1
  205. package/package.json +2 -2
  206. package/scripts/e2e-all-features.sh +41 -2
  207. package/server.ts +25 -0
  208. package/src/lib/modules/server/sos/coordinator.ts +492 -0
  209. package/src/lib/modules/server/sos/policy-gate.ts +56 -0
  210. package/src/lib/modules/server/sos/relay-store.ts +159 -0
  211. package/src/lib/modules/server/terminal/pty-input.ts +37 -0
  212. package/src/lib/modules/server/ws/server.ts +6 -1
  213. package/src/lib/modules/server/ws/session-handler.ts +6 -1
  214. package/src/lib/modules/server/ws/super-session-handler.ts +200 -0
  215. package/src/lib/types/index.ts +2 -1
  216. package/src/lib/types/sos.ts +134 -0
  217. package/src/routes/+layout.svelte +9 -2
  218. package/src/routes/api/sos/+server.ts +36 -0
  219. package/src/routes/api/sos/[id]/+server.ts +55 -0
  220. package/src/routes/api/sos/[id]/inject/+server.ts +44 -0
  221. package/src/routes/api/sos/[id]/members/+server.ts +47 -0
  222. package/src/routes/api/sos/[id]/members/[mid]/+server.ts +17 -0
  223. package/src/routes/api/sos/[id]/rules/+server.ts +85 -0
  224. package/src/routes/sos/+page.svelte +195 -0
  225. package/src/routes/sos/[id]/+page.svelte +677 -0
  226. package/build/client/_app/immutable/assets/0.NV8k8wxG.css.br +0 -0
  227. package/build/client/_app/immutable/chunks/8lO1IL7u.js.br +0 -0
  228. package/build/client/_app/immutable/chunks/B9WQy_3X.js.br +0 -0
  229. package/build/client/_app/immutable/chunks/B9WQy_3X.js.gz +0 -0
  230. package/build/client/_app/immutable/chunks/BRqaaL5D.js.br +0 -0
  231. package/build/client/_app/immutable/chunks/BRqaaL5D.js.gz +0 -0
  232. package/build/client/_app/immutable/chunks/C5VOyQCG.js.br +0 -0
  233. package/build/client/_app/immutable/chunks/C5VOyQCG.js.gz +0 -0
  234. package/build/client/_app/immutable/chunks/C_9BZILB.js.br +0 -0
  235. package/build/client/_app/immutable/chunks/C_9BZILB.js.gz +0 -0
  236. package/build/client/_app/immutable/chunks/Cg3dlX05.js.br +0 -0
  237. package/build/client/_app/immutable/chunks/Cg3dlX05.js.gz +0 -0
  238. package/build/client/_app/immutable/chunks/DJvX78LW.js.br +0 -0
  239. package/build/client/_app/immutable/chunks/DJvX78LW.js.gz +0 -0
  240. package/build/client/_app/immutable/chunks/DYuMZGL5.js.br +0 -0
  241. package/build/client/_app/immutable/chunks/DYuMZGL5.js.gz +0 -0
  242. package/build/client/_app/immutable/chunks/DZQMsHM5.js.br +0 -0
  243. package/build/client/_app/immutable/chunks/DZQMsHM5.js.gz +0 -0
  244. package/build/client/_app/immutable/chunks/DZvnhU_8.js.br +0 -0
  245. package/build/client/_app/immutable/chunks/DZvnhU_8.js.gz +0 -0
  246. package/build/client/_app/immutable/chunks/nWG9RHyB.js.br +0 -0
  247. package/build/client/_app/immutable/chunks/nWG9RHyB.js.gz +0 -0
  248. package/build/client/_app/immutable/entry/app.f46Ko1hu.js +0 -2
  249. package/build/client/_app/immutable/entry/app.f46Ko1hu.js.br +0 -0
  250. package/build/client/_app/immutable/entry/app.f46Ko1hu.js.gz +0 -0
  251. package/build/client/_app/immutable/entry/start.BVDjNnXt.js +0 -1
  252. package/build/client/_app/immutable/entry/start.BVDjNnXt.js.br +0 -2
  253. package/build/client/_app/immutable/entry/start.BVDjNnXt.js.gz +0 -0
  254. package/build/client/_app/immutable/nodes/0.D_9EwVmq.js +0 -7
  255. package/build/client/_app/immutable/nodes/0.D_9EwVmq.js.br +0 -0
  256. package/build/client/_app/immutable/nodes/0.D_9EwVmq.js.gz +0 -0
  257. package/build/client/_app/immutable/nodes/1.C4eFlqSB.js.br +0 -0
  258. package/build/client/_app/immutable/nodes/1.C4eFlqSB.js.gz +0 -0
  259. package/build/client/_app/immutable/nodes/2.CdC092Za.js.br +0 -0
  260. package/build/client/_app/immutable/nodes/2.CdC092Za.js.gz +0 -0
  261. package/build/client/_app/immutable/nodes/3.Dhf4ZWW0.js.br +0 -0
  262. package/build/client/_app/immutable/nodes/3.Dhf4ZWW0.js.gz +0 -0
  263. package/build/client/_app/immutable/nodes/4.BSVqdrrD.js.br +0 -0
  264. package/build/client/_app/immutable/nodes/4.BSVqdrrD.js.gz +0 -0
  265. package/build/client/_app/immutable/nodes/5.Cfj35gpY.js.br +0 -0
  266. package/build/client/_app/immutable/nodes/5.Cfj35gpY.js.gz +0 -0
  267. package/build/client/_app/immutable/nodes/6.B3SEB_li.js.br +0 -0
  268. package/build/client/_app/immutable/nodes/6.B3SEB_li.js.gz +0 -0
  269. package/build/client/_app/immutable/nodes/7.DV8cJ1lX.js.br +0 -0
  270. package/build/client/_app/immutable/nodes/7.DV8cJ1lX.js.gz +0 -0
  271. package/build/client/_app/immutable/nodes/8.Bs362gyb.js.br +0 -0
  272. package/build/client/_app/immutable/nodes/8.Bs362gyb.js.gz +0 -0
  273. package/build/client/_app/immutable/nodes/9.Cf7_3uqT.js.br +0 -0
  274. package/build/client/_app/immutable/nodes/9.Cf7_3uqT.js.gz +0 -0
  275. package/build/server/chunks/1-C4BOGoJY.js +0 -9
  276. package/build/server/chunks/6-D8xbnTSo.js +0 -9
  277. package/build/server/chunks/7-CkVK06S0.js +0 -9
  278. package/build/server/chunks/8-C8qVhrds.js +0 -9
  279. package/build/server/chunks/8-C8qVhrds.js.map +0 -1
  280. package/build/server/chunks/9-fL5zqN0T.js +0 -9
  281. package/build/server/chunks/9-fL5zqN0T.js.map +0 -1
  282. package/build/server/chunks/Button-B5dU-ntz.js.map +0 -1
  283. package/build/server/chunks/Icon-C7Ml3GX6.js.map +0 -1
  284. package/build/server/chunks/Input-CPGO0sbS.js.map +0 -1
  285. package/build/server/chunks/Pill-CcrtCejm.js.map +0 -1
  286. package/build/server/chunks/Shimmer-C5jkvGr1.js.map +0 -1
  287. package/build/server/chunks/_layout.svelte-noB4j-v2.js.map +0 -1
  288. package/build/server/chunks/_page.svelte-C60lAagP.js.map +0 -1
  289. package/build/server/chunks/_page.svelte-DnTpPnPR.js.map +0 -1
  290. package/build/server/chunks/_server.ts-BA_uWcPw.js.map +0 -1
  291. package/build/server/chunks/_server.ts-Bu3s5hfv.js.map +0 -1
  292. package/build/server/chunks/_server.ts-CyjDrcZN.js.map +0 -1
  293. package/build/server/chunks/_server.ts-DZ5naqSL.js.map +0 -1
  294. package/build/server/chunks/_server.ts-DZP2lhaY.js.map +0 -1
  295. package/build/server/chunks/client2-DDP30_vY.js +0 -7
  296. package/build/server/chunks/pty-manager-DmNSCKAr.js.map +0 -1
  297. package/build/server/chunks/registry-Kcw2UCMv.js.map +0 -1
  298. package/build/server/chunks/root-xvQIR1Bt.js.map +0 -1
  299. package/build/server/chunks/stores-C-LqoonT.js.map +0 -1
  300. /package/build/client/_app/immutable/assets/{8.BhoBXADL.css → 10.BhoBXADL.css} +0 -0
  301. /package/build/client/_app/immutable/assets/{8.BhoBXADL.css.br → 10.BhoBXADL.css.br} +0 -0
  302. /package/build/client/_app/immutable/assets/{8.BhoBXADL.css.gz → 10.BhoBXADL.css.gz} +0 -0
  303. /package/build/client/_app/immutable/assets/{9.v5KA95xm.css → 11.v5KA95xm.css} +0 -0
  304. /package/build/client/_app/immutable/assets/{9.v5KA95xm.css.br → 11.v5KA95xm.css.br} +0 -0
  305. /package/build/client/_app/immutable/assets/{9.v5KA95xm.css.gz → 11.v5KA95xm.css.gz} +0 -0
@@ -0,0 +1,37 @@
1
+ /**
2
+ * PTY input helpers.
3
+ *
4
+ * Submitting text to an interactive agent TUI (codex, claude, gemini, qwen, …)
5
+ * is not as simple as appending a newline. These TUIs read the PTY in raw mode:
6
+ *
7
+ * - A bare LF (`\n`) is NOT the Enter key — it types a literal newline into
8
+ * the prompt and never submits. (Verified: LF leaves codex sitting on its
9
+ * prompt; the message just accumulates.)
10
+ * - Even `"<text>\r"` written as a SINGLE chunk is treated as a bracketed
11
+ * paste by the TUI, so the trailing CR is absorbed into the pasted body
12
+ * instead of submitting. (Verified: codex types the text but does not run.)
13
+ *
14
+ * The reliable approach — the same bytes a real terminal emulator sends when a
15
+ * human pastes and presses Enter — is to wrap the body in an explicit bracketed
16
+ * paste (`ESC[200~` … `ESC[201~`) and then send a CR. The paste-end marker
17
+ * closes the paste unambiguously, so the following CR is a real Enter. This
18
+ * also preserves embedded newlines in multi-line messages (the whole point of
19
+ * bracketed paste) and submits correctly in modern interactive shells, where
20
+ * bracketed paste is enabled by default.
21
+ *
22
+ * Verified empirically against codex 0.136 and claude 2.1 — both receive the
23
+ * message and complete a turn.
24
+ */
25
+
26
+ const PASTE_START = '\x1b[200~';
27
+ const PASTE_END = '\x1b[201~';
28
+
29
+ /**
30
+ * Build the PTY byte sequence that delivers `text` to an interactive terminal
31
+ * and submits it (presses Enter). Any trailing newline the caller added is
32
+ * stripped — the CR after the paste-end marker is what submits.
33
+ */
34
+ export function ptySubmitSequence(text: string): string {
35
+ const body = text.replace(/[\r\n]+$/, '');
36
+ return `${PASTE_START}${body}${PASTE_END}\r`;
37
+ }
@@ -15,6 +15,7 @@ import {
15
15
  handleEventsConnection,
16
16
  } from './events-handler.js';
17
17
  import { handleSessionConnection } from './session-handler.js';
18
+ import { handleSuperSessionConnection } from './super-session-handler.js';
18
19
  import { handleTerminalConnection } from './terminal-handler.js';
19
20
  export type { WireShooterEvent as ShooterEvent } from '$lib/types';
20
21
 
@@ -61,10 +62,11 @@ export function setupWebSocketHandlers(
61
62
 
62
63
  // Route matching
63
64
  const terminalMatch = /^\/ws\/terminal\/(.+)$/.exec(pathname);
65
+ const superSessionMatch = /^\/ws\/super-session\/(.+)$/.exec(pathname);
64
66
  const sessionMatch = /^\/ws\/session\/(.+)$/.exec(pathname);
65
67
  const isEvents = pathname === '/ws/events';
66
68
 
67
- if (!terminalMatch && !sessionMatch && !isEvents) {
69
+ if (!terminalMatch && !superSessionMatch && !sessionMatch && !isEvents) {
68
70
  socket.destroy();
69
71
  return;
70
72
  }
@@ -83,6 +85,9 @@ export function setupWebSocketHandlers(
83
85
  if (terminalMatch) {
84
86
  const terminalId = terminalMatch[1];
85
87
  handleTerminalConnection(ws, terminalId);
88
+ } else if (superSessionMatch) {
89
+ const superSessionId = superSessionMatch[1];
90
+ handleSuperSessionConnection(ws, superSessionId);
86
91
  } else if (sessionMatch) {
87
92
  const sessionId = sessionMatch[1];
88
93
  handleSessionConnection(ws, sessionId);
@@ -23,6 +23,7 @@ import * as fs from 'fs';
23
23
  import * as path from 'path';
24
24
 
25
25
  import { findCodexRolloutById } from '../sessions/codex-reader';
26
+ import { ptySubmitSequence } from '../terminal/pty-input';
26
27
 
27
28
  // ── Module-level references ──────────────────────────────────────────
28
29
 
@@ -547,7 +548,11 @@ function wireClientMessages(ws: WebSocket, state: ConnectionState): void {
547
548
  safeSend(ws, { message: 'Terminal has exited', type: 'error' });
548
549
  return;
549
550
  }
550
- currentTerminal.pty.write(`${msg.text}\n`);
551
+ // Deliver + submit via a bracketed paste (see pty-input.ts): a bare
552
+ // LF never submits to an agent TUI and a trailing CR in the same
553
+ // write is absorbed as paste content. Bracketed paste closes the
554
+ // paste explicitly so the following CR is a real Enter.
555
+ currentTerminal.pty.write(ptySubmitSequence(msg.text));
551
556
  break;
552
557
  }
553
558
 
@@ -0,0 +1,200 @@
1
+ // WebSocket handler for /ws/super-session/:id — the merged Session-Over-Sessions
2
+ // stream. On connect it replays the merged transcript (sos-history) and then
3
+ // streams live tagged messages from every member. Accepts human-driven control
4
+ // messages: relay-forward (inject into a member's terminal), member-add,
5
+ // member-remove. Mirrors session-handler.ts in shape.
6
+
7
+ import type { SessionSource, SosClientMessage, SosServerMessage } from '$lib/types';
8
+ import type { WebSocket } from 'ws';
9
+
10
+ import * as path from 'path';
11
+
12
+ import { PROVIDERS } from '../sessions/registry';
13
+ import { sosCoordinator } from '../sos/coordinator';
14
+
15
+ const MAX_RELAY_TEXT = 10240; // 10 KB, same cap as /ws/session send-input
16
+ // Stop streaming to a client whose outbound buffer exceeds this — bounds memory
17
+ // growth when a slow consumer can't drain sos-history replay or a live burst.
18
+ const MAX_WS_BUFFERED_BYTES = 1_000_000;
19
+ const VALID_SOURCES = new Set<string>(PROVIDERS.map((p) => p.source));
20
+
21
+ export function handleSuperSessionConnection(ws: WebSocket, id: string): void {
22
+ const session = sosCoordinator.getSuperSession(id);
23
+ if (!session) {
24
+ safeSend(ws, { message: `Super-session not found: ${id}`, type: 'sos-error' });
25
+ ws.close(1008, 'Super-session not found');
26
+ return;
27
+ }
28
+
29
+ // subscribe() replays the current transcript as an sos-history message, then
30
+ // streams live sos-message / sos-member-* events. If a send fails (socket
31
+ // closed or buffer over cap), stop feeding this client to bound memory.
32
+ let unsubscribe: (() => void) | null = null;
33
+ unsubscribe = sosCoordinator.subscribe(id, (msg) => {
34
+ if (!safeSend(ws, msg)) {
35
+ unsubscribe?.();
36
+ unsubscribe = null;
37
+ }
38
+ });
39
+
40
+ ws.on('message', (raw: Buffer | string) => {
41
+ const data = typeof raw === 'string' ? raw : raw.toString('utf-8');
42
+ const msg = parseClientMessage(data);
43
+ if (!msg) {
44
+ // Surface schema drift instead of silently dropping the frame — a dead
45
+ // control in the UI is much harder to debug than an explicit error.
46
+ safeSend(ws, { message: 'Invalid super-session control message', type: 'sos-error' });
47
+ return;
48
+ }
49
+ handleClientMessage(ws, id, msg);
50
+ });
51
+
52
+ ws.on('close', () => {
53
+ unsubscribe?.();
54
+ });
55
+ ws.on('error', () => {
56
+ // cleanup happens in 'close'
57
+ });
58
+ }
59
+
60
+ /** True when the string is a known provider source. */
61
+ export function isValidProvider(value: string): value is SessionSource {
62
+ return VALID_SOURCES.has(value);
63
+ }
64
+
65
+ /** True for a bare session id (OpenCode) or an absolute path under HOME. */
66
+ export function isValidSessionKey(key: string): boolean {
67
+ if (/^[A-Za-z0-9_-]+$/.test(key)) {
68
+ return true;
69
+ }
70
+ const home = process.env.HOME || '';
71
+ if (home === '' || !path.isAbsolute(key)) {
72
+ return false;
73
+ }
74
+ // Resolve before comparing so `..` segments cannot escape the HOME sandbox
75
+ // (e.g. /home/user/../etc/passwd passes a raw prefix check but not this).
76
+ const relative = path.relative(path.resolve(home), path.resolve(key));
77
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
78
+ }
79
+
80
+ function handleClientMessage(ws: WebSocket, superSessionId: string, msg: SosClientMessage): void {
81
+ switch (msg.type) {
82
+ case 'member-add': {
83
+ const member = sosCoordinator.addMember(superSessionId, {
84
+ capability: msg.capability,
85
+ provider: msg.provider,
86
+ sessionKey: msg.sessionKey,
87
+ terminalId: msg.terminalId ?? null,
88
+ });
89
+ if (!member) {
90
+ safeSend(ws, { message: 'Failed to add member', type: 'sos-error' });
91
+ }
92
+ break;
93
+ }
94
+ case 'member-remove': {
95
+ const ok = sosCoordinator.removeMember(superSessionId, msg.memberId);
96
+ if (!ok) {
97
+ safeSend(ws, { message: 'Member not found', type: 'sos-error' });
98
+ }
99
+ break;
100
+ }
101
+ case 'relay-approve': {
102
+ if (!sosCoordinator.approveRelay(superSessionId, msg.relayId)) {
103
+ safeSend(ws, { message: 'Pending relay not found', type: 'sos-error' });
104
+ }
105
+ break;
106
+ }
107
+ case 'relay-deny': {
108
+ if (!sosCoordinator.denyRelay(superSessionId, msg.relayId)) {
109
+ safeSend(ws, { message: 'Pending relay not found', type: 'sos-error' });
110
+ }
111
+ break;
112
+ }
113
+ case 'relay-forward': {
114
+ const error = sosCoordinator.relayForward(superSessionId, msg.toMemberId, msg.text);
115
+ if (error) {
116
+ safeSend(ws, { message: error, type: 'sos-error' });
117
+ }
118
+ break;
119
+ }
120
+ }
121
+ }
122
+
123
+ function parseClientMessage(raw: string): null | SosClientMessage {
124
+ let parsed: unknown;
125
+ try {
126
+ parsed = JSON.parse(raw);
127
+ } catch {
128
+ return null;
129
+ }
130
+ if (typeof parsed !== 'object' || parsed === null) {
131
+ return null;
132
+ }
133
+ const msg = parsed as Record<string, unknown>;
134
+
135
+ switch (msg.type) {
136
+ case 'member-add': {
137
+ if (
138
+ typeof msg.sessionKey !== 'string' ||
139
+ !isValidSessionKey(msg.sessionKey) ||
140
+ typeof msg.provider !== 'string' ||
141
+ !isValidProvider(msg.provider)
142
+ ) {
143
+ return null;
144
+ }
145
+ return {
146
+ capability: typeof msg.capability === 'string' ? msg.capability : undefined,
147
+ provider: msg.provider,
148
+ sessionKey: msg.sessionKey,
149
+ terminalId: typeof msg.terminalId === 'string' ? msg.terminalId : undefined,
150
+ type: 'member-add',
151
+ };
152
+ }
153
+ case 'member-remove': {
154
+ if (typeof msg.memberId !== 'string' || msg.memberId.length === 0) {
155
+ return null;
156
+ }
157
+ return { memberId: msg.memberId, type: 'member-remove' };
158
+ }
159
+ case 'relay-approve': {
160
+ if (typeof msg.relayId !== 'string' || msg.relayId.length === 0) {
161
+ return null;
162
+ }
163
+ return { relayId: msg.relayId, type: 'relay-approve' };
164
+ }
165
+ case 'relay-deny': {
166
+ if (typeof msg.relayId !== 'string' || msg.relayId.length === 0) {
167
+ return null;
168
+ }
169
+ return { relayId: msg.relayId, type: 'relay-deny' };
170
+ }
171
+ case 'relay-forward': {
172
+ if (
173
+ typeof msg.toMemberId !== 'string' ||
174
+ typeof msg.text !== 'string' ||
175
+ msg.text.length === 0 ||
176
+ msg.text.length > MAX_RELAY_TEXT
177
+ ) {
178
+ return null;
179
+ }
180
+ return { text: msg.text, toMemberId: msg.toMemberId, type: 'relay-forward' };
181
+ }
182
+ default:
183
+ return null;
184
+ }
185
+ }
186
+
187
+ function safeSend(ws: WebSocket, msg: SosServerMessage): boolean {
188
+ try {
189
+ if (ws.readyState !== 1 /* OPEN */) {
190
+ return false;
191
+ }
192
+ if (ws.bufferedAmount > MAX_WS_BUFFERED_BYTES) {
193
+ return false;
194
+ }
195
+ ws.send(JSON.stringify(msg));
196
+ return true;
197
+ } catch {
198
+ return false;
199
+ }
200
+ }
@@ -12,8 +12,8 @@ export type * from './gemini';
12
12
  export * from './generated';
13
13
  export type * from './neurolink';
14
14
  export type * from './server';
15
-
16
15
  export type * from './sessions';
16
+
17
17
  // Explicit re-exports to resolve conflicts between generated types and the
18
18
  // hand-written sessions.ts versions. The generated Sessions module exports
19
19
  // wrapper-class variants (CMessagePartTextPart, etc.) with `type: string`
@@ -27,5 +27,6 @@ export type {
27
27
  ToolResultPart,
28
28
  ToolUsePart,
29
29
  } from './sessions';
30
+ export type * from './sos';
30
31
  export type * from './terminal-client';
31
32
  export type * from './ws';
@@ -0,0 +1,134 @@
1
+ // Session-Over-Sessions (SoS) types — the coordinator that merges N running
2
+ // agent sessions into one source-tagged super-session and relays messages
3
+ // between them. See docs/SESSION-OVER-SESSIONS.md.
4
+ //
5
+ // A member's `sessionKey` is exactly what the server's session-watcher adapter
6
+ // keys on: a JSONL/JSON file path for file-backed providers, or a bare session
7
+ // id for OpenCode. That lets the coordinator reuse the same watcher routing the
8
+ // WS session handler uses, covering all providers with no new watching code.
9
+
10
+ import type { SessionSource } from './generated';
11
+ import type { ConversationMessage } from './sessions';
12
+
13
+ /** An escalated relay awaiting human approve/deny (Phase 2 HITL). */
14
+ export interface PendingRelay {
15
+ createdAt: string;
16
+ expiresAt: string;
17
+ fromMemberId: string;
18
+ id: string;
19
+ text: string;
20
+ timer: null | ReturnType<typeof setTimeout>;
21
+ toMemberId: string;
22
+ }
23
+
24
+ /** A control message sent from a SoS client to the coordinator over /ws/super-session/:id. */
25
+ export type SosClientMessage =
26
+ | {
27
+ capability?: string;
28
+ provider: SessionSource;
29
+ sessionKey: string;
30
+ terminalId?: string;
31
+ type: 'member-add';
32
+ }
33
+ | { memberId: string; type: 'member-remove' }
34
+ | { relayId: string; type: 'relay-approve' }
35
+ | { relayId: string; type: 'relay-deny' }
36
+ | { text: string; toMemberId: string; type: 'relay-forward' };
37
+
38
+ /**
39
+ * Injects relay text into a Shooter-owned terminal's stdin. Supplied by
40
+ * server.ts (which owns PtyManager) so the coordinator stays free of PTY deps.
41
+ * Performs the ownership check (terminal exists + running) and returns the
42
+ * outcome.
43
+ */
44
+ export type SosInjector = (terminalId: string, text: string) => { error?: string; ok: boolean };
45
+
46
+ /** A WS listener registered against a super-session. */
47
+ export type SosListener = (msg: SosServerMessage) => void;
48
+
49
+ export interface SosMember {
50
+ /** Free-text capability tag, e.g. 'frontend' | 'backend' | '' (unused in MVP routing). */
51
+ capability: string;
52
+ /** Random hex id, primary key in sos_sessions. */
53
+ id: string;
54
+ provider: SessionSource;
55
+ registeredAt: string;
56
+ /** Watcher key: file path for file-backed providers, session id for OpenCode. */
57
+ sessionKey: string;
58
+ status: SosMemberStatus;
59
+ /** PtyManager terminal id when launched via Shooter; null for externally-observed sessions. */
60
+ terminalId: null | string;
61
+ }
62
+
63
+ // ── WebSocket protocol (/ws/super-session/:id) ──────────────────────────
64
+
65
+ /** Lifecycle status of a SoS member's underlying agent session. */
66
+ export type SosMemberStatus = 'Compacting' | 'Finished' | 'Idle' | 'Waiting' | 'Working';
67
+
68
+ /**
69
+ * A static routing rule (Phase 2). The coordinator evaluates these in ascending
70
+ * `priority` against each new member message; the first match decides the
71
+ * action. `fromMemberId` may be 'ANY'; an empty `matchPattern` matches all text.
72
+ */
73
+ export interface SosRoutingRule {
74
+ action: 'block' | 'escalate' | 'relay';
75
+ fromMemberId: string;
76
+ id: string;
77
+ matchPattern: string;
78
+ priority: number;
79
+ toMemberId: string;
80
+ }
81
+
82
+ /** A message broadcast from the coordinator to subscribed SoS clients. */
83
+ export type SosServerMessage =
84
+ | {
85
+ decision: 'approved' | 'denied' | 'expired';
86
+ relayId: string;
87
+ type: 'sos-relay-resolved';
88
+ }
89
+ | { entries: SosTranscriptEntry[]; type: 'sos-history' }
90
+ | { entry: SosTranscriptEntry; type: 'sos-message' }
91
+ | {
92
+ expiresAt: string;
93
+ fromMemberId: string;
94
+ preview: string;
95
+ relayId: string;
96
+ toMemberId: string;
97
+ type: 'sos-relay-pending';
98
+ }
99
+ | { member: SosMember; type: 'sos-member-added' }
100
+ | { memberId: string; status: SosMemberStatus; type: 'sos-member-status' }
101
+ | { memberId: string; type: 'sos-member-removed' }
102
+ | { message: string; type: 'sos-error' };
103
+
104
+ /** One message in the merged transcript, tagged with its origin member. */
105
+ export interface SosTranscriptEntry {
106
+ memberId: string;
107
+ message: ConversationMessage;
108
+ provider: SessionSource;
109
+ /** True when the coordinator injected this message (loop-guard marker). */
110
+ relayed: boolean;
111
+ }
112
+
113
+ /** A super-session: N merged agent sessions coordinated as one. */
114
+ export interface SuperSession {
115
+ createdAt: string;
116
+ id: string;
117
+ label: string;
118
+ members: SosMember[];
119
+ routingRules: SosRoutingRule[];
120
+ status: 'active' | 'archived' | 'paused';
121
+ /** Source-tagged merged transcript; in-memory ring buffer (capped). */
122
+ transcript: SosTranscriptEntry[];
123
+ }
124
+
125
+ /** Coordinator-internal runtime state for one live super-session. */
126
+ export interface SuperSessionRuntime {
127
+ /** `${fromMemberId}:${toMemberId}` -> last auto-relay epoch ms (cooldown guard). */
128
+ cooldowns: Map<string, number>;
129
+ listeners: Set<SosListener>;
130
+ /** Escalated relays awaiting human decision, keyed by relayId. */
131
+ pending: Map<string, PendingRelay>;
132
+ session: SuperSession;
133
+ unsubscribes: Map<string, () => void>;
134
+ }
@@ -10,6 +10,7 @@
10
10
  import DashboardSvg from '$lib/assets/icons/dashboard.svg?raw';
11
11
  import SettingsSvg from '$lib/assets/icons/settings.svg?raw';
12
12
  import TerminalSvg from '$lib/assets/icons/terminal.svg?raw';
13
+ import ToolSvg from '$lib/assets/icons/tool.svg?raw';
13
14
  import { Button, Icon, Pill } from '@juspay/svelte-ui-components';
14
15
  import { onMount, type Snippet } from 'svelte';
15
16
 
@@ -133,6 +134,10 @@
133
134
  <Icon svg={TerminalSvg} classes="icon-26" />
134
135
  <span>Terminals</span>
135
136
  </a>
137
+ <a href="/sos" class="tab-item" class:active={$page.url.pathname.startsWith('/sos')}>
138
+ <Icon svg={ToolSvg} classes="icon-26" />
139
+ <span>SoS</span>
140
+ </a>
136
141
  </div>
137
142
  </nav>
138
143
  </div>
@@ -191,6 +196,7 @@
191
196
  }
192
197
  .tab-item {
193
198
  display: flex;
199
+ flex: 1;
194
200
  flex-direction: column;
195
201
  align-items: center;
196
202
  justify-content: center;
@@ -199,7 +205,7 @@
199
205
  font-size: 11px;
200
206
  font-weight: 500;
201
207
  text-decoration: none;
202
- padding: 6px 36px;
208
+ padding: 6px 8px;
203
209
  border-radius: var(--radius-md);
204
210
  transition: color var(--transition-fast);
205
211
  user-select: none;
@@ -226,7 +232,8 @@
226
232
  height: 60px;
227
233
  }
228
234
  .tab-item {
229
- padding: 6px 28px;
235
+ padding: 6px 8px;
236
+ min-width: 0;
230
237
  font-size: 10px;
231
238
  gap: 3px;
232
239
  min-height: 44px;
@@ -0,0 +1,36 @@
1
+ import { validateAuth } from '$lib/modules/server/auth';
2
+ import { sosCoordinator } from '$lib/modules/server/sos/coordinator';
3
+ import { json } from '@sveltejs/kit';
4
+
5
+ import type { RequestHandler } from './$types';
6
+
7
+ /** GET /api/sos — list all super-sessions. */
8
+ export const GET: RequestHandler = ({ request }) => {
9
+ const authError = validateAuth(request);
10
+ if (authError) {
11
+ return authError;
12
+ }
13
+ return json({ superSessions: sosCoordinator.listSuperSessions() });
14
+ };
15
+
16
+ /** POST /api/sos — create a new super-session. */
17
+ export const POST: RequestHandler = async ({ request }) => {
18
+ const authError = validateAuth(request);
19
+ if (authError) {
20
+ return authError;
21
+ }
22
+ let body: unknown;
23
+ try {
24
+ body = await request.json();
25
+ } catch {
26
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
27
+ }
28
+ if (typeof body !== 'object' || body === null) {
29
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
30
+ }
31
+ const payload = body as { label?: unknown };
32
+ const label =
33
+ typeof payload.label === 'string' && payload.label.trim() ? payload.label.trim() : 'Untitled';
34
+ const session = sosCoordinator.createSuperSession(label);
35
+ return json(session, { status: 201 });
36
+ };
@@ -0,0 +1,55 @@
1
+ import { validateAuth } from '$lib/modules/server/auth';
2
+ import { sosCoordinator } from '$lib/modules/server/sos/coordinator';
3
+ import { json } from '@sveltejs/kit';
4
+
5
+ import type { RequestHandler } from './$types';
6
+
7
+ /** GET /api/sos/[id] — fetch one super-session (incl. members + transcript). */
8
+ export const GET: RequestHandler = ({ params, request }) => {
9
+ const authError = validateAuth(request);
10
+ if (authError) {
11
+ return authError;
12
+ }
13
+ const session = sosCoordinator.getSuperSession(params.id ?? '');
14
+ if (!session) {
15
+ return json({ error: 'Super-session not found' }, { status: 404 });
16
+ }
17
+ return json(session);
18
+ };
19
+
20
+ /** PATCH /api/sos/[id] — update lifecycle status (active | paused | archived). */
21
+ export const PATCH: RequestHandler = async ({ params, request }) => {
22
+ const authError = validateAuth(request);
23
+ if (authError) {
24
+ return authError;
25
+ }
26
+ let body: unknown;
27
+ try {
28
+ body = await request.json();
29
+ } catch {
30
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
31
+ }
32
+ if (typeof body !== 'object' || body === null) {
33
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
34
+ }
35
+ const payload = body as { status?: unknown };
36
+ if (payload.status !== 'active' && payload.status !== 'paused' && payload.status !== 'archived') {
37
+ return json({ error: 'status must be active | paused | archived' }, { status: 400 });
38
+ }
39
+ if (!sosCoordinator.setStatus(params.id ?? '', payload.status)) {
40
+ return json({ error: 'Super-session not found' }, { status: 404 });
41
+ }
42
+ return json({ id: params.id, status: payload.status });
43
+ };
44
+
45
+ /** DELETE /api/sos/[id] — tear down a super-session (unsubscribes all members). */
46
+ export const DELETE: RequestHandler = ({ params, request }) => {
47
+ const authError = validateAuth(request);
48
+ if (authError) {
49
+ return authError;
50
+ }
51
+ if (!sosCoordinator.deleteSuperSession(params.id ?? '')) {
52
+ return json({ error: 'Super-session not found' }, { status: 404 });
53
+ }
54
+ return json({ deleted: true });
55
+ };
@@ -0,0 +1,44 @@
1
+ import { validateAuth } from '$lib/modules/server/auth';
2
+ import { sosCoordinator } from '$lib/modules/server/sos/coordinator';
3
+ import { json } from '@sveltejs/kit';
4
+
5
+ import type { RequestHandler } from './$types';
6
+
7
+ const MAX_RELAY_TEXT = 10240; // 10 KB, same cap as /ws/session send-input
8
+
9
+ /**
10
+ * POST /api/sos/[id]/inject — human-initiated relay: inject text into a member's
11
+ * Shooter-owned terminal and record it in the merged transcript.
12
+ */
13
+ export const POST: RequestHandler = async ({ params, request }) => {
14
+ const authError = validateAuth(request);
15
+ if (authError) {
16
+ return authError;
17
+ }
18
+ let body: unknown;
19
+ try {
20
+ body = await request.json();
21
+ } catch {
22
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
23
+ }
24
+ if (typeof body !== 'object' || body === null) {
25
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
26
+ }
27
+ const payload = body as { text?: unknown; toMemberId?: unknown };
28
+ if (typeof payload.toMemberId !== 'string' || payload.toMemberId.length === 0) {
29
+ return json({ error: 'toMemberId is required (string)' }, { status: 400 });
30
+ }
31
+ if (typeof payload.text !== 'string' || payload.text.length === 0) {
32
+ return json({ error: 'text is required (string)' }, { status: 400 });
33
+ }
34
+ if (Buffer.byteLength(payload.text, 'utf8') > MAX_RELAY_TEXT) {
35
+ return json({ error: `text exceeds ${MAX_RELAY_TEXT} bytes` }, { status: 413 });
36
+ }
37
+
38
+ const error = sosCoordinator.relayForward(params.id ?? '', payload.toMemberId, payload.text);
39
+ if (error) {
40
+ const status = error.includes('not found') ? 404 : 400;
41
+ return json({ error }, { status });
42
+ }
43
+ return json({ ok: true });
44
+ };
@@ -0,0 +1,47 @@
1
+ import { validateAuth } from '$lib/modules/server/auth';
2
+ import { sosCoordinator } from '$lib/modules/server/sos/coordinator';
3
+ import { isValidProvider, isValidSessionKey } from '$lib/modules/server/ws/super-session-handler';
4
+ import { json } from '@sveltejs/kit';
5
+
6
+ import type { RequestHandler } from './$types';
7
+
8
+ /** POST /api/sos/[id]/members — add a member session to a super-session. */
9
+ export const POST: RequestHandler = async ({ params, request }) => {
10
+ const authError = validateAuth(request);
11
+ if (authError) {
12
+ return authError;
13
+ }
14
+ let body: unknown;
15
+ try {
16
+ body = await request.json();
17
+ } catch {
18
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
19
+ }
20
+ if (typeof body !== 'object' || body === null) {
21
+ return json({ error: 'Invalid JSON in request body' }, { status: 400 });
22
+ }
23
+ const payload = body as {
24
+ capability?: unknown;
25
+ provider?: unknown;
26
+ sessionKey?: unknown;
27
+ terminalId?: unknown;
28
+ };
29
+
30
+ if (typeof payload.sessionKey !== 'string' || !isValidSessionKey(payload.sessionKey)) {
31
+ return json({ error: 'sessionKey must be a session id or a path under home' }, { status: 400 });
32
+ }
33
+ if (typeof payload.provider !== 'string' || !isValidProvider(payload.provider)) {
34
+ return json({ error: 'provider must be a known session source' }, { status: 400 });
35
+ }
36
+
37
+ const member = sosCoordinator.addMember(params.id ?? '', {
38
+ capability: typeof payload.capability === 'string' ? payload.capability : undefined,
39
+ provider: payload.provider,
40
+ sessionKey: payload.sessionKey,
41
+ terminalId: typeof payload.terminalId === 'string' ? payload.terminalId : null,
42
+ });
43
+ if (!member) {
44
+ return json({ error: 'Super-session not found' }, { status: 404 });
45
+ }
46
+ return json(member, { status: 201 });
47
+ };