eagle-mem 4.9.6 → 4.9.8

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.
@@ -1,35 +1,80 @@
1
1
  #!/usr/bin/env bash
2
- # Eagle Mem statusline section — outputs a single formatted section
3
- # Called by the user's statusline command to append Eagle Mem stats.
4
- # Usage: source this script OR call eagle_mem_statusline "$project_dir"
2
+ # Eagle Mem statusline renderers.
3
+ # Usage:
4
+ # source this file and call eagle_mem_statusline "$project_dir" "$session_id" "$input"
5
+ # printf '%s' "$input" | bash ~/.eagle-mem/scripts/statusline-em.sh --hud
5
6
 
6
- eagle_mem_statusline() {
7
+ _eagle_statusline_load_common() {
8
+ local script_dir
9
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ . "$script_dir/../lib/common.sh"
11
+ }
12
+
13
+ _eagle_statusline_relative_time() {
14
+ local raw="${1:-}"
15
+ [ -n "$raw" ] && [ "$raw" != "never" ] || { printf 'never\n'; return; }
16
+
17
+ local last_epoch now_epoch diff_sec
18
+ last_epoch=$(date -j -u -f "%Y-%m-%dT%H:%M:%S" "${raw%%.*}" "+%s" 2>/dev/null \
19
+ || date -u -d "$raw" "+%s" 2>/dev/null \
20
+ || true)
21
+ now_epoch=$(date "+%s" 2>/dev/null || true)
22
+ if [ -z "$last_epoch" ] || [ -z "$now_epoch" ]; then
23
+ printf '%s\n' "$raw"
24
+ return
25
+ fi
26
+
27
+ diff_sec=$((now_epoch - last_epoch))
28
+ if [ "$diff_sec" -lt 60 ]; then
29
+ printf 'just now\n'
30
+ elif [ "$diff_sec" -lt 3600 ]; then
31
+ printf '%sm ago\n' "$((diff_sec / 60))"
32
+ elif [ "$diff_sec" -lt 86400 ]; then
33
+ printf '%sh ago\n' "$((diff_sec / 3600))"
34
+ else
35
+ printf '%sd ago\n' "$((diff_sec / 86400))"
36
+ fi
37
+ }
38
+
39
+ eagle_mem_statusline_stats() {
7
40
  local project_dir="${1:-}"
8
41
  local session_id="${2:-}"
9
42
  local statusline_input="${3:-}"
43
+ local current_dir="${4:-}"
10
44
  local em_db="$HOME/.eagle-mem/memory.db"
11
45
  [ -f "$em_db" ] || return
12
46
 
13
- local SCRIPT_DIR; SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
- . "$SCRIPT_DIR/../lib/common.sh"
47
+ _eagle_statusline_load_common
48
+
15
49
  local sqlite_bin
16
50
  sqlite_bin=$(eagle_sqlite_path)
17
51
  [ -n "$sqlite_bin" ] || return
18
52
 
19
- local proj
53
+ if [ -n "$statusline_input" ]; then
54
+ [ -z "$session_id" ] && session_id=$(printf '%s' "$statusline_input" | jq -r '.session_id // .session.id // empty' 2>/dev/null)
55
+ [ -z "$project_dir" ] && project_dir=$(printf '%s' "$statusline_input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // empty' 2>/dev/null)
56
+ [ -z "$current_dir" ] && current_dir=$(printf '%s' "$statusline_input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
57
+ fi
20
58
  [ -z "$project_dir" ] && project_dir="$(pwd)"
21
- proj=$(eagle_project_from_statusline_input "$statusline_input" "$project_dir" "$project_dir" "$session_id")
22
- [ -z "$proj" ] && return
59
+ [ -z "$current_dir" ] && current_dir="$project_dir"
23
60
 
24
- proj=$(eagle_sql_escape "$proj")
61
+ local project_key project_scope project_condition stats sessions memories last_raw turns version latest
62
+ project_key=$(eagle_project_from_statusline_input "$statusline_input" "$project_dir" "$current_dir" "$session_id")
63
+ [ -n "$project_key" ] || return
64
+ project_scope=$(eagle_recall_project_scope_from_cwd "${current_dir:-$project_dir}" "$project_key")
65
+ project_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
66
+
67
+ stats=$("$sqlite_bin" "$em_db" "SELECT
68
+ COUNT(*) || '|' ||
69
+ (SELECT COUNT(*) FROM agent_memories WHERE $project_condition) || '|' ||
70
+ COALESCE(MAX(COALESCE(last_activity_at, started_at)), 'never')
71
+ FROM sessions
72
+ WHERE $project_condition;" 2>/dev/null)
73
+ IFS='|' read -r sessions memories last_raw <<< "${stats:-0|0|never}"
74
+ sessions=${sessions:-0}
75
+ memories=${memories:-0}
76
+ last_raw=${last_raw:-never}
25
77
 
26
- local version cnt mem turns
27
- version=$(tr -d '[:space:]' < "$HOME/.eagle-mem/.version" 2>/dev/null)
28
- [ -z "$version" ] && version="?"
29
- cnt=$(echo ".headers off
30
- SELECT COUNT(*) FROM sessions WHERE project = '${proj}';" | "$sqlite_bin" "$em_db" 2>/dev/null | tr -d '[:space:]')
31
- mem=$(echo ".headers off
32
- SELECT COUNT(*) FROM agent_memories WHERE project = '${proj}';" | "$sqlite_bin" "$em_db" 2>/dev/null | tr -d '[:space:]')
33
78
  if [ -n "$session_id" ] && [ -f "$HOME/.eagle-mem/.turn-counter.${session_id}" ]; then
34
79
  turns=$(tr -d '[:space:]' < "$HOME/.eagle-mem/.turn-counter.${session_id}" 2>/dev/null)
35
80
  else
@@ -40,26 +85,85 @@ SELECT COUNT(*) FROM agent_memories WHERE project = '${proj}';" | "$sqlite_bin"
40
85
  done \
41
86
  | awk '($1+0)>max{max=$1+0} END{print max+0}')
42
87
  fi
43
- cnt=${cnt:-0}; mem=${mem:-0}
44
88
  turns=${turns:-0}
45
89
 
90
+ version=$(tr -d '[:space:]' < "$HOME/.eagle-mem/.version" 2>/dev/null)
91
+ latest=$(tr -d '[:space:]' < "$HOME/.eagle-mem/.latest-version" 2>/dev/null)
92
+ [ -z "$version" ] && version="?"
93
+ [ -z "$latest" ] && latest="$version"
94
+
95
+ printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$project_key" "$version" "$latest" "$sessions" "$memories" "$turns" "$last_raw"
96
+ }
97
+
98
+ eagle_mem_statusline() {
99
+ local stats project_key version latest sessions memories turns last_raw
100
+ stats=$(eagle_mem_statusline_stats "${1:-}" "${2:-}" "${3:-}" "${4:-}") || return
101
+ IFS=$'\t' read -r project_key version latest sessions memories turns last_raw <<< "$stats"
102
+
46
103
  local R='\033[0m' CYAN='\033[96m' WHT='\033[97m' DIM='\033[2m'
47
- printf "%bEM%b %bv%s%b ses %b%s%b mem %b%s%b turns %b%s%b" \
104
+ printf "%bEagle%b %bv%s%b | %b%s%b sessions | %b%s%b memories | turn %b%s%b" \
48
105
  "$CYAN" "$R" \
49
106
  "$WHT" "$version" "$DIM" \
50
- "$WHT" "$cnt" "$DIM" \
51
- "$WHT" "$mem" "$DIM" \
52
- "$WHT" "$turns" "$R"
107
+ "$WHT" "${sessions:-0}" "$DIM" \
108
+ "$WHT" "${memories:-0}" "$DIM" \
109
+ "$WHT" "${turns:-0}" "$R"
110
+ }
111
+
112
+ eagle_mem_statusline_hud() {
113
+ local stats project_key version latest sessions memories turns last_raw last_label
114
+ stats=$(eagle_mem_statusline_stats "${1:-}" "${2:-}" "${3:-}" "${4:-}") || return
115
+ IFS=$'\t' read -r project_key version latest sessions memories turns last_raw <<< "$stats"
116
+ last_label=$(_eagle_statusline_relative_time "$last_raw")
117
+
118
+ local R='\033[0m' CYAN='\033[96m' WHT='\033[97m' DIM='\033[2m'
119
+ local GRN='\033[92m' ORG='\033[38;5;214m' RED='\033[91m'
120
+ local turn_color pressure_label em_ver newest
121
+
122
+ turns=${turns:-0}
123
+ if [ "$turns" -ge 30 ] 2>/dev/null; then
124
+ turn_color="$RED"; pressure_label="CRITICAL"
125
+ elif [ "$turns" -ge 20 ] 2>/dev/null; then
126
+ turn_color="$ORG"; pressure_label="HIGH"
127
+ else
128
+ turn_color="$GRN"; pressure_label="OK"
129
+ fi
130
+
131
+ em_ver="v${version:-?}"
132
+ newest=$(printf '%s\n' "${version:-}" "${latest:-}" | sort -V 2>/dev/null | tail -1 || true)
133
+ if [ -n "$latest" ] && [ -n "$newest" ] && [ "$newest" != "$version" ]; then
134
+ em_ver="${em_ver} ${ORG}↑${latest}${R}"
135
+ elif [ -n "$latest" ] && [ "$latest" = "$version" ]; then
136
+ em_ver="${em_ver} ${GRN}✓${R}"
137
+ fi
138
+
139
+ printf "%bEagle Mem%b %b %b│%b %bSessions:%b %b%s%b %b│%b %bMemories:%b %b%s%b %b│%b %bTurns:%b %b%s/30%b %b(%s)%b %b│%b %bUpdated:%b %b%s%b" \
140
+ "$CYAN" "$R" "$em_ver" \
141
+ "$DIM" "$R" "$DIM" "$R" "$WHT" "${sessions:-0}" "$R" "$DIM" "$R" \
142
+ "$DIM" "$R" "$WHT" "${memories:-0}" "$R" "$DIM" "$R" \
143
+ "$DIM" "$R" "$turn_color" "$turns" "$R" "$turn_color" "$pressure_label" "$R" "$DIM" "$R" \
144
+ "$DIM" "$R" "$WHT" "$last_label" "$R"
53
145
  }
54
146
 
55
- # When run directly, read project_dir from stdin JSON (statusline format)
56
147
  if [ "${BASH_SOURCE[0]}" = "$0" ]; then
148
+ mode="${1:-compact}"
57
149
  if [ -t 0 ]; then
58
150
  input=""
59
151
  else
60
152
  input=$(cat)
61
153
  fi
62
- project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // empty' 2>/dev/null)
63
- session_id=$(echo "$input" | jq -r '.session_id // .session.id // empty' 2>/dev/null)
64
- eagle_mem_statusline "${project_dir:-$(pwd)}" "$session_id" "$input"
154
+ project_dir=$(printf '%s' "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // empty' 2>/dev/null)
155
+ current_dir=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
156
+ session_id=$(printf '%s' "$input" | jq -r '.session_id // .session.id // empty' 2>/dev/null)
157
+
158
+ case "$mode" in
159
+ --hud|hud)
160
+ eagle_mem_statusline_hud "${project_dir:-$(pwd)}" "$session_id" "$input" "$current_dir"
161
+ ;;
162
+ --stats|stats)
163
+ eagle_mem_statusline_stats "${project_dir:-$(pwd)}" "$session_id" "$input" "$current_dir"
164
+ ;;
165
+ *)
166
+ eagle_mem_statusline "${project_dir:-$(pwd)}" "$session_id" "$input" "$current_dir"
167
+ ;;
168
+ esac
65
169
  fi
@@ -13,12 +13,32 @@ LIB_DIR="$SCRIPTS_DIR/../lib"
13
13
  . "$LIB_DIR/codex-hooks.sh"
14
14
 
15
15
  SETTINGS="$EAGLE_SETTINGS"
16
+ dry_run=false
17
+
18
+ for arg in "$@"; do
19
+ case "$arg" in
20
+ --dry-run|--check)
21
+ dry_run=true
22
+ ;;
23
+ --help|-h)
24
+ echo "Usage: eagle-mem uninstall [--dry-run]"
25
+ exit 0
26
+ ;;
27
+ esac
28
+ done
16
29
 
17
30
  eagle_header "Uninstall"
31
+ eagle_uninstall_change_plan
32
+
33
+ if [ "$dry_run" = true ]; then
34
+ eagle_footer "Dry run complete. No files changed."
35
+ exit 0
36
+ fi
18
37
 
19
38
  # ─── Remove hooks from settings.json ──────────────────────
20
39
 
21
40
  if [ -f "$SETTINGS" ] && command -v jq &>/dev/null; then
41
+ settings_backup=$(eagle_backup_user_file "$SETTINGS" 2>/dev/null || true)
22
42
  for event in SessionStart Stop PostToolUse PreToolUse SessionEnd UserPromptSubmit; do
23
43
  if jq -e ".hooks.${event}" "$SETTINGS" &>/dev/null; then
24
44
  tmp=$(mktemp)
@@ -30,16 +50,55 @@ if [ -f "$SETTINGS" ] && command -v jq &>/dev/null; then
30
50
  tmp=$(mktemp)
31
51
  jq 'if .hooks == {} then del(.hooks) else . end' "$SETTINGS" > "$tmp" && mv "$tmp" "$SETTINGS"
32
52
  eagle_ok "Hooks removed from settings.json"
53
+ [ -n "${settings_backup:-}" ] && eagle_dim " Backup: $settings_backup"
33
54
  else
34
55
  eagle_warn "Could not patch settings.json (jq not found or file missing)"
35
56
  fi
36
57
 
58
+ codex_hooks_backup=""
59
+ if [ -f "$EAGLE_CODEX_HOOKS" ]; then
60
+ codex_hooks_backup=$(eagle_backup_user_file "$EAGLE_CODEX_HOOKS" 2>/dev/null || true)
61
+ fi
37
62
  if eagle_remove_codex_hooks; then
38
63
  eagle_ok "Hooks removed from Codex hooks.json"
64
+ [ -n "$codex_hooks_backup" ] && eagle_dim " Backup: $codex_hooks_backup"
39
65
  else
40
66
  eagle_warn "Could not patch Codex hooks.json (jq not found or file missing)"
41
67
  fi
42
68
 
69
+ # ─── Remove instruction blocks and statusline integration ───
70
+
71
+ claude_md="$HOME/.claude/CLAUDE.md"
72
+ if [ -f "$claude_md" ] && grep -qF "## Eagle Mem — Persistent Memory" "$claude_md" 2>/dev/null; then
73
+ claude_md_backup=$(eagle_backup_user_file "$claude_md" 2>/dev/null || true)
74
+ if eagle_remove_marked_markdown_section "$claude_md"; then
75
+ eagle_ok "Eagle Mem block removed from Claude CLAUDE.md"
76
+ [ -n "${claude_md_backup:-}" ] && eagle_dim " Backup: $claude_md_backup"
77
+ else
78
+ eagle_warn "Could not remove Eagle Mem block from Claude CLAUDE.md"
79
+ fi
80
+ else
81
+ eagle_info "Claude CLAUDE.md block not present"
82
+ fi
83
+
84
+ if [ -f "$EAGLE_CODEX_AGENTS_MD" ] && grep -qF "## Eagle Mem — Persistent Memory" "$EAGLE_CODEX_AGENTS_MD" 2>/dev/null; then
85
+ codex_agents_backup=$(eagle_backup_user_file "$EAGLE_CODEX_AGENTS_MD" 2>/dev/null || true)
86
+ if eagle_remove_marked_markdown_section "$EAGLE_CODEX_AGENTS_MD"; then
87
+ eagle_ok "Eagle Mem block removed from Codex AGENTS.md"
88
+ [ -n "${codex_agents_backup:-}" ] && eagle_dim " Backup: $codex_agents_backup"
89
+ else
90
+ eagle_warn "Could not remove Eagle Mem block from Codex AGENTS.md"
91
+ fi
92
+ else
93
+ eagle_info "Codex AGENTS.md block not present"
94
+ fi
95
+
96
+ if eagle_remove_statusline_integration "$SETTINGS"; then
97
+ eagle_ok "Eagle Mem statusline integration removed"
98
+ else
99
+ eagle_info "Statusline integration not present or not auto-removable"
100
+ fi
101
+
43
102
  # ─── Remove skill symlinks ────────────────────────────────
44
103
 
45
104
  if [ -d "$EAGLE_SKILLS_DIR" ]; then
@@ -50,6 +109,14 @@ if [ -d "$EAGLE_SKILLS_DIR" ]; then
50
109
  done
51
110
  fi
52
111
 
112
+ if [ -d "$EAGLE_CODEX_SKILLS_DIR" ]; then
113
+ for target in "$EAGLE_CODEX_SKILLS_DIR"/eagle-mem-*; do
114
+ [ -L "$target" ] || [ -d "$target" ] || continue
115
+ rm -rf "$target"
116
+ eagle_ok "Codex skill removed: $(basename "$target")"
117
+ done
118
+ fi
119
+
53
120
  # ─── Optionally wipe data ─────────────────────────────────
54
121
 
55
122
  if [ -d "$EAGLE_MEM_DIR" ]; then
package/scripts/update.sh CHANGED
@@ -40,6 +40,8 @@ if [ -d "$EAGLE_CODEX_DIR" ] || command -v codex &>/dev/null; then
40
40
  codex_found=true
41
41
  fi
42
42
 
43
+ eagle_runtime_change_plan "update" "$PACKAGE_DIR" "$claude_found" "$codex_found"
44
+
43
45
  # ─── Update files ──────────────────────────────────────────
44
46
 
45
47
  mkdir -p "$EAGLE_MEM_DIR"/{hooks,lib,db,scripts}
@@ -195,7 +197,7 @@ eagle_ok "Auto-updates ${DIM}(mode=$(eagle_update_config_mode), allow=$(eagle_up
195
197
 
196
198
  if [ "$claude_found" = true ]; then
197
199
  if eagle_patch_claude_md; then
198
- eagle_ok "CLAUDE.md updated ${DIM}(eagle-summary instructions added)${RESET}"
200
+ eagle_ok "CLAUDE.md updated ${DIM}(Eagle Mem guidance refreshed)${RESET}"
199
201
  else
200
202
  eagle_ok "CLAUDE.md up to date"
201
203
  fi
@@ -214,5 +216,10 @@ fi
214
216
  version=$(jq -r .version "$PACKAGE_DIR/package.json" 2>/dev/null || echo "unknown")
215
217
  echo "$version" > "$EAGLE_MEM_DIR/.version"
216
218
  echo "$version" > "$EAGLE_MEM_DIR/.latest-version"
219
+ if eagle_runtime_manifest_write "$PACKAGE_DIR" "update"; then
220
+ eagle_ok "Install manifest refreshed"
221
+ else
222
+ eagle_warn "Install manifest could not be refreshed"
223
+ fi
217
224
 
218
225
  eagle_footer "Eagle Mem updated to v${version}."