eagle-mem 3.0.0 → 3.0.2
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/db/015_integrity_fixes.sql +156 -0
- package/db/migrate.sh +3 -0
- package/hooks/post-tool-use.sh +18 -147
- package/hooks/pre-tool-use.sh +4 -23
- package/hooks/session-end.sh +4 -1
- package/hooks/session-start.sh +23 -29
- package/hooks/stop.sh +6 -3
- package/lib/common.sh +34 -8
- package/lib/db-backfill.sh +96 -0
- package/lib/db-core.sh +65 -0
- package/lib/db-features.sh +160 -0
- package/lib/db-mirrors.sh +264 -0
- package/lib/db-observations.sh +77 -0
- package/lib/db-sessions.sh +68 -0
- package/lib/db-summaries.sh +142 -0
- package/lib/db.sh +14 -706
- package/lib/hooks-posttool.sh +138 -0
- package/lib/provider.sh +22 -6
- package/package.json +1 -1
- package/scripts/curate.sh +16 -0
- package/scripts/install.sh +5 -2
- package/scripts/memories.sh +3 -3
- package/scripts/uninstall.sh +1 -1
- package/scripts/update.sh +5 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Eagle Mem — Session helpers
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
[ -n "${_EAGLE_DB_SESSIONS_LOADED:-}" ] && return 0
|
|
6
|
+
_EAGLE_DB_SESSIONS_LOADED=1
|
|
7
|
+
|
|
8
|
+
eagle_upsert_session() {
|
|
9
|
+
local session_id; session_id=$(eagle_sql_escape "$1")
|
|
10
|
+
local project; project=$(eagle_sql_escape "$2")
|
|
11
|
+
local cwd; cwd=$(eagle_sql_escape "${3:-}")
|
|
12
|
+
local model; model=$(eagle_sql_escape "${4:-}")
|
|
13
|
+
local source; source=$(eagle_sql_escape "${5:-}")
|
|
14
|
+
|
|
15
|
+
eagle_db "INSERT INTO sessions (id, project, cwd, model, source, last_activity_at)
|
|
16
|
+
VALUES ('$session_id', '$project', '$cwd', '$model', '$source', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
17
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
18
|
+
cwd = COALESCE(excluded.cwd, sessions.cwd),
|
|
19
|
+
model = COALESCE(excluded.model, sessions.model),
|
|
20
|
+
source = COALESCE(excluded.source, sessions.source),
|
|
21
|
+
status = 'active',
|
|
22
|
+
last_activity_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now');"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
eagle_end_session() {
|
|
26
|
+
local session_id; session_id=$(eagle_sql_escape "$1")
|
|
27
|
+
eagle_db "UPDATE sessions SET status = 'completed', ended_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = '$session_id';"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
eagle_abandon_stale_sessions() {
|
|
31
|
+
local exclude_sid="${1:-}"
|
|
32
|
+
local exclude_clause=""
|
|
33
|
+
if [ -n "$exclude_sid" ]; then
|
|
34
|
+
exclude_clause="AND id != '$(eagle_sql_escape "$exclude_sid")'"
|
|
35
|
+
fi
|
|
36
|
+
eagle_db "UPDATE sessions SET status = 'abandoned'
|
|
37
|
+
WHERE status = 'active'
|
|
38
|
+
$exclude_clause
|
|
39
|
+
AND COALESCE(last_activity_at, started_at) < strftime('%Y-%m-%dT%H:%M:%fZ', 'now', '-7 days');"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
eagle_get_project_stats() {
|
|
43
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
44
|
+
eagle_db_pipe <<SQL
|
|
45
|
+
SELECT 'sessions|' || COUNT(*) FROM sessions WHERE project = '$project';
|
|
46
|
+
SELECT 'summaries|' || COUNT(*) FROM summaries WHERE project = '$project';
|
|
47
|
+
SELECT 'with_summaries|' || COUNT(*) FROM summaries WHERE project = '$project' AND request IS NOT NULL AND request != '';
|
|
48
|
+
SELECT 'memories|' || COUNT(*) FROM claude_memories WHERE project = '$project';
|
|
49
|
+
SELECT 'plans|' || COUNT(*) FROM claude_plans WHERE project = '$project';
|
|
50
|
+
SELECT 'tasks_pending|' || COUNT(*) FROM claude_tasks WHERE project = '$project' AND status = 'pending';
|
|
51
|
+
SELECT 'tasks_progress|' || COUNT(*) FROM claude_tasks WHERE project = '$project' AND status = 'in_progress';
|
|
52
|
+
SELECT 'tasks_done|' || COUNT(*) FROM claude_tasks WHERE project = '$project' AND status = 'completed';
|
|
53
|
+
SELECT 'chunks|' || COUNT(*) FROM code_chunks WHERE project = '$project';
|
|
54
|
+
SELECT 'observations|' || COUNT(*) FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE project = '$project');
|
|
55
|
+
SELECT 'last_active|' || COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE project = '$project';
|
|
56
|
+
SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60) FROM summaries WHERE project = '$project' ORDER BY created_at DESC LIMIT 1), '');
|
|
57
|
+
SQL
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
eagle_get_session_project() {
|
|
61
|
+
local sid; sid=$(eagle_sql_escape "$1")
|
|
62
|
+
eagle_db "SELECT project FROM sessions WHERE id = '$sid' LIMIT 1;"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
eagle_count_session_summaries() {
|
|
66
|
+
local sid; sid=$(eagle_sql_escape "$1")
|
|
67
|
+
eagle_db "SELECT COUNT(*) FROM summaries WHERE session_id = '$sid';"
|
|
68
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Eagle Mem — Summary + overview helpers
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
[ -n "${_EAGLE_DB_SUMMARIES_LOADED:-}" ] && return 0
|
|
6
|
+
_EAGLE_DB_SUMMARIES_LOADED=1
|
|
7
|
+
|
|
8
|
+
eagle_insert_summary() {
|
|
9
|
+
local session_id; session_id=$(eagle_sql_escape "$1")
|
|
10
|
+
local project; project=$(eagle_sql_escape "$2")
|
|
11
|
+
local request; request=$(eagle_sql_escape "$3")
|
|
12
|
+
local investigated; investigated=$(eagle_sql_escape "$4")
|
|
13
|
+
local learned; learned=$(eagle_sql_escape "$5")
|
|
14
|
+
local completed; completed=$(eagle_sql_escape "$6")
|
|
15
|
+
local next_steps; next_steps=$(eagle_sql_escape "$7")
|
|
16
|
+
local files_read; files_read=$(eagle_sql_escape "$8")
|
|
17
|
+
local files_modified; files_modified=$(eagle_sql_escape "$9")
|
|
18
|
+
local notes; notes=$(eagle_sql_escape "${10:-}")
|
|
19
|
+
local decisions; decisions=$(eagle_sql_escape "${11:-}")
|
|
20
|
+
local gotchas; gotchas=$(eagle_sql_escape "${12:-}")
|
|
21
|
+
local key_files; key_files=$(eagle_sql_escape "${13:-}")
|
|
22
|
+
|
|
23
|
+
eagle_db_pipe <<SQL
|
|
24
|
+
INSERT INTO summaries (session_id, project, request, investigated, learned, completed, next_steps, files_read, files_modified, notes, decisions, gotchas, key_files)
|
|
25
|
+
VALUES (
|
|
26
|
+
'$session_id',
|
|
27
|
+
'$project',
|
|
28
|
+
'$request',
|
|
29
|
+
'$investigated',
|
|
30
|
+
'$learned',
|
|
31
|
+
'$completed',
|
|
32
|
+
'$next_steps',
|
|
33
|
+
'$files_read',
|
|
34
|
+
'$files_modified',
|
|
35
|
+
'$notes',
|
|
36
|
+
'$decisions',
|
|
37
|
+
'$gotchas',
|
|
38
|
+
'$key_files'
|
|
39
|
+
)
|
|
40
|
+
ON CONFLICT(session_id) DO UPDATE SET
|
|
41
|
+
project = excluded.project,
|
|
42
|
+
request = COALESCE(NULLIF(excluded.request, ''), summaries.request),
|
|
43
|
+
investigated = COALESCE(NULLIF(excluded.investigated, ''), summaries.investigated),
|
|
44
|
+
learned = COALESCE(NULLIF(excluded.learned, ''), summaries.learned),
|
|
45
|
+
completed = COALESCE(NULLIF(excluded.completed, ''), summaries.completed),
|
|
46
|
+
next_steps = COALESCE(NULLIF(excluded.next_steps, ''), summaries.next_steps),
|
|
47
|
+
files_read = COALESCE(NULLIF(excluded.files_read, '[]'), summaries.files_read),
|
|
48
|
+
files_modified = COALESCE(NULLIF(excluded.files_modified, '[]'), summaries.files_modified),
|
|
49
|
+
notes = COALESCE(NULLIF(excluded.notes, ''), summaries.notes),
|
|
50
|
+
decisions = COALESCE(NULLIF(excluded.decisions, ''), summaries.decisions),
|
|
51
|
+
gotchas = COALESCE(NULLIF(excluded.gotchas, ''), summaries.gotchas),
|
|
52
|
+
key_files = COALESCE(NULLIF(excluded.key_files, ''), summaries.key_files);
|
|
53
|
+
SQL
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
eagle_get_recent_summaries() {
|
|
57
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
58
|
+
local limit; limit=$(eagle_sql_int "${2:-5}")
|
|
59
|
+
|
|
60
|
+
eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.decisions, s.gotchas, s.key_files
|
|
61
|
+
FROM summaries s
|
|
62
|
+
WHERE s.project = '$project'
|
|
63
|
+
AND s.request NOT LIKE '%<local-command-caveat>%'
|
|
64
|
+
ORDER BY s.created_at DESC
|
|
65
|
+
LIMIT $limit;"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
eagle_search_summaries() {
|
|
69
|
+
local query; query=$(eagle_fts_sanitize "$1")
|
|
70
|
+
query=$(eagle_sql_escape "$query")
|
|
71
|
+
local project="${2:-}"
|
|
72
|
+
local limit; limit=$(eagle_sql_int "${3:-10}")
|
|
73
|
+
|
|
74
|
+
local where_clause=""
|
|
75
|
+
if [ -n "$project" ]; then
|
|
76
|
+
project=$(eagle_sql_escape "$project")
|
|
77
|
+
where_clause="AND s.project = '$project'"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
eagle_db "SELECT s.request, s.completed, s.learned, s.next_steps, s.created_at, s.project, s.decisions, s.gotchas, s.key_files
|
|
81
|
+
FROM summaries s
|
|
82
|
+
JOIN summaries_fts f ON f.rowid = s.id
|
|
83
|
+
WHERE summaries_fts MATCH '$query'
|
|
84
|
+
$where_clause
|
|
85
|
+
ORDER BY rank
|
|
86
|
+
LIMIT $limit;"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
eagle_upsert_overview() {
|
|
90
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
91
|
+
local raw_content="$2"
|
|
92
|
+
local ov_source; ov_source=$(eagle_sql_escape "${3:-manual}")
|
|
93
|
+
|
|
94
|
+
if [ ${#raw_content} -gt 16384 ]; then
|
|
95
|
+
raw_content="${raw_content:0:16384}"
|
|
96
|
+
eagle_log "WARN" "Overview for '$1' truncated to 16 KB (was ${#2} bytes)"
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
local content; content=$(eagle_sql_escape "$raw_content")
|
|
100
|
+
|
|
101
|
+
eagle_db "INSERT INTO overviews (project, content, source, updated_at)
|
|
102
|
+
VALUES ('$project', '$content', '$ov_source', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
103
|
+
ON CONFLICT(project) DO UPDATE SET
|
|
104
|
+
content = excluded.content,
|
|
105
|
+
source = excluded.source,
|
|
106
|
+
updated_at = excluded.updated_at;"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
eagle_get_overview_source() {
|
|
110
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
111
|
+
eagle_db "SELECT source FROM overviews WHERE project = '$project';"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
eagle_get_overview() {
|
|
115
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
116
|
+
eagle_db "SELECT content FROM overviews WHERE project = '$project';"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
eagle_search_decisions_for_file() {
|
|
120
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
121
|
+
local fts_query; fts_query=$(eagle_sql_escape "$2")
|
|
122
|
+
eagle_db "SELECT s.decisions
|
|
123
|
+
FROM summaries s
|
|
124
|
+
JOIN summaries_fts f ON f.rowid = s.id
|
|
125
|
+
WHERE summaries_fts MATCH '$fts_query'
|
|
126
|
+
AND s.project = '$project'
|
|
127
|
+
AND s.decisions IS NOT NULL
|
|
128
|
+
AND s.decisions != ''
|
|
129
|
+
ORDER BY s.created_at DESC
|
|
130
|
+
LIMIT 1;"
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
eagle_search_stale_memories() {
|
|
134
|
+
local project; project=$(eagle_sql_escape "$1")
|
|
135
|
+
local fts_query; fts_query=$(eagle_sql_escape "$2")
|
|
136
|
+
eagle_db "SELECT m.memory_name
|
|
137
|
+
FROM claude_memories m
|
|
138
|
+
JOIN claude_memories_fts f ON f.rowid = m.id
|
|
139
|
+
WHERE claude_memories_fts MATCH '$fts_query'
|
|
140
|
+
AND m.project = '$project'
|
|
141
|
+
LIMIT 1;"
|
|
142
|
+
}
|