eagle-mem 4.9.7 → 4.9.9
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/hooks/post-tool-use.sh +15 -10
- package/hooks/pre-tool-use.sh +2 -10
- package/hooks/session-start.sh +39 -19
- package/hooks/stop.sh +2 -6
- package/hooks/user-prompt-submit.sh +40 -6
- package/lib/common.sh +133 -14
- package/lib/db-features.sh +10 -10
- package/lib/db-mirrors.sh +6 -12
- package/lib/db-sessions.sh +22 -15
- package/lib/db-summaries.sh +9 -6
- package/lib/hooks-posttool.sh +0 -25
- package/lib/hooks.sh +12 -0
- package/package.json +1 -1
- package/scripts/feature.sh +22 -15
- package/scripts/install.sh +7 -15
- package/scripts/memories.sh +72 -13
- package/scripts/search.sh +45 -25
- package/scripts/statusline-em.sh +5 -4
- package/scripts/update.sh +5 -10
- package/skills/eagle-mem-feature/SKILL.md +123 -0
package/lib/db-sessions.sh
CHANGED
|
@@ -167,24 +167,31 @@ eagle_abandon_stale_sessions() {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
eagle_get_project_stats() {
|
|
170
|
-
local
|
|
170
|
+
local project_scope="${1:-}"
|
|
171
|
+
local session_filter memory_filter plan_filter task_filter chunk_filter observation_filter
|
|
172
|
+
session_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
173
|
+
memory_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
174
|
+
plan_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
175
|
+
task_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
176
|
+
chunk_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
177
|
+
observation_filter=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
171
178
|
eagle_db_pipe <<SQL
|
|
172
|
-
SELECT 'sessions|' || COUNT(*) FROM sessions WHERE
|
|
173
|
-
SELECT 'sessions_claude|' || COUNT(*) FROM sessions WHERE
|
|
174
|
-
SELECT 'sessions_codex|' || COUNT(*) FROM sessions WHERE
|
|
175
|
-
SELECT 'summaries|' || COUNT(*) FROM summaries WHERE
|
|
176
|
-
SELECT 'with_summaries|' || COUNT(*) FROM summaries WHERE
|
|
177
|
-
SELECT 'memories|' || COUNT(*) FROM agent_memories WHERE
|
|
178
|
-
SELECT 'plans|' || COUNT(*) FROM agent_plans WHERE
|
|
179
|
-
SELECT 'tasks_pending|' || COUNT(*) FROM agent_tasks WHERE
|
|
180
|
-
SELECT 'tasks_progress|' || COUNT(*) FROM agent_tasks WHERE
|
|
181
|
-
SELECT 'tasks_done|' || COUNT(*) FROM agent_tasks WHERE
|
|
182
|
-
SELECT 'chunks|' || COUNT(*) FROM code_chunks WHERE
|
|
183
|
-
SELECT 'observations|' || COUNT(*) FROM observations WHERE
|
|
184
|
-
SELECT 'last_active|' || COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE
|
|
179
|
+
SELECT 'sessions|' || COUNT(*) FROM sessions WHERE $session_filter;
|
|
180
|
+
SELECT 'sessions_claude|' || COUNT(*) FROM sessions WHERE $session_filter AND agent = 'claude-code';
|
|
181
|
+
SELECT 'sessions_codex|' || COUNT(*) FROM sessions WHERE $session_filter AND agent = 'codex';
|
|
182
|
+
SELECT 'summaries|' || COUNT(*) FROM summaries WHERE $session_filter;
|
|
183
|
+
SELECT 'with_summaries|' || COUNT(*) FROM summaries WHERE $session_filter AND request IS NOT NULL AND request != '';
|
|
184
|
+
SELECT 'memories|' || COUNT(*) FROM agent_memories WHERE $memory_filter;
|
|
185
|
+
SELECT 'plans|' || COUNT(*) FROM agent_plans WHERE $plan_filter;
|
|
186
|
+
SELECT 'tasks_pending|' || COUNT(*) FROM agent_tasks WHERE $task_filter AND status = 'pending';
|
|
187
|
+
SELECT 'tasks_progress|' || COUNT(*) FROM agent_tasks WHERE $task_filter AND status = 'in_progress';
|
|
188
|
+
SELECT 'tasks_done|' || COUNT(*) FROM agent_tasks WHERE $task_filter AND status = 'completed';
|
|
189
|
+
SELECT 'chunks|' || COUNT(*) FROM code_chunks WHERE $chunk_filter;
|
|
190
|
+
SELECT 'observations|' || COUNT(*) FROM observations WHERE $observation_filter;
|
|
191
|
+
SELECT 'last_active|' || COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE $session_filter;
|
|
185
192
|
SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60)
|
|
186
193
|
FROM summaries
|
|
187
|
-
WHERE
|
|
194
|
+
WHERE $session_filter
|
|
188
195
|
AND COALESCE(request, '') NOT LIKE '# AGENTS.md instructions%'
|
|
189
196
|
AND COALESCE(request, '') NOT LIKE '<environment_context>%'
|
|
190
197
|
ORDER BY created_at DESC
|
package/lib/db-summaries.sh
CHANGED
|
@@ -57,12 +57,16 @@ SQL
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
eagle_get_recent_summaries() {
|
|
60
|
-
local
|
|
60
|
+
local project_scope="${1:-}"
|
|
61
61
|
local limit; limit=$(eagle_sql_int "${2:-5}")
|
|
62
|
+
local project_filter="1 = 1"
|
|
63
|
+
if [ -n "$project_scope" ]; then
|
|
64
|
+
project_filter=$(eagle_sql_project_scope_condition "s.project" "$project_scope")
|
|
65
|
+
fi
|
|
62
66
|
|
|
63
67
|
eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.decisions, s.gotchas, s.key_files, s.agent
|
|
64
68
|
FROM summaries s
|
|
65
|
-
WHERE
|
|
69
|
+
WHERE $project_filter
|
|
66
70
|
AND COALESCE(s.request, '') NOT LIKE '%<local-command-caveat>%'
|
|
67
71
|
AND COALESCE(s.request, '') NOT LIKE '# AGENTS.md instructions%'
|
|
68
72
|
AND COALESCE(s.request, '') NOT LIKE '<environment_context>%'
|
|
@@ -73,13 +77,12 @@ eagle_get_recent_summaries() {
|
|
|
73
77
|
eagle_search_summaries() {
|
|
74
78
|
local query; query=$(eagle_fts_sanitize "$1")
|
|
75
79
|
query=$(eagle_sql_escape "$query")
|
|
76
|
-
local
|
|
80
|
+
local project_scope="${2:-}"
|
|
77
81
|
local limit; limit=$(eagle_sql_int "${3:-10}")
|
|
78
82
|
|
|
79
83
|
local where_clause=""
|
|
80
|
-
if [ -n "$
|
|
81
|
-
|
|
82
|
-
where_clause="AND s.project = '$project'"
|
|
84
|
+
if [ -n "$project_scope" ]; then
|
|
85
|
+
where_clause="AND $(eagle_sql_project_scope_condition "s.project" "$project_scope")"
|
|
83
86
|
fi
|
|
84
87
|
|
|
85
88
|
eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.project, s.decisions, s.gotchas, s.key_files, s.agent
|
package/lib/hooks-posttool.sh
CHANGED
|
@@ -33,31 +33,6 @@ eagle_posttool_mirror_writes() {
|
|
|
33
33
|
esac
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
eagle_posttool_mirror_tasks() {
|
|
37
|
-
local tool_name="$1" session_id="$2" project="$3" input="$4"
|
|
38
|
-
local agent="${5:-$(eagle_agent_source)}"
|
|
39
|
-
|
|
40
|
-
case "$tool_name" in
|
|
41
|
-
TaskCreate|TaskUpdate)
|
|
42
|
-
if eagle_validate_session_id "$session_id"; then
|
|
43
|
-
local task_dir="$EAGLE_CLAUDE_TASKS_DIR/$session_id"
|
|
44
|
-
if [ -d "$task_dir" ]; then
|
|
45
|
-
local task_id
|
|
46
|
-
task_id=$(echo "$input" | jq -r '.tool_input.id // empty')
|
|
47
|
-
if [ -z "$task_id" ]; then
|
|
48
|
-
local newest
|
|
49
|
-
newest=$(ls -t "$task_dir"/*.json 2>/dev/null | head -1)
|
|
50
|
-
[ -n "$newest" ] && [ -f "$newest" ] && eagle_capture_agent_task "$newest" "$session_id" "$project" "$agent"
|
|
51
|
-
elif eagle_validate_session_id "$task_id"; then
|
|
52
|
-
local task_json="$task_dir/$task_id.json"
|
|
53
|
-
[ -f "$task_json" ] && eagle_capture_agent_task "$task_json" "$session_id" "$project" "$agent"
|
|
54
|
-
fi
|
|
55
|
-
fi
|
|
56
|
-
fi
|
|
57
|
-
;;
|
|
58
|
-
esac
|
|
59
|
-
}
|
|
60
|
-
|
|
61
36
|
eagle_posttool_stale_hint() {
|
|
62
37
|
local tool_name="$1" fp="$2" project="$3"
|
|
63
38
|
local agent="${4:-$(eagle_agent_source)}"
|
package/lib/hooks.sh
CHANGED
|
@@ -4,6 +4,18 @@
|
|
|
4
4
|
# Shared by install.sh and update.sh
|
|
5
5
|
# ═══════════════════════════════════════════════════════════
|
|
6
6
|
|
|
7
|
+
eagle_clean_hook_entries() {
|
|
8
|
+
local settings="$1"
|
|
9
|
+
local event="$2"
|
|
10
|
+
local command="$3"
|
|
11
|
+
|
|
12
|
+
local tmp
|
|
13
|
+
tmp=$(mktemp)
|
|
14
|
+
jq --arg cmd "$command" \
|
|
15
|
+
".hooks.${event} = ((.hooks.${event} // []) | map(select(.hooks | all(.command != \$cmd))))" \
|
|
16
|
+
"$settings" > "$tmp" && mv "$tmp" "$settings"
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
eagle_patch_hook() {
|
|
8
20
|
local settings="$1"
|
|
9
21
|
local event="$2"
|
package/package.json
CHANGED
package/scripts/feature.sh
CHANGED
|
@@ -125,13 +125,7 @@ case "$subcommand" in
|
|
|
125
125
|
|
|
126
126
|
waive)
|
|
127
127
|
id="${1:-}"
|
|
128
|
-
[ -z "$id" ] && { eagle_err "Usage: eagle-mem feature waive <id> --reason <text>"; exit 1; }
|
|
129
|
-
case "$id" in
|
|
130
|
-
*[!0-9]*)
|
|
131
|
-
eagle_err "Invalid ID: '$id' (must be numeric)"
|
|
132
|
-
exit 1
|
|
133
|
-
;;
|
|
134
|
-
esac
|
|
128
|
+
[ -z "$id" ] && { eagle_err "Usage: eagle-mem feature waive <id|name> --reason <text>"; exit 1; }
|
|
135
129
|
shift
|
|
136
130
|
reason=""
|
|
137
131
|
while [ $# -gt 0 ]; do
|
|
@@ -147,14 +141,27 @@ case "$subcommand" in
|
|
|
147
141
|
*) reason="$1"; shift ;;
|
|
148
142
|
esac
|
|
149
143
|
done
|
|
150
|
-
[ -z "$reason" ] && { eagle_err "Usage: eagle-mem feature waive <id> --reason <text>"; exit 1; }
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
144
|
+
[ -z "$reason" ] && { eagle_err "Usage: eagle-mem feature waive <id|name> --reason <text>"; exit 1; }
|
|
145
|
+
case "$id" in
|
|
146
|
+
*[!0-9]*)
|
|
147
|
+
waived=$(eagle_resolve_pending_feature_verifications "$project" "$id" "waived" "$reason" | tail -1)
|
|
148
|
+
if [ "${waived:-0}" -gt 0 ] 2>/dev/null; then
|
|
149
|
+
eagle_ok "Waived $waived pending verification(s) for '$id'"
|
|
150
|
+
else
|
|
151
|
+
eagle_err "No pending verifications found for feature '$id'"
|
|
152
|
+
exit 1
|
|
153
|
+
fi
|
|
154
|
+
;;
|
|
155
|
+
*)
|
|
156
|
+
waived=$(eagle_waive_pending_feature_verification "$project" "$id" "$reason" | tail -1)
|
|
157
|
+
if [ "${waived:-0}" -gt 0 ] 2>/dev/null; then
|
|
158
|
+
eagle_ok "Pending verification #$id waived"
|
|
159
|
+
else
|
|
160
|
+
eagle_err "No pending verification found with ID $id"
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
;;
|
|
164
|
+
esac
|
|
158
165
|
;;
|
|
159
166
|
|
|
160
167
|
add)
|
package/scripts/install.sh
CHANGED
|
@@ -226,7 +226,11 @@ if [ "$claude_found" = true ]; then
|
|
|
226
226
|
"$EAGLE_MEM_DIR/hooks/stop.sh" \
|
|
227
227
|
"Stop hook"
|
|
228
228
|
|
|
229
|
-
|
|
229
|
+
# Clean old registrations before re-registering (handles matcher changes across versions)
|
|
230
|
+
eagle_clean_hook_entries "$SETTINGS" "PostToolUse" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
231
|
+
eagle_clean_hook_entries "$SETTINGS" "PreToolUse" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
232
|
+
|
|
233
|
+
eagle_patch_hook "$SETTINGS" "PostToolUse" "Read|Write|Edit|Bash|TaskUpdate" \
|
|
230
234
|
"$EAGLE_MEM_DIR/hooks/post-tool-use.sh" \
|
|
231
235
|
"PostToolUse hook"
|
|
232
236
|
|
|
@@ -246,21 +250,9 @@ if [ "$claude_found" = true ]; then
|
|
|
246
250
|
"$EAGLE_MEM_DIR/hooks/user-prompt-submit.sh" \
|
|
247
251
|
"UserPromptSubmit hook"
|
|
248
252
|
|
|
249
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash" \
|
|
250
|
-
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
251
|
-
"PreToolUse hook (Bash)"
|
|
252
|
-
|
|
253
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Read" \
|
|
254
|
-
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
255
|
-
"PreToolUse hook (Read)"
|
|
256
|
-
|
|
257
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Edit" \
|
|
258
|
-
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
259
|
-
"PreToolUse hook (Edit)"
|
|
260
|
-
|
|
261
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Write" \
|
|
253
|
+
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash|Read|Edit|Write" \
|
|
262
254
|
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
263
|
-
"PreToolUse hook
|
|
255
|
+
"PreToolUse hook"
|
|
264
256
|
else
|
|
265
257
|
eagle_info "Claude hooks skipped ${DIM}(Claude Code not detected)${RESET}"
|
|
266
258
|
fi
|
package/scripts/memories.sh
CHANGED
|
@@ -24,6 +24,7 @@ case "${1:-}" in
|
|
|
24
24
|
esac
|
|
25
25
|
|
|
26
26
|
project=""
|
|
27
|
+
project_was_explicit=false
|
|
27
28
|
limit=20
|
|
28
29
|
query=""
|
|
29
30
|
raw_output=false
|
|
@@ -76,7 +77,7 @@ esac
|
|
|
76
77
|
|
|
77
78
|
while [ $# -gt 0 ]; do
|
|
78
79
|
case "$1" in
|
|
79
|
-
--project|-p) project="$2"; shift 2 ;;
|
|
80
|
+
--project|-p) project="$2"; project_was_explicit=true; shift 2 ;;
|
|
80
81
|
--limit|-l) limit="$2"; shift 2 ;;
|
|
81
82
|
--all|-a) cross_project=true; shift ;;
|
|
82
83
|
--raw|--debug) raw_output=true; shift ;;
|
|
@@ -95,6 +96,9 @@ done
|
|
|
95
96
|
if [ -z "$project" ] && [ "$cross_project" = false ]; then
|
|
96
97
|
project=$(eagle_project_from_cwd "$(pwd)")
|
|
97
98
|
fi
|
|
99
|
+
if [ "$cross_project" = false ] && [ "$project_was_explicit" = false ]; then
|
|
100
|
+
project=$(eagle_recall_project_scope_from_cwd "$(pwd)" "$project")
|
|
101
|
+
fi
|
|
98
102
|
|
|
99
103
|
eagle_age_label() {
|
|
100
104
|
local updated="${1:-}"
|
|
@@ -230,7 +234,7 @@ memories_show() {
|
|
|
230
234
|
query_sql=$(eagle_sql_escape "$query")
|
|
231
235
|
project_filter=""
|
|
232
236
|
if [ -n "$project" ]; then
|
|
233
|
-
project_filter="AND
|
|
237
|
+
project_filter="AND $(eagle_sql_project_scope_condition "project" "$project")"
|
|
234
238
|
fi
|
|
235
239
|
|
|
236
240
|
meta_json=$(eagle_db_json "SELECT memory_name, memory_type, description, content, file_path, updated_at, origin_session_id, origin_agent
|
|
@@ -370,7 +374,7 @@ plans_show() {
|
|
|
370
374
|
query_sql=$(eagle_sql_escape "$query")
|
|
371
375
|
project_filter=""
|
|
372
376
|
if [ -n "$project" ]; then
|
|
373
|
-
project_filter="AND
|
|
377
|
+
project_filter="AND $(eagle_sql_project_scope_condition "project" "$project")"
|
|
374
378
|
fi
|
|
375
379
|
meta_json=$(eagle_db_json "SELECT title, project, content, file_path, updated_at, origin_session_id, origin_agent
|
|
376
380
|
FROM agent_plans
|
|
@@ -517,7 +521,7 @@ tasks_show() {
|
|
|
517
521
|
query_sql=$(eagle_sql_escape "$query")
|
|
518
522
|
project_filter=""
|
|
519
523
|
if [ -n "$project" ]; then
|
|
520
|
-
project_filter="AND
|
|
524
|
+
project_filter="AND $(eagle_sql_project_scope_condition "project" "$project")"
|
|
521
525
|
fi
|
|
522
526
|
meta_json=$(eagle_db_json "SELECT subject, status, description, active_form, source_session_id, source_task_id, file_path, updated_at, origin_agent
|
|
523
527
|
FROM agent_tasks
|
|
@@ -575,6 +579,33 @@ tasks_show() {
|
|
|
575
579
|
memories_sync() {
|
|
576
580
|
eagle_header "Memory, Plan & Task Sync"
|
|
577
581
|
|
|
582
|
+
local lock_root="$EAGLE_MEM_DIR/locks"
|
|
583
|
+
local lock_dir="$lock_root/memories-sync.lock"
|
|
584
|
+
mkdir -p "$lock_root" 2>/dev/null || true
|
|
585
|
+
if mkdir "$lock_dir" 2>/dev/null; then
|
|
586
|
+
printf '%s\n' "$$" > "$lock_dir/pid" 2>/dev/null || true
|
|
587
|
+
_EAGLE_MEMORIES_SYNC_LOCK_DIR="$lock_dir"
|
|
588
|
+
trap 'rm -rf "${_EAGLE_MEMORIES_SYNC_LOCK_DIR:-}" 2>/dev/null || true' EXIT
|
|
589
|
+
else
|
|
590
|
+
local lock_pid=""
|
|
591
|
+
[ -f "$lock_dir/pid" ] && lock_pid=$(cat "$lock_dir/pid" 2>/dev/null | tr -cd '0-9')
|
|
592
|
+
if [ -n "$lock_pid" ] && kill -0 "$lock_pid" 2>/dev/null; then
|
|
593
|
+
eagle_info "Sync already running (pid $lock_pid). Skipping this duplicate run."
|
|
594
|
+
echo ""
|
|
595
|
+
eagle_footer "Sync skipped."
|
|
596
|
+
return 0
|
|
597
|
+
fi
|
|
598
|
+
rm -rf "$lock_dir" 2>/dev/null || true
|
|
599
|
+
if mkdir "$lock_dir" 2>/dev/null; then
|
|
600
|
+
printf '%s\n' "$$" > "$lock_dir/pid" 2>/dev/null || true
|
|
601
|
+
_EAGLE_MEMORIES_SYNC_LOCK_DIR="$lock_dir"
|
|
602
|
+
trap 'rm -rf "${_EAGLE_MEMORIES_SYNC_LOCK_DIR:-}" 2>/dev/null || true' EXIT
|
|
603
|
+
else
|
|
604
|
+
eagle_err "Could not acquire memories sync lock."
|
|
605
|
+
return 1
|
|
606
|
+
fi
|
|
607
|
+
fi
|
|
608
|
+
|
|
578
609
|
# ─── Sync memories ───────────────────────────────────
|
|
579
610
|
eagle_info "Scanning for agent memory files..."
|
|
580
611
|
echo ""
|
|
@@ -583,15 +614,21 @@ memories_sync() {
|
|
|
583
614
|
local mem_synced=0
|
|
584
615
|
local mem_skipped=0
|
|
585
616
|
|
|
586
|
-
|
|
587
|
-
|
|
617
|
+
sync_one_memory_file() {
|
|
618
|
+
local memfile="$1"
|
|
619
|
+
[ -f "$memfile" ] || return 0
|
|
620
|
+
|
|
588
621
|
local base
|
|
589
622
|
base=$(basename "$memfile")
|
|
590
|
-
[ "$base" = "MEMORY.md" ] &&
|
|
623
|
+
[ "$base" = "MEMORY.md" ] && return 0
|
|
591
624
|
|
|
592
625
|
local mem_project mem_project_dir existing_row existing_hash existing_project
|
|
593
626
|
mem_project_dir="${memfile%/memory/*}"
|
|
594
627
|
mem_project=$(eagle_project_from_claude_project_dir "$mem_project_dir" 2>/dev/null || true)
|
|
628
|
+
if [ "$cross_project" = false ] && [ -n "$project" ]; then
|
|
629
|
+
eagle_project_scope_contains "$project" "$mem_project" || return 0
|
|
630
|
+
fi
|
|
631
|
+
|
|
595
632
|
existing_row=$(eagle_db "SELECT content_hash, project FROM agent_memories WHERE file_path = '$(eagle_sql_escape "$memfile")';")
|
|
596
633
|
IFS='|' read -r existing_hash existing_project <<< "$existing_row"
|
|
597
634
|
local new_hash
|
|
@@ -605,7 +642,25 @@ memories_sync() {
|
|
|
605
642
|
eagle_capture_agent_memory "$memfile" "" "$mem_project" "claude-code"
|
|
606
643
|
mem_synced=$((mem_synced + 1))
|
|
607
644
|
eagle_ok "Memory: $base"
|
|
608
|
-
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if [ -d "$claude_mem_root" ]; then
|
|
648
|
+
if [ "$cross_project" = true ] || [ -z "$project" ]; then
|
|
649
|
+
while IFS= read -r -d '' memfile; do
|
|
650
|
+
sync_one_memory_file "$memfile"
|
|
651
|
+
done < <(find "$claude_mem_root" -path "*/memory/*.md" -print0 2>/dev/null)
|
|
652
|
+
else
|
|
653
|
+
while IFS= read -r scope_project; do
|
|
654
|
+
[ -z "$scope_project" ] && continue
|
|
655
|
+
scope_dir=$(eagle_claude_project_dir_for_key "$scope_project")
|
|
656
|
+
[ -d "$scope_dir/memory" ] || continue
|
|
657
|
+
while IFS= read -r -d '' memfile; do
|
|
658
|
+
sync_one_memory_file "$memfile"
|
|
659
|
+
done < <(find "$scope_dir/memory" -maxdepth 1 -type f -name "*.md" -print0 2>/dev/null)
|
|
660
|
+
done <<EOF
|
|
661
|
+
$(printf '%s' "$project" | tr '|' '\n')
|
|
662
|
+
EOF
|
|
663
|
+
fi
|
|
609
664
|
fi
|
|
610
665
|
|
|
611
666
|
local codex_mem_root="$EAGLE_CODEX_MEMORIES_DIR"
|
|
@@ -710,12 +765,16 @@ memories_sync() {
|
|
|
710
765
|
# ─── Backfill project names ──────────────────────────
|
|
711
766
|
eagle_info "Resolving project names from agent transcripts..."
|
|
712
767
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
768
|
+
if [ "$cross_project" = true ]; then
|
|
769
|
+
local backfilled
|
|
770
|
+
backfilled=$(eagle_backfill_projects)
|
|
771
|
+
if [ "${backfilled:-0}" -gt 0 ]; then
|
|
772
|
+
eagle_ok "$backfilled rows updated with correct project names"
|
|
773
|
+
else
|
|
774
|
+
eagle_ok "All project names up to date"
|
|
775
|
+
fi
|
|
717
776
|
else
|
|
718
|
-
eagle_ok "
|
|
777
|
+
eagle_ok "Scoped sync complete; use --all for global transcript backfill"
|
|
719
778
|
fi
|
|
720
779
|
|
|
721
780
|
eagle_footer "Sync complete."
|
package/scripts/search.sh
CHANGED
|
@@ -43,6 +43,9 @@ show_help() {
|
|
|
43
43
|
|
|
44
44
|
mode="keyword"
|
|
45
45
|
project=""
|
|
46
|
+
project_was_explicit=false
|
|
47
|
+
project_scope=""
|
|
48
|
+
project_label=""
|
|
46
49
|
limit=10
|
|
47
50
|
session_id=""
|
|
48
51
|
json_output=false
|
|
@@ -59,7 +62,7 @@ while [ $# -gt 0 ]; do
|
|
|
59
62
|
--overview|-o) mode="overview"; shift ;;
|
|
60
63
|
--memories|-m) mode="memories"; shift ;;
|
|
61
64
|
--tasks) mode="tasks"; shift ;;
|
|
62
|
-
--project|-p) project="$2"; shift 2 ;;
|
|
65
|
+
--project|-p) project="$2"; project_was_explicit=true; shift 2 ;;
|
|
63
66
|
--limit|-n) limit="$2"; shift 2 ;;
|
|
64
67
|
--all|-a) cross_project=true; shift ;;
|
|
65
68
|
--json|-j) json_output=true; shift ;;
|
|
@@ -75,6 +78,12 @@ while [ $# -gt 0 ]; do
|
|
|
75
78
|
done
|
|
76
79
|
|
|
77
80
|
[ -z "$project" ] && project=$(eagle_project_from_cwd "$(pwd)")
|
|
81
|
+
project_scope="$project"
|
|
82
|
+
if [ "$cross_project" = false ] && [ "$project_was_explicit" = false ]; then
|
|
83
|
+
project_scope=$(eagle_recall_project_scope_from_cwd "$(pwd)" "$project")
|
|
84
|
+
fi
|
|
85
|
+
project_label=$(eagle_project_scope_label "$project_scope")
|
|
86
|
+
[ -z "$project_label" ] && project_label="$project"
|
|
78
87
|
limit=$(eagle_sql_int "$limit")
|
|
79
88
|
[ "$limit" -eq 0 ] && limit=10
|
|
80
89
|
|
|
@@ -88,11 +97,12 @@ search_keyword() {
|
|
|
88
97
|
exit 1
|
|
89
98
|
fi
|
|
90
99
|
local q; q=$(eagle_sql_escape "$sanitized_q")
|
|
91
|
-
local
|
|
100
|
+
local project_condition
|
|
101
|
+
project_condition=$(eagle_sql_project_scope_condition "s.project" "$project_scope")
|
|
92
102
|
|
|
93
103
|
local where_project=""
|
|
94
104
|
if [ "$cross_project" = false ]; then
|
|
95
|
-
where_project="AND
|
|
105
|
+
where_project="AND $project_condition"
|
|
96
106
|
fi
|
|
97
107
|
|
|
98
108
|
if [ "$json_output" = true ]; then
|
|
@@ -173,12 +183,13 @@ search_keyword() {
|
|
|
173
183
|
# ─── Timeline ────────────────────────────────────────────
|
|
174
184
|
|
|
175
185
|
search_timeline() {
|
|
176
|
-
local
|
|
186
|
+
local project_condition
|
|
187
|
+
project_condition=$(eagle_sql_project_scope_condition "s.project" "$project_scope")
|
|
177
188
|
|
|
178
189
|
if [ "$json_output" = true ]; then
|
|
179
190
|
eagle_db_json "SELECT s.id, s.agent, s.request, s.completed, s.learned, s.next_steps, s.created_at
|
|
180
191
|
FROM summaries s
|
|
181
|
-
WHERE
|
|
192
|
+
WHERE $project_condition
|
|
182
193
|
ORDER BY s.created_at DESC
|
|
183
194
|
LIMIT $limit;"
|
|
184
195
|
return
|
|
@@ -187,7 +198,7 @@ search_timeline() {
|
|
|
187
198
|
local results
|
|
188
199
|
results=$(eagle_db "SELECT s.id, s.agent, s.request, s.completed, s.learned, s.next_steps, s.created_at
|
|
189
200
|
FROM summaries s
|
|
190
|
-
WHERE
|
|
201
|
+
WHERE $project_condition
|
|
191
202
|
ORDER BY s.created_at DESC
|
|
192
203
|
LIMIT $limit;")
|
|
193
204
|
|
|
@@ -197,7 +208,7 @@ search_timeline() {
|
|
|
197
208
|
fi
|
|
198
209
|
|
|
199
210
|
echo ""
|
|
200
|
-
echo -e " ${BOLD}Recent sessions${RESET} ${DIM}($
|
|
211
|
+
echo -e " ${BOLD}Recent sessions${RESET} ${DIM}($project_label)${RESET}"
|
|
201
212
|
echo -e " ${DIM}─────────────────────────────────────${RESET}"
|
|
202
213
|
echo ""
|
|
203
214
|
|
|
@@ -401,20 +412,25 @@ search_files() {
|
|
|
401
412
|
# ─── Stats ────────────────────────────────────────────────
|
|
402
413
|
|
|
403
414
|
search_stats() {
|
|
404
|
-
local
|
|
415
|
+
local sessions_condition summaries_condition observations_condition tasks_condition chunks_condition
|
|
416
|
+
sessions_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
417
|
+
summaries_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
418
|
+
observations_condition=$(eagle_sql_project_scope_condition "s.project" "$project_scope")
|
|
419
|
+
tasks_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
420
|
+
chunks_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
405
421
|
|
|
406
422
|
local sessions sessions_claude sessions_codex summaries observations tasks
|
|
407
|
-
sessions=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE
|
|
408
|
-
sessions_claude=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE
|
|
409
|
-
sessions_codex=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE
|
|
410
|
-
summaries=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE
|
|
411
|
-
observations=$(eagle_db "SELECT COUNT(*) FROM observations o JOIN sessions s ON s.id = o.session_id WHERE
|
|
412
|
-
tasks=$(eagle_db "SELECT COUNT(*) FROM agent_tasks WHERE
|
|
423
|
+
sessions=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE $sessions_condition;")
|
|
424
|
+
sessions_claude=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE $sessions_condition AND agent = 'claude-code';")
|
|
425
|
+
sessions_codex=$(eagle_db "SELECT COUNT(*) FROM sessions WHERE $sessions_condition AND agent = 'codex';")
|
|
426
|
+
summaries=$(eagle_db "SELECT COUNT(*) FROM summaries WHERE $summaries_condition;")
|
|
427
|
+
observations=$(eagle_db "SELECT COUNT(*) FROM observations o JOIN sessions s ON s.id = o.session_id WHERE $observations_condition;")
|
|
428
|
+
tasks=$(eagle_db "SELECT COUNT(*) FROM agent_tasks WHERE $tasks_condition;")
|
|
413
429
|
local chunks
|
|
414
|
-
chunks=$(eagle_db "SELECT COUNT(*) FROM code_chunks WHERE
|
|
430
|
+
chunks=$(eagle_db "SELECT COUNT(*) FROM code_chunks WHERE $chunks_condition;")
|
|
415
431
|
|
|
416
432
|
if [ "$json_output" = true ]; then
|
|
417
|
-
jq -nc --arg project "$
|
|
433
|
+
jq -nc --arg project "$project_label" \
|
|
418
434
|
--argjson sessions "${sessions:-0}" \
|
|
419
435
|
--argjson sessions_claude "${sessions_claude:-0}" \
|
|
420
436
|
--argjson sessions_codex "${sessions_codex:-0}" \
|
|
@@ -427,7 +443,7 @@ search_stats() {
|
|
|
427
443
|
fi
|
|
428
444
|
|
|
429
445
|
echo ""
|
|
430
|
-
echo -e " ${BOLD}Stats${RESET} ${DIM}($
|
|
446
|
+
echo -e " ${BOLD}Stats${RESET} ${DIM}($project_label)${RESET}"
|
|
431
447
|
echo -e " ${DIM}─────────────────────────────────────${RESET}"
|
|
432
448
|
echo ""
|
|
433
449
|
eagle_kv "Sessions:" "${sessions:-0}"
|
|
@@ -474,11 +490,13 @@ search_overview() {
|
|
|
474
490
|
# ─── Memories ────────────────────────────────────────────
|
|
475
491
|
|
|
476
492
|
search_memories() {
|
|
477
|
-
local
|
|
493
|
+
local project_condition memory_condition
|
|
494
|
+
project_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
495
|
+
memory_condition=$(eagle_sql_project_scope_condition "m.project" "$project_scope")
|
|
478
496
|
|
|
479
497
|
local where_project=""
|
|
480
498
|
if [ "$cross_project" = false ]; then
|
|
481
|
-
where_project="WHERE
|
|
499
|
+
where_project="WHERE $project_condition"
|
|
482
500
|
fi
|
|
483
501
|
|
|
484
502
|
if [ -n "$query" ]; then
|
|
@@ -491,7 +509,7 @@ search_memories() {
|
|
|
491
509
|
local q; q=$(eagle_sql_escape "$sanitized_mq")
|
|
492
510
|
local where_match="WHERE agent_memories_fts MATCH '$q'"
|
|
493
511
|
if [ "$cross_project" = false ]; then
|
|
494
|
-
where_match="$where_match AND
|
|
512
|
+
where_match="$where_match AND $memory_condition"
|
|
495
513
|
fi
|
|
496
514
|
|
|
497
515
|
if [ "$json_output" = true ]; then
|
|
@@ -570,7 +588,7 @@ search_memories() {
|
|
|
570
588
|
fi
|
|
571
589
|
|
|
572
590
|
echo ""
|
|
573
|
-
echo -e " ${BOLD}Memories${RESET} ${DIM}($
|
|
591
|
+
echo -e " ${BOLD}Memories${RESET} ${DIM}($project_label)${RESET}"
|
|
574
592
|
echo -e " ${DIM}─────────────────────────────────────${RESET}"
|
|
575
593
|
echo ""
|
|
576
594
|
|
|
@@ -585,13 +603,15 @@ search_memories() {
|
|
|
585
603
|
# ─── Tasks ───────────────────────────────────────────────
|
|
586
604
|
|
|
587
605
|
search_tasks() {
|
|
588
|
-
local
|
|
606
|
+
local task_condition bare_task_condition
|
|
607
|
+
task_condition=$(eagle_sql_project_scope_condition "t.project" "$project_scope")
|
|
608
|
+
bare_task_condition=$(eagle_sql_project_scope_condition "project" "$project_scope")
|
|
589
609
|
|
|
590
610
|
local where_project=""
|
|
591
611
|
local where_task_project=""
|
|
592
612
|
if [ "$cross_project" = false ]; then
|
|
593
|
-
where_project="AND
|
|
594
|
-
where_task_project="AND
|
|
613
|
+
where_project="AND $bare_task_condition"
|
|
614
|
+
where_task_project="AND $task_condition"
|
|
595
615
|
fi
|
|
596
616
|
|
|
597
617
|
if [ -n "$query" ]; then
|
|
@@ -662,7 +682,7 @@ search_tasks() {
|
|
|
662
682
|
LIMIT $limit;")
|
|
663
683
|
|
|
664
684
|
if [ -z "$results" ]; then
|
|
665
|
-
eagle_dim "No active tasks for project '$
|
|
685
|
+
eagle_dim "No active tasks for project '$project_label'"
|
|
666
686
|
return
|
|
667
687
|
fi
|
|
668
688
|
|
package/scripts/statusline-em.sh
CHANGED
|
@@ -58,17 +58,18 @@ eagle_mem_statusline_stats() {
|
|
|
58
58
|
[ -z "$project_dir" ] && project_dir="$(pwd)"
|
|
59
59
|
[ -z "$current_dir" ] && current_dir="$project_dir"
|
|
60
60
|
|
|
61
|
-
local project_key
|
|
61
|
+
local project_key project_scope project_condition stats sessions memories last_raw turns version latest
|
|
62
62
|
project_key=$(eagle_project_from_statusline_input "$statusline_input" "$project_dir" "$current_dir" "$session_id")
|
|
63
63
|
[ -n "$project_key" ] || return
|
|
64
|
-
|
|
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")
|
|
65
66
|
|
|
66
67
|
stats=$("$sqlite_bin" "$em_db" "SELECT
|
|
67
68
|
COUNT(*) || '|' ||
|
|
68
|
-
(SELECT COUNT(*) FROM agent_memories WHERE
|
|
69
|
+
(SELECT COUNT(*) FROM agent_memories WHERE $project_condition) || '|' ||
|
|
69
70
|
COALESCE(MAX(COALESCE(last_activity_at, started_at)), 'never')
|
|
70
71
|
FROM sessions
|
|
71
|
-
WHERE
|
|
72
|
+
WHERE $project_condition;" 2>/dev/null)
|
|
72
73
|
IFS='|' read -r sessions memories last_raw <<< "${stats:-0|0|never}"
|
|
73
74
|
sessions=${sessions:-0}
|
|
74
75
|
memories=${memories:-0}
|
package/scripts/update.sh
CHANGED
|
@@ -76,23 +76,18 @@ fi
|
|
|
76
76
|
# ─── Re-register hooks (idempotent) ───────────────────────
|
|
77
77
|
|
|
78
78
|
if [ "$claude_found" = true ] && [ -f "$SETTINGS" ] && command -v jq &>/dev/null; then
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
jq '(.hooks.PostToolUse[] | select(.matcher == "Read|Write|Edit|Bash")).matcher = "Read|Write|Edit|Bash|TaskCreate|TaskUpdate"' "$SETTINGS" > "$_tmp" && mv "$_tmp" "$SETTINGS"
|
|
83
|
-
fi
|
|
79
|
+
# Clean old registrations before re-registering (handles matcher changes across versions)
|
|
80
|
+
eagle_clean_hook_entries "$SETTINGS" "PostToolUse" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
81
|
+
eagle_clean_hook_entries "$SETTINGS" "PreToolUse" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
84
82
|
|
|
85
83
|
eagle_patch_hook "$SETTINGS" "SessionStart" "" "$EAGLE_MEM_DIR/hooks/session-start.sh"
|
|
86
84
|
eagle_patch_hook "$SETTINGS" "Stop" "" "$EAGLE_MEM_DIR/hooks/stop.sh"
|
|
87
|
-
eagle_patch_hook "$SETTINGS" "PostToolUse" "Read|Write|Edit|Bash|
|
|
85
|
+
eagle_patch_hook "$SETTINGS" "PostToolUse" "Read|Write|Edit|Bash|TaskUpdate" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
88
86
|
eagle_patch_hook "$SETTINGS" "TaskCreated" "" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
89
87
|
eagle_patch_hook "$SETTINGS" "TaskCompleted" "" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
90
88
|
eagle_patch_hook "$SETTINGS" "SessionEnd" "" "$EAGLE_MEM_DIR/hooks/session-end.sh"
|
|
91
89
|
eagle_patch_hook "$SETTINGS" "UserPromptSubmit" "" "$EAGLE_MEM_DIR/hooks/user-prompt-submit.sh"
|
|
92
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
93
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Read" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
94
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Edit" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
95
|
-
eagle_patch_hook "$SETTINGS" "PreToolUse" "Write" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
90
|
+
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash|Read|Edit|Write" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
96
91
|
|
|
97
92
|
eagle_ok "Hooks registered"
|
|
98
93
|
fi
|