abtars 0.3.3 → 0.3.4-alpha.1

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 (384) hide show
  1. package/bundle/{_registry.generated-7DRCE4V6.js → _registry.generated-ZJBAZMXN.js} +16 -15
  2. package/bundle/{_registry.generated-7DRCE4V6.js.map → _registry.generated-ZJBAZMXN.js.map} +1 -1
  3. package/bundle/abtars-browser.js +6 -5
  4. package/bundle/abtars-browser.js.map +1 -1
  5. package/bundle/abtars-cli.js +47 -39
  6. package/bundle/abtars-cli.js.map +2 -2
  7. package/bundle/abtars-restart.js +7 -7
  8. package/bundle/abtars-rss.js +2 -1
  9. package/bundle/abtars-rss.js.map +2 -2
  10. package/bundle/abtars-task.js +6 -5
  11. package/bundle/abtars-task.js.map +1 -1
  12. package/bundle/abtars-todo.js +2 -1
  13. package/bundle/abtars-todo.js.map +1 -1
  14. package/bundle/abtars.js +299 -209
  15. package/bundle/abtars.js.map +4 -4
  16. package/bundle/{acp-raw-client-AZJCEB6S.js → acp-raw-client-YTBGFN4S.js} +4 -3
  17. package/bundle/{acp-raw-client-AZJCEB6S.js.map → acp-raw-client-YTBGFN4S.js.map} +1 -1
  18. package/bundle/{action-gate-QYJL57IX.js → action-gate-YISTP773.js} +4 -3
  19. package/bundle/{action-gate-QYJL57IX.js.map → action-gate-YISTP773.js.map} +1 -1
  20. package/bundle/{agent-api-adapter-PYMNQXHE.js → agent-api-adapter-E4HWVJ32.js} +5 -4
  21. package/bundle/{agent-api-adapter-PYMNQXHE.js.map → agent-api-adapter-E4HWVJ32.js.map} +1 -1
  22. package/bundle/{agent-api-rate-limit-4GEZ4YN5.js → agent-api-rate-limit-VENFGOAD.js} +6 -5
  23. package/bundle/{agent-registry-563P4EUJ.js → agent-registry-DL7UT272.js} +9 -8
  24. package/bundle/bootstrap-V5MROD3X.js +62 -0
  25. package/bundle/bootstrap-V5MROD3X.js.map +7 -0
  26. package/bundle/{bridge-lock-transport-LXCF2IVN.js → bridge-lock-transport-BJAMHMXW.js} +6 -5
  27. package/bundle/{browser-2VZOGOGX.js → browser-PT54UWSW.js} +8 -7
  28. package/bundle/{budget-PPA7WY3D.js → budget-QNK6IIT6.js} +5 -4
  29. package/bundle/{budget-PPA7WY3D.js.map → budget-QNK6IIT6.js.map} +1 -1
  30. package/bundle/{capability-WXEA2WFK.js → capability-EKPGHQIO.js} +7 -6
  31. package/bundle/{chunk-C3EYYJN3.js → chunk-2BXXQG7P.js} +16 -4
  32. package/bundle/chunk-2BXXQG7P.js.map +7 -0
  33. package/bundle/{chunk-4PIVWXUJ.js → chunk-2ZD7VQRW.js} +2 -2
  34. package/bundle/{chunk-OY2HAK33.js → chunk-36ZEYDKZ.js} +1 -1
  35. package/bundle/chunk-36ZEYDKZ.js.map +7 -0
  36. package/bundle/{chunk-3QW2K53E.js → chunk-4IGLXZCC.js} +11 -19
  37. package/bundle/chunk-4IGLXZCC.js.map +7 -0
  38. package/bundle/{chunk-T7TAWGBX.js → chunk-52PQM4EZ.js} +2 -2
  39. package/bundle/{chunk-2RGR3LSV.js → chunk-5P5HF7IJ.js} +2 -2
  40. package/bundle/{chunk-LE23VPN3.js → chunk-63A7ZRIH.js} +4 -4
  41. package/bundle/{chunk-LE23VPN3.js.map → chunk-63A7ZRIH.js.map} +1 -1
  42. package/bundle/chunk-6IB3GVXK.js +77 -0
  43. package/bundle/chunk-6IB3GVXK.js.map +7 -0
  44. package/bundle/{chunk-OOKNHOCB.js → chunk-6S3G6GPO.js} +2 -2
  45. package/bundle/{chunk-E7MV7WFT.js → chunk-6VTHSN4V.js} +6 -6
  46. package/bundle/{chunk-NGZVJ52F.js → chunk-76YN7O3U.js} +7 -7
  47. package/bundle/{chunk-43DKPXTP.js → chunk-7LORCJCQ.js} +4 -4
  48. package/bundle/{chunk-HDOFJVFS.js → chunk-7OI46MH7.js} +3 -3
  49. package/bundle/{chunk-H2K23MOF.js → chunk-7XXISOHU.js} +21 -5
  50. package/bundle/chunk-7XXISOHU.js.map +7 -0
  51. package/bundle/{chunk-CB6S3ZRF.js → chunk-AFFW2LRY.js} +3 -3
  52. package/bundle/{chunk-TCI6FZTP.js → chunk-AHJDG6OM.js} +9 -9
  53. package/bundle/{chunk-NP72ZB7P.js → chunk-AMUJEP6L.js} +45 -45
  54. package/bundle/{chunk-NP72ZB7P.js.map → chunk-AMUJEP6L.js.map} +2 -2
  55. package/bundle/{chunk-BU7LTI2W.js → chunk-AWCO3DQ3.js} +6 -7
  56. package/bundle/chunk-AWCO3DQ3.js.map +7 -0
  57. package/bundle/{chunk-YME7NRGP.js → chunk-B2TIRDZC.js} +2 -2
  58. package/bundle/{chunk-SSCGWDIC.js → chunk-BWJ37KMW.js} +2 -2
  59. package/bundle/{chunk-ULO2PX3T.js → chunk-CCZ43JB7.js} +3 -3
  60. package/bundle/{chunk-FVUL44T4.js → chunk-CNENVY37.js} +2 -2
  61. package/bundle/{chunk-J5NOL4DB.js → chunk-DJOSXXM2.js} +2 -2
  62. package/bundle/{chunk-7RAGSHSH.js → chunk-DMDX35YT.js} +12 -10
  63. package/bundle/chunk-DMDX35YT.js.map +7 -0
  64. package/bundle/{chunk-DNDYD5SL.js → chunk-E7DZYCSF.js} +3 -3
  65. package/bundle/{chunk-M6Q3IQ4H.js → chunk-FF2F7ENH.js} +250 -118
  66. package/bundle/chunk-FF2F7ENH.js.map +7 -0
  67. package/bundle/{chunk-GCFIK6OB.js → chunk-FSGICOCX.js} +21 -21
  68. package/bundle/{chunk-IXKQ4JMX.js → chunk-GFAJSPMD.js} +33 -17
  69. package/bundle/chunk-GFAJSPMD.js.map +7 -0
  70. package/bundle/{chunk-FJF42RZY.js → chunk-GHRLO2UL.js} +3 -3
  71. package/bundle/{chunk-3LQOJVTB.js → chunk-HFOCNYEO.js} +1842 -1220
  72. package/bundle/{chunk-3LQOJVTB.js.map → chunk-HFOCNYEO.js.map} +4 -4
  73. package/bundle/{chunk-7WHXTCVD.js → chunk-HWFN7JGU.js} +2 -2
  74. package/bundle/{chunk-KBPVJGD7.js → chunk-IXGDDDAB.js} +3 -3
  75. package/bundle/chunk-JHLKEUHE.js +37 -0
  76. package/bundle/chunk-JHLKEUHE.js.map +7 -0
  77. package/bundle/{chunk-YEOZN5IE.js → chunk-JRGEEGZF.js} +2 -2
  78. package/bundle/{chunk-56D3Y44D.js → chunk-KLG4SCF7.js} +10 -10
  79. package/bundle/{chunk-ASYX43OU.js → chunk-LB43Q7G6.js} +26 -26
  80. package/bundle/{chunk-TVSPVZTX.js → chunk-LN5MNDSA.js} +3 -3
  81. package/bundle/{chunk-RJX45XIC.js → chunk-LPF2HELD.js} +9 -4
  82. package/bundle/chunk-LPF2HELD.js.map +7 -0
  83. package/bundle/{chunk-72T2Q7IG.js → chunk-MJACYH7A.js} +270 -282
  84. package/bundle/chunk-MJACYH7A.js.map +7 -0
  85. package/bundle/{chunk-SESM4GBM.js → chunk-MPQ2PJQX.js} +52 -25
  86. package/bundle/chunk-MPQ2PJQX.js.map +7 -0
  87. package/bundle/{chunk-FIAVVKGN.js → chunk-MTE32OQH.js} +3 -3
  88. package/bundle/{chunk-MV5KOWOR.js → chunk-N3Q3TASM.js} +7 -7
  89. package/bundle/{chunk-IQKADER4.js → chunk-O4YBJS2K.js} +2 -2
  90. package/bundle/{chunk-VJATH7AN.js → chunk-OOUCUCUW.js} +9 -8
  91. package/bundle/chunk-OOUCUCUW.js.map +7 -0
  92. package/bundle/{chunk-5V4VHKEA.js → chunk-OT6HLPEA.js} +3 -3
  93. package/bundle/{chunk-V6CV3QPH.js → chunk-OWPQIBAO.js} +2 -2
  94. package/bundle/{chunk-EDZGF6BC.js → chunk-QJPDBJDP.js} +11 -4
  95. package/bundle/chunk-QJPDBJDP.js.map +7 -0
  96. package/bundle/{chunk-N5VROZ7A.js → chunk-QMP2KC4W.js} +5 -5
  97. package/bundle/{chunk-4HNCOQSK.js → chunk-QOGZ7BFL.js} +7 -7
  98. package/bundle/{chunk-2LKQV2ND.js → chunk-R23FHZRY.js} +3 -3
  99. package/bundle/{chunk-SXNY6HC4.js → chunk-R4GYWVCR.js} +6 -6
  100. package/bundle/chunk-R4GYWVCR.js.map +7 -0
  101. package/bundle/{chunk-S7ZIGIR5.js → chunk-R76K6L6H.js} +27 -27
  102. package/bundle/{chunk-S7ZIGIR5.js.map → chunk-R76K6L6H.js.map} +1 -1
  103. package/bundle/{chunk-TY26WMQY.js → chunk-RCWQ34QR.js} +2 -2
  104. package/bundle/{chunk-MQJG7OJX.js → chunk-RJ2OUNFU.js} +38 -36
  105. package/bundle/chunk-RJ2OUNFU.js.map +7 -0
  106. package/bundle/{chunk-S6HEHCCG.js → chunk-RO3TAYBR.js} +83 -46
  107. package/bundle/chunk-RO3TAYBR.js.map +7 -0
  108. package/bundle/{chunk-ZOCEBV62.js → chunk-UU3RLJSD.js} +3 -3
  109. package/bundle/{chunk-P5O6QZDC.js → chunk-V7Y2LFO4.js} +10 -6
  110. package/bundle/chunk-V7Y2LFO4.js.map +7 -0
  111. package/bundle/{chunk-WP7FZHMI.js → chunk-W2PSVV2T.js} +2 -2
  112. package/bundle/{chunk-V2QIAXWZ.js → chunk-WEGFRA6G.js} +3 -3
  113. package/bundle/{chunk-ZY6DH2S4.js → chunk-WTIGZO3N.js} +80 -70
  114. package/bundle/chunk-WTIGZO3N.js.map +7 -0
  115. package/bundle/{chunk-O4GKI3Q3.js → chunk-X7DLKIQM.js} +4 -4
  116. package/bundle/{chunk-BNBC4T45.js → chunk-XZ4ZBDM5.js} +3 -3
  117. package/bundle/{chunk-24V4A6RP.js → chunk-YI2KSYB4.js} +4 -4
  118. package/bundle/{chunk-37EX63K4.js → chunk-YWHJJHJ2.js} +6998 -3621
  119. package/bundle/chunk-YWHJJHJ2.js.map +7 -0
  120. package/bundle/{chunk-IK4R3RBZ.js → chunk-YZCOA4DC.js} +3 -3
  121. package/bundle/{chunk-2FZJDMAF.js → chunk-ZGNSCJWH.js} +10 -10
  122. package/bundle/{chunk-W726UGI6.js → chunk-ZKMKAO75.js} +3 -3
  123. package/bundle/{chunk-WGWM4IZM.js → chunk-ZT5ZBGWS.js} +4 -4
  124. package/bundle/{chunk-WGWM4IZM.js.map → chunk-ZT5ZBGWS.js.map} +1 -1
  125. package/bundle/{commands-XXFU2ZF7.js → commands-2JQ5YTJX.js} +20 -20
  126. package/bundle/{config-EWDZ234X.js → config-ZEWIM5Z2.js} +8 -7
  127. package/bundle/{config-show-6J33O4TE.js → config-show-WBJPQPRD.js} +5 -5
  128. package/bundle/{context-OCS7HLJP.js → context-V75QNXB5.js} +5 -2
  129. package/bundle/{context-OCS7HLJP.js.map → context-V75QNXB5.js.map} +1 -1
  130. package/bundle/{daemon-LTDAXNA2.js → daemon-W7VQOSZC.js} +7 -7
  131. package/bundle/{delegation-tools-YDTWQMZD.js → delegation-tools-VGTRFQBF.js} +13 -11
  132. package/bundle/{registry-client-VN2MM2HI.js → deploy-5AGIULM2.js} +10 -6
  133. package/bundle/{deploy-lib-import-RGZJ3CGC.js → deploy-lib-import-ZBDYORN4.js} +5 -3
  134. package/bundle/{deps-PHSLIA77.js → deps-VB3S3RLF.js} +21 -19
  135. package/bundle/deps-VB3S3RLF.js.map +7 -0
  136. package/bundle/{direct-api-transport-OAKYQBJR.js → direct-api-transport-YSROTC35.js} +30 -28
  137. package/bundle/direct-api-transport-YSROTC35.js.map +7 -0
  138. package/bundle/{discord-adapter-WUNYPTDE.js → discord-adapter-LKBSIFLV.js} +26 -26
  139. package/bundle/{dist-7HEHHQI2.js → dist-KMK7TZGN.js} +376 -348
  140. package/bundle/dist-KMK7TZGN.js.map +7 -0
  141. package/bundle/{dns-wakeup-F55ALHXJ.js → dns-wakeup-KIURCCFJ.js} +4 -3
  142. package/bundle/{dns-wakeup-F55ALHXJ.js.map → dns-wakeup-KIURCCFJ.js.map} +1 -1
  143. package/bundle/{doctor-probes-3SLIUGKS.js → doctor-probes-46UKIROK.js} +4 -3
  144. package/bundle/{env-schema-MSDP2YBO.js → env-schema-YGHCKX5B.js} +5 -4
  145. package/bundle/{gossip-CS3G3447.js → gossip-VSEY2HSE.js} +7 -6
  146. package/bundle/{guardrails-24XK2COI.js → guardrails-U7M6H2GE.js} +6 -5
  147. package/bundle/{health-check-FRUNRVNQ.js → health-check-ASRLUJE5.js} +6 -2
  148. package/bundle/health-check-ASRLUJE5.js.map +7 -0
  149. package/bundle/{heartbeat-system-G4IFQXT6.js → heartbeat-system-MUXLT4E6.js} +7 -6
  150. package/bundle/{heartbeat-tier3-3ZO3EVXP.js → heartbeat-tier3-636ZMM4E.js} +45 -44
  151. package/bundle/heartbeat-tier3-636ZMM4E.js.map +7 -0
  152. package/bundle/{hook-system-X6INNJGV.js → hook-system-Z4XD6IM5.js} +5 -4
  153. package/bundle/{hotskills-6FQYTJIO.js → hotskills-AOUWVTQB.js} +7 -6
  154. package/bundle/{install-ZAHTZ5M5.js → install-3GGZUN22.js} +23 -20
  155. package/bundle/install-3GGZUN22.js.map +7 -0
  156. package/bundle/{install-manifest-QX7KVDCA.js → install-manifest-624KOB4S.js} +4 -3
  157. package/bundle/{install-manifest-QX7KVDCA.js.map → install-manifest-624KOB4S.js.map} +1 -1
  158. package/bundle/{irc-adapter-IEJQKKJF.js → irc-adapter-SA7GLJGR.js} +5 -4
  159. package/bundle/{irc-adapter-IEJQKKJF.js.map → irc-adapter-SA7GLJGR.js.map} +1 -1
  160. package/bundle/{irc-config-TTWNYFLH.js → irc-config-PG4X2I4M.js} +6 -5
  161. package/bundle/{irc-config-TTWNYFLH.js.map → irc-config-PG4X2I4M.js.map} +1 -1
  162. package/bundle/{kanban-board-J6RO3ZU7.js → kanban-board-4AI5Z6B5.js} +7 -5
  163. package/bundle/{kanban-channel-5EIXBFSA.js → kanban-channel-JMBYWGWD.js} +8 -6
  164. package/bundle/{lazy-require-V6EFUATC.js → lazy-require-GURNBC3C.js} +11 -6
  165. package/bundle/{logger-Y3VILPRH.js → logger-UQJPZMYV.js} +4 -3
  166. package/bundle/{logs-YS3GDURO.js → logs-2WTDLMB5.js} +5 -5
  167. package/bundle/{main-chat-YLZDNQPO.js → main-chat-EID5Y6H2.js} +6 -5
  168. package/bundle/{master-user-Z4M7KCJE.js → master-user-TKA7M2GL.js} +7 -6
  169. package/bundle/{media-utils-P6RZ2K3U.js → media-utils-X3UN342B.js} +44 -43
  170. package/bundle/{media-utils-P6RZ2K3U.js.map → media-utils-X3UN342B.js.map} +2 -2
  171. package/bundle/{message-pipeline-MHEBDJLH.js → message-pipeline-TAWXNEVS.js} +20 -20
  172. package/bundle/meta.json +9264 -8575
  173. package/bundle/{migrate-layout-RJJQLVGR.js → migrate-layout-KEAIIN26.js} +8 -4
  174. package/bundle/migrate-layout-KEAIIN26.js.map +7 -0
  175. package/bundle/{nerve-VZNMFDGY.js → nerve-TC34H4EL.js} +5 -4
  176. package/bundle/{notification-VV2OR6NW.js → notification-JQNVGICN.js} +8 -7
  177. package/bundle/{openrouter-credits-LXC7P4G6.js → openrouter-credits-5Q3EYWE5.js} +5 -4
  178. package/bundle/{openrouter-credits-LXC7P4G6.js.map → openrouter-credits-5Q3EYWE5.js.map} +1 -1
  179. package/bundle/{orc-KC4USP55.js → orc-74Z62W7B.js} +4 -4
  180. package/bundle/{orc-tools-CHRSXSAS.js → orc-tools-GME3DKIN.js} +5 -4
  181. package/bundle/{paths-EDK6KWHG.js → paths-BAUNPLNJ.js} +6 -2
  182. package/bundle/{paths-RZF6WDMG.js → paths-MZC2KU2C.js} +3 -2
  183. package/bundle/{peer-auth-SRONOLNG.js → peer-auth-VRO3JYL5.js} +9 -8
  184. package/bundle/{peer-client-VOF77T6C.js → peer-client-WLK5GZQS.js} +9 -8
  185. package/bundle/{peer-client-VOF77T6C.js.map → peer-client-WLK5GZQS.js.map} +1 -1
  186. package/bundle/{peer-config-FRWLEYQ5.js → peer-config-24WILLCJ.js} +6 -5
  187. package/bundle/{peer-jwt-XY3XRIA2.js → peer-jwt-ZR6RF3XM.js} +6 -5
  188. package/bundle/{peer-transport-UBBXTDRP.js → peer-transport-BK5VHI2M.js} +8 -7
  189. package/bundle/{phase-transport-4NQHZX75.js → phase-transport-7QJM7J6V.js} +18 -16
  190. package/bundle/{reconcile-2EUXJ6W5.js → reconcile-7N7OE2GU.js} +5 -4
  191. package/bundle/{reconciler-FFQGV4DO.js → reconciler-7LOOUK43.js} +13 -11
  192. package/bundle/{reconciler-FFQGV4DO.js.map → reconciler-7LOOUK43.js.map} +1 -1
  193. package/bundle/{restore-NFDE2RG6.js → restore-MENZ3I3K.js} +13 -9
  194. package/bundle/{restore-NFDE2RG6.js.map → restore-MENZ3I3K.js.map} +3 -3
  195. package/bundle/{rollback-MVZ53XS4.js → rollback-JOHY6KWW.js} +5 -5
  196. package/bundle/{chunk-SKY6656M.js → sandbox-runtime-T7RF4WJD.js} +11 -28
  197. package/bundle/{chunk-SKY6656M.js.map → sandbox-runtime-T7RF4WJD.js.map} +1 -1
  198. package/bundle/{self-healer-utils-KD6LV63S.js → self-healer-utils-OR2N6RLD.js} +5 -4
  199. package/bundle/{self-healer-utils-KD6LV63S.js.map → self-healer-utils-OR2N6RLD.js.map} +1 -1
  200. package/bundle/{sha-tracker-2DB4R2TW.js → sha-tracker-BXOLWZJL.js} +5 -4
  201. package/bundle/{skill-session-BPDVA6ZG.js → skill-session-H6EQ4NGN.js} +5 -4
  202. package/bundle/{skill-session-BPDVA6ZG.js.map → skill-session-H6EQ4NGN.js.map} +1 -1
  203. package/bundle/{skill-stats-TPD2NROA.js → skill-stats-7O777ZSZ.js} +6 -5
  204. package/bundle/{skill-watcher-D7QYYYON.js → skill-watcher-ZGLTDPG5.js} +6 -5
  205. package/bundle/{sleep-GH6DLBJJ.js → sleep-3LFZH727.js} +10 -9
  206. package/bundle/{soul-bundle-GXLMDBCC.js → soul-bundle-RQ2YQMJW.js} +10 -9
  207. package/bundle/{spin-4DBYHS3E.js → spin-76K4R6FK.js} +12 -10
  208. package/bundle/{spin-notifications-IKYJPER5.js → spin-notifications-LD46B4K5.js} +7 -5
  209. package/bundle/{spin-notifications-IKYJPER5.js.map → spin-notifications-LD46B4K5.js.map} +1 -1
  210. package/bundle/{spin-types-PLJH3SIK.js → spin-types-MOKTZXGB.js} +5 -4
  211. package/bundle/{src-SUFZ27S5.js → src-6BTCMOD3.js} +4 -4
  212. package/bundle/{sse-parser-anthropic-U7ILHOY5.js → sse-parser-anthropic-NV2CGBIT.js} +5 -4
  213. package/bundle/{sse-parser-anthropic-U7ILHOY5.js.map → sse-parser-anthropic-NV2CGBIT.js.map} +1 -1
  214. package/bundle/{sse-parser-responses-OI73R3AH.js → sse-parser-responses-FC3PFHQ5.js} +5 -4
  215. package/bundle/{sse-parser-responses-OI73R3AH.js.map → sse-parser-responses-FC3PFHQ5.js.map} +1 -1
  216. package/bundle/{ssrf-guard-6GP4QYVA.js → ssrf-guard-E2YPLW6G.js} +5 -4
  217. package/bundle/{ssrf-guard-6GP4QYVA.js.map → ssrf-guard-E2YPLW6G.js.map} +1 -1
  218. package/bundle/{start-JT2BPMSW.js → start-HPO5LYJP.js} +5 -5
  219. package/bundle/start-HPO5LYJP.js.map +7 -0
  220. package/bundle/{stt-KD3AABKG.js → stt-UE7EOYD7.js} +6 -5
  221. package/bundle/{subagent-runtime-LVECAUPV.js → subagent-runtime-4X3UHF4H.js} +6 -5
  222. package/bundle/system-status-PLPWV4RF.js +346 -0
  223. package/bundle/system-status-PLPWV4RF.js.map +7 -0
  224. package/bundle/{task-store-2XRDM3AW.js → task-store-RAFMDQ7N.js} +6 -5
  225. package/bundle/{telegram-adapter-UJ3RYYV6.js → telegram-adapter-PPXKTGOP.js} +35 -35
  226. package/bundle/{tool-registry-YU6WBXPA.js → tool-registry-NKIPNJZ5.js} +25 -23
  227. package/bundle/{tool-sandbox-RNNPDR5M.js → tool-sandbox-DQCP3UTU.js} +6 -5
  228. package/bundle/{transport-config-OK3MZPJK.js → transport-config-SF6GBV47.js} +9 -8
  229. package/bundle/{update-ENNPRW7Y.js → update-QOOGMFSJ.js} +6 -6
  230. package/bundle/{update-check-SJB6GV3A.js → update-check-LPZG3K5P.js} +3 -2
  231. package/bundle/{update-check-SJB6GV3A.js.map → update-check-LPZG3K5P.js.map} +1 -1
  232. package/bundle/{usage-tracker-HRSGC7QC.js → usage-tracker-TBDM4KE6.js} +2 -2
  233. package/bundle/{user-registry-6PUJJ5J2.js → user-registry-OYJVAHDD.js} +6 -5
  234. package/bundle/{wrapper-WLHLG4MI.js → wrapper-W66YICNZ.js} +3 -3
  235. package/bundle/{ws-peer-client-WHW3RJTD.js → ws-peer-client-G5QHOF6K.js} +15 -14
  236. package/bundle/{ws-peer-client-WHW3RJTD.js.map → ws-peer-client-G5QHOF6K.js.map} +2 -2
  237. package/package.json +3 -7
  238. package/scripts/emergency-deploy.sh +11 -8
  239. package/scripts/emergency-update.sh +156 -23
  240. package/templates/config/.env +1 -1
  241. package/templates/config/models.json +13 -0
  242. package/bundle/chunk-37EX63K4.js.map +0 -7
  243. package/bundle/chunk-3QW2K53E.js.map +0 -7
  244. package/bundle/chunk-72T2Q7IG.js.map +0 -7
  245. package/bundle/chunk-7RAGSHSH.js.map +0 -7
  246. package/bundle/chunk-BU7LTI2W.js.map +0 -7
  247. package/bundle/chunk-C3EYYJN3.js.map +0 -7
  248. package/bundle/chunk-CAOIIVFP.js +0 -110
  249. package/bundle/chunk-CAOIIVFP.js.map +0 -7
  250. package/bundle/chunk-EDZGF6BC.js.map +0 -7
  251. package/bundle/chunk-H2K23MOF.js.map +0 -7
  252. package/bundle/chunk-HAZHNBBY.js +0 -156
  253. package/bundle/chunk-HAZHNBBY.js.map +0 -7
  254. package/bundle/chunk-IXKQ4JMX.js.map +0 -7
  255. package/bundle/chunk-JAJ3DUQ2.js +0 -30
  256. package/bundle/chunk-JAJ3DUQ2.js.map +0 -7
  257. package/bundle/chunk-KMFR5AVY.js +0 -45
  258. package/bundle/chunk-KMFR5AVY.js.map +0 -7
  259. package/bundle/chunk-M6Q3IQ4H.js.map +0 -7
  260. package/bundle/chunk-MQJG7OJX.js.map +0 -7
  261. package/bundle/chunk-OY2HAK33.js.map +0 -7
  262. package/bundle/chunk-P5O6QZDC.js.map +0 -7
  263. package/bundle/chunk-RJX45XIC.js.map +0 -7
  264. package/bundle/chunk-S6HEHCCG.js.map +0 -7
  265. package/bundle/chunk-SESM4GBM.js.map +0 -7
  266. package/bundle/chunk-SXNY6HC4.js.map +0 -7
  267. package/bundle/chunk-VJATH7AN.js.map +0 -7
  268. package/bundle/chunk-ZY6DH2S4.js.map +0 -7
  269. package/bundle/deps-PHSLIA77.js.map +0 -7
  270. package/bundle/direct-api-transport-OAKYQBJR.js.map +0 -7
  271. package/bundle/dist-7HEHHQI2.js.map +0 -7
  272. package/bundle/health-check-FRUNRVNQ.js.map +0 -7
  273. package/bundle/heartbeat-tier3-3ZO3EVXP.js.map +0 -7
  274. package/bundle/install-ZAHTZ5M5.js.map +0 -7
  275. package/bundle/migrate-layout-RJJQLVGR.js.map +0 -7
  276. package/bundle/phase-config-V4XETN5F.js +0 -18
  277. package/bundle/sandbox-runtime-WHACQLLN.js +0 -22
  278. package/bundle/start-JT2BPMSW.js.map +0 -7
  279. package/bundle/system-status-XXJWTVJN.js +0 -243
  280. package/bundle/system-status-XXJWTVJN.js.map +0 -7
  281. package/bundle/user-registry-6PUJJ5J2.js.map +0 -7
  282. package/bundle/wrapper-WLHLG4MI.js.map +0 -7
  283. /package/bundle/{agent-api-rate-limit-4GEZ4YN5.js.map → agent-api-rate-limit-VENFGOAD.js.map} +0 -0
  284. /package/bundle/{agent-registry-563P4EUJ.js.map → agent-registry-DL7UT272.js.map} +0 -0
  285. /package/bundle/{bridge-lock-transport-LXCF2IVN.js.map → bridge-lock-transport-BJAMHMXW.js.map} +0 -0
  286. /package/bundle/{browser-2VZOGOGX.js.map → browser-PT54UWSW.js.map} +0 -0
  287. /package/bundle/{capability-WXEA2WFK.js.map → capability-EKPGHQIO.js.map} +0 -0
  288. /package/bundle/{chunk-4PIVWXUJ.js.map → chunk-2ZD7VQRW.js.map} +0 -0
  289. /package/bundle/{chunk-T7TAWGBX.js.map → chunk-52PQM4EZ.js.map} +0 -0
  290. /package/bundle/{chunk-2RGR3LSV.js.map → chunk-5P5HF7IJ.js.map} +0 -0
  291. /package/bundle/{chunk-OOKNHOCB.js.map → chunk-6S3G6GPO.js.map} +0 -0
  292. /package/bundle/{chunk-E7MV7WFT.js.map → chunk-6VTHSN4V.js.map} +0 -0
  293. /package/bundle/{chunk-NGZVJ52F.js.map → chunk-76YN7O3U.js.map} +0 -0
  294. /package/bundle/{chunk-43DKPXTP.js.map → chunk-7LORCJCQ.js.map} +0 -0
  295. /package/bundle/{chunk-HDOFJVFS.js.map → chunk-7OI46MH7.js.map} +0 -0
  296. /package/bundle/{chunk-CB6S3ZRF.js.map → chunk-AFFW2LRY.js.map} +0 -0
  297. /package/bundle/{chunk-TCI6FZTP.js.map → chunk-AHJDG6OM.js.map} +0 -0
  298. /package/bundle/{chunk-YME7NRGP.js.map → chunk-B2TIRDZC.js.map} +0 -0
  299. /package/bundle/{chunk-SSCGWDIC.js.map → chunk-BWJ37KMW.js.map} +0 -0
  300. /package/bundle/{chunk-ULO2PX3T.js.map → chunk-CCZ43JB7.js.map} +0 -0
  301. /package/bundle/{chunk-FVUL44T4.js.map → chunk-CNENVY37.js.map} +0 -0
  302. /package/bundle/{chunk-J5NOL4DB.js.map → chunk-DJOSXXM2.js.map} +0 -0
  303. /package/bundle/{chunk-DNDYD5SL.js.map → chunk-E7DZYCSF.js.map} +0 -0
  304. /package/bundle/{chunk-GCFIK6OB.js.map → chunk-FSGICOCX.js.map} +0 -0
  305. /package/bundle/{chunk-FJF42RZY.js.map → chunk-GHRLO2UL.js.map} +0 -0
  306. /package/bundle/{chunk-7WHXTCVD.js.map → chunk-HWFN7JGU.js.map} +0 -0
  307. /package/bundle/{chunk-KBPVJGD7.js.map → chunk-IXGDDDAB.js.map} +0 -0
  308. /package/bundle/{chunk-YEOZN5IE.js.map → chunk-JRGEEGZF.js.map} +0 -0
  309. /package/bundle/{chunk-56D3Y44D.js.map → chunk-KLG4SCF7.js.map} +0 -0
  310. /package/bundle/{chunk-ASYX43OU.js.map → chunk-LB43Q7G6.js.map} +0 -0
  311. /package/bundle/{chunk-TVSPVZTX.js.map → chunk-LN5MNDSA.js.map} +0 -0
  312. /package/bundle/{chunk-FIAVVKGN.js.map → chunk-MTE32OQH.js.map} +0 -0
  313. /package/bundle/{chunk-MV5KOWOR.js.map → chunk-N3Q3TASM.js.map} +0 -0
  314. /package/bundle/{chunk-IQKADER4.js.map → chunk-O4YBJS2K.js.map} +0 -0
  315. /package/bundle/{chunk-5V4VHKEA.js.map → chunk-OT6HLPEA.js.map} +0 -0
  316. /package/bundle/{chunk-V6CV3QPH.js.map → chunk-OWPQIBAO.js.map} +0 -0
  317. /package/bundle/{chunk-N5VROZ7A.js.map → chunk-QMP2KC4W.js.map} +0 -0
  318. /package/bundle/{chunk-4HNCOQSK.js.map → chunk-QOGZ7BFL.js.map} +0 -0
  319. /package/bundle/{chunk-2LKQV2ND.js.map → chunk-R23FHZRY.js.map} +0 -0
  320. /package/bundle/{chunk-TY26WMQY.js.map → chunk-RCWQ34QR.js.map} +0 -0
  321. /package/bundle/{chunk-ZOCEBV62.js.map → chunk-UU3RLJSD.js.map} +0 -0
  322. /package/bundle/{chunk-WP7FZHMI.js.map → chunk-W2PSVV2T.js.map} +0 -0
  323. /package/bundle/{chunk-V2QIAXWZ.js.map → chunk-WEGFRA6G.js.map} +0 -0
  324. /package/bundle/{chunk-O4GKI3Q3.js.map → chunk-X7DLKIQM.js.map} +0 -0
  325. /package/bundle/{chunk-BNBC4T45.js.map → chunk-XZ4ZBDM5.js.map} +0 -0
  326. /package/bundle/{chunk-24V4A6RP.js.map → chunk-YI2KSYB4.js.map} +0 -0
  327. /package/bundle/{chunk-IK4R3RBZ.js.map → chunk-YZCOA4DC.js.map} +0 -0
  328. /package/bundle/{chunk-2FZJDMAF.js.map → chunk-ZGNSCJWH.js.map} +0 -0
  329. /package/bundle/{chunk-W726UGI6.js.map → chunk-ZKMKAO75.js.map} +0 -0
  330. /package/bundle/{commands-XXFU2ZF7.js.map → commands-2JQ5YTJX.js.map} +0 -0
  331. /package/bundle/{config-EWDZ234X.js.map → config-ZEWIM5Z2.js.map} +0 -0
  332. /package/bundle/{config-show-6J33O4TE.js.map → config-show-WBJPQPRD.js.map} +0 -0
  333. /package/bundle/{daemon-LTDAXNA2.js.map → daemon-W7VQOSZC.js.map} +0 -0
  334. /package/bundle/{delegation-tools-YDTWQMZD.js.map → delegation-tools-VGTRFQBF.js.map} +0 -0
  335. /package/bundle/{deploy-lib-import-RGZJ3CGC.js.map → deploy-5AGIULM2.js.map} +0 -0
  336. /package/bundle/{doctor-probes-3SLIUGKS.js.map → deploy-lib-import-ZBDYORN4.js.map} +0 -0
  337. /package/bundle/{discord-adapter-WUNYPTDE.js.map → discord-adapter-LKBSIFLV.js.map} +0 -0
  338. /package/bundle/{env-schema-MSDP2YBO.js.map → doctor-probes-46UKIROK.js.map} +0 -0
  339. /package/bundle/{gossip-CS3G3447.js.map → env-schema-YGHCKX5B.js.map} +0 -0
  340. /package/bundle/{guardrails-24XK2COI.js.map → gossip-VSEY2HSE.js.map} +0 -0
  341. /package/bundle/{heartbeat-system-G4IFQXT6.js.map → guardrails-U7M6H2GE.js.map} +0 -0
  342. /package/bundle/{hook-system-X6INNJGV.js.map → heartbeat-system-MUXLT4E6.js.map} +0 -0
  343. /package/bundle/{hotskills-6FQYTJIO.js.map → hook-system-Z4XD6IM5.js.map} +0 -0
  344. /package/bundle/{kanban-board-J6RO3ZU7.js.map → hotskills-AOUWVTQB.js.map} +0 -0
  345. /package/bundle/{kanban-channel-5EIXBFSA.js.map → kanban-board-4AI5Z6B5.js.map} +0 -0
  346. /package/bundle/{lazy-require-V6EFUATC.js.map → kanban-channel-JMBYWGWD.js.map} +0 -0
  347. /package/bundle/{logger-Y3VILPRH.js.map → lazy-require-GURNBC3C.js.map} +0 -0
  348. /package/bundle/{main-chat-YLZDNQPO.js.map → logger-UQJPZMYV.js.map} +0 -0
  349. /package/bundle/{logs-YS3GDURO.js.map → logs-2WTDLMB5.js.map} +0 -0
  350. /package/bundle/{master-user-Z4M7KCJE.js.map → main-chat-EID5Y6H2.js.map} +0 -0
  351. /package/bundle/{message-pipeline-MHEBDJLH.js.map → master-user-TKA7M2GL.js.map} +0 -0
  352. /package/bundle/{nerve-VZNMFDGY.js.map → message-pipeline-TAWXNEVS.js.map} +0 -0
  353. /package/bundle/{notification-VV2OR6NW.js.map → nerve-TC34H4EL.js.map} +0 -0
  354. /package/bundle/{orc-tools-CHRSXSAS.js.map → notification-JQNVGICN.js.map} +0 -0
  355. /package/bundle/{orc-KC4USP55.js.map → orc-74Z62W7B.js.map} +0 -0
  356. /package/bundle/{paths-EDK6KWHG.js.map → orc-tools-GME3DKIN.js.map} +0 -0
  357. /package/bundle/{paths-RZF6WDMG.js.map → paths-BAUNPLNJ.js.map} +0 -0
  358. /package/bundle/{peer-auth-SRONOLNG.js.map → paths-MZC2KU2C.js.map} +0 -0
  359. /package/bundle/{peer-config-FRWLEYQ5.js.map → peer-auth-VRO3JYL5.js.map} +0 -0
  360. /package/bundle/{peer-jwt-XY3XRIA2.js.map → peer-config-24WILLCJ.js.map} +0 -0
  361. /package/bundle/{peer-transport-UBBXTDRP.js.map → peer-jwt-ZR6RF3XM.js.map} +0 -0
  362. /package/bundle/{phase-config-V4XETN5F.js.map → peer-transport-BK5VHI2M.js.map} +0 -0
  363. /package/bundle/{phase-transport-4NQHZX75.js.map → phase-transport-7QJM7J6V.js.map} +0 -0
  364. /package/bundle/{reconcile-2EUXJ6W5.js.map → reconcile-7N7OE2GU.js.map} +0 -0
  365. /package/bundle/{registry-client-VN2MM2HI.js.map → rollback-JOHY6KWW.js.map} +0 -0
  366. /package/bundle/{rollback-MVZ53XS4.js.map → sha-tracker-BXOLWZJL.js.map} +0 -0
  367. /package/bundle/{sandbox-runtime-WHACQLLN.js.map → skill-stats-7O777ZSZ.js.map} +0 -0
  368. /package/bundle/{sha-tracker-2DB4R2TW.js.map → skill-watcher-ZGLTDPG5.js.map} +0 -0
  369. /package/bundle/{skill-stats-TPD2NROA.js.map → sleep-3LFZH727.js.map} +0 -0
  370. /package/bundle/{skill-watcher-D7QYYYON.js.map → soul-bundle-RQ2YQMJW.js.map} +0 -0
  371. /package/bundle/{sleep-GH6DLBJJ.js.map → spin-76K4R6FK.js.map} +0 -0
  372. /package/bundle/{soul-bundle-GXLMDBCC.js.map → spin-types-MOKTZXGB.js.map} +0 -0
  373. /package/bundle/{spin-4DBYHS3E.js.map → src-6BTCMOD3.js.map} +0 -0
  374. /package/bundle/{spin-types-PLJH3SIK.js.map → stt-UE7EOYD7.js.map} +0 -0
  375. /package/bundle/{src-SUFZ27S5.js.map → subagent-runtime-4X3UHF4H.js.map} +0 -0
  376. /package/bundle/{stt-KD3AABKG.js.map → task-store-RAFMDQ7N.js.map} +0 -0
  377. /package/bundle/{telegram-adapter-UJ3RYYV6.js.map → telegram-adapter-PPXKTGOP.js.map} +0 -0
  378. /package/bundle/{subagent-runtime-LVECAUPV.js.map → tool-registry-NKIPNJZ5.js.map} +0 -0
  379. /package/bundle/{task-store-2XRDM3AW.js.map → tool-sandbox-DQCP3UTU.js.map} +0 -0
  380. /package/bundle/{tool-registry-YU6WBXPA.js.map → transport-config-SF6GBV47.js.map} +0 -0
  381. /package/bundle/{tool-sandbox-RNNPDR5M.js.map → update-QOOGMFSJ.js.map} +0 -0
  382. /package/bundle/{transport-config-OK3MZPJK.js.map → usage-tracker-TBDM4KE6.js.map} +0 -0
  383. /package/bundle/{update-ENNPRW7Y.js.map → user-registry-OYJVAHDD.js.map} +0 -0
  384. /package/bundle/{usage-tracker-HRSGC7QC.js.map → wrapper-W66YICNZ.js.map} +0 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/capabilities/browser/browser-manager.ts", "../src/capabilities/browser/browser-tool.ts", "../src/components/content-extractor.ts", "../src/capabilities/browser/browser-ipc-server.ts", "../src/capabilities/browser/domain-allowlist.ts"],
