svamp-cli 0.1.51 → 0.1.52

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 (314) hide show
  1. package/dist/cli.mjs +18 -18
  2. package/dist/{commands-mw8HFkt6.mjs → commands-1tmye7o_.mjs} +3 -2
  3. package/dist/{commands-D1brd9fB.mjs → commands-CI_BVphs.mjs} +7 -3
  4. package/dist/{commands-DHnFOhQC.mjs → commands-DcFOU9nW.mjs} +7 -3
  5. package/dist/commands-DwY2B7KW.mjs +562 -0
  6. package/dist/index.mjs +1 -1
  7. package/dist/{package-BLDik3NY.mjs → package-D7EUXtnk.mjs} +1 -1
  8. package/dist/{run-6dwQnoBL.mjs → run-BYJX5syg.mjs} +1 -1
  9. package/dist/{run-C0ecvcRP.mjs → run-BnnUavlu.mjs} +131 -44
  10. package/dist/{run-3Et1ISd5.mjs → run-Bw6aGHLA.mjs} +1 -1
  11. package/dist/{run-BE_AIJ7z.mjs → run-DOwarObi.mjs} +1 -1
  12. package/dist/{run-Bc83CRUn.mjs → run-DxISzP_V.mjs} +38 -7
  13. package/dist/{run-BdEHYoYE.mjs → run-eYBOEaWw.mjs} +20 -7
  14. package/dist/tunnel-C2_V6y3d.mjs +299 -0
  15. package/package.json +1 -1
  16. package/dist/commands-4_MiOQVp.mjs +0 -1217
  17. package/dist/commands-8UAWGJrC.mjs +0 -1208
  18. package/dist/commands-8Wmq0uak.mjs +0 -1407
  19. package/dist/commands-8Xn02pQg.mjs +0 -1217
  20. package/dist/commands-9DPsh6ku.mjs +0 -1217
  21. package/dist/commands-9rMB13FP.mjs +0 -1214
  22. package/dist/commands-B-XaqFDB.mjs +0 -1407
  23. package/dist/commands-B53zuBHB.mjs +0 -1217
  24. package/dist/commands-B7yLt11i.mjs +0 -1217
  25. package/dist/commands-BDVAO_N2.mjs +0 -1217
  26. package/dist/commands-BD_NjWJL.mjs +0 -1217
  27. package/dist/commands-BEhSQqTp.mjs +0 -507
  28. package/dist/commands-BIFQZZGw.mjs +0 -1375
  29. package/dist/commands-BImRR1Wr.mjs +0 -1217
  30. package/dist/commands-BLmRIMdf.mjs +0 -1217
  31. package/dist/commands-BOYo9cdy.mjs +0 -1741
  32. package/dist/commands-BQ_347V_.mjs +0 -1374
  33. package/dist/commands-BTEmyf2m.mjs +0 -1407
  34. package/dist/commands-BVjcCbWS.mjs +0 -1375
  35. package/dist/commands-BVsLRttq.mjs +0 -1217
  36. package/dist/commands-BVuE0VQU.mjs +0 -507
  37. package/dist/commands-BY09VTpk.mjs +0 -1375
  38. package/dist/commands-Bcdp0X-o.mjs +0 -1217
  39. package/dist/commands-BdnG1cqQ.mjs +0 -1217
  40. package/dist/commands-BdvvRQIo.mjs +0 -1415
  41. package/dist/commands-Bgg_dvDw.mjs +0 -1683
  42. package/dist/commands-Bi0zYJvj.mjs +0 -1407
  43. package/dist/commands-BmirUCVt.mjs +0 -1208
  44. package/dist/commands-BpSUbvmr.mjs +0 -1217
  45. package/dist/commands-BuJ6xTfc.mjs +0 -1217
  46. package/dist/commands-BzbYPx0f.mjs +0 -1208
  47. package/dist/commands-C-RtFjJl.mjs +0 -1217
  48. package/dist/commands-C20_f6oo.mjs +0 -1217
  49. package/dist/commands-C6KDr9Yp.mjs +0 -1407
  50. package/dist/commands-C9TOoTCv.mjs +0 -1395
  51. package/dist/commands-C9TdN_El.mjs +0 -1683
  52. package/dist/commands-CFv6lO0D.mjs +0 -1217
  53. package/dist/commands-CJ2n5jS2.mjs +0 -1375
  54. package/dist/commands-CKEKQ_5B.mjs +0 -1217
  55. package/dist/commands-CQz67Rm1.mjs +0 -1395
  56. package/dist/commands-CRZbJjqN.mjs +0 -1375
  57. package/dist/commands-CToIvBFX.mjs +0 -1375
  58. package/dist/commands-CWsfciHn.mjs +0 -1217
  59. package/dist/commands-CYMSyqYC.mjs +0 -1395
  60. package/dist/commands-CZ7KPLLJ.mjs +0 -1217
  61. package/dist/commands-Cc73uUnP.mjs +0 -1375
  62. package/dist/commands-CdMsAD1-.mjs +0 -1217
  63. package/dist/commands-CdyCWC3y.mjs +0 -1395
  64. package/dist/commands-ClVCprrK.mjs +0 -1217
  65. package/dist/commands-Cnmf8znA.mjs +0 -1196
  66. package/dist/commands-CorUNLRF.mjs +0 -1375
  67. package/dist/commands-Cq0oj5_v.mjs +0 -1217
  68. package/dist/commands-CrdvbXPI.mjs +0 -1395
  69. package/dist/commands-Cw2Od6mc.mjs +0 -1683
  70. package/dist/commands-CwC2aVzu.mjs +0 -1217
  71. package/dist/commands-CxSCUJCB.mjs +0 -1217
  72. package/dist/commands-D-PTwdZz.mjs +0 -1217
  73. package/dist/commands-D-nIO_Sf.mjs +0 -1741
  74. package/dist/commands-D7-NHH5q.mjs +0 -1407
  75. package/dist/commands-D7kH-7Vn.mjs +0 -1217
  76. package/dist/commands-DBv6A3aJ.mjs +0 -507
  77. package/dist/commands-DD3HXakm.mjs +0 -1217
  78. package/dist/commands-DLoe6FyK.mjs +0 -1375
  79. package/dist/commands-DPbH8KF0.mjs +0 -1217
  80. package/dist/commands-DUAQ9MZM.mjs +0 -1217
  81. package/dist/commands-DVw-P6-0.mjs +0 -1407
  82. package/dist/commands-DVygnMsh.mjs +0 -1217
  83. package/dist/commands-DWira-Cz.mjs +0 -1741
  84. package/dist/commands-DYTdUlul.mjs +0 -1217
  85. package/dist/commands-DZfaDmsk.mjs +0 -1374
  86. package/dist/commands-Dd8cn8mW.mjs +0 -1217
  87. package/dist/commands-DsIoygTL.mjs +0 -1395
  88. package/dist/commands-Du-fdLLu.mjs +0 -969
  89. package/dist/commands-DuJGOq1y.mjs +0 -1217
  90. package/dist/commands-DwBr3sBn.mjs +0 -1217
  91. package/dist/commands-DwveR96q.mjs +0 -1683
  92. package/dist/commands-DypTF36z.mjs +0 -506
  93. package/dist/commands-EUMJqBCs.mjs +0 -1407
  94. package/dist/commands-HLu7P96l.mjs +0 -1214
  95. package/dist/commands-HrBaGV-C.mjs +0 -1683
  96. package/dist/commands-Jk5no-DX.mjs +0 -1407
  97. package/dist/commands-KH5dj9dv.mjs +0 -1214
  98. package/dist/commands-LaNHVHjc.mjs +0 -1217
  99. package/dist/commands-O1Q9g00y.mjs +0 -1395
  100. package/dist/commands-OwMfbBrU.mjs +0 -1395
  101. package/dist/commands-SQ0Wp_kD.mjs +0 -1217
  102. package/dist/commands-S_MFQ9n1.mjs +0 -354
  103. package/dist/commands-T3q8VKCY.mjs +0 -1407
  104. package/dist/commands-Ugz9TtRu.mjs +0 -1420
  105. package/dist/commands-Wng0OuNY.mjs +0 -1683
  106. package/dist/commands-YBW5jFpy.mjs +0 -1217
  107. package/dist/commands-Z-CbuF8E.mjs +0 -1217
  108. package/dist/commands-fSZOP80Z.mjs +0 -1217
  109. package/dist/commands-fqBuJe1b.mjs +0 -1217
  110. package/dist/commands-g-1n3_Rp.mjs +0 -1395
  111. package/dist/commands-mC0oe0lj.mjs +0 -1217
  112. package/dist/commands-od2hOku5.mjs +0 -1217
  113. package/dist/commands-otgzprjb.mjs +0 -1375
  114. package/dist/commands-rhHI6Wb2.mjs +0 -1420
  115. package/dist/commands-zGHnUXh5.mjs +0 -1217
  116. package/dist/package-BMCjXPI9.mjs +0 -58
  117. package/dist/package-BPMWPlS0.mjs +0 -57
  118. package/dist/package-BYUO-39f.mjs +0 -60
  119. package/dist/package-BaGfG8vL.mjs +0 -58
  120. package/dist/package-BkBE6ZdN.mjs +0 -57
  121. package/dist/package-BufekbY1.mjs +0 -57
  122. package/dist/package-C1hpYMj4.mjs +0 -57
  123. package/dist/package-CmIBOZtY.mjs +0 -57
  124. package/dist/package-CmVt1kdw.mjs +0 -58
  125. package/dist/package-Cn6Ya4A0.mjs +0 -57
  126. package/dist/package-Csd530Ym.mjs +0 -57
  127. package/dist/package-D6mNQtUs.mjs +0 -57
  128. package/dist/package-DG0AkZdm.mjs +0 -58
  129. package/dist/package-DRO1LpXW.mjs +0 -58
  130. package/dist/package-Dav8qh6X.mjs +0 -57
  131. package/dist/package-DiA55dzE.mjs +0 -57
  132. package/dist/package-UwLIU765.mjs +0 -58
  133. package/dist/package-k3XsdP9k.mjs +0 -58
  134. package/dist/package-rasGC9_z.mjs +0 -58
  135. package/dist/run-4B1XZQB8.mjs +0 -5426
  136. package/dist/run-4eArMb_9.mjs +0 -1050
  137. package/dist/run-4li60ojK.mjs +0 -1051
  138. package/dist/run-67wfoMuo.mjs +0 -5383
  139. package/dist/run-6N2IdEX7.mjs +0 -5410
  140. package/dist/run-7iQKryzo.mjs +0 -5383
  141. package/dist/run-7s8lOXqB.mjs +0 -1050
  142. package/dist/run-8kKykzTs.mjs +0 -5367
  143. package/dist/run-8mLZV2lg.mjs +0 -1050
  144. package/dist/run-9x7I9Ck-.mjs +0 -5264
  145. package/dist/run-B-PWtXF-.mjs +0 -5894
  146. package/dist/run-B1ivovUl.mjs +0 -5964
  147. package/dist/run-B1l9Ed8k.mjs +0 -5403
  148. package/dist/run-B2zRMxE0.mjs +0 -5508
  149. package/dist/run-B31biy0V.mjs +0 -1050
  150. package/dist/run-B5o5fMMd.mjs +0 -5369
  151. package/dist/run-B7V-xXM7.mjs +0 -5775
  152. package/dist/run-B9ND6srh.mjs +0 -6154
  153. package/dist/run-BG3279Kg.mjs +0 -1051
  154. package/dist/run-BHZNzX1F.mjs +0 -5235
  155. package/dist/run-BKdOv7gX.mjs +0 -1050
  156. package/dist/run-BLySdZ1K.mjs +0 -5251
  157. package/dist/run-BOVkQfM-.mjs +0 -1050
  158. package/dist/run-BQ0lIare.mjs +0 -1050
  159. package/dist/run-BREPr7Yc.mjs +0 -5508
  160. package/dist/run-BTwshVk1.mjs +0 -5728
  161. package/dist/run-BUL3eAqT.mjs +0 -1050
  162. package/dist/run-BVcPemGr.mjs +0 -5947
  163. package/dist/run-BWqEmIiz.mjs +0 -5964
  164. package/dist/run-BWsDPiNe.mjs +0 -1050
  165. package/dist/run-BX4iy6k8.mjs +0 -1050
  166. package/dist/run-BXYfq8mK.mjs +0 -5836
  167. package/dist/run-BY12Ataq.mjs +0 -5732
  168. package/dist/run-BYDOX4yk.mjs +0 -5402
  169. package/dist/run-Bd-t6s63.mjs +0 -5373
  170. package/dist/run-BenYqfwQ.mjs +0 -5273
  171. package/dist/run-BfF4bgA3.mjs +0 -5403
  172. package/dist/run-Bhh05yic.mjs +0 -5369
  173. package/dist/run-BicITYWX.mjs +0 -6138
  174. package/dist/run-BieEN0Pg.mjs +0 -5761
  175. package/dist/run-BjEQi6PN.mjs +0 -1050
  176. package/dist/run-BjZ6SyFy.mjs +0 -1051
  177. package/dist/run-Bl8OkKyC.mjs +0 -5969
  178. package/dist/run-BlEFlhfn.mjs +0 -5510
  179. package/dist/run-BmL1m0Bk.mjs +0 -1050
  180. package/dist/run-Bmx5wEBF.mjs +0 -1051
  181. package/dist/run-BnX5Rw8x.mjs +0 -5403
  182. package/dist/run-BpjmHeht.mjs +0 -1050
  183. package/dist/run-BxTdRjCG.mjs +0 -1051
  184. package/dist/run-ByOVDgvx.mjs +0 -6115
  185. package/dist/run-BzRP6Q5t.mjs +0 -1051
  186. package/dist/run-C0dyMP62.mjs +0 -1051
  187. package/dist/run-C1lS3SwN.mjs +0 -5733
  188. package/dist/run-C3PAp02X.mjs +0 -5252
  189. package/dist/run-C3eaYQub.mjs +0 -1050
  190. package/dist/run-C4pdX4sY.mjs +0 -1051
  191. package/dist/run-C676pHe-.mjs +0 -5423
  192. package/dist/run-C8GkzcfP.mjs +0 -1050
  193. package/dist/run-C9Hrqjy_.mjs +0 -1050
  194. package/dist/run-CC2C8P-U.mjs +0 -6031
  195. package/dist/run-CCcW4asS.mjs +0 -1050
  196. package/dist/run-CDBKhQ1Z.mjs +0 -1051
  197. package/dist/run-CE4H8ZiN.mjs +0 -6273
  198. package/dist/run-CEB6sYzn.mjs +0 -5962
  199. package/dist/run-CF6aXLmA.mjs +0 -5445
  200. package/dist/run-CHyN5U0t.mjs +0 -1050
  201. package/dist/run-CIFezmkC.mjs +0 -5949
  202. package/dist/run-CLA9zw7J.mjs +0 -5907
  203. package/dist/run-COWb9ovq.mjs +0 -1050
  204. package/dist/run-CSUAy5T5.mjs +0 -1051
  205. package/dist/run-CSk7i0Hq.mjs +0 -1050
  206. package/dist/run-CUtqSGWJ.mjs +0 -1050
  207. package/dist/run-CXrEt0TM.mjs +0 -5008
  208. package/dist/run-CY8Y0JPW.mjs +0 -5287
  209. package/dist/run-CZCKBcQ-.mjs +0 -5244
  210. package/dist/run-CZj0sRCs.mjs +0 -1050
  211. package/dist/run-C_1x2cNU.mjs +0 -5381
  212. package/dist/run-C_8iOjO1.mjs +0 -5892
  213. package/dist/run-C_KIew8H.mjs +0 -1051
  214. package/dist/run-CajRcN3C.mjs +0 -1050
  215. package/dist/run-CbzXO7fw.mjs +0 -1050
  216. package/dist/run-CcSr4x2f.mjs +0 -1050
  217. package/dist/run-CcYaXgCy.mjs +0 -6091
  218. package/dist/run-CdihMx0V.mjs +0 -1051
  219. package/dist/run-Cf2Dl_ck.mjs +0 -1051
  220. package/dist/run-CjH1H4vq.mjs +0 -1050
  221. package/dist/run-CkbDK6jA.mjs +0 -1051
  222. package/dist/run-Ckh6JE9F.mjs +0 -1050
  223. package/dist/run-Ckyg9-fm.mjs +0 -6079
  224. package/dist/run-CqL3ZWdr.mjs +0 -5381
  225. package/dist/run-Csj7sJAh.mjs +0 -1050
  226. package/dist/run-Ct--DWF1.mjs +0 -1051
  227. package/dist/run-CtJRxaFC.mjs +0 -1051
  228. package/dist/run-CuIMdkKF.mjs +0 -6099
  229. package/dist/run-CuckJGM-.mjs +0 -1050
  230. package/dist/run-CxGAa9MH.mjs +0 -1050
  231. package/dist/run-CyU4-O-e.mjs +0 -5411
  232. package/dist/run-CymDyu2b.mjs +0 -5389
  233. package/dist/run-CzIY4_RE.mjs +0 -6093
  234. package/dist/run-D0Ha4aWt.mjs +0 -1050
  235. package/dist/run-D0ow-xms.mjs +0 -5905
  236. package/dist/run-D1PFrNZB.mjs +0 -6273
  237. package/dist/run-D2X3jEqg.mjs +0 -1051
  238. package/dist/run-D39C7Ta3.mjs +0 -1050
  239. package/dist/run-D3Lqxasl.mjs +0 -1051
  240. package/dist/run-D3bhRCCb.mjs +0 -1051
  241. package/dist/run-D5N42sVA.mjs +0 -1050
  242. package/dist/run-D691XPXy.mjs +0 -6031
  243. package/dist/run-D7dLDpq3.mjs +0 -5403
  244. package/dist/run-D8mQ_fL5.mjs +0 -1050
  245. package/dist/run-DA-YBjNw.mjs +0 -6018
  246. package/dist/run-DByI8mI0.mjs +0 -1051
  247. package/dist/run-DCINWip4.mjs +0 -1050
  248. package/dist/run-DCrZ3vke.mjs +0 -5406
  249. package/dist/run-DDF-tRbn.mjs +0 -5954
  250. package/dist/run-DGSgljJE.mjs +0 -5421
  251. package/dist/run-DGsXW19O.mjs +0 -5541
  252. package/dist/run-DHrF2xpW.mjs +0 -5776
  253. package/dist/run-DIB0W42M.mjs +0 -1050
  254. package/dist/run-DJ4k0WzZ.mjs +0 -1051
  255. package/dist/run-DMI83W7i.mjs +0 -5434
  256. package/dist/run-DNX3djCI.mjs +0 -1050
  257. package/dist/run-DOPaGRT2.mjs +0 -6027
  258. package/dist/run-DP7KSZqR.mjs +0 -1051
  259. package/dist/run-DQ0yljWr.mjs +0 -1050
  260. package/dist/run-DTkldU6a.mjs +0 -1050
  261. package/dist/run-DU10B3gK.mjs +0 -5728
  262. package/dist/run-DV86VJNG.mjs +0 -5386
  263. package/dist/run-DVZGKdKO.mjs +0 -1050
  264. package/dist/run-DWdtp6VD.mjs +0 -6136
  265. package/dist/run-DWzA1gZ-.mjs +0 -1050
  266. package/dist/run-DXJ2M19k.mjs +0 -1050
  267. package/dist/run-DZOeccNu.mjs +0 -5484
  268. package/dist/run-D_W5YF0D.mjs +0 -6046
  269. package/dist/run-DaReJPf8.mjs +0 -1051
  270. package/dist/run-DaYrEeQ9.mjs +0 -5400
  271. package/dist/run-DbC9-WM4.mjs +0 -1050
  272. package/dist/run-Dd9XkswU.mjs +0 -1051
  273. package/dist/run-De-wkVl3.mjs +0 -5487
  274. package/dist/run-DfU2luyX.mjs +0 -1050
  275. package/dist/run-Dfl3Ze2L.mjs +0 -5541
  276. package/dist/run-DfuHUDIJ.mjs +0 -1051
  277. package/dist/run-DfwfyFqj.mjs +0 -5975
  278. package/dist/run-DgUDGHZy.mjs +0 -1051
  279. package/dist/run-Dge2K7h1.mjs +0 -1050
  280. package/dist/run-Di3I0USw.mjs +0 -1050
  281. package/dist/run-Dm3U4FB5.mjs +0 -6018
  282. package/dist/run-Du0YOs48.mjs +0 -5446
  283. package/dist/run-DuaIQAE4.mjs +0 -5392
  284. package/dist/run-Dwm19YhI.mjs +0 -1050
  285. package/dist/run-DxM7xaBa.mjs +0 -1050
  286. package/dist/run-DysN-cGm.mjs +0 -1050
  287. package/dist/run-DzXohf8-.mjs +0 -1051
  288. package/dist/run-E_MwVOtN.mjs +0 -5272
  289. package/dist/run-FPoL2-FD.mjs +0 -5381
  290. package/dist/run-HU4XjZfs.mjs +0 -6023
  291. package/dist/run-HhiYlJuS.mjs +0 -5414
  292. package/dist/run-JXLlRLFb.mjs +0 -1050
  293. package/dist/run-K-_jahIg.mjs +0 -1051
  294. package/dist/run-K_S7pfZ-.mjs +0 -1050
  295. package/dist/run-LDiT4WF-.mjs +0 -1050
  296. package/dist/run-NToLJWx-.mjs +0 -5442
  297. package/dist/run-RBufRqbs.mjs +0 -1050
  298. package/dist/run-YFYpyThQ.mjs +0 -1051
  299. package/dist/run-YG1Pb9dY.mjs +0 -5385
  300. package/dist/run-ZDa17iLg.mjs +0 -6060
  301. package/dist/run-ZN0qMdS_.mjs +0 -1051
  302. package/dist/run-azpFWM6w.mjs +0 -1050
  303. package/dist/run-coIDvBK_.mjs +0 -6127
  304. package/dist/run-jLp4pbTE.mjs +0 -1050
  305. package/dist/run-m3oAuSg0.mjs +0 -1050
  306. package/dist/run-r9CAcL_U.mjs +0 -5403
  307. package/dist/run-v32uF2bP.mjs +0 -5378
  308. package/dist/run-vTsskoZc.mjs +0 -5340
  309. package/dist/run-vt26p5D7.mjs +0 -1050
  310. package/dist/run-vvQiCHpi.mjs +0 -5427
  311. package/dist/run-w-HVv5py.mjs +0 -5410
  312. package/dist/run-wpUutZ9C.mjs +0 -1051
  313. package/dist/run-yTjJ7noq.mjs +0 -1051
  314. package/dist/run-zo5GSoVC.mjs +0 -1050
