eagle-mem 4.8.6 → 4.9.0
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 +8 -1
- package/bin/eagle-mem +1 -0
- package/hooks/session-start.sh +4 -26
- package/lib/provider.sh +17 -0
- package/lib/updater.sh +320 -0
- package/package.json +1 -1
- package/scripts/config.sh +2 -0
- package/scripts/health.sh +43 -0
- package/scripts/help.sh +2 -0
- package/scripts/install.sh +3 -0
- package/scripts/update.sh +7 -0
- package/scripts/updates.sh +174 -0
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ eagle-mem install
|
|
|
67
67
|
|
|
68
68
|
That's it. Open Claude Code or Codex in any project directory. Eagle Mem activates automatically.
|
|
69
69
|
|
|
70
|
-
Everything is automatic from here. Eagle Mem scans your codebase, indexes source files, captures session summaries, mirrors Claude's memories and tasks, learns which commands are noisy,
|
|
70
|
+
Everything is automatic from here. Eagle Mem scans your codebase, indexes source files, captures session summaries, mirrors Claude's memories and tasks, learns which commands are noisy, prunes stale data, and installs patch bug fixes — all in the background via hooks.
|
|
71
71
|
|
|
72
72
|
For Codex, the installer enables `codex_hooks` in `~/.codex/config.toml`, registers hooks in `~/.codex/hooks.json`, symlinks Eagle Mem skills into `~/.codex/skills`, and patches `~/.codex/AGENTS.md` with the Eagle Mem summary contract. For Claude Code, it keeps using `~/.claude/settings.json`, `CLAUDE.md`, `~/.claude/skills`, and the existing Claude memory/task locations.
|
|
73
73
|
|
|
@@ -101,6 +101,7 @@ These run automatically via SessionStart — no commands needed:
|
|
|
101
101
|
- **Auto-index** — new or stale project triggers FTS5 source indexing
|
|
102
102
|
- **Auto-prune** — observations over 10K rows trigger cleanup
|
|
103
103
|
- **Auto-curate** — the self-learning curator analyzes observation data and generates command rules, co-edit patterns, hot file detection, and guardrails (partially requires LLM provider)
|
|
104
|
+
- **Auto-update** — patch releases install automatically by default, then hooks, skills, migrations, and runtime files refresh through `eagle-mem update`
|
|
104
105
|
|
|
105
106
|
### Token Savings
|
|
106
107
|
|
|
@@ -138,6 +139,7 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
138
139
|
| `eagle-mem search` | Search past sessions, memories, and code |
|
|
139
140
|
| `eagle-mem health` | Diagnose pipeline health and background automation |
|
|
140
141
|
| `eagle-mem config` | View or change LLM provider and token-guard settings |
|
|
142
|
+
| `eagle-mem updates` | View or change auto-update policy |
|
|
141
143
|
| `eagle-mem guard` | Manage regression guardrails for files |
|
|
142
144
|
| `eagle-mem overview` | Build or view project overview |
|
|
143
145
|
| `eagle-mem session` | Save a manual fallback session summary |
|
|
@@ -150,6 +152,10 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
150
152
|
| `eagle-mem scan` | Scan codebase and generate overview |
|
|
151
153
|
| `eagle-mem index` | Index source files for FTS5 code search |
|
|
152
154
|
|
|
155
|
+
### v4.9.0 Patch
|
|
156
|
+
|
|
157
|
+
Eagle Mem now auto-updates by default for patch bug fixes. SessionStart performs a throttled background npm check, applies eligible patch releases with a lock and runtime/database backup, runs `eagle-mem update`, and records a one-time notice for the next session. Minor and major releases stay outside the default auto-apply range unless users opt in with `eagle-mem updates enable minor` or `eagle-mem updates enable major`.
|
|
158
|
+
|
|
153
159
|
### v4.8.6 Patch
|
|
154
160
|
|
|
155
161
|
`eagle-mem session save --summary "..."` now exists as a clean manual fallback for agents that need to persist an explicit session note. It writes through the same `sessions` and `summaries` tables used by Stop hooks, keeps Claude Code/Codex source attribution, and is immediately searchable through normal recall.
|
|
@@ -186,6 +192,7 @@ eagle-mem search --files # most frequently modified files
|
|
|
186
192
|
eagle-mem search --stats # project statistics
|
|
187
193
|
eagle-mem search --session <id> # full observation trail for one session
|
|
188
194
|
eagle-mem session save --summary "fixed auth flow" # manual fallback capture
|
|
195
|
+
eagle-mem updates status # auto-update state and policy
|
|
189
196
|
```
|
|
190
197
|
|
|
191
198
|
### Feature Verification
|
package/bin/eagle-mem
CHANGED
|
@@ -22,6 +22,7 @@ case "$command" in
|
|
|
22
22
|
search) bash "$SCRIPTS_DIR/search.sh" "$@" ;;
|
|
23
23
|
health) bash "$SCRIPTS_DIR/health.sh" "$@" ;;
|
|
24
24
|
config) bash "$SCRIPTS_DIR/config.sh" "$@" ;;
|
|
25
|
+
updates) bash "$SCRIPTS_DIR/updates.sh" "$@" ;;
|
|
25
26
|
guard) bash "$SCRIPTS_DIR/guard.sh" "$@" ;;
|
|
26
27
|
overview) bash "$SCRIPTS_DIR/overview.sh" "$@" ;;
|
|
27
28
|
session|sessions)
|
package/hooks/session-start.sh
CHANGED
|
@@ -14,6 +14,7 @@ SCRIPTS_DIR="$SCRIPT_DIR/../scripts"
|
|
|
14
14
|
. "$LIB_DIR/common.sh"
|
|
15
15
|
. "$LIB_DIR/db.sh"
|
|
16
16
|
. "$LIB_DIR/provider.sh"
|
|
17
|
+
. "$LIB_DIR/updater.sh"
|
|
17
18
|
. "$LIB_DIR/hooks-sessionstart.sh"
|
|
18
19
|
|
|
19
20
|
eagle_ensure_db
|
|
@@ -59,39 +60,16 @@ esac
|
|
|
59
60
|
eagle_sessionstart_auto_provision "$project" "$cwd" "$SCRIPTS_DIR"
|
|
60
61
|
eagle_sessionstart_auto_prune "$project" "$SCRIPTS_DIR" "$(eagle_db "SELECT COUNT(*) FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE project='$p_esc');")"
|
|
61
62
|
eagle_sessionstart_auto_curate "$project" "$SCRIPTS_DIR"
|
|
63
|
+
nohup bash "$SCRIPTS_DIR/updates.sh" auto >> "$EAGLE_MEM_LOG" 2>&1 &
|
|
62
64
|
|
|
63
65
|
find "$EAGLE_MEM_DIR/read-tracker" -type f -mtime +1 -delete 2>/dev/null &
|
|
64
66
|
find "$EAGLE_MEM_DIR/mod-tracker" -type f -mtime +1 -delete 2>/dev/null &
|
|
65
67
|
find "$EAGLE_MEM_DIR/edit-tracker" -type f -mtime +1 -delete 2>/dev/null &
|
|
66
68
|
find "$EAGLE_MEM_DIR" -name ".turn-counter.*" -mtime +1 -delete 2>/dev/null &
|
|
67
69
|
|
|
68
|
-
# ───
|
|
70
|
+
# ─── Update notice from previous background run ────────────
|
|
69
71
|
|
|
70
|
-
update_notice
|
|
71
|
-
version_file="$EAGLE_MEM_DIR/.version"
|
|
72
|
-
latest_file="$EAGLE_MEM_DIR/.latest-version"
|
|
73
|
-
|
|
74
|
-
if [ -f "$version_file" ] && [ -s "$version_file" ]; then
|
|
75
|
-
installed_version=$(tr -d '[:space:]' < "$version_file")
|
|
76
|
-
|
|
77
|
-
if [ -f "$latest_file" ] && [ -s "$latest_file" ]; then
|
|
78
|
-
latest_version=$(tr -d '[:space:]' < "$latest_file")
|
|
79
|
-
newest=$(printf '%s\n' "$installed_version" "$latest_version" | sort -V | tail -1)
|
|
80
|
-
if [ "$newest" != "$installed_version" ]; then
|
|
81
|
-
update_notice="Update available: v${installed_version} → v${latest_version} — run: npm update -g eagle-mem && eagle-mem update"
|
|
82
|
-
fi
|
|
83
|
-
fi
|
|
84
|
-
|
|
85
|
-
if [ ! -f "$latest_file" ] || [ -n "$(find "$latest_file" -mtime +0 2>/dev/null)" ]; then
|
|
86
|
-
(tmp_latest=$(mktemp)
|
|
87
|
-
npm view eagle-mem version 2>/dev/null | tr -d '[:space:]' > "$tmp_latest"
|
|
88
|
-
if [ -s "$tmp_latest" ]; then
|
|
89
|
-
mv "$tmp_latest" "$latest_file"
|
|
90
|
-
else
|
|
91
|
-
rm -f "$tmp_latest"
|
|
92
|
-
fi) &
|
|
93
|
-
fi
|
|
94
|
-
fi
|
|
72
|
+
update_notice=$(eagle_update_take_notice)
|
|
95
73
|
|
|
96
74
|
# ─── Gather stats ────────────────────────────────────────
|
|
97
75
|
|
package/lib/provider.sh
CHANGED
|
@@ -189,6 +189,16 @@ model = "gpt-4o-mini"
|
|
|
189
189
|
schedule = "auto"
|
|
190
190
|
min_sessions = 5
|
|
191
191
|
|
|
192
|
+
[updates]
|
|
193
|
+
# Eagle Mem is infrastructure: patch fixes auto-apply by default so stale bugs
|
|
194
|
+
# do not keep blocking Claude Code or Codex sessions.
|
|
195
|
+
# mode: "auto" applies eligible updates, "notify" only reports them, "off" disables checks.
|
|
196
|
+
mode = "auto"
|
|
197
|
+
# allow: "patch" auto-applies x.y.Z fixes only; "minor" allows x.Y.z; "major" allows all.
|
|
198
|
+
allow = "patch"
|
|
199
|
+
channel = "latest"
|
|
200
|
+
interval_hours = 24
|
|
201
|
+
|
|
192
202
|
[token_guard]
|
|
193
203
|
# rtk: "off" disables RTK help, "auto" uses RTK when found,
|
|
194
204
|
# "enforce" blocks known raw-output shell commands when RTK is unavailable.
|
|
@@ -565,6 +575,13 @@ eagle_show_config() {
|
|
|
565
575
|
echo " Codex: $(eagle_config_get "orchestration" "codex_worker_model" "gpt-5.5") / $(eagle_config_get "orchestration" "codex_worker_effort" "xhigh")"
|
|
566
576
|
echo " Claude: $(eagle_config_get "orchestration" "claude_worker_model" "claude-opus-4-7") / $(eagle_config_get "orchestration" "claude_worker_effort" "xhigh")"
|
|
567
577
|
|
|
578
|
+
echo ""
|
|
579
|
+
echo "Updates:"
|
|
580
|
+
echo " Mode: $(eagle_config_get "updates" "mode" "auto")"
|
|
581
|
+
echo " Allow: $(eagle_config_get "updates" "allow" "patch")"
|
|
582
|
+
echo " Channel: $(eagle_config_get "updates" "channel" "latest")"
|
|
583
|
+
echo " Interval: $(eagle_config_get "updates" "interval_hours" "24")h"
|
|
584
|
+
|
|
568
585
|
echo ""
|
|
569
586
|
echo "Token guard:"
|
|
570
587
|
echo " RTK mode: $(eagle_config_get "token_guard" "rtk" "auto")"
|
package/lib/updater.sh
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Eagle Mem — Auto-update helpers
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
[ -n "${_EAGLE_UPDATER_LOADED:-}" ] && return 0
|
|
6
|
+
_EAGLE_UPDATER_LOADED=1
|
|
7
|
+
|
|
8
|
+
EAGLE_UPDATE_LATEST_FILE="$EAGLE_MEM_DIR/.latest-version"
|
|
9
|
+
EAGLE_UPDATE_NOTICE_FILE="$EAGLE_MEM_DIR/.update-notice"
|
|
10
|
+
EAGLE_UPDATE_STATE_FILE="$EAGLE_MEM_DIR/.last-update.json"
|
|
11
|
+
EAGLE_UPDATE_LOCK_DIR="$EAGLE_MEM_DIR/.update.lock"
|
|
12
|
+
|
|
13
|
+
eagle_update_config_mode() {
|
|
14
|
+
eagle_config_get "updates" "mode" "auto"
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
eagle_update_config_allow() {
|
|
18
|
+
eagle_config_get "updates" "allow" "patch"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
eagle_update_config_channel() {
|
|
22
|
+
eagle_config_get "updates" "channel" "latest"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
eagle_update_config_interval_hours() {
|
|
26
|
+
local hours
|
|
27
|
+
hours=$(eagle_config_get "updates" "interval_hours" "24")
|
|
28
|
+
case "$hours" in
|
|
29
|
+
''|*[!0-9]*) echo "24" ;;
|
|
30
|
+
*) [ "$hours" -lt 1 ] 2>/dev/null && echo "1" || echo "$hours" ;;
|
|
31
|
+
esac
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
eagle_update_ensure_defaults() {
|
|
35
|
+
if [ ! -f "$EAGLE_CONFIG_FILE" ]; then
|
|
36
|
+
eagle_config_init
|
|
37
|
+
return
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if ! grep -q '^\[updates\]' "$EAGLE_CONFIG_FILE" 2>/dev/null; then
|
|
41
|
+
cat >> "$EAGLE_CONFIG_FILE" << 'TOML'
|
|
42
|
+
|
|
43
|
+
[updates]
|
|
44
|
+
# Patch fixes auto-apply by default so stale bugs do not block sessions.
|
|
45
|
+
mode = "auto"
|
|
46
|
+
allow = "patch"
|
|
47
|
+
channel = "latest"
|
|
48
|
+
interval_hours = 24
|
|
49
|
+
TOML
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
eagle_update_installed_version() {
|
|
54
|
+
local version_file="$EAGLE_MEM_DIR/.version"
|
|
55
|
+
if [ -f "$version_file" ] && [ -s "$version_file" ]; then
|
|
56
|
+
tr -d '[:space:]' < "$version_file"
|
|
57
|
+
return
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
if command -v eagle-mem >/dev/null 2>&1; then
|
|
61
|
+
eagle-mem version 2>/dev/null | sed -nE 's/.*v([0-9][0-9A-Za-z.+-]*).*/\1/p' | head -1
|
|
62
|
+
return
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
echo "0.0.0"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_eagle_update_file_age_seconds() {
|
|
69
|
+
local path="$1"
|
|
70
|
+
[ -f "$path" ] || { echo 999999999; return; }
|
|
71
|
+
local now mtime
|
|
72
|
+
now=$(date +%s)
|
|
73
|
+
mtime=$(stat -f %m "$path" 2>/dev/null || stat -c %Y "$path" 2>/dev/null || echo 0)
|
|
74
|
+
echo $((now - mtime))
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
eagle_update_latest_version() {
|
|
78
|
+
local force="${1:-0}"
|
|
79
|
+
local channel
|
|
80
|
+
channel=$(eagle_update_config_channel)
|
|
81
|
+
case "$channel" in latest|next) ;; *) channel="latest" ;; esac
|
|
82
|
+
|
|
83
|
+
local interval_seconds age
|
|
84
|
+
interval_seconds=$(( $(eagle_update_config_interval_hours) * 3600 ))
|
|
85
|
+
age=$(_eagle_update_file_age_seconds "$EAGLE_UPDATE_LATEST_FILE")
|
|
86
|
+
|
|
87
|
+
if [ "$force" != "1" ] && [ -f "$EAGLE_UPDATE_LATEST_FILE" ] && [ -s "$EAGLE_UPDATE_LATEST_FILE" ] && [ "$age" -lt "$interval_seconds" ]; then
|
|
88
|
+
tr -d '[:space:]' < "$EAGLE_UPDATE_LATEST_FILE"
|
|
89
|
+
return 0
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
command -v npm >/dev/null 2>&1 || return 1
|
|
93
|
+
|
|
94
|
+
local latest tmp
|
|
95
|
+
latest=$(npm view "eagle-mem@${channel}" version 2>/dev/null | tr -d '[:space:]')
|
|
96
|
+
[ -n "$latest" ] || return 1
|
|
97
|
+
|
|
98
|
+
mkdir -p "$EAGLE_MEM_DIR" 2>/dev/null
|
|
99
|
+
tmp=$(mktemp "${EAGLE_MEM_DIR}/.latest-version.XXXXXX" 2>/dev/null || mktemp)
|
|
100
|
+
printf '%s\n' "$latest" > "$tmp"
|
|
101
|
+
mv "$tmp" "$EAGLE_UPDATE_LATEST_FILE"
|
|
102
|
+
printf '%s\n' "$latest"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_eagle_update_clean_version() {
|
|
106
|
+
printf '%s' "${1:-0.0.0}" | sed -E 's/^v//; s/[^0-9.].*$//'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
_eagle_update_part() {
|
|
110
|
+
local version part
|
|
111
|
+
version=$(_eagle_update_clean_version "$1")
|
|
112
|
+
part="$2"
|
|
113
|
+
printf '%s' "$version" | awk -F. -v p="$part" '{ v=$p; if (v == "") v=0; gsub(/[^0-9]/, "", v); print v + 0 }'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
eagle_update_version_gt() {
|
|
117
|
+
local a="$1" b="$2" i av bv
|
|
118
|
+
for i in 1 2 3; do
|
|
119
|
+
av=$(_eagle_update_part "$a" "$i")
|
|
120
|
+
bv=$(_eagle_update_part "$b" "$i")
|
|
121
|
+
[ "$av" -gt "$bv" ] && return 0
|
|
122
|
+
[ "$av" -lt "$bv" ] && return 1
|
|
123
|
+
done
|
|
124
|
+
return 1
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
eagle_update_allowed() {
|
|
128
|
+
local installed="$1" latest="$2" allow="$3"
|
|
129
|
+
eagle_update_version_gt "$latest" "$installed" || return 1
|
|
130
|
+
|
|
131
|
+
local imaj imin lmaj lmin
|
|
132
|
+
imaj=$(_eagle_update_part "$installed" 1)
|
|
133
|
+
imin=$(_eagle_update_part "$installed" 2)
|
|
134
|
+
lmaj=$(_eagle_update_part "$latest" 1)
|
|
135
|
+
lmin=$(_eagle_update_part "$latest" 2)
|
|
136
|
+
|
|
137
|
+
case "$allow" in
|
|
138
|
+
major) return 0 ;;
|
|
139
|
+
minor) [ "$imaj" -eq "$lmaj" ] ;;
|
|
140
|
+
patch|*) [ "$imaj" -eq "$lmaj" ] && [ "$imin" -eq "$lmin" ] ;;
|
|
141
|
+
esac
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
eagle_update_write_state() {
|
|
145
|
+
local status="$1" installed="$2" latest="$3" message="$4"
|
|
146
|
+
mkdir -p "$EAGLE_MEM_DIR" 2>/dev/null
|
|
147
|
+
jq -nc \
|
|
148
|
+
--arg status "$status" \
|
|
149
|
+
--arg installed "$installed" \
|
|
150
|
+
--arg latest "$latest" \
|
|
151
|
+
--arg message "$message" \
|
|
152
|
+
--arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
153
|
+
'{status:$status, installed:$installed, latest:$latest, message:$message, updated_at:$at}' \
|
|
154
|
+
> "$EAGLE_UPDATE_STATE_FILE" 2>/dev/null || true
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
eagle_update_set_notice() {
|
|
158
|
+
local message="$1"
|
|
159
|
+
mkdir -p "$EAGLE_MEM_DIR" 2>/dev/null
|
|
160
|
+
printf '%s\n' "$message" > "$EAGLE_UPDATE_NOTICE_FILE" 2>/dev/null || true
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
eagle_update_take_notice() {
|
|
164
|
+
[ -f "$EAGLE_UPDATE_NOTICE_FILE" ] || return 0
|
|
165
|
+
cat "$EAGLE_UPDATE_NOTICE_FILE" 2>/dev/null
|
|
166
|
+
rm -f "$EAGLE_UPDATE_NOTICE_FILE" 2>/dev/null || true
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
eagle_update_lock() {
|
|
170
|
+
mkdir -p "$EAGLE_MEM_DIR" 2>/dev/null
|
|
171
|
+
mkdir "$EAGLE_UPDATE_LOCK_DIR" 2>/dev/null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
eagle_update_unlock() {
|
|
175
|
+
rmdir "$EAGLE_UPDATE_LOCK_DIR" 2>/dev/null || true
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
eagle_update_backup_runtime() {
|
|
179
|
+
local backup_dir="$1"
|
|
180
|
+
mkdir -p "$backup_dir"
|
|
181
|
+
|
|
182
|
+
for item in hooks lib db scripts; do
|
|
183
|
+
if [ -d "$EAGLE_MEM_DIR/$item" ]; then
|
|
184
|
+
cp -R "$EAGLE_MEM_DIR/$item" "$backup_dir/$item" 2>/dev/null || true
|
|
185
|
+
fi
|
|
186
|
+
done
|
|
187
|
+
|
|
188
|
+
if [ -f "$EAGLE_MEM_DB" ]; then
|
|
189
|
+
if command -v sqlite3 >/dev/null 2>&1; then
|
|
190
|
+
sqlite3 "$EAGLE_MEM_DB" ".backup '$backup_dir/memory.db'" >/dev/null 2>&1 || cp "$EAGLE_MEM_DB" "$backup_dir/memory.db" 2>/dev/null || true
|
|
191
|
+
else
|
|
192
|
+
cp "$EAGLE_MEM_DB" "$backup_dir/memory.db" 2>/dev/null || true
|
|
193
|
+
fi
|
|
194
|
+
fi
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
eagle_update_restore_runtime() {
|
|
198
|
+
local backup_dir="$1"
|
|
199
|
+
|
|
200
|
+
for item in hooks lib db scripts; do
|
|
201
|
+
if [ -d "$backup_dir/$item" ]; then
|
|
202
|
+
cp -R "$backup_dir/$item" "$EAGLE_MEM_DIR/" 2>/dev/null || true
|
|
203
|
+
fi
|
|
204
|
+
done
|
|
205
|
+
|
|
206
|
+
if [ -f "$backup_dir/memory.db" ]; then
|
|
207
|
+
cp "$backup_dir/memory.db" "$EAGLE_MEM_DB" 2>/dev/null || true
|
|
208
|
+
fi
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
eagle_update_apply_version() {
|
|
212
|
+
local latest="${1:-}"
|
|
213
|
+
local dry_run="${2:-0}"
|
|
214
|
+
local force="${3:-0}"
|
|
215
|
+
|
|
216
|
+
command -v npm >/dev/null 2>&1 || {
|
|
217
|
+
eagle_update_write_state "failed" "$(eagle_update_installed_version)" "${latest:-unknown}" "npm not found"
|
|
218
|
+
return 1
|
|
219
|
+
}
|
|
220
|
+
command -v eagle-mem >/dev/null 2>&1 || {
|
|
221
|
+
eagle_update_write_state "failed" "$(eagle_update_installed_version)" "${latest:-unknown}" "eagle-mem binary not found on PATH"
|
|
222
|
+
return 1
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
local installed allow
|
|
226
|
+
installed=$(eagle_update_installed_version)
|
|
227
|
+
[ -n "$latest" ] || latest=$(eagle_update_latest_version 1)
|
|
228
|
+
[ -n "$latest" ] || return 1
|
|
229
|
+
allow=$(eagle_update_config_allow)
|
|
230
|
+
|
|
231
|
+
if ! eagle_update_version_gt "$latest" "$installed"; then
|
|
232
|
+
eagle_update_write_state "current" "$installed" "$latest" "already current"
|
|
233
|
+
printf 'current|%s|%s\n' "$installed" "$latest"
|
|
234
|
+
return 0
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
if [ "$force" != "1" ] && ! eagle_update_allowed "$installed" "$latest" "$allow"; then
|
|
238
|
+
eagle_update_write_state "skipped" "$installed" "$latest" "outside allowed ${allow} update range"
|
|
239
|
+
return 2
|
|
240
|
+
fi
|
|
241
|
+
|
|
242
|
+
if [ "$dry_run" = "1" ]; then
|
|
243
|
+
eagle_update_write_state "dry-run" "$installed" "$latest" "eligible for auto-update"
|
|
244
|
+
printf 'eligible|%s|%s\n' "$installed" "$latest"
|
|
245
|
+
return 0
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
if ! eagle_update_lock; then
|
|
249
|
+
eagle_log "INFO" "Auto-update skipped: lock already held"
|
|
250
|
+
eagle_update_write_state "locked" "$installed" "$latest" "update already running"
|
|
251
|
+
printf 'locked|%s|%s\n' "$installed" "$latest"
|
|
252
|
+
return 3
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
local stamp backup_dir update_output update_rc
|
|
256
|
+
stamp=$(date -u +%Y%m%dT%H%M%SZ)
|
|
257
|
+
backup_dir="$EAGLE_MEM_DIR/backups/update-${stamp}-${installed}"
|
|
258
|
+
eagle_update_backup_runtime "$backup_dir"
|
|
259
|
+
|
|
260
|
+
eagle_log "INFO" "Auto-update: installing eagle-mem@$latest from $installed"
|
|
261
|
+
update_output=$(npm install -g "eagle-mem@$latest" 2>&1)
|
|
262
|
+
update_rc=$?
|
|
263
|
+
if [ "$update_rc" -ne 0 ]; then
|
|
264
|
+
eagle_log "ERROR" "Auto-update npm install failed: $update_output"
|
|
265
|
+
eagle_update_write_state "failed" "$installed" "$latest" "npm install failed"
|
|
266
|
+
eagle_update_set_notice "Eagle Mem auto-update failed while installing v${latest}; keeping v${installed}. Run: eagle-mem updates apply"
|
|
267
|
+
eagle_update_unlock
|
|
268
|
+
return 1
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
update_output=$(EAGLE_MEM_AUTO_UPDATE_ACTIVE=1 eagle-mem update 2>&1)
|
|
272
|
+
update_rc=$?
|
|
273
|
+
if [ "$update_rc" -ne 0 ]; then
|
|
274
|
+
eagle_log "ERROR" "Auto-update runtime update failed: $update_output"
|
|
275
|
+
npm install -g "eagle-mem@$installed" >/dev/null 2>&1 || true
|
|
276
|
+
eagle_update_restore_runtime "$backup_dir"
|
|
277
|
+
printf '%s\n' "$installed" > "$EAGLE_MEM_DIR/.version" 2>/dev/null || true
|
|
278
|
+
eagle_update_write_state "rolled-back" "$installed" "$latest" "runtime update failed; restored backup"
|
|
279
|
+
eagle_update_set_notice "Eagle Mem auto-update to v${latest} failed and was rolled back to v${installed}. Run: eagle-mem updates status"
|
|
280
|
+
eagle_update_unlock
|
|
281
|
+
return 1
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
printf '%s\n' "$latest" > "$EAGLE_MEM_DIR/.version" 2>/dev/null || true
|
|
285
|
+
eagle_update_write_state "updated" "$installed" "$latest" "auto-update applied"
|
|
286
|
+
eagle_update_set_notice "Eagle Mem auto-updated from v${installed} to v${latest}. Hooks and skills were refreshed automatically."
|
|
287
|
+
eagle_log "INFO" "Auto-update complete: $installed -> $latest"
|
|
288
|
+
eagle_update_unlock
|
|
289
|
+
printf 'updated|%s|%s\n' "$installed" "$latest"
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
eagle_update_auto() {
|
|
293
|
+
[ "${EAGLE_MEM_DISABLE_AUTO_UPDATE:-}" = "1" ] && return 0
|
|
294
|
+
[ "${EAGLE_MEM_AUTO_UPDATE_ACTIVE:-}" = "1" ] && return 0
|
|
295
|
+
|
|
296
|
+
eagle_update_ensure_defaults
|
|
297
|
+
|
|
298
|
+
local mode installed latest allow
|
|
299
|
+
mode=$(eagle_update_config_mode)
|
|
300
|
+
[ "$mode" = "off" ] && return 0
|
|
301
|
+
|
|
302
|
+
installed=$(eagle_update_installed_version)
|
|
303
|
+
latest=$(eagle_update_latest_version 0) || return 0
|
|
304
|
+
[ -n "$latest" ] || return 0
|
|
305
|
+
eagle_update_version_gt "$latest" "$installed" || return 0
|
|
306
|
+
|
|
307
|
+
allow=$(eagle_update_config_allow)
|
|
308
|
+
if ! eagle_update_allowed "$installed" "$latest" "$allow"; then
|
|
309
|
+
eagle_update_write_state "available" "$installed" "$latest" "outside allowed ${allow} update range"
|
|
310
|
+
eagle_update_set_notice "Eagle Mem v${latest} is available, but auto-update is limited to ${allow} releases. Run: eagle-mem updates apply --force"
|
|
311
|
+
return 0
|
|
312
|
+
fi
|
|
313
|
+
|
|
314
|
+
if [ "$mode" = "auto" ]; then
|
|
315
|
+
eagle_update_apply_version "$latest" 0 0 >/dev/null 2>&1 || true
|
|
316
|
+
else
|
|
317
|
+
eagle_update_write_state "available" "$installed" "$latest" "notify mode"
|
|
318
|
+
eagle_update_set_notice "Eagle Mem v${latest} is available. Run: eagle-mem updates apply"
|
|
319
|
+
fi
|
|
320
|
+
}
|
package/package.json
CHANGED
package/scripts/config.sh
CHANGED
|
@@ -32,6 +32,8 @@ show_help() {
|
|
|
32
32
|
echo -e " eagle-mem config set orchestration.route opposite"
|
|
33
33
|
echo -e " eagle-mem config set orchestration.codex_worker_model gpt-5.5"
|
|
34
34
|
echo -e " eagle-mem config set orchestration.claude_worker_model claude-opus-4-7"
|
|
35
|
+
echo -e " eagle-mem config set updates.mode auto"
|
|
36
|
+
echo -e " eagle-mem config set updates.allow patch"
|
|
35
37
|
echo -e " eagle-mem config set token_guard.rtk enforce"
|
|
36
38
|
echo -e " eagle-mem config set token_guard.raw_bash block"
|
|
37
39
|
echo ""
|
package/scripts/health.sh
CHANGED
|
@@ -12,6 +12,7 @@ LIB_DIR="$SCRIPT_DIR/../lib"
|
|
|
12
12
|
. "$SCRIPT_DIR/style.sh"
|
|
13
13
|
. "$LIB_DIR/db.sh"
|
|
14
14
|
. "$LIB_DIR/provider.sh"
|
|
15
|
+
. "$LIB_DIR/updater.sh"
|
|
15
16
|
|
|
16
17
|
project=""
|
|
17
18
|
JSON_OUT=0
|
|
@@ -191,6 +192,32 @@ if [ -n "$orch_worktree_root" ]; then
|
|
|
191
192
|
eagle_dim " Worktree root: $orch_worktree_root"
|
|
192
193
|
fi
|
|
193
194
|
|
|
195
|
+
# ─── Auto-update visibility (informational) ────────────────
|
|
196
|
+
|
|
197
|
+
updates_mode=$(eagle_update_config_mode)
|
|
198
|
+
updates_allow=$(eagle_update_config_allow)
|
|
199
|
+
updates_channel=$(eagle_update_config_channel)
|
|
200
|
+
updates_interval=$(eagle_update_config_interval_hours)
|
|
201
|
+
updates_latest=$(eagle_update_latest_version 0 2>/dev/null || true)
|
|
202
|
+
updates_installed=$(eagle_update_installed_version)
|
|
203
|
+
updates_status="current"
|
|
204
|
+
|
|
205
|
+
if [ "$updates_mode" = "off" ]; then
|
|
206
|
+
eagle_warn "Updates: disabled"
|
|
207
|
+
issues+=("Auto-updates disabled. Re-enable bug-fix delivery: eagle-mem updates enable patch")
|
|
208
|
+
updates_status="disabled"
|
|
209
|
+
elif [ -n "$updates_latest" ] && eagle_update_version_gt "$updates_latest" "$updates_installed"; then
|
|
210
|
+
if eagle_update_allowed "$updates_installed" "$updates_latest" "$updates_allow"; then
|
|
211
|
+
eagle_warn "Updates: v${updates_latest} available (mode=$updates_mode, allow=$updates_allow)"
|
|
212
|
+
updates_status="available"
|
|
213
|
+
else
|
|
214
|
+
eagle_warn "Updates: v${updates_latest} available, outside $updates_allow range"
|
|
215
|
+
updates_status="outside-range"
|
|
216
|
+
fi
|
|
217
|
+
else
|
|
218
|
+
eagle_ok "Updates: auto/${updates_allow} (${updates_channel}, every ${updates_interval}h)"
|
|
219
|
+
fi
|
|
220
|
+
|
|
194
221
|
# ─── 5. Data quality (10 pts) ──────────────────────────
|
|
195
222
|
|
|
196
223
|
max_score=$((max_score + 10))
|
|
@@ -290,6 +317,13 @@ if [ "$JSON_OUT" -eq 1 ]; then
|
|
|
290
317
|
--arg claude_worker_effort "$orch_claude_effort" \
|
|
291
318
|
--arg codex_bin "${codex_bin:-}" \
|
|
292
319
|
--arg claude_bin "${claude_bin:-}" \
|
|
320
|
+
--arg updates_mode "$updates_mode" \
|
|
321
|
+
--arg updates_allow "$updates_allow" \
|
|
322
|
+
--arg updates_channel "$updates_channel" \
|
|
323
|
+
--arg updates_interval "$updates_interval" \
|
|
324
|
+
--arg updates_installed "$updates_installed" \
|
|
325
|
+
--arg updates_latest "${updates_latest:-}" \
|
|
326
|
+
--arg updates_status "$updates_status" \
|
|
293
327
|
--argjson noise_pct "$noise_pct" \
|
|
294
328
|
--arg last_curated "${last_curated:-never}" \
|
|
295
329
|
'{project:$project, score:$score, max:$max_score, pct:$pct, grade:$grade,
|
|
@@ -304,5 +338,14 @@ if [ "$JSON_OUT" -eq 1 ]; then
|
|
|
304
338
|
codex:{model:$codex_worker_model, effort:$codex_worker_effort, cli:$codex_bin},
|
|
305
339
|
claude_code:{model:$claude_worker_model, effort:$claude_worker_effort, cli:$claude_bin}
|
|
306
340
|
},
|
|
341
|
+
updates:{
|
|
342
|
+
mode:$updates_mode,
|
|
343
|
+
allow:$updates_allow,
|
|
344
|
+
channel:$updates_channel,
|
|
345
|
+
interval_hours:$updates_interval,
|
|
346
|
+
installed:$updates_installed,
|
|
347
|
+
latest:$updates_latest,
|
|
348
|
+
status:$updates_status
|
|
349
|
+
},
|
|
307
350
|
noise_pct:$noise_pct, last_curated:$last_curated}' >&3
|
|
308
351
|
fi
|
package/scripts/help.sh
CHANGED
|
@@ -22,6 +22,7 @@ echo -e " ${CYAN}update${RESET} Re-deploy hooks and run migrations"
|
|
|
22
22
|
echo -e " ${CYAN}uninstall${RESET} Remove hooks and optionally delete data"
|
|
23
23
|
echo -e " ${CYAN}search${RESET} Search past sessions, memories, and code"
|
|
24
24
|
echo -e " ${CYAN}health${RESET} Diagnose pipeline health and background automation"
|
|
25
|
+
echo -e " ${CYAN}updates${RESET} Auto-update status and policy"
|
|
25
26
|
echo -e " ${CYAN}overview${RESET} Build or view project overview"
|
|
26
27
|
echo -e " ${CYAN}session${RESET} Save a manual session summary"
|
|
27
28
|
echo -e " ${CYAN}memories${RESET} View/sync agent memories"
|
|
@@ -42,6 +43,7 @@ echo -e " ${DIM}Recall${RESET} Project overview, summaries, memories, p
|
|
|
42
43
|
echo -e " ${DIM}Guardrails${RESET} Decisions, gotchas, feature verification, stale memory warnings"
|
|
43
44
|
echo -e " ${DIM}Tokens${RESET} Compact hook recall and optional RTK shell-output routing"
|
|
44
45
|
echo -e " ${DIM}Lanes${RESET} Cross-agent worker status, worktrees, logs, validation, handoffs"
|
|
46
|
+
echo -e " ${DIM}Updates${RESET} Patch fixes install automatically by default"
|
|
45
47
|
echo ""
|
|
46
48
|
echo -e " ${BOLD}Search modes:${RESET}"
|
|
47
49
|
echo -e " ${DIM}\$${RESET} eagle-mem search \"auth bug\" ${DIM}# keyword search${RESET}"
|
package/scripts/install.sh
CHANGED
|
@@ -316,12 +316,15 @@ fi
|
|
|
316
316
|
# ─── Initialize config ────────────────────────────────────
|
|
317
317
|
|
|
318
318
|
. "$LIB_DIR/provider.sh"
|
|
319
|
+
. "$LIB_DIR/updater.sh"
|
|
319
320
|
if [ ! -f "$EAGLE_CONFIG_FILE" ]; then
|
|
320
321
|
eagle_config_init
|
|
321
322
|
eagle_ok "Config created ${DIM}(auto-detected provider)${RESET}"
|
|
322
323
|
else
|
|
324
|
+
eagle_update_ensure_defaults
|
|
323
325
|
eagle_ok "Config ${DIM}(already exists)${RESET}"
|
|
324
326
|
fi
|
|
327
|
+
eagle_ok "Auto-updates ${DIM}(mode=$(eagle_update_config_mode), allow=$(eagle_update_config_allow))${RESET}"
|
|
325
328
|
|
|
326
329
|
# ─── Patch CLAUDE.md with Eagle Mem instructions ─────────
|
|
327
330
|
|
package/scripts/update.sh
CHANGED
|
@@ -12,6 +12,8 @@ LIB_DIR="$SCRIPTS_DIR/../lib"
|
|
|
12
12
|
. "$SCRIPTS_DIR/style.sh"
|
|
13
13
|
. "$LIB_DIR/common.sh"
|
|
14
14
|
. "$LIB_DIR/db.sh"
|
|
15
|
+
. "$LIB_DIR/provider.sh"
|
|
16
|
+
. "$LIB_DIR/updater.sh"
|
|
15
17
|
. "$LIB_DIR/hooks.sh"
|
|
16
18
|
. "$LIB_DIR/codex-hooks.sh"
|
|
17
19
|
|
|
@@ -150,6 +152,11 @@ else
|
|
|
150
152
|
eagle_ok "Project names up to date"
|
|
151
153
|
fi
|
|
152
154
|
|
|
155
|
+
# ─── Ensure auto-update defaults exist ─────────────────────
|
|
156
|
+
|
|
157
|
+
eagle_update_ensure_defaults
|
|
158
|
+
eagle_ok "Auto-updates ${DIM}(mode=$(eagle_update_config_mode), allow=$(eagle_update_config_allow))${RESET}"
|
|
159
|
+
|
|
153
160
|
# ─── Patch CLAUDE.md with Eagle Mem instructions ─────────
|
|
154
161
|
|
|
155
162
|
if [ "$claude_found" = true ]; then
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Eagle Mem — Update policy and auto-update CLI
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
LIB_DIR="$SCRIPTS_DIR/../lib"
|
|
9
|
+
|
|
10
|
+
. "$SCRIPTS_DIR/style.sh"
|
|
11
|
+
. "$LIB_DIR/common.sh"
|
|
12
|
+
. "$LIB_DIR/provider.sh"
|
|
13
|
+
. "$LIB_DIR/updater.sh"
|
|
14
|
+
|
|
15
|
+
show_help() {
|
|
16
|
+
echo -e " ${BOLD}eagle-mem updates${RESET} — Manage automatic Eagle Mem updates"
|
|
17
|
+
echo ""
|
|
18
|
+
echo -e " ${BOLD}Usage:${RESET}"
|
|
19
|
+
echo -e " eagle-mem updates ${CYAN}status${RESET}"
|
|
20
|
+
echo -e " eagle-mem updates ${CYAN}check${RESET}"
|
|
21
|
+
echo -e " eagle-mem updates ${CYAN}apply${RESET} [--force] [--dry-run]"
|
|
22
|
+
echo -e " eagle-mem updates ${CYAN}enable${RESET} [auto|notify|patch|minor|major]"
|
|
23
|
+
echo -e " eagle-mem updates ${CYAN}disable${RESET}"
|
|
24
|
+
echo ""
|
|
25
|
+
echo -e " ${DIM}Default: mode=auto, allow=patch. Patch bug fixes install in the${RESET}"
|
|
26
|
+
echo -e " ${DIM}background from SessionStart so stale bugs do not block agents.${RESET}"
|
|
27
|
+
echo ""
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
updates_status() {
|
|
31
|
+
eagle_update_ensure_defaults
|
|
32
|
+
|
|
33
|
+
local installed latest latest_rc
|
|
34
|
+
installed=$(eagle_update_installed_version)
|
|
35
|
+
latest=$(eagle_update_latest_version 0 2>/dev/null) && latest_rc=0 || latest_rc=$?
|
|
36
|
+
|
|
37
|
+
eagle_header "Updates"
|
|
38
|
+
eagle_kv "Installed:" "v${installed:-unknown}"
|
|
39
|
+
if [ "$latest_rc" -eq 0 ] && [ -n "$latest" ]; then
|
|
40
|
+
eagle_kv "Latest:" "v$latest"
|
|
41
|
+
else
|
|
42
|
+
eagle_kv "Latest:" "unavailable"
|
|
43
|
+
fi
|
|
44
|
+
eagle_kv "Mode:" "$(eagle_update_config_mode)"
|
|
45
|
+
eagle_kv "Allow:" "$(eagle_update_config_allow)"
|
|
46
|
+
eagle_kv "Channel:" "$(eagle_update_config_channel)"
|
|
47
|
+
eagle_kv "Interval:" "$(eagle_update_config_interval_hours)h"
|
|
48
|
+
|
|
49
|
+
if [ -f "$EAGLE_UPDATE_STATE_FILE" ]; then
|
|
50
|
+
status=$(jq -r '.status // "unknown"' "$EAGLE_UPDATE_STATE_FILE" 2>/dev/null || echo "unknown")
|
|
51
|
+
at=$(jq -r '.updated_at // ""' "$EAGLE_UPDATE_STATE_FILE" 2>/dev/null || echo "")
|
|
52
|
+
msg=$(jq -r '.message // ""' "$EAGLE_UPDATE_STATE_FILE" 2>/dev/null || echo "")
|
|
53
|
+
eagle_kv "Last run:" "$status ${at:+($at)}"
|
|
54
|
+
[ -n "$msg" ] && eagle_kv "Message:" "$msg"
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [ -n "$latest" ] && eagle_update_version_gt "$latest" "$installed"; then
|
|
58
|
+
if eagle_update_allowed "$installed" "$latest" "$(eagle_update_config_allow)"; then
|
|
59
|
+
eagle_ok "Eligible update available"
|
|
60
|
+
else
|
|
61
|
+
eagle_warn "Update available but outside allowed range"
|
|
62
|
+
fi
|
|
63
|
+
else
|
|
64
|
+
eagle_ok "Already current"
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
updates_check() {
|
|
69
|
+
eagle_update_ensure_defaults
|
|
70
|
+
installed=$(eagle_update_installed_version)
|
|
71
|
+
latest=$(eagle_update_latest_version 1)
|
|
72
|
+
if [ -z "$latest" ]; then
|
|
73
|
+
eagle_err "Could not check npm for updates"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if eagle_update_version_gt "$latest" "$installed"; then
|
|
78
|
+
if eagle_update_allowed "$installed" "$latest" "$(eagle_update_config_allow)"; then
|
|
79
|
+
eagle_ok "Update available: v$installed -> v$latest"
|
|
80
|
+
else
|
|
81
|
+
eagle_warn "Update available: v$installed -> v$latest (outside allowed range)"
|
|
82
|
+
fi
|
|
83
|
+
else
|
|
84
|
+
eagle_ok "Already current: v$installed"
|
|
85
|
+
fi
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
updates_apply() {
|
|
89
|
+
eagle_update_ensure_defaults
|
|
90
|
+
local dry_run=0 force=0 latest=""
|
|
91
|
+
while [ $# -gt 0 ]; do
|
|
92
|
+
case "$1" in
|
|
93
|
+
--dry-run) dry_run=1; shift ;;
|
|
94
|
+
--force) force=1; shift ;;
|
|
95
|
+
--latest) latest="${2:-}"; shift 2 ;;
|
|
96
|
+
--help|-h) show_help; exit 0 ;;
|
|
97
|
+
*)
|
|
98
|
+
eagle_err "Unknown apply option: $1"
|
|
99
|
+
exit 1
|
|
100
|
+
;;
|
|
101
|
+
esac
|
|
102
|
+
done
|
|
103
|
+
|
|
104
|
+
if output=$(eagle_update_apply_version "$latest" "$dry_run" "$force" 2>&1); then
|
|
105
|
+
state=$(printf '%s' "$output" | awk -F'|' 'NR == 1 {print $1}')
|
|
106
|
+
installed=$(printf '%s' "$output" | awk -F'|' 'NR == 1 {print $2}')
|
|
107
|
+
latest=$(printf '%s' "$output" | awk -F'|' 'NR == 1 {print $3}')
|
|
108
|
+
if [ "$state" = "current" ]; then
|
|
109
|
+
eagle_ok "Already current: v$installed"
|
|
110
|
+
elif [ "$dry_run" = "1" ]; then
|
|
111
|
+
eagle_ok "Would update v$installed -> v$latest"
|
|
112
|
+
else
|
|
113
|
+
eagle_ok "Eagle Mem updated from v$installed to v$latest"
|
|
114
|
+
fi
|
|
115
|
+
else
|
|
116
|
+
rc=$?
|
|
117
|
+
if [ "$rc" -eq 2 ]; then
|
|
118
|
+
eagle_warn "Update skipped: outside allowed range"
|
|
119
|
+
eagle_info "Use --force for a manual override"
|
|
120
|
+
exit 0
|
|
121
|
+
fi
|
|
122
|
+
if [ "$rc" -eq 3 ]; then
|
|
123
|
+
eagle_warn "Update already running"
|
|
124
|
+
exit 0
|
|
125
|
+
fi
|
|
126
|
+
eagle_err "Update failed"
|
|
127
|
+
[ -n "$output" ] && eagle_dim "$output"
|
|
128
|
+
exit 1
|
|
129
|
+
fi
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
updates_enable() {
|
|
133
|
+
eagle_update_ensure_defaults
|
|
134
|
+
local value="${1:-auto}"
|
|
135
|
+
case "$value" in
|
|
136
|
+
auto|notify|off)
|
|
137
|
+
eagle_config_set "updates" "mode" "$value"
|
|
138
|
+
;;
|
|
139
|
+
patch|minor|major)
|
|
140
|
+
eagle_config_set "updates" "mode" "auto"
|
|
141
|
+
eagle_config_set "updates" "allow" "$value"
|
|
142
|
+
;;
|
|
143
|
+
*)
|
|
144
|
+
eagle_err "Use: eagle-mem updates enable [auto|notify|patch|minor|major]"
|
|
145
|
+
exit 1
|
|
146
|
+
;;
|
|
147
|
+
esac
|
|
148
|
+
eagle_ok "Updates enabled: mode=$(eagle_update_config_mode), allow=$(eagle_update_config_allow)"
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
updates_disable() {
|
|
152
|
+
eagle_update_ensure_defaults
|
|
153
|
+
eagle_config_set "updates" "mode" "off"
|
|
154
|
+
eagle_ok "Automatic update checks disabled"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
command="${1:-status}"
|
|
158
|
+
shift 2>/dev/null || true
|
|
159
|
+
|
|
160
|
+
case "$command" in
|
|
161
|
+
status) updates_status "$@" ;;
|
|
162
|
+
check) updates_check "$@" ;;
|
|
163
|
+
apply) updates_apply "$@" ;;
|
|
164
|
+
auto) eagle_update_auto ;;
|
|
165
|
+
enable) updates_enable "$@" ;;
|
|
166
|
+
disable) updates_disable ;;
|
|
167
|
+
help|--help|-h) show_help ;;
|
|
168
|
+
*)
|
|
169
|
+
eagle_err "Unknown updates command: $command"
|
|
170
|
+
echo ""
|
|
171
|
+
show_help
|
|
172
|
+
exit 1
|
|
173
|
+
;;
|
|
174
|
+
esac
|