4
+ "sourcesContent": ["import { logAndSwallow } from \"../../components/log-and-swallow.js\";\nimport { logInfo, logWarn } from \"../../components/logger.js\";\nimport { getEnv } from \"../../components/env-schema.js\";\nimport type { Browser, BrowserContext, Page } from \"../../types/browser.js\";\nimport { execFileSync } from \"node:child_process\";\nimport type { BrowserSession } from \"../../types/browser.js\";\n\nconst TAG = \"browser_mgr\";\n\n// ---------------------------------------------------------------------------\n// Environment variable parsing\n\nfunction readPositiveInt(key: string, fallback: number): number {\n const raw = process.env[key];\n if (!raw) return fallback;\n const n = Number(raw);\n return Number.isFinite(n) && Number.isInteger(n) && n > 0 ? n : fallback;\n}\n// ---------------------------------------------------------------------------\n\n\nconst DEFAULTS = {\n BROWSER_SESSION_TIMEOUT_MS: 300_000,\n BROWSER_MAX_SESSIONS: 3,\n WEB_SCRAPE_USER_AGENT: \"Mozilla/5.0 (compatible; Abtars/1.0)\",\n} as const;\n\nexport type BrowserEngine = \"cloakbrowser\";\n\nexport interface BrowserConfig {\n sessionTimeoutMs: number;\n maxSessions: number;\n userAgent: string;\n engine: BrowserEngine;\n}\n\n/**\n * Read and validate browser-related env vars, returning resolved config.\n * Invalid values trigger a console.warn and fall back to defaults.\n * Exported for testability (Property 16).\n */\nexport function parseBrowserConfig(): BrowserConfig {\n const sessionTimeoutMs = readPositiveInt(\n \"BROWSER_SESSION_TIMEOUT_MS\",\n DEFAULTS.BROWSER_SESSION_TIMEOUT_MS,\n );\n const maxSessions = readPositiveInt(\n \"BROWSER_MAX_SESSIONS\",\n DEFAULTS.BROWSER_MAX_SESSIONS,\n );\n // Intentional: raw process.env \u2014 tests mutate this at runtime, getEnv() cache won't reflect changes\n const userAgent = process.env[\"WEB_SCRAPE_USER_AGENT\"]?.trim() || DEFAULTS.WEB_SCRAPE_USER_AGENT;\n\n const engine = \"cloakbrowser\" as BrowserEngine;\n\n return { sessionTimeoutMs, maxSessions, userAgent, engine };\n}\n\n// ---------------------------------------------------------------------------\n// BrowserManager singleton\n// ---------------------------------------------------------------------------\n\nexport class BrowserManager {\n private static _instance: BrowserManager | null = null;\n\n private _browser: Browser | null = null;\n private _launching: Promise<Browser> | null = null;\n private readonly _sessions = new Map<string, BrowserSession>();\n private _idleTimer: ReturnType<typeof setInterval> | null = null;\n private readonly _config: BrowserConfig;\n private _lastActivityAt = 0;\n private readonly _containerIdleStopMs: number;\n\n constructor(config?: BrowserConfig) {\n this._config = config ?? parseBrowserConfig();\n this._containerIdleStopMs = getEnv().browserIdleStopMin * 60_000;\n this._startIdleCheck();\n }\n\n /** Get (or create) the singleton instance. */\n static getInstance(): BrowserManager {\n if (!BrowserManager._instance) {\n BrowserManager._instance = new BrowserManager();\n }\n return BrowserManager._instance;\n }\n\n /** Reset singleton \u2014 primarily for testing. */\n static resetInstance(): void {\n BrowserManager._instance = null;\n }\n\n // -------------------------------------------------------------------------\n // Browser lifecycle\n // -------------------------------------------------------------------------\n\n /** Lazily launch or return the existing browser instance. */\n private async _ensureBrowser(): Promise<Browser> {\n if (this._browser?.isConnected()) return this._browser;\n\n // Avoid duplicate launches if multiple callers race.\n if (this._launching) return this._launching;\n\n this._launching = this._launchPatchright().then((browser) => {\n this._browser = browser;\n this._launching = null;\n browser.on(\"disconnected\", () => {\n this._browser = null;\n this._sessions.clear();\n });\n return browser;\n }).catch((err) => {\n this._launching = null;\n throw err;\n });\n\n return this._launching;\n }\n\n private async _launchPatchright(): Promise<Browser> {\n const { launch } = await import(\"cloakbrowser\");\n const headed = getEnv().browserHeaded;\n const args = headed ? [] : [\"--headless=new\"];\n if (getEnv().browserNoSandbox) args.push(\"--no-sandbox\");\n return launch({\n headless: !headed,\n channel: getEnv().browserChannel, // #1203: cloakbrowser LaunchOptions omits 'channel'; passed through to Playwright\n args,\n } as Parameters<typeof launch>[0]);\n }\n\n // -------------------------------------------------------------------------\n // Named sessions\n // -------------------------------------------------------------------------\n\n /**\n * Get or create a named browser session.\n * Reusing an existing session updates `lastActivityAt`.\n */\n async getSession(sessionId: string): Promise<BrowserSession> {\n const existing = this._sessions.get(sessionId);\n if (existing) {\n existing.lastActivityAt = Date.now();\n return existing;\n }\n\n // Enforce max sessions.\n if (this._sessions.size >= this._config.maxSessions) {\n const activeIds = [...this._sessions.keys()].join(\", \");\n throw new Error(\n `Maximum concurrent sessions (${this._config.maxSessions}) reached. ` +\n `Close an existing session first. Active sessions: ${activeIds}`,\n );\n }\n\n const browser = await this._ensureBrowser();\n const context = await browser.newContext({\n userAgent: this._config.userAgent,\n });\n const page = await context.newPage();\n const now = Date.now();\n\n const session: BrowserSession = {\n sessionId,\n context,\n page,\n createdAt: now,\n lastActivityAt: now,\n };\n\n this._sessions.set(sessionId, session);\n this._lastActivityAt = now;\n return session;\n }\n\n /** Close a named session and release its resources. */\n async closeSession(sessionId: string): Promise<void> {\n const session = this._sessions.get(sessionId);\n if (!session) return;\n\n this._sessions.delete(sessionId);\n try {\n await session.context.close();\n } catch (err) {\n logAndSwallow(TAG, \"closeSession context.close\", err);\n }\n }\n\n // -------------------------------------------------------------------------\n // One-off contexts (ingestion scrapes)\n // -------------------------------------------------------------------------\n\n /** Create a disposable context + page for ingestion. No session tracking. */\n async createOneOffContext(): Promise<{ context: BrowserContext; page: Page }> {\n const browser = await this._ensureBrowser();\n const context = await browser.newContext({\n userAgent: this._config.userAgent,\n });\n const page = await context.newPage();\n return { context, page };\n }\n\n /** Close a one-off context after use. */\n async closeContext(context: BrowserContext): Promise<void> {\n try {\n await context.close();\n } catch (err) {\n logAndSwallow(TAG, \"closeContext\", err);\n }\n }\n\n // -------------------------------------------------------------------------\n // Shutdown & cleanup\n // -------------------------------------------------------------------------\n\n /** Shut down everything: all sessions, the browser, cleanup timers. */\n async shutdown(): Promise<void> {\n this._stopIdleCheck();\n\n // Close all named sessions.\n const closePromises = [...this._sessions.keys()].map((id) =>\n this.closeSession(id),\n );\n await Promise.all(closePromises);\n\n // Close the browser itself.\n if (this._browser) {\n try {\n await this._browser.close();\n } catch (err) {\n logAndSwallow(TAG, \"browser.close shutdown\", err);\n }\n this._browser = null;\n }\n }\n\n // -------------------------------------------------------------------------\n // Idle-check interval\n // -------------------------------------------------------------------------\n\n private _startIdleCheck(): void {\n // Check every 30 seconds for idle sessions.\n this._idleTimer = setInterval(() => {\n void this._sweepIdleSessions();\n }, 30_000);\n\n // Don't prevent Node from exiting.\n if (this._idleTimer && typeof this._idleTimer === \"object\" && \"unref\" in this._idleTimer) {\n this._idleTimer.unref();\n }\n }\n\n private _stopIdleCheck(): void {\n if (this._idleTimer) {\n clearInterval(this._idleTimer);\n this._idleTimer = null;\n }\n }\n\n private async _sweepIdleSessions(): Promise<void> {\n const now = Date.now();\n const expired: string[] = [];\n\n for (const [id, session] of this._sessions) {\n if (now - session.lastActivityAt > this._config.sessionTimeoutMs) {\n expired.push(id);\n }\n }\n\n for (const id of expired) {\n logWarn(\"browser\", `Closing idle session \"${id}\".`);\n await this.closeSession(id);\n }\n\n // Stop container if no sessions and idle long enough\n if (this._sessions.size === 0 && this._browser && this._lastActivityAt > 0 && now - this._lastActivityAt > this._containerIdleStopMs) {\n logInfo(\"browser\", `No sessions for ${Math.round((now - this._lastActivityAt) / 60_000)}min \u2014 stopping container.`);\n await this.shutdown();\n this._stopContainer();\n }\n }\n\n private _stopContainer(): void {\n try {\n execFileSync(\"docker\", [\"stop\", \"abtars-browser\"], { stdio: \"pipe\", timeout: 10_000 });\n } catch (err) { logAndSwallow(\"browser_manager\", \"op\", err); }\n }\n\n // -------------------------------------------------------------------------\n // Accessors\n // -------------------------------------------------------------------------\n\n /** Number of active named sessions. */\n get activeSessionCount(): number {\n return this._sessions.size;\n }\n\n /** Exposed for testing \u2014 the resolved config. */\n get config(): BrowserConfig {\n return this._config;\n }\n}\n", "import { logDebug } from \"../../components/logger.js\";\nimport { logAndSwallow } from \"../../components/log-and-swallow.js\";\nimport { getEnv } from \"../../components/env-schema.js\";\n\nconst TAG = \"browser_tool\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { readFileSync } from \"node:fs\";\nimport type { BrowserAction, BrowserToolResult, PageElement } from \"../../types/browser.js\";\nimport type { BrowserManager } from \"./browser-manager.js\";\nimport type { DomainAllowlist } from \"./domain-allowlist.js\";\nimport { extractTextFromPage } from \"../../components/content-extractor.js\";\n\nconst LOG_PREFIX = \"[browser-tool]\";\n\n/** Max characters returned by extract_text before truncation. */\nconst TEXT_TRUNCATION_LIMIT = 4000;\n\n/** Max interactive elements returned by get_page_info. */\nconst MAX_PAGE_ELEMENTS = 50;\n\n/** Read navigation timeout from env, default 30 000 ms. */\nfunction getNavigationTimeout(): number {\n const raw = String(getEnv().webScrapePlaywrightTimeoutMs);\n if (raw === undefined || raw === \"\") return 30_000;\n const n = Number(raw);\n if (!Number.isFinite(n) || n <= 0) return 30_000;\n return n;\n}\n\n/**\n * Implements the seven browser actions (navigate, click, fill, extract_text,\n * screenshot, get_page_info, close_session). Pure action dispatch \u2014 receives\n * parsed args, calls BrowserManager + Playwright APIs, returns structured JSON.\n */\nexport class BrowserTool {\n private readonly _browserManager: BrowserManager;\n private readonly _domainAllowlist: DomainAllowlist;\n\n constructor(browserManager: BrowserManager, domainAllowlist: DomainAllowlist) {\n this._browserManager = browserManager;\n this._domainAllowlist = domainAllowlist;\n }\n\n /** Execute a browser action and return a JSON-serializable result. */\n async execute(action: BrowserAction): Promise<BrowserToolResult> {\n try {\n switch (action.action) {\n case \"navigate\":\n return await this._handleNavigate(action);\n case \"click\":\n return await this._handleClick(action);\n case \"fill\":\n return await this._handleFill(action);\n case \"extract_text\":\n return await this._handleExtractText(action);\n case \"screenshot\":\n return await this._handleScreenshot(action);\n case \"get_page_info\":\n return await this._handleGetPageInfo(action);\n case \"close_session\":\n return await this._handleCloseSession(action);\n case \"set_cookie\":\n return await this._handleSetCookie(action);\n default:\n return { success: false, error: `Unknown action: ${String((action as BrowserAction).action)}` };\n }\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { success: false, error: message };\n }\n }\n\n // -------------------------------------------------------------------------\n // navigate\n // -------------------------------------------------------------------------\n\n private async _handleNavigate(action: BrowserAction): Promise<BrowserToolResult> {\n const url = action.url;\n if (!url) {\n return { success: false, error: \"navigate action requires a url\" };\n }\n\n // Domain allowlist check\n if (!this._domainAllowlist.isAllowed(url)) {\n let hostname: string;\n try {\n hostname = new URL(url).hostname;\n } catch (err) {\n logAndSwallow(TAG, \"parse URL hostname\", err);\n hostname = url;\n }\n return {\n success: false,\n error: `Domain \"${hostname}\" is not in the allowed list. Allowed patterns: ${this._domainAllowlist.patterns.join(\", \")}`,\n };\n }\n\n // SSRF protection: reject private/internal IPs\n if (getEnv().ssrfCheck) {\n try {\n const { hostname } = new URL(url);\n const { isPrivateHost } = await import(\"./ssrf-guard.js\");\n if (await isPrivateHost(hostname)) {\n return { success: false, error: `Blocked: \"${hostname}\" resolves to a private/internal IP address` };\n }\n } catch (err) {\n logAndSwallow(TAG, \"SSRF check\", err);\n return { success: false, error: \"Invalid URL\" };\n }\n }\n\n const session = await this._browserManager.getSession(action.sessionId);\n const timeout = getNavigationTimeout();\n\n logDebug(\"browser\", `${LOG_PREFIX} navigate session=\"${action.sessionId}\" url=\"${url}\"`);\n\n try {\n const response = await session.page.goto(url, {\n waitUntil: \"domcontentloaded\",\n timeout,\n });\n\n const title = await session.page.title();\n const finalUrl = session.page.url();\n const status = response?.status();\n\n return { success: true, title, url: finalUrl, status };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n return { success: false, error: `Navigation failed for ${url}: ${message}` };\n }\n }\n\n // -------------------------------------------------------------------------\n // click\n // -------------------------------------------------------------------------\n\n private async _handleClick(action: BrowserAction): Promise<BrowserToolResult> {\n const selector = action.selector;\n if (!selector) {\n return { success: false, error: \"click action requires a selector\" };\n }\n\n const session = await this._browserManager.getSession(action.sessionId);\n\n logDebug(\"browser\", `${LOG_PREFIX} click session=\"${action.sessionId}\" selector=\"${selector}\"`);\n\n try {\n // Use Promise.race to detect if click triggers navigation\n const navigationPromise = session.page\n .waitForNavigation({ waitUntil: \"domcontentloaded\", timeout: 5000 })\n .catch((err: unknown) => { logAndSwallow(TAG, \"waitForNavigation click\", err); return null; });\n\n await session.page.click(selector);\n\n const navResult = await navigationPromise;\n\n if (navResult) {\n const title = await session.page.title();\n const url = session.page.url();\n return { success: true, navigated: true, title, url };\n }\n\n return { success: true, navigated: false };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"waiting for selector\") || message.includes(\"No element\")) {\n return { success: false, error: `Selector not found: \"${selector}\"` };\n }\n return { success: false, error: `Click failed for selector \"${selector}\": ${message}` };\n }\n }\n\n // -------------------------------------------------------------------------\n // fill\n // -------------------------------------------------------------------------\n\n private async _handleFill(action: BrowserAction): Promise<BrowserToolResult> {\n const selector = action.selector;\n const value = action.value;\n if (!selector) {\n return { success: false, error: \"fill action requires a selector\" };\n }\n if (value === undefined) {\n return { success: false, error: \"fill action requires a value\" };\n }\n\n const session = await this._browserManager.getSession(action.sessionId);\n\n // Check if the target is a password field to mask in logs\n let isPassword = false;\n try {\n isPassword = await session.page.evaluate(\n `(sel) => { const el = document.querySelector(sel); return el instanceof HTMLInputElement && el.type === \"password\"; }`,\n selector,\n ) as boolean;\n } catch (err) {\n logAndSwallow(TAG, \"evaluate isPassword\", err);\n }\n\n const logValue = isPassword ? \"***\" : value;\n logDebug(\"browser\",\n `${LOG_PREFIX} fill session=\"${action.sessionId}\" selector=\"${selector}\" value=\"${logValue}\"`,\n );\n\n try {\n await session.page.fill(selector, value);\n return { success: true };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"waiting for selector\") || message.includes(\"No element\")) {\n return { success: false, error: `Selector not found: \"${selector}\"` };\n }\n return { success: false, error: `Fill failed for selector \"${selector}\": ${message}` };\n }\n }\n\n // -------------------------------------------------------------------------\n // extract_text\n // -------------------------------------------------------------------------\n\n private async _handleExtractText(action: BrowserAction): Promise<BrowserToolResult> {\n const session = await this._browserManager.getSession(action.sessionId);\n\n logDebug(\"browser\",\n `${LOG_PREFIX} extract_text session=\"${action.sessionId}\" selector=\"${action.selector ?? \"(full page)\"}\"`,\n );\n\n try {\n const text = await extractTextFromPage(session.page, action.selector ?? undefined);\n\n if (!text || text.trim().length === 0) {\n return { success: false, error: \"No text content found on the page\" };\n }\n\n const truncated = text.length > TEXT_TRUNCATION_LIMIT;\n const resultText = truncated ? text.slice(0, TEXT_TRUNCATION_LIMIT) : text;\n\n return { success: true, text: resultText, truncated };\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (message.includes(\"waiting for selector\") || message.includes(\"No element\")) {\n return { success: false, error: `Selector not found: \"${action.selector}\"` };\n }\n return { success: false, error: `Text extraction failed: ${message}` };\n }\n }\n\n // -------------------------------------------------------------------------\n // screenshot\n // -------------------------------------------------------------------------\n\n private async _handleScreenshot(action: BrowserAction): Promise<BrowserToolResult> {\n const session = await this._browserManager.getSession(action.sessionId);\n\n const tmpFile = path.join(\n os.tmpdir(),\n `abtars-screenshot-${Date.now()}.png`,\n );\n\n logDebug(\"browser\",\n `${LOG_PREFIX} screenshot session=\"${action.sessionId}\" fullPage=${action.fullPage ?? false} path=\"${tmpFile}\"`,\n );\n\n await session.page.screenshot({\n fullPage: action.fullPage ?? false,\n path: tmpFile,\n });\n\n return { success: true, filePath: tmpFile };\n }\n\n // -------------------------------------------------------------------------\n // get_page_info\n // -------------------------------------------------------------------------\n\n private async _handleGetPageInfo(action: BrowserAction): Promise<BrowserToolResult> {\n const session = await this._browserManager.getSession(action.sessionId);\n\n logDebug(\"browser\", `${LOG_PREFIX} get_page_info session=\"${action.sessionId}\"`);\n\n const title = await session.page.title();\n const url = session.page.url();\n\n const elements = await session.page.evaluate(`(maxElements) => {\n const selectors = \"a, button, input, select, textarea, [role='button'], [role='link']\";\n const nodes = document.querySelectorAll(selectors);\n const results = [];\n\n for (let i = 0; i < nodes.length && results.length < maxElements; i++) {\n const el = nodes[i];\n if (!el || !(el instanceof HTMLElement)) continue;\n\n const style = window.getComputedStyle(el);\n if (style.display === \"none\" || style.visibility === \"hidden\") continue;\n\n let selector = el.tagName.toLowerCase();\n if (el.id) {\n selector = \"#\" + el.id;\n } else if (el.className && typeof el.className === \"string\" && el.className.trim()) {\n const cls = el.className.trim().split(/\\\\s+/).slice(0, 2).join(\".\");\n selector = el.tagName.toLowerCase() + \".\" + cls;\n } else {\n const parent = el.parentElement;\n if (parent) {\n const siblings = parent.querySelectorAll(\":scope > \" + el.tagName.toLowerCase());\n if (siblings.length > 1) {\n const idx = Array.from(siblings).indexOf(el) + 1;\n selector = el.tagName.toLowerCase() + \":nth-of-type(\" + idx + \")\";\n }\n }\n }\n\n const entry = { tag: el.tagName.toLowerCase(), selector };\n const text = (el.textContent || \"\").trim().slice(0, 100);\n if (text) entry.text = text;\n\n if (el instanceof HTMLInputElement || el instanceof HTMLSelectElement || el instanceof HTMLTextAreaElement) {\n if (el instanceof HTMLInputElement && el.type) entry.type = el.type;\n if (el.name) entry.name = el.name;\n if (el instanceof HTMLInputElement && el.placeholder) entry.placeholder = el.placeholder;\n if (el instanceof HTMLTextAreaElement && el.placeholder) entry.placeholder = el.placeholder;\n }\n\n if (el instanceof HTMLAnchorElement && el.href) {\n entry.href = el.href;\n }\n\n results.push(entry);\n }\n\n return results;\n }`, MAX_PAGE_ELEMENTS) as PageElement[];\n\n return {\n success: true,\n url,\n title,\n elements,\n };\n }\n\n // -------------------------------------------------------------------------\n // close_session\n // -------------------------------------------------------------------------\n\n private async _handleCloseSession(action: BrowserAction): Promise<BrowserToolResult> {\n logDebug(\"browser\", `${LOG_PREFIX} close_session session=\"${action.sessionId}\"`);\n await this._browserManager.closeSession(action.sessionId);\n return { success: true };\n }\n\n // -------------------------------------------------------------------------\n // set_cookie\n // -------------------------------------------------------------------------\n\n private async _handleSetCookie(action: BrowserAction): Promise<BrowserToolResult> {\n const file = action.cookieFile;\n if (!file) return { success: false, error: \"set_cookie requires --cookie-file\" };\n\n // Only allow files under /run/browser/cookies (mounted read-only)\n const COOKIES_DIR = \"/run/browser/cookies\";\n const resolved = path.resolve(file);\n if (!resolved.startsWith(COOKIES_DIR)) {\n return { success: false, error: `cookie file must be under ${COOKIES_DIR}` };\n }\n\n const raw = readFileSync(resolved, \"utf-8\");\n const json = JSON.parse(raw) as Record<string, string>;\n\n const session = await this._browserManager.getSession(action.sessionId);\n const url = action.url ?? session.page.url();\n let domain: string;\n try { domain = new URL(url).hostname; } catch (err) { logAndSwallow(TAG, \"parse cookie domain\", err); domain = \"\"; }\n\n const cookies = Object.entries(json).map(([name, value]) => ({\n name, value: String(value), domain, path: \"/\",\n }));\n\n await session.context.addCookies(cookies);\n logDebug(\"browser\", `${LOG_PREFIX} set_cookie session=\"${action.sessionId}\" loaded ${cookies.length} cookies for ${domain}`);\n return { success: true, text: `Loaded ${cookies.length} cookies for ${domain}` };\n }}\n", "import type { Page } from \"../types/browser.js\";\n\n/**\n * Strips non-content HTML elements and returns clean plain text.\n * Shared by both the agent tool's extract_text action and the ingestion WebScraper.\n *\n * Uses regex-based approach for raw HTML strings (no DOM available in Node.js).\n * Uses page.evaluate() for live Playwright pages (DOM APIs available in browser).\n */\n\n/** Tags whose entire content (including children) should be removed. */\nconst STRIPPED_TAGS = [\"script\", \"style\", \"nav\", \"footer\", \"header\", \"aside\"];\n\n/** Build a regex that matches an opening tag through its closing tag (non-greedy, case-insensitive). */\nfunction buildTagStripRegex(tag: string): RegExp {\n return new RegExp(`<${tag}[^>]*>[\\\\s\\\\S]*?<\\\\/${tag}>`, \"gi\");\n}\n\n/** Regex to match elements with role=\"navigation\" or role=\"banner\". */\nconst ROLE_STRIP_REGEX =\n /<[a-z][a-z0-9]*\\s[^>]*?\\brole\\s*=\\s*[\"'](navigation|banner)[\"'][^>]*>[\\s\\S]*?<\\/[a-z][a-z0-9]*>/gi;\n\n/** Regex to match any remaining HTML tag. */\nconst HTML_TAG_REGEX = /<[^>]+>/g;\n\n/** Common HTML entities to decode. */\nconst ENTITY_MAP: Record<string, string> = {\n \"&amp;\": \"&\",\n \"&lt;\": \"<\",\n \"&gt;\": \">\",\n \"&quot;\": '\"',\n \"&#39;\": \"'\",\n \"&nbsp;\": \" \",\n};\n\nconst ENTITY_REGEX = /&amp;|&lt;|&gt;|&quot;|&#39;|&nbsp;/g;\n\n/**\n * Parse raw HTML string and return clean text.\n * Removes non-content elements, strips tags, decodes entities, collapses whitespace.\n * Returns empty string on empty/whitespace-only input.\n */\nexport function extractTextFromHtml(html: string): string {\n if (!html || !html.trim()) return \"\";\n\n let text = html;\n\n // 1. Remove stripped tag elements and their content\n for (const tag of STRIPPED_TAGS) {\n text = text.replace(buildTagStripRegex(tag), \"\");\n }\n\n // 2. Remove elements with role=\"navigation\" or role=\"banner\"\n text = text.replace(ROLE_STRIP_REGEX, \"\");\n\n // 3. Strip all remaining HTML tags\n text = text.replace(HTML_TAG_REGEX, \" \");\n\n // 4. Decode common HTML entities\n text = text.replace(ENTITY_REGEX, (match) => ENTITY_MAP[match] ?? match);\n\n // 5. Collapse consecutive whitespace into single spaces/newlines\n // First normalize newlines, then collapse blank lines, then collapse spaces\n text = text.replace(/\\r\\n/g, \"\\n\");\n text = text.replace(/[ \\t]+/g, \" \");\n text = text.replace(/\\n[ ]+/g, \"\\n\");\n text = text.replace(/[ ]+\\n/g, \"\\n\");\n text = text.replace(/\\n{2,}/g, \"\\n\");\n\n return text.trim();\n}\n\n/**\n * JavaScript source executed inside the browser context via page.evaluate().\n * Uses DOM APIs (document, HTMLElement, etc.) which are only available at runtime.\n * Accepts a single argument: the CSS selector string or null for full-page extraction.\n */\nconst BROWSER_EXTRACT_FN = `\n(sel) => {\n const TAGS = [\"script\", \"style\", \"nav\", \"footer\", \"header\", \"aside\"];\n const ROLES = [\"navigation\", \"banner\"];\n\n const root = sel ? document.querySelector(sel) : document.body;\n if (!root) return \"\";\n\n const clone = root.cloneNode(true);\n\n for (const tag of TAGS) {\n for (const el of clone.querySelectorAll(tag)) el.remove();\n }\n for (const role of ROLES) {\n for (const el of clone.querySelectorAll('[role=\"' + role + '\"]')) el.remove();\n }\n\n let text = clone.textContent || \"\";\n text = text.replace(/\\\\u00a0/g, \" \");\n text = text.replace(/[ \\\\t]+/g, \" \");\n text = text.replace(/\\\\n[ ]+/g, \"\\\\n\");\n text = text.replace(/[ ]+\\\\n/g, \"\\\\n\");\n text = text.replace(/\\\\n{2,}/g, \"\\\\n\");\n return text.trim();\n}\n`;\n\n/**\n * Extract clean text from a live Playwright Page (runs in browser context).\n * Optionally scoped to a CSS selector. Returns empty string on failure.\n */\nexport async function extractTextFromPage(\n page: Page,\n selector?: string,\n): Promise<string> {\n const text = await page.evaluate<string, string | null>(\n new Function(\"sel\", `return (${BROWSER_EXTRACT_FN})(sel)`) as (sel: string | null) => string,\n selector ?? null,\n );\n\n return text ?? \"\";\n}\n", "import { logDebug } from \"../../components/logger.js\";\nimport { logAndSwallow } from \"../../components/log-and-swallow.js\";\nimport * as net from \"node:net\";\n\nconst TAG = \"browser_ipc\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { BrowserAction, BrowserToolResult } from \"../../types/browser.js\";\nimport type { BrowserTool } from \"./browser-tool.js\";\nimport { abtarsHome } from \"../../paths.js\";\n\nconst LOG_PREFIX = \"[browser-ipc]\";\n\n/** Default socket path: ~/.abtars/browser.sock */\nexport function getDefaultSocketPath(): string {\n return path.join(abtarsHome(), \"browser-socket\", \"browser.sock\");\n}\n\n/**\n * Unix domain socket server that routes BrowserAction requests\n * to a BrowserTool instance, enabling session persistence across\n * CLI invocations.\n *\n * Protocol: client connects \u2192 sends one JSON line \u2192 receives one JSON line \u2192 connection closes.\n */\nexport class BrowserIpcServer {\n private _server: net.Server | null = null;\n private readonly _tool: BrowserTool;\n private readonly _socketPath: string;\n\n constructor(tool: BrowserTool, socketPath?: string) {\n this._tool = tool;\n this._socketPath = socketPath ?? getDefaultSocketPath();\n }\n\n get socketPath(): string {\n return this._socketPath;\n }\n\n get isListening(): boolean {\n return this._server?.listening ?? false;\n }\n\n /** Start listening. Removes stale socket file if present. */\n async start(): Promise<void> {\n // Ensure parent directory exists.\n const dir = path.dirname(this._socketPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Remove stale socket file from a previous run.\n this._removeSocketFile();\n\n return new Promise<void>((resolve, reject) => {\n const server = net.createServer({ allowHalfOpen: true }, (conn) => {\n this._handleConnection(conn);\n });\n\n server.on(\"error\", (err) => {\n console.error(`${LOG_PREFIX} Server error: ${err.message}`);\n reject(err);\n });\n\n server.listen(this._socketPath, () => {\n this._server = server;\n logDebug(\"browser\", `${LOG_PREFIX} Listening on ${this._socketPath}`);\n resolve();\n });\n });\n }\n\n /** Stop the server and remove the socket file. */\n async shutdown(): Promise<void> {\n return new Promise<void>((resolve) => {\n if (!this._server) {\n this._removeSocketFile();\n resolve();\n return;\n }\n\n this._server.close(() => {\n this._server = null;\n this._removeSocketFile();\n logDebug(\"browser\", `${LOG_PREFIX} Shut down`);\n resolve();\n });\n });\n }\n\n // \u2500\u2500 Connection handler \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\n private _handleConnection(conn: net.Socket): void {\n let data = \"\";\n\n conn.on(\"data\", (chunk) => {\n data += chunk.toString();\n });\n\n conn.on(\"end\", () => {\n void this._processRequest(data, conn);\n });\n\n conn.on(\"error\", (err) => {\n console.error(`${LOG_PREFIX} Connection error: ${err.message}`);\n });\n }\n\n private async _processRequest(\n raw: string,\n conn: net.Socket,\n ): Promise<void> {\n let result: BrowserToolResult;\n\n try {\n const action = JSON.parse(raw.trim()) as BrowserAction;\n result = await this._tool.execute(action);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n result = { success: false, error: `IPC parse/execute error: ${message}` };\n }\n\n conn.end(JSON.stringify(result) + \"\\n\");\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\n\n private _removeSocketFile(): void {\n try {\n if (fs.existsSync(this._socketPath)) {\n fs.unlinkSync(this._socketPath);\n }\n } catch (err) {\n logAndSwallow(TAG, \"unlink socket\", err);\n }\n }\n}\n", "import { getEnv } from \"../../components/env-schema.js\";\nimport { logAndSwallow } from \"../../components/log-and-swallow.js\";\n\nconst TAG = \"domain_allowlist\";\n/**\n * Validates URLs against a configurable allowlist of domain patterns.\n * Prevents the agent from navigating to arbitrary domains.\n *\n * Pattern matching:\n * - `*.example.com` \u2192 matches any subdomain of example.com\n * - `example.com` \u2192 exact match only\n * - Empty list \u2192 open mode (all domains allowed)\n */\nexport class DomainAllowlist {\n private readonly _patterns: string[];\n\n constructor(patterns: string[]) {\n this._patterns = patterns\n .map((p) => p.trim().toLowerCase())\n .filter((p) => p.length > 0);\n }\n\n /** Check if a URL's hostname matches the allowlist. Returns true if allowed. */\n isAllowed(url: string): boolean {\n if (this._patterns.length === 0) return true;\n\n let hostname: string;\n try {\n hostname = new URL(url).hostname.toLowerCase();\n } catch (err) {\n logAndSwallow(TAG, \"parse URL\", err);\n return false;\n }\n\n return this._patterns.some((pattern) => {\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(2); // e.g. \"example.com\"\n return hostname === suffix || hostname.endsWith(`.${suffix}`);\n }\n return hostname === pattern;\n });\n }\n\n /** Get the list of configured patterns (for error messages). */\n get patterns(): string[] {\n return [...this._patterns];\n }\n\n /** True if no patterns configured (open mode). */\n get isOpenMode(): boolean {\n return this._patterns.length === 0;\n }\n\n /** Create a DomainAllowlist from the BROWSER_ALLOWED_DOMAINS env var. */\n static fromEnv(): DomainAllowlist {\n const raw = getEnv().browserAllowedDomains;\n const patterns = raw.split(\",\").map((s) => s.trim()).filter((s) => s.length > 0);\n return new DomainAllowlist(patterns);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["TAG", "path", "TAG", "LOG_PREFIX", "resolve", "TAG"]
7
+ }
@@ -3,11 +3,11 @@
3
3
  import {
4
4
  init_log_and_swallow,
5
5
  logAndSwallow
6
- } from "./chunk-WP7FZHMI.js";
6
+ } from "./chunk-W2PSVV2T.js";
7
7
  import {
8
8
  abtarsHome,
9
9
  init_paths
10
- } from "./chunk-H2K23MOF.js";
10
+ } from "./chunk-7XXISOHU.js";
11
11
 
