svamp-cli 0.1.51 → 0.1.53

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 (319) hide show
  1. package/README.md +193 -0
  2. package/bin/svamp.mjs +16 -7
  3. package/dist/cli.mjs +19 -19
  4. package/dist/{commands-mw8HFkt6.mjs → commands-1tmye7o_.mjs} +3 -2
  5. package/dist/{commands-D1brd9fB.mjs → commands-BJdwoEe6.mjs} +7 -3
  6. package/dist/{commands-DHnFOhQC.mjs → commands-CI_BVphs.mjs} +7 -3
  7. package/dist/{commands-BOYo9cdy.mjs → commands-DcFOU9nW.mjs} +7 -3
  8. package/dist/commands-DwY2B7KW.mjs +562 -0
  9. package/dist/commands-VGt5ofDo.mjs +1755 -0
  10. package/dist/commands-ZuFXrcot.mjs +558 -0
  11. package/dist/index.mjs +1 -1
  12. package/dist/{package-BLDik3NY.mjs → package-D7EUXtnk.mjs} +1 -1
  13. package/dist/{package-BYUO-39f.mjs → package-DbeynOln.mjs} +1 -1
  14. package/dist/{run-6dwQnoBL.mjs → run-BYJX5syg.mjs} +1 -1
  15. package/dist/{run-C0ecvcRP.mjs → run-BnnUavlu.mjs} +131 -44
  16. package/dist/{run-3Et1ISd5.mjs → run-Bw6aGHLA.mjs} +1 -1
  17. package/dist/{run-CE4H8ZiN.mjs → run-CBhm4Jop.mjs} +219 -80
  18. package/dist/{run-BE_AIJ7z.mjs → run-DOwarObi.mjs} +1 -1
  19. package/dist/{run-Bc83CRUn.mjs → run-DxISzP_V.mjs} +38 -7
  20. package/dist/{run-4li60ojK.mjs → run-Y0b60UYS.mjs} +1 -1
  21. package/dist/{run-BdEHYoYE.mjs → run-eYBOEaWw.mjs} +20 -7
  22. package/dist/tunnel-C2_V6y3d.mjs +299 -0
  23. package/dist/tunnel-DhVAOdGd.mjs +299 -0
  24. package/package.json +1 -1
  25. package/dist/commands-4_MiOQVp.mjs +0 -1217
  26. package/dist/commands-8UAWGJrC.mjs +0 -1208
  27. package/dist/commands-8Wmq0uak.mjs +0 -1407
  28. package/dist/commands-8Xn02pQg.mjs +0 -1217
  29. package/dist/commands-9DPsh6ku.mjs +0 -1217
  30. package/dist/commands-9rMB13FP.mjs +0 -1214
  31. package/dist/commands-B-XaqFDB.mjs +0 -1407
  32. package/dist/commands-B53zuBHB.mjs +0 -1217
  33. package/dist/commands-B7yLt11i.mjs +0 -1217
  34. package/dist/commands-BDVAO_N2.mjs +0 -1217
  35. package/dist/commands-BD_NjWJL.mjs +0 -1217
  36. package/dist/commands-BEhSQqTp.mjs +0 -507
  37. package/dist/commands-BIFQZZGw.mjs +0 -1375
  38. package/dist/commands-BImRR1Wr.mjs +0 -1217
  39. package/dist/commands-BLmRIMdf.mjs +0 -1217
  40. package/dist/commands-BQ_347V_.mjs +0 -1374
  41. package/dist/commands-BTEmyf2m.mjs +0 -1407
  42. package/dist/commands-BVjcCbWS.mjs +0 -1375
  43. package/dist/commands-BVsLRttq.mjs +0 -1217
  44. package/dist/commands-BVuE0VQU.mjs +0 -507
  45. package/dist/commands-BY09VTpk.mjs +0 -1375
  46. package/dist/commands-Bcdp0X-o.mjs +0 -1217
  47. package/dist/commands-BdnG1cqQ.mjs +0 -1217
  48. package/dist/commands-BdvvRQIo.mjs +0 -1415
  49. package/dist/commands-Bgg_dvDw.mjs +0 -1683
  50. package/dist/commands-Bi0zYJvj.mjs +0 -1407
  51. package/dist/commands-BmirUCVt.mjs +0 -1208
  52. package/dist/commands-BpSUbvmr.mjs +0 -1217
  53. package/dist/commands-BuJ6xTfc.mjs +0 -1217
  54. package/dist/commands-BzbYPx0f.mjs +0 -1208
  55. package/dist/commands-C-RtFjJl.mjs +0 -1217
  56. package/dist/commands-C20_f6oo.mjs +0 -1217
  57. package/dist/commands-C6KDr9Yp.mjs +0 -1407
  58. package/dist/commands-C9TOoTCv.mjs +0 -1395
  59. package/dist/commands-C9TdN_El.mjs +0 -1683
  60. package/dist/commands-CFv6lO0D.mjs +0 -1217
  61. package/dist/commands-CJ2n5jS2.mjs +0 -1375
  62. package/dist/commands-CKEKQ_5B.mjs +0 -1217
  63. package/dist/commands-CQz67Rm1.mjs +0 -1395
  64. package/dist/commands-CRZbJjqN.mjs +0 -1375
  65. package/dist/commands-CToIvBFX.mjs +0 -1375
  66. package/dist/commands-CWsfciHn.mjs +0 -1217
  67. package/dist/commands-CYMSyqYC.mjs +0 -1395
  68. package/dist/commands-CZ7KPLLJ.mjs +0 -1217
  69. package/dist/commands-Cc73uUnP.mjs +0 -1375
  70. package/dist/commands-CdMsAD1-.mjs +0 -1217
  71. package/dist/commands-CdyCWC3y.mjs +0 -1395
  72. package/dist/commands-ClVCprrK.mjs +0 -1217
  73. package/dist/commands-Cnmf8znA.mjs +0 -1196
  74. package/dist/commands-CorUNLRF.mjs +0 -1375
  75. package/dist/commands-Cq0oj5_v.mjs +0 -1217
  76. package/dist/commands-CrdvbXPI.mjs +0 -1395
  77. package/dist/commands-Cw2Od6mc.mjs +0 -1683
  78. package/dist/commands-CwC2aVzu.mjs +0 -1217
  79. package/dist/commands-CxSCUJCB.mjs +0 -1217
  80. package/dist/commands-D-PTwdZz.mjs +0 -1217
  81. package/dist/commands-D-nIO_Sf.mjs +0 -1741
  82. package/dist/commands-D7-NHH5q.mjs +0 -1407
  83. package/dist/commands-D7kH-7Vn.mjs +0 -1217
  84. package/dist/commands-DBv6A3aJ.mjs +0 -507
  85. package/dist/commands-DD3HXakm.mjs +0 -1217
  86. package/dist/commands-DLoe6FyK.mjs +0 -1375
  87. package/dist/commands-DPbH8KF0.mjs +0 -1217
  88. package/dist/commands-DUAQ9MZM.mjs +0 -1217
  89. package/dist/commands-DVw-P6-0.mjs +0 -1407
  90. package/dist/commands-DVygnMsh.mjs +0 -1217
  91. package/dist/commands-DWira-Cz.mjs +0 -1741
  92. package/dist/commands-DYTdUlul.mjs +0 -1217
  93. package/dist/commands-DZfaDmsk.mjs +0 -1374
  94. package/dist/commands-Dd8cn8mW.mjs +0 -1217
  95. package/dist/commands-DsIoygTL.mjs +0 -1395
  96. package/dist/commands-Du-fdLLu.mjs +0 -969
  97. package/dist/commands-DuJGOq1y.mjs +0 -1217
  98. package/dist/commands-DwBr3sBn.mjs +0 -1217
  99. package/dist/commands-DwveR96q.mjs +0 -1683
  100. package/dist/commands-DypTF36z.mjs +0 -506
  101. package/dist/commands-EUMJqBCs.mjs +0 -1407
  102. package/dist/commands-HLu7P96l.mjs +0 -1214
  103. package/dist/commands-HrBaGV-C.mjs +0 -1683
  104. package/dist/commands-Jk5no-DX.mjs +0 -1407
  105. package/dist/commands-KH5dj9dv.mjs +0 -1214
  106. package/dist/commands-LaNHVHjc.mjs +0 -1217
  107. package/dist/commands-O1Q9g00y.mjs +0 -1395
  108. package/dist/commands-OwMfbBrU.mjs +0 -1395
  109. package/dist/commands-SQ0Wp_kD.mjs +0 -1217
  110. package/dist/commands-S_MFQ9n1.mjs +0 -354
  111. package/dist/commands-T3q8VKCY.mjs +0 -1407
  112. package/dist/commands-Ugz9TtRu.mjs +0 -1420
  113. package/dist/commands-Wng0OuNY.mjs +0 -1683
  114. package/dist/commands-YBW5jFpy.mjs +0 -1217
  115. package/dist/commands-Z-CbuF8E.mjs +0 -1217
  116. package/dist/commands-fSZOP80Z.mjs +0 -1217
  117. package/dist/commands-fqBuJe1b.mjs +0 -1217
  118. package/dist/commands-g-1n3_Rp.mjs +0 -1395
  119. package/dist/commands-mC0oe0lj.mjs +0 -1217
  120. package/dist/commands-od2hOku5.mjs +0 -1217
  121. package/dist/commands-otgzprjb.mjs +0 -1375
  122. package/dist/commands-rhHI6Wb2.mjs +0 -1420
  123. package/dist/commands-zGHnUXh5.mjs +0 -1217
  124. package/dist/package-BMCjXPI9.mjs +0 -58
  125. package/dist/package-BPMWPlS0.mjs +0 -57
  126. package/dist/package-BaGfG8vL.mjs +0 -58
  127. package/dist/package-BkBE6ZdN.mjs +0 -57
  128. package/dist/package-BufekbY1.mjs +0 -57
  129. package/dist/package-C1hpYMj4.mjs +0 -57
  130. package/dist/package-CmIBOZtY.mjs +0 -57
  131. package/dist/package-CmVt1kdw.mjs +0 -58
  132. package/dist/package-Cn6Ya4A0.mjs +0 -57
  133. package/dist/package-Csd530Ym.mjs +0 -57
  134. package/dist/package-D6mNQtUs.mjs +0 -57
  135. package/dist/package-DG0AkZdm.mjs +0 -58
  136. package/dist/package-DRO1LpXW.mjs +0 -58
  137. package/dist/package-Dav8qh6X.mjs +0 -57
  138. package/dist/package-DiA55dzE.mjs +0 -57
  139. package/dist/package-UwLIU765.mjs +0 -58
  140. package/dist/package-k3XsdP9k.mjs +0 -58
  141. package/dist/package-rasGC9_z.mjs +0 -58
  142. package/dist/run-4B1XZQB8.mjs +0 -5426
  143. package/dist/run-4eArMb_9.mjs +0 -1050
  144. package/dist/run-67wfoMuo.mjs +0 -5383
  145. package/dist/run-6N2IdEX7.mjs +0 -5410
  146. package/dist/run-7iQKryzo.mjs +0 -5383
  147. package/dist/run-7s8lOXqB.mjs +0 -1050
  148. package/dist/run-8kKykzTs.mjs +0 -5367
  149. package/dist/run-8mLZV2lg.mjs +0 -1050
  150. package/dist/run-9x7I9Ck-.mjs +0 -5264
  151. package/dist/run-B-PWtXF-.mjs +0 -5894
  152. package/dist/run-B1ivovUl.mjs +0 -5964
  153. package/dist/run-B1l9Ed8k.mjs +0 -5403
  154. package/dist/run-B2zRMxE0.mjs +0 -5508
  155. package/dist/run-B31biy0V.mjs +0 -1050
  156. package/dist/run-B5o5fMMd.mjs +0 -5369
  157. package/dist/run-B7V-xXM7.mjs +0 -5775
  158. package/dist/run-B9ND6srh.mjs +0 -6154
  159. package/dist/run-BG3279Kg.mjs +0 -1051
  160. package/dist/run-BHZNzX1F.mjs +0 -5235
  161. package/dist/run-BKdOv7gX.mjs +0 -1050
  162. package/dist/run-BLySdZ1K.mjs +0 -5251
  163. package/dist/run-BOVkQfM-.mjs +0 -1050
  164. package/dist/run-BQ0lIare.mjs +0 -1050
  165. package/dist/run-BREPr7Yc.mjs +0 -5508
  166. package/dist/run-BTwshVk1.mjs +0 -5728
  167. package/dist/run-BUL3eAqT.mjs +0 -1050
  168. package/dist/run-BVcPemGr.mjs +0 -5947
  169. package/dist/run-BWqEmIiz.mjs +0 -5964
  170. package/dist/run-BWsDPiNe.mjs +0 -1050
  171. package/dist/run-BX4iy6k8.mjs +0 -1050
  172. package/dist/run-BXYfq8mK.mjs +0 -5836
  173. package/dist/run-BY12Ataq.mjs +0 -5732
  174. package/dist/run-BYDOX4yk.mjs +0 -5402
  175. package/dist/run-Bd-t6s63.mjs +0 -5373
  176. package/dist/run-BenYqfwQ.mjs +0 -5273
  177. package/dist/run-BfF4bgA3.mjs +0 -5403
  178. package/dist/run-Bhh05yic.mjs +0 -5369
  179. package/dist/run-BicITYWX.mjs +0 -6138
  180. package/dist/run-BieEN0Pg.mjs +0 -5761
  181. package/dist/run-BjEQi6PN.mjs +0 -1050
  182. package/dist/run-BjZ6SyFy.mjs +0 -1051
  183. package/dist/run-Bl8OkKyC.mjs +0 -5969
  184. package/dist/run-BlEFlhfn.mjs +0 -5510
  185. package/dist/run-BmL1m0Bk.mjs +0 -1050
  186. package/dist/run-Bmx5wEBF.mjs +0 -1051
  187. package/dist/run-BnX5Rw8x.mjs +0 -5403
  188. package/dist/run-BpjmHeht.mjs +0 -1050
  189. package/dist/run-BxTdRjCG.mjs +0 -1051
  190. package/dist/run-ByOVDgvx.mjs +0 -6115
  191. package/dist/run-BzRP6Q5t.mjs +0 -1051
  192. package/dist/run-C0dyMP62.mjs +0 -1051
  193. package/dist/run-C1lS3SwN.mjs +0 -5733
  194. package/dist/run-C3PAp02X.mjs +0 -5252
  195. package/dist/run-C3eaYQub.mjs +0 -1050
  196. package/dist/run-C4pdX4sY.mjs +0 -1051
  197. package/dist/run-C676pHe-.mjs +0 -5423
  198. package/dist/run-C8GkzcfP.mjs +0 -1050
  199. package/dist/run-C9Hrqjy_.mjs +0 -1050
  200. package/dist/run-CC2C8P-U.mjs +0 -6031
  201. package/dist/run-CCcW4asS.mjs +0 -1050
  202. package/dist/run-CDBKhQ1Z.mjs +0 -1051
  203. package/dist/run-CEB6sYzn.mjs +0 -5962
  204. package/dist/run-CF6aXLmA.mjs +0 -5445
  205. package/dist/run-CHyN5U0t.mjs +0 -1050
  206. package/dist/run-CIFezmkC.mjs +0 -5949
  207. package/dist/run-CLA9zw7J.mjs +0 -5907
  208. package/dist/run-COWb9ovq.mjs +0 -1050
  209. package/dist/run-CSUAy5T5.mjs +0 -1051
  210. package/dist/run-CSk7i0Hq.mjs +0 -1050
  211. package/dist/run-CUtqSGWJ.mjs +0 -1050
  212. package/dist/run-CXrEt0TM.mjs +0 -5008
  213. package/dist/run-CY8Y0JPW.mjs +0 -5287
  214. package/dist/run-CZCKBcQ-.mjs +0 -5244
  215. package/dist/run-CZj0sRCs.mjs +0 -1050
  216. package/dist/run-C_1x2cNU.mjs +0 -5381
  217. package/dist/run-C_8iOjO1.mjs +0 -5892
  218. package/dist/run-C_KIew8H.mjs +0 -1051
  219. package/dist/run-CajRcN3C.mjs +0 -1050
  220. package/dist/run-CbzXO7fw.mjs +0 -1050
  221. package/dist/run-CcSr4x2f.mjs +0 -1050
  222. package/dist/run-CcYaXgCy.mjs +0 -6091
  223. package/dist/run-CdihMx0V.mjs +0 -1051
  224. package/dist/run-Cf2Dl_ck.mjs +0 -1051
  225. package/dist/run-CjH1H4vq.mjs +0 -1050
  226. package/dist/run-CkbDK6jA.mjs +0 -1051
  227. package/dist/run-Ckh6JE9F.mjs +0 -1050
  228. package/dist/run-Ckyg9-fm.mjs +0 -6079
  229. package/dist/run-CqL3ZWdr.mjs +0 -5381
  230. package/dist/run-Csj7sJAh.mjs +0 -1050
  231. package/dist/run-Ct--DWF1.mjs +0 -1051
  232. package/dist/run-CtJRxaFC.mjs +0 -1051
  233. package/dist/run-CuIMdkKF.mjs +0 -6099
  234. package/dist/run-CuckJGM-.mjs +0 -1050
  235. package/dist/run-CxGAa9MH.mjs +0 -1050
  236. package/dist/run-CyU4-O-e.mjs +0 -5411
  237. package/dist/run-CymDyu2b.mjs +0 -5389
  238. package/dist/run-CzIY4_RE.mjs +0 -6093
  239. package/dist/run-D0Ha4aWt.mjs +0 -1050
  240. package/dist/run-D0ow-xms.mjs +0 -5905
  241. package/dist/run-D1PFrNZB.mjs +0 -6273
  242. package/dist/run-D2X3jEqg.mjs +0 -1051
  243. package/dist/run-D39C7Ta3.mjs +0 -1050
  244. package/dist/run-D3Lqxasl.mjs +0 -1051
  245. package/dist/run-D3bhRCCb.mjs +0 -1051
  246. package/dist/run-D5N42sVA.mjs +0 -1050
  247. package/dist/run-D691XPXy.mjs +0 -6031
  248. package/dist/run-D7dLDpq3.mjs +0 -5403
  249. package/dist/run-D8mQ_fL5.mjs +0 -1050
  250. package/dist/run-DA-YBjNw.mjs +0 -6018
  251. package/dist/run-DByI8mI0.mjs +0 -1051
  252. package/dist/run-DCINWip4.mjs +0 -1050
  253. package/dist/run-DCrZ3vke.mjs +0 -5406
  254. package/dist/run-DDF-tRbn.mjs +0 -5954
  255. package/dist/run-DGSgljJE.mjs +0 -5421
  256. package/dist/run-DGsXW19O.mjs +0 -5541
  257. package/dist/run-DHrF2xpW.mjs +0 -5776
  258. package/dist/run-DIB0W42M.mjs +0 -1050
  259. package/dist/run-DJ4k0WzZ.mjs +0 -1051
  260. package/dist/run-DMI83W7i.mjs +0 -5434
  261. package/dist/run-DNX3djCI.mjs +0 -1050
  262. package/dist/run-DOPaGRT2.mjs +0 -6027
  263. package/dist/run-DP7KSZqR.mjs +0 -1051
  264. package/dist/run-DQ0yljWr.mjs +0 -1050
  265. package/dist/run-DTkldU6a.mjs +0 -1050
  266. package/dist/run-DU10B3gK.mjs +0 -5728
  267. package/dist/run-DV86VJNG.mjs +0 -5386
  268. package/dist/run-DVZGKdKO.mjs +0 -1050
  269. package/dist/run-DWdtp6VD.mjs +0 -6136
  270. package/dist/run-DWzA1gZ-.mjs +0 -1050
  271. package/dist/run-DXJ2M19k.mjs +0 -1050
  272. package/dist/run-DZOeccNu.mjs +0 -5484
  273. package/dist/run-D_W5YF0D.mjs +0 -6046
  274. package/dist/run-DaReJPf8.mjs +0 -1051
  275. package/dist/run-DaYrEeQ9.mjs +0 -5400
  276. package/dist/run-DbC9-WM4.mjs +0 -1050
  277. package/dist/run-Dd9XkswU.mjs +0 -1051
  278. package/dist/run-De-wkVl3.mjs +0 -5487
  279. package/dist/run-DfU2luyX.mjs +0 -1050
  280. package/dist/run-Dfl3Ze2L.mjs +0 -5541
  281. package/dist/run-DfuHUDIJ.mjs +0 -1051
  282. package/dist/run-DfwfyFqj.mjs +0 -5975
  283. package/dist/run-DgUDGHZy.mjs +0 -1051
  284. package/dist/run-Dge2K7h1.mjs +0 -1050
  285. package/dist/run-Di3I0USw.mjs +0 -1050
  286. package/dist/run-Dm3U4FB5.mjs +0 -6018
  287. package/dist/run-Du0YOs48.mjs +0 -5446
  288. package/dist/run-DuaIQAE4.mjs +0 -5392
  289. package/dist/run-Dwm19YhI.mjs +0 -1050
  290. package/dist/run-DxM7xaBa.mjs +0 -1050
  291. package/dist/run-DysN-cGm.mjs +0 -1050
  292. package/dist/run-DzXohf8-.mjs +0 -1051
  293. package/dist/run-E_MwVOtN.mjs +0 -5272
  294. package/dist/run-FPoL2-FD.mjs +0 -5381
  295. package/dist/run-HU4XjZfs.mjs +0 -6023
  296. package/dist/run-HhiYlJuS.mjs +0 -5414
  297. package/dist/run-JXLlRLFb.mjs +0 -1050
  298. package/dist/run-K-_jahIg.mjs +0 -1051
  299. package/dist/run-K_S7pfZ-.mjs +0 -1050
  300. package/dist/run-LDiT4WF-.mjs +0 -1050
  301. package/dist/run-NToLJWx-.mjs +0 -5442
  302. package/dist/run-RBufRqbs.mjs +0 -1050
  303. package/dist/run-YFYpyThQ.mjs +0 -1051
  304. package/dist/run-YG1Pb9dY.mjs +0 -5385
  305. package/dist/run-ZDa17iLg.mjs +0 -6060
  306. package/dist/run-ZN0qMdS_.mjs +0 -1051
  307. package/dist/run-azpFWM6w.mjs +0 -1050
  308. package/dist/run-coIDvBK_.mjs +0 -6127
  309. package/dist/run-jLp4pbTE.mjs +0 -1050
  310. package/dist/run-m3oAuSg0.mjs +0 -1050
  311. package/dist/run-r9CAcL_U.mjs +0 -5403
  312. package/dist/run-v32uF2bP.mjs +0 -5378
  313. package/dist/run-vTsskoZc.mjs +0 -5340
  314. package/dist/run-vt26p5D7.mjs +0 -1050
  315. package/dist/run-vvQiCHpi.mjs +0 -5427
  316. package/dist/run-w-HVv5py.mjs +0 -5410
  317. package/dist/run-wpUutZ9C.mjs +0 -1051
  318. package/dist/run-yTjJ7noq.mjs +0 -1051
  319. package/dist/run-zo5GSoVC.mjs +0 -1050
