abtars 0.1.0-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 (312) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +84 -0
  3. package/bundle/_registry.generated-M4WY2MMI.js +35 -0
  4. package/bundle/_registry.generated-M4WY2MMI.js.map +7 -0
  5. package/bundle/abtars-browser.js +162 -0
  6. package/bundle/abtars-browser.js.map +7 -0
  7. package/bundle/abtars-cli.js +1438 -0
  8. package/bundle/abtars-cli.js.map +7 -0
  9. package/bundle/abtars-restart.js +12 -0
  10. package/bundle/abtars-restart.js.map +7 -0
  11. package/bundle/abtars-rss.js +165 -0
  12. package/bundle/abtars-rss.js.map +7 -0
  13. package/bundle/abtars-task.js +258 -0
  14. package/bundle/abtars-task.js.map +7 -0
  15. package/bundle/abtars.js +4072 -0
  16. package/bundle/abtars.js.map +7 -0
  17. package/bundle/agent-api-rate-limit-OQNFMXTZ.js +38 -0
  18. package/bundle/agent-api-rate-limit-OQNFMXTZ.js.map +7 -0
  19. package/bundle/agent-registry-LT4JNQH6.js +18 -0
  20. package/bundle/agent-registry-LT4JNQH6.js.map +7 -0
  21. package/bundle/agents/default.md +29 -0
  22. package/bundle/anthropic-adapter-2APTH3LA.js +40 -0
  23. package/bundle/anthropic-adapter-2APTH3LA.js.map +7 -0
  24. package/bundle/bridge-lock-transport-4AC2G5G6.js +39 -0
  25. package/bundle/bridge-lock-transport-4AC2G5G6.js.map +7 -0
  26. package/bundle/browse-delivery-JXBY36GK.js +17 -0
  27. package/bundle/browse-delivery-JXBY36GK.js.map +7 -0
  28. package/bundle/browser-ELNDVPLC.js +18 -0
  29. package/bundle/browser-ELNDVPLC.js.map +7 -0
  30. package/bundle/capability-CIL3G4FI.js +17 -0
  31. package/bundle/capability-CIL3G4FI.js.map +7 -0
  32. package/bundle/chunk-265TPOPC.js +289 -0
  33. package/bundle/chunk-265TPOPC.js.map +7 -0
  34. package/bundle/chunk-2UENBO6M.js +223 -0
  35. package/bundle/chunk-2UENBO6M.js.map +7 -0
  36. package/bundle/chunk-2UPU3OW6.js +67 -0
  37. package/bundle/chunk-2UPU3OW6.js.map +7 -0
  38. package/bundle/chunk-2XU2X4OI.js +125 -0
  39. package/bundle/chunk-2XU2X4OI.js.map +7 -0
  40. package/bundle/chunk-3B7BBE4F.js +758 -0
  41. package/bundle/chunk-3B7BBE4F.js.map +7 -0
  42. package/bundle/chunk-3E545J66.js +69 -0
  43. package/bundle/chunk-3E545J66.js.map +7 -0
  44. package/bundle/chunk-5R2ANXQ7.js +510 -0
  45. package/bundle/chunk-5R2ANXQ7.js.map +7 -0
  46. package/bundle/chunk-6CPN4IGS.js +507 -0
  47. package/bundle/chunk-6CPN4IGS.js.map +7 -0
  48. package/bundle/chunk-6NR3OHEW.js +88 -0
  49. package/bundle/chunk-6NR3OHEW.js.map +7 -0
  50. package/bundle/chunk-6SETMHNN.js +206 -0
  51. package/bundle/chunk-6SETMHNN.js.map +7 -0
  52. package/bundle/chunk-6UCRKRWR.js +644 -0
  53. package/bundle/chunk-6UCRKRWR.js.map +7 -0
  54. package/bundle/chunk-AR6GO6YC.js +83 -0
  55. package/bundle/chunk-AR6GO6YC.js.map +7 -0
  56. package/bundle/chunk-AZJIODTQ.js +54 -0
  57. package/bundle/chunk-AZJIODTQ.js.map +7 -0
  58. package/bundle/chunk-BHMZ4RCC.js +3706 -0
  59. package/bundle/chunk-BHMZ4RCC.js.map +7 -0
  60. package/bundle/chunk-BQ2L4GMG.js +9175 -0
  61. package/bundle/chunk-BQ2L4GMG.js.map +7 -0
  62. package/bundle/chunk-BSSBCSCL.js +159 -0
  63. package/bundle/chunk-BSSBCSCL.js.map +7 -0
  64. package/bundle/chunk-BUUVFUPO.js +157 -0
  65. package/bundle/chunk-BUUVFUPO.js.map +7 -0
  66. package/bundle/chunk-CEVRHKJY.js +131 -0
  67. package/bundle/chunk-CEVRHKJY.js.map +7 -0
  68. package/bundle/chunk-CWOHNFUV.js +39 -0
  69. package/bundle/chunk-CWOHNFUV.js.map +7 -0
  70. package/bundle/chunk-D2DCBO6M.js +228 -0
  71. package/bundle/chunk-D2DCBO6M.js.map +7 -0
  72. package/bundle/chunk-FMWKEPM7.js +31 -0
  73. package/bundle/chunk-FMWKEPM7.js.map +7 -0
  74. package/bundle/chunk-GRNENTPA.js +145 -0
  75. package/bundle/chunk-GRNENTPA.js.map +7 -0
  76. package/bundle/chunk-GST5T3WZ.js +93 -0
  77. package/bundle/chunk-GST5T3WZ.js.map +7 -0
  78. package/bundle/chunk-GUQVJC3U.js +299 -0
  79. package/bundle/chunk-GUQVJC3U.js.map +7 -0
  80. package/bundle/chunk-HX7Y7EYP.js +3659 -0
  81. package/bundle/chunk-HX7Y7EYP.js.map +7 -0
  82. package/bundle/chunk-JCJS4ZIB.js +296 -0
  83. package/bundle/chunk-JCJS4ZIB.js.map +7 -0
  84. package/bundle/chunk-JW6RU47G.js +184 -0
  85. package/bundle/chunk-JW6RU47G.js.map +7 -0
  86. package/bundle/chunk-LSPKJQCI.js +24 -0
  87. package/bundle/chunk-LSPKJQCI.js.map +7 -0
  88. package/bundle/chunk-M6VBAPNT.js +16 -0
  89. package/bundle/chunk-M6VBAPNT.js.map +7 -0
  90. package/bundle/chunk-MPX525QO.js +129 -0
  91. package/bundle/chunk-MPX525QO.js.map +7 -0
  92. package/bundle/chunk-MW6WDLU7.js +130 -0
  93. package/bundle/chunk-MW6WDLU7.js.map +7 -0
  94. package/bundle/chunk-NT3OBORC.js +215 -0
  95. package/bundle/chunk-NT3OBORC.js.map +7 -0
  96. package/bundle/chunk-NWDBD4PA.js +50 -0
  97. package/bundle/chunk-NWDBD4PA.js.map +7 -0
  98. package/bundle/chunk-OP7BTAWY.js +29 -0
  99. package/bundle/chunk-OP7BTAWY.js.map +7 -0
  100. package/bundle/chunk-PLCY3GFH.js +77 -0
  101. package/bundle/chunk-PLCY3GFH.js.map +7 -0
  102. package/bundle/chunk-PNEDC45Y.js +97 -0
  103. package/bundle/chunk-PNEDC45Y.js.map +7 -0
  104. package/bundle/chunk-QBGBT5QS.js +81 -0
  105. package/bundle/chunk-QBGBT5QS.js.map +7 -0
  106. package/bundle/chunk-RVE2N7FA.js +70 -0
  107. package/bundle/chunk-RVE2N7FA.js.map +7 -0
  108. package/bundle/chunk-TZHIDLDS.js +71910 -0
  109. package/bundle/chunk-TZHIDLDS.js.map +7 -0
  110. package/bundle/chunk-UCQ2WC3B.js +126 -0
  111. package/bundle/chunk-UCQ2WC3B.js.map +7 -0
  112. package/bundle/chunk-UHRP745J.js +214 -0
  113. package/bundle/chunk-UHRP745J.js.map +7 -0
  114. package/bundle/chunk-V76TVMCM.js +58 -0
  115. package/bundle/chunk-V76TVMCM.js.map +7 -0
  116. package/bundle/chunk-VVEDVGCR.js +981 -0
  117. package/bundle/chunk-VVEDVGCR.js.map +7 -0
  118. package/bundle/chunk-W6FAL35D.js +102 -0
  119. package/bundle/chunk-W6FAL35D.js.map +7 -0
  120. package/bundle/chunk-X6TERNVJ.js +15902 -0
  121. package/bundle/chunk-X6TERNVJ.js.map +7 -0
  122. package/bundle/chunk-X76UX47U.js +47 -0
  123. package/bundle/chunk-X76UX47U.js.map +7 -0
  124. package/bundle/chunk-XREWVCUO.js +518 -0
  125. package/bundle/chunk-XREWVCUO.js.map +7 -0
  126. package/bundle/chunk-Y6XAEX2Q.js +408 -0
  127. package/bundle/chunk-Y6XAEX2Q.js.map +7 -0
  128. package/bundle/chunk-YOCTDKKL.js +28 -0
  129. package/bundle/chunk-YOCTDKKL.js.map +7 -0
  130. package/bundle/chunk-ZXPXCDA6.js +160 -0
  131. package/bundle/chunk-ZXPXCDA6.js.map +7 -0
  132. package/bundle/commands-BHVUOU3V.js +31 -0
  133. package/bundle/commands-BHVUOU3V.js.map +7 -0
  134. package/bundle/completion-buffer-P253ONKF.js +13 -0
  135. package/bundle/completion-buffer-P253ONKF.js.map +7 -0
  136. package/bundle/config-RGSDAPZN.js +19 -0
  137. package/bundle/config-RGSDAPZN.js.map +7 -0
  138. package/bundle/config-show-ERTATR6E.js +40 -0
  139. package/bundle/config-show-ERTATR6E.js.map +7 -0
  140. package/bundle/context-HCEGZNDC.js +72 -0
  141. package/bundle/context-HCEGZNDC.js.map +7 -0
  142. package/bundle/delegation-tools-GYTS2D6A.js +27 -0
  143. package/bundle/delegation-tools-GYTS2D6A.js.map +7 -0
  144. package/bundle/deploy-lib-import-32ZFKHWP.js +49 -0
  145. package/bundle/deploy-lib-import-32ZFKHWP.js.map +7 -0
  146. package/bundle/digital-signature-OFCGSHWO.js +13 -0
  147. package/bundle/digital-signature-OFCGSHWO.js.map +7 -0
  148. package/bundle/direct-api-transport-YR7SXXNN.js +860 -0
  149. package/bundle/direct-api-transport-YR7SXXNN.js.map +7 -0
  150. package/bundle/discord-adapter-YYWVMPPU.js +584 -0
  151. package/bundle/discord-adapter-YYWVMPPU.js.map +7 -0
  152. package/bundle/dist-MTMKARCP.js +1969 -0
  153. package/bundle/dist-MTMKARCP.js.map +7 -0
  154. package/bundle/dns-wakeup-27M7D2MR.js +107 -0
  155. package/bundle/dns-wakeup-27M7D2MR.js.map +7 -0
  156. package/bundle/doctor-QNUSDY73.js +248 -0
  157. package/bundle/doctor-QNUSDY73.js.map +7 -0
  158. package/bundle/ensure-invariants-NMXNS476.js +49 -0
  159. package/bundle/ensure-invariants-NMXNS476.js.map +7 -0
  160. package/bundle/env-schema-2KBHBDGN.js +19 -0
  161. package/bundle/env-schema-2KBHBDGN.js.map +7 -0
  162. package/bundle/esm-DDP6NCZG.js +100663 -0
  163. package/bundle/esm-DDP6NCZG.js.map +7 -0
  164. package/bundle/fallback-policy-L4QV2PEJ.js +46 -0
  165. package/bundle/fallback-policy-L4QV2PEJ.js.map +7 -0
  166. package/bundle/health-check-SPA7NT6N.js +56 -0
  167. package/bundle/health-check-SPA7NT6N.js.map +7 -0
  168. package/bundle/hook-system-6Q5YTR53.js +17 -0
  169. package/bundle/hook-system-6Q5YTR53.js.map +7 -0
  170. package/bundle/hotskills-K7BM4YLB.js +12 -0
  171. package/bundle/hotskills-K7BM4YLB.js.map +7 -0
  172. package/bundle/install-6HRZVKUM.js +15 -0
  173. package/bundle/install-6HRZVKUM.js.map +7 -0
  174. package/bundle/install-log-IAPHYKD4.js +28 -0
  175. package/bundle/install-log-IAPHYKD4.js.map +7 -0
  176. package/bundle/install-manifest-SPQRUNXL.js +102 -0
  177. package/bundle/install-manifest-SPQRUNXL.js.map +7 -0
  178. package/bundle/install-validate-PVLZXYLQ.js +53 -0
  179. package/bundle/install-validate-PVLZXYLQ.js.map +7 -0
  180. package/bundle/irc-adapter-OI5UZSQF.js +293 -0
  181. package/bundle/irc-adapter-OI5UZSQF.js.map +7 -0
  182. package/bundle/irc-config-55YO6EGB.js +88 -0
  183. package/bundle/irc-config-55YO6EGB.js.map +7 -0
  184. package/bundle/logs-ZNYXX5PA.js +19 -0
  185. package/bundle/logs-ZNYXX5PA.js.map +7 -0
  186. package/bundle/media-utils-XNNDTYFI.js +4662 -0
  187. package/bundle/media-utils-XNNDTYFI.js.map +7 -0
  188. package/bundle/message-pipeline-LLH5SYMO.js +33 -0
  189. package/bundle/message-pipeline-LLH5SYMO.js.map +7 -0
  190. package/bundle/meta.json +41304 -0
  191. package/bundle/model-health-registry-35LQNVQR.js +11 -0
  192. package/bundle/model-health-registry-35LQNVQR.js.map +7 -0
  193. package/bundle/notification-Y5S5MMLV.js +13 -0
  194. package/bundle/notification-Y5S5MMLV.js.map +7 -0
  195. package/bundle/openrouter-credits-EDY7ETAU.js +32 -0
  196. package/bundle/openrouter-credits-EDY7ETAU.js.map +7 -0
  197. package/bundle/passwd-RRFV4CC5.js +133 -0
  198. package/bundle/passwd-RRFV4CC5.js.map +7 -0
  199. package/bundle/paths-G33RZWZ7.js +17 -0
  200. package/bundle/paths-G33RZWZ7.js.map +7 -0
  201. package/bundle/peer-client-52XYMNI7.js +156 -0
  202. package/bundle/peer-client-52XYMNI7.js.map +7 -0
  203. package/bundle/peer-config-VK6EDLN5.js +16 -0
  204. package/bundle/peer-config-VK6EDLN5.js.map +7 -0
  205. package/bundle/peer-sessions-EAXTNQ36.js +49 -0
  206. package/bundle/peer-sessions-EAXTNQ36.js.map +7 -0
  207. package/bundle/pending-callback-RIMQZ7FJ.js +40 -0
  208. package/bundle/pending-callback-RIMQZ7FJ.js.map +7 -0
  209. package/bundle/phase-transport-KYERDL2O.js +22 -0
  210. package/bundle/phase-transport-KYERDL2O.js.map +7 -0
  211. package/bundle/public/css/dashboard.css +542 -0
  212. package/bundle/public/index.html +180 -0
  213. package/bundle/public/js/app.js +437 -0
  214. package/bundle/public/memory-universe.js +384 -0
  215. package/bundle/responses-adapter-AAQTY3K4.js +30 -0
  216. package/bundle/responses-adapter-AAQTY3K4.js.map +7 -0
  217. package/bundle/restore-ZE3SEPSS.js +46 -0
  218. package/bundle/restore-ZE3SEPSS.js.map +7 -0
  219. package/bundle/self-healer-utils-DMUUXC47.js +43 -0
  220. package/bundle/self-healer-utils-DMUUXC47.js.map +7 -0
  221. package/bundle/skill-stats-LLEXEXLR.js +22 -0
  222. package/bundle/skill-stats-LLEXEXLR.js.map +7 -0
  223. package/bundle/sleep-OYIUOVQD.js +19 -0
  224. package/bundle/sleep-OYIUOVQD.js.map +7 -0
  225. package/bundle/soul-loader-54WCVNLJ.js +16 -0
  226. package/bundle/soul-loader-54WCVNLJ.js.map +7 -0
  227. package/bundle/src-JL4PVO23.js +8 -0
  228. package/bundle/src-JL4PVO23.js.map +7 -0
  229. package/bundle/sse-parser-anthropic-P7CE2MH2.js +72 -0
  230. package/bundle/sse-parser-anthropic-P7CE2MH2.js.map +7 -0
  231. package/bundle/sse-parser-responses-EQQA5FWN.js +63 -0
  232. package/bundle/sse-parser-responses-EQQA5FWN.js.map +7 -0
  233. package/bundle/ssrf-guard-FZCBYIVW.js +64 -0
  234. package/bundle/ssrf-guard-FZCBYIVW.js.map +7 -0
  235. package/bundle/start-FH3GRMJ4.js +35 -0
  236. package/bundle/start-FH3GRMJ4.js.map +7 -0
  237. package/bundle/stream-single-WSG4D53C.js +33 -0
  238. package/bundle/stream-single-WSG4D53C.js.map +7 -0
  239. package/bundle/stt-2UH3RITX.js +14 -0
  240. package/bundle/stt-2UH3RITX.js.map +7 -0
  241. package/bundle/subagent-runtime-LE2ZXH3G.js +12 -0
  242. package/bundle/subagent-runtime-LE2ZXH3G.js.map +7 -0
  243. package/bundle/system-message-T5R3EYYN.js +30 -0
  244. package/bundle/system-message-T5R3EYYN.js.map +7 -0
  245. package/bundle/system-status-KQ6KHFJ6.js +189 -0
  246. package/bundle/system-status-KQ6KHFJ6.js.map +7 -0
  247. package/bundle/task-store-K7CQDEPI.js +22 -0
  248. package/bundle/task-store-K7CQDEPI.js.map +7 -0
  249. package/bundle/telegram-adapter-2V3XUMT5.js +1060 -0
  250. package/bundle/telegram-adapter-2V3XUMT5.js.map +7 -0
  251. package/bundle/tool-registry-MU3OX4UI.js +38 -0
  252. package/bundle/tool-registry-MU3OX4UI.js.map +7 -0
  253. package/bundle/tool-sandbox-VYOK4ZOA.js +20 -0
  254. package/bundle/tool-sandbox-VYOK4ZOA.js.map +7 -0
  255. package/bundle/transport-config-YLXU33RO.js +57 -0
  256. package/bundle/transport-config-YLXU33RO.js.map +7 -0
  257. package/bundle/update-QCW5LXRN.js +13 -0
  258. package/bundle/update-QCW5LXRN.js.map +7 -0
  259. package/bundle/update-check-27KZSAP6.js +12 -0
  260. package/bundle/update-check-27KZSAP6.js.map +7 -0
  261. package/bundle/usage-tracker-OVVEVMOY.js +17 -0
  262. package/bundle/usage-tracker-OVVEVMOY.js.map +7 -0
  263. package/bundle/user-registry-D4SD73UV.js +16 -0
  264. package/bundle/user-registry-D4SD73UV.js.map +7 -0
  265. package/core/professor.json +14 -0
  266. package/core/prompts/browsing_prompt.md +39 -0
  267. package/core/prompts/compaction.md +32 -0
  268. package/core/skills/memory/classification/SKILL.md +37 -0
  269. package/core/skills/memory/memory-anomalies/SKILL.md +39 -0
  270. package/core/skills/memory/memory-search/SKILL.md +48 -0
  271. package/core/skills/memory/topic-save/SKILL.md +44 -0
  272. package/core/skills/ops/cron/SKILL.md +51 -0
  273. package/core/skills/ops/gdrive-backup/SKILL.md +15 -0
  274. package/core/skills/ops/session-start/SKILL.md +11 -0
  275. package/core/skills/ops/skill-authoring/SKILL.md +54 -0
  276. package/core/skills/ops/system-health/SKILL.md +104 -0
  277. package/core/skills/ops/troubleshooting/SKILL.md +48 -0
  278. package/core/skills/ops/trust-gating/SKILL.md +30 -0
  279. package/core/skills/tools/a2a-communication/SKILL.md +68 -0
  280. package/core/skills/tools/browse-delegate/SKILL.md +27 -0
  281. package/core/skills/tools/browser/SKILL.md +36 -0
  282. package/core/skills/tools/clawhub/SKILL.md +44 -0
  283. package/core/skills/tools/delegation/SKILL.md +48 -0
  284. package/core/skills/tools/fxtwitter/SKILL.md +52 -0
  285. package/core/skills/tools/gmail/SKILL.md +44 -0
  286. package/core/skills/tools/irc-chat/SKILL.md +84 -0
  287. package/core/skills/tools/linear/SKILL.md +90 -0
  288. package/core/skills/tools/mcporter/SKILL.md +46 -0
  289. package/core/skills/tools/model-scout/SKILL.md +132 -0
  290. package/core/skills/tools/model-scout/scout-add-model.py +67 -0
  291. package/core/skills/tools/model-scout/scout-ollama.py +116 -0
  292. package/core/skills/tools/model-scout/scout-openrouter.py +85 -0
  293. package/core/skills/tools/nlm/SKILL.md +40 -0
  294. package/core/skills/tools/todo/SKILL.md +30 -0
  295. package/core/skills/tools/twitterX/SKILL.md +52 -0
  296. package/core/skills/tools/twitterX/scripts/abtars-tweet.js +532 -0
  297. package/core/skills/tools/twitterX/scripts/package.json +1 -0
  298. package/core/skills/tools/web-fetch/SKILL.md +29 -0
  299. package/package.json +59 -0
  300. package/scripts/abtars-daemon.service +23 -0
  301. package/scripts/abtars-fetch.sh +42 -0
  302. package/scripts/abtars-watchdog.service +13 -0
  303. package/scripts/abtars.sh +14 -0
  304. package/scripts/abtars@.service +21 -0
  305. package/scripts/browser-patchright.sh +79 -0
  306. package/scripts/com.abtars.daemon.plist +24 -0
  307. package/scripts/com.abtars.watchdog.plist +27 -0
  308. package/scripts/daily-backup.sh +62 -0
  309. package/scripts/doctor.sh +553 -0
  310. package/scripts/hooks/audit-logger.sh +22 -0
  311. package/scripts/upgrade-deps.sh +64 -0
  312. package/scripts/watchdog.sh +309 -0
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env bash
2
+ # Abtars External Watchdog
3
+ # Spawns node directly, monitors bridge.lock heartbeat, kills+restarts on stale.
4
+ # Usage: watchdog.sh [bridge flags, e.g. --all --web --agent]
5
+ set -uo pipefail
6
+
7
+ AB="${ABTARS_HOME:-$HOME/.abtars}"
8
+ LOCK="$AB/bridge.lock"
9
+ WD_LOCK="$AB/watchdog.lock"
10
+ LOG="$AB/logs/watchdog.log"
11
+ ENV_FILE="$AB/.env"
12
+
13
+ POLL_SEC=60
14
+ STALE_SEC="${WATCHDOG_STALE_SEC:-360}"
15
+ HB_SEC=300
16
+ KILL_ON_STALE="false"
17
+ if [[ -f "$ENV_FILE" ]]; then
18
+ _hb_sec=$(grep -m1 '^HEARTBEAT_INTERVAL_SEC=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' || true)
19
+ if [[ -n "$_hb_sec" && "$_hb_sec" != "0" ]]; then
20
+ HB_SEC="$_hb_sec"
21
+ fi
22
+ _kill=$(grep -m1 '^WATCHDOG_KILL_ON_STALE=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' || true)
23
+ if [[ -n "$_kill" ]]; then KILL_ON_STALE="$_kill"; fi
24
+ _grace=$(grep -m1 '^WATCHDOG_SUSPEND_GRACE=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' || true)
25
+ if [[ -n "$_grace" ]]; then SUSPEND_GRACE="$_grace"; fi
26
+ fi
27
+ SUSPEND_GRACE="${SUSPEND_GRACE:-true}"
28
+ STARTUP_TIMEOUT=$(( HB_SEC + POLL_SEC * 2 ))
29
+ CIRCUIT_MAX=3
30
+ CIRCUIT_WINDOW=300
31
+ MAX_LOG_BYTES=10485760
32
+
33
+ BRIDGE_PID=""
34
+ SPAWNED_AT=0
35
+ RESTART_TIMES=()
36
+ RESTARTING=false
37
+ RESTART_STARTED_AT=0
38
+
39
+ # ── Load .env for Telegram notifications ──
40
+ TG_TOKEN=""
41
+ MAIN_CHAT_ID=""
42
+ if [[ -f "$ENV_FILE" ]]; then
43
+ TG_TOKEN=$(grep -m1 '^TELEGRAM_BOT_TOKEN=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' || true)
44
+ MAIN_CHAT_ID=$(grep -m1 '^MAIN_CHAT_ID=' "$ENV_FILE" | cut -d= -f2- | tr -d '"' || true)
45
+ fi
46
+
47
+ mkdir -p "$AB/logs"
48
+
49
+ # ── Ensure nvm/node is available ──
50
+ export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
51
+ [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
52
+ if ! command -v node &>/dev/null; then
53
+ echo "FATAL: node not found" >&2
54
+ exit 1
55
+ fi
56
+
57
+ log() {
58
+ local ts
59
+ ts=$(date '+%Y-%m-%dT%H:%M:%S')
60
+ echo "$ts $1" >> "$LOG"
61
+ echo "$ts $1"
62
+ }
63
+
64
+ notify() {
65
+ if [[ -n "$TG_TOKEN" && -n "$MAIN_CHAT_ID" ]]; then
66
+ curl -s "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
67
+ -d "chat_id=${MAIN_CHAT_ID}" -d "text=$1" >/dev/null 2>&1 || true
68
+ fi
69
+ }
70
+
71
+ read_lock() {
72
+ if [[ ! -f "$LOCK" ]]; then echo "ERR"; return; fi
73
+ local content
74
+ content=$(cat "$LOCK" 2>/dev/null) || { echo "ERR"; return; }
75
+ local pid hb sleep started
76
+ pid=$(echo "$content" | grep -o '"pid":[0-9]*' | grep -o '[0-9]*') || pid=0
77
+ hb=$(echo "$content" | grep -o '"lastHeartbeat":[0-9]*' | grep -o '[0-9]*') || hb=0
78
+ sleep=$(echo "$content" | grep -o '"sleepStatus":"[^"]*"' | cut -d'"' -f4) || sleep="awake"
79
+ started=$(echo "$content" | grep -o '"startedAt":[0-9]*' | grep -o '[0-9]*') || started=0
80
+ echo "${pid:-0} ${hb:-0} ${sleep:-awake} ${started:-0}"
81
+ }
82
+
83
+ now_ms() { echo $(( $(date +%s) * 1000 )); }
84
+
85
+ wait_for_death() {
86
+ local pid=$1 max=10 i=0
87
+ while kill -0 "$pid" 2>/dev/null && (( i < max )); do
88
+ sleep 0.5
89
+ ((i++))
90
+ done
91
+ }
92
+
93
+ write_wd_lock() {
94
+ printf '{"pid":%d,"lastCheck":%s}\n' $$ "$(now_ms)" > "$WD_LOCK"
95
+ }
96
+
97
+ rotate_log() {
98
+ if [[ -f "$LOG" ]]; then
99
+ local size
100
+ size=$(stat -f%z "$LOG" 2>/dev/null || stat -c%s "$LOG" 2>/dev/null || echo 0)
101
+ if (( size > MAX_LOG_BYTES )); then
102
+ mv "$LOG" "$LOG.1"
103
+ log "Log rotated (was ${size} bytes)"
104
+ fi
105
+ fi
106
+ }
107
+
108
+ circuit_check() {
109
+ local now
110
+ now=$(date +%s)
111
+ local fresh=()
112
+ for ts in ${RESTART_TIMES[@]+"${RESTART_TIMES[@]}"}; do
113
+ if (( now - ts < CIRCUIT_WINDOW )); then
114
+ fresh+=("$ts")
115
+ fi
116
+ done
117
+ RESTART_TIMES=(${fresh[@]+"${fresh[@]}"})
118
+ if (( ${#RESTART_TIMES[@]} >= CIRCUIT_MAX )); then
119
+ return 1
120
+ fi
121
+ return 0
122
+ }
123
+
124
+ spawn_bridge() {
125
+ if ! circuit_check; then
126
+ log "🚨 CIRCUIT BREAKER — ${CIRCUIT_MAX} restarts in ${CIRCUIT_WINDOW}s, stopping"
127
+ notify "🚨 Watchdog circuit breaker tripped — manual intervention needed"
128
+ rm -f "$WD_LOCK"
129
+ exit 1
130
+ fi
131
+
132
+ # Health check before every spawn
133
+ if [ -x "$AB/scripts/doctor.sh" ]; then
134
+ log "Running doctor --fix..."
135
+ if ! timeout 30 "$AB/scripts/doctor.sh" --fix >> "$AB/logs/launchd.log" 2>&1; then
136
+ log "⚠️ doctor --fix failed — spawning anyway (non-fatal)"
137
+ fi
138
+ fi
139
+
140
+ RESTART_TIMES+=("$(date +%s)")
141
+ rm -f "$LOCK"
142
+
143
+ # #686: Kill stale bridge holding port 3100
144
+ if [ -f "$AB/bridge.pid" ]; then
145
+ old_pid=$(cat "$AB/bridge.pid")
146
+ if kill -0 "$old_pid" 2>/dev/null; then
147
+ log "Killing stale bridge (pid $old_pid)..."
148
+ kill "$old_pid" 2>/dev/null
149
+ for i in 1 2 3 4 5; do kill -0 "$old_pid" 2>/dev/null || break; sleep 1; done
150
+ kill -0 "$old_pid" 2>/dev/null && kill -9 "$old_pid" 2>/dev/null
151
+ fi
152
+ fi
153
+ # Wait for port 3100 release
154
+ for i in 1 2 3 4 5; do lsof -ti :3100 >/dev/null 2>&1 || break; sleep 1; done
155
+
156
+ # Clean stale socket
157
+ rm -f "${ABMIND_HOME:-$HOME/.abmind}/memory.sock" 2>/dev/null || true
158
+
159
+ # Source .env so platform ENABLED vars reach the node process
160
+ if [ -f "$AB/config/.env" ]; then set -a; source "$AB/config/.env"; set +a; fi
161
+ # Stable entry point: main.js symlink created by abtars update.
162
+ log "Starting bridge: node current/main.js $*"
163
+ cd "$AB"
164
+ NODE_PATH="current/node_modules:$(npm root -g 2>/dev/null || echo ''):${ABMIND_HOME:-$HOME/.abmind}/lib/node_modules:${NODE_PATH:-}" node current/main.js "$@" >> "$AB/logs/launchd.log" 2>&1 &
165
+ SPAWNED_AT=$(date +%s)
166
+
167
+ # Wait for bridge.lock with PID
168
+ local wait=0
169
+ BRIDGE_PID=""
170
+ while (( wait < 30 )); do
171
+ if [[ -f "$LOCK" ]]; then
172
+ BRIDGE_PID=$(grep -o '"pid":[0-9]*' "$LOCK" | grep -o '[0-9]*' || echo "")
173
+ if [[ -n "$BRIDGE_PID" && "$BRIDGE_PID" != "0" ]]; then
174
+ break
175
+ fi
176
+ fi
177
+ sleep 1
178
+ ((wait++))
179
+ done
180
+ log "Bridge spawned (PID=$BRIDGE_PID)"
181
+ }
182
+
183
+ kill_bridge() {
184
+ local reason=$1
185
+ if [[ -n "$BRIDGE_PID" ]] && kill -0 "$BRIDGE_PID" 2>/dev/null; then
186
+ log "Killing bridge PID=$BRIDGE_PID ($reason)"
187
+ notify "🚨 Watchdog: $reason — killing PID $BRIDGE_PID"
188
+ kill -9 "$BRIDGE_PID" 2>/dev/null || true
189
+ wait_for_death "$BRIDGE_PID"
190
+ fi
191
+ rm -f "$LOCK"
192
+ BRIDGE_PID=""
193
+ }
194
+
195
+ graceful_restart() {
196
+ RESTARTING=true
197
+ RESTART_STARTED_AT=$(date +%s)
198
+ log "USR1 received — graceful restart"
199
+ notify "♻️ Restarting bridge..."
200
+ if [[ -n "$BRIDGE_PID" ]] && kill -0 "$BRIDGE_PID" 2>/dev/null; then
201
+ log "Stopping old bridge (PID=$BRIDGE_PID)..."
202
+ kill -TERM "$BRIDGE_PID" 2>/dev/null || true
203
+ local i=0
204
+ while kill -0 "$BRIDGE_PID" 2>/dev/null && (( i < 20 )); do
205
+ sleep 0.5
206
+ ((i++))
207
+ done
208
+ if kill -0 "$BRIDGE_PID" 2>/dev/null; then
209
+ log "Bridge didn't stop gracefully, SIGKILL"
210
+ kill -9 "$BRIDGE_PID" 2>/dev/null || true
211
+ wait_for_death "$BRIDGE_PID"
212
+ fi
213
+ log "Old bridge exited"
214
+ fi
215
+ rm -f "$LOCK"
216
+ BRIDGE_PID=""
217
+ spawn_bridge "${BRIDGE_ARGS[@]}"
218
+ RESTARTING=false
219
+ }
220
+
221
+ BRIDGE_ARGS=("$@")
222
+ trap 'graceful_restart' USR1
223
+ # Exit non-zero on TERM/INT so launchd KeepAlive restarts us even if a policy
224
+ # variant treats exit 0 as "intentional shutdown, do not restart".
225
+ trap 'kill_bridge "watchdog exit"; rm -f "$WD_LOCK"; exit 1' TERM INT
226
+
227
+ # ── Startup ──
228
+ log "Watchdog starting (stale=${STALE_SEC}s, poll=${POLL_SEC}s, circuit=${CIRCUIT_MAX}/${CIRCUIT_WINDOW}s)"
229
+ write_wd_lock
230
+
231
+ spawn_bridge "$@"
232
+ LAST_POLL_AT=$(date +%s)
233
+
234
+ # ── Monitor loop ──
235
+ while true; do
236
+ sleep "$POLL_SEC" &
237
+ wait $! 2>/dev/null || true
238
+
239
+ write_wd_lock
240
+ rotate_log
241
+
242
+ # Suspend detection: if real elapsed >> POLL_SEC, the host (laptop, VM, WSL)
243
+ # was suspended. Bridge was suspended too — its heartbeat is "stale" only
244
+ # because wall-clock advanced while both processes were frozen. Skip the
245
+ # staleness check for one cycle so the bridge can heartbeat on resume.
246
+ _now_s=$(date +%s)
247
+ _poll_gap=$(( _now_s - LAST_POLL_AT ))
248
+ LAST_POLL_AT=$_now_s
249
+ if [[ "$SUSPEND_GRACE" == "true" ]] && (( _poll_gap > POLL_SEC * 3 )); then
250
+ log "Suspend detected (poll gap ${_poll_gap}s >> ${POLL_SEC}s) — granting one-cycle grace"
251
+ continue
252
+ fi
253
+
254
+ local_lock=$(read_lock)
255
+ if [[ "$local_lock" == "ERR" ]]; then
256
+ continue
257
+ fi
258
+
259
+ lock_pid=$(echo "$local_lock" | awk '{print $1}')
260
+ lock_hb=$(echo "$local_lock" | awk '{print $2}')
261
+ lock_sleep=$(echo "$local_lock" | awk '{print $3}')
262
+ lock_started=$(echo "$local_lock" | awk '{print $4}')
263
+ now=$(now_ms)
264
+
265
+ if [[ -n "$lock_pid" && "$lock_pid" != "0" ]]; then
266
+ BRIDGE_PID="$lock_pid"
267
+ fi
268
+
269
+ # Guard: don't spawn if graceful_restart is in progress
270
+ if [[ "$RESTARTING" == "true" ]]; then
271
+ local elapsed=$(( $(date +%s) - RESTART_STARTED_AT ))
272
+ if (( elapsed > 30 )); then
273
+ log "RESTARTING flag stuck for ${elapsed}s — resetting"
274
+ RESTARTING=false
275
+ else
276
+ continue
277
+ fi
278
+ fi
279
+
280
+ if [[ -z "$BRIDGE_PID" ]] || ! kill -0 "$BRIDGE_PID" 2>/dev/null; then
281
+ log "Bridge process gone (PID=$BRIDGE_PID)"
282
+ notify "🚨 Watchdog: bridge process gone, restarting"
283
+ BRIDGE_PID=""
284
+ rm -f "$LOCK"
285
+ spawn_bridge "${BRIDGE_ARGS[@]}"
286
+ continue
287
+ fi
288
+
289
+ if [[ "$lock_sleep" == "hw_sleep" ]]; then
290
+ continue
291
+ fi
292
+
293
+ if (( lock_hb == 0 )); then
294
+ if (( lock_started > 0 )); then
295
+ age_s=$(( (now - lock_started) / 1000 ))
296
+ if (( age_s > STARTUP_TIMEOUT )); then
297
+ kill_bridge "startup timeout (${age_s}s from startedAt, no heartbeat)"
298
+ spawn_bridge "${BRIDGE_ARGS[@]}"
299
+ fi
300
+ fi
301
+ continue
302
+ fi
303
+
304
+ age_sec=$(( (now - lock_hb) / 1000 ))
305
+ if [[ "$KILL_ON_STALE" == "true" ]] && (( age_sec > STALE_SEC )); then
306
+ kill_bridge "heartbeat stale (${age_sec}s)"
307
+ spawn_bridge "${BRIDGE_ARGS[@]}"
308
+ fi
309
+ done