12
12
  // src/components/tool-sandbox.ts
13
13
  init_paths();
@@ -127,4 +127,4 @@ export {
127
127
  auditDeny,
128
128
  ToolLoopGuard
129
129
  };
130
- //# sourceMappingURL=chunk-5V4VHKEA.js.map
130
+ //# sourceMappingURL=chunk-OT6HLPEA.js.map
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  init_logger,
5
5
  logTrace
6
- } from "./chunk-OOKNHOCB.js";
6
+ } from "./chunk-6S3G6GPO.js";
7
7
 
8
8
  // src/components/env.ts
9
9
  init_logger();
@@ -26,4 +26,4 @@ export {
26
26
  readEnv,
27
27
  readEnvWithDefault
28
28
  };
29
- //# sourceMappingURL=chunk-V6CV3QPH.js.map
29
+ //# sourceMappingURL=chunk-OWPQIBAO.js.map
@@ -1,5 +1,11 @@
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_paths
5
+ } from "./chunk-2BXXQG7P.js";
6
+
7
+ // src/cli/deploy-lib/index.ts
8
+ init_paths();
3
9
 
4
10
  // src/cli/deploy-lib/manifest.ts
5
11
  import { readFile, writeFile } from "node:fs/promises";
@@ -165,19 +171,20 @@ function configSnapshot(configDir) {
165
171
  }
