abtars 0.3.4-alpha.8 → 0.3.4

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 (335) hide show
  1. package/bundle/{_registry.generated-YP5GLSG7.js → _registry.generated-AVR7DK2A.js} +15 -15
  2. package/bundle/{abmind-lazy-7Z44NODV.js → abmind-lazy-E3YCFKQ5.js} +15 -5
  3. package/bundle/abtars-browser.js +4 -4
  4. package/bundle/abtars-cli.js +23 -13
  5. package/bundle/abtars-cli.js.map +2 -2
  6. package/bundle/abtars-restart.js +3 -3
  7. package/bundle/abtars-task.js +3 -3
  8. package/bundle/abtars.js +385 -466
  9. package/bundle/abtars.js.map +4 -4
  10. package/bundle/{acp-raw-client-E6FM45NC.js → acp-raw-client-UCNK3OTU.js} +2 -2
  11. package/bundle/{action-gate-G2V47NHW.js → action-gate-V4FCBHFB.js} +2 -2
  12. package/bundle/{agent-api-adapter-WRGEQ6DV.js → agent-api-adapter-7HEPYSIN.js} +3 -3
  13. package/bundle/{agent-api-rate-limit-WCFXJMGY.js → agent-api-rate-limit-RZSAM3SW.js} +4 -4
  14. package/bundle/{agent-registry-GHNG2PH3.js → agent-registry-46A2R5KP.js} +7 -7
  15. package/bundle/{bootstrap-PZIDBPEJ.js → bootstrap-MIHJJSWU.js} +2 -2
  16. package/bundle/{bridge-lock-transport-4ZH7QTJP.js → bridge-lock-transport-7RSN7OLJ.js} +4 -4
  17. package/bundle/{browser-D3LZV7ZK.js → browser-F6BCWJWW.js} +6 -6
  18. package/bundle/{budget-45QOBDWA.js → budget-WUM3SPKW.js} +3 -3
  19. package/bundle/{capability-JFWX3IQF.js → capability-QVRKGRFC.js} +5 -5
  20. package/bundle/{chunk-YSKCQH6E.js → chunk-2IYJ4I66.js} +2 -2
  21. package/bundle/{chunk-W2R2HFOQ.js → chunk-2NLUT5S2.js} +6 -6
  22. package/bundle/chunk-3BG3AIDP.js +191 -0
  23. package/bundle/chunk-3BG3AIDP.js.map +7 -0
  24. package/bundle/{chunk-OKAQICWY.js → chunk-3GQX34S2.js} +3 -3
  25. package/bundle/{chunk-QROWBWLL.js → chunk-3XZ773BS.js} +2 -2
  26. package/bundle/{chunk-DYBW4XXL.js → chunk-467SRLLR.js} +2 -2
  27. package/bundle/{chunk-374NCXFZ.js → chunk-4AILRHUI.js} +10 -8
  28. package/bundle/chunk-4AILRHUI.js.map +7 -0
  29. package/bundle/{chunk-GPZNXY2U.js → chunk-4S3H4OK7.js} +4 -4
  30. package/bundle/{chunk-NDCRWEEJ.js → chunk-4Y5MJQRE.js} +6 -6
  31. package/bundle/{chunk-FRKW6LWB.js → chunk-55UWKI5C.js} +3 -3
  32. package/bundle/{chunk-7JN2MMU7.js → chunk-5PNJFDSW.js} +8 -8
  33. package/bundle/{chunk-LUNA6PM5.js → chunk-5RVOEFGT.js} +4 -2
  34. package/bundle/{chunk-LUNA6PM5.js.map → chunk-5RVOEFGT.js.map} +2 -2
  35. package/bundle/{chunk-OXTSWQCX.js → chunk-5Y3FJ2Y7.js} +2 -2
  36. package/bundle/{chunk-TMUYFERL.js → chunk-6B5ZFUPD.js} +2 -2
  37. package/bundle/{chunk-65VCEC32.js → chunk-6PA5JBUU.js} +2 -2
  38. package/bundle/{chunk-C7K6VZNY.js → chunk-BNXV7SZI.js} +21 -12
  39. package/bundle/chunk-BNXV7SZI.js.map +7 -0
  40. package/bundle/{chunk-AFREM7FX.js → chunk-CK7YTA2F.js} +2 -2
  41. package/bundle/{chunk-NRUSRJXR.js → chunk-DZJ5QZFD.js} +2 -2
  42. package/bundle/{chunk-YRSMGJFP.js → chunk-E67KESEG.js} +2 -2
  43. package/bundle/{chunk-ZV4IWKDJ.js → chunk-E7XD5UGB.js} +3 -3
  44. package/bundle/{chunk-CXXU3HAU.js → chunk-EAX5ZZUL.js} +63 -39
  45. package/bundle/chunk-EAX5ZZUL.js.map +7 -0
  46. package/bundle/{chunk-PEDX56EL.js → chunk-EFGBM555.js} +2 -2
  47. package/bundle/{chunk-EQSG2CRM.js → chunk-FGYDIX54.js} +22 -15
  48. package/bundle/chunk-FGYDIX54.js.map +7 -0
  49. package/bundle/{chunk-YPAQEQSC.js → chunk-GF6NVNA7.js} +15 -5
  50. package/bundle/chunk-GF6NVNA7.js.map +7 -0
  51. package/bundle/{chunk-UNM3OXHB.js → chunk-HGSHCQ5F.js} +110 -72
  52. package/bundle/{chunk-UNM3OXHB.js.map → chunk-HGSHCQ5F.js.map} +2 -2
  53. package/bundle/{chunk-VXCETPZU.js → chunk-IMIGG5EO.js} +39 -39
  54. package/bundle/chunk-IMIGG5EO.js.map +7 -0
  55. package/bundle/{chunk-P2K2K6XL.js → chunk-ITOFPJAV.js} +44 -32
  56. package/bundle/chunk-ITOFPJAV.js.map +7 -0
  57. package/bundle/{chunk-75ATTOW4.js → chunk-IY6UKLPS.js} +3 -3
  58. package/bundle/{chunk-EUZDKV3C.js → chunk-J4RUFAPK.js} +3 -3
  59. package/bundle/{chunk-HZDLFLRP.js → chunk-J7DRPVMU.js} +35 -5
  60. package/bundle/chunk-J7DRPVMU.js.map +7 -0
  61. package/bundle/{chunk-EGL6UMAO.js → chunk-JG4BKXBN.js} +7 -1
  62. package/bundle/chunk-JG4BKXBN.js.map +7 -0
  63. package/bundle/{chunk-N4EB6LA7.js → chunk-JLWYPGWI.js} +5 -5
  64. package/bundle/{chunk-5QUTMUIK.js → chunk-JXYWDAHD.js} +12 -12
  65. package/bundle/{chunk-GRVWZO4C.js → chunk-KOSFXW2S.js} +24 -3
  66. package/bundle/{chunk-GRVWZO4C.js.map → chunk-KOSFXW2S.js.map} +1 -1
  67. package/bundle/{chunk-M3JEX6L4.js → chunk-L72RIPEC.js} +9 -9
  68. package/bundle/{chunk-TEFZ4JA4.js → chunk-NHPLD3C7.js} +2 -2
  69. package/bundle/{chunk-2KC5G3EA.js → chunk-OWUO5RS3.js} +5 -5
  70. package/bundle/{chunk-4MULJ5SS.js → chunk-OY4Q6AMY.js} +71 -49
  71. package/bundle/chunk-OY4Q6AMY.js.map +7 -0
  72. package/bundle/{chunk-WBTJ2E62.js → chunk-P3NODAHF.js} +2 -5
  73. package/bundle/{chunk-WBTJ2E62.js.map → chunk-P3NODAHF.js.map} +2 -2
  74. package/bundle/{chunk-SMPHE3ZM.js → chunk-PB5GF4FG.js} +215 -163
  75. package/bundle/chunk-PB5GF4FG.js.map +7 -0
  76. package/bundle/{chunk-WYHGNI56.js → chunk-PMD5BLFS.js} +6 -6
  77. package/bundle/{chunk-URQPDCK5.js → chunk-Q66LQMMZ.js} +3 -3
  78. package/bundle/{chunk-IHYKTDIP.js → chunk-SC2Y5NR2.js} +36 -119
  79. package/bundle/chunk-SC2Y5NR2.js.map +7 -0
  80. package/bundle/chunk-SFL4EPCZ.js +555 -0
  81. package/bundle/chunk-SFL4EPCZ.js.map +7 -0
  82. package/bundle/{chunk-LDUOOKQY.js → chunk-SJPUNDZ3.js} +5 -5
  83. package/bundle/{chunk-LDUOOKQY.js.map → chunk-SJPUNDZ3.js.map} +1 -1
  84. package/bundle/{chunk-JQDJPUHM.js → chunk-TWB2ZGVH.js} +2 -2
  85. package/bundle/{chunk-IJT4KWXT.js → chunk-U4U47YE7.js} +2 -2
  86. package/bundle/{chunk-2FAZIA37.js → chunk-W546CU3A.js} +3 -3
  87. package/bundle/chunk-WC5O5KOE.js +211 -0
  88. package/bundle/chunk-WC5O5KOE.js.map +7 -0
  89. package/bundle/{chunk-JNIHEDKF.js → chunk-XPWYDNWL.js} +2 -2
  90. package/bundle/{chunk-GWILHZPT.js → chunk-XRTXYN66.js} +10 -7
  91. package/bundle/{chunk-GWILHZPT.js.map → chunk-XRTXYN66.js.map} +2 -2
  92. package/bundle/{chunk-EFJVUJBE.js → chunk-Y5FEFKGM.js} +6 -6
  93. package/bundle/chunk-YJZE4OK3.js +169 -0
  94. package/bundle/chunk-YJZE4OK3.js.map +7 -0
  95. package/bundle/{chunk-GVM5YU5I.js → chunk-Z4FZPB42.js} +2 -2
  96. package/bundle/{chunk-7BSQ5UQO.js → chunk-ZSIDQ66D.js} +3 -3
  97. package/bundle/{chunk-XX6BGTPO.js → chunk-ZZZCJJEO.js} +4 -4
  98. package/bundle/{commands-OIISYHTD.js → commands-2ZW6CMLC.js} +17 -16
  99. package/bundle/{config-M3P5IOAI.js → config-YMY5YHKN.js} +6 -6
  100. package/bundle/{context-2RJHC2LE.js → context-CL2RSLII.js} +7 -5
  101. package/bundle/context-CL2RSLII.js.map +7 -0
  102. package/bundle/{daemon-TB23FFWY.js → daemon-D7SU63OY.js} +3 -3
  103. package/bundle/{delegation-tools-YATZFKYO.js → delegation-tools-WS7Z56KZ.js} +12 -12
  104. package/bundle/{deploy-T6R45OZJ.js → deploy-AMTVKIMU.js} +2 -2
  105. package/bundle/{deps-WVK553KF.js → deps-T63AVJKJ.js} +3 -3
  106. package/bundle/{direct-api-transport-S2RDH2I7.js → direct-api-transport-QNNY2WWP.js} +51 -32
  107. package/bundle/direct-api-transport-QNNY2WWP.js.map +7 -0
  108. package/bundle/{discord-adapter-UTXUWX3A.js → discord-adapter-ABAD56Y2.js} +21 -20
  109. package/bundle/{discord-adapter-UTXUWX3A.js.map → discord-adapter-ABAD56Y2.js.map} +1 -1
  110. package/bundle/{dns-wakeup-IDOJIXBX.js → dns-wakeup-V3LEFXPE.js} +9 -33
  111. package/bundle/dns-wakeup-V3LEFXPE.js.map +7 -0
  112. package/bundle/{doctor-probes-B54JFIW3.js → doctor-probes-O6YI6XSZ.js} +6 -2
  113. package/bundle/{env-schema-4JXQUOH4.js → env-schema-B5RB32DC.js} +3 -3
  114. package/bundle/{gossip-3C3BSNPN.js → gossip-SKRCPOBS.js} +9 -5
  115. package/bundle/{guardrails-DL7ZSWVN.js → guardrails-64GQ5Y5K.js} +4 -4
  116. package/bundle/{heartbeat-system-MVTRS4GP.js → heartbeat-system-X4MUTKJD.js} +6 -6
  117. package/bundle/{heartbeat-tier3-6KH45CL6.js → heartbeat-tier3-2PTPWEQQ.js} +53 -76
  118. package/bundle/heartbeat-tier3-2PTPWEQQ.js.map +7 -0
  119. package/bundle/{hook-system-M3POLUIB.js → hook-system-YB635OC4.js} +3 -3
  120. package/bundle/{hotskills-FWX4QI7V.js → hotskills-Q75D2DK3.js} +5 -5
  121. package/bundle/{install-OS3CU7NF.js → install-RFKKFSGS.js} +17 -30
  122. package/bundle/install-RFKKFSGS.js.map +7 -0
  123. package/bundle/{install-manifest-5PPWMD2W.js → install-manifest-J7ICPCJN.js} +2 -2
  124. package/bundle/{irc-adapter-PTTZD32W.js → irc-adapter-TVEV4R6H.js} +3 -3
  125. package/bundle/{irc-config-CP7ZMUOX.js → irc-config-M676FOFI.js} +4 -4
  126. package/bundle/{kanban-board-M326B2XJ.js → kanban-board-DLEJUCNN.js} +9 -7
  127. package/bundle/{kanban-channel-IJ52OMNA.js → kanban-channel-XOLUHJZJ.js} +6 -6
  128. package/bundle/kanban-delivery-C4QPBNPX.js +45 -0
  129. package/bundle/kanban-delivery-C4QPBNPX.js.map +7 -0
  130. package/bundle/{lazy-require-KCRVT4SI.js → lazy-require-JKQSALXN.js} +3 -3
  131. package/bundle/{logger-OWCSNYCA.js → logger-3EGHBD4R.js} +2 -2
  132. package/bundle/{main-chat-ZNUZCTNS.js → main-chat-3H63REKK.js} +4 -4
  133. package/bundle/{master-user-HSKM4ZFN.js → master-user-MUBUP3KD.js} +5 -5
  134. package/bundle/{media-utils-3ZYOD7SK.js → media-utils-HUUIALAJ.js} +3 -3
  135. package/bundle/{message-pipeline-AUIUNM5R.js → message-pipeline-GRDRWONR.js} +17 -16
  136. package/bundle/meta.json +2773 -2241
  137. package/bundle/{metrics-collector-L3VPEHII.js → metrics-collector-YMUGY3PI.js} +31 -2
  138. package/bundle/metrics-collector-YMUGY3PI.js.map +7 -0
  139. package/bundle/{model-health-registry-MLEIZSTV.js → model-health-registry-QADMFQFQ.js} +2 -2
  140. package/bundle/{nerve-IGSXBKZZ.js → nerve-QPAEBRKX.js} +3 -3
  141. package/bundle/{notification-BFSIEECG.js → notification-3JICGXWU.js} +6 -6
  142. package/bundle/{openrouter-credits-NTVZDRYM.js → openrouter-credits-7NEIPYJN.js} +3 -3
  143. package/bundle/{orc-tools-TOD4WHTM.js → orc-tools-UZVPONKY.js} +5 -3
  144. package/bundle/{peer-auth-QC4EF2PM.js → peer-auth-RI43DKJE.js} +24 -15
  145. package/bundle/{peer-client-RGEU5HOK.js → peer-client-UITTMWJ2.js} +34 -29
  146. package/bundle/peer-client-UITTMWJ2.js.map +7 -0
  147. package/bundle/{peer-config-TN55LFDC.js → peer-config-URM7DCW6.js} +9 -4
  148. package/bundle/{peer-transport-5VKK2I7P.js → peer-transport-SI7I72DB.js} +12 -10
  149. package/bundle/{phase-transport-FS6NL4A5.js → phase-transport-ESWWACZI.js} +17 -17
  150. package/bundle/{reconcile-CTFCLQRN.js → reconcile-GFDQYNBD.js} +3 -3
  151. package/bundle/{reconciler-NZ4O4BCP.js → reconciler-IEUJXJN2.js} +12 -12
  152. package/bundle/{restore-IFHPI7I7.js → restore-FARTGLQQ.js} +3 -3
  153. package/bundle/{rollback-ANRI3T5Z.js → rollback-GEWPZABG.js} +2 -2
  154. package/bundle/{sandbox-runtime-QROWHDCS.js → sandbox-runtime-DV6E25J6.js} +2 -2
  155. package/bundle/{self-healer-utils-IFAYOQO2.js → self-healer-utils-P4SKNNEM.js} +3 -3
  156. package/bundle/{sha-tracker-ZWBP6CIJ.js → sha-tracker-77SHLYNY.js} +3 -3
  157. package/bundle/{skill-session-VJXTKOKL.js → skill-session-5HSMXY54.js} +3 -3
  158. package/bundle/{skill-stats-JORH5DGM.js → skill-stats-MI3RSWWL.js} +4 -4
  159. package/bundle/{skill-watcher-E4MGLKLS.js → skill-watcher-5L7JE6TN.js} +4 -4
  160. package/bundle/{sleep-BEWAUFCL.js → sleep-I4JFASCY.js} +11 -11
  161. package/bundle/{soul-bundle-VWAVHCZ6.js → soul-bundle-522C3IRH.js} +9 -8
  162. package/bundle/{spin-E3ZDEDKT.js → spin-VHNGNWTD.js} +11 -11
  163. package/bundle/{spin-notifications-SE2HVZI7.js → spin-notifications-7NC5XZEM.js} +5 -5
  164. package/bundle/{spin-types-OIE67MJK.js → spin-types-C5KOQOPD.js} +7 -3
  165. package/bundle/{sse-parser-anthropic-A6R4Z2TB.js → sse-parser-anthropic-MMTVWHLI.js} +3 -3
  166. package/bundle/{sse-parser-responses-HSZY3QGJ.js → sse-parser-responses-3AOFN64C.js} +3 -3
  167. package/bundle/{ssrf-guard-O6SHIK6Q.js → ssrf-guard-U2JA72TC.js} +3 -3
  168. package/bundle/{start-7QZIWO3S.js → start-H5IUFAWF.js} +4 -2
  169. package/bundle/{start-7QZIWO3S.js.map → start-H5IUFAWF.js.map} +2 -2
  170. package/bundle/{stt-LGVPXMVR.js → stt-PSOPPBV4.js} +4 -4
  171. package/bundle/{system-status-FAVNIUFJ.js → system-status-4LYGOFNO.js} +38 -24
  172. package/bundle/system-status-4LYGOFNO.js.map +7 -0
  173. package/bundle/{task-store-W5BFIAIH.js → task-store-MNCW42BW.js} +4 -4
  174. package/bundle/{telegram-adapter-4TX7QWKC.js → telegram-adapter-O6KIZDY6.js} +62 -45
  175. package/bundle/telegram-adapter-O6KIZDY6.js.map +7 -0
  176. package/bundle/{tool-registry-7FK3OQGL.js → tool-registry-JJMWCQKZ.js} +26 -24
  177. package/bundle/{tool-sandbox-4UC6GAKA.js → tool-sandbox-CNL6V6IH.js} +4 -4
  178. package/bundle/{transport-config-KBF5W2DP.js → transport-config-6MB2K2XC.js} +7 -7
  179. package/bundle/tribe-GDTFYJTK.js +111 -0
  180. package/bundle/tribe-GDTFYJTK.js.map +7 -0
  181. package/bundle/{update-CKFP6LBE.js → update-HGQAOC5L.js} +3 -3
  182. package/bundle/{usage-tracker-NXD364VX.js → usage-tracker-SR4BI6ZT.js} +2 -2
  183. package/bundle/{user-registry-35BW4XKM.js → user-registry-4PACZJIJ.js} +4 -4
  184. package/bundle/wire-platform-KKPWNNNQ.js +88 -0
  185. package/bundle/wire-platform-KKPWNNNQ.js.map +7 -0
  186. package/bundle/ws-peer-client-U3NNPOK7.js +370 -0
  187. package/bundle/ws-peer-client-U3NNPOK7.js.map +7 -0
  188. package/package.json +1 -1
  189. package/scripts/abtars-watchdog.sh +1 -5
  190. package/scripts/emergency-deploy.sh +2 -2
  191. package/scripts/emergency-update.sh +36 -37
  192. package/bundle/chunk-374NCXFZ.js.map +0 -7
  193. package/bundle/chunk-4MULJ5SS.js.map +0 -7
  194. package/bundle/chunk-4S554KLW.js +0 -105
  195. package/bundle/chunk-4S554KLW.js.map +0 -7
  196. package/bundle/chunk-C7K6VZNY.js.map +0 -7
  197. package/bundle/chunk-CXXU3HAU.js.map +0 -7
  198. package/bundle/chunk-EGL6UMAO.js.map +0 -7
  199. package/bundle/chunk-EQSG2CRM.js.map +0 -7
  200. package/bundle/chunk-HT2BPTZY.js +0 -241
  201. package/bundle/chunk-HT2BPTZY.js.map +0 -7
  202. package/bundle/chunk-HZDLFLRP.js.map +0 -7
  203. package/bundle/chunk-IHYKTDIP.js.map +0 -7
  204. package/bundle/chunk-IKUZPMVA.js +0 -82
  205. package/bundle/chunk-IKUZPMVA.js.map +0 -7
  206. package/bundle/chunk-P2K2K6XL.js.map +0 -7
  207. package/bundle/chunk-PU5HSKWH.js +0 -257
  208. package/bundle/chunk-PU5HSKWH.js.map +0 -7
  209. package/bundle/chunk-RWRRGE4U.js +0 -72
  210. package/bundle/chunk-RWRRGE4U.js.map +0 -7
  211. package/bundle/chunk-SMPHE3ZM.js.map +0 -7
  212. package/bundle/chunk-VUIX5AGB.js +0 -65
  213. package/bundle/chunk-VUIX5AGB.js.map +0 -7
  214. package/bundle/chunk-VXCETPZU.js.map +0 -7
  215. package/bundle/chunk-YPAQEQSC.js.map +0 -7
  216. package/bundle/context-2RJHC2LE.js.map +0 -7
  217. package/bundle/direct-api-transport-S2RDH2I7.js.map +0 -7
  218. package/bundle/dns-wakeup-IDOJIXBX.js.map +0 -7
  219. package/bundle/heartbeat-tier3-6KH45CL6.js.map +0 -7
  220. package/bundle/install-OS3CU7NF.js.map +0 -7
  221. package/bundle/metrics-collector-L3VPEHII.js.map +0 -7
  222. package/bundle/peer-client-RGEU5HOK.js.map +0 -7
  223. package/bundle/peer-jwt-NCCPXJRX.js +0 -18
  224. package/bundle/stream-single-RFJNUTL6.js +0 -34
  225. package/bundle/stream-single-RFJNUTL6.js.map +0 -7
  226. package/bundle/system-status-FAVNIUFJ.js.map +0 -7
  227. package/bundle/telegram-adapter-4TX7QWKC.js.map +0 -7
  228. package/bundle/user-registry-35BW4XKM.js.map +0 -7
  229. package/bundle/ws-peer-client-AIXCXF7V.js +0 -173
  230. package/bundle/ws-peer-client-AIXCXF7V.js.map +0 -7
  231. /package/bundle/{_registry.generated-YP5GLSG7.js.map → _registry.generated-AVR7DK2A.js.map} +0 -0
  232. /package/bundle/{abmind-lazy-7Z44NODV.js.map → abmind-lazy-E3YCFKQ5.js.map} +0 -0
  233. /package/bundle/{acp-raw-client-E6FM45NC.js.map → acp-raw-client-UCNK3OTU.js.map} +0 -0
  234. /package/bundle/{action-gate-G2V47NHW.js.map → action-gate-V4FCBHFB.js.map} +0 -0
  235. /package/bundle/{agent-api-adapter-WRGEQ6DV.js.map → agent-api-adapter-7HEPYSIN.js.map} +0 -0
  236. /package/bundle/{agent-api-rate-limit-WCFXJMGY.js.map → agent-api-rate-limit-RZSAM3SW.js.map} +0 -0
  237. /package/bundle/{agent-registry-GHNG2PH3.js.map → agent-registry-46A2R5KP.js.map} +0 -0
  238. /package/bundle/{bootstrap-PZIDBPEJ.js.map → bootstrap-MIHJJSWU.js.map} +0 -0
  239. /package/bundle/{bridge-lock-transport-4ZH7QTJP.js.map → bridge-lock-transport-7RSN7OLJ.js.map} +0 -0
  240. /package/bundle/{browser-D3LZV7ZK.js.map → browser-F6BCWJWW.js.map} +0 -0
  241. /package/bundle/{budget-45QOBDWA.js.map → budget-WUM3SPKW.js.map} +0 -0
  242. /package/bundle/{capability-JFWX3IQF.js.map → capability-QVRKGRFC.js.map} +0 -0
  243. /package/bundle/{chunk-YSKCQH6E.js.map → chunk-2IYJ4I66.js.map} +0 -0
  244. /package/bundle/{chunk-W2R2HFOQ.js.map → chunk-2NLUT5S2.js.map} +0 -0
  245. /package/bundle/{chunk-OKAQICWY.js.map → chunk-3GQX34S2.js.map} +0 -0
  246. /package/bundle/{chunk-QROWBWLL.js.map → chunk-3XZ773BS.js.map} +0 -0
  247. /package/bundle/{chunk-DYBW4XXL.js.map → chunk-467SRLLR.js.map} +0 -0
  248. /package/bundle/{chunk-GPZNXY2U.js.map → chunk-4S3H4OK7.js.map} +0 -0
  249. /package/bundle/{chunk-NDCRWEEJ.js.map → chunk-4Y5MJQRE.js.map} +0 -0
  250. /package/bundle/{chunk-FRKW6LWB.js.map → chunk-55UWKI5C.js.map} +0 -0
  251. /package/bundle/{chunk-7JN2MMU7.js.map → chunk-5PNJFDSW.js.map} +0 -0
  252. /package/bundle/{chunk-OXTSWQCX.js.map → chunk-5Y3FJ2Y7.js.map} +0 -0
  253. /package/bundle/{chunk-TMUYFERL.js.map → chunk-6B5ZFUPD.js.map} +0 -0
  254. /package/bundle/{chunk-65VCEC32.js.map → chunk-6PA5JBUU.js.map} +0 -0
  255. /package/bundle/{chunk-AFREM7FX.js.map → chunk-CK7YTA2F.js.map} +0 -0
  256. /package/bundle/{chunk-NRUSRJXR.js.map → chunk-DZJ5QZFD.js.map} +0 -0
  257. /package/bundle/{chunk-YRSMGJFP.js.map → chunk-E67KESEG.js.map} +0 -0
  258. /package/bundle/{chunk-ZV4IWKDJ.js.map → chunk-E7XD5UGB.js.map} +0 -0
  259. /package/bundle/{chunk-PEDX56EL.js.map → chunk-EFGBM555.js.map} +0 -0
  260. /package/bundle/{chunk-75ATTOW4.js.map → chunk-IY6UKLPS.js.map} +0 -0
  261. /package/bundle/{chunk-EUZDKV3C.js.map → chunk-J4RUFAPK.js.map} +0 -0
  262. /package/bundle/{chunk-N4EB6LA7.js.map → chunk-JLWYPGWI.js.map} +0 -0
  263. /package/bundle/{chunk-5QUTMUIK.js.map → chunk-JXYWDAHD.js.map} +0 -0
  264. /package/bundle/{chunk-M3JEX6L4.js.map → chunk-L72RIPEC.js.map} +0 -0
  265. /package/bundle/{chunk-TEFZ4JA4.js.map → chunk-NHPLD3C7.js.map} +0 -0
  266. /package/bundle/{chunk-2KC5G3EA.js.map → chunk-OWUO5RS3.js.map} +0 -0
  267. /package/bundle/{chunk-WYHGNI56.js.map → chunk-PMD5BLFS.js.map} +0 -0
  268. /package/bundle/{chunk-URQPDCK5.js.map → chunk-Q66LQMMZ.js.map} +0 -0
  269. /package/bundle/{chunk-JQDJPUHM.js.map → chunk-TWB2ZGVH.js.map} +0 -0
  270. /package/bundle/{chunk-IJT4KWXT.js.map → chunk-U4U47YE7.js.map} +0 -0
  271. /package/bundle/{chunk-2FAZIA37.js.map → chunk-W546CU3A.js.map} +0 -0
  272. /package/bundle/{chunk-JNIHEDKF.js.map → chunk-XPWYDNWL.js.map} +0 -0
  273. /package/bundle/{chunk-EFJVUJBE.js.map → chunk-Y5FEFKGM.js.map} +0 -0
  274. /package/bundle/{chunk-GVM5YU5I.js.map → chunk-Z4FZPB42.js.map} +0 -0
  275. /package/bundle/{chunk-7BSQ5UQO.js.map → chunk-ZSIDQ66D.js.map} +0 -0
  276. /package/bundle/{chunk-XX6BGTPO.js.map → chunk-ZZZCJJEO.js.map} +0 -0
  277. /package/bundle/{commands-OIISYHTD.js.map → commands-2ZW6CMLC.js.map} +0 -0
  278. /package/bundle/{config-M3P5IOAI.js.map → config-YMY5YHKN.js.map} +0 -0
  279. /package/bundle/{daemon-TB23FFWY.js.map → daemon-D7SU63OY.js.map} +0 -0
  280. /package/bundle/{delegation-tools-YATZFKYO.js.map → delegation-tools-WS7Z56KZ.js.map} +0 -0
  281. /package/bundle/{deploy-T6R45OZJ.js.map → deploy-AMTVKIMU.js.map} +0 -0
  282. /package/bundle/{deps-WVK553KF.js.map → deps-T63AVJKJ.js.map} +0 -0
  283. /package/bundle/{doctor-probes-B54JFIW3.js.map → doctor-probes-O6YI6XSZ.js.map} +0 -0
  284. /package/bundle/{env-schema-4JXQUOH4.js.map → env-schema-B5RB32DC.js.map} +0 -0
  285. /package/bundle/{gossip-3C3BSNPN.js.map → gossip-SKRCPOBS.js.map} +0 -0
  286. /package/bundle/{guardrails-DL7ZSWVN.js.map → guardrails-64GQ5Y5K.js.map} +0 -0
  287. /package/bundle/{heartbeat-system-MVTRS4GP.js.map → heartbeat-system-X4MUTKJD.js.map} +0 -0
  288. /package/bundle/{hook-system-M3POLUIB.js.map → hook-system-YB635OC4.js.map} +0 -0
  289. /package/bundle/{hotskills-FWX4QI7V.js.map → hotskills-Q75D2DK3.js.map} +0 -0
  290. /package/bundle/{install-manifest-5PPWMD2W.js.map → install-manifest-J7ICPCJN.js.map} +0 -0
  291. /package/bundle/{irc-adapter-PTTZD32W.js.map → irc-adapter-TVEV4R6H.js.map} +0 -0
  292. /package/bundle/{irc-config-CP7ZMUOX.js.map → irc-config-M676FOFI.js.map} +0 -0
  293. /package/bundle/{kanban-board-M326B2XJ.js.map → kanban-board-DLEJUCNN.js.map} +0 -0
  294. /package/bundle/{kanban-channel-IJ52OMNA.js.map → kanban-channel-XOLUHJZJ.js.map} +0 -0
  295. /package/bundle/{lazy-require-KCRVT4SI.js.map → lazy-require-JKQSALXN.js.map} +0 -0
  296. /package/bundle/{logger-OWCSNYCA.js.map → logger-3EGHBD4R.js.map} +0 -0
  297. /package/bundle/{main-chat-ZNUZCTNS.js.map → main-chat-3H63REKK.js.map} +0 -0
  298. /package/bundle/{master-user-HSKM4ZFN.js.map → master-user-MUBUP3KD.js.map} +0 -0
  299. /package/bundle/{media-utils-3ZYOD7SK.js.map → media-utils-HUUIALAJ.js.map} +0 -0
  300. /package/bundle/{message-pipeline-AUIUNM5R.js.map → message-pipeline-GRDRWONR.js.map} +0 -0
  301. /package/bundle/{model-health-registry-MLEIZSTV.js.map → model-health-registry-QADMFQFQ.js.map} +0 -0
  302. /package/bundle/{nerve-IGSXBKZZ.js.map → nerve-QPAEBRKX.js.map} +0 -0
  303. /package/bundle/{notification-BFSIEECG.js.map → notification-3JICGXWU.js.map} +0 -0
  304. /package/bundle/{openrouter-credits-NTVZDRYM.js.map → openrouter-credits-7NEIPYJN.js.map} +0 -0
  305. /package/bundle/{orc-tools-TOD4WHTM.js.map → orc-tools-UZVPONKY.js.map} +0 -0
  306. /package/bundle/{peer-auth-QC4EF2PM.js.map → peer-auth-RI43DKJE.js.map} +0 -0
  307. /package/bundle/{peer-config-TN55LFDC.js.map → peer-config-URM7DCW6.js.map} +0 -0
  308. /package/bundle/{peer-jwt-NCCPXJRX.js.map → peer-transport-SI7I72DB.js.map} +0 -0
  309. /package/bundle/{peer-transport-5VKK2I7P.js.map → phase-transport-ESWWACZI.js.map} +0 -0
  310. /package/bundle/{phase-transport-FS6NL4A5.js.map → reconcile-GFDQYNBD.js.map} +0 -0
  311. /package/bundle/{reconciler-NZ4O4BCP.js.map → reconciler-IEUJXJN2.js.map} +0 -0
  312. /package/bundle/{restore-IFHPI7I7.js.map → restore-FARTGLQQ.js.map} +0 -0
  313. /package/bundle/{reconcile-CTFCLQRN.js.map → rollback-GEWPZABG.js.map} +0 -0
  314. /package/bundle/{sandbox-runtime-QROWHDCS.js.map → sandbox-runtime-DV6E25J6.js.map} +0 -0
  315. /package/bundle/{self-healer-utils-IFAYOQO2.js.map → self-healer-utils-P4SKNNEM.js.map} +0 -0
  316. /package/bundle/{rollback-ANRI3T5Z.js.map → sha-tracker-77SHLYNY.js.map} +0 -0
  317. /package/bundle/{skill-session-VJXTKOKL.js.map → skill-session-5HSMXY54.js.map} +0 -0
  318. /package/bundle/{sha-tracker-ZWBP6CIJ.js.map → skill-stats-MI3RSWWL.js.map} +0 -0
  319. /package/bundle/{skill-stats-JORH5DGM.js.map → skill-watcher-5L7JE6TN.js.map} +0 -0
  320. /package/bundle/{skill-watcher-E4MGLKLS.js.map → sleep-I4JFASCY.js.map} +0 -0
  321. /package/bundle/{sleep-BEWAUFCL.js.map → soul-bundle-522C3IRH.js.map} +0 -0
  322. /package/bundle/{soul-bundle-VWAVHCZ6.js.map → spin-VHNGNWTD.js.map} +0 -0
  323. /package/bundle/{spin-notifications-SE2HVZI7.js.map → spin-notifications-7NC5XZEM.js.map} +0 -0
  324. /package/bundle/{spin-E3ZDEDKT.js.map → spin-types-C5KOQOPD.js.map} +0 -0
  325. /package/bundle/{sse-parser-anthropic-A6R4Z2TB.js.map → sse-parser-anthropic-MMTVWHLI.js.map} +0 -0
  326. /package/bundle/{sse-parser-responses-HSZY3QGJ.js.map → sse-parser-responses-3AOFN64C.js.map} +0 -0
  327. /package/bundle/{ssrf-guard-O6SHIK6Q.js.map → ssrf-guard-U2JA72TC.js.map} +0 -0
  328. /package/bundle/{spin-types-OIE67MJK.js.map → stt-PSOPPBV4.js.map} +0 -0
  329. /package/bundle/{stt-LGVPXMVR.js.map → task-store-MNCW42BW.js.map} +0 -0
  330. /package/bundle/{task-store-W5BFIAIH.js.map → tool-registry-JJMWCQKZ.js.map} +0 -0
  331. /package/bundle/{tool-registry-7FK3OQGL.js.map → tool-sandbox-CNL6V6IH.js.map} +0 -0
  332. /package/bundle/{tool-sandbox-4UC6GAKA.js.map → transport-config-6MB2K2XC.js.map} +0 -0
  333. /package/bundle/{transport-config-KBF5W2DP.js.map → update-HGQAOC5L.js.map} +0 -0
  334. /package/bundle/{update-CKFP6LBE.js.map → usage-tracker-SR4BI6ZT.js.map} +0 -0
  335. /package/bundle/{usage-tracker-NXD364VX.js.map → user-registry-4PACZJIJ.js.map} +0 -0