@@ -1058,6 +1058,14 @@ async function registerSessionService(server, sessionId, initialMetadata, initia
1058
1058
  });
1059
1059
  return await callbacks.onUpdateSecurityContext(newSecurityContext);
1060
1060
  },
1061
+ /** Apply a new system prompt and restart the agent process */
1062
+ applySystemPrompt: async (prompt, context) => {
1063
+ authorizeRequest(context, metadata.sharing, "admin");
1064
+ if (!callbacks.onApplySystemPrompt) {
1065
+ throw new Error("System prompt updates are not supported for this session");
1066
+ }
1067
+ return await callbacks.onApplySystemPrompt(prompt);
1068
+ },
1061
1069
  // ── Listener Registration ──
1062
1070
  registerListener: async (callback, context) => {
1063
1071
  authorizeRequest(context, metadata.sharing, "view");
@@ -3678,23 +3686,28 @@ function sanitizeEnvForSharing(env) {
3678
3686
 
3679
3687
  const __filename$1 = fileURLToPath(import.meta.url);
3680
3688
  const __dirname$1 = dirname(__filename$1);
3681
- function loadDotEnv() {
3682
- const envDir = process.env.SVAMP_HOME || join(os__default.homedir(), ".svamp");
3683
- const envFile = join(envDir, ".env");
3684
- if (existsSync$1(envFile)) {
3685
- const lines = readFileSync$1(envFile, "utf-8").split("\n");
3686
- for (const line of lines) {
3687
- const trimmed = line.trim();
3688
- if (!trimmed || trimmed.startsWith("#")) continue;
3689
- const eqIdx = trimmed.indexOf("=");
3690
- if (eqIdx === -1) continue;
3691
- const key = trimmed.slice(0, eqIdx).trim();
3692
- const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
3693
- if (!process.env[key]) {
3694
- process.env[key] = value;
3695
- }
3689
+ function loadEnvFile(path) {
3690
+ if (!existsSync$1(path)) return false;
3691
+ const lines = readFileSync$1(path, "utf-8").split("\n");
3692
+ for (const line of lines) {
3693
+ const trimmed = line.trim();
3694
+ if (!trimmed || trimmed.startsWith("#")) continue;
3695
+ const eqIdx = trimmed.indexOf("=");
3696
+ if (eqIdx === -1) continue;
3697
+ const key = trimmed.slice(0, eqIdx).trim();
3698
+ const value = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, "");
3699
+ if (!process.env[key]) {
3700
+ process.env[key] = value;
3696
3701
  }
3697
3702
  }
3703
+ return true;
3704
+ }
3705
+ function loadDotEnv() {
3706
+ const svampEnv = join(process.env.SVAMP_HOME || os__default.homedir() + "/.svamp", ".env");
3707
+ if (!loadEnvFile(svampEnv)) {
3708
+ const hyphaEnv = join(process.env.HYPHA_HOME || os__default.homedir() + "/.hypha", ".env");
3709
+ loadEnvFile(hyphaEnv);
3710
+ }
3698
3711
  }
3699
3712
  loadDotEnv();
3700
3713
  const SVAMP_HOME = process.env.SVAMP_HOME || join(os__default.homedir(), ".svamp");
@@ -3772,7 +3785,7 @@ function readRalphState(filePath) {
3772
3785
  return {
3773
3786
  iteration: parseInt(fields.iteration || "1", 10) || 1,
3774
3787
  max_iterations: parseInt(fields.max_iterations || "0", 10) || 0,
3775
- completion_promise: fields.completion_promise || "DONE",
3788
+ completion_promise: fields.completion_promise === "none" ? null : fields.completion_promise || "DONE",
3776
3789
  cooldown_seconds: parseInt(fields.cooldown_seconds || "1", 10) || 1,
3777
3790
  started_at: fields.started_at || (/* @__PURE__ */ new Date()).toISOString(),
3778
3791
  last_iteration_at: fields.last_iteration_at || void 0,
@@ -3786,7 +3799,7 @@ function readRalphState(filePath) {
3786
3799
  }
3787
3800
  function writeRalphState(filePath, state) {
3788
3801
  mkdirSync(dirname(filePath), { recursive: true });
3789
- const promiseYaml = state.completion_promise.includes(":") || state.completion_promise.includes('"') ? `"${state.completion_promise.replace(/"/g, '\\"')}"` : `"${state.completion_promise}"`;
3802
+ const promiseYaml = state.completion_promise === null ? "none" : state.completion_promise.includes(":") || state.completion_promise.includes('"') ? `"${state.completion_promise.replace(/"/g, '\\"')}"` : `"${state.completion_promise}"`;
3790
3803
  const lastIterLine = state.last_iteration_at ? `
3791
3804
  last_iteration_at: "${state.last_iteration_at}"` : "";
3792
3805
  const contextModeLine = state.context_mode ? `
@@ -3868,20 +3881,29 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3868
3881
  const ralphLoop = {
3869
3882
  active: true,
3870
3883
  task: state.task,
3871
- completionPromise: state.completion_promise,
3884
+ completionPromise: state.completion_promise ?? "none",
3872
3885
  maxIterations: state.max_iterations,
3873
3886
  currentIteration: state.iteration,
3874
3887
  startedAt: state.started_at,
3875
- cooldownSeconds: state.cooldown_seconds
3888
+ cooldownSeconds: state.cooldown_seconds,
3889
+ contextMode: state.context_mode || "fresh",
3890
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
3876
3891
  };
3877
3892
  if (!prevRalph?.active) {
3878
3893
  const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
3879
- const prompt = buildRalphPrompt(state.task, state, progressRelPath);
3894
+ const prompt = buildRalphPrompt(state.task, state);
3895
+ const ralphSysPrompt = buildRalphSystemPrompt(state, progressRelPath);
3880
3896
  const existingQueue = getMetadata().messageQueue || [];
3881
3897
  setMetadata((m) => ({
3882
3898
  ...m,
3883
3899
  ralphLoop,
3884
- messageQueue: [...existingQueue, { id: randomUUID$1(), text: prompt, displayText: state.task, createdAt: Date.now() }]
3900
+ messageQueue: [...existingQueue, {
3901
+ id: randomUUID$1(),
3902
+ text: prompt,
3903
+ displayText: state.task,
3904
+ createdAt: Date.now(),
3905
+ ralphSystemPrompt: ralphSysPrompt
3906
+ }]
3885
3907
  }));
3886
3908
  sessionService.updateMetadata(getMetadata());
3887
3909
  sessionService.pushMessage(
@@ -3890,7 +3912,7 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3890
3912
  );
3891
3913
  logger.log(`[svampConfig] Ralph loop started: "${state.task.slice(0, 50)}..."`);
3892
3914
  onRalphLoopActivated?.();
3893
- } else if (prevRalph.currentIteration !== ralphLoop.currentIteration) {
3915
+ } else if (prevRalph.currentIteration !== ralphLoop.currentIteration || prevRalph.task !== ralphLoop.task) {
3894
3916
  setMetadata((m) => ({ ...m, ralphLoop }));
3895
3917
  sessionService.updateMetadata(getMetadata());
3896
3918
  }
@@ -3940,12 +3962,18 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3940
3962
  if ("ralph_loop" in patch) {
3941
3963
  const rl = patch.ralph_loop;
3942
3964
  if (rl && typeof rl === "object" && typeof rl.task === "string") {
3965
+ const contextMode = rl.context_mode === "fresh" || rl.context_mode === "continue" ? rl.context_mode : void 0;
3943
3966
  writeRalphState(ralphStatePath, {
3944
3967
  iteration: rl.current_iteration || 1,
3945
3968
  max_iterations: typeof rl.max_iterations === "number" ? rl.max_iterations : 0,
3946
- completion_promise: rl.completion_promise || "DONE",
3947
- cooldown_seconds: typeof rl.cooldown_seconds === "number" ? rl.cooldown_seconds : 1,
3969
+ completion_promise: rl.completion_promise === "none" || rl.completion_promise === null ? null : rl.completion_promise || "DONE",
3970
+ cooldown_seconds: (() => {
3971
+ const cd = typeof rl.cooldown_seconds === "number" ? rl.cooldown_seconds : 1;
3972
+ const isInfinite = !rl.completion_promise || rl.completion_promise === "none";
3973
+ return isInfinite ? Math.max(1, cd) : cd;
3974
+ })(),
3948
3975
  started_at: rl.started_at || (/* @__PURE__ */ new Date()).toISOString(),
3976
+ context_mode: contextMode,
3949
3977
  task: rl.task.trim()
3950
3978
  });
3951
3979
  ralphChecker();
@@ -3992,64 +4020,128 @@ function buildIterationStatus(iteration, maxIterations, completionPromise) {
3992
4020
  if (completionPromise) {
3993
4021
  return `Ralph iteration ${iterStr} | To stop: output <promise>${completionPromise}</promise>`;
3994
4022
  }
3995
- return `Ralph iteration ${iterStr} | No completion promise set - loop runs until max iterations or manual cancel`;
4023
+ return `Ralph iteration ${iterStr} | Manual stop only`;
3996
4024
  }
3997
- function buildRalphPrompt(task, state, progressFilePath) {
3998
- const iterStr = state.max_iterations > 0 ? `${state.iteration}/${state.max_iterations}` : `${state.iteration}`;
4025
+ function buildRalphSystemPrompt(state, progressFilePath) {
3999
4026
  const isFresh = state.context_mode === "fresh" || !state.context_mode;
4000
4027
  if (isFresh && progressFilePath) {
4001
4028
  return [
4002
- task,
4029
+ "# Ralph Loop \u2014 Fresh Context Mode",
4030
+ "",
4031
+ "You are an autonomous coding agent in an automated loop.",
4032
+ "Each iteration spawns a fresh process \u2014 you have NO memory of previous iterations.",
4033
+ "",
4034
+ "## Your Workflow",
4035
+ "",
4036
+ `1. Read the progress file at \`${progressFilePath}\` (check Patterns section first)`,
4037
+ "2. Check workspace files and git history (`git log --oneline -10`) to understand current state",
4038
+ "3. Pick the next incomplete task and implement it",
4039
+ "4. Run quality checks (tests, typecheck, build \u2014 whatever the project requires)",
4040
+ "5. Commit your changes with a clear commit message",
4041
+ `6. Update \`${progressFilePath}\` with your progress (ALWAYS append, never replace)`,
4003
4042
  "",
4004
- `--- Ralph Loop (iteration ${iterStr}) ---`,
4043
+ "## Progress Report Format",
4005
4044
  "",
4006
- "This is iteration " + iterStr + " of an automated loop. Each iteration runs with",
4007
- "FRESH CONTEXT \u2014 you have NO memory of previous iterations. Your only link to past work is:",
4045
+ `APPEND to \`${progressFilePath}\`:`,
4046
+ "```",
4047
+ "## [Date/Time] \u2014 What was done",
4048
+ "- What was implemented",
4049
+ "- Files changed",
4050
+ "- **Learnings for future iterations:**",
4051
+ " - Patterns discovered",
4052
+ " - Gotchas encountered",
4053
+ " - Useful context",
4054
+ "---",
4055
+ "```",
4008
4056
  "",
4009
- `1. **Progress file**: Read \`${progressFilePath}\` for what was accomplished,`,
4010
- " decisions made, and what to do next.",
4011
- "2. **Workspace files**: Your previous iterations' code changes persist on disk and in git.",
4012
- "3. **Git history**: Run `git log --oneline -10` to see recent commits.",
4057
+ "## Consolidate Patterns",
4013
4058
  "",
4014
- "WORKFLOW:",
4015
- "1. Read the progress file FIRST to understand current state",
4016
- "2. Work on the NEXT incomplete task (one task per iteration)",
4017
- "3. Verify your work (run tests, build, etc.)",
4018
- `4. BEFORE FINISHING: Update \`${progressFilePath}\` with:`,
4019
- " - What you accomplished this iteration",
4020
- " - Key decisions made and why",
4021
- " - Files changed",
4022
- " - What should be done next",
4023
- ' - Any reusable patterns discovered (add to top "Patterns" section)',
4059
+ `If you discover a reusable pattern, add it to the \`## Patterns\` section at the TOP of \`${progressFilePath}\`.`,
4060
+ "Only add patterns that are general and reusable, not task-specific details.",
4024
4061
  "",
4025
- "COMPLETION:",
4026
- `Output <promise>${state.completion_promise}</promise> ONLY when the task is FULLY and PERMANENTLY complete.`,
4027
- "Do NOT output it if there is ANY remaining work.",
4028
- "When in doubt, do NOT output the promise \u2014 the loop will give you another turn."
4062
+ "## Quality Requirements",
4063
+ "",
4064
+ "- Do NOT commit broken code",
4065
+ "- Keep changes focused and minimal",
4066
+ "- Follow existing code patterns",
4067
+ ...state.completion_promise ? [
4068
+ "",
4069
+ "## Stop Condition",
4070
+ "",
4071
+ `To signal completion, output: <promise>${state.completion_promise}</promise>`,
4072
+ "",
4073
+ "ONLY output this when the task is FULLY and PERMANENTLY complete.",
4074
+ "Do NOT output it if there is ANY remaining work.",
4075
+ "When in doubt, do NOT output the promise \u2014 the loop will give you another turn.",
4076
+ "",
4077
+ "CRITICAL: Do NOT output a false promise to exit the loop.",
4078
+ "The loop is designed to continue until genuine completion. Trust the process."
4079
+ ] : [
4080
+ "",
4081
+ "## Continuous Mode",
4082
+ "",
4083
+ "This is a continuous/infinite loop with no completion signal.",
4084
+ "Just do meaningful work each iteration. The loop will continue until manually cancelled.",
4085
+ "Focus on making progress, documenting what you did, and setting up the next iteration."
4086
+ ]
4029
4087
  ].join("\n");
4030
4088
  }
4031
4089
  return [
4032
- task,
4033
- "",
4034
- `--- Ralph Loop (iteration ${iterStr}) ---`,
4090
+ "# Ralph Loop \u2014 Continue Mode",
4035
4091
  "",
4036
4092
  "You are in an automated loop. After this turn ends, the system will automatically",
4037
- "start a new turn with the same task \u2014 you do NOT need to finish everything now.",
4038
- "Your previous work persists in conversation history. Just do meaningful work this",
4039
- "turn and let the loop continue.",
4040
- "",
4041
- "COMPLETION:",
4042
- `Output <promise>${state.completion_promise}</promise> ONLY when the task is FULLY and PERMANENTLY complete.`,
4093
+ "start a new turn with the SAME PROMPT \u2014 you do NOT need to finish everything now.",
4094
+ "Your previous work persists in conversation history and files.",
4095
+ "Just do meaningful work this turn and let the loop continue.",
4043
4096
  "",
4044
- "CRITICAL \u2014 DO NOT output the promise if:",
4045
- '- The task says "continuously", "forever", "keep running", or "until I stop you"',
4046
- "- There is ANY remaining work, follow-up, or next step you could do",
4047
- "- You just finished one pass/cycle of a recurring task (the loop handles repetition)",
4048
- "- You are uncertain whether the task is truly done",
4049
- "",
4050
- "When in doubt: do NOT output the promise. The loop will give you another turn."
4097
+ ...state.completion_promise ? [
4098
+ "## Stop Condition",
4099
+ "",
4100
+ `To signal completion, output: <promise>${state.completion_promise}</promise>`,
4101
+ "",
4102
+ "CRITICAL \u2014 Do NOT output the promise if:",
4103
+ '- The task says "continuously", "forever", "keep running", or "until I stop you"',
4104
+ "- There is ANY remaining work, follow-up, or next step you could do",
4105
+ "- You just finished one pass/cycle of a recurring task (the loop handles repetition)",
4106
+ "- You are uncertain whether the task is truly done",
4107
+ "",
4108
+ "CRITICAL: Do NOT output a false promise to exit the loop, even if you think you're",
4109
+ "stuck or should exit for other reasons. The loop is designed to continue until genuine",
4110
+ "completion. Trust the process."
4111
+ ] : [
4112
+ "## Continuous Mode",
4113
+ "",
4114
+ "This is a continuous/infinite loop with no completion signal.",
4115
+ "Just do meaningful work this turn and let the loop continue.",
4116
+ "The loop will run until manually cancelled."
4117
+ ]
4051
4118
  ].join("\n");
4052
4119
  }
4120
+ function buildRalphPrompt(task, state) {
4121
+ const isFresh = state.context_mode === "fresh" || !state.context_mode;
4122
+ if (isFresh) {
4123
+ return task;
4124
+ }
4125
+ const iterStr = state.max_iterations > 0 ? `${state.iteration}/${state.max_iterations}` : `${state.iteration}`;
4126
+ const reminderLines = [
4127
+ "<system-reminder>",
4128
+ `Ralph Loop \u2014 Iteration ${iterStr} (Continue Mode)`,
4129
+ "Your conversation history persists. Continue from where you left off."
4130
+ ];
4131
+ if (state.completion_promise) {
4132
+ reminderLines.push(`To signal completion, output EXACTLY: <promise>${state.completion_promise}</promise>`);
4133
+ reminderLines.push("Only output the promise when the task is FULLY and PERMANENTLY complete.");
4134
+ reminderLines.push("Do NOT output a false promise to exit the loop.");
4135
+ } else {
4136
+ reminderLines.push("This is a continuous loop \u2014 no completion signal needed. Just do meaningful work.");
4137
+ }
4138
+ reminderLines.push("</system-reminder>");
4139
+ const reminder = reminderLines.join("\n");
4140
+ return task + "\n\n" + reminder;
4141
+ }
4142
+ function getRalphProgressFilePath(directory, sessionId) {
4143
+ return join(getSessionDir(directory, sessionId), "ralph-progress.md");
4144
+ }
4053
4145
  function loadSessionIndex() {
4054
4146
  if (!existsSync$1(SESSION_INDEX_FILE)) return {};
4055
4147
  try {
@@ -4789,12 +4881,19 @@ async function startDaemon(options) {
4789
4881
  } else if (claudeResumeId) {
4790
4882
  const rlState = readRalphState(getRalphStateFilePath(directory, sessionId));
4791
4883
  if (rlState) {
4792
- const promiseMatch = lastAssistantText.match(/<promise>([\s\S]*?)<\/promise>/);
4793
- const promiseFulfilled = promiseMatch && promiseMatch[1].trim().replace(/\s+/g, " ") === rlState.completion_promise;
4884
+ let promiseFulfilled = false;
4885
+ if (rlState.completion_promise) {
4886
+ const promiseMatch = lastAssistantText.match(/<promise>([\s\S]*?)<\/promise>/);
4887
+ promiseFulfilled = !!(promiseMatch && promiseMatch[1].trim().replace(/\s+/g, " ") === rlState.completion_promise);
4888
+ }
4794
4889
  const maxReached = rlState.max_iterations > 0 && rlState.iteration >= rlState.max_iterations;
4795
4890
  if (promiseFulfilled || maxReached) {
4796
4891
  const isFreshMode = rlState.context_mode === "fresh" || !rlState.context_mode;
4797
4892
  removeRalphState(getRalphStateFilePath(directory, sessionId));
4893
+ if (lastSpawnMeta.appendSystemPrompt) {
4894
+ const { appendSystemPrompt: _, ...rest } = lastSpawnMeta;
4895
+ lastSpawnMeta = rest;
4896
+ }
4798
4897
  sessionMetadata = { ...sessionMetadata, ralphLoop: { active: false }, lifecycleState: "idle" };
4799
4898
  sessionService.updateMetadata(sessionMetadata);
4800
4899
  const reason = promiseFulfilled ? `Ralph loop completed at iteration ${rlState.iteration} \u2014 promise "${rlState.completion_promise}" fulfilled.` : `Ralph loop stopped \u2014 max iterations (${rlState.max_iterations}) reached.`;
@@ -4809,7 +4908,28 @@ async function startDaemon(options) {
4809
4908
  isKillingClaude = false;
4810
4909
  }
4811
4910
  claudeResumeId = rlState.original_resume_id;
4812
- spawnClaude(void 0);
4911
+ const progressPath = getRalphProgressFilePath(directory, sessionId);
4912
+ let resumeMessage;
4913
+ try {
4914
+ if (existsSync$1(progressPath)) {
4915
+ const progressContent = readFileSync$1(progressPath, "utf-8").trim();
4916
+ if (progressContent) {
4917
+ resumeMessage = `<system-reminder>
4918
+ The Ralph Loop has completed (${reason}).
4919
+ Below is the progress log from all iterations:
4920
+
4921
+ ${progressContent}
4922
+ </system-reminder>
4923
+
4924
+ The automated loop has finished. Review the progress above and let me know if you need anything else.`;
4925
+ unlinkSync(progressPath);
4926
+ logger.log(`[Session ${sessionId}] Injected progress file content and deleted ${progressPath}`);
4927
+ }
4928
+ }
4929
+ } catch (progressErr) {
4930
+ logger.log(`[Session ${sessionId}] Could not read/delete progress file: ${progressErr.message}`);
4931
+ }
4932
+ spawnClaude(resumeMessage);
4813
4933
  logger.log(`[Session ${sessionId}] Resumed original session ${rlState.original_resume_id}`);
4814
4934
  } catch (err) {
4815
4935
  logger.log(`[Session ${sessionId}] Error resuming original session: ${err.message}`);
@@ -4831,17 +4951,20 @@ async function startDaemon(options) {
4831
4951
  const ralphLoop = {
4832
4952
  active: true,
4833
4953
  task: rlState.task,
4834
- completionPromise: rlState.completion_promise,
4954
+ completionPromise: rlState.completion_promise ?? "none",
4835
4955
  maxIterations: rlState.max_iterations,
4836
4956
  currentIteration: nextIteration,
4837
4957
  startedAt: rlState.started_at,
4838
- cooldownSeconds: rlState.cooldown_seconds
4958
+ cooldownSeconds: rlState.cooldown_seconds,
4959
+ contextMode: rlState.context_mode || "fresh",
4960
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
4839
4961
  };
4840
4962
  sessionMetadata = { ...sessionMetadata, ralphLoop };
4841
4963
  sessionService.updateMetadata(sessionMetadata);
4842
4964
  logger.log(`[Session ${sessionId}] Ralph loop iteration ${nextIteration}${rlState.max_iterations > 0 ? `/${rlState.max_iterations}` : ""}: spawning (${isFreshMode ? "fresh" : "continue"})`);
4843
4965
  const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
4844
- const prompt = buildRalphPrompt(rlState.task, updatedRlState, progressRelPath);
4966
+ const prompt = buildRalphPrompt(rlState.task, updatedRlState);
4967
+ const ralphSysPrompt = buildRalphSystemPrompt(updatedRlState, progressRelPath);
4845
4968
  const cooldownMs = Math.max(200, rlState.cooldown_seconds * 1e3);
4846
4969
  if (isFreshMode) {
4847
4970
  setTimeout(async () => {
@@ -4858,7 +4981,7 @@ async function startDaemon(options) {
4858
4981
  signalProcessing(true);
4859
4982
  sessionService.pushMessage({ type: "message", message: buildIterationStatus(nextIteration, rlState.max_iterations, rlState.completion_promise) }, "event");
4860
4983
  sessionService.pushMessage(rlState.task, "user");
4861
- spawnClaude(prompt);
4984
+ spawnClaude(prompt, { appendSystemPrompt: ralphSysPrompt });
4862
4985
  } catch (err) {
4863
4986
  logger.log(`[Session ${sessionId}] Error in fresh Ralph iteration: ${err.message}`);
4864
4987
  isKillingClaude = false;
@@ -4880,7 +5003,7 @@ async function startDaemon(options) {
4880
5003
  });
4881
5004
  claudeProcess.stdin?.write(stdinMsg + "\n");
4882
5005
  } else {
4883
- spawnClaude(prompt);
5006
+ spawnClaude(prompt, { appendSystemPrompt: ralphSysPrompt });
4884
5007
  }
4885
5008
  }, cooldownMs);
4886
5009
  }
@@ -5171,6 +5294,11 @@ async function startDaemon(options) {
5171
5294
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
5172
5295
  return await restartClaudeHandler();
5173
5296
  },
5297
+ onApplySystemPrompt: async (prompt) => {
5298
+ logger.log(`[Session ${sessionId}] System prompt update requested \u2014 restarting agent`);
5299
+ lastSpawnMeta = { ...lastSpawnMeta, appendSystemPrompt: prompt };
5300
+ return await restartClaudeHandler();
5301
+ },
5174
5302
  onKillSession: () => {
5175
5303
  logger.log(`[Session ${sessionId}] Kill session requested`);
5176
5304
  stopSession(sessionId);
@@ -5309,6 +5437,7 @@ async function startDaemon(options) {
5309
5437
  sessionService.pushMessage(next.displayText || next.text, "user");
5310
5438
  userMessagePending = true;
5311
5439
  turnInitiatedByUser = true;
5440
+ const queueMeta = next.ralphSystemPrompt ? { appendSystemPrompt: next.ralphSystemPrompt } : void 0;
5312
5441
  const rlState = readRalphState(getRalphStateFilePath(directory, sessionId));
5313
5442
  const isRalphFresh = rlState && (rlState.context_mode === "fresh" || !rlState.context_mode);
5314
5443
  if (isRalphFresh && claudeProcess && claudeProcess.exitCode === null) {
@@ -5325,7 +5454,7 @@ async function startDaemon(options) {
5325
5454
  await killAndWaitForExit2(claudeProcess);
5326
5455
  isKillingClaude = false;
5327
5456
  claudeResumeId = void 0;
5328
- spawnClaude(next.text);
5457
+ spawnClaude(next.text, queueMeta);
5329
5458
  } catch (err) {
5330
5459
  logger.log(`[Session ${sessionId}] Error in fresh Ralph queue processing: ${err.message}`);
5331
5460
  isKillingClaude = false;
@@ -5333,7 +5462,7 @@ async function startDaemon(options) {
5333
5462
  }
5334
5463
  })();
5335
5464
  } else if (!claudeProcess || claudeProcess.exitCode !== null) {
5336
- spawnClaude(next.text);
5465
+ spawnClaude(next.text, queueMeta);
5337
5466
  } else {
5338
5467
  const stdinMsg = JSON.stringify({
5339
5468
  type: "user",
@@ -5501,6 +5630,9 @@ async function startDaemon(options) {
5501
5630
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
5502
5631
  return { success: false, message: "Security context updates with restart are not yet supported for this agent type." };
5503
5632
  },
5633
+ onApplySystemPrompt: async () => {
5634
+ return { success: false, message: "System prompt updates with restart are not yet supported for this agent type." };
5635
+ },
5504
5636
  onKillSession: () => {
5505
5637
  logger.log(`[${agentName} Session ${sessionId}] Kill session requested`);
5506
5638
  stopSession(sessionId);
@@ -5692,8 +5824,11 @@ async function startDaemon(options) {
5692
5824
  checkSvampConfig?.();
5693
5825
  const rlState = readRalphState(getRalphStateFilePath(directory, sessionId));
5694
5826
  if (rlState) {
5695
- const promiseMatch = lastAssistantText.match(/<promise>([\s\S]*?)<\/promise>/);
5696
- const promiseFulfilled = promiseMatch && promiseMatch[1].trim().replace(/\s+/g, " ") === rlState.completion_promise;
5827
+ let promiseFulfilled = false;
5828
+ if (rlState.completion_promise) {
5829
+ const promiseMatch = lastAssistantText.match(/<promise>([\s\S]*?)<\/promise>/);
5830
+ promiseFulfilled = !!(promiseMatch && promiseMatch[1].trim().replace(/\s+/g, " ") === rlState.completion_promise);
5831
+ }
5697
5832
  const maxReached = rlState.max_iterations > 0 && rlState.iteration >= rlState.max_iterations;
5698
5833
  if (promiseFulfilled || maxReached) {
5699
5834
  removeRalphState(getRalphStateFilePath(directory, sessionId));
@@ -5709,11 +5844,13 @@ async function startDaemon(options) {
5709
5844
  const ralphLoop = {
5710
5845
  active: true,
5711
5846
  task: rlState.task,
5712
- completionPromise: rlState.completion_promise,
5847
+ completionPromise: rlState.completion_promise ?? "none",
5713
5848
  maxIterations: rlState.max_iterations,
5714
5849
  currentIteration: nextIteration,
5715
5850
  startedAt: rlState.started_at,
5716
- cooldownSeconds: rlState.cooldown_seconds
5851
+ cooldownSeconds: rlState.cooldown_seconds,
5852
+ contextMode: rlState.context_mode || "fresh",
5853
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
5717
5854
  };
5718
5855
  sessionMetadata = { ...sessionMetadata, ralphLoop };
5719
5856
  sessionService.updateMetadata(sessionMetadata);
@@ -5993,13 +6130,15 @@ async function startDaemon(options) {
5993
6130
  if (!currentState) return;
5994
6131
  const isFreshMode = currentState.context_mode === "fresh" || !currentState.context_mode;
5995
6132
  const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
5996
- const prompt = buildRalphPrompt(currentState.task, currentState, progressRelPath);
6133
+ const prompt = buildRalphPrompt(currentState.task, currentState);
6134
+ const ralphSysPrompt = buildRalphSystemPrompt(currentState, progressRelPath);
5997
6135
  await svc.sendMessage(
5998
6136
  JSON.stringify({
5999
6137
  role: "user",
6000
6138
  content: { type: "text", text: prompt },
6001
6139
  meta: {
6002
6140
  sentFrom: "svamp-daemon-ralph-resume",
6141
+ appendSystemPrompt: ralphSysPrompt,
6003
6142
  ...isFreshMode ? { ralphFreshContext: true } : {}
6004
6143
  }
6005
6144
  })
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
2
2
  import os from 'node:os';
3
3
  import { join, resolve } from 'node:path';
4
4
  import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
5
- import { c as connectToHypha, a as registerSessionService } from './run-Bl8OkKyC.mjs';
5
+ import { c as connectToHypha, a as registerSessionService } from './run-DxISzP_V.mjs';
6
6
  import { createServer } from 'node:http';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';
@@ -1058,6 +1058,14 @@ async function registerSessionService(server, sessionId, initialMetadata, initia
1058
1058
  });
1059
1059
  return await callbacks.onUpdateSecurityContext(newSecurityContext);
1060
1060
  },
1061
+ /** Apply a new system prompt and restart the agent process */
1062
+ applySystemPrompt: async (prompt, context) => {
1063
+ authorizeRequest(context, metadata.sharing, "admin");
1064
+ if (!callbacks.onApplySystemPrompt) {
1065
+ throw new Error("System prompt updates are not supported for this session");
1066
+ }
1067
+ return await callbacks.onApplySystemPrompt(prompt);
1068
+ },
1061
1069
  // ── Listener Registration ──
1062
1070
  registerListener: async (callback, context) => {
1063
1071
  authorizeRequest(context, metadata.sharing, "view");
@@ -3872,7 +3880,9 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3872
3880
  maxIterations: state.max_iterations,
3873
3881
  currentIteration: state.iteration,
3874
3882
  startedAt: state.started_at,
3875
- cooldownSeconds: state.cooldown_seconds
3883
+ cooldownSeconds: state.cooldown_seconds,
3884
+ contextMode: state.context_mode || "fresh",
3885
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
3876
3886
  };
3877
3887
  if (!prevRalph?.active) {
3878
3888
  const progressRelPath = `.svamp/${sessionId}/ralph-progress.md`;
@@ -3897,7 +3907,7 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3897
3907
  );
3898
3908
  logger.log(`[svampConfig] Ralph loop started: "${state.task.slice(0, 50)}..."`);
3899
3909
  onRalphLoopActivated?.();
3900
- } else if (prevRalph.currentIteration !== ralphLoop.currentIteration) {
3910
+ } else if (prevRalph.currentIteration !== ralphLoop.currentIteration || prevRalph.task !== ralphLoop.task) {
3901
3911
  setMetadata((m) => ({ ...m, ralphLoop }));
3902
3912
  sessionService.updateMetadata(getMetadata());
3903
3913
  }
@@ -3947,12 +3957,14 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
3947
3957
  if ("ralph_loop" in patch) {
3948
3958
  const rl = patch.ralph_loop;
3949
3959
  if (rl && typeof rl === "object" && typeof rl.task === "string") {
3960
+ const contextMode = rl.context_mode === "fresh" || rl.context_mode === "continue" ? rl.context_mode : void 0;
3950
3961
  writeRalphState(ralphStatePath, {
3951
3962
  iteration: rl.current_iteration || 1,
3952
3963
  max_iterations: typeof rl.max_iterations === "number" ? rl.max_iterations : 0,
3953
3964
  completion_promise: rl.completion_promise || "DONE",
3954
3965
  cooldown_seconds: typeof rl.cooldown_seconds === "number" ? rl.cooldown_seconds : 1,
3955
3966
  started_at: rl.started_at || (/* @__PURE__ */ new Date()).toISOString(),
3967
+ context_mode: contextMode,
3956
3968
  task: rl.task.trim()
3957
3969
  });
3958
3970
  ralphChecker();
@@ -4085,9 +4097,16 @@ function buildRalphPrompt(task, state) {
4085
4097
  return task;
4086
4098
  }
4087
4099
  const iterStr = state.max_iterations > 0 ? `${state.iteration}/${state.max_iterations}` : `${state.iteration}`;
4088
- return task + `
4089
-
4090
- [Ralph iteration ${iterStr} \u2014 to complete: output <promise>${state.completion_promise}</promise> ONLY when truly done]`;
4100
+ const reminder = [
4101
+ "<system-reminder>",
4102
+ `Ralph Loop \u2014 Iteration ${iterStr} (Continue Mode)`,
4103
+ "Your conversation history persists. Continue from where you left off.",
4104
+ `To signal completion, output EXACTLY: <promise>${state.completion_promise}</promise>`,
4105
+ "Only output the promise when the task is FULLY and PERMANENTLY complete.",
4106
+ "Do NOT output a false promise to exit the loop.",
4107
+ "</system-reminder>"
4108
+ ].join("\n");
4109
+ return task + "\n\n" + reminder;
4091
4110
  }
4092
4111
  function getRalphProgressFilePath(directory, sessionId) {
4093
4112
  return join(getSessionDir(directory, sessionId), "ralph-progress.md");
@@ -4902,7 +4921,9 @@ The automated loop has finished. Review the progress above and let me know if yo
4902
4921
  maxIterations: rlState.max_iterations,
4903
4922
  currentIteration: nextIteration,
4904
4923
  startedAt: rlState.started_at,
4905
- cooldownSeconds: rlState.cooldown_seconds
4924
+ cooldownSeconds: rlState.cooldown_seconds,
4925
+ contextMode: rlState.context_mode || "fresh",
4926
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
4906
4927
  };
4907
4928
  sessionMetadata = { ...sessionMetadata, ralphLoop };
4908
4929
  sessionService.updateMetadata(sessionMetadata);
@@ -5239,6 +5260,11 @@ The automated loop has finished. Review the progress above and let me know if yo
5239
5260
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
5240
5261
  return await restartClaudeHandler();
5241
5262
  },
5263
+ onApplySystemPrompt: async (prompt) => {
5264
+ logger.log(`[Session ${sessionId}] System prompt update requested \u2014 restarting agent`);
5265
+ lastSpawnMeta = { ...lastSpawnMeta, appendSystemPrompt: prompt };
5266
+ return await restartClaudeHandler();
5267
+ },
5242
5268
  onKillSession: () => {
5243
5269
  logger.log(`[Session ${sessionId}] Kill session requested`);
5244
5270
  stopSession(sessionId);
@@ -5570,6 +5596,9 @@ The automated loop has finished. Review the progress above and let me know if yo
5570
5596
  sessionMetadata = { ...sessionMetadata, securityContext: newSecurityContext };
5571
5597
  return { success: false, message: "Security context updates with restart are not yet supported for this agent type." };
5572
5598
  },
5599
+ onApplySystemPrompt: async () => {
5600
+ return { success: false, message: "System prompt updates with restart are not yet supported for this agent type." };
5601
+ },
5573
5602
  onKillSession: () => {
5574
5603
  logger.log(`[${agentName} Session ${sessionId}] Kill session requested`);
5575
5604
  stopSession(sessionId);
@@ -5782,7 +5811,9 @@ The automated loop has finished. Review the progress above and let me know if yo
5782
5811
  maxIterations: rlState.max_iterations,
5783
5812
  currentIteration: nextIteration,
5784
5813
  startedAt: rlState.started_at,
5785
- cooldownSeconds: rlState.cooldown_seconds
5814
+ cooldownSeconds: rlState.cooldown_seconds,
5815
+ contextMode: rlState.context_mode || "fresh",
5816
+ lastIterationStartedAt: (/* @__PURE__ */ new Date()).toISOString()
5786
5817
  };
5787
5818
  sessionMetadata = { ...sessionMetadata, ralphLoop };
5788
5819
  sessionService.updateMetadata(sessionMetadata);
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
2
2
  import os from 'node:os';
3
3
  import { join, resolve } from 'node:path';
4
4
  import { mkdirSync, writeFileSync, existsSync, unlinkSync, readFileSync, watch } from 'node:fs';
5
- import { c as connectToHypha, a as registerSessionService } from './run-DA-YBjNw.mjs';
5
+ import { c as connectToHypha, a as registerSessionService } from './run-CBhm4Jop.mjs';
6
6
  import { createServer } from 'node:http';
7
7
  import { spawn } from 'node:child_process';
8
8
  import { createInterface } from 'node:readline';