166
172
  }
167
173
  }
168
- async function healthProbe(home, afterTimestamp, timeoutMs = 6e4) {
174
+ async function healthProbe(home, afterTimestamp, timeoutMs = 6e4, opts) {
169
175
  const lockPath = join(home, "bridge.lock");
170
176
  const deadline = Date.now() + timeoutMs;
177
+ const readLock2 = opts?.lockReader ?? ((p) => readFileSync(p, "utf-8"));
171
178
  const oldPid = (() => {
172
179
  try {
173
- return JSON.parse(readFileSync(lockPath, "utf-8")).pid;
180
+ return JSON.parse(readLock2(lockPath)).pid;
174
181
  } catch {
175
182
  return 0;
176
183
  }
177
184
  })();
178
185
  while (Date.now() < deadline) {
179
186
  try {
180
- const content = JSON.parse(await readFile3(lockPath, "utf-8"));
187
+ const content = JSON.parse(readLock2(lockPath));
181
188
  if (content.pid !== oldPid && content.lastHeartbeat && content.lastHeartbeat > afterTimestamp) {
182
189
  return { healthy: true, pid: content.pid, heartbeat: content.lastHeartbeat };
183
190
  }
@@ -303,4 +310,4 @@ export {
303
310
  removePath,
304
311
  safeCopyTree
305
312
  };
306
- //# sourceMappingURL=chunk-EDZGF6BC.js.map
313
+ //# sourceMappingURL=chunk-QJPDBJDP.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/deploy-lib/index.ts", "../src/cli/deploy-lib/manifest.ts", "../src/cli/deploy-lib/lock.ts", "../src/cli/deploy-lib/releases.ts", "../src/cli/deploy-lib/cleanup.ts", "../src/cli/deploy-lib/safe-copy.ts"],
4
+ "sourcesContent": ["/**\n * Deploy-lib: shared install/update/rollback primitives.\n *\n * Consumed by both `abmind` CLI (its own runtime at ~/.abmind) and by\n * `abtars` (via file:../abmind dependency, managing ~/.abtars).\n *\n * Entry points are the module files directly:\n * import { resolveAbtarsHome } from 'abmind/deploy-lib/paths.js'\n * import { readManifest, writeManifest } from 'abmind/deploy-lib/manifest.js'\n * etc.\n *\n * See abproject/docs/plans/158-deploy-rewrite.md for the full contract.\n */\n\nexport * from './paths.js';\nexport * from './manifest.js';\nexport * from './lock.js';\nexport * from './releases.js';\nexport * from './cleanup.js';\nexport * from './safe-copy.js';\n", "/**\n * Runtime manifest: the single source of truth for \"what's installed\".\n *\n * Location: $HOME/manifest.json (per packagePaths().manifest).\n * Read by: `status`, cross-package compatibility checks, doctor.\n * Written by: `install`, `update`, `rollback`, migrations.\n */\n\nimport { readFile, writeFile } from 'node:fs/promises';\n\nexport interface Manifest {\n readonly package: 'abtars' | 'abmind';\n /** Currently active release version. */\n readonly version: string;\n /** Git SHA of the source that produced the active release, if known. */\n readonly commit: string | null;\n /** Git branch, if known. */\n readonly branch: string | null;\n /** Hash of package-lock.json at time of last install. */\n readonly packageLockHash: string | null;\n /** ISO timestamp of when the active release became active. */\n readonly activatedAt: string;\n /** Hostname where install lives (informational). */\n readonly host: string;\n /** Source adapter that produced the current release. */\n readonly source: 'dev' | 'alpha' | 'stable' | 'local' | 'npm' | 'github';\n /** Applied migrations (ordered). */\n readonly migrationsApplied: readonly string[];\n /** Previous version (for rollback). Null on first install. */\n readonly previousVersion: string | null;\n /** Previous commit (for rollback reference). */\n readonly previousCommit: string | null;\n /** Install mode: simple (manual) or daemon (watchdog + OS integration if available). */\n readonly installMode?: 'simple' | 'daemon';\n /** Repo root path (set when source=local). Null for npm installs. */\n readonly repoRoot?: string | null;\n}\n\nexport async function readManifest(path: string): Promise<Manifest | null> {\n try {\n const raw = await readFile(path, 'utf-8');\n return JSON.parse(raw) as Manifest;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\nexport async function writeManifest(path: string, manifest: Manifest): Promise<void> {\n await writeFile(path, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\nexport function emptyManifest(pkg: 'abtars' | 'abmind', host: string): Manifest {\n return {\n package: pkg,\n version: '',\n commit: null,\n branch: null,\n packageLockHash: null,\n activatedAt: new Date().toISOString(),\n host,\n source: 'dev',\n migrationsApplied: [],\n previousVersion: null,\n previousCommit: null,\n };\n}\n", "/**\n * Update lock: prevents concurrent `install` / `update` / `rollback` runs\n * in the same runtime from colliding.\n *\n * Mechanism: write a JSON pidfile at packagePaths().lock. If file exists and\n * the PID is alive and the mtime is recent (<1h), refuse to proceed. Otherwise\n * take the lock.\n *\n * Stale timeout matches plan: 1 hour (our updates take minutes). Compared to\n * claude-code's 7-day timeout which accommodates laptop sleep during a long\n * install \u2014 not applicable for our short-lived updates.\n */\n\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { unlinkSync } from 'node:fs';\nimport { hostname } from 'node:os';\n\nconst STALE_MS = 5 * 60 * 1000; // 5 minutes \u2014 deploys take <2min\n\nexport interface LockContent {\n readonly pid: number;\n readonly host: string;\n readonly startedAt: string;\n readonly cmd: string;\n}\n\nexport class LockHeldError extends Error {\n constructor(\n public readonly content: LockContent,\n public readonly isStale: boolean,\n ) {\n const staleMsg = isStale ? ' (appears stale \u2014 process may have crashed)' : '';\n super(\n `Lock held by pid ${content.pid} since ${content.startedAt} ` +\n `(cmd: ${content.cmd})${staleMsg}`,\n );\n this.name = 'LockHeldError';\n }\n}\n\nfunction isPidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code === 'EPERM';\n }\n}\n\nasync function readLock(path: string): Promise<LockContent | null> {\n try {\n return JSON.parse(await readFile(path, 'utf-8')) as LockContent;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\n/**\n * Acquire the lock or throw LockHeldError. Returns a release function.\n * Caller must call release() on both success and failure; the returned\n * function is idempotent.\n */\nexport async function acquireLock(path: string, cmd: string): Promise<() => Promise<void>> {\n const existing = await readLock(path);\n if (existing) {\n const alive = isPidAlive(existing.pid);\n const started = Date.parse(existing.startedAt);\n const age = Date.now() - (Number.isFinite(started) ? started : 0);\n const stale = !alive || age > STALE_MS;\n if (!stale) {\n throw new LockHeldError(existing, false);\n }\n // Stale: fall through and take it, but tell the caller so doctor can surface.\n }\n\n const content: LockContent = {\n pid: process.pid,\n host: hostname(),\n startedAt: new Date().toISOString(),\n cmd,\n };\n await writeFile(path, JSON.stringify(content, null, 2) + '\\n', 'utf-8');\n\n let released = false;\n const release = async (): Promise<void> => {\n if (released) return;\n released = true;\n try {\n await unlink(path);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n };\n\n // Best-effort cleanup on unexpected exit.\n const exitHandler = (): void => {\n try {\n unlinkSync(path);\n } catch {\n /* ignore \u2014 stale detection handles orphans next run */\n }\n };\n process.once('exit', exitHandler);\n\n return release;\n}\n\nexport async function inspectLock(path: string): Promise<\n | { held: false }\n | { held: true; content: LockContent; stale: boolean }\n> {\n const content = await readLock(path);\n if (!content) return { held: false };\n const alive = isPidAlive(content.pid);\n const started = Date.parse(content.startedAt);\n const age = Date.now() - (Number.isFinite(started) ? started : 0);\n const stale = !alive || age > STALE_MS;\n return { held: true, content, stale };\n}\n", "/**\n * Deploy primitives: atomic swap, config snapshot, health probe, hash.\n *\n * #785: replaces the old releases/current symlink model with\n * app/ + app.prev/ atomic rename swap.\n */\n\nimport { createHash } from 'node:crypto';\nimport { existsSync, mkdirSync, rmSync, renameSync, readdirSync, cpSync, readFileSync, writeFileSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\n/**\n * Atomic swap with 3-prior rotation.\n * app.prev.3/ \u2192 delete, app.prev.2/ \u2192 .3, app.prev.1/ \u2192 .2, app/ \u2192 .prev.1, staging/ \u2192 app/\n * Backward compat: migrates old app.prev/ \u2192 app.prev.1/ if found.\n */\nexport function atomicSwap(appDir: string, _appPrevLegacy: string, appStagingDir: string): void {\n const prev1 = appDir.replace(/\\/app$/, '/app.prev.1');\n const prev2 = appDir.replace(/\\/app$/, '/app.prev.2');\n const prev3 = appDir.replace(/\\/app$/, '/app.prev.3');\n const legacyPrev = _appPrevLegacy; // app.prev/ (old format)\n\n // Migrate old app.prev/ \u2192 app.prev.1/ if exists\n if (existsSync(legacyPrev) && !existsSync(prev1)) {\n renameSync(legacyPrev, prev1);\n } else if (existsSync(legacyPrev)) {\n rmSync(legacyPrev, { recursive: true, force: true });\n }\n\n // Skip rotation if current app/ has same version as staging (no-op redeploy)\n try {\n const curPkg = join(appDir, \"package.json\");\n const stagePkg = join(appStagingDir, \"package.json\");\n if (existsSync(curPkg) && existsSync(stagePkg)) {\n const curVer = JSON.parse(readFileSync(curPkg, \"utf-8\")).version;\n const stageVer = JSON.parse(readFileSync(stagePkg, \"utf-8\")).version;\n if (curVer && curVer === stageVer) {\n // Same version \u2014 just replace app/ without rotating priors\n rmSync(appDir, { recursive: true, force: true });\n renameSync(appStagingDir, appDir);\n return;\n }\n }\n } catch { /* proceed with normal rotation if read fails */ }\n\n // Rotate: 3 \u2192 delete, 2 \u2192 3, 1 \u2192 2\n if (existsSync(prev3)) rmSync(prev3, { recursive: true, force: true });\n if (existsSync(prev2)) renameSync(prev2, prev3);\n if (existsSync(prev1)) renameSync(prev1, prev2);\n\n // app/ \u2192 app.prev.1/\n if (existsSync(appDir)) renameSync(appDir, prev1);\n\n // app.staging/ \u2192 app/\n renameSync(appStagingDir, appDir);\n}\n\n/**\n * Rotate config snapshots (3 slots) and create a fresh snapshot.\n * Excludes .pre-update* dirs from the copy to avoid recursion.\n */\nexport function configSnapshot(configDir: string): void {\n const slot0 = join(configDir, '.pre-update');\n const slot1 = join(configDir, '.pre-update.1');\n const slot2 = join(configDir, '.pre-update.2');\n\n // Rotate\n if (existsSync(slot2)) rmSync(slot2, { recursive: true, force: true });\n if (existsSync(slot1)) renameSync(slot1, slot2);\n if (existsSync(slot0)) renameSync(slot0, slot1);\n\n // Fresh snapshot \u2014 copy config/ contents excluding .pre-update* dirs\n mkdirSync(slot0, { recursive: true });\n if (!existsSync(configDir)) return;\n for (const entry of readdirSync(configDir, { withFileTypes: true })) {\n if (entry.name.startsWith('.pre-update')) continue;\n const src = join(configDir, entry.name);\n const dst = join(slot0, entry.name);\n if (entry.isDirectory()) {\n cpSync(src, dst, { recursive: true });\n } else {\n cpSync(src, dst);\n }\n }\n}\n\n/**\n * Poll bridge.lock for a fresh lastHeartbeat after restart.\n * Returns true if healthy within timeoutMs, false otherwise.\n */\nexport async function healthProbe(\n home: string,\n afterTimestamp: number,\n timeoutMs: number = 60_000,\n opts?: { lockReader?: (path: string) => string },\n): Promise<{ healthy: boolean; pid?: number; heartbeat?: number }> {\n const lockPath = join(home, 'bridge.lock');\n const deadline = Date.now() + timeoutMs;\n const readLock = opts?.lockReader ?? ((p: string) => readFileSync(p, 'utf-8'));\n const oldPid = (() => { try { return JSON.parse(readLock(lockPath)).pid; } catch { return 0; } })();\n while (Date.now() < deadline) {\n try {\n const content = JSON.parse(readLock(lockPath));\n // Verify bridge restarted (new PID) AND is healthy (fresh heartbeat)\n if (content.pid !== oldPid && content.lastHeartbeat && content.lastHeartbeat > afterTimestamp) {\n return { healthy: true, pid: content.pid, heartbeat: content.lastHeartbeat };\n }\n } catch {}\n await new Promise(r => setTimeout(r, 3000));\n }\n return { healthy: false };\n}\n\n/**\n * Write/read/clear the update sentinel.\n */\nexport interface UpdateSentinel {\n version: string;\n previousVersion: string | null;\n startedAt: string;\n status: 'pending' | 'success';\n}\n\nexport function writeSentinel(home: string, sentinel: UpdateSentinel): void {\n const dir = join(home, 'state');\n mkdirSync(dir, { recursive: true });\n writeFileSync(join(dir, 'update.sentinel'), JSON.stringify(sentinel, null, 2) + '\\n');\n}\n\nexport function readSentinel(home: string): UpdateSentinel | null {\n try {\n const content = readFileSync(join(home, 'state', 'update.sentinel'), 'utf-8');\n return JSON.parse(content);\n } catch {\n return null;\n }\n}\n\nexport function clearSentinel(home: string, _version: string): void {\n const path = join(home, 'state', 'update.sentinel');\n if (!existsSync(path)) return;\n try {\n const sentinel: UpdateSentinel = JSON.parse(readFileSync(path, 'utf-8'));\n sentinel.status = 'success';\n writeFileSync(path, JSON.stringify(sentinel, null, 2) + '\\n');\n } catch {\n // Best effort\n }\n}\n\nexport async function hashFile(path: string): Promise<string | null> {\n try {\n const buf = await readFile(path);\n return createHash('sha256').update(buf).digest('hex');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\n/**\n * Clean up stale app.staging/ from a previously interrupted update.\n */\nexport function cleanStaleStaging(stagingDir: string): void {\n if (existsSync(stagingDir)) {\n rmSync(stagingDir, { recursive: true, force: true });\n }\n}\n", "/**\n * Safety-guarded destructive ops for `reset` / `uninstall`.\n *\n * Cleanup utilities for deploy operations.\n * Key primitive: isUnsafeRemovalTarget() rejects catastrophic paths ('/',\n * '~', empty, etc.) BEFORE any caller invokes rm. Caller must always check.\n */\n\nimport { rm } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { resolve } from 'node:path';\n\n/**\n * True if the path is something we refuse to remove, regardless of flags.\n *\n * Rejects:\n * - empty / whitespace-only strings\n * - '/', '\\\\', or any path that resolves to root\n * - '~' (home), home dir itself, or parents of home\n * - Anything not under the user's home dir (defense-in-depth against\n * config pointing at /etc/... by mistake)\n *\n * Callers SHOULD still confirm with the user before removing even \"safe\"\n * paths; this function is a hard floor, not a substitute for confirmation.\n */\nexport function isUnsafeRemovalTarget(path: string): boolean {\n const trimmed = path.trim();\n if (trimmed === '') return true;\n if (trimmed === '~' || trimmed === '/' || trimmed === '\\\\') return true;\n const abs = resolve(trimmed);\n if (abs === '/' || abs === '') return true;\n const home = homedir();\n if (abs === home) return true;\n // Must be under home (defense in depth).\n const homeWithSep = home.endsWith('/') ? home : home + '/';\n if (!abs.startsWith(homeWithSep)) return true;\n return false;\n}\n\nexport interface RemovePlan {\n readonly path: string;\n readonly willRemove: boolean;\n readonly reason: string;\n}\n\n/**\n * Plan a remove without executing. Used by --dry-run flows in reset/uninstall.\n */\nexport function planRemoval(path: string): RemovePlan {\n if (isUnsafeRemovalTarget(path)) {\n return { path, willRemove: false, reason: 'refused: unsafe target' };\n }\n return { path, willRemove: true, reason: 'would remove recursively' };\n}\n\n/**\n * Remove a path after validating safety. Throws if the target is unsafe.\n * Returns true if the path was removed, false if it didn't exist.\n */\nexport async function removePath(path: string, opts: { dryRun?: boolean } = {}): Promise<boolean> {\n if (isUnsafeRemovalTarget(path)) {\n throw new Error(`Refused to remove unsafe target: ${path}`);\n }\n if (opts.dryRun) return true;\n try {\n await rm(path, { recursive: true });\n return true;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return false;\n throw err;\n }\n}\n", "/**\n * Safe recursive copy that skips non-regular-file entries Node's cp()\n * refuses to handle (EINVAL on sockets). Real runtime roots can contain\n * UNIX sockets (browser.sock, memory.sock, etc.) which are ephemeral IPC\n * endpoints \u2014 not data we want or can back up.\n *\n * Skipped: sockets, FIFOs, block devices, character devices.\n * Copied: regular files, directories, symlinks.\n */\n\nimport { cp, lstat } from 'node:fs/promises';\n\nexport interface SafeCopyOptions {\n readonly preserveTimestamps?: boolean;\n /** Overwrite existing entries at the destination. Default: false. */\n readonly force?: boolean;\n}\n\nasync function shouldCopy(src: string): Promise<boolean> {\n try {\n const s = await lstat(src);\n if (s.isSocket() || s.isFIFO() || s.isBlockDevice() || s.isCharacterDevice()) {\n return false;\n }\n return true;\n } catch {\n // Let the subsequent cp call surface the real error if any.\n return true;\n }\n}\n\nexport async function safeCopyTree(src: string, dst: string, opts: SafeCopyOptions = {}): Promise<void> {\n await cp(src, dst, {\n recursive: true,\n preserveTimestamps: opts.preserveTimestamps === true,\n force: opts.force === true,\n filter: shouldCopy,\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["readFile", "writeFile", "readFile", "readLock"]
7
+ }
@@ -3,19 +3,19 @@
3
3
  import {
4
4
  init_spin,
5
5
  spin
6
- } from "./chunk-GCFIK6OB.js";
6
+ } from "./chunk-FSGICOCX.js";
7
7
  import {
8
8
  addCompletion
9
9
  } from "./chunk-MV6CJFWR.js";
10
10
  import {
11
11
  getEnv,
12
12
  init_env_schema
13
- } from "./chunk-SSCGWDIC.js";
13
+ } from "./chunk-BWJ37KMW.js";
14
14
  import {
15
15
  init_logger,
16
16
  logInfo,
17
17
  logWarn
18
- } from "./chunk-OOKNHOCB.js";
18
+ } from "./chunk-6S3G6GPO.js";
19
19
 
20
20
  // src/components/transport/delegation-tools.ts
21
21
  init_spin();
@@ -56,7 +56,7 @@ var spawnSessionTool = {
56
56
  if (running.length >= MAX_BACKGROUND) {
57
57
  return JSON.stringify({ error: `Max ${MAX_BACKGROUND} concurrent background sessions. Wait for one to finish or terminate it.` });
58
58
  }
59
- const masterUid = (await import("./master-user-Z4M7KCJE.js")).getMasterUserId();
59
+ const masterUid = (await import("./master-user-TKA7M2GL.js")).getMasterUserId();
60
60
  const session = spin.createSubSession(masterUid, "telegram", typeInfo.sessionType);
61
61
  if (typeof session === "string") return JSON.stringify({ error: session });
62
62
  const goal = args.goal ?? "No goal specified";
@@ -216,4 +216,4 @@ export {
216
216
  consumePendingInstruction,
217
217
  getDelegationTools
218
218
  };
219
- //# sourceMappingURL=chunk-N5VROZ7A.js.map
219
+ //# sourceMappingURL=chunk-QMP2KC4W.js.map
@@ -2,30 +2,30 @@
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
3
  import {
4
4
  readEnvWithDefault
5
- } from "./chunk-V6CV3QPH.js";
5
+ } from "./chunk-OWPQIBAO.js";
6
6
  import {
7
7
  TRANSPORT_SCHEMA,
8
8
  init_config_validator,
9
9
  validateShape
10
- } from "./chunk-4PIVWXUJ.js";
10
+ } from "./chunk-2ZD7VQRW.js";
11
11
  import {
12
12
  getEnv,
13
13
  init_env_schema
14
- } from "./chunk-SSCGWDIC.js";
14
+ } from "./chunk-BWJ37KMW.js";
15
15
  import {
16
16
  init_log_and_swallow,
17
17
  logAndSwallow
18
- } from "./chunk-WP7FZHMI.js";
18
+ } from "./chunk-W2PSVV2T.js";
19
19
  import {
20
20
  init_logger,
21
21
  logError,
22
22
  logInfo,
23
23
  logWarn
24
- } from "./chunk-OOKNHOCB.js";
24
+ } from "./chunk-6S3G6GPO.js";
25
25
  import {
26
26
  abtarsHome,
27
27
  init_paths
28
- } from "./chunk-H2K23MOF.js";
28
+ } from "./chunk-7XXISOHU.js";
29
29
  import {
30
30
  __require
31
31
  } from "./chunk-7K2YZTLD.js";
