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/hooks/post-tool-use.sh
CHANGED
|
@@ -17,13 +17,10 @@ LIB_DIR="$SCRIPT_DIR/../lib"
|
|
|
17
17
|
input=$(eagle_read_stdin)
|
|
18
18
|
[ -z "$input" ] && exit 0
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
|
|
20
|
+
IFS=$'\x1f' read -r session_id cwd tool_name hook_event <<< \
|
|
21
|
+
"$(echo "$input" | jq -r '[.session_id, .cwd, .tool_name, .hook_event_name] | map(. // "") | join("")')"
|
|
23
22
|
agent=$(eagle_agent_source_from_json "$input")
|
|
24
23
|
|
|
25
|
-
hook_event=$(echo "$input" | jq -r '.hook_event_name // empty')
|
|
26
|
-
|
|
27
24
|
if [ -z "$session_id" ]; then exit 0; fi
|
|
28
25
|
|
|
29
26
|
# TaskCreated/TaskCompleted dedicated events — parse top-level fields and exit
|
|
@@ -73,7 +70,7 @@ esac
|
|
|
73
70
|
|
|
74
71
|
# Only track relevant tools
|
|
75
72
|
case "$tool_name" in
|
|
76
|
-
Read|Write|Edit|
|
|
73
|
+
Read|Write|Edit|apply_patch|TaskUpdate) ;;
|
|
77
74
|
*) eagle_is_shell_tool "$tool_name" || exit 0 ;;
|
|
78
75
|
esac
|
|
79
76
|
|
|
@@ -153,9 +150,18 @@ case "$tool_name" in
|
|
|
153
150
|
*) command_category="other" ;;
|
|
154
151
|
esac
|
|
155
152
|
;;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
TaskUpdate)
|
|
154
|
+
task_id=$(echo "$input" | jq -r '.tool_input.taskId // empty')
|
|
155
|
+
task_status=$(echo "$input" | jq -r '.tool_input.status // empty')
|
|
156
|
+
tool_summary="TaskUpdate: ${task_id} → ${task_status}"
|
|
157
|
+
if [ -n "$task_id" ] && [ -n "$task_status" ]; then
|
|
158
|
+
fp_sql=$(eagle_sql_escape "event://${session_id}/${task_id}")
|
|
159
|
+
stat_sql=$(eagle_sql_escape "$task_status")
|
|
160
|
+
eagle_db_pipe <<SQL
|
|
161
|
+
UPDATE agent_tasks SET status = '$stat_sql', updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
162
|
+
WHERE file_path = '$fp_sql';
|
|
163
|
+
SQL
|
|
164
|
+
fi
|
|
159
165
|
;;
|
|
160
166
|
esac
|
|
161
167
|
|
|
@@ -199,7 +205,6 @@ esac
|
|
|
199
205
|
# ─── Dispatch to extracted responsibilities ───────────────
|
|
200
206
|
|
|
201
207
|
eagle_posttool_mirror_writes "$tool_name" "$fp" "$session_id" "$project" "$agent"
|
|
202
|
-
eagle_posttool_mirror_tasks "$tool_name" "$session_id" "$project" "$input" "$agent"
|
|
203
208
|
eagle_posttool_stale_hint "$tool_name" "$fp" "$project" "$agent"
|
|
204
209
|
eagle_posttool_decision_surface "$tool_name" "$fp" "$project" "$agent"
|
|
205
210
|
|
package/hooks/pre-tool-use.sh
CHANGED
|
@@ -21,7 +21,8 @@ LIB_DIR="$SCRIPT_DIR/../lib"
|
|
|
21
21
|
input=$(eagle_read_stdin)
|
|
22
22
|
[ -z "$input" ] && exit 0
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
IFS=$'\x1f' read -r tool_name session_id cwd <<< \
|
|
25
|
+
"$(echo "$input" | jq -r '[.tool_name, .session_id, .cwd] | map(. // "") | join("")')"
|
|
25
26
|
agent=$(eagle_agent_source_from_json "$input")
|
|
26
27
|
|
|
27
28
|
case "$tool_name" in
|
|
@@ -30,9 +31,6 @@ case "$tool_name" in
|
|
|
30
31
|
esac
|
|
31
32
|
|
|
32
33
|
[ ! -f "$EAGLE_MEM_DB" ] && exit 0
|
|
33
|
-
|
|
34
|
-
session_id=$(echo "$input" | jq -r '.session_id // empty')
|
|
35
|
-
cwd=$(echo "$input" | jq -r '.cwd // empty')
|
|
36
34
|
project=$(eagle_project_from_hook_input "$input")
|
|
37
35
|
[ -z "$project" ] && exit 0
|
|
38
36
|
|
|
@@ -77,8 +75,6 @@ Pending checks:"
|
|
|
77
75
|
done <<< "$pending_rows"
|
|
78
76
|
|
|
79
77
|
jq -nc --arg reason "$block_reason" '{
|
|
80
|
-
"decision":"block",
|
|
81
|
-
"reason":$reason,
|
|
82
78
|
"hookSpecificOutput":{
|
|
83
79
|
"hookEventName":"PreToolUse",
|
|
84
80
|
"permissionDecision":"deny",
|
|
@@ -104,8 +100,6 @@ Recommended compact command:
|
|
|
104
100
|
One-off developer bypass:
|
|
105
101
|
touch $EAGLE_RAW_BASH_UNLOCK"
|
|
106
102
|
jq -nc --arg reason "$reason" '{
|
|
107
|
-
"decision":"block",
|
|
108
|
-
"reason":$reason,
|
|
109
103
|
"hookSpecificOutput":{
|
|
110
104
|
"hookEventName":"PreToolUse",
|
|
111
105
|
"permissionDecision":"deny",
|
|
@@ -131,8 +125,6 @@ Install RTK or switch enforcement to auto:
|
|
|
131
125
|
One-off developer bypass:
|
|
132
126
|
touch $EAGLE_RAW_BASH_UNLOCK"
|
|
133
127
|
jq -nc --arg reason "$reason" '{
|
|
134
|
-
"decision":"block",
|
|
135
|
-
"reason":$reason,
|
|
136
128
|
"hookSpecificOutput":{
|
|
137
129
|
"hookEventName":"PreToolUse",
|
|
138
130
|
"permissionDecision":"deny",
|
package/hooks/session-start.sh
CHANGED
|
@@ -37,6 +37,12 @@ project=$(eagle_project_from_hook_input "$input")
|
|
|
37
37
|
[ -z "$project" ] && exit 0
|
|
38
38
|
|
|
39
39
|
p_esc=$(eagle_sql_escape "$project")
|
|
40
|
+
recall_scope=$(eagle_recall_project_scope_from_cwd "$cwd" "$project")
|
|
41
|
+
[ -z "$recall_scope" ] && recall_scope="$project"
|
|
42
|
+
recall_scope_label=$(eagle_project_scope_label "$recall_scope")
|
|
43
|
+
recall_project_filter=$(eagle_sql_project_scope_condition "project" "$recall_scope")
|
|
44
|
+
recall_memory_filter=$(eagle_sql_project_scope_condition "m.project" "$recall_scope")
|
|
45
|
+
recall_lane_filter=$(eagle_sql_project_scope_condition "l.project" "$recall_scope")
|
|
40
46
|
|
|
41
47
|
eagle_log "INFO" "SessionStart: session=$session_id project=$project source=$source_type agent=$agent"
|
|
42
48
|
|
|
@@ -96,7 +102,7 @@ while IFS='|' read -r key val; do
|
|
|
96
102
|
last_active) stat_last_active="$val" ;;
|
|
97
103
|
last_summary) stat_last_summary="$val" ;;
|
|
98
104
|
esac
|
|
99
|
-
done <<< "$(eagle_get_project_stats "$
|
|
105
|
+
done <<< "$(eagle_get_project_stats "$recall_scope")"
|
|
100
106
|
|
|
101
107
|
# ─── Build compressed banner (elide zero-value lines) ────
|
|
102
108
|
|
|
@@ -119,6 +125,10 @@ eagle_banner="======================================
|
|
|
119
125
|
Project | $project
|
|
120
126
|
Agent | $agent_label
|
|
121
127
|
Sessions | $stat_sessions ($stat_with_summaries with summaries)"
|
|
128
|
+
if [ "$recall_scope_label" != "$project" ]; then
|
|
129
|
+
eagle_banner+="
|
|
130
|
+
Recall Scope | $recall_scope_label"
|
|
131
|
+
fi
|
|
122
132
|
if [ "$stat_sessions_codex" -gt 0 ] || [ "$stat_sessions_claude" -gt 0 ]; then
|
|
123
133
|
eagle_banner+="
|
|
124
134
|
Sources | Claude $stat_sessions_claude, Codex $stat_sessions_codex"
|
|
@@ -137,12 +147,18 @@ eagle_banner+="
|
|
|
137
147
|
======================================"
|
|
138
148
|
|
|
139
149
|
context="$eagle_banner
|
|
150
|
+
Eagle Mem recalls: use the project memory below before making design or implementation claims. If it affects your answer, mention the recall in one short attribution line.
|
|
140
151
|
"
|
|
141
152
|
|
|
142
153
|
if [ "$codex_compact" -eq 1 ]; then
|
|
143
154
|
codex_context="Eagle Mem Recall Ready
|
|
144
155
|
Project: $project | Agent: $agent_label
|
|
145
156
|
Memory: $stat_sessions sessions"
|
|
157
|
+
if [ "$recall_scope_label" != "$project" ]; then
|
|
158
|
+
codex_context="Eagle Mem Recall Ready
|
|
159
|
+
Project: $project | Recall: $recall_scope_label | Agent: $agent_label
|
|
160
|
+
Memory: $stat_sessions sessions"
|
|
161
|
+
fi
|
|
146
162
|
[ "$stat_with_summaries" -gt 0 ] && codex_context+=", $stat_with_summaries summarized"
|
|
147
163
|
[ "$stat_memories" -gt 0 ] && codex_context+=", $stat_memories memories"
|
|
148
164
|
[ "$stat_chunks" -gt 0 ] && codex_context+=", $stat_chunks code chunks"
|
|
@@ -172,7 +188,7 @@ Project brief: no overview yet; background scan is running.
|
|
|
172
188
|
"
|
|
173
189
|
fi
|
|
174
190
|
|
|
175
|
-
recent=$(eagle_get_recent_summaries "$
|
|
191
|
+
recent=$(eagle_get_recent_summaries "$recall_scope" 1)
|
|
176
192
|
if [ -n "$recent" ]; then
|
|
177
193
|
codex_context+="
|
|
178
194
|
Relevant now:
|
|
@@ -194,16 +210,18 @@ Relevant now:
|
|
|
194
210
|
memories=$(eagle_db "SELECT memory_name, memory_type, description, origin_agent,
|
|
195
211
|
CAST(julianday('now') - julianday(updated_at) AS INTEGER) as days_ago
|
|
196
212
|
FROM agent_memories
|
|
197
|
-
WHERE
|
|
213
|
+
WHERE $recall_project_filter
|
|
214
|
+
AND memory_name NOT IN ('Codex Memory Registry', 'Codex Memory Summary')
|
|
198
215
|
ORDER BY
|
|
199
216
|
CASE
|
|
200
217
|
WHEN lower(memory_name) LIKE 'current status%' THEN 4
|
|
201
|
-
WHEN memory_type
|
|
202
|
-
WHEN memory_type = '
|
|
203
|
-
|
|
218
|
+
WHEN memory_type = 'project' THEN 0
|
|
219
|
+
WHEN memory_type = 'feedback' THEN 1
|
|
220
|
+
WHEN memory_type IN ('user', 'reference') THEN 2
|
|
221
|
+
ELSE 3
|
|
204
222
|
END,
|
|
205
223
|
updated_at DESC
|
|
206
|
-
LIMIT
|
|
224
|
+
LIMIT 4;")
|
|
207
225
|
if [ -n "$memories" ]; then
|
|
208
226
|
[ -z "$recent" ] && codex_context+="
|
|
209
227
|
Relevant now:
|
|
@@ -225,7 +243,7 @@ Relevant now:
|
|
|
225
243
|
fi
|
|
226
244
|
|
|
227
245
|
synced_tasks=$(eagle_db "SELECT subject, status, blocked_by, origin_agent FROM agent_tasks
|
|
228
|
-
WHERE
|
|
246
|
+
WHERE $recall_project_filter
|
|
229
247
|
AND status IN ('in_progress', 'pending')
|
|
230
248
|
AND source_session_id != 'orchestration'
|
|
231
249
|
AND updated_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-7 days')
|
|
@@ -234,7 +252,7 @@ Relevant now:
|
|
|
234
252
|
orchestration_lanes=$(eagle_db "SELECT o.name, l.lane_key, l.title, l.agent, l.status
|
|
235
253
|
FROM orchestration_lanes l
|
|
236
254
|
JOIN orchestrations o ON o.id = l.orchestration_id
|
|
237
|
-
WHERE
|
|
255
|
+
WHERE $recall_lane_filter
|
|
238
256
|
AND o.status = 'active'
|
|
239
257
|
AND l.status IN ('in_progress', 'pending', 'blocked')
|
|
240
258
|
ORDER BY CASE l.status WHEN 'in_progress' THEN 0 WHEN 'blocked' THEN 1 ELSE 2 END, l.updated_at DESC
|
|
@@ -361,7 +379,7 @@ else
|
|
|
361
379
|
_summary_limit=2
|
|
362
380
|
fi
|
|
363
381
|
|
|
364
|
-
recent=$(eagle_get_recent_summaries "$
|
|
382
|
+
recent=$(eagle_get_recent_summaries "$recall_scope" "$_summary_limit")
|
|
365
383
|
|
|
366
384
|
if [ -n "$recent" ]; then
|
|
367
385
|
context+="
|
|
@@ -410,18 +428,20 @@ fi
|
|
|
410
428
|
|
|
411
429
|
# ─── Memories (skip if none) ─────────────────────────────
|
|
412
430
|
|
|
413
|
-
memory_limit=
|
|
414
|
-
[ "$codex_compact" -eq 1 ] && memory_limit=
|
|
431
|
+
memory_limit=5
|
|
432
|
+
[ "$codex_compact" -eq 1 ] && memory_limit=3
|
|
415
433
|
memories=$(eagle_db "SELECT memory_name, memory_type, description, file_path, updated_at, origin_agent,
|
|
416
434
|
CAST(julianday('now') - julianday(updated_at) AS INTEGER) as days_ago
|
|
417
435
|
FROM agent_memories
|
|
418
|
-
WHERE
|
|
436
|
+
WHERE $recall_project_filter
|
|
437
|
+
AND memory_name NOT IN ('Codex Memory Registry', 'Codex Memory Summary')
|
|
419
438
|
ORDER BY
|
|
420
439
|
CASE
|
|
421
440
|
WHEN lower(memory_name) LIKE 'current status%' THEN 4
|
|
422
|
-
WHEN memory_type
|
|
423
|
-
WHEN memory_type = '
|
|
424
|
-
|
|
441
|
+
WHEN memory_type = 'project' THEN 0
|
|
442
|
+
WHEN memory_type = 'feedback' THEN 1
|
|
443
|
+
WHEN memory_type IN ('user', 'reference') THEN 2
|
|
444
|
+
ELSE 3
|
|
425
445
|
END,
|
|
426
446
|
updated_at DESC
|
|
427
447
|
LIMIT $memory_limit;")
|
|
@@ -450,7 +470,7 @@ fi
|
|
|
450
470
|
|
|
451
471
|
# ─── Plans (skip if none) ────────────────────────────────
|
|
452
472
|
|
|
453
|
-
plans=$(eagle_list_agent_plans "$
|
|
473
|
+
plans=$(eagle_list_agent_plans "$recall_scope" 3)
|
|
454
474
|
if [ -n "$plans" ]; then
|
|
455
475
|
context+="
|
|
456
476
|
=== Eagle Mem: Plans ===
|
|
@@ -468,7 +488,7 @@ fi
|
|
|
468
488
|
task_limit=5
|
|
469
489
|
[ "$codex_compact" -eq 1 ] && task_limit=3
|
|
470
490
|
synced_tasks=$(eagle_db "SELECT subject, status, blocked_by, origin_agent FROM agent_tasks
|
|
471
|
-
WHERE
|
|
491
|
+
WHERE $recall_project_filter
|
|
472
492
|
AND status IN ('in_progress', 'pending')
|
|
473
493
|
AND source_session_id != 'orchestration'
|
|
474
494
|
AND updated_at > strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-7 days')
|
|
@@ -501,7 +521,7 @@ orchestration_lanes=$(eagle_db "SELECT o.name, o.goal, l.lane_key, l.title,
|
|
|
501
521
|
l.agent, l.status, l.validation, l.worktree_path, l.notes
|
|
502
522
|
FROM orchestration_lanes l
|
|
503
523
|
JOIN orchestrations o ON o.id = l.orchestration_id
|
|
504
|
-
WHERE
|
|
524
|
+
WHERE $recall_lane_filter
|
|
505
525
|
AND o.status = 'active'
|
|
506
526
|
AND l.status IN ('in_progress', 'pending', 'blocked')
|
|
507
527
|
ORDER BY
|
package/hooks/stop.sh
CHANGED
|
@@ -21,16 +21,12 @@ eagle_ensure_db
|
|
|
21
21
|
input=$(eagle_read_stdin)
|
|
22
22
|
[ -z "$input" ] && exit 0
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
transcript_path=$(echo "$input" | jq -r '.transcript_path // empty')
|
|
24
|
+
IFS=$'\x1f' read -r session_id cwd transcript_path agent_type <<< \
|
|
25
|
+
"$(echo "$input" | jq -r '[.session_id, .cwd, .transcript_path, .agent_type] | map(. // "") | join("")')"
|
|
27
26
|
last_assistant_message=$(echo "$input" | jq -r '.last_assistant_message // empty')
|
|
28
27
|
agent=$(eagle_agent_source_from_json "$input")
|
|
29
28
|
|
|
30
29
|
[ -z "$session_id" ] && exit 0
|
|
31
|
-
|
|
32
|
-
# Skip subagent contexts
|
|
33
|
-
agent_type=$(echo "$input" | jq -r '.agent_type // empty')
|
|
34
30
|
[ -n "$agent_type" ] && [ "$agent_type" != "main" ] && exit 0
|
|
35
31
|
|
|
36
32
|
project=$(eagle_project_from_hook_input "$input")
|
|
@@ -18,14 +18,16 @@ LIB_DIR="$SCRIPT_DIR/../lib"
|
|
|
18
18
|
input=$(eagle_read_stdin)
|
|
19
19
|
[ -z "$input" ] && exit 0
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
IFS=$'\x1f' read -r session_id cwd <<< \
|
|
22
|
+
"$(echo "$input" | jq -r '[.session_id, .cwd] | map(. // "") | join("")')"
|
|
23
23
|
user_prompt=$(echo "$input" | jq -r '.prompt // empty')
|
|
24
24
|
agent=$(eagle_agent_source_from_json "$input")
|
|
25
25
|
|
|
26
26
|
[ -z "$user_prompt" ] && exit 0
|
|
27
27
|
|
|
28
28
|
project=$(eagle_project_from_hook_input "$input")
|
|
29
|
+
recall_scope=$(eagle_recall_project_scope_from_cwd "$cwd" "$project")
|
|
30
|
+
[ -z "$recall_scope" ] && recall_scope="$project"
|
|
29
31
|
codex_compact=0
|
|
30
32
|
[ "$agent" = "codex" ] && codex_compact=1
|
|
31
33
|
|
|
@@ -93,8 +95,10 @@ fts_query=$(echo "$user_prompt" | tr -cs '[:alnum:]' ' ' | tr '[:upper:]' '[:low
|
|
|
93
95
|
split("the a an is are was were be been being have has had do does did will would shall should may might can could of in to for on with at by from", sw, " ")
|
|
94
96
|
for (i in sw) stop[sw[i]]=1
|
|
95
97
|
n=0
|
|
98
|
+
split("ad ai ui ux db", keep, " ")
|
|
99
|
+
for (i in keep) short_keep[keep[i]]=1
|
|
96
100
|
for (i=1; i<=NF && n<6; i++) {
|
|
97
|
-
if (length($i) > 2 && !($i in stop)) {
|
|
101
|
+
if ((length($i) > 2 || ($i in short_keep)) && !($i in stop)) {
|
|
98
102
|
printf "%s%s", (n>0?" OR ":""), $i; n++
|
|
99
103
|
}
|
|
100
104
|
}
|
|
@@ -137,15 +141,21 @@ if [ "$codex_compact" -eq 1 ]; then
|
|
|
137
141
|
code_limit=2
|
|
138
142
|
fi
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
memory_limit=3
|
|
145
|
+
[ "$codex_compact" -eq 1 ] && memory_limit=2
|
|
141
146
|
|
|
142
|
-
|
|
147
|
+
results=$(eagle_search_summaries "$fts_query" "$recall_scope" "$summary_limit")
|
|
148
|
+
memory_results=$(eagle_search_agent_memories "$fts_query" "$recall_scope" "$memory_limit" 2>/dev/null || true)
|
|
149
|
+
|
|
150
|
+
if [ -n "$results" ] || [ -n "$memory_results" ]; then
|
|
143
151
|
if [ "$codex_compact" -eq 1 ]; then
|
|
144
152
|
context+="
|
|
145
153
|
Eagle Mem recalls:
|
|
146
154
|
"
|
|
147
155
|
else
|
|
148
|
-
context+="
|
|
156
|
+
context+="Eagle Mem recalls: apply these retrieved project facts before answering. If they are relevant to the user's prompt, start with one short \"Eagle Mem recalls:\" attribution line.
|
|
157
|
+
|
|
158
|
+
=== Eagle Mem: Relevant Recall ===
|
|
149
159
|
"
|
|
150
160
|
fi
|
|
151
161
|
while IFS='|' read -r req completed learned _next_steps created_at _proj decisions gotchas key_files summary_agent; do
|
|
@@ -186,6 +196,30 @@ Eagle Mem recalls:
|
|
|
186
196
|
"
|
|
187
197
|
fi
|
|
188
198
|
done <<< "$results"
|
|
199
|
+
|
|
200
|
+
while IFS='|' read -r mname mtype mdesc msnippet _mfile _mupdated morigin; do
|
|
201
|
+
[ -z "$mname" ] && continue
|
|
202
|
+
case "$mname" in
|
|
203
|
+
"Codex Memory Registry"|"Codex Memory Summary") continue ;;
|
|
204
|
+
esac
|
|
205
|
+
origin_label=$(eagle_agent_label "$morigin")
|
|
206
|
+
if [ "$codex_compact" -eq 1 ]; then
|
|
207
|
+
mdesc=$(eagle_trim_text "$mdesc" 120)
|
|
208
|
+
context+="- Memory [$mtype][$origin_label]: $mname"
|
|
209
|
+
[ -n "$mdesc" ] && context+=" — $mdesc"
|
|
210
|
+
context+="
|
|
211
|
+
"
|
|
212
|
+
else
|
|
213
|
+
mdesc=$(eagle_trim_text "$mdesc" 180)
|
|
214
|
+
msnippet=$(eagle_trim_text "$msnippet" 220)
|
|
215
|
+
context+="[Memory][$origin_label][$mtype] $mname"
|
|
216
|
+
[ -n "$mdesc" ] && context+=" — $mdesc"
|
|
217
|
+
[ -n "$msnippet" ] && context+="
|
|
218
|
+
Snippet: $msnippet"
|
|
219
|
+
context+="
|
|
220
|
+
"
|
|
221
|
+
fi
|
|
222
|
+
done <<< "$memory_results"
|
|
189
223
|
fi
|
|
190
224
|
|
|
191
225
|
# Search indexed code chunks (if any exist for this project)
|
package/lib/common.sh
CHANGED
|
@@ -362,6 +362,121 @@ eagle_project_from_existing_ancestor() {
|
|
|
362
362
|
return 1
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
+
eagle_project_has_recall_rows() {
|
|
366
|
+
local project="${1:-}"
|
|
367
|
+
[ -n "$project" ] || return 1
|
|
368
|
+
|
|
369
|
+
eagle_project_has_table_row "agent_memories" "$project" \
|
|
370
|
+
|| eagle_project_has_table_row "agent_plans" "$project" \
|
|
371
|
+
|| eagle_project_has_table_row "agent_tasks" "$project" \
|
|
372
|
+
|| eagle_project_has_table_row "summaries" "$project"
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
eagle_recall_ancestor_project_from_cwd() {
|
|
376
|
+
local path="${1:-$(pwd)}"
|
|
377
|
+
local current_project="${2:-}"
|
|
378
|
+
local current key
|
|
379
|
+
|
|
380
|
+
current=$(eagle_normalize_project_path "$path")
|
|
381
|
+
eagle_is_ephemeral_project_path "$current" && return 1
|
|
382
|
+
|
|
383
|
+
[ -d "$current" ] || current=$(dirname "$current")
|
|
384
|
+
current=$(dirname "$current")
|
|
385
|
+
|
|
386
|
+
while [ -n "$current" ] && [ "$current" != "/" ]; do
|
|
387
|
+
if [ "$current" = "$HOME" ]; then
|
|
388
|
+
break
|
|
389
|
+
fi
|
|
390
|
+
|
|
391
|
+
key=$(eagle_project_key_from_target_dir "$current")
|
|
392
|
+
if [ -n "$key" ] && [ "$key" != "$current_project" ]; then
|
|
393
|
+
if eagle_project_has_recall_rows "$key"; then
|
|
394
|
+
printf '%s\n' "$key"
|
|
395
|
+
return 0
|
|
396
|
+
fi
|
|
397
|
+
fi
|
|
398
|
+
|
|
399
|
+
current=$(dirname "$current")
|
|
400
|
+
done
|
|
401
|
+
|
|
402
|
+
return 1
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
eagle_recall_project_scope_from_cwd() {
|
|
406
|
+
local path="${1:-$(pwd)}"
|
|
407
|
+
local project="${2:-}"
|
|
408
|
+
local ancestor
|
|
409
|
+
|
|
410
|
+
[ -z "$project" ] && project=$(eagle_project_from_cwd "$path")
|
|
411
|
+
if ancestor=$(eagle_recall_ancestor_project_from_cwd "$path" "$project"); then
|
|
412
|
+
if [ -n "$project" ] && [ "$ancestor" != "$project" ]; then
|
|
413
|
+
printf '%s|%s\n' "$project" "$ancestor"
|
|
414
|
+
return 0
|
|
415
|
+
fi
|
|
416
|
+
printf '%s\n' "$ancestor"
|
|
417
|
+
return 0
|
|
418
|
+
fi
|
|
419
|
+
|
|
420
|
+
printf '%s\n' "$project"
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
eagle_sql_project_scope_condition() {
|
|
424
|
+
local column="${1:-project}"
|
|
425
|
+
local scope="${2:-}"
|
|
426
|
+
local values="" count=0 item escaped
|
|
427
|
+
|
|
428
|
+
while IFS= read -r item; do
|
|
429
|
+
[ -n "$item" ] || continue
|
|
430
|
+
escaped=$(eagle_sql_escape "$item")
|
|
431
|
+
values="${values},'${escaped}'"
|
|
432
|
+
count=$((count + 1))
|
|
433
|
+
done <<EOF
|
|
434
|
+
$(printf '%s' "$scope" | tr '|' '\n')
|
|
435
|
+
EOF
|
|
436
|
+
|
|
437
|
+
if [ "$count" -eq 0 ]; then
|
|
438
|
+
printf '1 = 0\n'
|
|
439
|
+
elif [ "$count" -eq 1 ]; then
|
|
440
|
+
printf "%s = %s\n" "$column" "${values#,}"
|
|
441
|
+
else
|
|
442
|
+
printf "%s IN (%s)\n" "$column" "${values#,}"
|
|
443
|
+
fi
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
eagle_project_scope_label() {
|
|
447
|
+
local scope="${1:-}"
|
|
448
|
+
printf '%s\n' "$scope" | tr '|' ','
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
eagle_project_scope_contains() {
|
|
452
|
+
local scope="${1:-}"
|
|
453
|
+
local target="${2:-}"
|
|
454
|
+
local item
|
|
455
|
+
[ -n "$target" ] || return 1
|
|
456
|
+
|
|
457
|
+
while IFS= read -r item; do
|
|
458
|
+
[ -z "$item" ] && continue
|
|
459
|
+
[ "$item" = "$target" ] && return 0
|
|
460
|
+
done <<EOF
|
|
461
|
+
$(printf '%s' "$scope" | tr '|' '\n')
|
|
462
|
+
EOF
|
|
463
|
+
|
|
464
|
+
return 1
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
eagle_claude_project_dir_for_key() {
|
|
468
|
+
local project="${1:-}"
|
|
469
|
+
[ -n "$project" ] || return 1
|
|
470
|
+
|
|
471
|
+
local abs slug
|
|
472
|
+
case "$project" in
|
|
473
|
+
/*) abs="$project" ;;
|
|
474
|
+
*) abs="$HOME/$project" ;;
|
|
475
|
+
esac
|
|
476
|
+
slug=$(printf '%s' "$abs" | sed -E 's#[^[:alnum:].]+#-#g')
|
|
477
|
+
printf '%s/%s\n' "$EAGLE_CLAUDE_PROJECTS_DIR" "$slug"
|
|
478
|
+
}
|
|
479
|
+
|
|
365
480
|
eagle_project_from_workspace_path() {
|
|
366
481
|
if [ -n "${EAGLE_MEM_PROJECT:-}" ]; then
|
|
367
482
|
printf '%s\n' "$EAGLE_MEM_PROJECT"
|
|
@@ -557,6 +672,15 @@ eagle_project_from_hook_input() {
|
|
|
557
672
|
cwd=$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null)
|
|
558
673
|
transcript_path=$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
559
674
|
|
|
675
|
+
if [ -n "${CLAUDE_PROJECT_DIR:-}" ]; then
|
|
676
|
+
project=$(eagle_project_from_workspace_path "$CLAUDE_PROJECT_DIR")
|
|
677
|
+
if [ -n "$project" ]; then
|
|
678
|
+
[ -n "$session_id" ] && eagle_remember_session_project "$session_id" "$project" 1 >/dev/null 2>&1
|
|
679
|
+
printf '%s\n' "$project"
|
|
680
|
+
return
|
|
681
|
+
fi
|
|
682
|
+
fi
|
|
683
|
+
|
|
560
684
|
workspace_project=$(printf '%s' "$input" | jq -r '.workspace.project_dir // empty' 2>/dev/null)
|
|
561
685
|
if [ -n "$workspace_project" ]; then
|
|
562
686
|
project=$(eagle_project_from_workspace_path "$workspace_project")
|
|
@@ -728,20 +852,15 @@ eagle_emit_context_for_agent() {
|
|
|
728
852
|
|
|
729
853
|
[ -z "$context" ] && return 0
|
|
730
854
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}'
|
|
741
|
-
return 0
|
|
742
|
-
fi
|
|
743
|
-
|
|
744
|
-
printf '%s\n' "$context"
|
|
855
|
+
jq -cn \
|
|
856
|
+
--arg event "$hook_event" \
|
|
857
|
+
--arg context "$context" \
|
|
858
|
+
'{
|
|
859
|
+
hookSpecificOutput: {
|
|
860
|
+
hookEventName: $event,
|
|
861
|
+
additionalContext: $context
|
|
862
|
+
}
|
|
863
|
+
}'
|
|
745
864
|
}
|
|
746
865
|
|
|
747
866
|
eagle_config_get_light() {
|
package/lib/db-features.sh
CHANGED
|
@@ -110,16 +110,16 @@ eagle_record_pending_feature_verifications() {
|
|
|
110
110
|
local fid; fid=$(eagle_sql_int "$feature_id")
|
|
111
111
|
local name_esc; name_esc=$(eagle_sql_escape "$feature_name")
|
|
112
112
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
already_resolved=$(eagle_db "SELECT 1 FROM pending_feature_verifications
|
|
114
|
+
WHERE project = '$p_esc'
|
|
115
|
+
AND feature_id = $fid
|
|
116
|
+
AND file_path = '$fp_esc'
|
|
117
|
+
AND (
|
|
118
|
+
(change_fingerprint = '$fp_hash_esc' AND status = 'verified')
|
|
119
|
+
OR status = 'waived'
|
|
120
|
+
)
|
|
121
|
+
LIMIT 1;")
|
|
122
|
+
[ -n "$already_resolved" ] && continue
|
|
123
123
|
|
|
124
124
|
eagle_db "INSERT INTO pending_feature_verifications
|
|
125
125
|
(project, feature_id, feature_name, file_path, reason, source_session_id, trigger_tool, change_fingerprint)
|
package/lib/db-mirrors.sh
CHANGED
|
@@ -103,8 +103,7 @@ eagle_search_agent_memories() {
|
|
|
103
103
|
|
|
104
104
|
local where_clause=""
|
|
105
105
|
if [ -n "$project" ]; then
|
|
106
|
-
|
|
107
|
-
where_clause="AND m.project = '$project'"
|
|
106
|
+
where_clause="AND $(eagle_sql_project_scope_condition "m.project" "$project")"
|
|
108
107
|
fi
|
|
109
108
|
|
|
110
109
|
eagle_db "SELECT m.memory_name, m.memory_type, m.description,
|
|
@@ -124,8 +123,7 @@ eagle_list_agent_memories() {
|
|
|
124
123
|
|
|
125
124
|
local where_clause=""
|
|
126
125
|
if [ -n "$project" ]; then
|
|
127
|
-
|
|
128
|
-
where_clause="WHERE project = '$project'"
|
|
126
|
+
where_clause="WHERE $(eagle_sql_project_scope_condition "project" "$project")"
|
|
129
127
|
fi
|
|
130
128
|
|
|
131
129
|
eagle_db "SELECT memory_name, memory_type, description, file_path, updated_at, origin_agent
|
|
@@ -198,8 +196,7 @@ eagle_search_agent_plans() {
|
|
|
198
196
|
|
|
199
197
|
local where_clause=""
|
|
200
198
|
if [ -n "$project" ]; then
|
|
201
|
-
|
|
202
|
-
where_clause="AND p.project = '$project'"
|
|
199
|
+
where_clause="AND $(eagle_sql_project_scope_condition "p.project" "$project")"
|
|
203
200
|
fi
|
|
204
201
|
|
|
205
202
|
eagle_db "SELECT p.title, p.project,
|
|
@@ -219,8 +216,7 @@ eagle_list_agent_plans() {
|
|
|
219
216
|
|
|
220
217
|
local where_clause=""
|
|
221
218
|
if [ -n "$project" ]; then
|
|
222
|
-
|
|
223
|
-
where_clause="WHERE project = '$project'"
|
|
219
|
+
where_clause="WHERE $(eagle_sql_project_scope_condition "project" "$project")"
|
|
224
220
|
fi
|
|
225
221
|
|
|
226
222
|
eagle_db "SELECT title, project, file_path, updated_at, origin_agent
|
|
@@ -303,8 +299,7 @@ eagle_list_agent_tasks() {
|
|
|
303
299
|
|
|
304
300
|
local where_clause=""
|
|
305
301
|
if [ -n "$project" ]; then
|
|
306
|
-
|
|
307
|
-
where_clause="WHERE project = '$project'"
|
|
302
|
+
where_clause="WHERE $(eagle_sql_project_scope_condition "project" "$project")"
|
|
308
303
|
fi
|
|
309
304
|
|
|
310
305
|
eagle_db "SELECT subject, status, source_session_id, source_task_id, updated_at, origin_agent
|
|
@@ -326,8 +321,7 @@ eagle_search_agent_tasks() {
|
|
|
326
321
|
|
|
327
322
|
local where_clause=""
|
|
328
323
|
if [ -n "$project" ]; then
|
|
329
|
-
|
|
330
|
-
where_clause="AND t.project = '$project'"
|
|
324
|
+
where_clause="AND $(eagle_sql_project_scope_condition "t.project" "$project")"
|
|
331
325
|
fi
|
|
332
326
|
|
|
333
327
|
eagle_db "SELECT t.subject, t.status,
|