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.
- package/LICENSE +190 -0
- package/README.md +84 -0
- package/bundle/_registry.generated-M4WY2MMI.js +35 -0
- package/bundle/_registry.generated-M4WY2MMI.js.map +7 -0
- package/bundle/abtars-browser.js +162 -0
- package/bundle/abtars-browser.js.map +7 -0
- package/bundle/abtars-cli.js +1438 -0
- package/bundle/abtars-cli.js.map +7 -0
- package/bundle/abtars-restart.js +12 -0
- package/bundle/abtars-restart.js.map +7 -0
- package/bundle/abtars-rss.js +165 -0
- package/bundle/abtars-rss.js.map +7 -0
- package/bundle/abtars-task.js +258 -0
- package/bundle/abtars-task.js.map +7 -0
- package/bundle/abtars.js +4072 -0
- package/bundle/abtars.js.map +7 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js +38 -0
- package/bundle/agent-api-rate-limit-OQNFMXTZ.js.map +7 -0
- package/bundle/agent-registry-LT4JNQH6.js +18 -0
- package/bundle/agent-registry-LT4JNQH6.js.map +7 -0
- package/bundle/agents/default.md +29 -0
- package/bundle/anthropic-adapter-2APTH3LA.js +40 -0
- package/bundle/anthropic-adapter-2APTH3LA.js.map +7 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js +39 -0
- package/bundle/bridge-lock-transport-4AC2G5G6.js.map +7 -0
- package/bundle/browse-delivery-JXBY36GK.js +17 -0
- package/bundle/browse-delivery-JXBY36GK.js.map +7 -0
- package/bundle/browser-ELNDVPLC.js +18 -0
- package/bundle/browser-ELNDVPLC.js.map +7 -0
- package/bundle/capability-CIL3G4FI.js +17 -0
- package/bundle/capability-CIL3G4FI.js.map +7 -0
- package/bundle/chunk-265TPOPC.js +289 -0
- package/bundle/chunk-265TPOPC.js.map +7 -0
- package/bundle/chunk-2UENBO6M.js +223 -0
- package/bundle/chunk-2UENBO6M.js.map +7 -0
- package/bundle/chunk-2UPU3OW6.js +67 -0
- package/bundle/chunk-2UPU3OW6.js.map +7 -0
- package/bundle/chunk-2XU2X4OI.js +125 -0
- package/bundle/chunk-2XU2X4OI.js.map +7 -0
- package/bundle/chunk-3B7BBE4F.js +758 -0
- package/bundle/chunk-3B7BBE4F.js.map +7 -0
- package/bundle/chunk-3E545J66.js +69 -0
- package/bundle/chunk-3E545J66.js.map +7 -0
- package/bundle/chunk-5R2ANXQ7.js +510 -0
- package/bundle/chunk-5R2ANXQ7.js.map +7 -0
- package/bundle/chunk-6CPN4IGS.js +507 -0
- package/bundle/chunk-6CPN4IGS.js.map +7 -0
- package/bundle/chunk-6NR3OHEW.js +88 -0
- package/bundle/chunk-6NR3OHEW.js.map +7 -0
- package/bundle/chunk-6SETMHNN.js +206 -0
- package/bundle/chunk-6SETMHNN.js.map +7 -0
- package/bundle/chunk-6UCRKRWR.js +644 -0
- package/bundle/chunk-6UCRKRWR.js.map +7 -0
- package/bundle/chunk-AR6GO6YC.js +83 -0
- package/bundle/chunk-AR6GO6YC.js.map +7 -0
- package/bundle/chunk-AZJIODTQ.js +54 -0
- package/bundle/chunk-AZJIODTQ.js.map +7 -0
- package/bundle/chunk-BHMZ4RCC.js +3706 -0
- package/bundle/chunk-BHMZ4RCC.js.map +7 -0
- package/bundle/chunk-BQ2L4GMG.js +9175 -0
- package/bundle/chunk-BQ2L4GMG.js.map +7 -0
- package/bundle/chunk-BSSBCSCL.js +159 -0
- package/bundle/chunk-BSSBCSCL.js.map +7 -0
- package/bundle/chunk-BUUVFUPO.js +157 -0
- package/bundle/chunk-BUUVFUPO.js.map +7 -0
- package/bundle/chunk-CEVRHKJY.js +131 -0
- package/bundle/chunk-CEVRHKJY.js.map +7 -0
- package/bundle/chunk-CWOHNFUV.js +39 -0
- package/bundle/chunk-CWOHNFUV.js.map +7 -0
- package/bundle/chunk-D2DCBO6M.js +228 -0
- package/bundle/chunk-D2DCBO6M.js.map +7 -0
- package/bundle/chunk-FMWKEPM7.js +31 -0
- package/bundle/chunk-FMWKEPM7.js.map +7 -0
- package/bundle/chunk-GRNENTPA.js +145 -0
- package/bundle/chunk-GRNENTPA.js.map +7 -0
- package/bundle/chunk-GST5T3WZ.js +93 -0
- package/bundle/chunk-GST5T3WZ.js.map +7 -0
- package/bundle/chunk-GUQVJC3U.js +299 -0
- package/bundle/chunk-GUQVJC3U.js.map +7 -0
- package/bundle/chunk-HX7Y7EYP.js +3659 -0
- package/bundle/chunk-HX7Y7EYP.js.map +7 -0
- package/bundle/chunk-JCJS4ZIB.js +296 -0
- package/bundle/chunk-JCJS4ZIB.js.map +7 -0
- package/bundle/chunk-JW6RU47G.js +184 -0
- package/bundle/chunk-JW6RU47G.js.map +7 -0
- package/bundle/chunk-LSPKJQCI.js +24 -0
- package/bundle/chunk-LSPKJQCI.js.map +7 -0
- package/bundle/chunk-M6VBAPNT.js +16 -0
- package/bundle/chunk-M6VBAPNT.js.map +7 -0
- package/bundle/chunk-MPX525QO.js +129 -0
- package/bundle/chunk-MPX525QO.js.map +7 -0
- package/bundle/chunk-MW6WDLU7.js +130 -0
- package/bundle/chunk-MW6WDLU7.js.map +7 -0
- package/bundle/chunk-NT3OBORC.js +215 -0
- package/bundle/chunk-NT3OBORC.js.map +7 -0
- package/bundle/chunk-NWDBD4PA.js +50 -0
- package/bundle/chunk-NWDBD4PA.js.map +7 -0
- package/bundle/chunk-OP7BTAWY.js +29 -0
- package/bundle/chunk-OP7BTAWY.js.map +7 -0
- package/bundle/chunk-PLCY3GFH.js +77 -0
- package/bundle/chunk-PLCY3GFH.js.map +7 -0
- package/bundle/chunk-PNEDC45Y.js +97 -0
- package/bundle/chunk-PNEDC45Y.js.map +7 -0
- package/bundle/chunk-QBGBT5QS.js +81 -0
- package/bundle/chunk-QBGBT5QS.js.map +7 -0
- package/bundle/chunk-RVE2N7FA.js +70 -0
- package/bundle/chunk-RVE2N7FA.js.map +7 -0
- package/bundle/chunk-TZHIDLDS.js +71910 -0
- package/bundle/chunk-TZHIDLDS.js.map +7 -0
- package/bundle/chunk-UCQ2WC3B.js +126 -0
- package/bundle/chunk-UCQ2WC3B.js.map +7 -0
- package/bundle/chunk-UHRP745J.js +214 -0
- package/bundle/chunk-UHRP745J.js.map +7 -0
- package/bundle/chunk-V76TVMCM.js +58 -0
- package/bundle/chunk-V76TVMCM.js.map +7 -0
- package/bundle/chunk-VVEDVGCR.js +981 -0
- package/bundle/chunk-VVEDVGCR.js.map +7 -0
- package/bundle/chunk-W6FAL35D.js +102 -0
- package/bundle/chunk-W6FAL35D.js.map +7 -0
- package/bundle/chunk-X6TERNVJ.js +15902 -0
- package/bundle/chunk-X6TERNVJ.js.map +7 -0
- package/bundle/chunk-X76UX47U.js +47 -0
- package/bundle/chunk-X76UX47U.js.map +7 -0
- package/bundle/chunk-XREWVCUO.js +518 -0
- package/bundle/chunk-XREWVCUO.js.map +7 -0
- package/bundle/chunk-Y6XAEX2Q.js +408 -0
- package/bundle/chunk-Y6XAEX2Q.js.map +7 -0
- package/bundle/chunk-YOCTDKKL.js +28 -0
- package/bundle/chunk-YOCTDKKL.js.map +7 -0
- package/bundle/chunk-ZXPXCDA6.js +160 -0
- package/bundle/chunk-ZXPXCDA6.js.map +7 -0
- package/bundle/commands-BHVUOU3V.js +31 -0
- package/bundle/commands-BHVUOU3V.js.map +7 -0
- package/bundle/completion-buffer-P253ONKF.js +13 -0
- package/bundle/completion-buffer-P253ONKF.js.map +7 -0
- package/bundle/config-RGSDAPZN.js +19 -0
- package/bundle/config-RGSDAPZN.js.map +7 -0
- package/bundle/config-show-ERTATR6E.js +40 -0
- package/bundle/config-show-ERTATR6E.js.map +7 -0
- package/bundle/context-HCEGZNDC.js +72 -0
- package/bundle/context-HCEGZNDC.js.map +7 -0
- package/bundle/delegation-tools-GYTS2D6A.js +27 -0
- package/bundle/delegation-tools-GYTS2D6A.js.map +7 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js +49 -0
- package/bundle/deploy-lib-import-32ZFKHWP.js.map +7 -0
- package/bundle/digital-signature-OFCGSHWO.js +13 -0
- package/bundle/digital-signature-OFCGSHWO.js.map +7 -0
- package/bundle/direct-api-transport-YR7SXXNN.js +860 -0
- package/bundle/direct-api-transport-YR7SXXNN.js.map +7 -0
- package/bundle/discord-adapter-YYWVMPPU.js +584 -0
- package/bundle/discord-adapter-YYWVMPPU.js.map +7 -0
- package/bundle/dist-MTMKARCP.js +1969 -0
- package/bundle/dist-MTMKARCP.js.map +7 -0
- package/bundle/dns-wakeup-27M7D2MR.js +107 -0
- package/bundle/dns-wakeup-27M7D2MR.js.map +7 -0
- package/bundle/doctor-QNUSDY73.js +248 -0
- package/bundle/doctor-QNUSDY73.js.map +7 -0
- package/bundle/ensure-invariants-NMXNS476.js +49 -0
- package/bundle/ensure-invariants-NMXNS476.js.map +7 -0
- package/bundle/env-schema-2KBHBDGN.js +19 -0
- package/bundle/env-schema-2KBHBDGN.js.map +7 -0
- package/bundle/esm-DDP6NCZG.js +100663 -0
- package/bundle/esm-DDP6NCZG.js.map +7 -0
- package/bundle/fallback-policy-L4QV2PEJ.js +46 -0
- package/bundle/fallback-policy-L4QV2PEJ.js.map +7 -0
- package/bundle/health-check-SPA7NT6N.js +56 -0
- package/bundle/health-check-SPA7NT6N.js.map +7 -0
- package/bundle/hook-system-6Q5YTR53.js +17 -0
- package/bundle/hook-system-6Q5YTR53.js.map +7 -0
- package/bundle/hotskills-K7BM4YLB.js +12 -0
- package/bundle/hotskills-K7BM4YLB.js.map +7 -0
- package/bundle/install-6HRZVKUM.js +15 -0
- package/bundle/install-6HRZVKUM.js.map +7 -0
- package/bundle/install-log-IAPHYKD4.js +28 -0
- package/bundle/install-log-IAPHYKD4.js.map +7 -0
- package/bundle/install-manifest-SPQRUNXL.js +102 -0
- package/bundle/install-manifest-SPQRUNXL.js.map +7 -0
- package/bundle/install-validate-PVLZXYLQ.js +53 -0
- package/bundle/install-validate-PVLZXYLQ.js.map +7 -0
- package/bundle/irc-adapter-OI5UZSQF.js +293 -0
- package/bundle/irc-adapter-OI5UZSQF.js.map +7 -0
- package/bundle/irc-config-55YO6EGB.js +88 -0
- package/bundle/irc-config-55YO6EGB.js.map +7 -0
- package/bundle/logs-ZNYXX5PA.js +19 -0
- package/bundle/logs-ZNYXX5PA.js.map +7 -0
- package/bundle/media-utils-XNNDTYFI.js +4662 -0
- package/bundle/media-utils-XNNDTYFI.js.map +7 -0
- package/bundle/message-pipeline-LLH5SYMO.js +33 -0
- package/bundle/message-pipeline-LLH5SYMO.js.map +7 -0
- package/bundle/meta.json +41304 -0
- package/bundle/model-health-registry-35LQNVQR.js +11 -0
- package/bundle/model-health-registry-35LQNVQR.js.map +7 -0
- package/bundle/notification-Y5S5MMLV.js +13 -0
- package/bundle/notification-Y5S5MMLV.js.map +7 -0
- package/bundle/openrouter-credits-EDY7ETAU.js +32 -0
- package/bundle/openrouter-credits-EDY7ETAU.js.map +7 -0
- package/bundle/passwd-RRFV4CC5.js +133 -0
- package/bundle/passwd-RRFV4CC5.js.map +7 -0
- package/bundle/paths-G33RZWZ7.js +17 -0
- package/bundle/paths-G33RZWZ7.js.map +7 -0
- package/bundle/peer-client-52XYMNI7.js +156 -0
- package/bundle/peer-client-52XYMNI7.js.map +7 -0
- package/bundle/peer-config-VK6EDLN5.js +16 -0
- package/bundle/peer-config-VK6EDLN5.js.map +7 -0
- package/bundle/peer-sessions-EAXTNQ36.js +49 -0
- package/bundle/peer-sessions-EAXTNQ36.js.map +7 -0
- package/bundle/pending-callback-RIMQZ7FJ.js +40 -0
- package/bundle/pending-callback-RIMQZ7FJ.js.map +7 -0
- package/bundle/phase-transport-KYERDL2O.js +22 -0
- package/bundle/phase-transport-KYERDL2O.js.map +7 -0
- package/bundle/public/css/dashboard.css +542 -0
- package/bundle/public/index.html +180 -0
- package/bundle/public/js/app.js +437 -0
- package/bundle/public/memory-universe.js +384 -0
- package/bundle/responses-adapter-AAQTY3K4.js +30 -0
- package/bundle/responses-adapter-AAQTY3K4.js.map +7 -0
- package/bundle/restore-ZE3SEPSS.js +46 -0
- package/bundle/restore-ZE3SEPSS.js.map +7 -0
- package/bundle/self-healer-utils-DMUUXC47.js +43 -0
- package/bundle/self-healer-utils-DMUUXC47.js.map +7 -0
- package/bundle/skill-stats-LLEXEXLR.js +22 -0
- package/bundle/skill-stats-LLEXEXLR.js.map +7 -0
- package/bundle/sleep-OYIUOVQD.js +19 -0
- package/bundle/sleep-OYIUOVQD.js.map +7 -0
- package/bundle/soul-loader-54WCVNLJ.js +16 -0
- package/bundle/soul-loader-54WCVNLJ.js.map +7 -0
- package/bundle/src-JL4PVO23.js +8 -0
- package/bundle/src-JL4PVO23.js.map +7 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js +72 -0
- package/bundle/sse-parser-anthropic-P7CE2MH2.js.map +7 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js +63 -0
- package/bundle/sse-parser-responses-EQQA5FWN.js.map +7 -0
- package/bundle/ssrf-guard-FZCBYIVW.js +64 -0
- package/bundle/ssrf-guard-FZCBYIVW.js.map +7 -0
- package/bundle/start-FH3GRMJ4.js +35 -0
- package/bundle/start-FH3GRMJ4.js.map +7 -0
- package/bundle/stream-single-WSG4D53C.js +33 -0
- package/bundle/stream-single-WSG4D53C.js.map +7 -0
- package/bundle/stt-2UH3RITX.js +14 -0
- package/bundle/stt-2UH3RITX.js.map +7 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js +12 -0
- package/bundle/subagent-runtime-LE2ZXH3G.js.map +7 -0
- package/bundle/system-message-T5R3EYYN.js +30 -0
- package/bundle/system-message-T5R3EYYN.js.map +7 -0
- package/bundle/system-status-KQ6KHFJ6.js +189 -0
- package/bundle/system-status-KQ6KHFJ6.js.map +7 -0
- package/bundle/task-store-K7CQDEPI.js +22 -0
- package/bundle/task-store-K7CQDEPI.js.map +7 -0
- package/bundle/telegram-adapter-2V3XUMT5.js +1060 -0
- package/bundle/telegram-adapter-2V3XUMT5.js.map +7 -0
- package/bundle/tool-registry-MU3OX4UI.js +38 -0
- package/bundle/tool-registry-MU3OX4UI.js.map +7 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js +20 -0
- package/bundle/tool-sandbox-VYOK4ZOA.js.map +7 -0
- package/bundle/transport-config-YLXU33RO.js +57 -0
- package/bundle/transport-config-YLXU33RO.js.map +7 -0
- package/bundle/update-QCW5LXRN.js +13 -0
- package/bundle/update-QCW5LXRN.js.map +7 -0
- package/bundle/update-check-27KZSAP6.js +12 -0
- package/bundle/update-check-27KZSAP6.js.map +7 -0
- package/bundle/usage-tracker-OVVEVMOY.js +17 -0
- package/bundle/usage-tracker-OVVEVMOY.js.map +7 -0
- package/bundle/user-registry-D4SD73UV.js +16 -0
- package/bundle/user-registry-D4SD73UV.js.map +7 -0
- package/core/professor.json +14 -0
- package/core/prompts/browsing_prompt.md +39 -0
- package/core/prompts/compaction.md +32 -0
- package/core/skills/memory/classification/SKILL.md +37 -0
- package/core/skills/memory/memory-anomalies/SKILL.md +39 -0
- package/core/skills/memory/memory-search/SKILL.md +48 -0
- package/core/skills/memory/topic-save/SKILL.md +44 -0
- package/core/skills/ops/cron/SKILL.md +51 -0
- package/core/skills/ops/gdrive-backup/SKILL.md +15 -0
- package/core/skills/ops/session-start/SKILL.md +11 -0
- package/core/skills/ops/skill-authoring/SKILL.md +54 -0
- package/core/skills/ops/system-health/SKILL.md +104 -0
- package/core/skills/ops/troubleshooting/SKILL.md +48 -0
- package/core/skills/ops/trust-gating/SKILL.md +30 -0
- package/core/skills/tools/a2a-communication/SKILL.md +68 -0
- package/core/skills/tools/browse-delegate/SKILL.md +27 -0
- package/core/skills/tools/browser/SKILL.md +36 -0
- package/core/skills/tools/clawhub/SKILL.md +44 -0
- package/core/skills/tools/delegation/SKILL.md +48 -0
- package/core/skills/tools/fxtwitter/SKILL.md +52 -0
- package/core/skills/tools/gmail/SKILL.md +44 -0
- package/core/skills/tools/irc-chat/SKILL.md +84 -0
- package/core/skills/tools/linear/SKILL.md +90 -0
- package/core/skills/tools/mcporter/SKILL.md +46 -0
- package/core/skills/tools/model-scout/SKILL.md +132 -0
- package/core/skills/tools/model-scout/scout-add-model.py +67 -0
- package/core/skills/tools/model-scout/scout-ollama.py +116 -0
- package/core/skills/tools/model-scout/scout-openrouter.py +85 -0
- package/core/skills/tools/nlm/SKILL.md +40 -0
- package/core/skills/tools/todo/SKILL.md +30 -0
- package/core/skills/tools/twitterX/SKILL.md +52 -0
- package/core/skills/tools/twitterX/scripts/abtars-tweet.js +532 -0
- package/core/skills/tools/twitterX/scripts/package.json +1 -0
- package/core/skills/tools/web-fetch/SKILL.md +29 -0
- package/package.json +59 -0
- package/scripts/abtars-daemon.service +23 -0
- package/scripts/abtars-fetch.sh +42 -0
- package/scripts/abtars-watchdog.service +13 -0
- package/scripts/abtars.sh +14 -0
- package/scripts/abtars@.service +21 -0
- package/scripts/browser-patchright.sh +79 -0
- package/scripts/com.abtars.daemon.plist +24 -0
- package/scripts/com.abtars.watchdog.plist +27 -0
- package/scripts/daily-backup.sh +62 -0
- package/scripts/doctor.sh +553 -0
- package/scripts/hooks/audit-logger.sh +22 -0
- package/scripts/upgrade-deps.sh +64 -0
- 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
|