@@ -411,4 +411,4 @@ export {
411
411
  validateProviderReady,
412
412
  formatValidationError
413
413
  };
414
- //# sourceMappingURL=chunk-4HNCOQSK.js.map
414
+ //# sourceMappingURL=chunk-QOGZ7BFL.js.map
@@ -6,12 +6,12 @@ import {
6
6
  import {
7
7
  getEnv,
8
8
  init_env_schema
9
- } from "./chunk-SSCGWDIC.js";
9
+ } from "./chunk-BWJ37KMW.js";
10
10
  import {
11
11
  init_logger,
12
12
  logError,
13
13
  logWarn
14
- } from "./chunk-OOKNHOCB.js";
14
+ } from "./chunk-6S3G6GPO.js";
15
15
 
16
16
  // src/components/main-chat.ts
17
17
  init_env_schema();
@@ -40,4 +40,4 @@ async function sendToMainChat(adapters, text, opts) {
40
40
  export {
41
41
  sendToMainChat
42
42
  };
43
- //# sourceMappingURL=chunk-2LKQV2ND.js.map
43
+ //# sourceMappingURL=chunk-R23FHZRY.js.map
@@ -2,15 +2,15 @@
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
3
  import {
4
4
  printBanner
5
- } from "./chunk-TVSPVZTX.js";
5
+ } from "./chunk-LN5MNDSA.js";
6
6
  import {
7
7
  init_log_and_swallow,
8
8
  logAndSwallow
9
- } from "./chunk-WP7FZHMI.js";
9
+ } from "./chunk-W2PSVV2T.js";
10
10
  import {
11
11
  abtarsHome,
12
12
  init_paths
13
- } from "./chunk-H2K23MOF.js";
13
+ } from "./chunk-7XXISOHU.js";
14
14
 
