eagle-mem 4.10.13 → 4.12.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/CHANGELOG.md +25 -0
- package/README.md +22 -22
- package/architecture.html +26 -14
- package/bin/eagle-mem +4 -0
- package/db/039_recall_events.sql +27 -0
- package/db/040_graph_decision_nodes.sql +21 -0
- package/db/041_graph_semantic_edge_types.sql +21 -0
- package/db/042_orchestration_auto_events.sql +23 -0
- package/db/043_eagle_events.sql +22 -0
- package/db/044_summary_capture_source.sql +12 -0
- package/docs/agent-compatibility/README.md +38 -0
- package/docs/agent-compatibility/claude-code.md +58 -0
- package/docs/agent-compatibility/codex.md +57 -0
- package/docs/agent-compatibility/opencode.md +72 -0
- package/hooks/post-tool-use.sh +8 -0
- package/hooks/pre-tool-use.sh +10 -1
- package/hooks/session-end.sh +3 -0
- package/hooks/session-start.sh +15 -17
- package/hooks/stop.sh +34 -5
- package/hooks/user-prompt-submit.sh +85 -10
- package/integrations/opencode_eagle_mem_plugin.js +387 -0
- package/lib/codex-hooks.sh +13 -6
- package/lib/common.sh +77 -7
- package/lib/db-events.sh +89 -0
- package/lib/db-graph.sh +154 -0
- package/lib/db-observations.sh +34 -0
- package/lib/db-orchestration.sh +149 -0
- package/lib/db-summaries.sh +70 -3
- package/lib/db.sh +2 -0
- package/lib/hooks.sh +41 -7
- package/lib/opencode-hooks.sh +105 -0
- package/lib/provider.sh +2 -2
- package/package.json +5 -2
- package/scripts/compaction.sh +109 -9
- package/scripts/dashboard.sh +372 -0
- package/scripts/doctor.sh +30 -3
- package/scripts/enrich-summary.sh +8 -2
- package/scripts/health.sh +40 -2
- package/scripts/help.sh +10 -2
- package/scripts/inspect.sh +285 -0
- package/scripts/install.sh +36 -7
- package/scripts/memories.sh +13 -0
- package/scripts/repair.sh +187 -0
- package/scripts/replay.sh +248 -0
- package/scripts/search.sh +44 -3
- package/scripts/session.sh +155 -18
- package/scripts/statusline-em.sh +34 -7
- package/scripts/tasks.sh +34 -0
- package/scripts/test.sh +13 -0
- package/scripts/uninstall.sh +9 -0
- package/scripts/update.sh +21 -2
- package/tests/fixtures/agent-hooks/claude-statusline.json +32 -0
- package/tests/fixtures/agent-hooks/claude-user-prompt-submit.json +9 -0
- package/tests/fixtures/agent-hooks/codex-pre-tool-use.json +10 -0
- package/tests/fixtures/agent-hooks/codex-user-prompt-submit.json +7 -0
- package/tests/fixtures/agent-hooks/opencode-chat-message.json +36 -0
- package/tests/fixtures/agent-hooks/opencode-session-compacting.json +9 -0
- package/tests/fixtures/agent-hooks/opencode-todo-updated.json +13 -0
- package/tests/fixtures/agent-hooks/opencode-tool-execute-after.json +15 -0
- package/tests/fixtures/agent-hooks/opencode-tool-execute-before.json +12 -0
- package/tests/test_agent_compatibility_docs_gate.sh +123 -0
- package/tests/test_auto_orchestration_detection.sh +109 -0
- package/tests/test_claude_stop_hook_registration.sh +56 -0
- package/tests/test_clean_session_capture.sh +105 -0
- package/tests/test_codex_hooks_config.sh +73 -0
- package/tests/test_compaction_survival_matrix.sh +237 -0
- package/tests/test_dashboard.sh +96 -0
- package/tests/test_eagle_events.sh +96 -0
- package/tests/test_opencode_hooks_config.sh +56 -0
- package/tests/test_opencode_plugin_adapter.sh +202 -0
- package/tests/test_recall_observability.sh +144 -0
- package/tests/test_repair.sh +63 -0
- package/tests/test_rust_migration_plan.sh +75 -0
- package/tests/test_trust_surfaces.sh +123 -0
package/scripts/health.sh
CHANGED
|
@@ -29,6 +29,30 @@ if [ "$JSON_OUT" -eq 1 ]; then
|
|
|
29
29
|
exec 3>&1 1>&2
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
|
+
health_fail() {
|
|
33
|
+
local error_code="$1"
|
|
34
|
+
local message="$2"
|
|
35
|
+
local db_status="${3:-unknown}"
|
|
36
|
+
local db_detail="${4:-}"
|
|
37
|
+
|
|
38
|
+
if [ "$JSON_OUT" -eq 1 ]; then
|
|
39
|
+
jq -nc \
|
|
40
|
+
--arg status "error" \
|
|
41
|
+
--arg command "health" \
|
|
42
|
+
--arg error "$error_code" \
|
|
43
|
+
--arg message "$message" \
|
|
44
|
+
--arg project "${project:-}" \
|
|
45
|
+
--arg db_status "$db_status" \
|
|
46
|
+
--arg db_detail "$db_detail" \
|
|
47
|
+
'{status:$status, command:$command, error:$error, message:$message,
|
|
48
|
+
project:$project, database:{integrity:{status:$db_status, detail:$db_detail}}}' >&3
|
|
49
|
+
else
|
|
50
|
+
eagle_fail "$message"
|
|
51
|
+
[ -n "$db_detail" ] && eagle_dim " $db_detail"
|
|
52
|
+
fi
|
|
53
|
+
exit 1
|
|
54
|
+
}
|
|
55
|
+
|
|
32
56
|
eagle_header "Health Check"
|
|
33
57
|
|
|
34
58
|
if [ -z "$project" ]; then
|
|
@@ -40,7 +64,18 @@ if [ -z "$project" ]; then
|
|
|
40
64
|
exit 1
|
|
41
65
|
fi
|
|
42
66
|
|
|
43
|
-
eagle_ensure_db
|
|
67
|
+
if ! eagle_ensure_db; then
|
|
68
|
+
health_fail "database_unavailable" "Database is unavailable; SQLite/FTS5 setup failed." "unavailable" "eagle_ensure_db failed"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
db_integrity_check=$(eagle_db_integrity_status "$EAGLE_MEM_DB" 2>/dev/null || true)
|
|
72
|
+
db_integrity_status="${db_integrity_check%%|*}"
|
|
73
|
+
db_integrity_detail="${db_integrity_check#*|}"
|
|
74
|
+
[ -n "$db_integrity_status" ] || db_integrity_status="unknown"
|
|
75
|
+
[ -n "$db_integrity_detail" ] || db_integrity_detail="not checked"
|
|
76
|
+
if [ "$db_integrity_status" != "ok" ]; then
|
|
77
|
+
health_fail "database_integrity" "Database integrity check failed; memory state is unreadable." "$db_integrity_status" "$db_integrity_detail"
|
|
78
|
+
fi
|
|
44
79
|
|
|
45
80
|
p_esc=$(eagle_sql_escape "$project")
|
|
46
81
|
|
|
@@ -340,7 +375,10 @@ if [ "$JSON_OUT" -eq 1 ]; then
|
|
|
340
375
|
--arg updates_status "$updates_status" \
|
|
341
376
|
--argjson noise_pct "$noise_pct" \
|
|
342
377
|
--arg last_curated "${last_curated:-never}" \
|
|
343
|
-
|
|
378
|
+
--arg db_integrity_status "$db_integrity_status" \
|
|
379
|
+
--arg db_integrity_detail "$db_integrity_detail" \
|
|
380
|
+
'{status:"ok", project:$project, score:$score, max:$max_score, pct:$pct, grade:$grade,
|
|
381
|
+
database:{integrity:{status:$db_integrity_status, detail:$db_integrity_detail}},
|
|
344
382
|
capture:{sessions:$total_sessions, summaries:$total_summaries, heuristic:$heuristic_summaries},
|
|
345
383
|
enrichment:$enriched_summaries,
|
|
346
384
|
features:$features, provider:$provider, provider_chain:$provider_chain,
|
package/scripts/help.sh
CHANGED
|
@@ -14,7 +14,7 @@ eagle_banner
|
|
|
14
14
|
|
|
15
15
|
echo -e " ${BOLD}Eagle Mem${RESET} ${DIM}v${version}${RESET}"
|
|
16
16
|
echo -e " ${DIM}Shared memory, release guardrails, RTK token protection, and worker lanes${RESET}"
|
|
17
|
-
echo -e " ${DIM}for Claude Code, Codex, Grok, and Google Antigravity.${RESET}"
|
|
17
|
+
echo -e " ${DIM}for Claude Code, Codex, OpenCode, Grok, and Google Antigravity.${RESET}"
|
|
18
18
|
echo ""
|
|
19
19
|
echo -e " ${BOLD}Core commands:${RESET}"
|
|
20
20
|
echo -e " ${CYAN}install${RESET} First-time setup: hooks, database, skills"
|
|
@@ -23,6 +23,10 @@ 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
25
|
echo -e " ${CYAN}doctor${RESET} Show install footprint, hooks, SQLite, manifest, and runtime drift"
|
|
26
|
+
echo -e " ${CYAN}repair${RESET} Preview or run safe SQLite memory DB recovery"
|
|
27
|
+
echo -e " ${CYAN}inspect${RESET} Inspect recall and hook observability events"
|
|
28
|
+
echo -e " ${CYAN}replay${RESET} Replay prompt, recall, injected context, and observed work"
|
|
29
|
+
echo -e " ${CYAN}dashboard${RESET} Generate a local HTML memory dashboard"
|
|
26
30
|
echo -e " ${CYAN}logs${RESET} Inspect/prune command-scoped scan/index/curate logs"
|
|
27
31
|
echo -e " ${CYAN}updates${RESET} Auto-update status and policy"
|
|
28
32
|
echo -e " ${CYAN}overview${RESET} Build or view project overview"
|
|
@@ -60,6 +64,10 @@ echo -e " ${DIM}\$${RESET} eagle-mem search --memories ${DIM}# mirrored m
|
|
|
60
64
|
echo -e " ${DIM}\$${RESET} eagle-mem search --tasks ${DIM}# in-flight tasks${RESET}"
|
|
61
65
|
echo -e " ${DIM}\$${RESET} eagle-mem search --files ${DIM}# hot files${RESET}"
|
|
62
66
|
echo -e " ${DIM}\$${RESET} eagle-mem search --stats ${DIM}# project stats${RESET}"
|
|
67
|
+
echo -e " ${DIM}\$${RESET} eagle-mem repair ${DIM}# preview DB recovery plan${RESET}"
|
|
68
|
+
echo -e " ${DIM}\$${RESET} eagle-mem inspect recall --last ${DIM}# latest UserPromptSubmit recall event${RESET}"
|
|
69
|
+
echo -e " ${DIM}\$${RESET} eagle-mem replay --last ${DIM}# replay latest recall session${RESET}"
|
|
70
|
+
echo -e " ${DIM}\$${RESET} eagle-mem dashboard ${DIM}# local HTML dashboard${RESET}"
|
|
63
71
|
echo -e " ${DIM}\$${RESET} eagle-mem session save --summary \"fixed auth\""
|
|
64
72
|
echo -e " ${DIM}\$${RESET} eagle-mem graph rebuild ${DIM}# rebuild code graph + chunks${RESET}"
|
|
65
73
|
echo -e " ${DIM}\$${RESET} eagle-mem index --force ${DIM}# force source chunk/declaration indexing${RESET}"
|
|
@@ -78,7 +86,7 @@ echo -e " ${DIM}\$${RESET} eagle-mem orchestrate spawn api ${DIM}# work
|
|
|
78
86
|
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate sync ${DIM}# reconcile worker status${RESET}"
|
|
79
87
|
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate handoff --write docs/handoff-context.md"
|
|
80
88
|
echo ""
|
|
81
|
-
echo -e " ${BOLD}Skills${RESET} ${DIM}(inside Claude Code, Codex, and Grok sessions):${RESET}"
|
|
89
|
+
echo -e " ${BOLD}Skills${RESET} ${DIM}(inside Claude Code, Codex, OpenCode, and Grok sessions):${RESET}"
|
|
82
90
|
echo -e " ${CYAN}eagle-mem-search${RESET} Search memory and past sessions"
|
|
83
91
|
echo -e " ${CYAN}eagle-mem-overview${RESET} Build or update project overview"
|
|
84
92
|
echo -e " ${CYAN}eagle-mem-memories${RESET} View/sync agent memories"
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Eagle Mem — Inspect
|
|
4
|
+
# Human-facing inspection surfaces for hook and recall observability.
|
|
5
|
+
# ═══════════════════════════════════════════════════════════
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
SCRIPTS_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
+
LIB_DIR="$SCRIPTS_DIR/../lib"
|
|
10
|
+
|
|
11
|
+
. "$SCRIPTS_DIR/style.sh"
|
|
12
|
+
. "$LIB_DIR/common.sh"
|
|
13
|
+
. "$LIB_DIR/db.sh"
|
|
14
|
+
|
|
15
|
+
action="${1:-recall}"
|
|
16
|
+
case "$action" in
|
|
17
|
+
recall|events) shift 2>/dev/null || true ;;
|
|
18
|
+
--help|-h|"") ;;
|
|
19
|
+
*)
|
|
20
|
+
eagle_err "Unknown inspect action: $action"
|
|
21
|
+
eagle_dim "Run: eagle-mem inspect --help"
|
|
22
|
+
exit 1
|
|
23
|
+
;;
|
|
24
|
+
esac
|
|
25
|
+
|
|
26
|
+
project=""
|
|
27
|
+
project_was_explicit=false
|
|
28
|
+
cross_project=false
|
|
29
|
+
session_id=""
|
|
30
|
+
limit=10
|
|
31
|
+
json_output=false
|
|
32
|
+
|
|
33
|
+
show_help() {
|
|
34
|
+
echo -e " ${BOLD}eagle-mem inspect${RESET} — Inspect Eagle Mem observability events"
|
|
35
|
+
echo ""
|
|
36
|
+
echo -e " ${BOLD}Usage:${RESET}"
|
|
37
|
+
echo -e " eagle-mem inspect recall ${DIM}# recent recall events${RESET}"
|
|
38
|
+
echo -e " eagle-mem inspect events ${DIM}# recent hook/action events${RESET}"
|
|
39
|
+
echo -e " eagle-mem inspect recall ${CYAN}--last${RESET} ${DIM}# latest recall event${RESET}"
|
|
40
|
+
echo -e " eagle-mem inspect recall ${CYAN}--json${RESET} ${DIM}# structured output${RESET}"
|
|
41
|
+
echo ""
|
|
42
|
+
echo -e " ${BOLD}Options:${RESET}"
|
|
43
|
+
echo -e " ${CYAN}-p, --project${RESET} <name> Project name (default: current dir scope)"
|
|
44
|
+
echo -e " ${CYAN}-s, --session${RESET} <id> Filter by agent session id"
|
|
45
|
+
echo -e " ${CYAN}-n, --limit${RESET} <N> Max events (default: 10)"
|
|
46
|
+
echo -e " ${CYAN}--all${RESET} Inspect all projects"
|
|
47
|
+
echo -e " ${CYAN}--last${RESET} Same as --limit 1"
|
|
48
|
+
echo -e " ${CYAN}-j, --json${RESET} Output structured JSON"
|
|
49
|
+
echo ""
|
|
50
|
+
exit 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
while [ $# -gt 0 ]; do
|
|
54
|
+
case "$1" in
|
|
55
|
+
--project|-p) project="$2"; project_was_explicit=true; shift 2 ;;
|
|
56
|
+
--session|-s) session_id="$2"; shift 2 ;;
|
|
57
|
+
--limit|-n) limit="$2"; shift 2 ;;
|
|
58
|
+
--last) limit=1; shift ;;
|
|
59
|
+
--all|-a) cross_project=true; shift ;;
|
|
60
|
+
--json|-j) json_output=true; shift ;;
|
|
61
|
+
--help|-h) show_help ;;
|
|
62
|
+
*)
|
|
63
|
+
eagle_err "Unknown option: $1"
|
|
64
|
+
exit 1
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
inspect_fail() {
|
|
70
|
+
local error_code="$1"
|
|
71
|
+
local message="$2"
|
|
72
|
+
local db_status="${3:-unknown}"
|
|
73
|
+
local db_detail="${4:-}"
|
|
74
|
+
|
|
75
|
+
if [ "$json_output" = true ]; then
|
|
76
|
+
jq -nc \
|
|
77
|
+
--arg status "error" \
|
|
78
|
+
--arg command "inspect" \
|
|
79
|
+
--arg action "$action" \
|
|
80
|
+
--arg error "$error_code" \
|
|
81
|
+
--arg message "$message" \
|
|
82
|
+
--arg project "${project:-}" \
|
|
83
|
+
--arg db_status "$db_status" \
|
|
84
|
+
--arg db_detail "$db_detail" \
|
|
85
|
+
'{status:$status, command:$command, action:$action, error:$error, message:$message,
|
|
86
|
+
project:$project, database:{integrity:{status:$db_status, detail:$db_detail}}}'
|
|
87
|
+
else
|
|
88
|
+
eagle_err "$message"
|
|
89
|
+
[ -n "$db_detail" ] && eagle_dim " $db_detail"
|
|
90
|
+
fi
|
|
91
|
+
exit 1
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if [ "$action" = "--help" ] || [ "$action" = "-h" ] || [ -z "$action" ]; then
|
|
95
|
+
show_help
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
if ! eagle_ensure_db; then
|
|
99
|
+
inspect_fail "database_unavailable" "Database is unavailable; SQLite/FTS5 setup failed." "unavailable" "eagle_ensure_db failed"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
db_integrity_check=$(eagle_db_integrity_status "$EAGLE_MEM_DB" 2>/dev/null || true)
|
|
103
|
+
db_integrity_status="${db_integrity_check%%|*}"
|
|
104
|
+
db_integrity_detail="${db_integrity_check#*|}"
|
|
105
|
+
[ -n "$db_integrity_status" ] || db_integrity_status="unknown"
|
|
106
|
+
[ -n "$db_integrity_detail" ] || db_integrity_detail="not checked"
|
|
107
|
+
if [ "$db_integrity_status" != "ok" ]; then
|
|
108
|
+
inspect_fail "database_integrity" "Database integrity check failed; inspection is unavailable." "$db_integrity_status" "$db_integrity_detail"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [ "$action" = "recall" ] && [ -z "$(eagle_db "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'recall_events' LIMIT 1;" 2>/dev/null || true)" ]; then
|
|
112
|
+
inspect_fail "migration_missing" "Recall inspection is unavailable until migrations create recall_events." "ok" "run: eagle-mem update"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [ "$action" = "events" ] && [ -z "$(eagle_db "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'eagle_events' LIMIT 1;" 2>/dev/null || true)" ]; then
|
|
116
|
+
inspect_fail "migration_missing" "Event inspection is unavailable until migrations create eagle_events." "ok" "run: eagle-mem update"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
limit=$(eagle_sql_int "$limit")
|
|
120
|
+
[ "$limit" -le 0 ] 2>/dev/null && limit=10
|
|
121
|
+
|
|
122
|
+
if [ -z "$project" ] && [ "$cross_project" = false ]; then
|
|
123
|
+
project=$(eagle_project_from_cwd "$(pwd)")
|
|
124
|
+
fi
|
|
125
|
+
if [ "$cross_project" = false ] && [ "$project_was_explicit" = false ]; then
|
|
126
|
+
project=$(eagle_recall_project_scope_from_cwd "$(pwd)" "$project")
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
recall_inspect() {
|
|
130
|
+
local where_clause="1 = 1"
|
|
131
|
+
local project_label="$project"
|
|
132
|
+
|
|
133
|
+
if [ "$cross_project" = false ]; then
|
|
134
|
+
where_clause="$where_clause AND $(eagle_sql_project_scope_condition "project" "$project")"
|
|
135
|
+
project_label=$(eagle_project_scope_label "$project")
|
|
136
|
+
else
|
|
137
|
+
project_label="all projects"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
if [ -n "$session_id" ]; then
|
|
141
|
+
local sid_sql
|
|
142
|
+
sid_sql=$(eagle_sql_escape "$session_id")
|
|
143
|
+
where_clause="$where_clause AND session_id = '$sid_sql'"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
local events_json
|
|
147
|
+
events_json=$(eagle_db_json "SELECT id, session_id, project, agent, hook_name, prompt_snippet, fts_query,
|
|
148
|
+
summary_matches, memory_matches, code_matches, injected_chars,
|
|
149
|
+
injected_token_estimate, status, error, created_at
|
|
150
|
+
FROM recall_events
|
|
151
|
+
WHERE $where_clause
|
|
152
|
+
ORDER BY created_at DESC, id DESC
|
|
153
|
+
LIMIT $limit;")
|
|
154
|
+
[ -n "$events_json" ] || events_json="[]"
|
|
155
|
+
|
|
156
|
+
if [ "$json_output" = true ]; then
|
|
157
|
+
jq -nc \
|
|
158
|
+
--arg status "ok" \
|
|
159
|
+
--arg command "inspect" \
|
|
160
|
+
--arg action "recall" \
|
|
161
|
+
--arg project "$project_label" \
|
|
162
|
+
--arg db_integrity_status "$db_integrity_status" \
|
|
163
|
+
--arg db_integrity_detail "$db_integrity_detail" \
|
|
164
|
+
--argjson events "$events_json" \
|
|
165
|
+
'{status:$status, command:$command, action:$action, project:$project,
|
|
166
|
+
database:{integrity:{status:$db_integrity_status, detail:$db_integrity_detail}},
|
|
167
|
+
events:$events}'
|
|
168
|
+
return
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
eagle_header "Recall Inspector"
|
|
172
|
+
eagle_info "Project: $project_label"
|
|
173
|
+
[ -n "$session_id" ] && eagle_info "Session: $session_id"
|
|
174
|
+
echo ""
|
|
175
|
+
|
|
176
|
+
if [ "$(printf '%s' "$events_json" | jq 'length')" -eq 0 ]; then
|
|
177
|
+
eagle_dim "No recall events recorded yet."
|
|
178
|
+
eagle_dim "UserPromptSubmit records events after migrations include recall_events."
|
|
179
|
+
echo ""
|
|
180
|
+
return
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
printf '%s' "$events_json" | jq -c '.[]' | while IFS= read -r event; do
|
|
184
|
+
local created agent prompt query summaries memories code tokens status event_project sid
|
|
185
|
+
created=$(printf '%s' "$event" | jq -r '.created_at // ""')
|
|
186
|
+
agent=$(printf '%s' "$event" | jq -r '.agent // ""')
|
|
187
|
+
event_project=$(printf '%s' "$event" | jq -r '.project // ""')
|
|
188
|
+
sid=$(printf '%s' "$event" | jq -r '.session_id // ""')
|
|
189
|
+
prompt=$(printf '%s' "$event" | jq -r '.prompt_snippet // ""')
|
|
190
|
+
query=$(printf '%s' "$event" | jq -r '.fts_query // ""')
|
|
191
|
+
summaries=$(printf '%s' "$event" | jq -r '.summary_matches // 0')
|
|
192
|
+
memories=$(printf '%s' "$event" | jq -r '.memory_matches // 0')
|
|
193
|
+
code=$(printf '%s' "$event" | jq -r '.code_matches // 0')
|
|
194
|
+
tokens=$(printf '%s' "$event" | jq -r '.injected_token_estimate // 0')
|
|
195
|
+
status=$(printf '%s' "$event" | jq -r '.status // "unknown"')
|
|
196
|
+
|
|
197
|
+
echo -e " ${BOLD}${created}${RESET} ${DIM}$(eagle_agent_label "$agent")${RESET} ${CYAN}${status}${RESET}"
|
|
198
|
+
[ "$cross_project" = true ] && echo -e " ${DIM}Project:${RESET} $event_project"
|
|
199
|
+
[ -n "$sid" ] && echo -e " ${DIM}Session:${RESET} $sid"
|
|
200
|
+
[ -n "$prompt" ] && echo -e " ${DIM}Prompt:${RESET} $prompt"
|
|
201
|
+
[ -n "$query" ] && echo -e " ${DIM}Query:${RESET} $query"
|
|
202
|
+
echo -e " ${DIM}Retrieved:${RESET} summaries=$summaries memories=$memories code=$code ${DIM}Injected:${RESET} ~${tokens} tokens"
|
|
203
|
+
echo ""
|
|
204
|
+
done
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
events_inspect() {
|
|
208
|
+
local where_clause="1 = 1"
|
|
209
|
+
local project_label="$project"
|
|
210
|
+
|
|
211
|
+
if [ "$cross_project" = false ]; then
|
|
212
|
+
where_clause="$where_clause AND $(eagle_sql_project_scope_condition "project" "$project")"
|
|
213
|
+
project_label=$(eagle_project_scope_label "$project")
|
|
214
|
+
else
|
|
215
|
+
project_label="all projects"
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
if [ -n "$session_id" ]; then
|
|
219
|
+
local sid_sql
|
|
220
|
+
sid_sql=$(eagle_sql_escape "$session_id")
|
|
221
|
+
where_clause="$where_clause AND session_id = '$sid_sql'"
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
local events_json
|
|
225
|
+
events_json=$(eagle_db_json "SELECT id, session_id, project, agent, event_type, command,
|
|
226
|
+
hook_event_name, status, detail_json, created_at
|
|
227
|
+
FROM eagle_events
|
|
228
|
+
WHERE $where_clause
|
|
229
|
+
ORDER BY created_at DESC, id DESC
|
|
230
|
+
LIMIT $limit;")
|
|
231
|
+
[ -n "$events_json" ] || events_json="[]"
|
|
232
|
+
|
|
233
|
+
if [ "$json_output" = true ]; then
|
|
234
|
+
jq -nc \
|
|
235
|
+
--arg status "ok" \
|
|
236
|
+
--arg command "inspect" \
|
|
237
|
+
--arg action "events" \
|
|
238
|
+
--arg project "$project_label" \
|
|
239
|
+
--arg db_integrity_status "$db_integrity_status" \
|
|
240
|
+
--arg db_integrity_detail "$db_integrity_detail" \
|
|
241
|
+
--argjson events "$events_json" \
|
|
242
|
+
'{status:$status, command:$command, action:$action, project:$project,
|
|
243
|
+
database:{integrity:{status:$db_integrity_status, detail:$db_integrity_detail}},
|
|
244
|
+
events:($events | map(.detail = ((.detail_json // "{}") | fromjson? // {}) | del(.detail_json)))}'
|
|
245
|
+
return
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
eagle_header "Event Inspector"
|
|
249
|
+
eagle_info "Project: $project_label"
|
|
250
|
+
[ -n "$session_id" ] && eagle_info "Session: $session_id"
|
|
251
|
+
echo ""
|
|
252
|
+
|
|
253
|
+
if [ "$(printf '%s' "$events_json" | jq 'length')" -eq 0 ]; then
|
|
254
|
+
eagle_dim "No Eagle events recorded yet."
|
|
255
|
+
eagle_dim "Hooks record events after migrations include eagle_events."
|
|
256
|
+
echo ""
|
|
257
|
+
return
|
|
258
|
+
fi
|
|
259
|
+
|
|
260
|
+
printf '%s' "$events_json" | jq -c '.[]' | while IFS= read -r event; do
|
|
261
|
+
local created agent event_type hook status event_project sid detail
|
|
262
|
+
created=$(printf '%s' "$event" | jq -r '.created_at // ""')
|
|
263
|
+
agent=$(printf '%s' "$event" | jq -r '.agent // ""')
|
|
264
|
+
event_project=$(printf '%s' "$event" | jq -r '.project // ""')
|
|
265
|
+
sid=$(printf '%s' "$event" | jq -r '.session_id // ""')
|
|
266
|
+
event_type=$(printf '%s' "$event" | jq -r '.event_type // ""')
|
|
267
|
+
hook=$(printf '%s' "$event" | jq -r '.hook_event_name // ""')
|
|
268
|
+
status=$(printf '%s' "$event" | jq -r '.status // "unknown"')
|
|
269
|
+
detail=$(printf '%s' "$event" | jq -r '(.detail_json // "{}") | fromjson? | to_entries | map("\(.key)=\(.value|tostring)") | join(", ")' 2>/dev/null)
|
|
270
|
+
|
|
271
|
+
echo -e " ${BOLD}${created}${RESET} ${CYAN}${event_type}${RESET} ${DIM}${status}${RESET}"
|
|
272
|
+
[ "$cross_project" = true ] && echo -e " ${DIM}Project:${RESET} $event_project"
|
|
273
|
+
[ -n "$agent" ] && echo -e " ${DIM}Agent:${RESET} $(eagle_agent_label "$agent")"
|
|
274
|
+
[ -n "$sid" ] && echo -e " ${DIM}Session:${RESET} $sid"
|
|
275
|
+
[ -n "$hook" ] && echo -e " ${DIM}Hook:${RESET} $hook"
|
|
276
|
+
[ -n "$detail" ] && echo -e " ${DIM}Detail:${RESET} $detail"
|
|
277
|
+
echo ""
|
|
278
|
+
done
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
case "$action" in
|
|
282
|
+
recall) recall_inspect ;;
|
|
283
|
+
events) events_inspect ;;
|
|
284
|
+
*) show_help ;;
|
|
285
|
+
esac
|
package/scripts/install.sh
CHANGED
|
@@ -50,6 +50,7 @@ LIB_DIR="$SCRIPTS_DIR/../lib"
|
|
|
50
50
|
. "$LIB_DIR/common.sh"
|
|
51
51
|
. "$LIB_DIR/hooks.sh"
|
|
52
52
|
. "$LIB_DIR/codex-hooks.sh"
|
|
53
|
+
. "$LIB_DIR/opencode-hooks.sh"
|
|
53
54
|
|
|
54
55
|
SETTINGS="$EAGLE_SETTINGS"
|
|
55
56
|
|
|
@@ -184,6 +185,7 @@ ensure_rtk
|
|
|
184
185
|
claude_found=false
|
|
185
186
|
codex_found=false
|
|
186
187
|
grok_found=false
|
|
188
|
+
opencode_found=false
|
|
187
189
|
|
|
188
190
|
if [ -d "$HOME/.claude" ]; then
|
|
189
191
|
eagle_ok "Claude Code ${DIM}(~/.claude/)${RESET}"
|
|
@@ -209,10 +211,17 @@ else
|
|
|
209
211
|
eagle_warn "Grok not found ${DIM}(~/.grok/ does not exist)${RESET}"
|
|
210
212
|
fi
|
|
211
213
|
|
|
212
|
-
if
|
|
214
|
+
if eagle_opencode_detected; then
|
|
215
|
+
opencode_found=true
|
|
216
|
+
eagle_ok "OpenCode ${DIM}($EAGLE_OPENCODE_DIR/)${RESET}"
|
|
217
|
+
else
|
|
218
|
+
eagle_warn "OpenCode not found ${DIM}(~/.config/opencode/ missing and opencode not on PATH)${RESET}"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
if [ "$claude_found" = false ] && [ "$codex_found" = false ] && [ "$grok_found" = false ] && [ "$opencode_found" = false ]; then
|
|
213
222
|
eagle_fail "No supported agent install found"
|
|
214
223
|
echo ""
|
|
215
|
-
eagle_dim "Install Claude Code, Codex, or ensure ~/.grok/ exists, then re-run."
|
|
224
|
+
eagle_dim "Install Claude Code, Codex, OpenCode, or ensure ~/.grok/ exists, then re-run."
|
|
216
225
|
echo ""
|
|
217
226
|
exit 1
|
|
218
227
|
fi
|
|
@@ -223,7 +232,7 @@ if [ "$prereqs_ok" = false ]; then
|
|
|
223
232
|
exit 1
|
|
224
233
|
fi
|
|
225
234
|
|
|
226
|
-
eagle_runtime_change_plan "install" "$PACKAGE_DIR" "$claude_found" "$codex_found"
|
|
235
|
+
eagle_runtime_change_plan "install" "$PACKAGE_DIR" "$claude_found" "$codex_found" "$opencode_found"
|
|
227
236
|
|
|
228
237
|
echo ""
|
|
229
238
|
|
|
@@ -278,14 +287,15 @@ if [ "$claude_found" = true ]; then
|
|
|
278
287
|
"$EAGLE_MEM_DIR/hooks/session-start.sh" \
|
|
279
288
|
"SessionStart hook"
|
|
280
289
|
|
|
281
|
-
eagle_patch_hook "$SETTINGS" "Stop" "" \
|
|
282
|
-
"$EAGLE_MEM_DIR/hooks/stop.sh" \
|
|
283
|
-
"Stop hook"
|
|
284
|
-
|
|
285
290
|
# Clean old registrations before re-registering (handles matcher changes across versions)
|
|
291
|
+
eagle_clean_hook_entries "$SETTINGS" "Stop" "$EAGLE_MEM_DIR/hooks/stop.sh"
|
|
286
292
|
eagle_clean_hook_entries "$SETTINGS" "PostToolUse" "$EAGLE_MEM_DIR/hooks/post-tool-use.sh"
|
|
287
293
|
eagle_clean_hook_entries "$SETTINGS" "PreToolUse" "$EAGLE_MEM_DIR/hooks/pre-tool-use.sh"
|
|
288
294
|
|
|
295
|
+
eagle_patch_hook "$SETTINGS" "Stop" "" \
|
|
296
|
+
"bash \"$EAGLE_MEM_DIR/hooks/stop.sh\"" \
|
|
297
|
+
"Stop hook"
|
|
298
|
+
|
|
289
299
|
eagle_patch_hook "$SETTINGS" "PostToolUse" "Read|Write|Edit|Bash|TaskUpdate" \
|
|
290
300
|
"$EAGLE_MEM_DIR/hooks/post-tool-use.sh" \
|
|
291
301
|
"PostToolUse hook"
|
|
@@ -309,6 +319,11 @@ if [ "$claude_found" = true ]; then
|
|
|
309
319
|
eagle_patch_hook "$SETTINGS" "PreToolUse" "Bash|Read|Edit|Write" \
|
|
310
320
|
"$EAGLE_MEM_DIR/hooks/pre-tool-use.sh" \
|
|
311
321
|
"PreToolUse hook"
|
|
322
|
+
|
|
323
|
+
# Allow agent-issued session capture to run without a permission prompt
|
|
324
|
+
if eagle_patch_permission_allow "$SETTINGS" "Bash(eagle-mem session save:*)"; then
|
|
325
|
+
eagle_ok "Capture permission ${DIM}(eagle-mem session save)${RESET}"
|
|
326
|
+
fi
|
|
312
327
|
fi
|
|
313
328
|
else
|
|
314
329
|
eagle_info "Claude hooks skipped ${DIM}(Claude Code not detected)${RESET}"
|
|
@@ -324,6 +339,12 @@ else
|
|
|
324
339
|
eagle_info "Codex hooks skipped ${DIM}(Codex not detected)${RESET}"
|
|
325
340
|
fi
|
|
326
341
|
|
|
342
|
+
if [ "$opencode_found" = true ]; then
|
|
343
|
+
eagle_install_opencode_plugin "$PACKAGE_DIR" "$DRY_RUN"
|
|
344
|
+
else
|
|
345
|
+
eagle_info "OpenCode plugin skipped ${DIM}(OpenCode not detected)${RESET}"
|
|
346
|
+
fi
|
|
347
|
+
|
|
327
348
|
# ─── Install skills ────────────────────────────────────────
|
|
328
349
|
|
|
329
350
|
if [ "$claude_found" = true ] && [ -d "$PACKAGE_DIR/skills" ]; then
|
|
@@ -374,6 +395,10 @@ if [ "$grok_found" = true ] && [ -d "$PACKAGE_DIR/skills" ]; then
|
|
|
374
395
|
fi
|
|
375
396
|
fi
|
|
376
397
|
|
|
398
|
+
if [ "$opencode_found" = true ] && [ -d "$PACKAGE_DIR/skills" ]; then
|
|
399
|
+
eagle_install_opencode_skills "$PACKAGE_DIR" "$DRY_RUN"
|
|
400
|
+
fi
|
|
401
|
+
|
|
377
402
|
# ─── Statusline integration ───────────────────────────────
|
|
378
403
|
|
|
379
404
|
if [ "$claude_found" = true ]; then
|
|
@@ -510,12 +535,16 @@ eagle_kv "Hooks:" "$EAGLE_MEM_DIR/hooks/"
|
|
|
510
535
|
[ "$claude_found" = true ] && eagle_kv "Claude settings:" "$SETTINGS"
|
|
511
536
|
[ "$codex_found" = true ] && eagle_kv "Codex hooks:" "$EAGLE_CODEX_HOOKS"
|
|
512
537
|
[ "$grok_found" = true ] && eagle_kv "Grok skills:" "$EAGLE_GROK_SKILLS_DIR"
|
|
538
|
+
[ "$opencode_found" = true ] && eagle_kv "OpenCode plugin:" "$EAGLE_OPENCODE_PLUGIN"
|
|
513
539
|
eagle_kv "Antigravity Hook:" "$EAGLE_MEM_DIR/integrations/google_antigravity_hook.py"
|
|
514
540
|
|
|
515
541
|
echo ""
|
|
516
542
|
if [ "$grok_found" = true ]; then
|
|
517
543
|
eagle_dim "Grok skills installed. Run 'eagle-mem grok-bootstrap' for setup guidance and recall."
|
|
518
544
|
fi
|
|
545
|
+
if [ "$opencode_found" = true ]; then
|
|
546
|
+
eagle_dim "Start a new OpenCode session without --pure — Eagle Mem will activate through the global local plugin."
|
|
547
|
+
fi
|
|
519
548
|
if [ "$claude_found" = true ] || [ "$codex_found" = true ]; then
|
|
520
549
|
eagle_dim "Start a new Claude Code or Codex session — Eagle Mem will activate automatically."
|
|
521
550
|
fi
|
package/scripts/memories.sh
CHANGED
|
@@ -109,6 +109,17 @@ if [ "$cross_project" = false ] && [ "$project_was_explicit" = false ]; then
|
|
|
109
109
|
project=$(eagle_recall_project_scope_from_cwd "$(pwd)" "$project")
|
|
110
110
|
fi
|
|
111
111
|
|
|
112
|
+
db_integrity_check=$(eagle_db_integrity_status "$EAGLE_MEM_DB" 2>/dev/null || true)
|
|
113
|
+
db_integrity_status="${db_integrity_check%%|*}"
|
|
114
|
+
db_integrity_detail="${db_integrity_check#*|}"
|
|
115
|
+
[ -n "$db_integrity_status" ] || db_integrity_status="unknown"
|
|
116
|
+
[ -n "$db_integrity_detail" ] || db_integrity_detail="not checked"
|
|
117
|
+
if [ "$db_integrity_status" != "ok" ]; then
|
|
118
|
+
eagle_err "Database integrity check failed; memories and graph are unavailable."
|
|
119
|
+
eagle_dim " $db_integrity_detail"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
112
123
|
eagle_age_label() {
|
|
113
124
|
local updated="${1:-}"
|
|
114
125
|
[ -z "$updated" ] && { printf 'unknown'; return; }
|
|
@@ -975,6 +986,8 @@ memories_graph() {
|
|
|
975
986
|
file_count=$(eagle_graph_rebuild_codebase "$project" "$target_dir")
|
|
976
987
|
eagle_ok "Rebuilt file graph ($file_count files)"
|
|
977
988
|
bash "$SCRIPTS_DIR/index.sh" --force "$target_dir"
|
|
989
|
+
context_count=$(eagle_graph_wire_project_context_edges "$project")
|
|
990
|
+
eagle_ok "Wired durable context graph ($context_count nodes)"
|
|
978
991
|
eagle_footer "Graph rebuild complete."
|
|
979
992
|
;;
|
|
980
993
|
summary|*)
|