@@ -7,13 +7,14 @@ import {
7
7
  import {
8
8
  init_log_and_swallow,
9
9
  logAndSwallow
10
- } from "./chunk-YSKCQH6E.js";
10
+ } from "./chunk-2IYJ4I66.js";
11
11
  import {
12
12
  abtarsHome,
13
13
  init_paths
14
14
  } from "./chunk-GALQBVKO.js";
15
15
  import {
16
- __esm
16
+ __esm,
17
+ __export
17
18
  } from "./chunk-7K2YZTLD.js";
18
19
 
19
20
  // src/components/atomic-write.ts
@@ -33,6 +34,25 @@ var init_atomic_write = __esm({
33
34
  });
34
35
 
35
36
  // src/components/transport/bridge-lock-transport.ts
37
+ var bridge_lock_transport_exports = {};
38
+ __export(bridge_lock_transport_exports, {
39
+ appendRestartTimestamp: () => appendRestartTimestamp,
40
+ initBridgeLock: () => initBridgeLock,
41
+ readAndClearAcpPids: () => readAndClearAcpPids,
42
+ readAndClearForceSleep: () => readAndClearForceSleep,
43
+ readAndClearRestartReason: () => readAndClearRestartReason,
44
+ readAndClearRestartRequested: () => readAndClearRestartRequested,
45
+ readBridgeLockField: () => readBridgeLockField,
46
+ readLastPromptAt: () => readLastPromptAt,
47
+ readRestartTimestamps: () => readRestartTimestamps,
48
+ trackAcpPid: () => trackAcpPid,
49
+ updateBridgeLockField: () => updateBridgeLockField,
50
+ updateLastHeartbeat: () => updateLastHeartbeat,
51
+ writeForceSleep: () => writeForceSleep,
52
+ writeRestartReason: () => writeRestartReason,
53
+ writeRestartRequested: () => writeRestartRequested,
54
+ writeSleepStatus: () => writeSleepStatus
55
+ });
36
56
  import { readFileSync } from "node:fs";
