eagle-mem 4.7.1 → 4.8.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/README.md +46 -4
- package/bin/eagle-mem +1 -0
- package/db/029_orchestration_lanes.sql +45 -0
- package/db/030_orchestration_lane_scope.sql +88 -0
- package/db/031_orchestration_workers.sql +20 -0
- package/db/032_orchestration_run_keys.sql +9 -0
- package/hooks/pre-tool-use.sh +24 -1
- package/hooks/session-start.sh +92 -10
- package/hooks/stop.sh +14 -13
- package/hooks/user-prompt-submit.sh +70 -12
- package/lib/common.sh +170 -3
- package/lib/db-observations.sh +7 -0
- package/lib/db-sessions.sh +7 -1
- package/lib/db-summaries.sh +6 -2
- package/lib/provider.sh +34 -0
- package/package.json +3 -1
- package/scripts/config.sh +30 -0
- package/scripts/health.sh +66 -0
- package/scripts/help.sh +12 -1
- package/scripts/orchestrate.sh +1268 -0
- package/skills/eagle-mem-orchestrate/SKILL.md +149 -0
- package/skills/eagle-mem-tasks/SKILL.md +2 -0
|
@@ -26,6 +26,8 @@ agent=$(eagle_agent_source_from_json "$input")
|
|
|
26
26
|
[ -z "$user_prompt" ] && exit 0
|
|
27
27
|
|
|
28
28
|
project=$(eagle_project_from_cwd "$cwd")
|
|
29
|
+
codex_compact=0
|
|
30
|
+
[ "$agent" = "codex" ] && codex_compact=1
|
|
29
31
|
|
|
30
32
|
# ─── Context pressure detection (turn counter since last compact) ──
|
|
31
33
|
# Must run before any early exits so every prompt is counted
|
|
@@ -85,8 +87,37 @@ if [ -z "$fts_query" ]; then
|
|
|
85
87
|
exit 0
|
|
86
88
|
fi
|
|
87
89
|
|
|
90
|
+
# ─── Agent-run orchestration nudge ────────────────────────
|
|
91
|
+
|
|
92
|
+
lower_prompt=$(printf '%s' "$user_prompt" | tr '[:upper:]' '[:lower:]')
|
|
93
|
+
if printf '%s\n' "$lower_prompt" | grep -Eq '(orchestrat|worker|parallel|multi-agent|multi agent|split|lane|scope out|plan and get started|broad|full codebase|release|publish|ship)'; then
|
|
94
|
+
if [ "$codex_compact" -eq 1 ]; then
|
|
95
|
+
context+="=== Eagle Mem: Orchestration Protocol ===
|
|
96
|
+
For broad work, you run eagle-mem orchestrate yourself. Use durable lanes, opposite-agent workers, and concise user-visible status.
|
|
97
|
+
"
|
|
98
|
+
else
|
|
99
|
+
context+="=== Eagle Mem: Orchestration Protocol ===
|
|
100
|
+
If this request is broad enough to split into worker lanes, YOU run the orchestration commands. Do not ask the user to run them.
|
|
101
|
+
|
|
102
|
+
Use:
|
|
103
|
+
eagle-mem orchestrate init \"<goal>\"
|
|
104
|
+
eagle-mem orchestrate lane add <key> --agent codex|claude-code --desc \"<self-contained scope>\" --validate \"<command>\"
|
|
105
|
+
eagle-mem orchestrate lane start|block|complete <key>
|
|
106
|
+
|
|
107
|
+
Keep this mostly invisible to the user; surface only concise status or handoff when useful.
|
|
108
|
+
"
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
88
112
|
# Search for relevant past summaries (cross-session)
|
|
89
|
-
|
|
113
|
+
summary_limit=2
|
|
114
|
+
code_limit=3
|
|
115
|
+
if [ "$codex_compact" -eq 1 ]; then
|
|
116
|
+
summary_limit=1
|
|
117
|
+
code_limit=2
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
results=$(eagle_search_summaries "$fts_query" "$project" "$summary_limit")
|
|
90
121
|
|
|
91
122
|
if [ -n "$results" ]; then
|
|
92
123
|
context+="=== Eagle Mem: Relevant Recall ===
|
|
@@ -94,25 +125,46 @@ if [ -n "$results" ]; then
|
|
|
94
125
|
while IFS='|' read -r req completed learned _next_steps created_at _proj decisions gotchas key_files summary_agent; do
|
|
95
126
|
[ -z "$req" ] && [ -z "$completed" ] && continue
|
|
96
127
|
origin_label=$(eagle_agent_label "$summary_agent")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
if [ "$codex_compact" -eq 1 ]; then
|
|
129
|
+
req=$(eagle_trim_text "$req" 90)
|
|
130
|
+
completed=$(eagle_trim_text "$completed" 150)
|
|
131
|
+
learned=$(eagle_trim_text "$learned" 110)
|
|
132
|
+
context+="- [$origin_label] "
|
|
133
|
+
if [ -n "$completed" ]; then
|
|
134
|
+
context+="$completed"
|
|
135
|
+
else
|
|
136
|
+
context+="$req"
|
|
137
|
+
fi
|
|
138
|
+
[ -n "$learned" ] && context+=" | learned: $learned"
|
|
139
|
+
context+="
|
|
140
|
+
"
|
|
141
|
+
else
|
|
142
|
+
req=$(eagle_trim_text "$req" 160)
|
|
143
|
+
completed=$(eagle_trim_text "$completed" 220)
|
|
144
|
+
learned=$(eagle_trim_text "$learned" 180)
|
|
145
|
+
decisions=$(eagle_trim_text "$decisions" 160)
|
|
146
|
+
gotchas=$(eagle_trim_text "$gotchas" 160)
|
|
147
|
+
key_files=$(eagle_trim_text "$key_files" 160)
|
|
148
|
+
context+="[$created_at][$origin_label] "
|
|
149
|
+
[ -n "$req" ] && context+="$req"
|
|
150
|
+
[ -n "$completed" ] && context+=" → $completed"
|
|
151
|
+
[ -n "$learned" ] && context+=" (Learned: $learned)"
|
|
152
|
+
[ -n "$decisions" ] && context+="
|
|
102
153
|
Decisions: $decisions"
|
|
103
|
-
|
|
154
|
+
[ -n "$gotchas" ] && context+="
|
|
104
155
|
Gotchas: $gotchas"
|
|
105
|
-
|
|
156
|
+
[ -n "$key_files" ] && context+="
|
|
106
157
|
Key files: $key_files"
|
|
107
|
-
|
|
158
|
+
context+="
|
|
108
159
|
"
|
|
160
|
+
fi
|
|
109
161
|
done <<< "$results"
|
|
110
162
|
fi
|
|
111
163
|
|
|
112
164
|
# Search indexed code chunks (if any exist for this project)
|
|
113
165
|
has_chunks=$(eagle_count_code_chunks "$project")
|
|
114
166
|
if [ "${has_chunks:-0}" -gt 0 ]; then
|
|
115
|
-
code_results=$(eagle_search_code_chunks "$fts_query" "$project"
|
|
167
|
+
code_results=$(eagle_search_code_chunks "$fts_query" "$project" "$code_limit")
|
|
116
168
|
|
|
117
169
|
if [ -n "$code_results" ]; then
|
|
118
170
|
context+="=== Eagle Mem: Relevant Code ===
|
|
@@ -129,11 +181,17 @@ fi
|
|
|
129
181
|
|
|
130
182
|
[ -z "$context" ] && exit 0
|
|
131
183
|
|
|
132
|
-
|
|
133
|
-
|
|
184
|
+
if [ "$codex_compact" -eq 1 ]; then
|
|
185
|
+
context+="
|
|
186
|
+
Use only if directly useful. If you mention it to the user, keep Eagle Mem attribution to one short line.
|
|
187
|
+
"
|
|
188
|
+
else
|
|
189
|
+
context+="
|
|
190
|
+
IMPORTANT: If directly useful, start with one short Eagle Mem attribution line, then proceed.
|
|
134
191
|
|
|
135
192
|
=== Eagle Mem: Persistent Memory ===
|
|
136
193
|
"
|
|
194
|
+
fi
|
|
137
195
|
|
|
138
196
|
eagle_emit_context_for_agent "$agent" "UserPromptSubmit" "$context"
|
|
139
197
|
exit 0
|
package/lib/common.sh
CHANGED
|
@@ -31,6 +31,11 @@ eagle_log() {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
eagle_project_from_cwd() {
|
|
34
|
+
if [ -n "${EAGLE_MEM_PROJECT:-}" ]; then
|
|
35
|
+
echo "$EAGLE_MEM_PROJECT"
|
|
36
|
+
return
|
|
37
|
+
fi
|
|
38
|
+
|
|
34
39
|
local cwd="${1:-$(pwd)}"
|
|
35
40
|
local resolved="$cwd"
|
|
36
41
|
|
|
@@ -113,7 +118,13 @@ eagle_agent_source() {
|
|
|
113
118
|
case "$agent" in
|
|
114
119
|
codex|openai-codex) echo "codex" ;;
|
|
115
120
|
claude|claude-code|cloud-code) echo "claude-code" ;;
|
|
116
|
-
*)
|
|
121
|
+
*)
|
|
122
|
+
if [ -n "${CODEX_THREAD_ID:-}" ] || [ -n "${CODEX_CI:-}" ] || [ -n "${CODEX_MANAGED_BY_NPM:-}" ]; then
|
|
123
|
+
echo "codex"
|
|
124
|
+
else
|
|
125
|
+
echo "claude-code"
|
|
126
|
+
fi
|
|
127
|
+
;;
|
|
117
128
|
esac
|
|
118
129
|
}
|
|
119
130
|
|
|
@@ -147,6 +158,22 @@ eagle_agent_label() {
|
|
|
147
158
|
esac
|
|
148
159
|
}
|
|
149
160
|
|
|
161
|
+
eagle_trim_text() {
|
|
162
|
+
local text="${1:-}"
|
|
163
|
+
local max="${2:-240}"
|
|
164
|
+
|
|
165
|
+
text=$(printf '%s' "$text" | tr '\n' ' ' | sed -E 's/[[:space:]]+/ /g; s/^ //; s/ $//')
|
|
166
|
+
if [ "${#text}" -gt "$max" ] 2>/dev/null; then
|
|
167
|
+
if [ "$max" -gt 3 ] 2>/dev/null; then
|
|
168
|
+
printf '%s...' "${text:0:$((max - 3))}"
|
|
169
|
+
else
|
|
170
|
+
printf '%s' "${text:0:$max}"
|
|
171
|
+
fi
|
|
172
|
+
else
|
|
173
|
+
printf '%s' "$text"
|
|
174
|
+
fi
|
|
175
|
+
}
|
|
176
|
+
|
|
150
177
|
eagle_is_shell_tool() {
|
|
151
178
|
case "${1:-}" in
|
|
152
179
|
Bash|exec_command|shell_command|unified_exec) return 0 ;;
|
|
@@ -190,8 +217,124 @@ eagle_emit_context_for_agent() {
|
|
|
190
217
|
printf '%s\n' "$context"
|
|
191
218
|
}
|
|
192
219
|
|
|
220
|
+
eagle_config_get_light() {
|
|
221
|
+
local section="$1"
|
|
222
|
+
local key="$2"
|
|
223
|
+
local default="${3:-}"
|
|
224
|
+
local cfg="${EAGLE_CONFIG_FILE:-$EAGLE_MEM_DIR/config.toml}"
|
|
225
|
+
|
|
226
|
+
if [ ! -f "$cfg" ]; then
|
|
227
|
+
echo "$default"
|
|
228
|
+
return
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
local value
|
|
232
|
+
value=$(awk -v section="$section" -v key="$key" '
|
|
233
|
+
/^[[:space:]]*\[/ {
|
|
234
|
+
gsub(/[\[\][:space:]]/, "")
|
|
235
|
+
current = $0
|
|
236
|
+
}
|
|
237
|
+
current == section && /^[[:space:]]*[^#\[]/ {
|
|
238
|
+
split($0, parts, "=")
|
|
239
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", parts[1])
|
|
240
|
+
if (parts[1] == key) {
|
|
241
|
+
val = substr($0, index($0, "=") + 1)
|
|
242
|
+
gsub(/^[[:space:]]+|[[:space:]]+$/, "", val)
|
|
243
|
+
gsub(/^["'"'"']|["'"'"']$/, "", val)
|
|
244
|
+
print val
|
|
245
|
+
exit
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
' "$cfg")
|
|
249
|
+
|
|
250
|
+
if [ -n "$value" ]; then
|
|
251
|
+
echo "$value"
|
|
252
|
+
else
|
|
253
|
+
echo "$default"
|
|
254
|
+
fi
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
eagle_token_guard_rtk_mode() {
|
|
258
|
+
if declare -F eagle_config_get >/dev/null 2>&1; then
|
|
259
|
+
eagle_config_get "token_guard" "rtk" "auto"
|
|
260
|
+
else
|
|
261
|
+
eagle_config_get_light "token_guard" "rtk" "auto"
|
|
262
|
+
fi
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
eagle_token_guard_raw_bash_mode() {
|
|
266
|
+
if declare -F eagle_config_get >/dev/null 2>&1; then
|
|
267
|
+
eagle_config_get "token_guard" "raw_bash" "block"
|
|
268
|
+
else
|
|
269
|
+
eagle_config_get_light "token_guard" "raw_bash" "block"
|
|
270
|
+
fi
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
eagle_raw_output_command_needs_guard() {
|
|
274
|
+
local cmd="$1"
|
|
275
|
+
local first
|
|
276
|
+
first=$(printf '%s\n' "$cmd" | awk 'NR == 1 {print $1}' | sed 's|.*/||')
|
|
277
|
+
|
|
278
|
+
case "$first" in
|
|
279
|
+
cat|head|tail|find|grep|rg|wc) return 0 ;;
|
|
280
|
+
esac
|
|
281
|
+
|
|
282
|
+
if printf '%s\n' "$cmd" \
|
|
283
|
+
| tr '\n' ';' \
|
|
284
|
+
| sed -E 's/(&&|[|][|]|;)/\
|
|
285
|
+
/g' \
|
|
286
|
+
| awk '
|
|
287
|
+
{
|
|
288
|
+
for (i = 1; i <= NF; i++) {
|
|
289
|
+
token = $i
|
|
290
|
+
sub(/^.*\//, "", token)
|
|
291
|
+
if (token ~ /^(cat|head|tail|find|grep|rg|wc)$/) found = 1
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
END { exit(found ? 0 : 1) }
|
|
295
|
+
'
|
|
296
|
+
then
|
|
297
|
+
return 0
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
if printf '%s\n' "$cmd" \
|
|
301
|
+
| tr '\n' ';' \
|
|
302
|
+
| sed -E 's/(&&|[|][|]|;)/\
|
|
303
|
+
/g' \
|
|
304
|
+
| awk '
|
|
305
|
+
{
|
|
306
|
+
for (i = 1; i <= NF; i++) {
|
|
307
|
+
if ($i !~ /(^|\/)git$/) continue
|
|
308
|
+
j = i + 1
|
|
309
|
+
while (j <= NF && $j ~ /^-/) {
|
|
310
|
+
opt = $j
|
|
311
|
+
j++
|
|
312
|
+
if (opt == "-C" || opt == "-c" ||
|
|
313
|
+
opt == "--git-dir" || opt == "--work-tree" ||
|
|
314
|
+
opt == "--namespace" || opt == "--exec-path" ||
|
|
315
|
+
opt == "--config-env" || opt == "--super-prefix") {
|
|
316
|
+
j++
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if ($j ~ /^(diff|show|log|blame|grep)$/) found = 1
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
END { exit(found ? 0 : 1) }
|
|
323
|
+
'
|
|
324
|
+
then
|
|
325
|
+
return 0
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
if printf '%s\n' "$cmd" | grep -qE '\|\s*(head|tail|grep|rg|wc)\b'; then
|
|
329
|
+
return 0
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
return 1
|
|
333
|
+
}
|
|
334
|
+
|
|
193
335
|
eagle_rtk_rewrite_command() {
|
|
194
336
|
local cmd="$1"
|
|
337
|
+
[ "$(eagle_token_guard_rtk_mode)" = "off" ] && return 1
|
|
195
338
|
command -v rtk >/dev/null 2>&1 || return 1
|
|
196
339
|
|
|
197
340
|
case "$cmd" in
|
|
@@ -464,7 +607,7 @@ _eagle_claude_md_section() {
|
|
|
464
607
|
|
|
465
608
|
## Eagle Mem — Persistent Memory
|
|
466
609
|
|
|
467
|
-
Eagle Mem hooks are active in every project. SessionStart injects context (overview, recent sessions, memories, tasks, core files). Stop captures session summaries. PostToolUse mirrors memories/plans/tasks.
|
|
610
|
+
Eagle Mem hooks are active in every project. SessionStart injects context (overview, recent sessions, memories, tasks, orchestration lanes, core files). Stop captures session summaries. PostToolUse mirrors memories/plans/tasks.
|
|
468
611
|
|
|
469
612
|
**Rule:** Before your final response in every session, emit an `<eagle-summary>` block so the Stop hook can capture a rich summary instead of just heuristics.
|
|
470
613
|
|
|
@@ -492,6 +635,7 @@ regression_risks: [risk, ...]
|
|
|
492
635
|
- When Eagle Mem injects context at SessionStart, attribute it: "Eagle Mem recalls:"
|
|
493
636
|
- Do not revert decisions surfaced by PostToolUse without asking the user
|
|
494
637
|
- If Eagle Mem reports pending feature verification, verify or waive it before push/PR/publish
|
|
638
|
+
- For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands
|
|
495
639
|
- Never put raw secrets in the summary — Eagle Mem redacts but defense in depth
|
|
496
640
|
- If you contradict a loaded memory, update the memory file
|
|
497
641
|
EAGLE_MD
|
|
@@ -522,6 +666,17 @@ eagle_patch_claude_md() {
|
|
|
522
666
|
_eagle_claude_md_section >> "$claude_md"
|
|
523
667
|
return 0
|
|
524
668
|
fi
|
|
669
|
+
if ! grep -qF 'eagle-mem orchestrate' "$claude_md" 2>/dev/null; then
|
|
670
|
+
local tmp_md
|
|
671
|
+
tmp_md=$(mktemp)
|
|
672
|
+
awk '
|
|
673
|
+
{ print }
|
|
674
|
+
/pending feature verification/ {
|
|
675
|
+
print "- For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands"
|
|
676
|
+
}
|
|
677
|
+
' "$claude_md" > "$tmp_md" && mv "$tmp_md" "$claude_md"
|
|
678
|
+
return 0
|
|
679
|
+
fi
|
|
525
680
|
return 1
|
|
526
681
|
fi
|
|
527
682
|
|
|
@@ -558,7 +713,8 @@ regression_risks: [risk, ...]
|
|
|
558
713
|
|
|
559
714
|
**How to apply:**
|
|
560
715
|
- Attribute recalled context as "Eagle Mem recalls:" when it is injected
|
|
561
|
-
- Use the Eagle Mem skills when relevant: `eagle-mem-search`, `eagle-mem-overview`, `eagle-mem-memories`, and `eagle-mem-
|
|
716
|
+
- Use the Eagle Mem skills when relevant: `eagle-mem-search`, `eagle-mem-overview`, `eagle-mem-memories`, `eagle-mem-tasks`, and `eagle-mem-orchestrate`
|
|
717
|
+
- For broad multi-agent work, YOU run `eagle-mem orchestrate`; do not ask the user to run these commands
|
|
562
718
|
- For important decisions, preferences, gotchas, or durable project facts, explicitly include them in the `<eagle-summary>` block so Codex-originated memories become available to future Claude Code and Codex sessions
|
|
563
719
|
- Do not revert Eagle Mem-surfaced decisions without asking the user
|
|
564
720
|
- If Eagle Mem reports pending feature verification, verify or waive it before push/PR/publish
|
|
@@ -573,6 +729,17 @@ eagle_patch_codex_agents_md() {
|
|
|
573
729
|
mkdir -p "$(dirname "$agents_md")"
|
|
574
730
|
|
|
575
731
|
if [ -f "$agents_md" ] && grep -qF "$marker" "$agents_md" 2>/dev/null; then
|
|
732
|
+
if ! grep -qF 'eagle-mem orchestrate' "$agents_md" 2>/dev/null; then
|
|
733
|
+
local tmp_md
|
|
734
|
+
tmp_md=$(mktemp)
|
|
735
|
+
awk '
|
|
736
|
+
{ print }
|
|
737
|
+
/eagle-mem-tasks/ {
|
|
738
|
+
print "- Use the `eagle-mem-orchestrate` skill for broad multi-agent work. YOU run `eagle-mem orchestrate`; do not ask the user to run these commands"
|
|
739
|
+
}
|
|
740
|
+
' "$agents_md" > "$tmp_md" && mv "$tmp_md" "$agents_md"
|
|
741
|
+
return 0
|
|
742
|
+
fi
|
|
576
743
|
return 1
|
|
577
744
|
fi
|
|
578
745
|
|
package/lib/db-observations.sh
CHANGED
|
@@ -70,6 +70,13 @@ eagle_search_code_chunks() {
|
|
|
70
70
|
JOIN code_chunks_fts f ON f.rowid = c.id
|
|
71
71
|
WHERE code_chunks_fts MATCH '$query'
|
|
72
72
|
AND c.project = '$project'
|
|
73
|
+
AND c.file_path NOT LIKE '.playwright-mcp/%'
|
|
74
|
+
AND c.file_path NOT LIKE '.eagle-worktrees/%'
|
|
75
|
+
AND c.file_path NOT LIKE '.git/%'
|
|
76
|
+
AND c.file_path NOT LIKE 'node_modules/%'
|
|
77
|
+
AND c.file_path NOT LIKE 'dist/%'
|
|
78
|
+
AND c.file_path NOT LIKE 'build/%'
|
|
79
|
+
AND c.file_path NOT LIKE 'coverage/%'
|
|
73
80
|
ORDER BY rank
|
|
74
81
|
LIMIT $limit;"
|
|
75
82
|
}
|
package/lib/db-sessions.sh
CHANGED
|
@@ -57,7 +57,13 @@ SELECT 'tasks_done|' || COUNT(*) FROM agent_tasks WHERE project = '$project' AND
|
|
|
57
57
|
SELECT 'chunks|' || COUNT(*) FROM code_chunks WHERE project = '$project';
|
|
58
58
|
SELECT 'observations|' || COUNT(*) FROM observations WHERE session_id IN (SELECT id FROM sessions WHERE project = '$project');
|
|
59
59
|
SELECT 'last_active|' || COALESCE(MAX(date(COALESCE(last_activity_at, started_at))), 'never') FROM sessions WHERE project = '$project';
|
|
60
|
-
SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60)
|
|
60
|
+
SELECT 'last_summary|' || COALESCE((SELECT substr(request, 1, 60)
|
|
61
|
+
FROM summaries
|
|
62
|
+
WHERE project = '$project'
|
|
63
|
+
AND COALESCE(request, '') NOT LIKE '# AGENTS.md instructions%'
|
|
64
|
+
AND COALESCE(request, '') NOT LIKE '<environment_context>%'
|
|
65
|
+
ORDER BY created_at DESC
|
|
66
|
+
LIMIT 1), '');
|
|
61
67
|
SQL
|
|
62
68
|
}
|
|
63
69
|
|
package/lib/db-summaries.sh
CHANGED
|
@@ -63,7 +63,9 @@ eagle_get_recent_summaries() {
|
|
|
63
63
|
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
64
|
FROM summaries s
|
|
65
65
|
WHERE s.project = '$project'
|
|
66
|
-
AND s.request NOT LIKE '%<local-command-caveat>%'
|
|
66
|
+
AND COALESCE(s.request, '') NOT LIKE '%<local-command-caveat>%'
|
|
67
|
+
AND COALESCE(s.request, '') NOT LIKE '# AGENTS.md instructions%'
|
|
68
|
+
AND COALESCE(s.request, '') NOT LIKE '<environment_context>%'
|
|
67
69
|
ORDER BY s.created_at DESC
|
|
68
70
|
LIMIT $limit;"
|
|
69
71
|
}
|
|
@@ -84,7 +86,9 @@ eagle_search_summaries() {
|
|
|
84
86
|
FROM summaries s
|
|
85
87
|
JOIN summaries_fts f ON f.rowid = s.id
|
|
86
88
|
WHERE summaries_fts MATCH '$query'
|
|
87
|
-
AND s.request NOT LIKE '%<local-command-caveat>%'
|
|
89
|
+
AND COALESCE(s.request, '') NOT LIKE '%<local-command-caveat>%'
|
|
90
|
+
AND COALESCE(s.request, '') NOT LIKE '# AGENTS.md instructions%'
|
|
91
|
+
AND COALESCE(s.request, '') NOT LIKE '<environment_context>%'
|
|
88
92
|
$where_clause
|
|
89
93
|
ORDER BY rank
|
|
90
94
|
LIMIT $limit;"
|
package/lib/provider.sh
CHANGED
|
@@ -143,6 +143,7 @@ eagle_config_init() {
|
|
|
143
143
|
# Create config with restrictive permissions from the start (no TOCTOU window)
|
|
144
144
|
(
|
|
145
145
|
umask 077
|
|
146
|
+
mkdir -p "$EAGLE_MEM_DIR"
|
|
146
147
|
cat > "$EAGLE_CONFIG_FILE" << TOML
|
|
147
148
|
# Eagle Mem configuration
|
|
148
149
|
# Docs: https://github.com/eagleisbatman/eagle-mem
|
|
@@ -164,6 +165,17 @@ preferred = "current"
|
|
|
164
165
|
codex_model = ""
|
|
165
166
|
claude_model = ""
|
|
166
167
|
|
|
168
|
+
[orchestration]
|
|
169
|
+
# route = "opposite" means Codex coordinates Claude workers and Claude
|
|
170
|
+
# coordinates Codex workers by default.
|
|
171
|
+
route = "opposite"
|
|
172
|
+
auto_worktree = "true"
|
|
173
|
+
worktree_root = ""
|
|
174
|
+
codex_worker_model = "gpt-5.5"
|
|
175
|
+
codex_worker_effort = "xhigh"
|
|
176
|
+
claude_worker_model = "claude-opus-4-7"
|
|
177
|
+
claude_worker_effort = "xhigh"
|
|
178
|
+
|
|
167
179
|
[anthropic]
|
|
168
180
|
# Uses ANTHROPIC_API_KEY env var for authentication
|
|
169
181
|
model = "claude-haiku-4-5-20251001"
|
|
@@ -177,11 +189,20 @@ model = "gpt-4o-mini"
|
|
|
177
189
|
schedule = "auto"
|
|
178
190
|
min_sessions = 5
|
|
179
191
|
|
|
192
|
+
[token_guard]
|
|
193
|
+
# rtk: "off" disables RTK help, "auto" uses RTK when found,
|
|
194
|
+
# "enforce" blocks known raw-output shell commands when RTK is unavailable.
|
|
195
|
+
rtk = "auto"
|
|
196
|
+
# raw_bash: "block" blocks raw Codex shell output when an RTK rewrite exists.
|
|
197
|
+
# "allow" keeps RTK advisory only.
|
|
198
|
+
raw_bash = "block"
|
|
199
|
+
|
|
180
200
|
[redaction]
|
|
181
201
|
# Additional secret patterns (regex) beyond built-in defaults
|
|
182
202
|
# extra_patterns = ["MY_CUSTOM_SECRET_.*"]
|
|
183
203
|
TOML
|
|
184
204
|
)
|
|
205
|
+
chmod 700 "$EAGLE_MEM_DIR" 2>/dev/null || true
|
|
185
206
|
eagle_log "INFO" "Config initialized: provider=$provider model=$model"
|
|
186
207
|
}
|
|
187
208
|
|
|
@@ -537,6 +558,19 @@ eagle_show_config() {
|
|
|
537
558
|
echo "Claude: $(command -v claude 2>/dev/null || echo "not found")"
|
|
538
559
|
fi
|
|
539
560
|
|
|
561
|
+
echo ""
|
|
562
|
+
echo "Orchestration:"
|
|
563
|
+
echo " Route: $(eagle_config_get "orchestration" "route" "opposite")"
|
|
564
|
+
echo " Worktrees: $(eagle_config_get "orchestration" "auto_worktree" "true")"
|
|
565
|
+
echo " Codex: $(eagle_config_get "orchestration" "codex_worker_model" "gpt-5.5") / $(eagle_config_get "orchestration" "codex_worker_effort" "xhigh")"
|
|
566
|
+
echo " Claude: $(eagle_config_get "orchestration" "claude_worker_model" "claude-opus-4-7") / $(eagle_config_get "orchestration" "claude_worker_effort" "xhigh")"
|
|
567
|
+
|
|
568
|
+
echo ""
|
|
569
|
+
echo "Token guard:"
|
|
570
|
+
echo " RTK mode: $(eagle_config_get "token_guard" "rtk" "auto")"
|
|
571
|
+
echo " Raw bash: $(eagle_config_get "token_guard" "raw_bash" "block")"
|
|
572
|
+
echo " RTK bin: $(command -v rtk 2>/dev/null || echo "not found")"
|
|
573
|
+
|
|
540
574
|
echo ""
|
|
541
575
|
echo "Config: $EAGLE_CONFIG_FILE"
|
|
542
576
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eagle-mem",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Context that survives /compact for Claude Code and Codex — SQLite + FTS5, no daemon, no bloat",
|
|
5
5
|
"bin": {
|
|
6
6
|
"eagle-mem": "bin/eagle-mem"
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"sqlite",
|
|
21
21
|
"fts5",
|
|
22
22
|
"hooks",
|
|
23
|
+
"orchestration",
|
|
24
|
+
"rtk",
|
|
23
25
|
"persistent-memory"
|
|
24
26
|
],
|
|
25
27
|
"author": "eagleisbatman",
|
package/scripts/config.sh
CHANGED
|
@@ -17,7 +17,32 @@ eagle_header "Config"
|
|
|
17
17
|
subcommand="${1:-show}"
|
|
18
18
|
shift 2>/dev/null || true
|
|
19
19
|
|
|
20
|
+
show_help() {
|
|
21
|
+
echo -e " ${BOLD}eagle-mem config${RESET} — Provider and token-guard settings"
|
|
22
|
+
echo ""
|
|
23
|
+
echo -e " ${BOLD}Usage:${RESET}"
|
|
24
|
+
echo -e " eagle-mem config ${DIM}# show current config${RESET}"
|
|
25
|
+
echo -e " eagle-mem config ${CYAN}init${RESET} ${DIM}# create config.toml${RESET}"
|
|
26
|
+
echo -e " eagle-mem config ${CYAN}set${RESET} section.key value"
|
|
27
|
+
echo -e " eagle-mem config ${CYAN}test${RESET} ${DIM}# test curator provider${RESET}"
|
|
28
|
+
echo ""
|
|
29
|
+
echo -e " ${BOLD}Examples:${RESET}"
|
|
30
|
+
echo -e " eagle-mem config set provider.type agent_cli"
|
|
31
|
+
echo -e " eagle-mem config set agent_cli.preferred current"
|
|
32
|
+
echo -e " eagle-mem config set orchestration.route opposite"
|
|
33
|
+
echo -e " eagle-mem config set orchestration.codex_worker_model gpt-5.5"
|
|
34
|
+
echo -e " eagle-mem config set orchestration.claude_worker_model claude-opus-4-7"
|
|
35
|
+
echo -e " eagle-mem config set token_guard.rtk enforce"
|
|
36
|
+
echo -e " eagle-mem config set token_guard.raw_bash block"
|
|
37
|
+
echo ""
|
|
38
|
+
exit 0
|
|
39
|
+
}
|
|
40
|
+
|
|
20
41
|
case "$subcommand" in
|
|
42
|
+
--help|-h|help)
|
|
43
|
+
show_help
|
|
44
|
+
;;
|
|
45
|
+
|
|
21
46
|
init)
|
|
22
47
|
eagle_config_init
|
|
23
48
|
eagle_ok "Config created: $EAGLE_CONFIG_FILE"
|
|
@@ -38,8 +63,13 @@ case "$subcommand" in
|
|
|
38
63
|
eagle_info " eagle-mem config set provider.type ollama"
|
|
39
64
|
eagle_info " eagle-mem config set provider.type agent_cli"
|
|
40
65
|
eagle_info " eagle-mem config set agent_cli.preferred current"
|
|
66
|
+
eagle_info " eagle-mem config set orchestration.route opposite"
|
|
67
|
+
eagle_info " eagle-mem config set orchestration.codex_worker_effort xhigh"
|
|
68
|
+
eagle_info " eagle-mem config set orchestration.claude_worker_effort xhigh"
|
|
41
69
|
eagle_info " eagle-mem config set ollama.model mistral"
|
|
42
70
|
eagle_info " eagle-mem config set anthropic.model claude-haiku-4-5-20251001"
|
|
71
|
+
eagle_info " eagle-mem config set token_guard.rtk enforce"
|
|
72
|
+
eagle_info " eagle-mem config set token_guard.raw_bash block"
|
|
43
73
|
exit 1
|
|
44
74
|
fi
|
|
45
75
|
section="${key%%.*}"
|
package/scripts/health.sh
CHANGED
|
@@ -39,6 +39,8 @@ if [ -z "$project" ]; then
|
|
|
39
39
|
exit 1
|
|
40
40
|
fi
|
|
41
41
|
|
|
42
|
+
eagle_ensure_db
|
|
43
|
+
|
|
42
44
|
p_esc=$(eagle_sql_escape "$project")
|
|
43
45
|
|
|
44
46
|
eagle_info "Project: ${BOLD}$project${RESET}"
|
|
@@ -145,6 +147,50 @@ else
|
|
|
145
147
|
issues+=("Configure a provider: eagle-mem config init")
|
|
146
148
|
fi
|
|
147
149
|
|
|
150
|
+
# ─── Token guard visibility (informational) ────────────────
|
|
151
|
+
|
|
152
|
+
rtk_mode=$(eagle_config_get "token_guard" "rtk" "auto")
|
|
153
|
+
raw_bash_mode=$(eagle_config_get "token_guard" "raw_bash" "block")
|
|
154
|
+
rtk_bin=$(command -v rtk 2>/dev/null || true)
|
|
155
|
+
if [ -n "$rtk_bin" ]; then
|
|
156
|
+
eagle_ok "Token guard: RTK $rtk_mode (${rtk_bin}), raw_bash=$raw_bash_mode"
|
|
157
|
+
elif [ "$rtk_mode" = "enforce" ]; then
|
|
158
|
+
eagle_fail "Token guard: RTK enforce enabled, but rtk not found"
|
|
159
|
+
issues+=("Install RTK or run: eagle-mem config set token_guard.rtk auto")
|
|
160
|
+
else
|
|
161
|
+
eagle_dim " Token guard: RTK not found (mode: $rtk_mode, raw_bash: $raw_bash_mode)"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# ─── Orchestration visibility (informational) ───────────────
|
|
165
|
+
|
|
166
|
+
orch_route=$(eagle_config_get "orchestration" "route" "opposite")
|
|
167
|
+
orch_auto_worktree=$(eagle_config_get "orchestration" "auto_worktree" "true")
|
|
168
|
+
orch_worktree_root=$(eagle_config_get "orchestration" "worktree_root" "")
|
|
169
|
+
orch_codex_model=$(eagle_config_get "orchestration" "codex_worker_model" "gpt-5.5")
|
|
170
|
+
orch_codex_effort=$(eagle_config_get "orchestration" "codex_worker_effort" "xhigh")
|
|
171
|
+
orch_claude_model=$(eagle_config_get "orchestration" "claude_worker_model" "claude-opus-4-7")
|
|
172
|
+
orch_claude_effort=$(eagle_config_get "orchestration" "claude_worker_effort" "xhigh")
|
|
173
|
+
codex_bin=$(command -v codex 2>/dev/null || true)
|
|
174
|
+
claude_bin=$(command -v claude 2>/dev/null || true)
|
|
175
|
+
|
|
176
|
+
if [ -n "$codex_bin" ] && [ -n "$claude_bin" ]; then
|
|
177
|
+
eagle_ok "Orchestration: route=$orch_route, worktrees=$orch_auto_worktree, Codex + Claude workers available"
|
|
178
|
+
elif [ -n "$codex_bin" ]; then
|
|
179
|
+
eagle_warn "Orchestration: Codex available, Claude CLI missing"
|
|
180
|
+
issues+=("Install or authenticate Claude Code CLI before spawning Claude worker lanes.")
|
|
181
|
+
elif [ -n "$claude_bin" ]; then
|
|
182
|
+
eagle_warn "Orchestration: Claude available, Codex CLI missing"
|
|
183
|
+
issues+=("Install or authenticate Codex CLI before spawning Codex worker lanes.")
|
|
184
|
+
else
|
|
185
|
+
eagle_warn "Orchestration: worker CLIs not found"
|
|
186
|
+
issues+=("Install/authenticate Codex and Claude Code CLIs before using eagle-mem orchestrate spawn.")
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
eagle_dim " Workers: codex=${orch_codex_model}/${orch_codex_effort}, claude-code=${orch_claude_model}/${orch_claude_effort}"
|
|
190
|
+
if [ -n "$orch_worktree_root" ]; then
|
|
191
|
+
eagle_dim " Worktree root: $orch_worktree_root"
|
|
192
|
+
fi
|
|
193
|
+
|
|
148
194
|
# ─── 5. Data quality (10 pts) ──────────────────────────
|
|
149
195
|
|
|
150
196
|
max_score=$((max_score + 10))
|
|
@@ -232,11 +278,31 @@ if [ "$JSON_OUT" -eq 1 ]; then
|
|
|
232
278
|
--argjson enriched_summaries "${enriched_summaries:-0}" \
|
|
233
279
|
--argjson features "${feature_count:-0}" \
|
|
234
280
|
--arg provider "$provider" \
|
|
281
|
+
--arg token_guard_rtk "$rtk_mode" \
|
|
282
|
+
--arg token_guard_raw_bash "$raw_bash_mode" \
|
|
283
|
+
--arg rtk_bin "${rtk_bin:-}" \
|
|
284
|
+
--arg orchestration_route "$orch_route" \
|
|
285
|
+
--arg orchestration_auto_worktree "$orch_auto_worktree" \
|
|
286
|
+
--arg orchestration_worktree_root "$orch_worktree_root" \
|
|
287
|
+
--arg codex_worker_model "$orch_codex_model" \
|
|
288
|
+
--arg codex_worker_effort "$orch_codex_effort" \
|
|
289
|
+
--arg claude_worker_model "$orch_claude_model" \
|
|
290
|
+
--arg claude_worker_effort "$orch_claude_effort" \
|
|
291
|
+
--arg codex_bin "${codex_bin:-}" \
|
|
292
|
+
--arg claude_bin "${claude_bin:-}" \
|
|
235
293
|
--argjson noise_pct "$noise_pct" \
|
|
236
294
|
--arg last_curated "${last_curated:-never}" \
|
|
237
295
|
'{project:$project, score:$score, max:$max_score, pct:$pct, grade:$grade,
|
|
238
296
|
capture:{sessions:$total_sessions, summaries:$total_summaries, heuristic:$heuristic_summaries},
|
|
239
297
|
enrichment:$enriched_summaries,
|
|
240
298
|
features:$features, provider:$provider,
|
|
299
|
+
token_guard:{rtk:$token_guard_rtk, raw_bash:$token_guard_raw_bash, rtk_bin:$rtk_bin},
|
|
300
|
+
orchestration:{
|
|
301
|
+
route:$orchestration_route,
|
|
302
|
+
auto_worktree:$orchestration_auto_worktree,
|
|
303
|
+
worktree_root:$orchestration_worktree_root,
|
|
304
|
+
codex:{model:$codex_worker_model, effort:$codex_worker_effort, cli:$codex_bin},
|
|
305
|
+
claude_code:{model:$claude_worker_model, effort:$claude_worker_effort, cli:$claude_bin}
|
|
306
|
+
},
|
|
241
307
|
noise_pct:$noise_pct, last_curated:$last_curated}' >&3
|
|
242
308
|
fi
|
package/scripts/help.sh
CHANGED
|
@@ -21,11 +21,12 @@ echo -e " ${CYAN}update${RESET} Re-deploy hooks and run migrations"
|
|
|
21
21
|
echo -e " ${CYAN}uninstall${RESET} Remove hooks and optionally delete data"
|
|
22
22
|
echo -e " ${CYAN}search${RESET} Search past sessions, memories, and code"
|
|
23
23
|
echo -e " ${CYAN}health${RESET} Diagnose pipeline health and background automation"
|
|
24
|
-
echo -e " ${CYAN}config${RESET} View or change
|
|
24
|
+
echo -e " ${CYAN}config${RESET} View or change provider and token-guard settings"
|
|
25
25
|
echo -e " ${CYAN}guard${RESET} Manage regression guardrails for files"
|
|
26
26
|
echo -e " ${CYAN}overview${RESET} Build or view project overview"
|
|
27
27
|
echo -e " ${CYAN}memories${RESET} View/sync agent memories"
|
|
28
28
|
echo -e " ${CYAN}tasks${RESET} View mirrored tasks"
|
|
29
|
+
echo -e " ${CYAN}orchestrate${RESET} Durable worker-lane coordination"
|
|
29
30
|
echo -e " ${CYAN}curate${RESET} Run curator (co-edits, hot files, guardrails)"
|
|
30
31
|
echo -e " ${CYAN}feature${RESET} Track, verify, and unblock features"
|
|
31
32
|
echo -e " ${CYAN}prune${RESET} Clean old sessions and stale data"
|
|
@@ -44,11 +45,21 @@ echo -e " ${DIM}\$${RESET} eagle-mem feature pending ${DIM}# pending re
|
|
|
44
45
|
echo -e " ${DIM}\$${RESET} eagle-mem feature verify NAME ${DIM}# verify current diff after testing${RESET}"
|
|
45
46
|
echo -e " ${DIM}\$${RESET} eagle-mem feature waive ID ${DIM}# intentional exception${RESET}"
|
|
46
47
|
echo ""
|
|
48
|
+
echo -e " ${BOLD}Orchestration:${RESET}"
|
|
49
|
+
echo -e " ${DIM}Agent-run protocol for broad multi-lane work; users normally do not run this manually.${RESET}"
|
|
50
|
+
echo -e " ${DIM}Codex sessions spawn Claude workers; Claude sessions spawn Codex workers by default.${RESET}"
|
|
51
|
+
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate init \"Ship release\""
|
|
52
|
+
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate lane add api --agent codex --validate \"npm test\""
|
|
53
|
+
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate spawn api ${DIM}# worktree + worker process${RESET}"
|
|
54
|
+
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate sync ${DIM}# reconcile worker status${RESET}"
|
|
55
|
+
echo -e " ${DIM}\$${RESET} eagle-mem orchestrate handoff --write docs/handoff-context.md"
|
|
56
|
+
echo ""
|
|
47
57
|
echo -e " ${BOLD}Skills${RESET} ${DIM}(inside Claude Code and Codex sessions):${RESET}"
|
|
48
58
|
echo -e " ${CYAN}eagle-mem-search${RESET} Search memory and past sessions"
|
|
49
59
|
echo -e " ${CYAN}eagle-mem-overview${RESET} Build or update project overview"
|
|
50
60
|
echo -e " ${CYAN}eagle-mem-memories${RESET} View/sync agent memories"
|
|
51
61
|
echo -e " ${CYAN}eagle-mem-tasks${RESET} TaskAware Compact Loop for multi-step work"
|
|
62
|
+
echo -e " ${CYAN}eagle-mem-orchestrate${RESET} Orchestrator/worker lane handoffs"
|
|
52
63
|
echo ""
|
|
53
64
|
echo -e " ${DIM}Everything else is automatic — scan, index, prune, and${RESET}"
|
|
54
65
|
echo -e " ${DIM}curator all run in the background via hooks.${RESET}"
|