15
15
  // src/cli/commands/restart.ts
16
16
  init_paths();
@@ -66,11 +66,11 @@ async function restart(opts) {
66
66
  (await import("node:fs")).writeFileSync(join(home, "deploy.state"), JSON.stringify(s) + "\n");
67
67
  } catch {
68
68
  }
69
- const { start } = await import("./start-JT2BPMSW.js");
69
+ const { start } = await import("./start-HPO5LYJP.js");
70
70
  return start();
71
71
  }
72
72
  if (bridgeAlive) {
73
- const { writeRestartRequested } = await import("./bridge-lock-transport-LXCF2IVN.js");
73
+ const { writeRestartRequested } = await import("./bridge-lock-transport-BJAMHMXW.js");
74
74
  writeRestartRequested("restart");
75
75
  process.stdout.write(`\u267B\uFE0F Restart requested (PID ${bridgePid}) \u2014 bridge will restart within 30s
76
76
  `);
@@ -83,4 +83,4 @@ async function restart(opts) {
83
83
  export {
84
84
  restart
85
85
  };
86
- //# sourceMappingURL=chunk-SXNY6HC4.js.map
86
+ //# sourceMappingURL=chunk-R4GYWVCR.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/commands/restart.ts"],
4
+ "sourcesContent": ["import { printBanner } from './banner.js';\n/**\n * abtars restart [--cold] \u2014 unified restart command.\n * Warm (default): writeRestartRequested \u2192 main.ts internal loop restarts.\n * Cold (--cold): kill process, then start fresh.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { abtarsHome } from \"../../paths.js\";\nimport { logAndSwallow } from \"../../components/log-and-swallow.js\";\n\nfunction readJsonField(file: string, field: string): unknown {\n try { return JSON.parse(readFileSync(file, \"utf-8\"))[field]; } catch { return undefined; }\n}\n\nfunction pidAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\nasync function killBridge(pid: number): Promise<void> {\n try { process.kill(pid, \"SIGTERM\"); } catch { return; }\n process.stdout.write(`\uD83D\uDED1 Killing bridge (PID ${pid})...\\n`);\n for (let i = 0; i < 20; i++) {\n await new Promise(r => setTimeout(r, 500));\n if (!pidAlive(pid)) return;\n }\n try { process.kill(pid, \"SIGKILL\"); } catch (err) { logAndSwallow(\"restart\", \"op\", err); }\n await new Promise(r => setTimeout(r, 1000));\n}\n\nexport async function restart(opts: { cold?: boolean }): Promise<number> {\n await printBanner(\"restart\");\n const home = abtarsHome();\n const lockFile = join(home, \"bridge.lock\");\n const cold = opts.cold ?? false;\n\n const bridgePid = readJsonField(lockFile, \"pid\") as number | undefined;\n const bridgeAlive = bridgePid != null && bridgePid > 0 && pidAlive(bridgePid);\n\n if (cold) {\n if (bridgeAlive) await killBridge(bridgePid!);\n\n // Clear circuit breaker \u2014 intentional restart = clean slate\n try {\n const s = JSON.parse(readFileSync(join(home, \"deploy.state\"), \"utf-8\"));\n s.restartCount = 0;\n (await import(\"node:fs\")).writeFileSync(join(home, \"deploy.state\"), JSON.stringify(s) + \"\\n\");\n } catch {}\n\n // Start via the start command (handles both modes)\n const { start } = await import(\"./start.js\");\n return start();\n }\n\n // Warm restart\n if (bridgeAlive) {\n const { writeRestartRequested } = await import(\"../../components/transport/bridge-lock-transport.js\");\n writeRestartRequested(\"restart\");\n process.stdout.write(`\u267B\uFE0F Restart requested (PID ${bridgePid}) \u2014 bridge will restart within 30s\\n`);\n return 0;\n }\n\n process.stdout.write(\"Bridge not running. Use --cold to start fresh.\\n\");\n return 1;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;AASA;AACA;AAHA,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AAIrB,SAAS,cAAc,MAAc,OAAwB;AAC3D,MAAI;AAAE,WAAO,KAAK,MAAM,aAAa,MAAM,OAAO,CAAC,EAAE,KAAK;AAAA,EAAG,QAAQ;AAAE,WAAO;AAAA,EAAW;AAC3F;AAEA,SAAS,SAAS,KAAsB;AACtC,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAEA,eAAe,WAAW,KAA4B;AACpD,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,QAAQ;AAAE;AAAA,EAAQ;AACtD,UAAQ,OAAO,MAAM,iCAA0B,GAAG;AAAA,CAAQ;AAC1D,WAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,UAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAG,CAAC;AACzC,QAAI,CAAC,SAAS,GAAG,EAAG;AAAA,EACtB;AACA,MAAI;AAAE,YAAQ,KAAK,KAAK,SAAS;AAAA,EAAG,SAAS,KAAK;AAAE,kBAAc,WAAW,MAAM,GAAG;AAAA,EAAG;AACzF,QAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,GAAI,CAAC;AAC5C;AAEA,eAAsB,QAAQ,MAA2C;AACvE,QAAM,YAAY,SAAS;AAC3B,QAAM,OAAO,WAAW;AACxB,QAAM,WAAW,KAAK,MAAM,aAAa;AACzC,QAAM,OAAO,KAAK,QAAQ;AAE1B,QAAM,YAAY,cAAc,UAAU,KAAK;AAC/C,QAAM,cAAc,aAAa,QAAQ,YAAY,KAAK,SAAS,SAAS;AAE5E,MAAI,MAAM;AACR,QAAI,YAAa,OAAM,WAAW,SAAU;AAG5C,QAAI;AACF,YAAM,IAAI,KAAK,MAAM,aAAa,KAAK,MAAM,cAAc,GAAG,OAAO,CAAC;AACtE,QAAE,eAAe;AACjB,OAAC,MAAM,OAAO,SAAS,GAAG,cAAc,KAAK,MAAM,cAAc,GAAG,KAAK,UAAU,CAAC,IAAI,IAAI;AAAA,IAC9F,QAAQ;AAAA,IAAC;AAGT,UAAM,EAAE,MAAM,IAAI,MAAM,OAAO,qBAAY;AAC3C,WAAO,MAAM;AAAA,EACf;AAGA,MAAI,aAAa;AACf,UAAM,EAAE,sBAAsB,IAAI,MAAM,OAAO,qCAAqD;AACpG,0BAAsB,SAAS;AAC/B,YAAQ,OAAO,MAAM,uCAA6B,SAAS;AAAA,CAAsC;AACjG,WAAO;AAAA,EACT;AAEA,UAAQ,OAAO,MAAM,kDAAkD;AACvE,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -5,9 +5,9 @@ import {
5
5
  __require
6
6
  } from "./chunk-7K2YZTLD.js";
7
7
 
8
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js
8
+ // node_modules/ws/lib/constants.js
9
9
  var require_constants = __commonJS({
10
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/constants.js"(exports, module) {
10
+ "node_modules/ws/lib/constants.js"(exports, module) {
11
11
  "use strict";
12
12
  var BINARY_TYPES = ["nodebuffer", "arraybuffer", "fragments"];
13
13
  var hasBlob = typeof Blob !== "undefined";
@@ -28,9 +28,9 @@ var require_constants = __commonJS({
28
28
  }
29
29
  });
30
30
 
31
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/buffer-util.js
31
+ // node_modules/ws/lib/buffer-util.js
32
32
  var require_buffer_util = __commonJS({
33
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/buffer-util.js"(exports, module) {
33
+ "node_modules/ws/lib/buffer-util.js"(exports, module) {
34
34
  "use strict";
35
35
  var { EMPTY_BUFFER } = require_constants();
36
36
  var FastBuffer = Buffer[Symbol.species];
@@ -103,9 +103,9 @@ var require_buffer_util = __commonJS({
103
103
  }
104
104
  });
105
105
 
106
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/limiter.js
106
+ // node_modules/ws/lib/limiter.js
107
107
  var require_limiter = __commonJS({
108
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/limiter.js"(exports, module) {
108
+ "node_modules/ws/lib/limiter.js"(exports, module) {
109
109
  "use strict";
110
110
  var kDone = Symbol("kDone");
111
111
  var kRun = Symbol("kRun");
@@ -153,9 +153,9 @@ var require_limiter = __commonJS({
153
153
  }
154
154
  });
155
155
 
156
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/permessage-deflate.js
156
+ // node_modules/ws/lib/permessage-deflate.js
157
157
  var require_permessage_deflate = __commonJS({
158
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/permessage-deflate.js"(exports, module) {
158
+ "node_modules/ws/lib/permessage-deflate.js"(exports, module) {
159
159
  "use strict";
160
160
  var zlib = __require("zlib");
161
161
  var bufferUtil = require_buffer_util();
@@ -536,9 +536,9 @@ var require_permessage_deflate = __commonJS({
536
536
  }
537
537
  });
538
538
 
539
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/validation.js
539
+ // node_modules/ws/lib/validation.js
540
540
  var require_validation = __commonJS({
541
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/validation.js"(exports, module) {
541
+ "node_modules/ws/lib/validation.js"(exports, module) {
542
542
  "use strict";
543
543
  var { isUtf8 } = __require("buffer");
544
544
  var { hasBlob } = require_constants();
@@ -737,9 +737,9 @@ var require_validation = __commonJS({
737
737
  }
738
738
  });
739
739
 
740
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/receiver.js
740
+ // node_modules/ws/lib/receiver.js
741
741
  var require_receiver = __commonJS({
742
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/receiver.js"(exports, module) {
742
+ "node_modules/ws/lib/receiver.js"(exports, module) {
743
743
  "use strict";
744
744
  var { Writable } = __require("stream");
745
745
  var PerMessageDeflate = require_permessage_deflate();
@@ -1369,9 +1369,9 @@ var require_receiver = __commonJS({
1369
1369
  }
1370
1370
  });
1371
1371
 
1372
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/sender.js
1372
+ // node_modules/ws/lib/sender.js
1373
1373
  var require_sender = __commonJS({
1374
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/sender.js"(exports, module) {
1374
+ "node_modules/ws/lib/sender.js"(exports, module) {
1375
1375
  "use strict";
1376
1376
  var { Duplex } = __require("stream");
1377
1377
  var { randomFillSync } = __require("crypto");
@@ -1862,9 +1862,9 @@ var require_sender = __commonJS({
1862
1862
  }
1863
1863
  });
1864
1864
 
1865
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/extension.js
1865
+ // node_modules/ws/lib/extension.js
1866
1866
  var require_extension = __commonJS({
1867
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/extension.js"(exports, module) {
1867
+ "node_modules/ws/lib/extension.js"(exports, module) {
1868
1868
  "use strict";
1869
1869
  var { tokenChars } = require_validation();
1870
1870
  function push(dest, name, elem) {
@@ -2015,9 +2015,9 @@ var require_extension = __commonJS({
2015
2015
  }
2016
2016
  });
2017
2017
 
2018
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/event-target.js
2018
+ // node_modules/ws/lib/event-target.js
2019
2019
  var require_event_target = __commonJS({
2020
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/event-target.js"(exports, module) {
2020
+ "node_modules/ws/lib/event-target.js"(exports, module) {
2021
2021
  "use strict";
2022
2022
  var { kForOnEventAttribute, kListener } = require_constants();
2023
2023
  var kCode = Symbol("kCode");
@@ -2244,9 +2244,9 @@ var require_event_target = __commonJS({
2244
2244
  }
2245
2245
  });
2246
2246
 
2247
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket.js
2247
+ // node_modules/ws/lib/websocket.js
2248
2248
  var require_websocket = __commonJS({
2249
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket.js"(exports, module) {
2249
+ "node_modules/ws/lib/websocket.js"(exports, module) {
2250
2250
  "use strict";
2251
2251
  var EventEmitter = __require("events");
2252
2252
  var https = __require("https");
@@ -3140,9 +3140,9 @@ var require_websocket = __commonJS({
3140
3140
  }
3141
3141
  });
3142
3142
 
3143
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/stream.js
3143
+ // node_modules/ws/lib/stream.js
3144
3144
  var require_stream = __commonJS({
3145
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/stream.js"(exports, module) {
3145
+ "node_modules/ws/lib/stream.js"(exports, module) {
3146
3146
  "use strict";
3147
3147
  var WebSocket = require_websocket();
3148
3148
  var { Duplex } = __require("stream");
@@ -3238,9 +3238,9 @@ var require_stream = __commonJS({
3238
3238
  }
3239
3239
  });
3240
3240
 
3241
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js
3241
+ // node_modules/ws/lib/subprotocol.js
3242
3242
  var require_subprotocol = __commonJS({
3243
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
3243
+ "node_modules/ws/lib/subprotocol.js"(exports, module) {
3244
3244
  "use strict";
3245
3245
  var { tokenChars } = require_validation();
3246
3246
  function parse(header) {
@@ -3283,9 +3283,9 @@ var require_subprotocol = __commonJS({
3283
3283
  }
3284
3284
  });
3285
3285
 
3286
- // node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket-server.js
3286
+ // node_modules/ws/lib/websocket-server.js
3287
3287
  var require_websocket_server = __commonJS({
3288
- "node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/websocket-server.js"(exports, module) {
3288
+ "node_modules/ws/lib/websocket-server.js"(exports, module) {
3289
3289
  "use strict";
3290
3290
  var EventEmitter = __require("events");
3291
3291
  var http = __require("http");
@@ -3694,4 +3694,4 @@ export {
3694
3694
  require_subprotocol,
3695
3695
  require_websocket_server
3696
3696
  };
3697
- //# sourceMappingURL=chunk-S7ZIGIR5.js.map
3697
+ //# sourceMappingURL=chunk-R76K6L6H.js.map