abtars 0.2.0 → 0.2.1-alpha.10
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/README.md +15 -18
- package/bundle/{_registry.generated-6GO2PAMD.js → _registry.generated-4P6KTBTH.js} +8 -8
- package/bundle/_registry.generated-G2FSGHNY.js +36 -0
- package/bundle/_registry.generated-G2FSGHNY.js.map +7 -0
- package/bundle/_registry.generated-N74SMTUJ.js +36 -0
- package/bundle/_registry.generated-N74SMTUJ.js.map +7 -0
- package/bundle/_registry.generated-Y4VT5MBX.js +36 -0
- package/bundle/_registry.generated-Y4VT5MBX.js.map +7 -0
- package/bundle/abtars-browser.js +0 -1
- package/bundle/abtars-browser.js.map +2 -2
- package/bundle/abtars-cli.js +589 -547
- package/bundle/abtars-cli.js.map +4 -4
- package/bundle/abtars-restart.js +1 -1
- package/bundle/abtars-rss.js +0 -1
- package/bundle/abtars-rss.js.map +2 -2
- package/bundle/abtars-task.js +1 -2
- package/bundle/abtars-task.js.map +2 -2
- package/bundle/abtars.js +58 -33
- package/bundle/abtars.js.map +2 -2
- package/bundle/{agent-registry-SYUFNSVB.js → agent-registry-TM7EISOV.js} +2 -2
- package/bundle/{browse-delivery-64GQIUHG.js → browse-delivery-VTLEAVYA.js} +4 -4
- package/bundle/{browser-5H2Q7GEC.js → browser-JQGYFZAG.js} +5 -5
- package/bundle/browser-M4KDLN75.js +19 -0
- package/bundle/browser-REIXOJ6S.js +19 -0
- package/bundle/browser-VG2GTEND.js +19 -0
- package/bundle/{chunk-KFENC7BM.js → chunk-4YOTNYAE.js} +2 -2
- package/bundle/{chunk-KWBGYWDO.js → chunk-7I5C2U3C.js} +1 -1
- package/bundle/chunk-7I5C2U3C.js.map +7 -0
- package/bundle/{chunk-7STAQF5O.js → chunk-CNWXVXGH.js} +4 -4
- package/bundle/{chunk-7STAQF5O.js.map → chunk-CNWXVXGH.js.map} +2 -2
- package/bundle/{chunk-JX3ZZU3O.js → chunk-CU3O53U3.js} +28 -14
- package/bundle/chunk-CU3O53U3.js.map +7 -0
- package/bundle/chunk-EZZBO2QK.js +85 -0
- package/bundle/chunk-EZZBO2QK.js.map +7 -0
- package/bundle/{chunk-XLLSPBBT.js → chunk-GPL57SRN.js} +2 -2
- package/bundle/chunk-GPL57SRN.js.map +7 -0
- package/bundle/{chunk-PQ62LZNA.js → chunk-HEHD3GG5.js} +2 -2
- package/bundle/{chunk-A5OJYQNU.js → chunk-HTGVYNPE.js} +4 -4
- package/bundle/{chunk-WUTCGJDZ.js → chunk-HZRUBJ4Q.js} +148 -9
- package/bundle/chunk-HZRUBJ4Q.js.map +7 -0
- package/bundle/{chunk-ZVDVNSXK.js → chunk-J7CFCY4U.js} +2 -2
- package/bundle/{chunk-HXJRZWKA.js → chunk-JRK3UFBS.js} +106 -58
- package/bundle/chunk-JRK3UFBS.js.map +7 -0
- package/bundle/{chunk-GZUQQWBZ.js → chunk-KJOCXWJ5.js} +3 -3
- package/bundle/chunk-KJOCXWJ5.js.map +7 -0
- package/bundle/{chunk-K7P74UNQ.js → chunk-LDKSCXGL.js} +3 -3
- package/bundle/{chunk-K7P74UNQ.js.map → chunk-LDKSCXGL.js.map} +2 -2
- package/bundle/chunk-MNKLPRGY.js +138 -0
- package/bundle/chunk-MNKLPRGY.js.map +7 -0
- package/bundle/chunk-O73EZGKR.js +135 -0
- package/bundle/chunk-O73EZGKR.js.map +7 -0
- package/bundle/{chunk-OZ4IZFV4.js → chunk-Q7F5R2LL.js} +1 -1
- package/bundle/{chunk-OZ4IZFV4.js.map → chunk-Q7F5R2LL.js.map} +2 -2
- package/bundle/{chunk-XOCP5BMO.js → chunk-URAQLQ2U.js} +2 -2
- package/bundle/chunk-URAQLQ2U.js.map +7 -0
- package/bundle/{chunk-PPSB2ZIN.js → chunk-VREI2GUO.js} +18 -7
- package/bundle/chunk-VREI2GUO.js.map +7 -0
- package/bundle/chunk-VYR25H37.js +135 -0
- package/bundle/chunk-VYR25H37.js.map +7 -0
- package/bundle/{commands-E3Y4QUNF.js → commands-J6JAZ7D2.js} +5 -5
- package/bundle/{deploy-lib-import-ODLDL2DB.js → deploy-lib-import-PJXUADPS.js} +18 -16
- package/bundle/{direct-api-transport-TRV45NO6.js → direct-api-transport-ZSJHKYBX.js} +1 -1
- package/bundle/direct-api-transport-ZSJHKYBX.js.map +7 -0
- package/bundle/{discord-adapter-5DS7UTBE.js → discord-adapter-OCWSJTJU.js} +8 -8
- package/bundle/{doctor-R54GZPKL.js → doctor-XOGVHA4W.js} +13 -2
- package/bundle/{doctor-R54GZPKL.js.map → doctor-XOGVHA4W.js.map} +2 -2
- package/bundle/{install-RSLOS3Q5.js → install-6H3APAIJ.js} +3 -3
- package/bundle/{irc-adapter-RKRUSZXB.js → irc-adapter-AIEP6OX6.js} +6 -2
- package/bundle/irc-adapter-AIEP6OX6.js.map +7 -0
- package/bundle/{message-pipeline-CFVO73CK.js → message-pipeline-TCPHRBAK.js} +5 -5
- package/bundle/meta.json +4005 -3868
- package/bundle/{phase-transport-FEZ4SIJJ.js → phase-transport-ME2XDRR2.js} +3 -3
- package/bundle/restore-UH2UE2K5.js +151 -0
- package/bundle/restore-UH2UE2K5.js.map +7 -0
- package/bundle/rollback-D7AYTC7Z.js +11 -0
- package/bundle/{sleep-BPWX3FCN.js → sleep-IOWYTSMK.js} +2 -2
- package/bundle/{soul-bundle-BRIUDEQ2.js → soul-bundle-AH5S3MVI.js} +2 -2
- package/bundle/{soul-loader-GBXJ7EBH.js → soul-loader-N5FA4I6C.js} +3 -3
- package/bundle/soul-loader-N5FA4I6C.js.map +7 -0
- package/bundle/{start-4IWBKLWO.js → start-CBVKNEAT.js} +1 -1
- package/bundle/{subagent-runtime-MDBO6LHS.js → subagent-runtime-OOJXCKJF.js} +2 -2
- package/bundle/subagent-runtime-OOJXCKJF.js.map +7 -0
- package/bundle/{system-status-WAY63BYC.js → system-status-4JP36OKC.js} +12 -5
- package/bundle/{system-status-WAY63BYC.js.map → system-status-4JP36OKC.js.map} +2 -2
- package/bundle/{task-store-KIBFZL5A.js → task-store-LC7ZMS72.js} +2 -2
- package/bundle/task-store-LC7ZMS72.js.map +7 -0
- package/bundle/{telegram-adapter-MVA33IO2.js → telegram-adapter-QXHJQLLX.js} +5 -5
- package/bundle/{update-check-O5MS6B3L.js → update-check-XVY2IK2L.js} +2 -2
- package/bundle/update-check-XVY2IK2L.js.map +7 -0
- package/core/skills/tools/rss/SKILL.md +51 -0
- package/install-manifest.json +4 -3
- package/package.json +3 -4
- package/scripts/abtars-daemon.service +1 -1
- package/scripts/abtars-watchdog.service +1 -1
- package/scripts/abtars.sh +3 -5
- package/scripts/abtars@.service +1 -1
- package/scripts/build-and-deploy.sh +6 -0
- package/scripts/com.abtars.daemon.plist +1 -1
- package/scripts/com.abtars.watchdog.plist +1 -1
- package/scripts/daily-backup.sh +1 -61
- package/scripts/doctor.sh +48 -33
- package/scripts/watchdog.sh +53 -8
- package/bundle/chunk-GZUQQWBZ.js.map +0 -7
- package/bundle/chunk-HXJRZWKA.js.map +0 -7
- package/bundle/chunk-JX3ZZU3O.js.map +0 -7
- package/bundle/chunk-KWBGYWDO.js.map +0 -7
- package/bundle/chunk-PPSB2ZIN.js.map +0 -7
- package/bundle/chunk-WUTCGJDZ.js.map +0 -7
- package/bundle/chunk-XLLSPBBT.js.map +0 -7
- package/bundle/chunk-XOCP5BMO.js.map +0 -7
- package/bundle/direct-api-transport-TRV45NO6.js.map +0 -7
- package/bundle/irc-adapter-RKRUSZXB.js.map +0 -7
- package/bundle/passwd-QSHZJ2CG.js +0 -134
- package/bundle/passwd-QSHZJ2CG.js.map +0 -7
- package/bundle/restore-ROJF22R2.js +0 -47
- package/bundle/restore-ROJF22R2.js.map +0 -7
- package/core/core_templates/SOUL.md +0 -24
- package/core/core_templates/agent_notes.md +0 -7
- package/core/core_templates/core_facts.md +0 -10
- package/core/core_templates/user_profile.md +0 -7
- package/core/skills/tools/fxtwitter/SKILL.md +0 -52
- package/core/skills/tools/twitterX/SKILL.md +0 -52
- package/core/skills/tools/twitterX/scripts/abtars-tweet.js +0 -532
- package/core/skills/tools/twitterX/scripts/package.json +0 -1
- /package/bundle/{_registry.generated-6GO2PAMD.js.map → _registry.generated-4P6KTBTH.js.map} +0 -0
- /package/bundle/{agent-registry-SYUFNSVB.js.map → agent-registry-TM7EISOV.js.map} +0 -0
- /package/bundle/{browse-delivery-64GQIUHG.js.map → browse-delivery-VTLEAVYA.js.map} +0 -0
- /package/bundle/{browser-5H2Q7GEC.js.map → browser-JQGYFZAG.js.map} +0 -0
- /package/bundle/{commands-E3Y4QUNF.js.map → browser-M4KDLN75.js.map} +0 -0
- /package/bundle/{deploy-lib-import-ODLDL2DB.js.map → browser-REIXOJ6S.js.map} +0 -0
- /package/bundle/{install-RSLOS3Q5.js.map → browser-VG2GTEND.js.map} +0 -0
- /package/bundle/{chunk-KFENC7BM.js.map → chunk-4YOTNYAE.js.map} +0 -0
- /package/bundle/{chunk-PQ62LZNA.js.map → chunk-HEHD3GG5.js.map} +0 -0
- /package/bundle/{chunk-A5OJYQNU.js.map → chunk-HTGVYNPE.js.map} +0 -0
- /package/bundle/{chunk-ZVDVNSXK.js.map → chunk-J7CFCY4U.js.map} +0 -0
- /package/bundle/{message-pipeline-CFVO73CK.js.map → commands-J6JAZ7D2.js.map} +0 -0
- /package/bundle/{phase-transport-FEZ4SIJJ.js.map → deploy-lib-import-PJXUADPS.js.map} +0 -0
- /package/bundle/{discord-adapter-5DS7UTBE.js.map → discord-adapter-OCWSJTJU.js.map} +0 -0
- /package/bundle/{sleep-BPWX3FCN.js.map → install-6H3APAIJ.js.map} +0 -0
- /package/bundle/{soul-bundle-BRIUDEQ2.js.map → message-pipeline-TCPHRBAK.js.map} +0 -0
- /package/bundle/{soul-loader-GBXJ7EBH.js.map → phase-transport-ME2XDRR2.js.map} +0 -0
- /package/bundle/{subagent-runtime-MDBO6LHS.js.map → rollback-D7AYTC7Z.js.map} +0 -0
- /package/bundle/{task-store-KIBFZL5A.js.map → sleep-IOWYTSMK.js.map} +0 -0
- /package/bundle/{update-check-O5MS6B3L.js.map → soul-bundle-AH5S3MVI.js.map} +0 -0
- /package/bundle/{start-4IWBKLWO.js.map → start-CBVKNEAT.js.map} +0 -0
- /package/bundle/{telegram-adapter-MVA33IO2.js.map → telegram-adapter-QXHJQLLX.js.map} +0 -0
package/scripts/abtars@.service
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<key>WorkingDirectory</key><string>/Users/{{USER}}/.abtars</string>
|
|
9
9
|
<key>ProgramArguments</key>
|
|
10
10
|
<array>
|
|
11
|
-
<string>/Users/{{USER}}/.abtars/watchdog.sh</string>
|
|
11
|
+
<string>/Users/{{USER}}/.abtars/scripts/watchdog.sh</string>
|
|
12
12
|
</array>
|
|
13
13
|
<key>KeepAlive</key><true/>
|
|
14
14
|
<key>RunAtLoad</key><true/>
|
package/scripts/daily-backup.sh
CHANGED
|
@@ -1,62 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
AB="$HOME/.abtars"
|
|
5
|
-
ABMIND="${ABMIND_HOME:-$HOME/.abmind}"
|
|
6
|
-
DEST="$HOME/.backup-abtars"
|
|
7
|
-
DATE=$(date +%Y%m%d)
|
|
8
|
-
|
|
9
|
-
mkdir -p "$DEST"
|
|
10
|
-
|
|
11
|
-
# WAL-safe memory.db backup via sqlite3
|
|
12
|
-
DB="$ABMIND/memory/memory.db"
|
|
13
|
-
DB_TMP="$DEST/.memory-$DATE.db"
|
|
14
|
-
if [ -f "$DB" ] && command -v sqlite3 &>/dev/null; then
|
|
15
|
-
sqlite3 "$DB" ".backup '$DB_TMP'"
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
# Zip backup: abtars config/skills + abmind core/memory
|
|
19
|
-
cd "$AB"
|
|
20
|
-
zip -qr "$DEST/abtars-$DATE.zip" \
|
|
21
|
-
config/ secret/ skills/ prompts/ tasks/ topics/ reports/ finance/ core/ \
|
|
22
|
-
-x "config/.env.skills" 2>/dev/null || true
|
|
23
|
-
|
|
24
|
-
# Add abmind memory/core + sleep reports
|
|
25
|
-
if [ -d "$ABMIND/memory" ]; then
|
|
26
|
-
cd "$ABMIND"
|
|
27
|
-
zip -qr "$DEST/abtars-$DATE.zip" \
|
|
28
|
-
memory/core/ memory/sleep/ 2>/dev/null || true
|
|
29
|
-
fi
|
|
30
|
-
|
|
31
|
-
# Add the WAL-safe DB copy
|
|
32
|
-
if [ -f "$DB_TMP" ]; then
|
|
33
|
-
cd "$DEST"
|
|
34
|
-
zip -qj "$DEST/abtars-$DATE.zip" "$DB_TMP"
|
|
35
|
-
rm -f "$DB_TMP"
|
|
36
|
-
fi
|
|
37
|
-
|
|
38
|
-
# Encrypted DB backup
|
|
39
|
-
mkdir -p "$AB/backup"
|
|
40
|
-
DB_KEY="$AB/secret/db.key"
|
|
41
|
-
if [ -f "$DB_KEY" ] && [ -f "$DB" ]; then
|
|
42
|
-
sqlite3 "$DB" ".backup '$AB/backup/memory.db.tmp'"
|
|
43
|
-
openssl enc -aes-256-cbc -pbkdf2 -salt -pass "file:$DB_KEY" \
|
|
44
|
-
-in "$AB/backup/memory.db.tmp" -out "$AB/backup/memory.db.enc"
|
|
45
|
-
rm -f "$AB/backup/memory.db.tmp"
|
|
46
|
-
fi
|
|
47
|
-
|
|
48
|
-
# Prune >7 days
|
|
49
|
-
find "$DEST" -name "abtars-*.zip" -mtime +7 -delete
|
|
50
|
-
|
|
51
|
-
# DoD: verify zip contains memory DB and is reasonable size
|
|
52
|
-
ZIP="$DEST/abtars-$DATE.zip"
|
|
53
|
-
if ! unzip -l "$ZIP" 2>/dev/null | grep -q "memory.*\.db"; then
|
|
54
|
-
echo "ERROR: backup zip missing memory.db" >&2
|
|
55
|
-
exit 1
|
|
56
|
-
fi
|
|
57
|
-
MIN_SIZE=100000 # 100KB minimum
|
|
58
|
-
ACTUAL=$(stat -f%z "$ZIP" 2>/dev/null || stat -c%s "$ZIP" 2>/dev/null || echo 0)
|
|
59
|
-
if [ "$ACTUAL" -lt "$MIN_SIZE" ]; then
|
|
60
|
-
echo "ERROR: backup zip too small (${ACTUAL} bytes)" >&2
|
|
61
|
-
exit 1
|
|
62
|
-
fi
|
|
2
|
+
exec abtars backup "$@"
|
package/scripts/doctor.sh
CHANGED
|
@@ -3,21 +3,18 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Usage:
|
|
5
5
|
# doctor.sh # diagnose only -- prints warnings, changes nothing
|
|
6
|
-
# doctor.sh --fix # safe fixes (chmod, mkdir, stale locks,
|
|
7
|
-
# doctor.sh --fix-full # all safe fixes + FTS rebuild, WAL checkpoint, git push check
|
|
6
|
+
# doctor.sh --fix # safe fixes (chmod, mkdir, stale locks, watchdog install, delegate to abmind)
|
|
8
7
|
set -uo pipefail
|
|
9
8
|
|
|
10
9
|
AB="$HOME/.abtars"
|
|
11
10
|
ABMIND="${ABMIND_HOME:-$HOME/.abmind}"
|
|
12
11
|
DB="$ABMIND/memory/memory.db"
|
|
13
12
|
FIX=false
|
|
14
|
-
FIX_FULL=false
|
|
15
13
|
WARNS=0
|
|
16
14
|
FIXES=0
|
|
17
15
|
|
|
18
16
|
case "${1:-}" in
|
|
19
|
-
--fix
|
|
20
|
-
--fix) FIX=true ;;
|
|
17
|
+
--fix|--fix) FIX=true ;;
|
|
21
18
|
esac
|
|
22
19
|
|
|
23
20
|
warn() { echo "[doctor] WARN: $1"; WARNS=$((WARNS + 1)); }
|
|
@@ -132,7 +129,7 @@ if [ -f "$WD_LOCK" ]; then
|
|
|
132
129
|
elif command -v systemctl &>/dev/null && systemctl --user is-enabled abtars-watchdog.service &>/dev/null; then
|
|
133
130
|
systemctl --user restart abtars-watchdog.service 2>/dev/null && fix "restarted watchdog via systemd"
|
|
134
131
|
else
|
|
135
|
-
warn "watchdog not running -- start manually: ~/.abtars/watchdog.sh
|
|
132
|
+
warn "watchdog not running -- start manually: ~/.abtars/scripts/watchdog.sh &"
|
|
136
133
|
fi
|
|
137
134
|
fi
|
|
138
135
|
fi
|
|
@@ -144,7 +141,7 @@ else
|
|
|
144
141
|
elif command -v systemctl &>/dev/null && systemctl --user is-enabled abtars-watchdog.service &>/dev/null; then
|
|
145
142
|
systemctl --user start abtars-watchdog.service 2>/dev/null && fix "started watchdog via systemd"
|
|
146
143
|
else
|
|
147
|
-
warn "start manually: ~/.abtars/watchdog.sh
|
|
144
|
+
warn "start manually: ~/.abtars/scripts/watchdog.sh &"
|
|
148
145
|
fi
|
|
149
146
|
fi
|
|
150
147
|
fi
|
|
@@ -153,7 +150,7 @@ fi
|
|
|
153
150
|
if [[ "$INSTALL_MODE" == "supervised" || "$INSTALL_MODE" == "supervised-daemon" ]]; then
|
|
154
151
|
if [[ "$(uname)" == "Darwin" ]]; then
|
|
155
152
|
if ! launchctl list 2>/dev/null | grep -q abtars.watchdog; then
|
|
156
|
-
if $FIX
|
|
153
|
+
if $FIX; then
|
|
157
154
|
PLIST_SRC="$(dirname "$0")/com.abtars.watchdog.plist"
|
|
158
155
|
PLIST_DST="$HOME/Library/LaunchAgents/com.abtars.watchdog.plist"
|
|
159
156
|
if [ -f "$PLIST_SRC" ]; then
|
|
@@ -163,12 +160,12 @@ if [[ "$(uname)" == "Darwin" ]]; then
|
|
|
163
160
|
warn "watchdog LaunchAgent not loaded -- plist not found at $PLIST_SRC"
|
|
164
161
|
fi
|
|
165
162
|
else
|
|
166
|
-
warn "watchdog LaunchAgent not loaded -- run with --fix
|
|
163
|
+
warn "watchdog LaunchAgent not loaded -- run with --fix to install"
|
|
167
164
|
fi
|
|
168
165
|
fi
|
|
169
166
|
elif command -v systemctl &>/dev/null; then
|
|
170
167
|
if ! systemctl --user is-enabled abtars-watchdog.service &>/dev/null 2>&1; then
|
|
171
|
-
if $
|
|
168
|
+
if $FIX; then
|
|
172
169
|
SVC_SRC="$(dirname "$0")/abtars-watchdog.service"
|
|
173
170
|
SVC_DST="$HOME/.config/systemd/user/abtars-watchdog.service"
|
|
174
171
|
if [ -f "$SVC_SRC" ]; then
|
|
@@ -180,7 +177,7 @@ elif command -v systemctl &>/dev/null; then
|
|
|
180
177
|
warn "watchdog systemd unit not enabled -- service file not found at $SVC_SRC"
|
|
181
178
|
fi
|
|
182
179
|
else
|
|
183
|
-
warn "watchdog systemd unit not enabled -- run with --fix
|
|
180
|
+
warn "watchdog systemd unit not enabled -- run with --fix to install"
|
|
184
181
|
fi
|
|
185
182
|
fi
|
|
186
183
|
fi
|
|
@@ -190,7 +187,7 @@ fi # end supervised-only supervisor check
|
|
|
190
187
|
# 1. Directory permissions (sensitive dirs should be 700)
|
|
191
188
|
for d in "$AB/secret" "$AB/secret/cookies" "$ABMIND/memory"; do
|
|
192
189
|
if [ -d "$d" ] && [ "$(file_mode "$d")" != "700" ]; then
|
|
193
|
-
if $FIX
|
|
190
|
+
if $FIX; then
|
|
194
191
|
chmod 700 "$d"; fix "$d permissions → 700"
|
|
195
192
|
else
|
|
196
193
|
warn "$d permissions not 700"
|
|
@@ -210,6 +207,16 @@ while IFS= read -r f; do
|
|
|
210
207
|
fi
|
|
211
208
|
done < <(find "$AB" -name "*.lock" -not -path "*/sleep/*" -not -path "*/node_modules/*" -not -name "watchdog.lock" -mmin +60 2>/dev/null)
|
|
212
209
|
|
|
210
|
+
# 2b. Stale Unix sockets (left by dead bridge process)
|
|
211
|
+
for sock in "$AB/browser-socket/"*.sock "$AB/"*.sock "${ABMIND_HOME:-$HOME/.abmind}/"*.sock; do
|
|
212
|
+
[ -S "$sock" ] || continue
|
|
213
|
+
if $FIX; then
|
|
214
|
+
rm -f "$sock"; fix "removed stale socket $sock"
|
|
215
|
+
else
|
|
216
|
+
warn "stale socket: $sock"
|
|
217
|
+
fi
|
|
218
|
+
done
|
|
219
|
+
|
|
213
220
|
# 3. Stale sleep lock (older than 2 hours, no matching audit .md)
|
|
214
221
|
for lockfile in "$ABMIND/memory/sleep"/sleep_*.lock; do
|
|
215
222
|
[ -f "$lockfile" ] || continue
|
|
@@ -350,6 +357,22 @@ if [ "$KIRO_PROCS" -gt 1 ]; then
|
|
|
350
357
|
fi
|
|
351
358
|
fi
|
|
352
359
|
|
|
360
|
+
# 14b. Orphaned gemini-cli processes
|
|
361
|
+
GEMINI_PROCS=$(pgrep -f 'gemini.*--acp' 2>/dev/null | wc -l)
|
|
362
|
+
if [ "$GEMINI_PROCS" -gt 1 ]; then
|
|
363
|
+
if $FIX; then
|
|
364
|
+
PIDS=$(pgrep -f 'gemini.*--acp' 2>/dev/null | sort -n)
|
|
365
|
+
NEWEST=$(echo "$PIDS" | tail -1)
|
|
366
|
+
for pid in $PIDS; do
|
|
367
|
+
if [ "$pid" != "$NEWEST" ]; then
|
|
368
|
+
kill "$pid" 2>/dev/null && fix "killed orphaned gemini-cli pid $pid"
|
|
369
|
+
fi
|
|
370
|
+
done
|
|
371
|
+
else
|
|
372
|
+
warn "$GEMINI_PROCS gemini-cli acp processes running -- likely orphans from previous bridge"
|
|
373
|
+
fi
|
|
374
|
+
fi
|
|
375
|
+
|
|
353
376
|
# 12b. Orphaned abtars-sleep processes
|
|
354
377
|
SLEEP_PROCS=$(pgrep -f 'abtars-sleep' 2>/dev/null | wc -l)
|
|
355
378
|
if [ "$SLEEP_PROCS" -gt 1 ]; then
|
|
@@ -383,21 +406,13 @@ if $WD_ALIVE && [ -n "$WD_PID" ]; then
|
|
|
383
406
|
fi
|
|
384
407
|
fi
|
|
385
408
|
|
|
386
|
-
# 13.
|
|
387
|
-
if
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if $FIX_FULL; then
|
|
394
|
-
cd "$AB"
|
|
395
|
-
if [ -d .git ]; then
|
|
396
|
-
if ! git remote get-url origin &>/dev/null; then
|
|
397
|
-
warn "git remote 'origin' missing -- backup push will fail"
|
|
398
|
-
elif ! timeout 5 git push --dry-run &>/dev/null; then
|
|
399
|
-
warn "git push would fail -- check upstream/auth"
|
|
400
|
-
fi
|
|
409
|
+
# 13. Delegate DB health to abmind doctor
|
|
410
|
+
if [ -d "$ABMIND" ] && command -v abmind &>/dev/null; then
|
|
411
|
+
echo "[doctor] Delegating DB health to abmind doctor..."
|
|
412
|
+
if $FIX; then
|
|
413
|
+
abmind doctor --fix 2>&1 | sed 's/^/ [abmind] /'
|
|
414
|
+
else
|
|
415
|
+
abmind doctor 2>&1 | sed 's/^/ [abmind] /'
|
|
401
416
|
fi
|
|
402
417
|
fi
|
|
403
418
|
|
|
@@ -475,7 +490,7 @@ check_perm() {
|
|
|
475
490
|
actual=$(stat -c "%a" "$path" 2>/dev/null || stat -f "%Lp" "$path" 2>/dev/null)
|
|
476
491
|
if [ "$actual" != "$expected" ]; then
|
|
477
492
|
warn "$label is $actual — should be $expected"
|
|
478
|
-
if $FIX
|
|
493
|
+
if $FIX; then
|
|
479
494
|
chmod "$expected" "$path" && fix "$label → $expected"
|
|
480
495
|
fi
|
|
481
496
|
fi
|
|
@@ -493,7 +508,7 @@ for dir in "$AB/config" "$AB/secret"; do
|
|
|
493
508
|
actual=$(stat -c "%a" "$f" 2>/dev/null || stat -f "%Lp" "$f" 2>/dev/null)
|
|
494
509
|
if [ "$actual" != "600" ]; then
|
|
495
510
|
warn "$(basename "$f") in $(basename "$dir")/ is $actual — should be 600"
|
|
496
|
-
if $FIX
|
|
511
|
+
if $FIX; then
|
|
497
512
|
chmod 600 "$f" && fix "$(basename "$f") → 600"
|
|
498
513
|
fi
|
|
499
514
|
fi
|
|
@@ -517,7 +532,7 @@ fi
|
|
|
517
532
|
|
|
518
533
|
total_stale=$((stale_logs + stale_overflow + stale_reports + stale_media))
|
|
519
534
|
if [ "$total_stale" -gt 0 ] || [ "$audit_size" -gt "$AUDIT_MAX_BYTES" ]; then
|
|
520
|
-
if $FIX
|
|
535
|
+
if $FIX; then
|
|
521
536
|
[ "$stale_logs" -gt 0 ] && find "$AB/logs" -type f -name "*.log" -mtime +"$LOGS_KEEP_DAYS" -delete && fix "deleted $stale_logs log file(s) older than ${LOGS_KEEP_DAYS}d"
|
|
522
537
|
[ "$stale_overflow" -gt 0 ] && find "$AB/overflow" -type f -mtime +"$DATA_KEEP_DAYS" -delete && fix "deleted $stale_overflow overflow file(s) older than ${DATA_KEEP_DAYS}d"
|
|
523
538
|
[ "$stale_reports" -gt 0 ] && find "$AB/reports" -type f -mtime +"$DATA_KEEP_DAYS" -delete && fix "deleted $stale_reports report file(s) older than ${DATA_KEEP_DAYS}d"
|
|
@@ -533,19 +548,19 @@ if [ "$total_stale" -gt 0 ] || [ "$audit_size" -gt "$AUDIT_MAX_BYTES" ]; then
|
|
|
533
548
|
fi
|
|
534
549
|
|
|
535
550
|
# Summary
|
|
536
|
-
if $
|
|
551
|
+
if $FIX && [ -f "$AB/logs/watchdog.log" ]; then
|
|
537
552
|
echo ""
|
|
538
553
|
echo "[doctor] Last 10 lines of watchdog.log:"
|
|
539
554
|
tail -10 "$AB/logs/watchdog.log" | sed 's/^/ /'
|
|
540
555
|
fi
|
|
541
556
|
|
|
542
|
-
if $FIX
|
|
557
|
+
if $FIX; then
|
|
543
558
|
echo "[doctor] Done. $FIXES fixes applied, $WARNS warnings."
|
|
544
559
|
else
|
|
545
560
|
if [ "$WARNS" -eq 0 ]; then
|
|
546
561
|
echo "[doctor] All clear."
|
|
547
562
|
else
|
|
548
|
-
echo "[doctor] $WARNS warnings. Run with --fix
|
|
563
|
+
echo "[doctor] $WARNS warnings. Run with --fix to repair."
|
|
549
564
|
fi
|
|
550
565
|
fi
|
|
551
566
|
|
package/scripts/watchdog.sh
CHANGED
|
@@ -27,7 +27,7 @@ fi
|
|
|
27
27
|
SUSPEND_GRACE="${SUSPEND_GRACE:-true}"
|
|
28
28
|
STARTUP_TIMEOUT=$(( HB_SEC + POLL_SEC * 2 ))
|
|
29
29
|
CIRCUIT_MAX=3
|
|
30
|
-
CIRCUIT_WINDOW=
|
|
30
|
+
CIRCUIT_WINDOW=180
|
|
31
31
|
MAX_LOG_BYTES=10485760
|
|
32
32
|
|
|
33
33
|
BRIDGE_PID=""
|
|
@@ -123,10 +123,52 @@ circuit_check() {
|
|
|
123
123
|
|
|
124
124
|
spawn_bridge() {
|
|
125
125
|
if ! circuit_check; then
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
# Auto-rollback attempt before giving up
|
|
127
|
+
local PREV="$AB/app.prev.1"
|
|
128
|
+
if [ -d "$PREV" ]; then
|
|
129
|
+
local ROLLED_VER
|
|
130
|
+
ROLLED_VER=$(python3 -c "import json; print(json.load(open('$PREV/package.json'))['version'])" 2>/dev/null || echo "unknown")
|
|
131
|
+
log "🔄 Circuit breaker — attempting auto-rollback to $ROLLED_VER..."
|
|
132
|
+
rm -rf "$AB/app.broken"
|
|
133
|
+
mv "$AB/app" "$AB/app.broken"
|
|
134
|
+
mv "$PREV" "$AB/app"
|
|
135
|
+
RESTART_TIMES=() # Reset counter for the rollback attempt
|
|
136
|
+
|
|
137
|
+
# Try starting the rolled-back version
|
|
138
|
+
if [ -x "$AB/scripts/doctor.sh" ]; then
|
|
139
|
+
timeout 30 "$AB/scripts/doctor.sh" --fix >> "$AB/logs/launchd.log" 2>&1 || true
|
|
140
|
+
fi
|
|
141
|
+
rm -f "$LOCK"
|
|
142
|
+
if [ -f "$AB/config/.env" ]; then set -a; source "$AB/config/.env"; set +a; fi
|
|
143
|
+
log "Starting bridge (rollback): node app/bundle/abtars.js"
|
|
144
|
+
cd "$AB"
|
|
145
|
+
NODE_PATH="${ABMIND_HOME:-$HOME/.abmind}/lib/node_modules:${NODE_PATH:-}" node app/bundle/abtars.js >> "$AB/logs/launchd.log" 2>&1 &
|
|
146
|
+
BRIDGE_PID=""
|
|
147
|
+
for i in $(seq 1 15); do
|
|
148
|
+
sleep 2
|
|
149
|
+
if [ -f "$LOCK" ]; then
|
|
150
|
+
BRIDGE_PID=$(grep -o '"pid":[0-9]*' "$LOCK" | grep -o '[0-9]*' || echo "")
|
|
151
|
+
if [[ -n "$BRIDGE_PID" && "$BRIDGE_PID" != "0" ]]; then break; fi
|
|
152
|
+
fi
|
|
153
|
+
done
|
|
154
|
+
|
|
155
|
+
if [[ -n "$BRIDGE_PID" ]] && kill -0 "$BRIDGE_PID" 2>/dev/null; then
|
|
156
|
+
rm -rf "$AB/app.broken"
|
|
157
|
+
log "✓ Auto-rollback successful — running $ROLLED_VER (PID=$BRIDGE_PID)"
|
|
158
|
+
notify "⚠️ Auto-rolled back to $ROLLED_VER after crash loop (3 restarts in ${CIRCUIT_WINDOW}s)"
|
|
159
|
+
return 0
|
|
160
|
+
else
|
|
161
|
+
log "❌ Auto-rollback also failed"
|
|
162
|
+
notify "❌ Auto-rollback to $ROLLED_VER also failed. Manual intervention required."
|
|
163
|
+
rm -f "$WD_LOCK"
|
|
164
|
+
exit 1
|
|
165
|
+
fi
|
|
166
|
+
else
|
|
167
|
+
log "🚨 CIRCUIT BREAKER — ${CIRCUIT_MAX} restarts in ${CIRCUIT_WINDOW}s, no prior version available"
|
|
168
|
+
notify "🚨 Watchdog circuit breaker tripped — no rollback available, manual intervention needed"
|
|
169
|
+
rm -f "$WD_LOCK"
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
130
172
|
fi
|
|
131
173
|
|
|
132
174
|
# Health check before every spawn
|
|
@@ -158,10 +200,9 @@ spawn_bridge() {
|
|
|
158
200
|
|
|
159
201
|
# Source .env so platform ENABLED vars reach the node process
|
|
160
202
|
if [ -f "$AB/config/.env" ]; then set -a; source "$AB/config/.env"; set +a; fi
|
|
161
|
-
|
|
162
|
-
log "Starting bridge: node current/main.js $*"
|
|
203
|
+
log "Starting bridge: node app/bundle/abtars.js $*"
|
|
163
204
|
cd "$AB"
|
|
164
|
-
NODE_PATH="
|
|
205
|
+
NODE_PATH="${ABMIND_HOME:-$HOME/.abmind}/lib/node_modules:${NODE_PATH:-}" node app/bundle/abtars.js "$@" >> "$AB/logs/launchd.log" 2>&1 &
|
|
165
206
|
SPAWNED_AT=$(date +%s)
|
|
166
207
|
|
|
167
208
|
# Wait for bridge.lock with PID
|
|
@@ -303,6 +344,10 @@ while true; do
|
|
|
303
344
|
|
|
304
345
|
age_sec=$(( (now - lock_hb) / 1000 ))
|
|
305
346
|
if [[ "$KILL_ON_STALE" == "true" ]] && (( age_sec > STALE_SEC )); then
|
|
347
|
+
# Skip if update in progress — bridge will be restarted by update command
|
|
348
|
+
if [[ -f "$AB/state/update.sentinel" ]] && grep -q '"pending"' "$AB/state/update.sentinel" 2>/dev/null; then
|
|
349
|
+
continue
|
|
350
|
+
fi
|
|
306
351
|
kill_bridge "heartbeat stale (${age_sec}s)"
|
|
307
352
|
spawn_bridge "${BRIDGE_ARGS[@]}"
|
|
308
353
|
fi
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/capabilities/browser/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { logAndSwallow } from \"../../components/log-and-swallow.js\";\nimport { getEnv } from \"../../components/env-schema.js\";\n/**\n * Browser capability \u2014 browse-spawn IPC + browse-checker heartbeat.\n * Level 1 (lightpanda fetch) is handled by the agent via skill \u2014 no bridge code needed.\n * Level 2 (Browsie) uses runtime.spawn() via IPC socket.\n */\n\nimport { BrowserManager } from \"./browser-manager.js\";\nimport { BrowserTool } from \"./browser-tool.js\";\nimport { BrowserIpcServer } from \"./browser-ipc-server.js\";\nimport { DomainAllowlist } from \"./domain-allowlist.js\";\nimport { checkBrowseTasks, deliverBrowseResult } from \"./browse-delivery.js\";\nimport { readPendingBrowse, writePendingBrowse } from \"./abtars-browse.js\";\nimport type { PendingBrowseEntry } from \"./abtars-browse.js\";\nimport { logInfo, logWarn } from \"../../components/logger.js\";\nimport { abtarsHome } from \"../../paths.js\";\nimport type { CapabilityApi } from \"../capability.js\";\nimport * as net from \"node:net\";\nimport { join } from \"node:path\";\nimport { unlinkSync } from \"node:fs\";\n\nexport function register(api: CapabilityApi): void {\n const browserManager = new BrowserManager();\n const allowlist = DomainAllowlist.fromEnv();\n const browserTool = new BrowserTool(browserManager, allowlist);\n let browserIpc: BrowserIpcServer | null = null;\n\n const ensureBrowserIpc = async (): Promise<void> => {\n if (browserIpc || getEnv().browserDocker) return;\n browserIpc = new BrowserIpcServer(browserTool);\n await browserIpc.start();\n logInfo(\"browser\", `\uD83D\uDD0C Browser IPC listening on ${browserIpc.socketPath}`);\n };\n\n // Browse-spawn IPC \u2014 CLI sends task, bridge spawns via runtime\n const spawnSocketPath = join(abtarsHome(), \"browse-spawn.sock\");\n try { unlinkSync(spawnSocketPath); } catch (err) { logAndSwallow(\"index\", \"op\", err); }\n\n const spawnServer = net.createServer((conn) => {\n let buf = \"\";\n conn.on(\"data\", (chunk) => {\n buf += chunk.toString();\n const nl = buf.indexOf(\"\\n\");\n if (nl === -1) return;\n const line = buf.slice(0, nl);\n buf = buf.slice(nl + 1);\n\n try {\n const { taskId, task, prompt, chatId, threadId, timeoutMs } = JSON.parse(line);\n\n const entry: PendingBrowseEntry = {\n taskId, task, chatId, threadId,\n pid: process.pid, // bridge pid \u2014 runtime manages the actual transport\n startedAt: Date.now(), timeoutMs,\n logFile: \"\", // no log file \u2014 result comes from callback\n };\n const entries = readPendingBrowse();\n entries.push(entry);\n writePendingBrowse(entries);\n\n // Fire-and-forget via runtime\n api.runtime.spawn(\"browsie\", prompt, {\n timeoutMs,\n onComplete: (_id: string, result: string) => {\n deliverBrowseResult(entry, result);\n const remaining = readPendingBrowse().filter(e => e.taskId !== taskId);\n writePendingBrowse(remaining);\n },\n onError: (_id: string, err: Error) => {\n logWarn(\"browser\", `Browsie spawn failed for ${taskId}: ${err.message}`);\n deliverBrowseResult(entry, `Browse task failed: ${err.message}`);\n const remaining = readPendingBrowse().filter(e => e.taskId !== taskId);\n writePendingBrowse(remaining);\n },\n }).then(({ taskId: spawnId }) => {\n conn.write(JSON.stringify({ ok: true, taskId, spawnId, status: \"spawned\" }) + \"\\n\");\n }).catch((err) => {\n conn.write(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }) + \"\\n\");\n });\n } catch (err) {\n conn.write(JSON.stringify({ ok: false, error: err instanceof Error ? err.message : String(err) }) + \"\\n\");\n }\n });\n conn.on(\"error\", () => {});\n });\n\n spawnServer.listen(spawnSocketPath, () => {\n logInfo(\"browser\", `\uD83D\uDD0C Browse spawn IPC listening on ${spawnSocketPath}`);\n });\n\n api.registerHeartbeatTask({\n name: \"browse-checker\",\n execute: async () => { await ensureBrowserIpc(); checkBrowseTasks(); },\n });\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli/deploy-lib/paths.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 * Runtime directory resolution for deploy-lib consumers.\n *\n * Rules:\n * - abtars runtime root: $ABTARS_HOME ?? ~/.abtars\n * - abmind runtime root: $ABMIND_HOME ?? ~/.abmind\n * - user bin dir: ~/.local/bin (always, XDG convention)\n *\n * All callers use these resolvers \u2014 never hardcode paths. Required by\n * plan #158 v7 (Ag2 round-2 nit): cross-repo manifest reads must respect\n * env-var overrides, not assume default locations.\n */\n\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nexport type PackageName = 'abtars' | 'abmind';\n\nexport function resolveAbtarsHome(): string {\n return process.env['ABTARS_HOME'] ?? join(homedir(), '.abtars');\n}\n\nexport function resolveAbmindHome(): string {\n return process.env['ABMIND_HOME'] ?? join(homedir(), '.abmind');\n}\n\nexport function resolvePackageHome(pkg: PackageName): string {\n return pkg === 'abtars' ? resolveAbtarsHome() : resolveAbmindHome();\n}\n\nexport function resolveUserBinDir(): string {\n return join(homedir(), '.local', 'bin');\n}\n\nexport interface PackagePaths {\n readonly home: string;\n readonly config: string;\n readonly releases: string;\n readonly current: string;\n readonly nodeModules: string;\n readonly bin: string;\n readonly manifest: string;\n readonly lock: string;\n}\n\nexport function packagePaths(pkg: PackageName): PackagePaths {\n const home = resolvePackageHome(pkg);\n return {\n home,\n config: join(home, 'config'),\n releases: join(home, 'releases'),\n current: join(home, 'current'),\n nodeModules: join(home, 'node_modules'),\n bin: join(home, 'bin'),\n manifest: join(home, 'manifest.json'),\n lock: join(home, '.update.lock'),\n };\n}\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 (matches releases/<version>/ dirname). */\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 node_modules 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 (local | npm | github). */\n readonly source: 'local' | 'npm' | 'github';\n /** Applied migrations (ordered). */\n readonly migrationsApplied: readonly string[];\n /** Prior releases still retained (newest first). Empty on fresh install. */\n readonly priorReleases: readonly PriorRelease[];\n /** Pre-158 backup location, if this install was migrated from the flat layout. */\n readonly preMigrationBackup: string | null;\n /** Install mode: simple (manual), supervised (launchd/systemd user-scope), or supervised-daemon (system-scope). */\n readonly installMode?: 'simple' | 'supervised' | 'supervised-daemon';\n}\n\nexport interface PriorRelease {\n readonly version: string;\n readonly commit: string | null;\n readonly activatedAt: string;\n readonly packageLockHash: 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: 'local',\n migrationsApplied: [],\n priorReleases: [],\n preMigrationBackup: 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 = 60 * 60 * 1000; // 1 hour\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 * Release management: stage / activate (flip symlink) / prune.\n *\n * Invariants (per plan \u00A7\"Directory layout\"):\n * - releases/<version>/dist/ holds only compiled code, no node_modules\n * - node_modules/ lives at the package home root, shared across releases\n * - current is a symlink to releases/<version>/\n * - Retention = 3 (plan \u00A7\"Key invariants\"); oldest pruned on activate\n *\n * Activation is atomic via rename(2): write current.new \u2192 rename to current.\n * This replaces the existing symlink in one syscall; readers never see a\n * broken state.\n */\n\nimport { createHash } from 'node:crypto';\nimport { readFile, readdir, rename, rm, stat, symlink, unlink } from 'node:fs/promises';\nimport { basename, dirname, join } from 'node:path';\n\nconst RETENTION = 3;\n\nexport interface StagedRelease {\n readonly version: string;\n readonly stagedPath: string;\n readonly commit: string | null;\n readonly packageLockHash: string | null;\n readonly source: 'local' | 'npm' | 'github';\n}\n\n/**\n * List release versions in a releases/ dir, newest-activation-first as\n * reported by the caller (this function sorts lexicographically; callers\n * with a preferred order should rely on manifest priorReleases).\n */\nexport async function listReleases(releasesDir: string): Promise<string[]> {\n try {\n const entries = await readdir(releasesDir, { withFileTypes: true });\n return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n}\n\n/**\n * Resolve the currently active release version from the `current` symlink.\n * Returns null if the symlink is missing or dangling.\n */\nexport async function readCurrent(currentLink: string): Promise<string | null> {\n try {\n const s = await stat(currentLink);\n if (!s.isDirectory()) return null;\n const { readlink } = await import('node:fs/promises');\n const target = await readlink(currentLink);\n // Target is like \"releases/vX.Y.Z\" or absolute path ending in vX.Y.Z.\n return basename(target);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n}\n\n/**\n * Atomically flip the `current` symlink to point at releases/<version>/.\n * Link target is relative (so moves of the package home don't break it).\n */\nexport async function activate(currentLink: string, version: string): Promise<void> {\n const tmp = `${currentLink}.new`;\n // Relative symlink target: \"releases/<version>\"\n const target = join('releases', version);\n // Clear any leftover tmp from a crashed prior run.\n try {\n await unlink(tmp);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n await symlink(target, tmp);\n await rename(tmp, currentLink);\n}\n\n/**\n * Prune old releases, keeping the `keep` newest (by activation order provided\n * by caller, most-recent-first). Never removes the currently-active release\n * even if it falls outside the window.\n */\nexport async function pruneReleases(\n releasesDir: string,\n activatedOrder: readonly string[],\n currentVersion: string,\n keep: number = RETENTION,\n): Promise<string[]> {\n const retained = new Set<string>([currentVersion]);\n for (const v of activatedOrder.slice(0, keep)) retained.add(v);\n const all = await listReleases(releasesDir);\n const pruned: string[] = [];\n for (const version of all) {\n if (retained.has(version)) continue;\n await rm(join(releasesDir, version), { recursive: true, force: true });\n pruned.push(version);\n }\n return pruned;\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 * Validate that `releases/<version>/` exists and has a dist/ subdir. Used by\n * rollback to refuse flipping to a pruned or partial release.\n */\nexport async function releaseExists(releasesDir: string, version: string): Promise<boolean> {\n try {\n const s = await stat(join(releasesDir, version, 'dist'));\n return s.isDirectory();\n } catch {\n return false;\n }\n}\n\nexport { RETENTION };\n// dirname import preserves tree-shake correctness with downstream tooling\nexport const _dirname = dirname;\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": ";;;;AAaA,SAAS,eAAe;AACxB,SAAS,YAAY;AAId,SAAS,oBAA4B;AAC1C,SAAO,QAAQ,IAAI,aAAa,KAAK,KAAK,QAAQ,GAAG,SAAS;AAChE;AAEO,SAAS,oBAA4B;AAC1C,SAAO,QAAQ,IAAI,aAAa,KAAK,KAAK,QAAQ,GAAG,SAAS;AAChE;AAEO,SAAS,mBAAmB,KAA0B;AAC3D,SAAO,QAAQ,WAAW,kBAAkB,IAAI,kBAAkB;AACpE;AAEO,SAAS,oBAA4B;AAC1C,SAAO,KAAK,QAAQ,GAAG,UAAU,KAAK;AACxC;AAaO,SAAS,aAAa,KAAgC;AAC3D,QAAM,OAAO,mBAAmB,GAAG;AACnC,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,KAAK,MAAM,QAAQ;AAAA,IAC3B,UAAU,KAAK,MAAM,UAAU;AAAA,IAC/B,SAAS,KAAK,MAAM,SAAS;AAAA,IAC7B,aAAa,KAAK,MAAM,cAAc;AAAA,IACtC,KAAK,KAAK,MAAM,KAAK;AAAA,IACrB,UAAU,KAAK,MAAM,eAAe;AAAA,IACpC,MAAM,KAAK,MAAM,cAAc;AAAA,EACjC;AACF;;;ACjDA,SAAS,UAAU,iBAAiB;AAmCpC,eAAsB,aAAa,MAAwC;AACzE,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AACxC,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AACF;AAEA,eAAsB,cAAc,MAAc,UAAmC;AACnF,QAAM,UAAU,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,MAAM,OAAO;AACzE;AAEO,SAAS,cAAc,KAA0B,MAAwB;AAC9E,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,IACA,QAAQ;AAAA,IACR,mBAAmB,CAAC;AAAA,IACpB,eAAe,CAAC;AAAA,IAChB,oBAAoB;AAAA,EACtB;AACF;;;AC1DA,SAAS,YAAAA,WAAU,QAAQ,aAAAC,kBAAiB;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AAEzB,IAAM,WAAW,KAAK,KAAK;AASpB,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACkB,SACA,SAChB;AACA,UAAM,WAAW,UAAU,qDAAgD;AAC3E;AAAA,MACE,oBAAoB,QAAQ,GAAG,UAAU,QAAQ,SAAS,UAC/C,QAAQ,GAAG,IAAI,QAAQ;AAAA,IACpC;AAPgB;AACA;AAOhB,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,WAAW,KAAsB;AACxC,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,WAAQ,IAA8B,SAAS;AAAA,EACjD;AACF;AAEA,eAAe,SAAS,MAA2C;AACjE,MAAI;AACF,WAAO,KAAK,MAAM,MAAMD,UAAS,MAAM,OAAO,CAAC;AAAA,EACjD,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AACF;AAOA,eAAsB,YAAY,MAAc,KAA2C;AACzF,QAAM,WAAW,MAAM,SAAS,IAAI;AACpC,MAAI,UAAU;AACZ,UAAM,QAAQ,WAAW,SAAS,GAAG;AACrC,UAAM,UAAU,KAAK,MAAM,SAAS,SAAS;AAC7C,UAAM,MAAM,KAAK,IAAI,KAAK,OAAO,SAAS,OAAO,IAAI,UAAU;AAC/D,UAAM,QAAQ,CAAC,SAAS,MAAM;AAC9B,QAAI,CAAC,OAAO;AACV,YAAM,IAAI,cAAc,UAAU,KAAK;AAAA,IACzC;AAAA,EAEF;AAEA,QAAM,UAAuB;AAAA,IAC3B,KAAK,QAAQ;AAAA,IACb,MAAM,SAAS;AAAA,IACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,EACF;AACA,QAAMC,WAAU,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI,MAAM,OAAO;AAEtE,MAAI,WAAW;AACf,QAAM,UAAU,YAA2B;AACzC,QAAI,SAAU;AACd,eAAW;AACX,QAAI;AACF,YAAM,OAAO,IAAI;AAAA,IACnB,SAAS,KAAK;AACZ,UAAK,IAA8B,SAAS,SAAU,OAAM;AAAA,IAC9D;AAAA,EACF;AAGA,QAAM,cAAc,MAAY;AAC9B,QAAI;AACF,iBAAW,IAAI;AAAA,IACjB,QAAQ;AAAA,IAER;AAAA,EACF;AACA,UAAQ,KAAK,QAAQ,WAAW;AAEhC,SAAO;AACT;AAEA,eAAsB,YAAY,MAGhC;AACA,QAAM,UAAU,MAAM,SAAS,IAAI;AACnC,MAAI,CAAC,QAAS,QAAO,EAAE,MAAM,MAAM;AACnC,QAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,QAAM,UAAU,KAAK,MAAM,QAAQ,SAAS;AAC5C,QAAM,MAAM,KAAK,IAAI,KAAK,OAAO,SAAS,OAAO,IAAI,UAAU;AAC/D,QAAM,QAAQ,CAAC,SAAS,MAAM;AAC9B,SAAO,EAAE,MAAM,MAAM,SAAS,MAAM;AACtC;;;ACzGA,SAAS,kBAAkB;AAC3B,SAAS,YAAAC,WAAU,SAAS,QAAQ,IAAI,MAAM,SAAS,UAAAC,eAAc;AACrE,SAAS,UAAU,SAAS,QAAAC,aAAY;AAExC,IAAM,YAAY;AAelB,eAAsB,aAAa,aAAwC;AACzE,MAAI;AACF,UAAM,UAAU,MAAM,QAAQ,aAAa,EAAE,eAAe,KAAK,CAAC;AAClE,WAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK;AAAA,EACxE,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO,CAAC;AAC9D,UAAM;AAAA,EACR;AACF;AAMA,eAAsB,YAAY,aAA6C;AAC7E,MAAI;AACF,UAAM,IAAI,MAAM,KAAK,WAAW;AAChC,QAAI,CAAC,EAAE,YAAY,EAAG,QAAO;AAC7B,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,kBAAkB;AACpD,UAAM,SAAS,MAAM,SAAS,WAAW;AAEzC,WAAO,SAAS,MAAM;AAAA,EACxB,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AACF;AAMA,eAAsB,SAAS,aAAqB,SAAgC;AAClF,QAAM,MAAM,GAAG,WAAW;AAE1B,QAAM,SAASA,MAAK,YAAY,OAAO;AAEvC,MAAI;AACF,UAAMD,QAAO,GAAG;AAAA,EAClB,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,OAAM;AAAA,EAC9D;AACA,QAAM,QAAQ,QAAQ,GAAG;AACzB,QAAM,OAAO,KAAK,WAAW;AAC/B;AAOA,eAAsB,cACpB,aACA,gBACA,gBACA,OAAe,WACI;AACnB,QAAM,WAAW,oBAAI,IAAY,CAAC,cAAc,CAAC;AACjD,aAAW,KAAK,eAAe,MAAM,GAAG,IAAI,EAAG,UAAS,IAAI,CAAC;AAC7D,QAAM,MAAM,MAAM,aAAa,WAAW;AAC1C,QAAM,SAAmB,CAAC;AAC1B,aAAW,WAAW,KAAK;AACzB,QAAI,SAAS,IAAI,OAAO,EAAG;AAC3B,UAAM,GAAGC,MAAK,aAAa,OAAO,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACrE,WAAO,KAAK,OAAO;AAAA,EACrB;AACA,SAAO;AACT;AAEA,eAAsB,SAAS,MAAsC;AACnE,MAAI;AACF,UAAM,MAAM,MAAMF,UAAS,IAAI;AAC/B,WAAO,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK;AAAA,EACtD,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AACF;AAMA,eAAsB,cAAc,aAAqB,SAAmC;AAC1F,MAAI;AACF,UAAM,IAAI,MAAM,KAAKE,MAAK,aAAa,SAAS,MAAM,CAAC;AACvD,WAAO,EAAE,YAAY;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACnHA,SAAS,MAAAC,WAAU;AACnB,SAAS,WAAAC,gBAAe;AACxB,SAAS,eAAe;AAejB,SAAS,sBAAsB,MAAuB;AAC3D,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,YAAY,OAAO,YAAY,OAAO,YAAY,KAAM,QAAO;AACnE,QAAM,MAAM,QAAQ,OAAO;AAC3B,MAAI,QAAQ,OAAO,QAAQ,GAAI,QAAO;AACtC,QAAM,OAAOA,SAAQ;AACrB,MAAI,QAAQ,KAAM,QAAO;AAEzB,QAAM,cAAc,KAAK,SAAS,GAAG,IAAI,OAAO,OAAO;AACvD,MAAI,CAAC,IAAI,WAAW,WAAW,EAAG,QAAO;AACzC,SAAO;AACT;AAWO,SAAS,YAAY,MAA0B;AACpD,MAAI,sBAAsB,IAAI,GAAG;AAC/B,WAAO,EAAE,MAAM,YAAY,OAAO,QAAQ,yBAAyB;AAAA,EACrE;AACA,SAAO,EAAE,MAAM,YAAY,MAAM,QAAQ,2BAA2B;AACtE;AAMA,eAAsB,WAAW,MAAc,OAA6B,CAAC,GAAqB;AAChG,MAAI,sBAAsB,IAAI,GAAG;AAC/B,UAAM,IAAI,MAAM,oCAAoC,IAAI,EAAE;AAAA,EAC5D;AACA,MAAI,KAAK,OAAQ,QAAO;AACxB,MAAI;AACF,UAAMD,IAAG,MAAM,EAAE,WAAW,KAAK,CAAC;AAClC,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAK,IAA8B,SAAS,SAAU,QAAO;AAC7D,UAAM;AAAA,EACR;AACF;;;AC7DA,SAAS,IAAI,aAAa;AAQ1B,eAAe,WAAW,KAA+B;AACvD,MAAI;AACF,UAAM,IAAI,MAAM,MAAM,GAAG;AACzB,QAAI,EAAE,SAAS,KAAK,EAAE,OAAO,KAAK,EAAE,cAAc,KAAK,EAAE,kBAAkB,GAAG;AAC5E,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,aAAa,KAAa,KAAa,OAAwB,CAAC,GAAkB;AACtG,QAAM,GAAG,KAAK,KAAK;AAAA,IACjB,WAAW;AAAA,IACX,oBAAoB,KAAK,uBAAuB;AAAA,IAChD,OAAO,KAAK,UAAU;AAAA,IACtB,QAAQ;AAAA,EACV,CAAC;AACH;",
|
|
6
|
-
"names": ["readFile", "writeFile", "readFile", "unlink", "join", "rm", "homedir"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/components/update-check.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * update-check.ts \u2014 Check npm registry for newer abtars versions (#440, #588).\n * Single module: configurable TTL, notify cooldown, logger integration.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { abtarsHome } from \"../paths.js\";\n\nconst DEFAULT_TTL_MS = 6 * 60 * 60_000; // 6h\nconst NOTIFY_COOLDOWN_MS = 24 * 60 * 60_000; // 1 per day\n\ninterface CacheData {\n ts: number;\n latest: string;\n lastNotifiedAt?: number;\n}\n\nfunction cachePath(): string {\n const dir = join(abtarsHome(), \"state\");\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n return join(dir, \"update-check.json\");\n}\n\nfunction readCache(ttlMs: number): CacheData | null {\n try {\n const data = JSON.parse(readFileSync(cachePath(), \"utf-8\")) as CacheData;\n if (Date.now() - data.ts < ttlMs) return data;\n } catch { /* missing or corrupt */ }\n return null;\n}\n\nfunction writeCache(data: CacheData): void {\n try { writeFileSync(cachePath(), JSON.stringify(data), \"utf-8\"); } catch { /* non-critical */ }\n}\n\nfunction fetchLatest(pkg: string): string | null {\n try {\n return execFileSync(\"npm\", [\"view\", pkg, \"version\"], { encoding: \"utf-8\", timeout: 10_000 }).trim();\n } catch {\n return null;\n }\n}\n\n/** True if a is newer than b (semver major.minor.patch). */\nfunction isNewer(a: string, b: string): boolean {\n const pa = a.split(\".\").map(Number);\n const pb = b.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] ?? 0) > (pb[i] ?? 0)) return true;\n if ((pa[i] ?? 0) < (pb[i] ?? 0)) return false;\n }\n return false;\n}\n\nexport interface UpdateCheckResult {\n current: string;\n latest: string;\n updateAvailable: boolean;\n shouldNotify: boolean;\n}\n\n/**\n * Check if a newer version is available on npm.\n * Returns null if check is skipped (cached fresh / offline / npm not found).\n */\nexport function checkForUpdate(pkg: string, currentVersion: string, opts?: { ttlMs?: number }): UpdateCheckResult | null {\n const ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;\n const cache = readCache(ttlMs);\n const latest = cache?.latest ?? fetchLatest(pkg);\n if (!latest) return null;\n\n const now = Date.now();\n const updateAvailable = isNewer(latest, currentVersion);\n const shouldNotify = updateAvailable && (!cache?.lastNotifiedAt || now - cache.lastNotifiedAt > NOTIFY_COOLDOWN_MS);\n\n const newCache: CacheData = { ts: now, latest, lastNotifiedAt: shouldNotify ? now : cache?.lastNotifiedAt };\n if (!cache) writeCache(newCache);\n else if (shouldNotify) writeCache(newCache);\n\n return { current: currentVersion, latest, updateAvailable, shouldNotify };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAKA,SAAS,oBAAoB;AAC7B,SAAS,cAAc,eAAe,WAAW,kBAAkB;AACnE,SAAS,YAAY;AAYrB,SAAS,YAAoB;AAC3B,QAAM,MAAM,KAAK,WAAW,GAAG,OAAO;AACtC,MAAI,CAAC,WAAW,GAAG,EAAG,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACxD,SAAO,KAAK,KAAK,mBAAmB;AACtC;AAEA,SAAS,UAAU,OAAiC;AAClD,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,aAAa,UAAU,GAAG,OAAO,CAAC;AAC1D,QAAI,KAAK,IAAI,IAAI,KAAK,KAAK,MAAO,QAAO;AAAA,EAC3C,QAAQ;AAAA,EAA2B;AACnC,SAAO;AACT;AAEA,SAAS,WAAW,MAAuB;AACzC,MAAI;AAAE,kBAAc,UAAU,GAAG,KAAK,UAAU,IAAI,GAAG,OAAO;AAAA,EAAG,QAAQ;AAAA,EAAqB;AAChG;AAEA,SAAS,YAAY,KAA4B;AAC/C,MAAI;AACF,WAAO,aAAa,OAAO,CAAC,QAAQ,KAAK,SAAS,GAAG,EAAE,UAAU,SAAS,SAAS,IAAO,CAAC,EAAE,KAAK;AAAA,EACpG,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,QAAQ,GAAW,GAAoB;AAC9C,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,SAAK,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,KAAK,GAAI,QAAO;AACxC,SAAK,GAAG,CAAC,KAAK,MAAM,GAAG,CAAC,KAAK,GAAI,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAaO,SAAS,eAAe,KAAa,gBAAwB,MAAqD;AACvH,QAAM,QAAQ,MAAM,SAAS;AAC7B,QAAM,QAAQ,UAAU,KAAK;AAC7B,QAAM,SAAS,OAAO,UAAU,YAAY,GAAG;AAC/C,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,kBAAkB,QAAQ,QAAQ,cAAc;AACtD,QAAM,eAAe,oBAAoB,CAAC,OAAO,kBAAkB,MAAM,MAAM,iBAAiB;AAEhG,QAAM,WAAsB,EAAE,IAAI,KAAK,QAAQ,gBAAgB,eAAe,MAAM,OAAO,eAAe;AAC1G,MAAI,CAAC,MAAO,YAAW,QAAQ;AAAA,WACtB,aAAc,YAAW,QAAQ;AAE1C,SAAO,EAAE,SAAS,gBAAgB,QAAQ,iBAAiB,aAAa;AAC1E;AAlFA,IAUM,gBACA;AAXN;AAAA;AAQA;AAEA,IAAM,iBAAiB,IAAI,KAAK;AAChC,IAAM,qBAAqB,KAAK,KAAK;AAAA;AAAA;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/capabilities/sleep/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { logAndSwallow } from \"../../components/log-and-swallow.js\";\nimport { getEnv } from \"../../components/env-schema.js\";\nimport type { CapabilityApi } from \"../capability.js\";\n/**\n * Sleep capability \u2014 spawn nightly sleep cycle via tick system.\n * One path: BED_TIME + quiet ticks \u2192 Dreamy \u2192 quiet ticks \u2192 hardware sleep.\n * Parses PROGRESS:<pct>:<label> from stdout for visibility.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { writeSleepStatus, readAndClearForceSleep } from \"../../components/transport/bridge-lock-transport.js\";\nimport { join } from \"node:path\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport type { Level } from \"abmind\";\nimport { abmind } from \"../../utils/abmind-lazy.js\";\nimport type { SleepRuntime } from \"abmind\";\nimport { logInfo, logWarn, logDebug } from \"../../components/logger.js\";\nimport { readEnv, readEnvWithDefault } from \"../../components/env.js\";\n\nconst TAG = \"sleep\";\n\nexport interface SleepOpts {\n sleepHour: number;\n sleepAuditDir: string;\n memoryEnabled: boolean;\n memoryDir?: string;\n /** LLM runtime adapter \u2014 bridge wraps its SubagentRuntime.complete(\"dreamy\", ...). */\n runtime: SleepRuntime;\n onComplete: () => void;\n getLastMsgTs?: () => number;\n sendSystemMessage?: (prompt: string) => Promise<void>;\n killWakeInhibit?: () => void;\n}\n\nexport interface SleepProgress {\n percent: number;\n step: string;\n}\n\nexport interface SleepHandle {\n /** True while a sleep cycle is running in-process. */\n readonly isActive: boolean;\n readonly progress: SleepProgress | null;\n readonly awaitingHwSleep: boolean;\n spawn(): void;\n /** Called by tick system to check if hardware sleep should fire. */\n checkHwSleep(): void;\n}\n\nconst MAX_RETRIES = 3;\nconst RETRY_MS = 5 * 60 * 1000;\n\nexport function createSleepHandle(opts: SleepOpts): SleepHandle {\n let running = false;\n let attempts = 0;\n let progress: SleepProgress | null = null;\n let _awaitingHwSleep = false;\n // Post-Dreamy hw-sleep quiet-tick tracking (internal to this closure \u2014 decoupled from\n // daily-cycle.quietTickCount which freezes once hasSleepAuditToday returns true).\n // Both reset when _awaitingHwSleep flips to true (see the onComplete handler below).\n let postSleepQuietTicks = 0;\n let lastMsgTsSeenByHwCheck = 0;\n\n function buildDreamReport(): string {\n let dreamReport = \"Dreamy finished nightly maintenance.\";\n try {\n const sleepDir = join(opts.memoryDir ?? \"\", \"sleep\");\n const dateStr = new Date().toISOString().slice(0, 10).replace(/-/g, \"\");\n const lockPath = join(sleepDir, `sleep_${dateStr}.lock`);\n if (existsSync(lockPath)) {\n const lockData = JSON.parse(readFileSync(lockPath, \"utf-8\")) as { steps: Record<string, { status: string }>; llmCalls?: number };\n const ok = Object.entries(lockData.steps).filter(([, s]) => s.status === \"ok\").map(([k]) => k);\n const skipped = Object.entries(lockData.steps).filter(([, s]) => s.status === \"skipped\").map(([k]) => k);\n const failed = Object.entries(lockData.steps).filter(([, s]) => s.status === \"failed\" || s.status === \"timeout\").map(([k]) => k);\n dreamReport = `Dreamy finished nightly maintenance (${lockData.llmCalls ?? \"?\"} LLM calls). Completed: ${ok.join(\", \") || \"none\"}.`;\n if (skipped.length > 0) dreamReport += ` Skipped: ${skipped.join(\", \")}.`;\n if (failed.length > 0) dreamReport += ` \u26A0\uFE0F FAILED: ${failed.join(\", \")}. Please review.`;\n }\n } catch (err) { logAndSwallow(\"index\", \"op\", err); }\n return dreamReport;\n }\n\n function spawnSleep(): void {\n const forceSleep = readAndClearForceSleep();\n const forced = forceSleep !== null;\n if (forced) {\n logInfo(\"sleep\", `\u26A1 forceSleep=${forceSleep} \u2014 bypassing time-window + audit-today guards`);\n }\n\n if (!forced) {\n const hour = new Date().getHours();\n const WAKE_HOUR = parseInt(readEnvWithDefault(\"WAKE_TIME\", \"7\", \"wake hour\").split(\":\")[0] ?? \"7\", 10);\n if (opts.sleepHour <= WAKE_HOUR) {\n if (hour < opts.sleepHour || hour >= WAKE_HOUR) {\n logDebug(\"sleep\", `\uD83D\uDE34 Outside sleep window (${opts.sleepHour}:00-${WAKE_HOUR}:00) \u2014 skip`);\n return;\n }\n } else {\n if (hour < opts.sleepHour && hour >= WAKE_HOUR) {\n logDebug(\"sleep\", `\uD83D\uDE34 Outside sleep window (${opts.sleepHour}:00-${WAKE_HOUR}:00) \u2014 skip`);\n return;\n }\n }\n if (abmind()?.hasSleepAuditToday(opts.sleepAuditDir)) {\n logDebug(\"sleep\", \"\uD83D\uDE34 Sleep already done today \u2014 skip\");\n return;\n }\n }\n if (running) return;\n attempts++;\n progress = null;\n running = true;\n writeSleepStatus(\"sleeping\");\n logInfo(\"sleep\", `\uD83D\uDE34 Sleep started in-process (attempt ${attempts}, model=dreamy)`);\n\n const level = (() => {\n if (forced && forceSleep?.includes(\"fresh\")) return \"ultimate\" as Level;\n const raw = getEnv().sleepQuality;\n if (!raw) return abmind()!.DEFAULT_LEVEL;\n try { return abmind()!.parseLevel(raw); }\n catch (err) { logWarn(\"sleep\", `Invalid SLEEP_QUALITY='${raw}', using ${abmind()!.DEFAULT_LEVEL}: ${err instanceof Error ? err.message : String(err)}`); return abmind()!.DEFAULT_LEVEL; }\n })();\n\n abmind()!.runSleepCycle({ runtime: opts.runtime, level })\n .then((result) => {\n running = false;\n progress = null;\n logInfo(\"sleep\", `\uD83D\uDE34 Sleep finished (ok=${result.ok}, failCount=${result.failCount}, attempt ${attempts})`);\n writeSleepStatus(\"awake\");\n if (!result.ok) {\n if (attempts < MAX_RETRIES) {\n logWarn(\"sleep\", `\uD83D\uDE34 Sleep had ${result.failCount} failures (attempt ${attempts}/${MAX_RETRIES}) \u2014 retry in 5min`);\n setTimeout(spawnSleep, RETRY_MS);\n } else {\n logWarn(\"sleep\", `\uD83D\uDE34 Sleep failures persist \u2014 exhausted ${MAX_RETRIES} attempts`);\n }\n return;\n }\n\n if (opts.memoryEnabled) opts.onComplete();\n\n // Force-sleep runs are explicit test/verify triggers \u2014 skip hw-sleep even if env enabled.\n const hwEnabled = !forced && readEnv(\"HARDWARE_SLEEP_AFTER_DREAMY\", \"hardware sleep after Dreamy disabled\") === \"true\";\n const quietTicks = Math.ceil(getEnv().bedQuietMin * 60 / parseInt(readEnvWithDefault(\"HEARTBEAT_INTERVAL_SEC\", \"60\", \"hb\"), 10));\n const hbInterval = parseInt(readEnvWithDefault(\"HEARTBEAT_INTERVAL_SEC\", \"60\", \"heartbeat tick interval\"), 10);\n const hwSleepMin = Math.round(quietTicks * hbInterval / 60);\n\n const dreamReport = buildDreamReport();\n const sleepNote = hwEnabled ? ` Hardware sleep in ~${hwSleepMin} minutes if no activity.` : \"\";\n\n if (opts.sendSystemMessage) {\n opts.sendSystemMessage(`${dreamReport}${sleepNote}`).catch(err => logAndSwallow(TAG, \"sendSystemMessage dream report\", err));\n }\n\n if (hwEnabled) {\n _awaitingHwSleep = true;\n // Reset hw-check counters \u2014 prevents stale state from a prior cycle (crash, force-sleep\n // re-run) from poisoning this one, and avoids burning the first tick on a spurious\n // reset when the very first checkHwSleep() sees currentMsgTs > 0.\n postSleepQuietTicks = 0;\n lastMsgTsSeenByHwCheck = opts.getLastMsgTs?.() ?? 0;\n logInfo(\"sleep\", `\uD83D\uDCA4 Awaiting hardware sleep \u2014 ${quietTicks} quiet ticks (${hwSleepMin} min) required`);\n }\n })\n .catch((err) => {\n running = false;\n progress = null;\n writeSleepStatus(\"awake\");\n const msg = err instanceof Error ? err.message : String(err);\n if (attempts < MAX_RETRIES) {\n logWarn(\"sleep\", `\uD83D\uDE34 Sleep threw (attempt ${attempts}/${MAX_RETRIES}): ${msg} \u2014 retry in 5min`);\n setTimeout(spawnSleep, RETRY_MS);\n } else {\n logWarn(\"sleep\", `\uD83D\uDE34 Sleep threw \u2014 exhausted ${MAX_RETRIES} attempts: ${msg}`);\n }\n });\n }\n\n function checkHwSleep(): void {\n if (!_awaitingHwSleep) return;\n\n // Sleep-window cutoff \u2014 give up if we've crossed out of the window. Next night retries.\n // Mirrors spawnSleep()'s window logic for consistency.\n const WAKE_HOUR = parseInt(readEnvWithDefault(\"WAKE_TIME\", \"7\", \"wake hour\").split(\":\")[0] ?? \"7\", 10);\n const BED_HOUR = opts.sleepHour;\n const hour = new Date().getHours();\n const inSleepWindow = (BED_HOUR < WAKE_HOUR)\n ? (hour >= BED_HOUR && hour < WAKE_HOUR) // normal: BED=00:30, WAKE=07:00 \u2192 sleep 00-06\n : (hour >= BED_HOUR || hour < WAKE_HOUR); // overnight: BED=23:00, WAKE=07:00 \u2192 sleep 23-06\n if (!inSleepWindow) {\n logInfo(\"sleep\", `\u23F0 Past sleep window (now ${hour}:00, window ${BED_HOUR}:00-${WAKE_HOUR}:00) \u2014 abandoning hw-sleep attempt`);\n _awaitingHwSleep = false;\n postSleepQuietTicks = 0;\n return;\n }\n\n // User messaged since last check \u2014 postpone and reset\n const currentMsgTs = opts.getLastMsgTs?.() ?? 0;\n if (currentMsgTs > lastMsgTsSeenByHwCheck) {\n lastMsgTsSeenByHwCheck = currentMsgTs;\n postSleepQuietTicks = 0;\n logInfo(\"sleep\", \"\uD83D\uDCA4 Hardware sleep postponed \u2014 user messaged (will retry after quiet period)\");\n return;\n }\n\n // Quiet tick \u2014 increment\n const requiredTicks = Math.ceil(getEnv().bedQuietMin * 60 / parseInt(process.env[\"HEARTBEAT_INTERVAL_SEC\"] ?? \"60\", 10));\n postSleepQuietTicks++;\n if (postSleepQuietTicks < requiredTicks) return;\n\n // Threshold reached \u2014 sleep\n _awaitingHwSleep = false;\n postSleepQuietTicks = 0;\n // Kill any wake inhibitor from /wakeup before sleeping\n opts.killWakeInhibit?.();\n const sleepCmd = process.platform === \"darwin\" ? \"pmset sleepnow\" : \"systemctl suspend\";\n logInfo(\"sleep\", `\uD83D\uDCA4 Putting hardware to sleep (${sleepCmd})...`);\n writeSleepStatus(\"hw_sleep\");\n try { execSync(sleepCmd, { timeout: 5000 }); }\n catch (err) {\n writeSleepStatus(\"awake\"); // recover \u2014 don't leave \"hw_sleep\" if pmset failed\n logWarn(\"sleep\", `\uD83D\uDCA4 Hardware sleep failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return {\n get isActive() { return running; },\n get progress() { return progress; },\n get awaitingHwSleep() { return _awaitingHwSleep; },\n spawn: spawnSleep,\n checkHwSleep,\n };\n}\n\n/** Capability registration \u2014 called by discoverCapabilities(). */\nexport function register(_api: CapabilityApi): void {\n // Sleep registration is a no-op here \u2014 the actual SleepHandle is created\n // in phase-sleep.ts because it needs ctx.sendSystemMessage + memory deps\n // that aren't available at capability discovery time.\n // This manifest exists so sleep appears in discoverCapabilities() and\n // can be disabled via DISABLED_CAPABILITIES=sleep.\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/cli/commands/install.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * `abtars install [--upgrade]` \u2014 first-time setup.\n *\n * Phase 1 behavior:\n * - No existing ~/.abtars: create dirs, seed config/ from .env.example,\n * create PATH symlinks. Does NOT run onboard (Phase 3).\n * - Existing ~/.abtars with flat layout (pre-158): refuse unless\n * --upgrade, then run migration 003-flat-to-releases (Phase 1c).\n * - Existing ~/.abtars with new layout: refuse unless --force (which\n * re-seeds missing config and reconciles symlinks, no code changes).\n */\n\nimport { mkdir, readFile, stat, symlink, writeFile } from 'node:fs/promises';\nimport { existsSync, readFileSync, readdirSync, copyFileSync, mkdirSync } from 'node:fs';\nimport { hostname, homedir as _homedir } from 'node:os';\nimport { execSync } from 'node:child_process';\nimport { basename, dirname, join } from 'node:path';\nimport { emptyManifest, packagePaths, readManifest, resolveUserBinDir, writeManifest } from '../deploy-lib-import.js';\n\n/** Resolve real user home even under sudo. */\nfunction homedir(): string {\n const sudoUser = process.env['SUDO_USER'];\n if (sudoUser) {\n try { return execSync(`getent passwd ${sudoUser}`, { encoding: 'utf-8' }).split(':')[5]!.trim(); }\n catch { /* fall through */ }\n }\n return _homedir();\n}\n\nexport interface InstallOptions {\n readonly restore?: string;\n readonly force: boolean;\n readonly dryRun: boolean;\n readonly mode?: \"simple\" | \"supervised\";\n}\n\n// CLI wrappers are read from install-manifest.json at runtime.\n// Each is a thin wrapper that invokes `node current/dist/cli/<name>.js \"$@\"`.\n// Regenerated on every install / flat-to-releases migration.\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await stat(p);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * True if `p` exists as any filesystem entry \u2014 regular file, directory,\n * symlink (including dangling). Use this for collision checks in\n * reconcilePathLink, where a dangling symlink still occupies the inode\n * and would cause EEXIST on symlink(). `exists()` above uses stat() which\n * follows symlinks and returns false on dangling ones; that's wrong for\n * collision detection.\n */\nasync function existsAny(p: string): Promise<boolean> {\n try {\n const { lstat } = await import('node:fs/promises');\n await lstat(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isSymlink(p: string): Promise<boolean> {\n try {\n const { lstat } = await import('node:fs/promises');\n const s = await lstat(p);\n return s.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\nasync function createSkeleton(home: string, dryRun: boolean): Promise<void> {\n const { loadManifest } = await import('../install-manifest.js');\n const manifest = loadManifest();\n const dirs = manifest.directories.map(d => join(home, d.path));\n if (dryRun) {\n process.stdout.write(`[dry-run] mkdir -p:\\n ${dirs.join('\\n ')}\\n`);\n return;\n }\n for (const d of manifest.directories) {\n await mkdir(join(home, d.path), { recursive: true, mode: d.mode ? parseInt(d.mode, 8) : undefined });\n }\n}\n\nasync function seedConfig(repoRoot: string, _configDir: string, dryRun: boolean, home: string): Promise<readonly string[]> {\n const { loadManifest } = await import('../install-manifest.js');\n const manifest = loadManifest(repoRoot);\n const seeded: string[] = [];\n for (const seed of manifest.configSeeds) {\n const src = join(repoRoot, seed.source);\n const dst = join(home, seed.dest);\n if (!(await exists(src))) continue;\n if (await exists(dst)) continue;\n if (dryRun) {\n seeded.push(`[dry-run] cp ${src} ${dst}`);\n continue;\n }\n const content = await readFile(src, 'utf-8');\n await mkdir(dirname(dst), { recursive: true });\n await writeFile(dst, content, { mode: seed.mode ? parseInt(seed.mode, 8) : 0o644 });\n seeded.push(basename(dst));\n }\n return seeded;\n}\n\n/**\n * Reconcile a single PATH symlink at ~/.local/bin/<name>.\n * Policy (plan \u00A7\"PATH symlink collision\"):\n * - Missing \u2192 create\n * - Symlink pointing into our own ~/.abtars/bin/ \u2192 overwrite\n * - Anything else \u2192 refuse with message, unless force\n */\nasync function reconcilePathLink(\n binDir: string,\n userBinDir: string,\n name: string,\n force: boolean,\n dryRun: boolean,\n): Promise<{ action: string; message?: string }> {\n const linkPath = join(userBinDir, name);\n const targetPath = join(binDir, name);\n const linkExists = await existsAny(linkPath);\n if (!linkExists) {\n if (dryRun) return { action: `[dry-run] ln -s ${targetPath} ${linkPath}` };\n await symlink(targetPath, linkPath);\n return { action: `created ${linkPath}` };\n }\n if (await isSymlink(linkPath)) {\n const { readlink, unlink } = await import('node:fs/promises');\n const current = await readlink(linkPath);\n // \"We own it\" means: points at THIS install's bin dir, not a fuzzy match\n // on any path containing /.abtars/bin/. A smoke-test install at\n // ABTARS_HOME=~/.cache/ab-smoke-.../ must not clobber the real\n // ~/.abtars symlinks. Compare absolute paths directly.\n const ownsIt = current === targetPath;\n if (ownsIt) {\n if (dryRun) return { action: `[dry-run] overwrite ${linkPath} (we own it)` };\n await unlink(linkPath);\n await symlink(targetPath, linkPath);\n return { action: `updated ${linkPath}` };\n }\n if (force) {\n if (dryRun) return { action: `[dry-run] --force overwrite ${linkPath} (currently -> ${current})` };\n await unlink(linkPath);\n await symlink(targetPath, linkPath);\n return { action: `forced overwrite ${linkPath} (was -> ${current})` };\n }\n return {\n action: 'refused',\n message: `${linkPath} is a symlink to ${current} (not ours). Pass --force to overwrite.`,\n };\n }\n if (force) {\n if (dryRun) return { action: `[dry-run] --force overwrite ${linkPath} (regular file)` };\n const { unlink } = await import('node:fs/promises');\n await unlink(linkPath);\n await symlink(targetPath, linkPath);\n return { action: `forced overwrite ${linkPath} (was regular file)` };\n }\n return {\n action: 'refused',\n message: `${linkPath} exists as a regular file (not our symlink). Pass --force to overwrite.`,\n };\n}\n\nexport async function writeWrapper(binDir: string, name: string, currentLink: string, dryRun: boolean): Promise<void> {\n const bundleFile = name === 'abtars' ? 'abtars-cli.js' : `${name}.js`;\n const target = join(currentLink, 'bundle', bundleFile);\n // Fallback: pre-bundle dist/ layout (tsc build) for installs that haven't migrated yet.\n const distFile = name === 'abtars' ? 'abtars.js' : `${name}.js`;\n const fallback = join(currentLink, 'dist', 'cli', distFile);\n const content = `#!/usr/bin/env bash\nif [ -f \"${target}\" ]; then\n exec node \"${target}\" \"$@\"\nelif [ -f \"${fallback}\" ]; then\n exec node \"${fallback}\" \"$@\"\nelse\n # No local release \u2014 fall through to npm global binary\n GLOBAL_BIN=\"$(npm root -g 2>/dev/null)/abtars/bundle/${bundleFile}\"\n if [ -f \"$GLOBAL_BIN\" ]; then\n exec node \"$GLOBAL_BIN\" \"$@\"\n fi\n echo \"abtars: no release staged. Run 'abtars install' first.\" >&2\n exit 1\nfi\n`;\n const path = join(binDir, name);\n if (dryRun) {\n process.stdout.write(`[dry-run] write wrapper ${path} -> node ${target} (fallback: ${fallback})\\n`);\n return;\n }\n await writeFile(path, content, { mode: 0o755 });\n}\n\nfunction isPathOnPATH(userBinDir: string): boolean {\n const PATH = process.env['PATH'] ?? '';\n return PATH.split(':').some((p) => p === userBinDir);\n}\n\nexport async function install(opts: InstallOptions): Promise<number> {\n const paths = packagePaths('abtars');\n const home = paths.home;\n const userBinDir = resolveUserBinDir();\n const repoRoot = process.cwd();\n\n // Install log (#718)\n const { initInstallLog, logInstall, logInstallHeader } = await import(\"../install-log.js\");\n initInstallLog(home);\n logInstallHeader(\"install\");\n const _origWrite = process.stdout.write.bind(process.stdout);\n process.stdout.write = ((chunk: any, ...args: any[]) => {\n if (typeof chunk === \"string\" && (chunk.startsWith(\"\u2713\") || chunk.startsWith(\"\u26A0\"))) logInstall(chunk.trimEnd());\n return _origWrite(chunk, ...args);\n }) as typeof process.stdout.write;\n\n const homeExists = await exists(home);\n const manifest = homeExists ? await readManifest(paths.manifest) : null;\n\n if (homeExists && manifest && !opts.force && !opts.restore) {\n process.stderr.write(\n `~/.abtars already installed at version ${manifest.version || '(unset)'}.\\nUse 'abtars update' to upgrade, or --force to re-seed missing config.\\n`,\n );\n return 2;\n }\n\n // Create skeleton (idempotent)\n await createSkeleton(home, opts.dryRun);\n process.stdout.write(`\u2713 skeleton at ${home}\\n`);\n\n // Core templates: abmind seeds its own on first boot (#427 ensureInitialized).\n // No longer seeded by abtars install.\n\n // Create kiro-cli agent config \u2014 ACP transport needs ~/.kiro/agents/professor.json\n const kiroAgentsDir = join(homedir(), '.kiro', 'agents');\n const professorJson = join(kiroAgentsDir, 'professor.json');\n if (!opts.dryRun) {\n await mkdir(kiroAgentsDir, { recursive: true });\n if (!(await exists(professorJson))) {\n await writeFile(professorJson, JSON.stringify({\n name: \"professor\",\n description: \"Abtars bridge agent\",\n tools: [\"*\"],\n allowedTools: [\"@builtin\"],\n toolsSettings: { shell: { autoAllowReadonly: true } },\n includeMcpJson: true,\n }, null, 2) + '\\n');\n process.stdout.write(`\u2713 kiro agent: ${professorJson}\\n`);\n }\n } else {\n process.stdout.write(`[dry-run] create ${professorJson}\\n`);\n }\n\n // Generate Ed25519 identity keypair (skip if already exists)\n const identityKey = join(paths.config, 'identity.key');\n const identityPub = join(paths.config, 'identity.pub');\n if (!opts.dryRun && !(await exists(identityKey))) {\n const { generateKeyPairSync } = await import('node:crypto');\n const { privateKey, publicKey } = generateKeyPairSync('ed25519');\n await writeFile(identityKey, privateKey.export({ format: 'der', type: 'pkcs8' }).toString('base64'));\n await writeFile(identityPub, publicKey.export({ format: 'der', type: 'spki' }).toString('base64'));\n const { chmodSync } = await import('node:fs');\n chmodSync(identityKey, 0o600);\n process.stdout.write(`\u2713 identity keypair generated\\n`);\n }\n\n // Generate self-signed Ed25519 TLS certificate (skip if already exists)\n const identityCrt = join(paths.config, 'identity.crt');\n const identityTlsKey = join(paths.config, 'identity.tls.key');\n if (!opts.dryRun && !(await exists(identityCrt))) {\n const { execSync } = await import('node:child_process');\n const { chmodSync } = await import('node:fs');\n const agentName = hostname();\n try {\n execSync(`openssl req -x509 -newkey ed25519 -keyout identity.tls.key -out identity.crt -days 3650 -nodes -subj \"/CN=${agentName}\"`, { cwd: paths.config, stdio: 'ignore' });\n chmodSync(identityTlsKey, 0o600);\n process.stdout.write(`\u2713 TLS certificate generated (Ed25519, 10yr)\\n`);\n } catch (err) {\n process.stderr.write(`\u26A0 TLS cert generation failed (openssl not found?). Agent-api will start without TLS.\\n`);\n }\n }\n\n // Seed config from examples (only missing ones)\n const seeded = await seedConfig(repoRoot, paths.config, opts.dryRun, home);\n if (seeded.length > 0) {\n process.stdout.write(`\u2713 seeded config: ${seeded.join(', ')}\\n`);\n }\n\n // Write wrappers (always overwrite \u2014 they're regenerable thin shims)\n const { loadManifest: loadInstallManifest } = await import('../install-manifest.js');\n const installManifest = loadInstallManifest(repoRoot);\n if (!opts.dryRun) {\n await mkdir(paths.bin, { recursive: true });\n }\n for (const name of installManifest.cliWrappers) {\n await writeWrapper(paths.bin, name, paths.current, opts.dryRun);\n }\n process.stdout.write(`\u2713 wrappers in ${paths.bin}\\n`);\n\n // Reconcile PATH symlinks\n if (!opts.dryRun) await mkdir(userBinDir, { recursive: true });\n const refused: string[] = [];\n for (const name of installManifest.cliWrappers) {\n const r = await reconcilePathLink(paths.bin, userBinDir, name, opts.force, opts.dryRun);\n if (r.action === 'refused') {\n refused.push(r.message ?? name);\n }\n }\n if (refused.length > 0) {\n process.stderr.write(`\\nPATH symlink conflicts:\\n ${refused.join('\\n ')}\\n`);\n return 4;\n }\n process.stdout.write(`\u2713 PATH symlinks in ${userBinDir}\\n`);\n\n // Warn if ~/.local/bin not on PATH\n if (!isPathOnPATH(userBinDir)) {\n process.stderr.write(\n `\\nWarning: ${userBinDir} is not on $PATH. Add to your shell config:\\n export PATH=\"${userBinDir}:$PATH\"\\n`,\n );\n }\n\n // Initialize manifest if brand-new install AND migration didn't write one.\n // (Migration 003 writes a manifest mid-flow with version + migration record;\n // we must not clobber it here.)\n const manifestAfter = await readManifest(paths.manifest);\n if (manifestAfter === null && !opts.dryRun) {\n await writeManifest(paths.manifest, {\n ...emptyManifest('abtars', hostname()),\n version: '',\n preMigrationBackup: null,\n });\n process.stdout.write(`\u2713 manifest initialized at ${paths.manifest}\\n`);\n }\n\n // Write install mode to manifest. Priority:\n // 1. --mode flag (explicit) \u2014 always wins\n // 2. existing manifest installMode \u2014 preserved (don't clobber on --force)\n // 3. default: supervised\n const manifestForMode = await readManifest(paths.manifest);\n const existingMode = manifestForMode?.installMode;\n const mode = opts.mode ?? existingMode ?? \"supervised\";\n if (manifestForMode) {\n await writeManifest(paths.manifest, { ...manifestForMode, installMode: mode });\n }\n process.stdout.write(`\u2713 install mode: ${mode}\\n`);\n\n // Release staging is handled by `abtars update` (auto-detects npm vs git source)\n\n // Restore from backup zip\n if (opts.restore) {\n const { spawnSync } = await import('node:child_process');\n const { existsSync: fileExists } = await import('node:fs');\n const zipPath = opts.restore;\n if (!fileExists(zipPath)) {\n process.stderr.write(`error: backup file not found: ${zipPath}\\n`);\n return 1;\n }\n // Extract to temp dir\n const tmpDir = join(process.env['TMPDIR'] ?? '/tmp', `abtars-restore-${Date.now()}`);\n const is7z = zipPath.endsWith('.7z');\n const extractCmd = is7z\n ? spawnSync('7z', ['x', zipPath, `-o${tmpDir}`, '-y'], { encoding: 'utf-8' })\n : spawnSync('unzip', ['-o', zipPath, '-d', tmpDir], { encoding: 'utf-8' });\n if (extractCmd.status !== 0) {\n process.stderr.write(`error: extract failed: ${extractCmd.stderr}\\n`);\n return 1;\n }\n // Copy abtars files \u2014 overwrite everything EXCEPT binaries (releases/, current, bin/)\n const abSrc = join(tmpDir, 'abtars');\n if (fileExists(abSrc)) {\n const skipSet = new Set(['releases', 'current', 'bin']);\n for (const f of readdirSync(abSrc)) {\n if (skipSet.has(f)) continue;\n spawnSync('cp', ['-r', join(abSrc, f), home], { stdio: 'inherit' });\n }\n process.stdout.write(`\u2713 restored abtars data\\n`);\n }\n // Copy abmind files\n const abmindHome = process.env['ABMIND_HOME'] ?? join(dirname(home), '.abmind');\n const abmindSrc = join(tmpDir, 'abmind');\n if (fileExists(abmindSrc)) {\n spawnSync('cp', ['-r', ...readdirSync(abmindSrc).map(f => join(abmindSrc, f)), abmindHome], { stdio: 'inherit' });\n process.stdout.write(`\u2713 restored abmind data\\n`);\n }\n // Cleanup + resync\n spawnSync('rm', ['-rf', tmpDir]);\n process.stdout.write(`\\n\u2713 Restore complete. Run 'abtars update' to resync.\\n`);\n return 0;\n }\n\n // --- supervised: load user-scope watchdog (LaunchAgent / systemd user) ---\n if (mode === 'supervised') {\n const { execSync } = await import('node:child_process');\n if (process.platform === 'darwin') {\n const plistSrc = join(home, 'scripts', 'com.abtars.watchdog.plist');\n const plistDst = join(homedir(), 'Library', 'LaunchAgents', 'com.abtars.watchdog.plist');\n if (existsSync(plistSrc)) {\n const content = readFileSync(plistSrc, 'utf-8').replaceAll('{{HOME}}', homedir());\n const { writeFileSync } = await import('node:fs');\n writeFileSync(plistDst, content);\n try { execSync(`launchctl load \"${plistDst}\"`, { stdio: 'ignore' }); } catch { /* already loaded */ }\n process.stdout.write(`\u2713 watchdog LaunchAgent loaded\\n`);\n }\n } else if (process.platform === 'linux') {\n const unitSrc = join(home, 'scripts', 'abtars-watchdog.service');\n const unitDir = join(homedir(), '.config', 'systemd', 'user');\n if (existsSync(unitSrc)) {\n mkdirSync(unitDir, { recursive: true });\n copyFileSync(unitSrc, join(unitDir, 'abtars-watchdog.service'));\n try { execSync('systemctl --user daemon-reload && systemctl --user enable --now abtars-watchdog', { stdio: 'ignore' }); } catch { /* may fail in chroot */ }\n process.stdout.write(`\u2713 watchdog systemd user service enabled\\n`);\n }\n }\n }\n\n process.stdout.write(`\\nInstall complete.\\n`);\n if (!manifestAfter || manifestAfter.version === '') {\n process.stdout.write(`Next: 'abtars update' to build and activate the first release.\\n`);\n } else {\n process.stdout.write(`\\n\u2500\u2500 Next steps \u2500\u2500\\n`);\n process.stdout.write(` 1. Run 'abtars onboard' to configure Telegram token + model provider\\n`);\n process.stdout.write(` 2. (Optional) Install Ollama for memory embeddings: curl -fsSL https://ollama.com/install.sh | sh\\n`);\n process.stdout.write(` 3. Start the bridge: 'abtars restart' or use the watchdog\\n\\n`);\n }\n\n const { printHealthSummary } = await import('./health-check.js');\n printHealthSummary(paths.home);\n\n // #334: Post-install healthcheck \u2014 validate operator channel exists (only on --restore)\n if (!opts.dryRun && opts.restore) {\n const { validateMinimumViability, formatValidationError } = await import('./install-validate.js');\n const validation = validateMinimumViability(paths.config);\n if (!validation.ok) {\n const invocation = `abtars install --restore ${opts.restore}`;\n process.stderr.write(\"\\n\" + formatValidationError(validation, invocation) + \"\\n\");\n return 1;\n }\n }\n\n return 0;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;AAYA,SAAS,OAAO,UAAU,MAAM,SAAS,iBAAiB;AAC1D,SAAS,YAAY,cAAc,aAAa,cAAc,iBAAiB;AAC/E,SAAS,UAAU,WAAW,gBAAgB;AAC9C,SAAS,gBAAgB;AACzB,SAAS,UAAU,SAAS,YAAY;AAIxC,SAAS,UAAkB;AACzB,QAAM,WAAW,QAAQ,IAAI,WAAW;AACxC,MAAI,UAAU;AACZ,QAAI;AAAE,aAAO,SAAS,iBAAiB,QAAQ,IAAI,EAAE,UAAU,QAAQ,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,EAAG,KAAK;AAAA,IAAG,QAC3F;AAAA,IAAqB;AAAA,EAC7B;AACA,SAAO,SAAS;AAClB;AAaA,eAAe,OAAO,GAA6B;AACjD,MAAI;AACF,UAAM,KAAK,CAAC;AACZ,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,eAAe,UAAU,GAA6B;AACpD,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,UAAM,MAAM,CAAC;AACb,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,UAAU,GAA6B;AACpD,MAAI;AACF,UAAM,EAAE,MAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,UAAM,IAAI,MAAM,MAAM,CAAC;AACvB,WAAO,EAAE,eAAe;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,eAAe,MAAc,QAAgC;AAC1E,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,gCAAwB;AAC9D,QAAM,WAAW,aAAa;AAC9B,QAAM,OAAO,SAAS,YAAY,IAAI,OAAK,KAAK,MAAM,EAAE,IAAI,CAAC;AAC7D,MAAI,QAAQ;AACV,YAAQ,OAAO,MAAM;AAAA,IAA0B,KAAK,KAAK,MAAM,CAAC;AAAA,CAAI;AACpE;AAAA,EACF;AACA,aAAW,KAAK,SAAS,aAAa;AACpC,UAAM,MAAM,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,WAAW,MAAM,MAAM,EAAE,OAAO,SAAS,EAAE,MAAM,CAAC,IAAI,OAAU,CAAC;AAAA,EACrG;AACF;AAEA,eAAe,WAAW,UAAkB,YAAoB,QAAiB,MAA0C;AACzH,QAAM,EAAE,aAAa,IAAI,MAAM,OAAO,gCAAwB;AAC9D,QAAM,WAAW,aAAa,QAAQ;AACtC,QAAM,SAAmB,CAAC;AAC1B,aAAW,QAAQ,SAAS,aAAa;AACvC,UAAM,MAAM,KAAK,UAAU,KAAK,MAAM;AACtC,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI;AAChC,QAAI,CAAE,MAAM,OAAO,GAAG,EAAI;AAC1B,QAAI,MAAM,OAAO,GAAG,EAAG;AACvB,QAAI,QAAQ;AACV,aAAO,KAAK,gBAAgB,GAAG,IAAI,GAAG,EAAE;AACxC;AAAA,IACF;AACA,UAAM,UAAU,MAAM,SAAS,KAAK,OAAO;AAC3C,UAAM,MAAM,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7C,UAAM,UAAU,KAAK,SAAS,EAAE,MAAM,KAAK,OAAO,SAAS,KAAK,MAAM,CAAC,IAAI,IAAM,CAAC;AAClF,WAAO,KAAK,SAAS,GAAG,CAAC;AAAA,EAC3B;AACA,SAAO;AACT;AASA,eAAe,kBACb,QACA,YACA,MACA,OACA,QAC+C;AAC/C,QAAM,WAAW,KAAK,YAAY,IAAI;AACtC,QAAM,aAAa,KAAK,QAAQ,IAAI;AACpC,QAAM,aAAa,MAAM,UAAU,QAAQ;AAC3C,MAAI,CAAC,YAAY;AACf,QAAI,OAAQ,QAAO,EAAE,QAAQ,mBAAmB,UAAU,IAAI,QAAQ,GAAG;AACzE,UAAM,QAAQ,YAAY,QAAQ;AAClC,WAAO,EAAE,QAAQ,WAAW,QAAQ,GAAG;AAAA,EACzC;AACA,MAAI,MAAM,UAAU,QAAQ,GAAG;AAC7B,UAAM,EAAE,UAAU,OAAO,IAAI,MAAM,OAAO,kBAAkB;AAC5D,UAAM,UAAU,MAAM,SAAS,QAAQ;AAKvC,UAAM,SAAS,YAAY;AAC3B,QAAI,QAAQ;AACV,UAAI,OAAQ,QAAO,EAAE,QAAQ,uBAAuB,QAAQ,eAAe;AAC3E,YAAM,OAAO,QAAQ;AACrB,YAAM,QAAQ,YAAY,QAAQ;AAClC,aAAO,EAAE,QAAQ,WAAW,QAAQ,GAAG;AAAA,IACzC;AACA,QAAI,OAAO;AACT,UAAI,OAAQ,QAAO,EAAE,QAAQ,+BAA+B,QAAQ,kBAAkB,OAAO,IAAI;AACjG,YAAM,OAAO,QAAQ;AACrB,YAAM,QAAQ,YAAY,QAAQ;AAClC,aAAO,EAAE,QAAQ,oBAAoB,QAAQ,YAAY,OAAO,IAAI;AAAA,IACtE;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,GAAG,QAAQ,oBAAoB,OAAO;AAAA,IACjD;AAAA,EACF;AACA,MAAI,OAAO;AACT,QAAI,OAAQ,QAAO,EAAE,QAAQ,+BAA+B,QAAQ,kBAAkB;AACtF,UAAM,EAAE,OAAO,IAAI,MAAM,OAAO,kBAAkB;AAClD,UAAM,OAAO,QAAQ;AACrB,UAAM,QAAQ,YAAY,QAAQ;AAClC,WAAO,EAAE,QAAQ,oBAAoB,QAAQ,sBAAsB;AAAA,EACrE;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS,GAAG,QAAQ;AAAA,EACtB;AACF;AAEA,eAAsB,aAAa,QAAgB,MAAc,aAAqB,QAAgC;AACpH,QAAM,aAAa,SAAS,WAAW,kBAAkB,GAAG,IAAI;AAChE,QAAM,SAAS,KAAK,aAAa,UAAU,UAAU;AAErD,QAAM,WAAW,SAAS,WAAW,cAAc,GAAG,IAAI;AAC1D,QAAM,WAAW,KAAK,aAAa,QAAQ,OAAO,QAAQ;AAC1D,QAAM,UAAU;AAAA,WACP,MAAM;AAAA,eACF,MAAM;AAAA,aACR,QAAQ;AAAA,eACN,QAAQ;AAAA;AAAA;AAAA,yDAGkC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQjE,QAAM,OAAO,KAAK,QAAQ,IAAI;AAC9B,MAAI,QAAQ;AACV,YAAQ,OAAO,MAAM,2BAA2B,IAAI,YAAY,MAAM,eAAe,QAAQ;AAAA,CAAK;AAClG;AAAA,EACF;AACA,QAAM,UAAU,MAAM,SAAS,EAAE,MAAM,IAAM,CAAC;AAChD;AAEA,SAAS,aAAa,YAA6B;AACjD,QAAM,OAAO,QAAQ,IAAI,MAAM,KAAK;AACpC,SAAO,KAAK,MAAM,GAAG,EAAE,KAAK,CAAC,MAAM,MAAM,UAAU;AACrD;AAEA,eAAsB,QAAQ,MAAuC;AACnE,QAAM,QAAQ,aAAa,QAAQ;AACnC,QAAM,OAAO,MAAM;AACnB,QAAM,aAAa,kBAAkB;AACrC,QAAM,WAAW,QAAQ,IAAI;AAG7B,QAAM,EAAE,gBAAgB,YAAY,iBAAiB,IAAI,MAAM,OAAO,2BAAmB;AACzF,iBAAe,IAAI;AACnB,mBAAiB,SAAS;AAC1B,QAAM,aAAa,QAAQ,OAAO,MAAM,KAAK,QAAQ,MAAM;AAC3D,UAAQ,OAAO,QAAS,CAAC,UAAe,SAAgB;AACtD,QAAI,OAAO,UAAU,aAAa,MAAM,WAAW,QAAG,KAAK,MAAM,WAAW,QAAG,GAAI,YAAW,MAAM,QAAQ,CAAC;AAC7G,WAAO,WAAW,OAAO,GAAG,IAAI;AAAA,EAClC;AAEA,QAAM,aAAa,MAAM,OAAO,IAAI;AACpC,QAAM,WAAW,aAAa,MAAM,aAAa,MAAM,QAAQ,IAAI;AAEnE,MAAI,cAAc,YAAY,CAAC,KAAK,SAAS,CAAC,KAAK,SAAS;AAC1D,YAAQ,OAAO;AAAA,MACb,0CAA0C,SAAS,WAAW,SAAS;AAAA;AAAA;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,MAAM,KAAK,MAAM;AACtC,UAAQ,OAAO,MAAM,sBAAiB,IAAI;AAAA,CAAI;AAM9C,QAAM,gBAAgB,KAAK,QAAQ,GAAG,SAAS,QAAQ;AACvD,QAAM,gBAAgB,KAAK,eAAe,gBAAgB;AAC1D,MAAI,CAAC,KAAK,QAAQ;AAChB,UAAM,MAAM,eAAe,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAI,CAAE,MAAM,OAAO,aAAa,GAAI;AAClC,YAAM,UAAU,eAAe,KAAK,UAAU;AAAA,QAC5C,MAAM;AAAA,QACN,aAAa;AAAA,QACb,OAAO,CAAC,GAAG;AAAA,QACX,cAAc,CAAC,UAAU;AAAA,QACzB,eAAe,EAAE,OAAO,EAAE,mBAAmB,KAAK,EAAE;AAAA,QACpD,gBAAgB;AAAA,MAClB,GAAG,MAAM,CAAC,IAAI,IAAI;AAClB,cAAQ,OAAO,MAAM,sBAAiB,aAAa;AAAA,CAAI;AAAA,IACzD;AAAA,EACF,OAAO;AACL,YAAQ,OAAO,MAAM,oBAAoB,aAAa;AAAA,CAAI;AAAA,EAC5D;AAGA,QAAM,cAAc,KAAK,MAAM,QAAQ,cAAc;AACrD,QAAM,cAAc,KAAK,MAAM,QAAQ,cAAc;AACrD,MAAI,CAAC,KAAK,UAAU,CAAE,MAAM,OAAO,WAAW,GAAI;AAChD,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,aAAa;AAC1D,UAAM,EAAE,YAAY,UAAU,IAAI,oBAAoB,SAAS;AAC/D,UAAM,UAAU,aAAa,WAAW,OAAO,EAAE,QAAQ,OAAO,MAAM,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC;AACnG,UAAM,UAAU,aAAa,UAAU,OAAO,EAAE,QAAQ,OAAO,MAAM,OAAO,CAAC,EAAE,SAAS,QAAQ,CAAC;AACjG,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,SAAS;AAC5C,cAAU,aAAa,GAAK;AAC5B,YAAQ,OAAO,MAAM;AAAA,CAAgC;AAAA,EACvD;AAGA,QAAM,cAAc,KAAK,MAAM,QAAQ,cAAc;AACrD,QAAM,iBAAiB,KAAK,MAAM,QAAQ,kBAAkB;AAC5D,MAAI,CAAC,KAAK,UAAU,CAAE,MAAM,OAAO,WAAW,GAAI;AAChD,UAAM,EAAE,UAAAA,UAAS,IAAI,MAAM,OAAO,oBAAoB;AACtD,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,SAAS;AAC5C,UAAM,YAAY,SAAS;AAC3B,QAAI;AACF,MAAAA,UAAS,6GAA6G,SAAS,KAAK,EAAE,KAAK,MAAM,QAAQ,OAAO,SAAS,CAAC;AAC1K,gBAAU,gBAAgB,GAAK;AAC/B,cAAQ,OAAO,MAAM;AAAA,CAA+C;AAAA,IACtE,SAAS,KAAK;AACZ,cAAQ,OAAO,MAAM;AAAA,CAAwF;AAAA,IAC/G;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,WAAW,UAAU,MAAM,QAAQ,KAAK,QAAQ,IAAI;AACzE,MAAI,OAAO,SAAS,GAAG;AACrB,YAAQ,OAAO,MAAM,yBAAoB,OAAO,KAAK,IAAI,CAAC;AAAA,CAAI;AAAA,EAChE;AAGA,QAAM,EAAE,cAAc,oBAAoB,IAAI,MAAM,OAAO,gCAAwB;AACnF,QAAM,kBAAkB,oBAAoB,QAAQ;AACpD,MAAI,CAAC,KAAK,QAAQ;AAChB,UAAM,MAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5C;AACA,aAAW,QAAQ,gBAAgB,aAAa;AAC9C,UAAM,aAAa,MAAM,KAAK,MAAM,MAAM,SAAS,KAAK,MAAM;AAAA,EAChE;AACA,UAAQ,OAAO,MAAM,sBAAiB,MAAM,GAAG;AAAA,CAAI;AAGnD,MAAI,CAAC,KAAK,OAAQ,OAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC7D,QAAM,UAAoB,CAAC;AAC3B,aAAW,QAAQ,gBAAgB,aAAa;AAC9C,UAAM,IAAI,MAAM,kBAAkB,MAAM,KAAK,YAAY,MAAM,KAAK,OAAO,KAAK,MAAM;AACtF,QAAI,EAAE,WAAW,WAAW;AAC1B,cAAQ,KAAK,EAAE,WAAW,IAAI;AAAA,IAChC;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,OAAO,MAAM;AAAA;AAAA,IAAgC,QAAQ,KAAK,MAAM,CAAC;AAAA,CAAI;AAC7E,WAAO;AAAA,EACT;AACA,UAAQ,OAAO,MAAM,2BAAsB,UAAU;AAAA,CAAI;AAGzD,MAAI,CAAC,aAAa,UAAU,GAAG;AAC7B,YAAQ,OAAO;AAAA,MACb;AAAA,WAAc,UAAU;AAAA,iBAA+D,UAAU;AAAA;AAAA,IACnG;AAAA,EACF;AAKA,QAAM,gBAAgB,MAAM,aAAa,MAAM,QAAQ;AACvD,MAAI,kBAAkB,QAAQ,CAAC,KAAK,QAAQ;AAC1C,UAAM,cAAc,MAAM,UAAU;AAAA,MAClC,GAAG,cAAc,UAAU,SAAS,CAAC;AAAA,MACrC,SAAS;AAAA,MACT,oBAAoB;AAAA,IACtB,CAAC;AACD,YAAQ,OAAO,MAAM,kCAA6B,MAAM,QAAQ;AAAA,CAAI;AAAA,EACtE;AAMA,QAAM,kBAAkB,MAAM,aAAa,MAAM,QAAQ;AACzD,QAAM,eAAe,iBAAiB;AACtC,QAAM,OAAO,KAAK,QAAQ,gBAAgB;AAC1C,MAAI,iBAAiB;AACnB,UAAM,cAAc,MAAM,UAAU,EAAE,GAAG,iBAAiB,aAAa,KAAK,CAAC;AAAA,EAC/E;AACA,UAAQ,OAAO,MAAM,wBAAmB,IAAI;AAAA,CAAI;AAKhD,MAAI,KAAK,SAAS;AAChB,UAAM,EAAE,UAAU,IAAI,MAAM,OAAO,oBAAoB;AACvD,UAAM,EAAE,YAAY,WAAW,IAAI,MAAM,OAAO,SAAS;AACzD,UAAM,UAAU,KAAK;AACrB,QAAI,CAAC,WAAW,OAAO,GAAG;AACxB,cAAQ,OAAO,MAAM,iCAAiC,OAAO;AAAA,CAAI;AACjE,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,kBAAkB,KAAK,IAAI,CAAC,EAAE;AACnF,UAAM,OAAO,QAAQ,SAAS,KAAK;AACnC,UAAM,aAAa,OACf,UAAU,MAAM,CAAC,KAAK,SAAS,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,UAAU,QAAQ,CAAC,IAC1E,UAAU,SAAS,CAAC,MAAM,SAAS,MAAM,MAAM,GAAG,EAAE,UAAU,QAAQ,CAAC;AAC3E,QAAI,WAAW,WAAW,GAAG;AAC3B,cAAQ,OAAO,MAAM,0BAA0B,WAAW,MAAM;AAAA,CAAI;AACpE,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,KAAK,QAAQ,QAAQ;AACnC,QAAI,WAAW,KAAK,GAAG;AACrB,YAAM,UAAU,oBAAI,IAAI,CAAC,YAAY,WAAW,KAAK,CAAC;AACtD,iBAAW,KAAK,YAAY,KAAK,GAAG;AAClC,YAAI,QAAQ,IAAI,CAAC,EAAG;AACpB,kBAAU,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,OAAO,UAAU,CAAC;AAAA,MACpE;AACA,cAAQ,OAAO,MAAM;AAAA,CAA0B;AAAA,IACjD;AAEA,UAAM,aAAa,QAAQ,IAAI,aAAa,KAAK,KAAK,QAAQ,IAAI,GAAG,SAAS;AAC9E,UAAM,YAAY,KAAK,QAAQ,QAAQ;AACvC,QAAI,WAAW,SAAS,GAAG;AACzB,gBAAU,MAAM,CAAC,MAAM,GAAG,YAAY,SAAS,EAAE,IAAI,OAAK,KAAK,WAAW,CAAC,CAAC,GAAG,UAAU,GAAG,EAAE,OAAO,UAAU,CAAC;AAChH,cAAQ,OAAO,MAAM;AAAA,CAA0B;AAAA,IACjD;AAEA,cAAU,MAAM,CAAC,OAAO,MAAM,CAAC;AAC/B,YAAQ,OAAO,MAAM;AAAA;AAAA,CAAwD;AAC7E,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,cAAc;AACzB,UAAM,EAAE,UAAAA,UAAS,IAAI,MAAM,OAAO,oBAAoB;AACtD,QAAI,QAAQ,aAAa,UAAU;AACjC,YAAM,WAAW,KAAK,MAAM,WAAW,2BAA2B;AAClE,YAAM,WAAW,KAAK,QAAQ,GAAG,WAAW,gBAAgB,2BAA2B;AACvF,UAAI,WAAW,QAAQ,GAAG;AACxB,cAAM,UAAU,aAAa,UAAU,OAAO,EAAE,WAAW,YAAY,QAAQ,CAAC;AAChF,cAAM,EAAE,cAAc,IAAI,MAAM,OAAO,SAAS;AAChD,sBAAc,UAAU,OAAO;AAC/B,YAAI;AAAE,UAAAA,UAAS,mBAAmB,QAAQ,KAAK,EAAE,OAAO,SAAS,CAAC;AAAA,QAAG,QAAQ;AAAA,QAAuB;AACpG,gBAAQ,OAAO,MAAM;AAAA,CAAiC;AAAA,MACxD;AAAA,IACF,WAAW,QAAQ,aAAa,SAAS;AACvC,YAAM,UAAU,KAAK,MAAM,WAAW,yBAAyB;AAC/D,YAAM,UAAU,KAAK,QAAQ,GAAG,WAAW,WAAW,MAAM;AAC5D,UAAI,WAAW,OAAO,GAAG;AACvB,kBAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,qBAAa,SAAS,KAAK,SAAS,yBAAyB,CAAC;AAC9D,YAAI;AAAE,UAAAA,UAAS,mFAAmF,EAAE,OAAO,SAAS,CAAC;AAAA,QAAG,QAAQ;AAAA,QAA2B;AAC3J,gBAAQ,OAAO,MAAM;AAAA,CAA2C;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM;AAAA;AAAA,CAAuB;AAC5C,MAAI,CAAC,iBAAiB,cAAc,YAAY,IAAI;AAClD,YAAQ,OAAO,MAAM;AAAA,CAAkE;AAAA,EACzF,OAAO;AACL,YAAQ,OAAO,MAAM;AAAA;AAAA,CAAsB;AAC3C,YAAQ,OAAO,MAAM;AAAA,CAA0E;AAC/F,YAAQ,OAAO,MAAM;AAAA,CAAuG;AAC5H,YAAQ,OAAO,MAAM;AAAA;AAAA,CAAiE;AAAA,EACxF;AAEA,QAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,4BAAmB;AAC/D,qBAAmB,MAAM,IAAI;AAG7B,MAAI,CAAC,KAAK,UAAU,KAAK,SAAS;AAChC,UAAM,EAAE,0BAA0B,sBAAsB,IAAI,MAAM,OAAO,gCAAuB;AAChG,UAAM,aAAa,yBAAyB,MAAM,MAAM;AACxD,QAAI,CAAC,WAAW,IAAI;AAClB,YAAM,aAAa,4BAA4B,KAAK,OAAO;AAC3D,cAAQ,OAAO,MAAM,OAAO,sBAAsB,YAAY,UAAU,IAAI,IAAI;AAChF,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
|
-
"names": ["execSync"]
|
|
7
|
-
}
|