37
57
  import { join } from "node:path";
38
58
  function trackAcpPid(pid) {
@@ -173,6 +193,7 @@ export {
173
193
  readAndClearForceSleep,
174
194
  initBridgeLock,
175
195
  updateLastHeartbeat,
196
+ bridge_lock_transport_exports,
176
197
  init_bridge_lock_transport
177
198
  };
178
- //# sourceMappingURL=chunk-GRVWZO4C.js.map
199
+ //# sourceMappingURL=chunk-KOSFXW2S.js.map
@@ -2,6 +2,6 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/components/atomic-write.ts", "../src/components/transport/bridge-lock-transport.ts"],
4
4
  "sourcesContent": ["import { writeFileSync, renameSync, openSync, fsyncSync, closeSync, unlinkSync } from \"node:fs\";\n\n/** Atomic write: .tmp \u2192 fsync \u2192 rename. Crash-safe on POSIX. */\nexport function atomicWriteSync(path: string, data: string): void {\n const tmp = path + \".tmp\";\n writeFileSync(tmp, data, \"utf-8\");\n const fd = openSync(tmp, \"r\");\n fsyncSync(fd);\n closeSync(fd);\n renameSync(tmp, path);\n}\n\n/** Clean orphan .tmp files left by crashes. Call on boot. */\nexport function cleanOrphanTmp(path: string): void {\n try { unlinkSync(path + \".tmp\"); } catch { /* no orphan */ }\n}\n", "/**\n * bridge.lock \u2014 single source of truth for bridge runtime state.\n * Fields: pid, startedAt, lastHeartbeat, lastPromptAt, version,\n * sleepStatus, restartReason, restartRequested, forceSleep.\n */\nimport { logAndSwallow } from \"../log-and-swallow.js\";\nimport { readFileSync } from \"node:fs\";\nimport { atomicWriteSync } from \"../atomic-write.js\";\nimport { join } from \"node:path\";\nimport { abtarsHome } from \"../../paths.js\";\nimport { localISO } from \"../../utils/local-time.js\";\n\nexport type SleepStatus = \"awake\" | \"sleeping\" | \"hw_sleep\";\n\n/** Add an ACP child PID to bridge.lock tracking. */\nexport function trackAcpPid(pid: number): void {\n const pids = readBridgeLockField<number[]>(\"acpPids\") ?? [];\n pids.push(pid);\n updateBridgeLockField(\"acpPids\", pids);\n}\n\n/** Read and clear stale ACP PIDs from bridge.lock. */\nexport function readAndClearAcpPids(): number[] {\n const pids = readBridgeLockField<number[]>(\"acpPids\") ?? [];\n if (pids.length) updateBridgeLockField(\"acpPids\", []);\n return pids;\n}\n\n/** Read lastPromptAt from bridge.lock. Returns 0 if missing/unreadable. */\nexport function readLastPromptAt(): number {\n try {\n const lock = JSON.parse(readFileSync(join(abtarsHome(), \"bridge.lock\"), \"utf-8\"));\n return typeof lock.lastPromptAt === \"number\" ? lock.lastPromptAt : 0;\n } catch (err) { logAndSwallow(\"bridge_lock_transport\", \"readLastPromptAt\", err); return 0; }\n}\n\n/** Update a single field in bridge.lock (read-merge-write). */\nexport function updateBridgeLockField(key: string, value: unknown): void {\n const p = join(abtarsHome(), \"bridge.lock\");\n try {\n const lock = JSON.parse(readFileSync(p, \"utf-8\"));\n lock[key] = value;\n atomicWriteSync(p, JSON.stringify(lock));\n } catch (err) { logAndSwallow(\"bridge_lock_transport\", \"op\", err); }\n}\n\n/** Read a field from bridge.lock. Returns null if missing/unreadable. */\nexport function readBridgeLockField<T = unknown>(key: string): T | null {\n try {\n const lock = JSON.parse(readFileSync(join(abtarsHome(), \"bridge.lock\"), \"utf-8\"));\n return lock[key] ?? null;\n } catch (err) { logAndSwallow(\"bridge_lock_transport\", \"readBridgeLockField\", err); return null; }\n}\n\n/** Write restart reason to bridge.lock. */\nexport function writeRestartReason(reason: string): void {\n updateBridgeLockField(\"restartReason\", `${localISO()} ${reason}`);\n}\n\n/** Read and clear restart reason from bridge.lock. */\nexport function readAndClearRestartReason(): string | null {\n const reason = readBridgeLockField<string>(\"restartReason\");\n if (reason) updateBridgeLockField(\"restartReason\", null);\n return reason;\n}\n\n/** Write restart request to bridge.lock. */\nexport function writeRestartRequested(reason: string): void {\n updateBridgeLockField(\"restartRequested\", `${localISO()} ${reason}`);\n}\n\n/** Read and clear restart request from bridge.lock. */\nexport function readAndClearRestartRequested(): string | null {\n const req = readBridgeLockField<string>(\"restartRequested\");\n if (req) updateBridgeLockField(\"restartRequested\", null);\n return req;\n}\n\n/** Update sleep status in bridge.lock. */\nexport function writeSleepStatus(status: SleepStatus): void {\n updateBridgeLockField(\"sleepStatus\", status);\n}\n\n/** Append a restart timestamp to bridge.lock (capped at 10). Used by in-process watchdog circuit breaker. */\nexport function appendRestartTimestamp(): void {\n const ts = readBridgeLockField<number[]>(\"restartTimestamps\") ?? [];\n ts.push(Date.now());\n if (ts.length > 10) ts.splice(0, ts.length - 10);\n updateBridgeLockField(\"restartTimestamps\", ts);\n}\n\n/** Read recent restart timestamps from bridge.lock. */\nexport function readRestartTimestamps(): number[] {\n return readBridgeLockField<number[]>(\"restartTimestamps\") ?? [];\n}\n\n/** Request a forced sleep cycle on the next heartbeat tick.\n * See src/capabilities/sleep/index.ts spawnSleep() + src/components/daily-cycle.ts isDailyCycleDue().\n * Pattern mirrors writeRestartRequested/readAndClearRestartRequested. */\nexport function writeForceSleep(reason: string): void {\n updateBridgeLockField(\"forceSleep\", `${localISO()} ${reason}`);\n}\n\n/** Read and clear the force-sleep request from bridge.lock.\n * Sole deleter: spawnSleep. isDailyCycleDue peeks via readBridgeLockField. */\nexport function readAndClearForceSleep(): string | null {\n const v = readBridgeLockField<string>(\"forceSleep\");\n if (v) updateBridgeLockField(\"forceSleep\", null);\n return v;\n}\n\n/** Initialize bridge.lock with full boot state. Single writer for initial creation. */\nexport interface PrevBridgeState { pid: number | null; lastHeartbeat: number | null }\n\nexport function initBridgeLock(opts: { pid: number; startedAt: number; version: string; argv: string[]; startReason?: string }): PrevBridgeState {\n const p = join(abtarsHome(), \"bridge.lock\");\n let prev: PrevBridgeState = { pid: null, lastHeartbeat: null };\n try {\n // Read existing state (may have watchdogPid from watchdog, or stale pid from previous bridge)\n let existing: Record<string, unknown> = {};\n try { existing = JSON.parse(readFileSync(p, \"utf-8\")); } catch { /* missing or corrupt \u2014 cold boot */ }\n const prevPid = typeof existing.pid === \"number\" ? existing.pid : null;\n prev = { pid: prevPid, lastHeartbeat: typeof existing.lastHeartbeat === \"number\" ? existing.lastHeartbeat : null };\n // Classify boot type from previous heartbeat gap\n let bootType = \"cold\";\n if (prev.lastHeartbeat) {\n const gapS = (Date.now() - prev.lastHeartbeat) / 1000;\n if (gapS < 300) bootType = \"darkwake\";\n else if (gapS <= 7200) bootType = \"short-outage\";\n else bootType = \"long-outage\";\n }\n // Merge: preserve watchdogPid from watchdog or env var\n const wdPid = Number(process.env.ABTARS_WATCHDOG_PID) || existing.watchdogPid || null;\n atomicWriteSync(p, JSON.stringify({\n pid: opts.pid, watchdogPid: wdPid, startedAt: opts.startedAt, version: opts.version,\n sleepStatus: \"awake\", argv: opts.argv, lastHeartbeat: Date.now(), startReason: opts.startReason ?? \"unknown\", bootType,\n }));\n } catch (err) { logAndSwallow(\"bridge_lock_transport\", \"op\", err); }\n return prev;\n}\n\n/** Update lastHeartbeat timestamp in bridge.lock (called every tick). */\nexport function updateLastHeartbeat(): void {\n updateBridgeLockField(\"lastHeartbeat\", Date.now());\n}\n"],
5
- "mappings": "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",
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -9,15 +9,15 @@ import {
9
9
  sessionType,
10
10
  typeAgent,
11
11
  typeLabel
12
- } from "./chunk-C7K6VZNY.js";
12
+ } from "./chunk-BNXV7SZI.js";
13
13
  import {
14
14
  getMasterUserId,
15
15
  init_master_user
16
- } from "./chunk-AFREM7FX.js";
16
+ } from "./chunk-CK7YTA2F.js";
17
17
  import {
18
18
  init_user_registry,
19
19
  loadUsers
20
- } from "./chunk-ZV4IWKDJ.js";
20
+ } from "./chunk-E7XD5UGB.js";
21
21
  import {
22
22
  init_kanban_board,
23
23
  isUnblocked,
@@ -28,17 +28,17 @@ import {
28
28
  kanbanList,
29
29
  kanbanRetryOrFail,
30
30
  kanbanRunning
31
- } from "./chunk-EQSG2CRM.js";
31
+ } from "./chunk-FGYDIX54.js";
32
32
  import {
33
33
  init_log_and_swallow,
34
34
  logAndSwallow
35
- } from "./chunk-YSKCQH6E.js";
35
+ } from "./chunk-2IYJ4I66.js";
36
36
  import {
37
37
  init_logger,
38
38
  logDebug,
39
39
  logInfo,
40
40
  logWarn
41
- } from "./chunk-GWILHZPT.js";
41
+ } from "./chunk-XRTXYN66.js";
42
42
  import {
43
43
  init_paths,
44
44
  paths_exports
@@ -380,7 +380,7 @@ __export(spin_exports, {
380
380
  });
381
381
  async function fireCallback(peerName, taskId, status, result, error, artifacts, tokensUsed) {
382
382
  try {
383
- const { getPeerTransport } = await import("./peer-transport-5VKK2I7P.js");
383
+ const { getPeerTransport } = await import("./peer-transport-SI7I72DB.js");
384
384
  const transport = getPeerTransport();
385
385
  const payload = { action: "callback", task_id: taskId, status, result_summary: result, error, tokens_used: tokensUsed ?? 0 };
386
386
  if (artifacts?.length) payload.artifacts = artifacts;
@@ -1069,7 +1069,7 @@ var init_spin = __esm({
1069
1069
  async pollRemoteCards() {
1070
1070
  const remoteCards = kanbanList("running", "status").filter((c) => c.type === "remote");
1071
1071
  if (remoteCards.length === 0) return;
1072
- const { getPeerTransport } = await import("./peer-transport-5VKK2I7P.js");
1072
+ const { getPeerTransport } = await import("./peer-transport-SI7I72DB.js");
1073
1073
  const transport = getPeerTransport();
1074
1074
  const REMOTE_MAX_AGE_MS = 15 * 60 * 1e3;
1075
1075
  for (const card of remoteCards) {
@@ -1119,4 +1119,4 @@ export {
1119
1119
  spin_exports,
1120
1120
  init_spin
1121
1121
  };
1122
- //# sourceMappingURL=chunk-M3JEX6L4.js.map
1122
+ //# sourceMappingURL=chunk-L72RIPEC.js.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  init_log_and_swallow,
5
5
  logAndSwallow
6
- } from "./chunk-YSKCQH6E.js";
6
+ } from "./chunk-2IYJ4I66.js";
7
7
  import {
8
8
  abtarsHome,
9
9
  init_paths
@@ -81,4 +81,4 @@ export {
81
81
  _getStats,
82
82
  _reset
83
83
  };
84
- //# sourceMappingURL=chunk-TEFZ4JA4.js.map
84
+ //# sourceMappingURL=chunk-NHPLD3C7.js.map
@@ -3,17 +3,17 @@
3
3
  import {
4
4
  getEnv,
5
5
  init_env_schema
6
- } from "./chunk-65VCEC32.js";
6
+ } from "./chunk-6PA5JBUU.js";
7
7
  import {
8
8
  init_log_and_swallow,
9
9
  logAndSwallow
10
- } from "./chunk-YSKCQH6E.js";
10
+ } from "./chunk-2IYJ4I66.js";
11
11
  import {
12
12
  init_logger,
13
13
  logDebug,
14
14
  logInfo,
15
15
  logWarn
16
- } from "./chunk-GWILHZPT.js";
16
+ } from "./chunk-XRTXYN66.js";
17
17
  import {
18
18
  abtarsHome,
19
19
  init_paths
@@ -362,7 +362,7 @@ var BrowserTool = class {
362
362
  if (getEnv().ssrfCheck) {
363
363
  try {
364
364
  const { hostname } = new URL(url);
365
- const { isPrivateHost } = await import("./ssrf-guard-O6SHIK6Q.js");
365
+ const { isPrivateHost } = await import("./ssrf-guard-U2JA72TC.js");
366
366
  if (await isPrivateHost(hostname)) {
367
367
  return { success: false, error: `Blocked: "${hostname}" resolves to a private/internal IP address` };
368
368
  }
@@ -757,4 +757,4 @@ export {
757
757
  BrowserIpcServer,
758
758
  DomainAllowlist
759
759
  };
760
- //# sourceMappingURL=chunk-2KC5G3EA.js.map
760
+ //# sourceMappingURL=chunk-OWUO5RS3.js.map
@@ -1,11 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __bundleCreateRequire } from 'node:module'; import { fileURLToPath as __bundleFileURLToPath } from 'node:url'; import { dirname as __bundleDirname } from 'node:path'; const require = __bundleCreateRequire(import.meta.url); const __chunk_filename = __bundleFileURLToPath(import.meta.url); const __chunk_dirname = __bundleDirname(__chunk_filename);
3
+ import {
4
+ init_peer_config,
5
+ peer_config_exports
6
+ } from "./chunk-3BG3AIDP.js";
7
+ import {
8
+ init_peer_auth,
9
+ peer_auth_exports
10
+ } from "./chunk-WC5O5KOE.js";
3
11
  import {
4
12
  abtarsHome,
5
13
  init_paths
6
14
  } from "./chunk-GALQBVKO.js";
7
15
  import {
8
- __require
16
+ __require,
17
+ __toCommonJS
9
18
  } from "./chunk-7K2YZTLD.js";
10
19
 
11
20
  // src/cli/commands/doctor-probes.ts
@@ -15,6 +24,7 @@ import { join } from "node:path";
15
24
  import { homedir } from "node:os";
16
25
  var home = abtarsHome();
17
26
  var configDir = join(home, "config");
27
+ var TTL_MS = 18e4;
18
28
  function readJson(path) {
19
29
  try {
20
30
  return JSON.parse(readFileSync(path, "utf-8"));
@@ -219,9 +229,9 @@ async function probeSha() {
219
229
  if (existsSync(join(configDir, "sha-policy.json"))) return { name: "sha", status: "ok", detail: "rules loaded" };
220
230
  return { name: "sha", status: "skipped", detail: "no healer rules configured" };
221
231
  }
222
- async function probeAgentApi() {
232
+ async function probeA2a() {
223
233
  const env = readEnv();
224
- if (env.get("ENABLE_AGENT_API") !== "true") return { name: "agent-api", status: "skipped", detail: "not enabled" };
234
+ if (env.get("ENABLE_AGENT_API") !== "true") return { name: "a2a", status: "skipped", detail: "not enabled" };
225
235
  const port = parseInt(env.get("AGENT_API_PORT") || "7100", 10);
226
236
  try {
227
237
  const { createConnection } = await import("node:net");
@@ -236,68 +246,80 @@ async function probeAgentApi() {
236
246
  reject(new Error("timeout"));
237
247
  });
238
248
  });
239
- return { name: "agent-api", status: "ok", detail: `:${port}` };
249
+ return { name: "a2a", status: "ok", detail: `${port}` };
240
250
  } catch {
241
- return { name: "agent-api", status: "failed", detail: `:${port} not listening` };
251
+ return { name: "a2a", status: "failed", detail: `${port} not listening` };
242
252
  }
243
253
  }
244
254
  async function probePeers() {
245
255
  const peersPath = join(configDir, "peers.json");
246
256
  const peers = readJson(peersPath);
247
257
  if (!peers) return { name: "peers", status: "skipped", detail: "peers.json missing" };
248
- const peerCount = Object.keys(peers.peers ?? {}).length;
249
- if (peerCount === 0) return { name: "peers", status: "ok", detail: "no peers configured" };
250
- const lock = readJson(join(home, "bridge.lock"));
251
- const gossipAge = lock?.lastGossipBroadcast ? ago(Date.now() - lock.lastGossipBroadcast) : "unknown";
252
- return { name: "peers", status: "ok", detail: `${peerCount} configured, gossip: ${gossipAge}` };
258
+ if (!peers.self?.signingKey) return { name: "peers", status: "failed", detail: "self.signingKey missing \u2014 run: abtars install" };
259
+ const peerEntries = Object.entries(peers.peers ?? {});
260
+ const peerCount = peerEntries.length;
261
+ if (peerCount === 0) return { name: "peers", status: "skipped", detail: "no peers (solo)" };
262
+ const missingKey = peerEntries.filter(([, e]) => !e.verifyKey).map(([n]) => n);
263
+ if (missingKey.length > 0) return { name: "peers", status: "failed", detail: `missing verifyKey: ${missingKey.join(", ")}` };
264
+ return { name: "peers", status: "ok", detail: `${peerCount} enrolled (all keys valid)` };
253
265
  }
254
- async function probeTls() {
266
+ async function probeIdentity() {
255
267
  const env = readEnv();
256
- if (env.get("ENABLE_AGENT_API") !== "true") return { name: "tls", status: "skipped", detail: "agent-api disabled" };
257
- const certExists = existsSync(join(configDir, "identity.crt"));
258
- const keyExists = existsSync(join(configDir, "identity.tls.key"));
259
- if (certExists && keyExists) return { name: "tls", status: "ok", detail: "certs present" };
260
- const missing = [!certExists && "identity.crt", !keyExists && "identity.tls.key"].filter(Boolean);
261
- return { name: "tls", status: "failed", detail: `missing: ${missing.join(", ")}` };
262
- }
263
- async function probeA2a() {
264
- const peersPath = join(configDir, "peers.json");
265
- const peers = readJson(peersPath);
266
- if (!peers?.self?.udpPort) return { name: "a2a", status: "skipped", detail: "no gossip port configured" };
267
- const port = peers.self.udpPort;
268
+ if (env.get("ENABLE_AGENT_API") !== "true") return { name: "identity", status: "skipped", detail: "a2a disabled" };
269
+ const certPath = join(configDir, "identity.crt");
270
+ const keyPath = join(configDir, "identity.tls.key");
271
+ const certExists = existsSync(certPath);
272
+ const keyExists = existsSync(keyPath);
273
+ if (!certExists || !keyExists) {
274
+ const missing = [!certExists && "identity.crt", !keyExists && "identity.tls.key"].filter(Boolean);
275
+ return { name: "identity", status: "failed", detail: `missing: ${missing.join(", ")}` };
276
+ }
268
277
  try {
269
- const dgram = await import("node:dgram");
270
- const { createHmac } = await import("node:crypto");
271
- const key = peers.gossipSecret ?? Object.values(peers.peers ?? {})[0]?.token ?? "default";
272
- const payload = JSON.stringify({ type: "ping", name: "__doctor__" });
273
- const sig = createHmac("sha256", key).update(payload).digest("base64url").slice(0, 16);
274
- const ping = Buffer.from(`${payload}|${sig}`);
275
- const alive = await new Promise((resolve) => {
276
- const sock = dgram.createSocket("udp4");
277
- const timer = setTimeout(() => {
278
- sock.close();
279
- resolve(false);
280
- }, 500);
281
- sock.on("message", () => {
282
- clearTimeout(timer);
278
+ const { loadPeerConfig, deriveVerifyKey } = (init_peer_config(), __toCommonJS(peer_config_exports));
279
+ const { verifyServerCert } = (init_peer_auth(), __toCommonJS(peer_auth_exports));
280
+ const config = loadPeerConfig();
281
+ const expectedVerifyKey = deriveVerifyKey(config.self.signingKey);
282
+ const certPem = readFileSync(certPath, "utf-8");
283
+ if (!verifyServerCert(certPem, expectedVerifyKey)) {
284
+ return { name: "identity", status: "failed", detail: "cert pubkey mismatch \u2014 re-run: abtars install --force" };
285
+ }
286
+ return { name: "identity", status: "ok", detail: "cert matches signing key" };
287
+ } catch {
288
+ return { name: "identity", status: "ok", detail: "cert present (key-match skipped)" };
289
+ }
290
+ }
291
+ async function probeGossip() {
292
+ const env = readEnv();
293
+ if (env.get("ENABLE_AGENT_API") !== "true") return { name: "gossip", status: "skipped", detail: "a2a disabled" };
294
+ const peers = readJson(join(configDir, "peers.json"));
295
+ const peerCount = Object.keys(peers?.peers ?? {}).length;
296
+ if (peerCount === 0) return { name: "gossip", status: "skipped", detail: "no peers (solo)" };
297
+ if (!peers?.self?.signingKey) return { name: "gossip", status: "failed", detail: "self.signingKey missing \u2014 Ed25519 gossip requires identity" };
298
+ const port = parseInt(env.get("GOSSIP_PORT") || "5355", 10);
299
+ const inUse = await new Promise((resolve) => {
300
+ import("node:dgram").then(({ createSocket }) => {
301
+ const sock = createSocket("udp4");
302
+ sock.once("error", (err) => {
283
303
  sock.close();
284
- resolve(true);
304
+ resolve(err.code === "EADDRINUSE");
285
305
  });
286
- sock.on("error", () => {
287
- clearTimeout(timer);
306
+ sock.bind(port, "0.0.0.0", () => {
288
307
  sock.close();
289
308
  resolve(false);
290
309
  });
291
- sock.send(ping, port, "127.0.0.1");
292
- });
293
- return { name: "a2a", status: alive ? "ok" : "failed", detail: alive ? `UDP :${port} alive` : `UDP :${port} no response` };
294
- } catch {
295
- return { name: "a2a", status: "failed", detail: "UDP probe error" };
296
- }
310
+ }).catch(() => resolve(false));
311
+ });
312
+ if (!inUse) return { name: "gossip", status: "failed", detail: `${port} not listening` };
313
+ const lock = readJson(join(home, "bridge.lock"));
314
+ const last = typeof lock?.lastGossipBroadcast === "number" ? lock.lastGossipBroadcast : 0;
315
+ if (!last) return { name: "gossip", status: "ok", detail: `${port} / no broadcast yet` };
316
+ const age = Date.now() - last;
317
+ if (age > TTL_MS) return { name: "gossip", status: "failed", detail: `${port} / stale (${ago(age)})` };
318
+ return { name: "gossip", status: "ok", detail: `${port} / last broadcast ${ago(age)}` };
297
319
  }
298
320
  async function probeMind() {
299
321
  try {
300
- const { loadAbmind } = await import("./abmind-lazy-7Z44NODV.js");
322
+ const { loadAbmind } = await import("./abmind-lazy-E3YCFKQ5.js");
301
323
  const mod = await loadAbmind();
302
324
  if (!mod) return { name: "mind", status: "skipped", detail: "abmind not installed" };
303
325
  return { name: "mind", status: "ok", detail: "abmind loaded (in-process)" };
@@ -312,7 +334,7 @@ async function runAllProbes() {
312
334
  Promise.all([probeHeartbeat()].map((p) => timedProbe(() => p))),
313
335
  Promise.all([probeTransport(), probeSpin(), probeKanban(), probeSkills(), probeSha()].map((p) => timedProbe(() => p))),
314
336
  Promise.all([probeMind()].map((p) => timedProbe(() => p))),
315
- Promise.all([probeAgentApi(), probePeers(), probeTls(), probeA2a()].map((p) => timedProbe(() => p)))
337
+ Promise.all([probeA2a(), probePeers(), probeIdentity(), probeGossip()].map((p) => timedProbe(() => p)))
316
338
  ]);
317
339
  return { version: "1.0", totalMs: Date.now() - start, layers: { body, heart, brain, soul, tribe } };
318
340
  }
@@ -501,4 +523,4 @@ export {
501
523
  renderHuman,
502
524
  renderJson
503
525
  };
504
- //# sourceMappingURL=chunk-4MULJ5SS.js.map
526
+ //# sourceMappingURL=chunk-OY4Q6AMY.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/commands/doctor-probes.ts"],
4
+ "sourcesContent": ["/**\n * doctor-probes.ts \u2014 structured health probes grouped by subsystem layer.\n * Replaces scripts/doctor.sh entirely.\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { abtarsHome } from \"../../paths.js\";\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ProbeResult {\n name: string;\n status: \"ok\" | \"failed\" | \"skipped\";\n detail?: string;\n ms?: number;\n}\n\nexport interface FixResult {\n probe: string;\n action: string;\n success: boolean;\n}\n\nexport type LayerName = \"body\" | \"heart\" | \"brain\" | \"soul\" | \"tribe\";\n\nexport interface DoctorOutput {\n version: \"1.0\";\n totalMs: number;\n layers: Record<LayerName, ProbeResult[]>;\n fixes?: FixResult[];\n}\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst home = abtarsHome();\nconst configDir = join(home, \"config\");\nconst TTL_MS = 180_000; // gossip: 3 missed 60s broadcasts \u2192 stale (matches gossip.ts)\n\nfunction readJson(path: string): any | null {\n try { return JSON.parse(readFileSync(path, \"utf-8\")); } catch { return null; }\n}\n\nfunction readEnv(): Map<string, string> {\n const envPath = join(configDir, \".env\");\n const map = new Map<string, string>();\n if (!existsSync(envPath)) return map;\n for (const line of readFileSync(envPath, \"utf-8\").split(\"\\n\")) {\n const m = line.match(/^([A-Z_]+)=(.*)$/);\n if (m) map.set(m[1]!, m[2]!.replace(/^[\"']|[\"']$/g, \"\"));\n }\n return map;\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\nfunction ago(ms: number): string {\n const s = Math.round(ms / 1000);\n if (s < 60) return `${s}s ago`;\n return `${Math.round(s / 60)}m ago`;\n}\n\nasync function timedProbe(fn: () => Promise<ProbeResult>): Promise<ProbeResult> {\n const start = Date.now();\n try {\n const r = await fn();\n r.ms = r.ms ?? (Date.now() - start);\n return r;\n } catch (err) {\n return { name: \"unknown\", status: \"failed\", detail: String(err), ms: Date.now() - start };\n }\n}\n\n// \u2500\u2500 Body Probes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function probePlatforms(): Promise<ProbeResult> {\n const { readSecret, initSecretsKey } = await import(\"../../components/secrets.js\");\n initSecretsKey();\n\n const results: Array<{ name: string; status: \"ok\" | \"failed\" | \"skipped\"; detail: string }> = [];\n\n // Telegram: read token, call getMe\n const telegramToken = readSecret(\"TELEGRAM_BOT_TOKEN\") ?? readSecret(\"TELEGRAM_TOKEN\");\n if (telegramToken) {\n const r = await verifyTelegram(telegramToken);\n results.push({ name: \"telegram\", ...r });\n }\n\n // Discord: read token, call gateway\n const discordToken = readSecret(\"DISCORD_BOT_TOKEN\") ?? readSecret(\"DISCORD_TOKEN\");\n if (discordToken) {\n const r = await verifyDiscord(discordToken);\n results.push({ name: \"discord\", ...r });\n }\n\n // IRC: skip real verification (connection-based), just check if configured\n const ircServer = readSecret(\"IRC_SERVER\");\n if (ircServer) {\n results.push({ name: \"irc\", status: \"ok\", detail: \"server configured (connection not verified)\" });\n }\n\n if (results.length === 0) return { name: \"platforms\", status: \"skipped\", detail: \"no platform configured\" };\n\n const failed = results.filter(r => r.status === \"failed\");\n const skipped = results.filter(r => r.status === \"skipped\");\n const allOk = failed.length === 0 && skipped.length === 0;\n const status = allOk ? \"ok\" : failed.length > 0 ? \"failed\" : \"ok\";\n const detail = results.map(r => `${r.name}: ${r.status}${r.detail ? ` (${r.detail})` : \"\"}`).join(\", \");\n return { name: \"platforms\", status, detail };\n}\n\nasync function verifyTelegram(token: string): Promise<{ status: \"ok\" | \"failed\" | \"skipped\"; detail: string }> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`, { signal: controller.signal });\n clearTimeout(timeout);\n if (res.ok) return { status: \"ok\", detail: \"getMe ok\" };\n if (res.status === 401 || res.status === 403) return { status: \"failed\", detail: \"invalid token\" };\n return { status: \"skipped\", detail: `http ${res.status}` };\n } catch {\n return { status: \"skipped\", detail: \"unreachable\" };\n }\n}\n\nasync function verifyDiscord(token: string): Promise<{ status: \"ok\" | \"failed\" | \"skipped\"; detail: string }> {\n try {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n const res = await fetch(\"https://discord.com/api/v10/users/@me\", {\n headers: { \"Authorization\": `Bot ${token}` },\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (res.ok) return { status: \"ok\", detail: \"gateway ok\" };\n if (res.status === 401 || res.status === 403) return { status: \"failed\", detail: \"invalid token\" };\n return { status: \"skipped\", detail: `http ${res.status}` };\n } catch {\n return { status: \"skipped\", detail: \"unreachable\" };\n }\n}\n\nasync function probeDashboard(): Promise<ProbeResult> {\n const env = readEnv();\n if (env.get(\"ENABLE_DASHBOARD\") !== \"true\") return { name: \"dashboard\", status: \"skipped\", detail: \"not enabled\" };\n const port = env.get(\"DASHBOARD_PORT\") || env.get(\"WEB_PORT\") || \"3000\";\n try {\n const res = await fetch(`http://127.0.0.1:${port}/`, { signal: AbortSignal.timeout(3000) });\n return { name: \"dashboard\", status: res.ok ? \"ok\" : \"failed\", detail: `:${port}` };\n } catch {\n return { name: \"dashboard\", status: \"failed\", detail: `:${port} unreachable` };\n }\n}\n\nasync function probeSecurity(): Promise<ProbeResult> {\n const env = readEnv();\n const mode = env.get(\"SECURITY_MODE\") || \"off\";\n const validModes = [\"off\", \"guardrails\", \"seatbelt\", \"docker\"];\n if (!validModes.includes(mode)) return { name: \"security\", status: \"failed\", detail: `invalid mode: ${mode}` };\n\n // Check secret file perms\n const secretDir = join(home, \"secret\");\n let permIssues = 0;\n if (existsSync(secretDir)) {\n for (const f of readdirSync(secretDir)) {\n const st = statSync(join(secretDir, f));\n if (st.isFile() && (st.mode & 0o777) !== 0o600) permIssues++;\n }\n }\n\n const parts = [mode];\n if (existsSync(join(home, \"auth\", \"rules.json\"))) parts.push(\"ActionGate\");\n if (permIssues > 0) return { name: \"security\", status: \"failed\", detail: `${mode}, ${permIssues} file(s) not 600` };\n return { name: \"security\", status: \"ok\", detail: parts.join(\", \") };\n}\n\nasync function probeWatchdog(): Promise<ProbeResult> {\n const lock = readJson(join(home, \"bridge.lock\"));\n if (!lock) return { name: \"watchdog\", status: \"failed\", detail: \"bridge.lock missing\" };\n\n const bridgePid = lock.pid ?? 0;\n const wdPid = lock.watchdogPid ?? 0;\n const bridgeAlive = bridgePid > 0 && pidAlive(bridgePid);\n const wdAlive = wdPid > 0 && pidAlive(wdPid);\n\n if (bridgeAlive && wdAlive) return { name: \"watchdog\", status: \"ok\", detail: `bridge:${bridgePid}, wd:${wdPid}` };\n if (!bridgeAlive && !wdAlive) return { name: \"watchdog\", status: \"failed\", detail: `bridge:${bridgePid} dead, wd:${wdPid} dead` };\n if (!wdAlive) return { name: \"watchdog\", status: \"failed\", detail: `bridge:${bridgePid} alive, wd:${wdPid} dead (unprotected)` };\n return { name: \"watchdog\", status: \"failed\", detail: `bridge:${bridgePid} dead, wd:${wdPid} alive (will restart)` };\n}\n\n// \u2500\u2500 Heart Probes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function probeHeartbeat(): Promise<ProbeResult> {\n const lock = readJson(join(home, \"bridge.lock\"));\n if (!lock?.lastHeartbeat) return { name: \"heartbeat\", status: \"skipped\", detail: \"no bridge.lock\" };\n const ageMs = Date.now() - lock.lastHeartbeat;\n if (ageMs > 120_000) return { name: \"heartbeat\", status: \"failed\", detail: `stale (${ago(ageMs)})` };\n return { name: \"heartbeat\", status: \"ok\", detail: ago(ageMs) };\n}\n\n// #1261: single-bridge invariant \u2014 catches duplicate-bridge regressions at runtime.\n// pgrep counts the bridge processes. >1 means a second bridge is running (likely orphaned).\nasync function probeSingleBridge(): Promise<ProbeResult> {\n const { spawnSync } = await import(\"node:child_process\");\n const pgrep = spawnSync(\"pgrep\", [\"-f\", \"app/bundle/abtars.js\"], { encoding: \"utf-8\" });\n const pids = pgrep.stdout ? pgrep.stdout.trim().split(\"\\n\").filter(Boolean) : [];\n if (pids.length === 0) return { name: \"single-bridge\", status: \"skipped\", detail: \"no bridge running\" };\n if (pids.length === 1) return { name: \"single-bridge\", status: \"ok\", detail: `pid:${pids[0]}` };\n return { name: \"single-bridge\", status: \"failed\", detail: `${pids.length} bridges running: ${pids.join(\",\")}` };\n}\n\n// \u2500\u2500 Brain Probes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function probeTransport(): Promise<ProbeResult> {\n const tPath = join(configDir, \"transport.json\");\n const t = readJson(tPath);\n if (!t) return { name: \"transport\", status: \"failed\", detail: \"transport.json missing or invalid\" };\n const agents = Object.keys(t.agents ?? {});\n if (agents.length === 0) return { name: \"transport\", status: \"failed\", detail: \"no agents configured\" };\n return { name: \"transport\", status: \"ok\", detail: `${agents.length} agent(s): ${agents.join(\", \")}` };\n}\n\nasync function probeSpin(): Promise<ProbeResult> {\n const lock = readJson(join(home, \"bridge.lock\"));\n if (!lock?.pid || !pidAlive(lock.pid)) return { name: \"spin\", status: \"failed\", detail: \"bridge not running\" };\n return { name: \"spin\", status: \"ok\", detail: \"bridge alive\" };\n}\n\nasync function probeKanban(): Promise<ProbeResult> {\n const dbPath = join(home, \"kanban\", \"kanban.db\");\n if (!existsSync(dbPath)) return { name: \"kanban\", status: \"skipped\", detail: \"kanban.db not found\" };\n const sharedNm = join(homedir(), \".local\", \"lib\", \"node_modules\", \"better-sqlite3\");\n if (!existsSync(sharedNm)) return { name: \"kanban\", status: \"skipped\", detail: \"better-sqlite3 not installed (run: abtars deps install)\" };\n let Db: any;\n try {\n const { createRequire } = await import(\"node:module\");\n const _require = createRequire(import.meta.url);\n Db = _require(sharedNm);\n } catch (err) {\n return { name: \"kanban\", status: \"skipped\", detail: `better-sqlite3 not loadable: ${err instanceof Error ? err.message : String(err)}` };\n }\n try {\n const db = new Db(dbPath, { readonly: true });\n const row = db.prepare(\"SELECT COUNT(*) as cnt FROM kanban_board\").get() as { cnt: number };\n const stuck = db.prepare(\"SELECT COUNT(*) as cnt FROM kanban_board WHERE status='running' AND updated_at < datetime('now', '-10 minutes')\").get() as { cnt: number };\n db.close();\n const detail = stuck.cnt > 0 ? `${row.cnt} cards, ${stuck.cnt} stuck` : `${row.cnt} cards`;\n return { name: \"kanban\", status: stuck.cnt > 0 ? \"failed\" : \"ok\", detail };\n } catch (err) {\n return { name: \"kanban\", status: \"skipped\", detail: `kanban.db query failed: ${err instanceof Error ? err.message : String(err)}` };\n }\n}\n\nasync function probeSkills(): Promise<ProbeResult> {\n const catalog = join(home, \"skills\", \"skills_catalog.md\");\n if (!existsSync(catalog)) return { name: \"skills\", status: \"failed\", detail: \"skills_catalog.md missing\" };\n const content = readFileSync(catalog, \"utf-8\");\n const count = (content.match(/^## /gm) || []).length;\n if (count === 0) return { name: \"skills\", status: \"failed\", detail: \"catalog empty\" };\n return { name: \"skills\", status: \"ok\", detail: `${count} loaded` };\n}\n\nasync function probeSha(): Promise<ProbeResult> {\n // Check if healer skill exists in catalog\n const catalog = join(home, \"skills\", \"skills_catalog.md\");\n if (!existsSync(catalog)) return { name: \"sha\", status: \"skipped\", detail: \"no catalog\" };\n const content = readFileSync(catalog, \"utf-8\");\n if (/self.heal|healer|auto.fix/i.test(content)) return { name: \"sha\", status: \"ok\", detail: \"rules loaded\" };\n // Check sha-policy.json\n if (existsSync(join(configDir, \"sha-policy.json\"))) return { name: \"sha\", status: \"ok\", detail: \"rules loaded\" };\n return { name: \"sha\", status: \"skipped\", detail: \"no healer rules configured\" };\n}\n\n// \u2500\u2500 Tribe Probes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function probeA2a(): Promise<ProbeResult> {\n const env = readEnv();\n if (env.get(\"ENABLE_AGENT_API\") !== \"true\") return { name: \"a2a\", status: \"skipped\", detail: \"not enabled\" };\n const port = parseInt(env.get(\"AGENT_API_PORT\") || \"7100\", 10);\n try {\n const { createConnection } = await import(\"node:net\");\n await new Promise<void>((resolve, reject) => {\n const sock = createConnection({ port, host: \"127.0.0.1\" }, () => { sock.destroy(); resolve(); });\n sock.on(\"error\", reject);\n sock.setTimeout(2000, () => { sock.destroy(); reject(new Error(\"timeout\")); });\n });\n return { name: \"a2a\", status: \"ok\", detail: `${port}` };\n } catch {\n return { name: \"a2a\", status: \"failed\", detail: `${port} not listening` };\n }\n}\n\nasync function probePeers(): Promise<ProbeResult> {\n const peersPath = join(configDir, \"peers.json\");\n const peers = readJson(peersPath) as { peers?: Record<string, { verifyKey?: string; trust?: number }>; self?: { signingKey?: string; tribeToken?: string } } | null;\n if (!peers) return { name: \"peers\", status: \"skipped\", detail: \"peers.json missing\" };\n if (!peers.self?.signingKey) return { name: \"peers\", status: \"failed\", detail: \"self.signingKey missing \u2014 run: abtars install\" };\n\n const peerEntries = Object.entries(peers.peers ?? {});\n const peerCount = peerEntries.length;\n if (peerCount === 0) return { name: \"peers\", status: \"skipped\", detail: \"no peers (solo)\" };\n\n // Check that all peers have verifyKey\n const missingKey = peerEntries.filter(([, e]) => !e.verifyKey).map(([n]) => n);\n if (missingKey.length > 0) return { name: \"peers\", status: \"failed\", detail: `missing verifyKey: ${missingKey.join(\", \")}` };\n\n return { name: \"peers\", status: \"ok\", detail: `${peerCount} enrolled (all keys valid)` };\n}\n\nasync function probeIdentity(): Promise<ProbeResult> {\n const env = readEnv();\n if (env.get(\"ENABLE_AGENT_API\") !== \"true\") return { name: \"identity\", status: \"skipped\", detail: \"a2a disabled\" };\n\n const certPath = join(configDir, \"identity.crt\");\n const keyPath = join(configDir, \"identity.tls.key\");\n const certExists = existsSync(certPath);\n const keyExists = existsSync(keyPath);\n if (!certExists || !keyExists) {\n const missing = [!certExists && \"identity.crt\", !keyExists && \"identity.tls.key\"].filter(Boolean);\n return { name: \"identity\", status: \"failed\", detail: `missing: ${missing.join(\", \")}` };\n }\n\n // Verify cert public key matches self.signingKey (#1293)\n try {\n const { loadPeerConfig, deriveVerifyKey } = require(\"../../components/peer-config.js\") as typeof import(\"../../components/peer-config.js\");\n const { verifyServerCert } = require(\"../../components/peer-transport/peer-auth.js\") as typeof import(\"../../components/peer-transport/peer-auth.js\");\n const config = loadPeerConfig();\n const expectedVerifyKey = deriveVerifyKey(config.self.signingKey);\n const certPem = readFileSync(certPath, \"utf-8\");\n if (!verifyServerCert(certPem, expectedVerifyKey)) {\n return { name: \"identity\", status: \"failed\", detail: \"cert pubkey mismatch \u2014 re-run: abtars install --force\" };\n }\n return { name: \"identity\", status: \"ok\", detail: \"cert matches signing key\" };\n } catch {\n return { name: \"identity\", status: \"ok\", detail: \"cert present (key-match skipped)\" };\n }\n}\n\nasync function probeGossip(): Promise<ProbeResult> {\n const env = readEnv();\n if (env.get(\"ENABLE_AGENT_API\") !== \"true\") return { name: \"gossip\", status: \"skipped\", detail: \"a2a disabled\" };\n\n const peers = readJson(join(configDir, \"peers.json\")) as { peers?: Record<string, unknown>; self?: { signingKey?: string } } | null;\n const peerCount = Object.keys(peers?.peers ?? {}).length;\n if (peerCount === 0) return { name: \"gossip\", status: \"skipped\", detail: \"no peers (solo)\" };\n if (!peers?.self?.signingKey) return { name: \"gossip\", status: \"failed\", detail: \"self.signingKey missing \u2014 Ed25519 gossip requires identity\" };\n\n const port = parseInt(env.get(\"GOSSIP_PORT\") || \"5355\", 10);\n\n // Bind-test: if the port is already in use, gossip is live (EADDRINUSE = good).\n // If we can bind it, nothing is listening \u2192 gossip not running.\n const inUse = await new Promise<boolean>((resolve) => {\n import(\"node:dgram\").then(({ createSocket }) => {\n const sock = createSocket(\"udp4\");\n sock.once(\"error\", (err: NodeJS.ErrnoException) => { sock.close(); resolve(err.code === \"EADDRINUSE\"); });\n sock.bind(port, \"0.0.0.0\", () => { sock.close(); resolve(false); });\n }).catch(() => resolve(false));\n });\n if (!inUse) return { name: \"gossip\", status: \"failed\", detail: `${port} not listening` };\n\n // Live \u2014 report broadcast freshness.\n const lock = readJson(join(home, \"bridge.lock\"));\n const last = typeof lock?.lastGossipBroadcast === \"number\" ? lock.lastGossipBroadcast : 0;\n if (!last) return { name: \"gossip\", status: \"ok\", detail: `${port} / no broadcast yet` };\n const age = Date.now() - last;\n if (age > TTL_MS) return { name: \"gossip\", status: \"failed\", detail: `${port} / stale (${ago(age)})` };\n return { name: \"gossip\", status: \"ok\", detail: `${port} / last broadcast ${ago(age)}` };\n}\n\n// \u2500\u2500 Soul Probes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function probeMind(): Promise<ProbeResult> {\n try {\n const { loadAbmind } = await import(\"../../utils/abmind-lazy.js\");\n const mod = await loadAbmind();\n if (!mod) return { name: \"mind\", status: \"skipped\", detail: \"abmind not installed\" };\n return { name: \"mind\", status: \"ok\", detail: \"abmind loaded (in-process)\" };\n } catch {\n return { name: \"mind\", status: \"skipped\", detail: \"abmind load failed\" };\n }\n}\n\n// \u2500\u2500 Runner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function runAllProbes(): Promise<DoctorOutput> {\n const start = Date.now();\n\n const [body, heart, brain, soul, tribe] = await Promise.all([\n Promise.all([probePlatforms(), probeDashboard(), probeSecurity(), probeWatchdog(), probeSingleBridge()].map(p => timedProbe(() => p))),\n Promise.all([probeHeartbeat()].map(p => timedProbe(() => p))),\n Promise.all([probeTransport(), probeSpin(), probeKanban(), probeSkills(), probeSha()].map(p => timedProbe(() => p))),\n Promise.all([probeMind()].map(p => timedProbe(() => p))),\n Promise.all([probeA2a(), probePeers(), probeIdentity(), probeGossip()].map(p => timedProbe(() => p))),\n ]);\n\n return { version: \"1.0\", totalMs: Date.now() - start, layers: { body, heart, brain, soul, tribe } };\n}\n\n// \u2500\u2500 Fix Logic \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function runFixes(): Promise<FixResult[]> {\n const { chmodSync, unlinkSync, mkdirSync, existsSync: ex, readdirSync: rd, statSync: st, readFileSync: rf, writeFileSync: wf } = await import(\"node:fs\");\n const { spawnSync } = await import(\"node:child_process\");\n const fixes: FixResult[] = [];\n\n function fix(probe: string, action: string, fn: () => void): void {\n try { fn(); fixes.push({ probe, action, success: true }); }\n catch { fixes.push({ probe, action, success: false }); }\n }\n\n // 1. chmod 700 sensitive dirs\n for (const dir of [\"config\", \"secret\", \"auth\", \"hooks\"]) {\n const p = join(home, dir);\n if (ex(p) && (st(p).mode & 0o777) !== 0o700) {\n fix(\"security\", `${dir}/ \u2192 700`, () => chmodSync(p, 0o700));\n }\n }\n\n // 2. chmod 600 secret files\n const secretDir = join(home, \"secret\");\n if (ex(secretDir)) {\n for (const f of rd(secretDir)) {\n const fp = join(secretDir, f);\n if (st(fp).isFile() && (st(fp).mode & 0o777) !== 0o600) {\n fix(\"security\", `${f} \u2192 600`, () => chmodSync(fp, 0o600));\n }\n }\n }\n\n // 3. chmod 600 config files\n if (ex(configDir)) {\n for (const f of rd(configDir)) {\n const fp = join(configDir, f);\n if (st(fp).isFile() && (st(fp).mode & 0o777) !== 0o600) {\n fix(\"security\", `config/${f} \u2192 600`, () => chmodSync(fp, 0o600));\n }\n }\n }\n\n // 4. Stale deploy.lock\n const deployLock = join(home, \"deploy.lock\");\n if (ex(deployLock)) {\n const lock = readJson(deployLock);\n const lockAge = lock?.startedAt ? (Date.now() - new Date(lock.startedAt).getTime()) / 1000 : 9999;\n const lockPid = lock?.pid ?? 0;\n if (lockAge > 300 && (lockPid === 0 || !pidAlive(lockPid))) {\n fix(\"watchdog\", \"removed stale deploy.lock\", () => unlinkSync(deployLock));\n }\n }\n\n // 5. Stale .start-reason\n const startReason = join(home, \".start-reason\");\n if (ex(startReason)) {\n const age = (Date.now() - st(startReason).mtimeMs) / 1000;\n if (age > 300) fix(\"watchdog\", \"removed stale .start-reason\", () => unlinkSync(startReason));\n }\n\n // 6. Create missing dirs\n for (const dir of [\"logs\", \"workspace\", \"overflow\", \"received\"]) {\n const p = join(home, dir);\n if (!ex(p)) fix(\"watchdog\", `created ${dir}/`, () => mkdirSync(p, { recursive: true }));\n }\n\n // 7. Kill orphan CLI processes\n try {\n const lock = readJson(join(home, \"bridge.lock\"));\n const bridgePid = lock?.pid ?? 0;\n const wdPid = lock?.watchdogPid ?? 0;\n\n // Orphan kiro-cli\n const kiro = spawnSync(\"pgrep\", [\"-f\", \"kiro-cli.*acp\"], { encoding: \"utf-8\" });\n if (kiro.stdout) {\n for (const pid of kiro.stdout.trim().split(\"\\n\").filter(Boolean).map(Number)) {\n if (pid > 0 && pid !== bridgePid && pid !== wdPid && pid !== process.pid) {\n fix(\"brain\", `killed orphan kiro-cli ${pid}`, () => process.kill(pid, \"SIGTERM\"));\n }\n }\n }\n\n // Orphan abtars-sleep\n const sleep = spawnSync(\"pgrep\", [\"-f\", \"abtars-sleep\"], { encoding: \"utf-8\" });\n if (sleep.stdout) {\n for (const pid of sleep.stdout.trim().split(\"\\n\").filter(Boolean).map(Number)) {\n if (pid > 0 && pid !== bridgePid) {\n fix(\"brain\", `killed orphan abtars-sleep ${pid}`, () => process.kill(pid, \"SIGTERM\"));\n }\n }\n }\n } catch { /* pgrep not available or no orphans */ }\n\n // 8. Stale locks/sockets\n for (const f of [\"sleep.lock\", \"memory.sock\"]) {\n const p = join(home, f);\n if (ex(p)) {\n const age = (Date.now() - st(p).mtimeMs) / 1000;\n const lock = readJson(join(home, \"bridge.lock\"));\n if (age > 600 && (!lock?.pid || !pidAlive(lock.pid))) {\n fix(\"watchdog\", `removed stale ${f}`, () => unlinkSync(p));\n }\n }\n }\n\n // 9. Retention: delete old logs/overflow/media\n const LOGS_KEEP_DAYS = 7;\n const DATA_KEEP_DAYS = 30;\n try {\n const cutoffLogs = Date.now() - LOGS_KEEP_DAYS * 86400_000;\n const cutoffData = Date.now() - DATA_KEEP_DAYS * 86400_000;\n\n for (const [dir, cutoff] of [[join(home, \"logs\"), cutoffLogs], [join(home, \"overflow\"), cutoffData], [join(home, \"received\", \"media\"), cutoffLogs]] as const) {\n if (!ex(dir)) continue;\n let deleted = 0;\n for (const f of rd(dir)) {\n const fp = join(dir, f);\n if (st(fp).isFile() && st(fp).mtimeMs < cutoff) { unlinkSync(fp); deleted++; }\n }\n if (deleted > 0) fixes.push({ probe: \"retention\", action: `deleted ${deleted} stale file(s) from ${dir.split(\"/\").pop()}`, success: true });\n }\n\n // Truncate audit.jsonl if >10MB\n const auditPath = join(home, \"auth\", \"audit.jsonl\");\n if (ex(auditPath) && st(auditPath).size > 10_000_000) {\n const lines = rf(auditPath, \"utf-8\").split(\"\\n\");\n wf(auditPath, lines.slice(-1000).join(\"\\n\"));\n fixes.push({ probe: \"retention\", action: \"truncated audit.jsonl\", success: true });\n }\n } catch { /* retention errors non-fatal */ }\n\n // 10. Kill duplicate bridges\n try {\n const lock = readJson(join(home, \"bridge.lock\"));\n const expectedPid = lock?.pid ?? 0;\n const pgrep = spawnSync(\"pgrep\", [\"-f\", \"abtars.*main\"], { encoding: \"utf-8\" });\n if (pgrep.stdout) {\n for (const pid of pgrep.stdout.trim().split(\"\\n\").filter(Boolean).map(Number)) {\n if (pid > 0 && pid !== expectedPid && pid !== process.pid) {\n fix(\"watchdog\", `killed duplicate bridge ${pid}`, () => process.kill(pid, \"SIGTERM\"));\n }\n }\n }\n } catch { /* non-fatal */ }\n\n // 11. Hooks dir perms\n const hooksDir = join(home, \"hooks\");\n if (ex(hooksDir) && (st(hooksDir).mode & 0o777) !== 0o700) {\n fix(\"security\", \"hooks/ \u2192 700\", () => chmodSync(hooksDir, 0o700));\n }\n\n // 12. Install watchdog service if missing\n try {\n const manifest = readJson(join(home, \"manifest.json\"));\n if (manifest?.installMode === \"daemon\") {\n const { platform } = await import(\"node:os\");\n if (platform() === \"darwin\") {\n const plist = `${home}/com.abtars.watchdog.plist`;\n const dst = `${process.env[\"HOME\"]}/Library/LaunchAgents/com.abtars.watchdog.plist`;\n if (ex(plist) && !ex(dst)) {\n fix(\"watchdog\", \"installed LaunchAgent\", () => {\n const { copyFileSync } = require(\"node:fs\");\n copyFileSync(plist, dst);\n spawnSync(\"launchctl\", [\"load\", dst]);\n });\n }\n } else {\n const svc = `${home}/abtars-watchdog.service`;\n const dst = `${process.env[\"HOME\"]}/.config/systemd/user/abtars-watchdog.service`;\n if (ex(svc) && !ex(dst)) {\n fix(\"watchdog\", \"installed systemd unit\", () => {\n mkdirSync(join(process.env[\"HOME\"]!, \".config\", \"systemd\", \"user\"), { recursive: true });\n const { copyFileSync } = require(\"node:fs\");\n copyFileSync(svc, dst);\n spawnSync(\"systemctl\", [\"--user\", \"enable\", \"--now\", \"abtars-watchdog.service\"]);\n });\n }\n }\n }\n } catch { /* non-fatal */ }\n\n return fixes;\n}\n\n// \u2500\u2500 Renderer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ICON = { ok: \"\u2713\", failed: \"\u2717\", skipped: \"~\" } as const;\n\nexport function renderHuman(output: DoctorOutput): string {\n const lines: string[] = [];\n for (const [layer, probes] of Object.entries(output.layers) as [string, ProbeResult[]][]) {\n lines.push(`${layer.charAt(0).toUpperCase() + layer.slice(1)}:`);\n for (const p of probes) {\n const ms = p.ms && p.ms > 500 ? ` (${p.ms}ms)` : \"\";\n const detail = p.detail ? ` \u2014 ${p.detail}` : \"\";\n lines.push(` ${ICON[p.status]} ${p.name}${ms}${detail}`);\n }\n }\n const total = Object.values(output.layers).flat();\n const okCount = total.filter(r => r.status === \"ok\").length;\n lines.push(`\\n${okCount}/${total.length} ok (${(output.totalMs / 1000).toFixed(1)}s)`);\n return lines.join(\"\\n\");\n}\n\nexport function renderJson(output: DoctorOutput): string {\n return JSON.stringify(output, null, 2);\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  init_log_and_swallow,
5
5
  logAndSwallow
6
- } from "./chunk-YSKCQH6E.js";
6
+ } from "./chunk-2IYJ4I66.js";
7
7
  import {
8
8
  abmindHome,
9
9
  abtarsHome,
@@ -70,9 +70,6 @@ function buildPolicy(source, config) {
70
70
  case "peer":
71
71
  base = { allowedTools: [], allowedRead: [], allowedWrite: [], canExecuteBash: false };
72
72
  break;
73
- case "guest":
74
- base = { allowedTools: ["web_fetch"], allowedRead: [], allowedWrite: [], canExecuteBash: false };
75
- break;
76
73
  }
77
74
  if (config) base = { ...base, ...config };
78
75
  return Object.freeze(base);
@@ -128,4 +125,4 @@ export {
128
125
  auditDeny,
129
126
  ToolLoopGuard
130
127
  };
131
- //# sourceMappingURL=chunk-WBTJ2E62.js.map
128
+ //# sourceMappingURL=chunk-P3NODAHF.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/components/tool-sandbox.ts"],
4
- "sourcesContent": ["/**\n * tool-sandbox.ts \u2014 unified policy enforcement for tool access and path restrictions.\n * Provides SandboxPolicy interface, check functions, loop guardrails, and audit logging.\n */\n\nimport { resolve } from \"node:path\";\nimport { realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport { abtarsHome, abmindHome } from \"../paths.js\";\nimport { logAndSwallow } from \"./log-and-swallow.js\";\n\nexport interface SandboxPolicy {\n readonly allowedTools: string[];\n readonly allowedRead: string[];\n readonly allowedWrite: string[];\n readonly canExecuteBash: boolean;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n reason?: string;\n}\n\nconst PATH_BLACKLIST: readonly string[] = [\n resolve(abtarsHome(), \"config\"),\n resolve(abtarsHome(), \"secret\"),\n resolve(abmindHome()),\n];\n\nconst AUDIT_DIR = join(abtarsHome(), \"logs\");\nconst AUDIT_PATH = join(AUDIT_DIR, \"audit.jsonl\");\ntry { mkdirSync(AUDIT_DIR, { recursive: true }); } catch (err) { logAndSwallow(\"tool-sandbox\", \"mkdirSync\", err); }\n\nexport function checkTool(name: string, policy: SandboxPolicy): CheckResult {\n if (policy.allowedTools.length === 1 && policy.allowedTools[0] === \"*\") return { allowed: true };\n if (policy.allowedTools.length === 0) return { allowed: false, reason: `Tool '${name}' not available in this session` };\n if (name === \"execute_bash\" && !policy.canExecuteBash) return { allowed: false, reason: `Tool '${name}' not available in this session` };\n if (policy.allowedTools.includes(name)) return { allowed: true };\n return { allowed: false, reason: `Tool '${name}' not available in this session` };\n}\n\nexport function checkPath(filePath: string, mode: \"read\" | \"write\", policy: SandboxPolicy): CheckResult {\n // Resolve ~, normalize .., and resolve symlinks to prevent traversal attacks\n const expanded = filePath.replace(/^~/, homedir());\n const normalized = resolve(expanded);\n let abs: string;\n try { abs = realpathSync(normalized); } catch { abs = normalized; /* file may not exist yet (write) */ }\n\n const list = mode === \"read\" ? policy.allowedRead : policy.allowedWrite;\n // If wildcard, skip blacklist (owner sessions)\n if (list.length === 1 && list[0] === \"*\") return { allowed: true };\n // Blacklist always enforced for explicit path lists\n for (const blocked of PATH_BLACKLIST) {\n if (abs === blocked || abs.startsWith(blocked + \"/\")) {\n return { allowed: false, reason: `Path '${filePath}' is restricted` };\n }\n }\n if (list.length === 0) return { allowed: false, reason: `No ${mode} access in this session` };\n for (const prefix of list) {\n const absPrefix = resolve(prefix.replace(/^~/, homedir()));\n if (abs === absPrefix || abs.startsWith(absPrefix + \"/\")) return { allowed: true };\n }\n return { allowed: false, reason: `Path '${filePath}' not in allowed ${mode} paths` };\n}\n\nexport function buildPolicy(source: \"owner\" | \"peer\" | \"guest\", config?: Partial<SandboxPolicy>): Readonly<SandboxPolicy> {\n let base: SandboxPolicy;\n switch (source) {\n case \"owner\":\n base = { allowedTools: [\"*\"], allowedRead: [\"*\"], allowedWrite: [\"*\"], canExecuteBash: true };\n break;\n case \"peer\":\n base = { allowedTools: [], allowedRead: [], allowedWrite: [], canExecuteBash: false };\n break;\n case \"guest\":\n base = { allowedTools: [\"web_fetch\"], allowedRead: [], allowedWrite: [], canExecuteBash: false };\n break;\n }\n if (config) base = { ...base, ...config };\n return Object.freeze(base);\n}\n\nexport function auditDeny(tool: string, path: string | undefined, policy: string, reason: string): void {\n const entry = { ts: Date.now(), event: \"sandbox_deny\", tool, path, policy, reason };\n try { appendFileSync(AUDIT_PATH, JSON.stringify(entry) + \"\\n\"); } catch (err) { logAndSwallow(\"tool-sandbox\", \"audit write\", err); }\n}\n\n// \u2500\u2500 Tool Loop Guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst IDEMPOTENT_TOOLS = new Set([\"file_read\", \"web_fetch\", \"web_browse\", \"memory_recall\"]);\n\nfunction argsHash(name: string, args: Record<string, unknown>): string {\n return createHash(\"sha256\").update(name + JSON.stringify(args)).digest(\"hex\");\n}\n\nexport class ToolLoopGuard {\n private failCounts = new Map<string, number>();\n private resultCounts = new Map<string, number>();\n\n beforeCall(name: string, args: Record<string, unknown>): CheckResult {\n const hash = argsHash(name, args);\n const fails = this.failCounts.get(hash) ?? 0;\n if (fails >= 4) return { allowed: false, reason: `Tool '${name}' blocked: repeated identical failure (${fails} times)` };\n if (IDEMPOTENT_TOOLS.has(name)) {\n const repeats = this.resultCounts.get(hash) ?? 0;\n if (repeats >= 4) return { allowed: false, reason: `Tool '${name}' blocked: same result returned ${repeats} times \u2014 stuck loop` };\n }\n return { allowed: true };\n }\n\n afterCall(name: string, args: Record<string, unknown>, _result: string, failed: boolean): string | undefined {\n const hash = argsHash(name, args);\n if (failed) {\n const count = (this.failCounts.get(hash) ?? 0) + 1;\n this.failCounts.set(hash, count);\n if (count === 2) return \"This tool call failed twice with identical arguments. Consider changing your approach.\";\n } else if (IDEMPOTENT_TOOLS.has(name)) {\n const count = (this.resultCounts.get(hash) ?? 0) + 1;\n this.resultCounts.set(hash, count);\n if (count === 2) return \"Same result returned twice for identical query. Use the result or change the query.\";\n }\n return undefined;\n }\n\n resetForTurn(): void {\n this.failCounts.clear();\n this.resultCounts.clear();\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * tool-sandbox.ts \u2014 unified policy enforcement for tool access and path restrictions.\n * Provides SandboxPolicy interface, check functions, loop guardrails, and audit logging.\n */\n\nimport { resolve } from \"node:path\";\nimport { realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { appendFileSync, mkdirSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport { abtarsHome, abmindHome } from \"../paths.js\";\nimport { logAndSwallow } from \"./log-and-swallow.js\";\n\nexport interface SandboxPolicy {\n readonly allowedTools: string[];\n readonly allowedRead: string[];\n readonly allowedWrite: string[];\n readonly canExecuteBash: boolean;\n}\n\nexport interface CheckResult {\n allowed: boolean;\n reason?: string;\n}\n\nconst PATH_BLACKLIST: readonly string[] = [\n resolve(abtarsHome(), \"config\"),\n resolve(abtarsHome(), \"secret\"),\n resolve(abmindHome()),\n];\n\nconst AUDIT_DIR = join(abtarsHome(), \"logs\");\nconst AUDIT_PATH = join(AUDIT_DIR, \"audit.jsonl\");\ntry { mkdirSync(AUDIT_DIR, { recursive: true }); } catch (err) { logAndSwallow(\"tool-sandbox\", \"mkdirSync\", err); }\n\nexport function checkTool(name: string, policy: SandboxPolicy): CheckResult {\n if (policy.allowedTools.length === 1 && policy.allowedTools[0] === \"*\") return { allowed: true };\n if (policy.allowedTools.length === 0) return { allowed: false, reason: `Tool '${name}' not available in this session` };\n if (name === \"execute_bash\" && !policy.canExecuteBash) return { allowed: false, reason: `Tool '${name}' not available in this session` };\n if (policy.allowedTools.includes(name)) return { allowed: true };\n return { allowed: false, reason: `Tool '${name}' not available in this session` };\n}\n\nexport function checkPath(filePath: string, mode: \"read\" | \"write\", policy: SandboxPolicy): CheckResult {\n // Resolve ~, normalize .., and resolve symlinks to prevent traversal attacks\n const expanded = filePath.replace(/^~/, homedir());\n const normalized = resolve(expanded);\n let abs: string;\n try { abs = realpathSync(normalized); } catch { abs = normalized; /* file may not exist yet (write) */ }\n\n const list = mode === \"read\" ? policy.allowedRead : policy.allowedWrite;\n // If wildcard, skip blacklist (owner sessions)\n if (list.length === 1 && list[0] === \"*\") return { allowed: true };\n // Blacklist always enforced for explicit path lists\n for (const blocked of PATH_BLACKLIST) {\n if (abs === blocked || abs.startsWith(blocked + \"/\")) {\n return { allowed: false, reason: `Path '${filePath}' is restricted` };\n }\n }\n if (list.length === 0) return { allowed: false, reason: `No ${mode} access in this session` };\n for (const prefix of list) {\n const absPrefix = resolve(prefix.replace(/^~/, homedir()));\n if (abs === absPrefix || abs.startsWith(absPrefix + \"/\")) return { allowed: true };\n }\n return { allowed: false, reason: `Path '${filePath}' not in allowed ${mode} paths` };\n}\n\nexport function buildPolicy(source: \"owner\" | \"peer\", config?: Partial<SandboxPolicy>): Readonly<SandboxPolicy> {\n let base: SandboxPolicy;\n switch (source) {\n case \"owner\":\n base = { allowedTools: [\"*\"], allowedRead: [\"*\"], allowedWrite: [\"*\"], canExecuteBash: true };\n break;\n case \"peer\":\n base = { allowedTools: [], allowedRead: [], allowedWrite: [], canExecuteBash: false };\n break;\n }\n if (config) base = { ...base, ...config };\n return Object.freeze(base);\n}\n\nexport function auditDeny(tool: string, path: string | undefined, policy: string, reason: string): void {\n const entry = { ts: Date.now(), event: \"sandbox_deny\", tool, path, policy, reason };\n try { appendFileSync(AUDIT_PATH, JSON.stringify(entry) + \"\\n\"); } catch (err) { logAndSwallow(\"tool-sandbox\", \"audit write\", err); }\n}\n\n// \u2500\u2500 Tool Loop Guard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst IDEMPOTENT_TOOLS = new Set([\"file_read\", \"web_fetch\", \"web_browse\", \"memory_recall\"]);\n\nfunction argsHash(name: string, args: Record<string, unknown>): string {\n return createHash(\"sha256\").update(name + JSON.stringify(args)).digest(\"hex\");\n}\n\nexport class ToolLoopGuard {\n private failCounts = new Map<string, number>();\n private resultCounts = new Map<string, number>();\n\n beforeCall(name: string, args: Record<string, unknown>): CheckResult {\n const hash = argsHash(name, args);\n const fails = this.failCounts.get(hash) ?? 0;\n if (fails >= 4) return { allowed: false, reason: `Tool '${name}' blocked: repeated identical failure (${fails} times)` };\n if (IDEMPOTENT_TOOLS.has(name)) {\n const repeats = this.resultCounts.get(hash) ?? 0;\n if (repeats >= 4) return { allowed: false, reason: `Tool '${name}' blocked: same result returned ${repeats} times \u2014 stuck loop` };\n }\n return { allowed: true };\n }\n\n afterCall(name: string, args: Record<string, unknown>, _result: string, failed: boolean): string | undefined {\n const hash = argsHash(name, args);\n if (failed) {\n const count = (this.failCounts.get(hash) ?? 0) + 1;\n this.failCounts.set(hash, count);\n if (count === 2) return \"This tool call failed twice with identical arguments. Consider changing your approach.\";\n } else if (IDEMPOTENT_TOOLS.has(name)) {\n const count = (this.resultCounts.get(hash) ?? 0) + 1;\n this.resultCounts.set(hash, count);\n if (count === 2) return \"Same result returned twice for identical query. Use the result or change the query.\";\n }\n return undefined;\n }\n\n resetForTurn(): void {\n this.failCounts.clear();\n this.resultCounts.clear();\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;AAWA;AACA;AAPA,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,gBAAgB,iBAAiB;AAC1C,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAgBrB,IAAM,iBAAoC;AAAA,EACxC,QAAQ,WAAW,GAAG,QAAQ;AAAA,EAC9B,QAAQ,WAAW,GAAG,QAAQ;AAAA,EAC9B,QAAQ,WAAW,CAAC;AACtB;AAEA,IAAM,YAAY,KAAK,WAAW,GAAG,MAAM;AAC3C,IAAM,aAAa,KAAK,WAAW,aAAa;AAChD,IAAI;AAAE,YAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAG,SAAS,KAAK;AAAE,gBAAc,gBAAgB,aAAa,GAAG;AAAG;AAE3G,SAAS,UAAU,MAAc,QAAoC;AAC1E,MAAI,OAAO,aAAa,WAAW,KAAK,OAAO,aAAa,CAAC,MAAM,IAAK,QAAO,EAAE,SAAS,KAAK;AAC/F,MAAI,OAAO,aAAa,WAAW,EAAG,QAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,kCAAkC;AACtH,MAAI,SAAS,kBAAkB,CAAC,OAAO,eAAgB,QAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,kCAAkC;AACvI,MAAI,OAAO,aAAa,SAAS,IAAI,EAAG,QAAO,EAAE,SAAS,KAAK;AAC/D,SAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,kCAAkC;AAClF;AAEO,SAAS,UAAU,UAAkB,MAAwB,QAAoC;AAEtG,QAAM,WAAW,SAAS,QAAQ,MAAM,QAAQ,CAAC;AACjD,QAAM,aAAa,QAAQ,QAAQ;AACnC,MAAI;AACJ,MAAI;AAAE,UAAM,aAAa,UAAU;AAAA,EAAG,QAAQ;AAAE,UAAM;AAAA,EAAiD;AAEvG,QAAM,OAAO,SAAS,SAAS,OAAO,cAAc,OAAO;AAE3D,MAAI,KAAK,WAAW,KAAK,KAAK,CAAC,MAAM,IAAK,QAAO,EAAE,SAAS,KAAK;AAEjE,aAAW,WAAW,gBAAgB;AACpC,QAAI,QAAQ,WAAW,IAAI,WAAW,UAAU,GAAG,GAAG;AACpD,aAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,QAAQ,kBAAkB;AAAA,IACtE;AAAA,EACF;AACA,MAAI,KAAK,WAAW,EAAG,QAAO,EAAE,SAAS,OAAO,QAAQ,MAAM,IAAI,0BAA0B;AAC5F,aAAW,UAAU,MAAM;AACzB,UAAM,YAAY,QAAQ,OAAO,QAAQ,MAAM,QAAQ,CAAC,CAAC;AACzD,QAAI,QAAQ,aAAa,IAAI,WAAW,YAAY,GAAG,EAAG,QAAO,EAAE,SAAS,KAAK;AAAA,EACnF;AACA,SAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,QAAQ,oBAAoB,IAAI,SAAS;AACrF;AAEO,SAAS,YAAY,QAA0B,QAA0D;AAC9G,MAAI;AACJ,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,EAAE,cAAc,CAAC,GAAG,GAAG,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC,GAAG,GAAG,gBAAgB,KAAK;AAC5F;AAAA,IACF,KAAK;AACH,aAAO,EAAE,cAAc,CAAC,GAAG,aAAa,CAAC,GAAG,cAAc,CAAC,GAAG,gBAAgB,MAAM;AACpF;AAAA,EACJ;AACA,MAAI,OAAQ,QAAO,EAAE,GAAG,MAAM,GAAG,OAAO;AACxC,SAAO,OAAO,OAAO,IAAI;AAC3B;AAEO,SAAS,UAAU,MAAc,MAA0B,QAAgB,QAAsB;AACtG,QAAM,QAAQ,EAAE,IAAI,KAAK,IAAI,GAAG,OAAO,gBAAgB,MAAM,MAAM,QAAQ,OAAO;AAClF,MAAI;AAAE,mBAAe,YAAY,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EAAG,SAAS,KAAK;AAAE,kBAAc,gBAAgB,eAAe,GAAG;AAAA,EAAG;AACrI;AAIA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,aAAa,aAAa,cAAc,eAAe,CAAC;AAE1F,SAAS,SAAS,MAAc,MAAuC;AACrE,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,KAAK,UAAU,IAAI,CAAC,EAAE,OAAO,KAAK;AAC9E;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACjB,aAAa,oBAAI,IAAoB;AAAA,EACrC,eAAe,oBAAI,IAAoB;AAAA,EAE/C,WAAW,MAAc,MAA4C;AACnE,UAAM,OAAO,SAAS,MAAM,IAAI;AAChC,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI,KAAK;AAC3C,QAAI,SAAS,EAAG,QAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,0CAA0C,KAAK,UAAU;AACvH,QAAI,iBAAiB,IAAI,IAAI,GAAG;AAC9B,YAAM,UAAU,KAAK,aAAa,IAAI,IAAI,KAAK;AAC/C,UAAI,WAAW,EAAG,QAAO,EAAE,SAAS,OAAO,QAAQ,SAAS,IAAI,mCAAmC,OAAO,2BAAsB;AAAA,IAClI;AACA,WAAO,EAAE,SAAS,KAAK;AAAA,EACzB;AAAA,EAEA,UAAU,MAAc,MAA+B,SAAiB,QAAqC;AAC3G,UAAM,OAAO,SAAS,MAAM,IAAI;AAChC,QAAI,QAAQ;AACV,YAAM,SAAS,KAAK,WAAW,IAAI,IAAI,KAAK,KAAK;AACjD,WAAK,WAAW,IAAI,MAAM,KAAK;AAC/B,UAAI,UAAU,EAAG,QAAO;AAAA,IAC1B,WAAW,iBAAiB,IAAI,IAAI,GAAG;AACrC,YAAM,SAAS,KAAK,aAAa,IAAI,IAAI,KAAK,KAAK;AACnD,WAAK,aAAa,IAAI,MAAM,KAAK;AACjC,UAAI,UAAU,EAAG,QAAO;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eAAqB;AACnB,SAAK,WAAW,MAAM;AACtB,SAAK,aAAa,MAAM;AAAA,EAC1B;AACF;",
6
6
  "names": []
7
7
  }