@@ -1,1050 +0,0 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { randomUUID } from 'node:crypto';
2
- import os from 'node:os';
3
- import { join, resolve } from 'node:path';
4
- import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
5
- import { c as connectToHypha, a as registerSessionService } from './run-Dfl3Ze2L.mjs';
6
- import { createServer } from 'node:http';
7
- import { spawn } from 'node:child_process';
8
- import { createInterface } from 'node:readline';
9
- import 'os';
10
- import 'fs/promises';
11
- import 'fs';
12
- import 'path';
13
- import 'url';
14
- import 'child_process';
15
- import 'crypto';
16
- import '@agentclientprotocol/sdk';
17
- import '@modelcontextprotocol/sdk/client/index.js';
18
- import '@modelcontextprotocol/sdk/client/stdio.js';
19
- import '@modelcontextprotocol/sdk/types.js';
20
- import 'zod';
21
- import 'node:fs/promises';
22
- import 'node:util';
23
-
24
- async function startHookServer(onSessionHook, log) {
25
- return new Promise((resolve, reject) => {
26
- const server = createServer(async (req, res) => {
27
- if (req.method === "POST" && req.url === "/hook/session-start") {
28
- const timeout = setTimeout(() => {
29
- if (!res.headersSent) res.writeHead(408).end("timeout");
30
- }, 5e3);
31
- try {
32
- const chunks = [];
33
- for await (const chunk of req) chunks.push(chunk);
34
- clearTimeout(timeout);
35
- const body = Buffer.concat(chunks).toString("utf-8");
36
- log("[hook] Received:", body.slice(0, 200));
37
- let data = {};
38
- try {
39
- data = JSON.parse(body);
40
- } catch {
41
- }
42
- const sessionId = data.session_id || data.sessionId;
43
- if (sessionId) {
44
- log(`[hook] Session ID: ${sessionId}`);
45
- onSessionHook(sessionId);
46
- }
47
- res.writeHead(200).end("ok");
48
- } catch {
49
- clearTimeout(timeout);
50
- if (!res.headersSent) res.writeHead(500).end("error");
51
- }
52
- return;
53
- }
54
- res.writeHead(404).end("not found");
55
- });
56
- server.listen(0, "127.0.0.1", () => {
57
- const addr = server.address();
58
- if (!addr || typeof addr === "string") {
59
- reject(new Error("Failed to get server address"));
60
- return;
61
- }
62
- log(`[hook] Listening on port ${addr.port}`);
63
- resolve({ port: addr.port, stop: () => server.close() });
64
- });
65
- server.on("error", reject);
66
- });
67
- }
68
-
69
- const SVAMP_HOME$1 = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
70
- function generateHookSettings(port) {
71
- const hooksDir = join(SVAMP_HOME$1, "tmp", "hooks");
72
- mkdirSync(hooksDir, { recursive: true });
73
- const forwarderPath = join(hooksDir, `forwarder-${process.pid}.cjs`);
74
- const forwarderCode = `#!/usr/bin/env node
75
- const http = require('http');
76
- const port = parseInt(process.argv[2], 10);
77
- if (!port || isNaN(port)) process.exit(1);
78
- const chunks = [];
79
- process.stdin.on('data', c => chunks.push(c));
80
- process.stdin.on('end', () => {
81
- const body = Buffer.concat(chunks);
82
- const req = http.request({
83
- host: '127.0.0.1', port, method: 'POST',
84
- path: '/hook/session-start',
85
- headers: { 'Content-Type': 'application/json', 'Content-Length': body.length }
86
- }, res => res.resume());
87
- req.on('error', () => {});
88
- req.end(body);
89
- });
90
- process.stdin.resume();
91
- `;
92
- writeFileSync(forwarderPath, forwarderCode, { mode: 493 });
93
- const settingsPath = join(hooksDir, `session-hook-${process.pid}.json`);
94
- const hookCommand = `node "${forwarderPath}" ${port}`;
95
- const settings = {
96
- hooks: {
97
- SessionStart: [
98
- {
99
- matcher: "*",
100
- hooks: [{ type: "command", command: hookCommand }]
101
- }
102
- ]
103
- }
104
- };
105
- writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
106
- const cleanup = () => {
107
- try {
108
- if (existsSync(settingsPath)) unlinkSync(settingsPath);
109
- } catch {
110
- }
111
- try {
112
- if (existsSync(forwarderPath)) unlinkSync(forwarderPath);
113
- } catch {
114
- }
115
- };
116
- return { settingsPath, cleanup };
117
- }
118
-
119
- const INTERNAL_EVENT_TYPES = /* @__PURE__ */ new Set([
120
- "file-history-snapshot",
121
- "change",
122
- "queue-operation"
123
- ]);
124
- function getProjectDir(workingDirectory) {
125
- const projectId = resolve(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
126
- const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join(os.homedir(), ".claude");
127
- return join(claudeConfigDir, "projects", projectId);
128
- }
129
- function createSessionScanner(opts) {
130
- const { workingDirectory, onMessage, log } = opts;
131
- const projectDir = getProjectDir(workingDirectory);
132
- const processedKeys = /* @__PURE__ */ new Set();
133
- let currentSessionId = null;
134
- let watcher = null;
135
- let syncInterval = null;
136
- let stopped = false;
137
- function messageKey(msg) {
138
- if (msg.type === "summary") return `summary:${msg.leafUuid}:${msg.summary}`;
139
- return msg.uuid || "";
140
- }
141
- function readAndSync() {
142
- if (stopped || !currentSessionId) return;
143
- const filePath = join(projectDir, `${currentSessionId}.jsonl`);
144
- if (!existsSync(filePath)) return;
145
- let content;
146
- try {
147
- content = readFileSync(filePath, "utf-8");
148
- } catch {
149
- return;
150
- }
151
- const lines = content.split("\n");
152
- for (const line of lines) {
153
- const trimmed = line.trim();
154
- if (!trimmed) continue;
155
- let parsed;
156
- try {
157
- parsed = JSON.parse(trimmed);
158
- } catch {
159
- continue;
160
- }
161
- if (parsed.type && INTERNAL_EVENT_TYPES.has(parsed.type)) continue;
162
- if (!["user", "assistant", "summary", "system"].includes(parsed.type)) continue;
163
- const key = messageKey(parsed);
164
- if (!key || processedKeys.has(key)) continue;
165
- processedKeys.add(key);
166
- onMessage(parsed);
167
- }
168
- }
169
- function startWatching(sessionId) {
170
- stopWatching();
171
- currentSessionId = sessionId;
172
- const filePath = join(projectDir, `${sessionId}.jsonl`);
173
- log(`[scanner] Watching: ${filePath}`);
174
- readAndSync();
175
- try {
176
- watcher = watch(filePath, { persistent: false }, () => {
177
- readAndSync();
178
- });
179
- watcher.on("error", () => {
180
- });
181
- } catch {
182
- }
183
- syncInterval = setInterval(readAndSync, 2e3);
184
- }
185
- function stopWatching() {
186
- if (watcher) {
187
- try {
188
- watcher.close();
189
- } catch {
190
- }
191
- watcher = null;
192
- }
193
- if (syncInterval) {
194
- clearInterval(syncInterval);
195
- syncInterval = null;
196
- }
197
- }
198
- return {
199
- onNewSession(sessionId) {
200
- if (sessionId === currentSessionId) return;
201
- log(`[scanner] New session: ${sessionId}`);
202
- startWatching(sessionId);
203
- },
204
- sync: readAndSync,
205
- cleanup() {
206
- stopped = true;
207
- stopWatching();
208
- if (currentSessionId) readAndSync();
209
- }
210
- };
211
- }
212
-
213
- async function runLocalMode(opts) {
214
- const { cwd, onSessionFound, onMessage, onThinkingChange, log } = opts;
215
- const scanner = createSessionScanner({
216
- workingDirectory: cwd,
217
- onMessage,
218
- log
219
- });
220
- if (opts.claudeSessionId) {
221
- scanner.onNewSession(opts.claudeSessionId);
222
- }
223
- const args = [];
224
- if (opts.claudeSessionId) {
225
- args.push("--resume", opts.claudeSessionId);
226
- }
227
- if (opts.hookSettingsPath) {
228
- args.push("--settings", opts.hookSettingsPath);
229
- }
230
- if (opts.claudeArgs) {
231
- args.push(...opts.claudeArgs);
232
- }
233
- log(`[local] Spawning: claude ${args.join(" ")}`);
234
- const claudeBin = findClaudeBinary();
235
- if (!claudeBin) {
236
- process.stderr.write("Claude Code CLI not found. Install with: npm install -g @anthropic-ai/claude-code\n");
237
- return { type: "exit", code: 1 };
238
- }
239
- process.stdin.pause();
240
- return new Promise((resolve) => {
241
- const child = spawn(claudeBin, args, {
242
- stdio: ["inherit", "inherit", "inherit"],
243
- cwd,
244
- signal: opts.abort,
245
- env: process.env
246
- });
247
- child.on("error", (err) => {
248
- log(`[local] Spawn error: ${err.message}`);
249
- scanner.cleanup();
250
- process.stdin.resume();
251
- onThinkingChange(false);
252
- if (err.code === "ABORT_ERR" || opts.abort.aborted) {
253
- resolve({ type: "switch" });
254
- } else {
255
- resolve({ type: "exit", code: 1 });
256
- }
257
- });
258
- child.on("exit", (code, signal) => {
259
- log(`[local] Claude exited: code=${code}, signal=${signal}`);
260
- scanner.cleanup();
261
- process.stdin.resume();
262
- onThinkingChange(false);
263
- if (signal === "SIGTERM" && opts.abort.aborted) {
264
- resolve({ type: "switch" });
265
- } else {
266
- resolve({ type: "exit", code: code ?? 0 });
267
- }
268
- });
269
- if (opts.abort.aborted) {
270
- try {
271
- child.kill("SIGTERM");
272
- } catch {
273
- }
274
- }
275
- });
276
- }
277
- function findClaudeBinary() {
278
- try {
279
- const { execSync } = require("child_process");
280
- const path = execSync("which claude 2>/dev/null", { encoding: "utf-8" }).trim();
281
- if (path && existsSync(path)) return path;
282
- } catch {
283
- }
284
- return null;
285
- }
286
-
287
- async function runRemoteMode(opts) {
288
- const { cwd, log, onThinkingChange, onMessage } = opts;
289
- let claudeBin = null;
290
- try {
291
- const { execSync } = require("child_process");
292
- claudeBin = execSync("which claude 2>/dev/null", { encoding: "utf-8" }).trim();
293
- } catch {
294
- }
295
- if (!claudeBin || !existsSync(claudeBin)) {
296
- process.stderr.write("Claude Code CLI not found.\n");
297
- return "exit";
298
- }
299
- const print = (s) => process.stderr.write(s + "\n");
300
- print("\n\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m");
301
- print("\x1B[36m Remote mode\x1B[0m \u2014 processing message from web app");
302
- print("\x1B[90m Press Space Space to switch to local mode\x1B[0m");
303
- print("\x1B[90m Press Ctrl-C Ctrl-C to exit\x1B[0m");
304
- print("\x1B[90m" + "\u2550".repeat(50) + "\x1B[0m\n");
305
- let exitReason = null;
306
- let lastSpace = 0;
307
- let lastCtrlC = 0;
308
- const DOUBLE_TAP_MS = 2e3;
309
- let spaceHintShown = false;
310
- let ctrlcHintShown = false;
311
- const stdinWasRaw = process.stdin.isRaw;
312
- if (process.stdin.isTTY) {
313
- process.stdin.setRawMode(true);
314
- }
315
- process.stdin.resume();
316
- process.stdin.setEncoding("utf8");
317
- const keyHandler = (data) => {
318
- const now = Date.now();
319
- if (data === "") {
320
- if (now - lastCtrlC < DOUBLE_TAP_MS) {
321
- exitReason = "exit";
322
- abortController.abort();
323
- return;
324
- }
325
- lastCtrlC = now;
326
- if (!ctrlcHintShown) {
327
- ctrlcHintShown = true;
328
- process.stdout.write("\n\x1B[33m Press Ctrl-C again to exit\x1B[0m\n");
329
- setTimeout(() => {
330
- ctrlcHintShown = false;
331
- }, DOUBLE_TAP_MS);
332
- }
333
- return;
334
- }
335
- if (data === " ") {
336
- if (now - lastSpace < DOUBLE_TAP_MS) {
337
- exitReason = "switch";
338
- abortController.abort();
339
- return;
340
- }
341
- lastSpace = now;
342
- if (!spaceHintShown) {
343
- spaceHintShown = true;
344
- process.stdout.write("\n\x1B[33m Press Space again to switch to local mode\x1B[0m\n");
345
- setTimeout(() => {
346
- spaceHintShown = false;
347
- }, DOUBLE_TAP_MS);
348
- }
349
- return;
350
- }
351
- lastSpace = 0;
352
- lastCtrlC = 0;
353
- };
354
- process.stdin.on("data", keyHandler);
355
- const abortController = new AbortController();
356
- if (opts.abort.aborted) {
357
- abortController.abort();
358
- } else {
359
- opts.abort.addEventListener("abort", () => abortController.abort(), { once: true });
360
- }
361
- try {
362
- while (!exitReason && !abortController.signal.aborted) {
363
- const message = await Promise.race([
364
- opts.nextMessage(),
365
- new Promise((_, reject) => {
366
- if (abortController.signal.aborted) reject(new Error("aborted"));
367
- abortController.signal.addEventListener("abort", () => reject(new Error("aborted")), { once: true });
368
- })
369
- ]).catch(() => null);
370
- if (!message || exitReason || abortController.signal.aborted) break;
371
- const turnResult = await runClaudeTurn({
372
- claudeBin,
373
- cwd,
374
- message,
375
- sessionId: opts.claudeSessionId,
376
- permissionMode: opts.permissionMode,
377
- hookSettingsPath: opts.hookSettingsPath,
378
- claudeArgs: opts.claudeArgs,
379
- signal: abortController.signal,
380
- onSessionFound: opts.onSessionFound,
381
- onThinkingChange,
382
- onMessage,
383
- log
384
- });
385
- if (turnResult === "error") {
386
- continue;
387
- }
388
- if (!exitReason && !abortController.signal.aborted) {
389
- process.stderr.write("\n\x1B[90m Agent idle. Waiting for next message...\x1B[0m\n");
390
- }
391
- }
392
- } finally {
393
- process.stdin.removeListener("data", keyHandler);
394
- if (process.stdin.isTTY) {
395
- process.stdin.setRawMode(stdinWasRaw ?? false);
396
- }
397
- }
398
- return exitReason || "exit";
399
- }
400
- async function runClaudeTurn(opts) {
401
- const args = [
402
- "--output-format",
403
- "stream-json",
404
- "--verbose",
405
- "--print",
406
- opts.message
407
- ];
408
- if (opts.hookSettingsPath) {
409
- args.push("--settings", opts.hookSettingsPath);
410
- }
411
- if (opts.sessionId) {
412
- args.push("--resume", opts.sessionId);
413
- }
414
- const claudeMode = mapPermissionMode(opts.permissionMode) || "bypassPermissions";
415
- args.push("--permission-mode", claudeMode);
416
- if (opts.claudeArgs) {
417
- args.push(...opts.claudeArgs);
418
- }
419
- opts.log(`[remote] Spawning: claude ${args.join(" ")}`);
420
- process.stderr.write(`
421
- \x1B[34m \u25B6 User:\x1B[0m ${opts.message}
422
-
423
- `);
424
- const spawnEnv = { ...process.env, CLAUDE_CODE_ENTRYPOINT: "sdk-ts" };
425
- delete spawnEnv.CLAUDECODE;
426
- const child = spawn(opts.claudeBin, args, {
427
- stdio: ["pipe", "pipe", "pipe"],
428
- cwd: opts.cwd,
429
- env: spawnEnv
430
- });
431
- child.stdin.end();
432
- opts.onThinkingChange(true);
433
- let currentText = "";
434
- return new Promise((resolve) => {
435
- const abortHandler = () => {
436
- try {
437
- child.kill("SIGTERM");
438
- } catch {
439
- }
440
- };
441
- if (opts.signal.aborted) {
442
- abortHandler();
443
- } else {
444
- opts.signal.addEventListener("abort", abortHandler, { once: true });
445
- }
446
- const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
447
- rl.on("line", (line) => {
448
- const trimmed = line.trim();
449
- if (!trimmed) return;
450
- let msg;
451
- try {
452
- msg = JSON.parse(trimmed);
453
- } catch {
454
- return;
455
- }
456
- handleSDKMessage(msg, opts, (text) => {
457
- process.stdout.write(text);
458
- currentText += text;
459
- });
460
- });
461
- if (child.stderr) {
462
- child.stderr.on("data", (data) => {
463
- opts.log(`[remote:stderr] ${data.toString().trim()}`);
464
- });
465
- }
466
- child.on("error", (err) => {
467
- opts.log(`[remote] Error: ${err.message}`);
468
- opts.onThinkingChange(false);
469
- if (currentText && !currentText.endsWith("\n")) process.stdout.write("\n");
470
- resolve("error");
471
- });
472
- child.on("exit", (code, signal) => {
473
- opts.log(`[remote] Exit: code=${code}, signal=${signal}`);
474
- opts.onThinkingChange(false);
475
- if (currentText && !currentText.endsWith("\n")) process.stdout.write("\n");
476
- resolve(code === 0 || signal === "SIGTERM" ? "ok" : "error");
477
- });
478
- });
479
- }
480
- function handleSDKMessage(msg, opts, write) {
481
- switch (msg.type) {
482
- case "system": {
483
- if (msg.subtype === "init" && msg.session_id) {
484
- opts.onSessionFound(msg.session_id);
485
- }
486
- break;
487
- }
488
- case "assistant": {
489
- const content = msg.message?.content;
490
- if (Array.isArray(content)) {
491
- for (const block of content) {
492
- if (block.type === "text" && block.text) {
493
- write(block.text);
494
- } else if (block.type === "tool_use") {
495
- const argsStr = JSON.stringify(block.input || {}).slice(0, 100);
496
- write(`
497
- \x1B[33m[tool]\x1B[0m ${block.name}(${argsStr})
498
- `);
499
- }
500
- }
501
- }
502
- if (msg.message) {
503
- opts.onMessage({ type: "assistant", uuid: msg.uuid || msg.message?.id, message: msg.message });
504
- }
505
- break;
506
- }
507
- case "user": {
508
- const content = msg.message?.content;
509
- if (Array.isArray(content)) {
510
- for (const block of content) {
511
- if (block.type === "tool_result") {
512
- const text = typeof block.content === "string" ? block.content : JSON.stringify(block.content || "");
513
- if (text.length > 0) {
514
- const preview = text.length > 200 ? text.slice(0, 200) + "..." : text;
515
- write(`\x1B[90m[result]\x1B[0m ${preview}
516
- `);
517
- }
518
- }
519
- }
520
- }
521
- break;
522
- }
523
- case "result": {
524
- write(`
525
- \x1B[32m[done]\x1B[0m
526
- `);
527
- break;
528
- }
529
- default:
530
- opts.log(`[remote] Unknown msg type: ${msg.type}`);
531
- }
532
- }
533
- function mapPermissionMode(mode) {
534
- const map = {
535
- "default": "default",
536
- "acceptEdits": "acceptEdits",
537
- "bypassPermissions": "bypassPermissions",
538
- "plan": "plan",
539
- "auto-approve-all": "bypassPermissions"
540
- };
541
- return map[mode] || null;
542
- }
543
-
544
- async function loop(opts) {
545
- const { log } = opts;
546
- let mode = opts.startingMode;
547
- let claudeSessionId = null;
548
- const onSessionFound = (id) => {
549
- if (id !== claudeSessionId) {
550
- log(`[loop] Session ID: ${id}`);
551
- claudeSessionId = id;
552
- opts.onSessionFound(id);
553
- }
554
- };
555
- while (true) {
556
- log(`[loop] Mode: ${mode}`);
557
- switch (mode) {
558
- case "local": {
559
- if (opts.hasRemoteMessage()) {
560
- log("[loop] Pending remote message, switching to remote");
561
- mode = "remote";
562
- opts.onModeChange(mode);
563
- break;
564
- }
565
- const abortController = new AbortController();
566
- let messageWatcher = null;
567
- messageWatcher = setInterval(() => {
568
- if (opts.hasRemoteMessage() && !abortController.signal.aborted) {
569
- log("[loop] Remote message received, switching to remote mode");
570
- abortController.abort();
571
- }
572
- }, 500);
573
- const result = await runLocalMode({
574
- cwd: opts.cwd,
575
- claudeSessionId,
576
- onSessionFound,
577
- onMessage: opts.onMessage,
578
- onThinkingChange: opts.onThinkingChange,
579
- abort: abortController.signal,
580
- hookSettingsPath: opts.hookSettingsPath,
581
- claudeArgs: opts.claudeArgs,
582
- log
583
- });
584
- if (messageWatcher) clearInterval(messageWatcher);
585
- if (result.type === "switch") {
586
- mode = "remote";
587
- opts.onModeChange(mode);
588
- } else {
589
- return result.code;
590
- }
591
- break;
592
- }
593
- case "remote": {
594
- const abortController = new AbortController();
595
- const result = await runRemoteMode({
596
- cwd: opts.cwd,
597
- claudeSessionId,
598
- onSessionFound,
599
- onMessage: opts.onMessage,
600
- onThinkingChange: opts.onThinkingChange,
601
- nextMessage: opts.waitForRemoteMessage,
602
- permissionMode: opts.permissionMode,
603
- abort: abortController.signal,
604
- hookSettingsPath: opts.hookSettingsPath,
605
- claudeArgs: opts.claudeArgs,
606
- log
607
- });
608
- if (result === "switch") {
609
- mode = "local";
610
- opts.onModeChange(mode);
611
- } else {
612
- return 0;
613
- }
614
- break;
615
- }
616
- }
617
- }
618
- }
619
-
620
- const SVAMP_HOME = process.env.SVAMP_HOME || join(os.homedir(), ".svamp");
621
- const ENV_FILE = join(SVAMP_HOME, ".env");
622
- const DAEMON_STATE_FILE = join(SVAMP_HOME, "daemon.state.json");
623
- const DEBUG = !!process.env.DEBUG;
624
- const log = (...args) => {
625
- if (DEBUG) console.error("[svamp]", ...args);
626
- };
627
- async function runInteractive(options) {
628
- const cwd = options.directory;
629
- const sessionId = randomUUID();
630
- const permissionMode = options.permissionMode || "default";
631
- log(`Starting interactive session: ${sessionId}`);
632
- log(`Directory: ${cwd}`);
633
- loadDotEnv();
634
- let server = null;
635
- let sessionService = null;
636
- const serverUrl = process.env.HYPHA_SERVER_URL;
637
- const token = process.env.HYPHA_TOKEN;
638
- if (serverUrl && token) {
639
- try {
640
- suppressHyphaLogs();
641
- server = await connectToHypha({ serverUrl, token, name: "svamp-interactive" });
642
- log("Connected to Hypha");
643
- } catch (err) {
644
- restoreConsoleLogs();
645
- console.error(`\x1B[33mNote:\x1B[0m Could not connect to Hypha (${err.message}). Running in offline mode.`);
646
- }
647
- } else {
648
- console.error("\x1B[33mNote:\x1B[0m No Hypha credentials found. Running in offline mode.");
649
- console.error(' Run "svamp login <url>" to enable cloud sync.\n');
650
- }
651
- const messageQueue = [];
652
- let messageWaiter = null;
653
- function enqueueMessage(text) {
654
- if (messageWaiter) {
655
- const w = messageWaiter;
656
- messageWaiter = null;
657
- w.resolve(text);
658
- } else {
659
- messageQueue.push(text);
660
- }
661
- }
662
- function waitForRemoteMessage() {
663
- if (messageQueue.length > 0) {
664
- return Promise.resolve(messageQueue.shift());
665
- }
666
- return new Promise((resolve) => {
667
- messageWaiter = { resolve };
668
- });
669
- }
670
- function hasRemoteMessage() {
671
- return messageQueue.length > 0;
672
- }
673
- const machineId = readMachineId();
674
- const metadata = {
675
- path: cwd,
676
- host: os.hostname(),
677
- os: os.platform(),
678
- machineId: machineId || void 0,
679
- homeDir: os.homedir(),
680
- svampHomeDir: SVAMP_HOME,
681
- svampLibDir: "",
682
- svampToolsDir: "",
683
- startedBy: "terminal",
684
- lifecycleState: "running",
685
- flavor: "claude"
686
- };
687
- let currentMode = "local";
688
- if (server) {
689
- const callbacks = {
690
- onUserMessage: (content, _meta) => {
691
- const text = typeof content === "string" ? content : content?.text || content?.content?.text || JSON.stringify(content);
692
- log(`[hypha] User message received: ${text.slice(0, 80)}`);
693
- enqueueMessage(text);
694
- },
695
- onAbort: () => {
696
- log("[hypha] Abort requested");
697
- },
698
- onPermissionResponse: (_params) => {
699
- log("[hypha] Permission response");
700
- },
701
- onSwitchMode: (mode) => {
702
- log(`[hypha] Switch mode: ${mode}`);
703
- },
704
- onRestartClaude: async () => {
705
- log("[hypha] Restart requested");
706
- return { success: false, message: "Restart not supported in interactive mode" };
707
- },
708
- onKillSession: () => {
709
- log("[hypha] Kill requested");
710
- cleanup();
711
- process.exit(0);
712
- },
713
- // File system operations — run locally since we have direct access
714
- // All callbacks use try/catch to prevent errors from leaking
715
- // through hypha-rpc's error handler to the terminal
716
- onBash: async (command, execCwd) => {
717
- try {
718
- const { execSync } = await import('child_process');
719
- const result = execSync(command, {
720
- cwd: execCwd || cwd,
721
- encoding: "utf-8",
722
- timeout: 3e4,
723
- maxBuffer: 1024 * 1024
724
- });
725
- return { output: result };
726
- } catch (err) {
727
- return { output: err.stdout || "", error: err.message, exitCode: err.status || 1 };
728
- }
729
- },
730
- onReadFile: async (path) => {
731
- try {
732
- const { readFileSync: readFileSync2 } = await import('fs');
733
- return readFileSync2(path, "utf-8");
734
- } catch (err) {
735
- throw new Error(`Cannot read file: ${err.message}`);
736
- }
737
- },
738
- onWriteFile: async (path, content) => {
739
- try {
740
- const { writeFileSync } = await import('fs');
741
- writeFileSync(path, content, "utf-8");
742
- } catch (err) {
743
- throw new Error(`Cannot write file: ${err.message}`);
744
- }
745
- },
746
- onListDirectory: async (path) => {
747
- const { readdirSync, statSync } = await import('fs');
748
- const { join: joinPath } = await import('path');
749
- return readdirSync(path).map((name) => {
750
- try {
751
- const st = statSync(joinPath(path, name));
752
- return { name, type: st.isDirectory() ? "directory" : "file", size: st.size };
753
- } catch {
754
- return { name, type: "unknown", size: 0 };
755
- }
756
- });
757
- },
758
- onRipgrep: async (rgArgs, execCwd) => {
759
- try {
760
- const { execSync } = await import('child_process');
761
- return execSync(`rg ${rgArgs}`, {
762
- cwd: execCwd || cwd,
763
- encoding: "utf-8",
764
- timeout: 15e3,
765
- maxBuffer: 1024 * 1024
766
- });
767
- } catch (err) {
768
- return err.stdout || "";
769
- }
770
- }
771
- };
772
- try {
773
- sessionService = await registerSessionService(
774
- server,
775
- sessionId,
776
- metadata,
777
- { controlledByUser: true },
778
- callbacks
779
- );
780
- log(`Session service registered: svamp-session-${sessionId}`);
781
- } catch (err) {
782
- restoreConsoleLogs();
783
- console.error(`\x1B[33mNote:\x1B[0m Could not register session on Hypha (${err.message}).`);
784
- }
785
- }
786
- let hookServer = null;
787
- let hookSettings = null;
788
- let claudeSessionId = options.resumeSessionId || null;
789
- try {
790
- hookServer = await startHookServer((id) => {
791
- claudeSessionId = id;
792
- log(`Claude session ID from hook: ${id}`);
793
- if (sessionService) {
794
- sessionService.updateMetadata({ ...metadata, claudeSessionId: id });
795
- }
796
- }, log);
797
- hookSettings = generateHookSettings(hookServer.port);
798
- log(`Hook settings: ${hookSettings.settingsPath}`);
799
- } catch (err) {
800
- log(`Failed to start hook server: ${err.message}`);
801
- }
802
- let keepAliveInterval = null;
803
- if (sessionService) {
804
- keepAliveInterval = setInterval(() => {
805
- sessionService.sendKeepAlive(false);
806
- }, 3e4);
807
- }
808
- const cleanup = async () => {
809
- log("Cleaning up...");
810
- if (keepAliveInterval) clearInterval(keepAliveInterval);
811
- if (sessionService) {
812
- sessionService.sendSessionEnd();
813
- await sessionService.disconnect().catch(() => {
814
- });
815
- }
816
- hookSettings?.cleanup();
817
- hookServer?.stop();
818
- if (server) {
819
- await server.disconnect().catch(() => {
820
- });
821
- }
822
- if (messageWaiter) {
823
- messageWaiter.resolve(null);
824
- messageWaiter = null;
825
- }
826
- restoreConsoleLogs();
827
- };
828
- let exiting = false;
829
- const handleExit = async () => {
830
- if (exiting) return;
831
- exiting = true;
832
- await cleanup();
833
- process.exit(0);
834
- };
835
- process.on("SIGTERM", handleExit);
836
- process.on("SIGINT", handleExit);
837
- const claudeArgs = [...options.claudeArgs || []];
838
- if (options.resumeSessionId) ; else if (options.continueSession) {
839
- claudeArgs.push("--continue");
840
- }
841
- restoreConsoleLogs();
842
- console.log(`\x1B[36mSvamp interactive mode\x1B[0m`);
843
- if (server && sessionService) {
844
- const serviceId = sessionService.serviceInfo?.id || `svamp-session-${sessionId}`;
845
- const slashIdx = serviceId.indexOf("/");
846
- const colonIdx = serviceId.indexOf(":");
847
- let serviceUrl = "";
848
- if (slashIdx > 0 && colonIdx > slashIdx) {
849
- const workspace = serviceId.slice(0, slashIdx);
850
- const clientAndService = serviceId.slice(slashIdx + 1);
851
- serviceUrl = `${serverUrl}/${workspace}/services/${clientAndService}`;
852
- }
853
- console.log(`\x1B[90mSession synced to Hypha \u2014 visible in the web app\x1B[0m`);
854
- if (serviceUrl) {
855
- console.log(`\x1B[90mService: ${serviceUrl}\x1B[0m`);
856
- }
857
- console.log(`\x1B[90mSession ID: ${sessionId.slice(0, 8)}\x1B[0m`);
858
- }
859
- console.log("");
860
- if (server) suppressHyphaLogs();
861
- try {
862
- const exitCode = await loop({
863
- cwd,
864
- startingMode: "local",
865
- hookSettingsPath: hookSettings?.settingsPath || "",
866
- permissionMode,
867
- claudeArgs: claudeArgs.length > 0 ? claudeArgs : void 0,
868
- log,
869
- onModeChange: (mode) => {
870
- log(`Mode changed: ${mode}`);
871
- currentMode = mode;
872
- if (sessionService) {
873
- sessionService.updateAgentState({
874
- controlledByUser: mode === "local"
875
- });
876
- sessionService.updateMetadata({ ...metadata, lifecycleState: "running" });
877
- sessionService.sendKeepAlive(false, mode);
878
- }
879
- },
880
- onSessionFound: (id) => {
881
- claudeSessionId = id;
882
- if (sessionService) {
883
- sessionService.updateMetadata({ ...metadata, claudeSessionId: id });
884
- }
885
- },
886
- onMessage: (msg) => {
887
- if (!sessionService) return;
888
- if (msg.type === "assistant" && msg.message) {
889
- sessionService.pushMessage({
890
- type: "assistant",
891
- message: msg.message
892
- }, "agent");
893
- } else if (msg.type === "user" && msg.message) {
894
- const text = typeof msg.message.content === "string" ? msg.message.content : msg.message.content?.text || JSON.stringify(msg.message.content);
895
- sessionService.pushMessage({ type: "text", text }, "user");
896
- } else if (msg.type === "summary") {
897
- sessionService.updateMetadata({
898
- ...metadata,
899
- claudeSessionId: claudeSessionId || void 0,
900
- summary: { text: msg.summary || "", updatedAt: Date.now() }
901
- });
902
- }
903
- },
904
- onThinkingChange: (thinking) => {
905
- if (sessionService) {
906
- sessionService.sendKeepAlive(thinking);
907
- }
908
- },
909
- waitForRemoteMessage,
910
- hasRemoteMessage
911
- });
912
- await cleanup();
913
- process.exit(exitCode);
914
- } catch (err) {
915
- log(`Loop error: ${err.message}`);
916
- await cleanup();
917
- process.exit(1);
918
- }
919
- }
920
- function loadDotEnv() {
921
- if (!existsSync(ENV_FILE)) return;
922
- const lines = readFileSync(ENV_FILE, "utf-8").split("\n");
923
- for (const line of lines) {
924
- const trimmed = line.trim();
925
- if (!trimmed || trimmed.startsWith("#")) continue;
926
- const eqIdx = trimmed.indexOf("=");
927
- if (eqIdx === -1) continue;
928
- const key = trimmed.slice(0, eqIdx).trim();
929
- const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
930
- if (!process.env[key]) process.env[key] = value;
931
- }
932
- }
933
- function readMachineId() {
934
- try {
935
- if (!existsSync(DAEMON_STATE_FILE)) return null;
936
- const state = JSON.parse(readFileSync(DAEMON_STATE_FILE, "utf-8"));
937
- return state.machineId || null;
938
- } catch {
939
- return null;
940
- }
941
- }
942
- let _origLog = null;
943
- let _origWarn = null;
944
- let _origInfo = null;
945
- let _origDebug = null;
946
- let _origError = null;
947
- let _origStdoutWrite = null;
948
- let _origStderrWrite = null;
949
- const HYPHA_LOG_PATTERNS = [
950
- "WebSocket connection",
951
- "Connection established",
952
- "reporting services",
953
- "Successfully registered",
954
- "Subscribing to",
955
- "Successfully subscribed",
956
- "Cleaning up all sessions",
957
- "Cleaned up session",
958
- "ClTaned up",
959
- "Cleaned up ",
960
- "Handling disconnection",
961
- "Client ws-user-",
962
- "WebSocket connection disconnected",
963
- "disconnected, cleaning up",
964
- "HYPHA SESSION",
965
- "Listener registered",
966
- "local RPC disconnection",
967
- "not found for method",
968
- "likely cleaned up",
969
- "Promise method",
970
- "not available (detected by session type)",
971
- "Session ",
972
- // catch-all for "Session X not found" etc.
973
- "Failed to find method",
974
- "Method not found",
975
- "Error during calling method",
976
- "Timeout subscribing",
977
- "Manager does not support subscribe"
978
- ];
979
- function isHyphaLogLine(text) {
980
- return HYPHA_LOG_PATTERNS.some((p) => text.includes(p));
981
- }
982
- function suppressHyphaLogs() {
983
- if (_origLog) return;
984
- _origLog = console.log;
985
- _origWarn = console.warn;
986
- _origInfo = console.info;
987
- _origDebug = console.debug;
988
- _origError = console.error;
989
- _origStdoutWrite = process.stdout.write.bind(process.stdout);
990
- _origStderrWrite = process.stderr.write.bind(process.stderr);
991
- console.log = (...args) => {
992
- if (DEBUG) _origLog.call(console, "[hypha-log]", ...args);
993
- };
994
- console.warn = (...args) => {
995
- if (DEBUG) _origWarn.call(console, "[hypha-warn]", ...args);
996
- };
997
- console.info = (...args) => {
998
- if (DEBUG) _origInfo.call(console, "[hypha-info]", ...args);
999
- };
1000
- console.debug = (...args) => {
1001
- if (DEBUG) _origDebug.call(console, "[hypha-debug]", ...args);
1002
- };
1003
- console.error = (...args) => {
1004
- const text = args.map((a) => typeof a === "string" ? a : String(a)).join(" ");
1005
- if (isHyphaLogLine(text)) {
1006
- if (DEBUG) _origError.call(console, "[hypha-err]", ...args);
1007
- return;
1008
- }
1009
- _origError.call(console, ...args);
1010
- };
1011
- process.stdout.write = function(chunk, ...rest) {
1012
- const text = typeof chunk === "string" ? chunk : chunk?.toString?.() || "";
1013
- if (isHyphaLogLine(text)) {
1014
- if (DEBUG) _origStdoutWrite(`[hypha-stdout] ${text}`);
1015
- return true;
1016
- }
1017
- return _origStdoutWrite.call(process.stdout, chunk, ...rest);
1018
- };
1019
- process.stderr.write = function(chunk, ...rest) {
1020
- const text = typeof chunk === "string" ? chunk : chunk?.toString?.() || "";
1021
- if (isHyphaLogLine(text)) {
1022
- if (DEBUG) _origStderrWrite(`[hypha-stderr] ${text}`);
1023
- return true;
1024
- }
1025
- return _origStderrWrite.call(process.stderr, chunk, ...rest);
1026
- };
1027
- }
1028
- function restoreConsoleLogs() {
1029
- if (!_origLog) return;
1030
- console.log = _origLog;
1031
- console.warn = _origWarn;
1032
- console.info = _origInfo;
1033
- console.debug = _origDebug;
1034
- console.error = _origError;
1035
- if (_origStdoutWrite) {
1036
- process.stdout.write = _origStdoutWrite;
1037
- }
1038
- if (_origStderrWrite) {
1039
- process.stderr.write = _origStderrWrite;
1040
- }
1041
- _origLog = null;
1042
- _origWarn = null;
1043
- _origInfo = null;
1044
- _origDebug = null;
1045
- _origError = null;
1046
- _origStdoutWrite = null;
1047
- _origStderrWrite = null;
1048
- }
1049
-
1050
- export { runInteractive };