eagle-mem 4.9.3 → 4.9.4
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 +4 -0
- package/db/034_safe_feature_rekey_trigger.sql +17 -0
- package/lib/common.sh +369 -6
- package/lib/db-sessions.sh +127 -2
- package/package.json +1 -1
- package/scripts/install.sh +26 -17
- package/scripts/statusline-em.sh +3 -2
- package/scripts/update.sh +11 -1
package/README.md
CHANGED
|
@@ -152,6 +152,10 @@ Eagle Mem prevents Claude from repeating past mistakes:
|
|
|
152
152
|
| `eagle-mem scan` | Scan codebase and generate overview |
|
|
153
153
|
| `eagle-mem index` | Index source files for FTS5 code search |
|
|
154
154
|
|
|
155
|
+
### v4.9.4 Patch
|
|
156
|
+
|
|
157
|
+
Project-key hardening for agents that move between folders: hooks now keep a per-session project identity instead of recalculating from every new cwd, and statuslines prefer the stored session project before falling back to folder paths. Install/update also repairs older embedded Eagle Mem statusline blocks so nested-repo projects stop showing `Memories: 0` when the session belongs to the parent workspace.
|
|
158
|
+
|
|
155
159
|
### v4.9.3 Patch
|
|
156
160
|
|
|
157
161
|
Follow-up hardening for the v4.9.2 project-key repair: Claude transcript workspace detection now reads complete early JSONL records instead of a fixed byte slice, so large SessionStart hook context cannot hide the first `cwd`. Metadata-only memory/plan/task repairs also avoid touching FTS-indexed columns, preventing SQLite FTS update triggers from firing during safe project/source rekeys.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
-- Migration 034: Make feature FTS updates safe for project-key repairs.
|
|
2
|
+
--
|
|
3
|
+
-- Project-key repairs update features.project, but the older trigger fired on
|
|
4
|
+
-- every UPDATE and tried to rewrite the FTS5 row even when searchable text did
|
|
5
|
+
-- not change. Restrict it to the indexed columns so metadata-only rekeys are
|
|
6
|
+
-- safe.
|
|
7
|
+
|
|
8
|
+
DROP TRIGGER IF EXISTS features_au;
|
|
9
|
+
|
|
10
|
+
CREATE TRIGGER features_au
|
|
11
|
+
AFTER UPDATE OF name, description ON features
|
|
12
|
+
BEGIN
|
|
13
|
+
INSERT INTO features_fts(features_fts, rowid, name, description)
|
|
14
|
+
VALUES ('delete', old.id, old.name, old.description);
|
|
15
|
+
INSERT INTO features_fts(rowid, name, description)
|
|
16
|
+
VALUES (new.id, new.name, new.description);
|
|
17
|
+
END;
|
package/lib/common.sh
CHANGED
|
@@ -210,14 +210,231 @@ eagle_transcript_first_cwd() {
|
|
|
210
210
|
local transcript_path="${1:-}"
|
|
211
211
|
[ -f "$transcript_path" ] || return 1
|
|
212
212
|
|
|
213
|
+
local head_lines
|
|
214
|
+
head_lines=$(sed -n '1,200p' "$transcript_path" 2>/dev/null || true)
|
|
215
|
+
[ -n "$head_lines" ] || return 1
|
|
216
|
+
|
|
213
217
|
local cwd
|
|
214
|
-
cwd=$(
|
|
215
|
-
| jq -r '
|
|
218
|
+
cwd=$(printf '%s\n' "$head_lines" \
|
|
219
|
+
| jq -r '
|
|
220
|
+
[
|
|
221
|
+
(.payload? | objects | .workspace? | objects | .project_dir? | strings),
|
|
222
|
+
(.workspace? | objects | .project_dir? | strings),
|
|
223
|
+
(.payload? | objects | .workspace? | objects | .current_dir? | strings),
|
|
224
|
+
(.workspace? | objects | .current_dir? | strings),
|
|
225
|
+
(.cwd? | strings),
|
|
226
|
+
(.payload? | objects | .cwd? | strings),
|
|
227
|
+
(.payload? | objects | .current_dir? | strings)
|
|
228
|
+
]
|
|
229
|
+
| .[0] // empty
|
|
230
|
+
' 2>/dev/null \
|
|
216
231
|
| awk 'NF { print; exit }' || true)
|
|
232
|
+
|
|
217
233
|
[ -n "$cwd" ] || return 1
|
|
218
234
|
printf '%s\n' "$cwd"
|
|
219
235
|
}
|
|
220
236
|
|
|
237
|
+
eagle_session_project_marker_file() {
|
|
238
|
+
local session_id="${1:-}"
|
|
239
|
+
eagle_validate_session_id "$session_id" || return 1
|
|
240
|
+
mkdir -p "$EAGLE_MEM_DIR/session-projects" 2>/dev/null || return 1
|
|
241
|
+
printf '%s/session-projects/%s\n' "$EAGLE_MEM_DIR" "$session_id"
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
eagle_get_session_project_marker() {
|
|
245
|
+
local marker
|
|
246
|
+
marker=$(eagle_session_project_marker_file "$1") || return 1
|
|
247
|
+
[ -s "$marker" ] || return 1
|
|
248
|
+
awk 'NF { print; exit }' "$marker"
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
eagle_remember_session_project() {
|
|
252
|
+
local session_id="${1:-}"
|
|
253
|
+
local project="${2:-}"
|
|
254
|
+
local force="${3:-0}"
|
|
255
|
+
[ -n "$project" ] || return 1
|
|
256
|
+
|
|
257
|
+
local marker
|
|
258
|
+
marker=$(eagle_session_project_marker_file "$session_id") || return 1
|
|
259
|
+
if [ "$force" = "1" ] || [ ! -s "$marker" ]; then
|
|
260
|
+
printf '%s\n' "$project" > "$marker" 2>/dev/null || return 1
|
|
261
|
+
fi
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
eagle_get_session_project_light() {
|
|
265
|
+
local session_id="${1:-}"
|
|
266
|
+
eagle_validate_session_id "$session_id" || return 1
|
|
267
|
+
command -v sqlite3 >/dev/null 2>&1 || return 1
|
|
268
|
+
[ -f "$EAGLE_MEM_DB" ] || return 1
|
|
269
|
+
|
|
270
|
+
local sid_sql project
|
|
271
|
+
sid_sql=$(eagle_sql_escape "$session_id")
|
|
272
|
+
project=$(sqlite3 "$EAGLE_MEM_DB" "SELECT project FROM sessions WHERE id = '$sid_sql' AND project != '' LIMIT 1;" 2>/dev/null | awk 'NF { print; exit }')
|
|
273
|
+
[ -n "$project" ] || return 1
|
|
274
|
+
printf '%s\n' "$project"
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
eagle_project_has_table_row() {
|
|
278
|
+
local table="${1:-}"
|
|
279
|
+
local project="${2:-}"
|
|
280
|
+
[ -n "$table" ] && [ -n "$project" ] || return 1
|
|
281
|
+
command -v sqlite3 >/dev/null 2>&1 || return 1
|
|
282
|
+
[ -f "$EAGLE_MEM_DB" ] || return 1
|
|
283
|
+
|
|
284
|
+
local project_sql found
|
|
285
|
+
project_sql=$(eagle_sql_escape "$project")
|
|
286
|
+
found=$(sqlite3 "$EAGLE_MEM_DB" "SELECT 1 FROM $table WHERE project = '$project_sql' LIMIT 1;" 2>/dev/null | awk 'NF { print; exit }')
|
|
287
|
+
[ "$found" = "1" ]
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
eagle_project_from_existing_ancestor() {
|
|
291
|
+
local path="${1:-}"
|
|
292
|
+
[ -n "$path" ] || return 1
|
|
293
|
+
|
|
294
|
+
local current key
|
|
295
|
+
current=$(eagle_normalize_project_path "$path")
|
|
296
|
+
eagle_is_ephemeral_project_path "$current" && return 1
|
|
297
|
+
|
|
298
|
+
while [ -n "$current" ] && [ "$current" != "/" ]; do
|
|
299
|
+
key=$(eagle_project_key_from_target_dir "$current")
|
|
300
|
+
if [ -n "$key" ]; then
|
|
301
|
+
# Prefer ancestors with durable memory/summary content. Session-only
|
|
302
|
+
# rows can be created by the very folder drift this helper repairs.
|
|
303
|
+
if eagle_project_has_table_row "agent_memories" "$key" \
|
|
304
|
+
|| eagle_project_has_table_row "summaries" "$key"; then
|
|
305
|
+
printf '%s\n' "$key"
|
|
306
|
+
return 0
|
|
307
|
+
fi
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
[ "$current" = "$HOME" ] && break
|
|
311
|
+
current=$(dirname "$current")
|
|
312
|
+
done
|
|
313
|
+
|
|
314
|
+
return 1
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
eagle_project_from_workspace_path() {
|
|
318
|
+
if [ -n "${EAGLE_MEM_PROJECT:-}" ]; then
|
|
319
|
+
printf '%s\n' "$EAGLE_MEM_PROJECT"
|
|
320
|
+
return 0
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
local path="${1:-}"
|
|
324
|
+
[ -n "$path" ] || return 1
|
|
325
|
+
|
|
326
|
+
local resolved worktree_project git_root project
|
|
327
|
+
resolved=$(eagle_normalize_project_path "$path")
|
|
328
|
+
eagle_is_ephemeral_project_path "$resolved" && return 1
|
|
329
|
+
|
|
330
|
+
if worktree_project=$(eagle_project_key_for_worktree_path "$resolved"); then
|
|
331
|
+
printf '%s\n' "$worktree_project"
|
|
332
|
+
return 0
|
|
333
|
+
fi
|
|
334
|
+
|
|
335
|
+
git_root=$(git -C "$resolved" rev-parse --show-toplevel 2>/dev/null)
|
|
336
|
+
if [ -n "$git_root" ]; then
|
|
337
|
+
project=$(eagle_project_key_from_target_dir "$git_root")
|
|
338
|
+
[ -n "$project" ] && { printf '%s\n' "$project"; return 0; }
|
|
339
|
+
fi
|
|
340
|
+
|
|
341
|
+
if project=$(eagle_project_from_existing_ancestor "$path"); then
|
|
342
|
+
printf '%s\n' "$project"
|
|
343
|
+
return 0
|
|
344
|
+
fi
|
|
345
|
+
|
|
346
|
+
project=$(eagle_project_from_path_no_git "$path")
|
|
347
|
+
[ -n "$project" ] || return 1
|
|
348
|
+
printf '%s\n' "$project"
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
eagle_project_from_transcript_start() {
|
|
352
|
+
local transcript_path="${1:-}"
|
|
353
|
+
local cwd="${2:-}"
|
|
354
|
+
[ -f "$transcript_path" ] || return 1
|
|
355
|
+
|
|
356
|
+
local transcript_cwd project
|
|
357
|
+
if project=$(eagle_project_from_claude_transcript "$transcript_path" "$cwd"); then
|
|
358
|
+
printf '%s\n' "$project"
|
|
359
|
+
return 0
|
|
360
|
+
fi
|
|
361
|
+
|
|
362
|
+
transcript_cwd=$(eagle_transcript_first_cwd "$transcript_path") || return 1
|
|
363
|
+
if [ -n "$cwd" ] && ! eagle_path_is_same_or_child "$transcript_cwd" "$cwd"; then
|
|
364
|
+
return 1
|
|
365
|
+
fi
|
|
366
|
+
|
|
367
|
+
project=$(eagle_project_from_workspace_path "$transcript_cwd")
|
|
368
|
+
[ -n "$project" ] || return 1
|
|
369
|
+
printf '%s\n' "$project"
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
eagle_project_from_statusline_input() {
|
|
373
|
+
local input="${1:-}"
|
|
374
|
+
local project_dir="${2:-}"
|
|
375
|
+
local cwd="${3:-}"
|
|
376
|
+
local session_id="${4:-}"
|
|
377
|
+
local project workspace_project_dir transcript_path
|
|
378
|
+
|
|
379
|
+
if [ -n "${EAGLE_MEM_PROJECT:-}" ]; then
|
|
380
|
+
printf '%s\n' "$EAGLE_MEM_PROJECT"
|
|
381
|
+
return
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
if [ -z "$session_id" ] && [ -n "$input" ]; then
|
|
385
|
+
session_id=$(printf '%s' "$input" | jq -r '.session_id // .session.id // empty' 2>/dev/null)
|
|
386
|
+
fi
|
|
387
|
+
|
|
388
|
+
if [ -n "$input" ]; then
|
|
389
|
+
workspace_project_dir=$(printf '%s' "$input" | jq -r '.workspace.project_dir // empty' 2>/dev/null)
|
|
390
|
+
transcript_path=$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
391
|
+
[ -z "$cwd" ] && cwd=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
# Explicit workspace project and transcript start are stronger than older
|
|
395
|
+
# cached session rows because they repair pre-fix sessions that were stored
|
|
396
|
+
# under a nested folder key.
|
|
397
|
+
if [ -n "$workspace_project_dir" ]; then
|
|
398
|
+
project=$(eagle_project_from_workspace_path "$workspace_project_dir")
|
|
399
|
+
[ -n "$project" ] && { printf '%s\n' "$project"; return; }
|
|
400
|
+
fi
|
|
401
|
+
|
|
402
|
+
if [ -n "$transcript_path" ]; then
|
|
403
|
+
if project=$(eagle_project_from_transcript_start "$transcript_path" "${cwd:-$project_dir}"); then
|
|
404
|
+
printf '%s\n' "$project"
|
|
405
|
+
return
|
|
406
|
+
fi
|
|
407
|
+
fi
|
|
408
|
+
|
|
409
|
+
if [ -n "$session_id" ]; then
|
|
410
|
+
if project=$(eagle_get_session_project_light "$session_id"); then
|
|
411
|
+
printf '%s\n' "$project"
|
|
412
|
+
return
|
|
413
|
+
fi
|
|
414
|
+
if project=$(eagle_get_session_project_marker "$session_id"); then
|
|
415
|
+
printf '%s\n' "$project"
|
|
416
|
+
return
|
|
417
|
+
fi
|
|
418
|
+
fi
|
|
419
|
+
|
|
420
|
+
if [ -z "$project_dir" ] && [ -n "$input" ]; then
|
|
421
|
+
project_dir=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
|
|
422
|
+
fi
|
|
423
|
+
if [ -n "$project_dir" ]; then
|
|
424
|
+
project=$(eagle_project_from_workspace_path "$project_dir")
|
|
425
|
+
[ -n "$project" ] && { printf '%s\n' "$project"; return; }
|
|
426
|
+
fi
|
|
427
|
+
|
|
428
|
+
if [ -z "$cwd" ] && [ -n "$input" ]; then
|
|
429
|
+
cwd=$(printf '%s' "$input" | jq -r '.workspace.current_dir // .cwd // empty' 2>/dev/null)
|
|
430
|
+
fi
|
|
431
|
+
if [ -n "$cwd" ]; then
|
|
432
|
+
project=$(eagle_project_from_workspace_path "$cwd")
|
|
433
|
+
[ -n "$project" ] && { printf '%s\n' "$project"; return; }
|
|
434
|
+
fi
|
|
435
|
+
eagle_project_from_cwd "$cwd"
|
|
436
|
+
}
|
|
437
|
+
|
|
221
438
|
eagle_project_from_claude_project_dir() {
|
|
222
439
|
local project_dir="${1:-}"
|
|
223
440
|
project_dir="${project_dir%/}"
|
|
@@ -228,7 +445,7 @@ eagle_project_from_claude_project_dir() {
|
|
|
228
445
|
[ -f "$jsonl" ] || continue
|
|
229
446
|
cwd=$(eagle_transcript_first_cwd "$jsonl")
|
|
230
447
|
[ -z "$cwd" ] && continue
|
|
231
|
-
project=$(
|
|
448
|
+
project=$(eagle_project_from_workspace_path "$cwd")
|
|
232
449
|
[ -n "$project" ] && { printf '%s\n' "$project"; return 0; }
|
|
233
450
|
done
|
|
234
451
|
|
|
@@ -252,7 +469,7 @@ eagle_project_from_claude_transcript() {
|
|
|
252
469
|
return 1
|
|
253
470
|
fi
|
|
254
471
|
|
|
255
|
-
project=$(
|
|
472
|
+
project=$(eagle_project_from_workspace_path "$transcript_cwd")
|
|
256
473
|
[ -n "$project" ] || return 1
|
|
257
474
|
printf '%s\n' "$project"
|
|
258
475
|
}
|
|
@@ -265,16 +482,54 @@ eagle_project_from_hook_input() {
|
|
|
265
482
|
return
|
|
266
483
|
fi
|
|
267
484
|
|
|
268
|
-
local cwd transcript_path project
|
|
485
|
+
local session_id cwd transcript_path workspace_project project
|
|
486
|
+
session_id=$(printf '%s' "$input" | jq -r '.session_id // empty' 2>/dev/null)
|
|
269
487
|
cwd=$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null)
|
|
270
488
|
transcript_path=$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
271
489
|
|
|
490
|
+
workspace_project=$(printf '%s' "$input" | jq -r '.workspace.project_dir // empty' 2>/dev/null)
|
|
491
|
+
if [ -n "$workspace_project" ]; then
|
|
492
|
+
project=$(eagle_project_from_workspace_path "$workspace_project")
|
|
493
|
+
if [ -n "$project" ]; then
|
|
494
|
+
[ -n "$session_id" ] && eagle_remember_session_project "$session_id" "$project" 1 >/dev/null 2>&1
|
|
495
|
+
printf '%s\n' "$project"
|
|
496
|
+
return
|
|
497
|
+
fi
|
|
498
|
+
fi
|
|
499
|
+
|
|
272
500
|
if project=$(eagle_project_from_claude_transcript "$transcript_path" "$cwd"); then
|
|
501
|
+
[ -n "$session_id" ] && eagle_remember_session_project "$session_id" "$project" 1 >/dev/null 2>&1
|
|
273
502
|
printf '%s\n' "$project"
|
|
274
503
|
return
|
|
275
504
|
fi
|
|
276
505
|
|
|
277
|
-
|
|
506
|
+
if [ -n "$transcript_path" ] && [ -f "$transcript_path" ]; then
|
|
507
|
+
local transcript_cwd
|
|
508
|
+
transcript_cwd=$(eagle_transcript_first_cwd "$transcript_path")
|
|
509
|
+
if [ -n "$transcript_cwd" ]; then
|
|
510
|
+
project=$(eagle_project_from_workspace_path "$transcript_cwd")
|
|
511
|
+
if [ -n "$project" ]; then
|
|
512
|
+
[ -n "$session_id" ] && eagle_remember_session_project "$session_id" "$project" 1 >/dev/null 2>&1
|
|
513
|
+
printf '%s\n' "$project"
|
|
514
|
+
return
|
|
515
|
+
fi
|
|
516
|
+
fi
|
|
517
|
+
fi
|
|
518
|
+
|
|
519
|
+
if [ -n "$session_id" ]; then
|
|
520
|
+
if project=$(eagle_get_session_project_light "$session_id"); then
|
|
521
|
+
printf '%s\n' "$project"
|
|
522
|
+
return
|
|
523
|
+
fi
|
|
524
|
+
if project=$(eagle_get_session_project_marker "$session_id"); then
|
|
525
|
+
printf '%s\n' "$project"
|
|
526
|
+
return
|
|
527
|
+
fi
|
|
528
|
+
fi
|
|
529
|
+
|
|
530
|
+
project=$(eagle_project_from_cwd "$cwd")
|
|
531
|
+
[ -n "$session_id" ] && [ -n "$project" ] && eagle_remember_session_project "$session_id" "$project" 0 >/dev/null 2>&1
|
|
532
|
+
printf '%s\n' "$project"
|
|
278
533
|
}
|
|
279
534
|
|
|
280
535
|
eagle_project_file_path() {
|
|
@@ -810,6 +1065,114 @@ eagle_collect_files() {
|
|
|
810
1065
|
fi
|
|
811
1066
|
}
|
|
812
1067
|
|
|
1068
|
+
eagle_statusline_script_from_command() {
|
|
1069
|
+
local cmd="${1:-}"
|
|
1070
|
+
[ -z "$cmd" ] && return 1
|
|
1071
|
+
|
|
1072
|
+
cmd="${cmd#sh }"
|
|
1073
|
+
cmd="${cmd#bash }"
|
|
1074
|
+
cmd="${cmd#/bin/sh }"
|
|
1075
|
+
cmd="${cmd#/bin/bash }"
|
|
1076
|
+
cmd="${cmd#zsh }"
|
|
1077
|
+
cmd="${cmd#/bin/zsh }"
|
|
1078
|
+
cmd="${cmd%\"}"
|
|
1079
|
+
cmd="${cmd#\"}"
|
|
1080
|
+
cmd="${cmd%\'}"
|
|
1081
|
+
cmd="${cmd#\'}"
|
|
1082
|
+
|
|
1083
|
+
case "$cmd" in
|
|
1084
|
+
"~/"*) cmd="$HOME/${cmd#\~/}" ;;
|
|
1085
|
+
"\$HOME/"*) cmd="$HOME/${cmd#\$HOME/}" ;;
|
|
1086
|
+
"\${HOME}/"*) cmd="$HOME/${cmd#\$\{HOME\}/}" ;;
|
|
1087
|
+
esac
|
|
1088
|
+
|
|
1089
|
+
if [ -L "$cmd" ]; then
|
|
1090
|
+
local link_target link_dir
|
|
1091
|
+
link_target=$(readlink "$cmd" 2>/dev/null || true)
|
|
1092
|
+
if [ -n "$link_target" ]; then
|
|
1093
|
+
case "$link_target" in
|
|
1094
|
+
/*) cmd="$link_target" ;;
|
|
1095
|
+
*)
|
|
1096
|
+
link_dir=$(cd "$(dirname "$cmd")" && pwd -P) || return 1
|
|
1097
|
+
cmd="$link_dir/$link_target"
|
|
1098
|
+
;;
|
|
1099
|
+
esac
|
|
1100
|
+
fi
|
|
1101
|
+
fi
|
|
1102
|
+
|
|
1103
|
+
[ -f "$cmd" ] || return 1
|
|
1104
|
+
printf '%s\n' "$cmd"
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
eagle_statusline_script_uses_input() {
|
|
1108
|
+
local sl_file="${1:-}"
|
|
1109
|
+
[ -f "$sl_file" ] || return 1
|
|
1110
|
+
grep -Eq 'eagle_project_from_statusline_input|eagle_mem_statusline.*(\$\{input:-\}|\$input)' "$sl_file"
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
eagle_patch_statusline_script() {
|
|
1114
|
+
local sl_file="${1:-}"
|
|
1115
|
+
[ -f "$sl_file" ] || return 1
|
|
1116
|
+
command -v perl >/dev/null 2>&1 || return 1
|
|
1117
|
+
|
|
1118
|
+
if [ -L "$sl_file" ]; then
|
|
1119
|
+
local link_target link_dir
|
|
1120
|
+
link_target=$(readlink "$sl_file" 2>/dev/null || true)
|
|
1121
|
+
if [ -n "$link_target" ]; then
|
|
1122
|
+
case "$link_target" in
|
|
1123
|
+
/*) sl_file="$link_target" ;;
|
|
1124
|
+
*)
|
|
1125
|
+
link_dir=$(cd "$(dirname "$sl_file")" && pwd -P) || return 1
|
|
1126
|
+
sl_file="$link_dir/$link_target"
|
|
1127
|
+
;;
|
|
1128
|
+
esac
|
|
1129
|
+
fi
|
|
1130
|
+
fi
|
|
1131
|
+
|
|
1132
|
+
local tmp backup mode
|
|
1133
|
+
tmp=$(mktemp) || return 1
|
|
1134
|
+
cp "$sl_file" "$tmp" || { rm -f "$tmp"; return 1; }
|
|
1135
|
+
|
|
1136
|
+
if ! grep -Eq 'eagle_mem_statusline|eagle_project_from_cwd|claude_memories|agent_memories|\.eagle-mem/scripts/statusline-em' "$tmp" 2>/dev/null; then
|
|
1137
|
+
rm -f "$tmp"
|
|
1138
|
+
return 1
|
|
1139
|
+
fi
|
|
1140
|
+
|
|
1141
|
+
perl -0pi -e '
|
|
1142
|
+
s/(project_dir=\$\(echo "\$input" \| jq -r \x27)\.workspace\.current_dir \/\/ \.cwd/$1.workspace.project_dir \/\/ .workspace.current_dir \/\/ .cwd/g;
|
|
1143
|
+
s/(project_dir=\$\(echo "\$input" \| jq -r ")\.workspace\.current_dir \/\/ \.cwd/$1.workspace.project_dir \/\/ .workspace.current_dir \/\/ .cwd/g;
|
|
1144
|
+
s/eagle_mem_statusline "\$project_dir" "\$session_id" "\$\{input\}"/eagle_mem_statusline "\$project_dir" "\$session_id" "\${input:-}"/g;
|
|
1145
|
+
s/eagle_mem_statusline "\$project_dir" "\$session_id"(?=[\)\n;])/eagle_mem_statusline "\$project_dir" "\$session_id" "\${input:-}"/g;
|
|
1146
|
+
s/eagle_mem_statusline "\$project_dir"(?=[\)\n;])/eagle_mem_statusline "\$project_dir" "\${session_id:-}" "\${input:-}"/g;
|
|
1147
|
+
s/eagle_project_from_cwd "\$cwd"/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1148
|
+
s/eagle_project_from_cwd "\$project_dir"/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1149
|
+
s/eagle_project_from_cwd "\${project_dir:-\$cwd}"/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1150
|
+
s/eagle_project_from_cwd "\${project_dir:-\$(pwd)}"/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1151
|
+
s/eagle_project_from_cwd "\${eagle_mem_project_dir:-\${project_dir:-\$cwd}}"/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1152
|
+
s/eagle_project_from_cwd\("\$cwd"\)/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1153
|
+
s/eagle_project_from_cwd\("\$project_dir"\)/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1154
|
+
s/eagle_project_from_cwd\("\${project_dir:-\$cwd}"\)/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1155
|
+
s/eagle_project_from_cwd\("\${project_dir:-\$(pwd)}"\)/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1156
|
+
s/eagle_project_from_cwd\("\${eagle_mem_project_dir:-\${project_dir:-\$cwd}}"\)/eagle_project_from_statusline_input "\${input:-}" "\${project_dir:-}" "\${cwd:-}" "\${session_id:-}"/g;
|
|
1157
|
+
s/FROM claude_memories WHERE project/FROM agent_memories WHERE project/g;
|
|
1158
|
+
' "$tmp" || { rm -f "$tmp"; return 1; }
|
|
1159
|
+
|
|
1160
|
+
if cmp -s "$sl_file" "$tmp"; then
|
|
1161
|
+
rm -f "$tmp"
|
|
1162
|
+
return 1
|
|
1163
|
+
fi
|
|
1164
|
+
|
|
1165
|
+
backup="${sl_file}.eagle-mem.bak-$(date -u +%Y%m%dT%H%M%SZ)"
|
|
1166
|
+
cp "$sl_file" "$backup" 2>/dev/null || true
|
|
1167
|
+
mode=$(stat -f %Lp "$sl_file" 2>/dev/null || stat -c %a "$sl_file" 2>/dev/null || echo "")
|
|
1168
|
+
if ! mv "$tmp" "$sl_file"; then
|
|
1169
|
+
rm -f "$tmp"
|
|
1170
|
+
return 1
|
|
1171
|
+
fi
|
|
1172
|
+
[ -n "$mode" ] && chmod "$mode" "$sl_file" 2>/dev/null || chmod +x "$sl_file" 2>/dev/null || true
|
|
1173
|
+
return 0
|
|
1174
|
+
}
|
|
1175
|
+
|
|
813
1176
|
_eagle_claude_md_section() {
|
|
814
1177
|
cat << 'EAGLE_MD'
|
|
815
1178
|
|
package/lib/db-sessions.sh
CHANGED
|
@@ -6,12 +6,16 @@
|
|
|
6
6
|
_EAGLE_DB_SESSIONS_LOADED=1
|
|
7
7
|
|
|
8
8
|
eagle_upsert_session() {
|
|
9
|
-
local
|
|
10
|
-
local
|
|
9
|
+
local session_id_raw="${1:-}"
|
|
10
|
+
local project_raw="${2:-}"
|
|
11
|
+
local session_id; session_id=$(eagle_sql_escape "$session_id_raw")
|
|
12
|
+
local project; project=$(eagle_sql_escape "$project_raw")
|
|
11
13
|
local cwd; cwd=$(eagle_sql_escape "${3:-}")
|
|
12
14
|
local model; model=$(eagle_sql_escape "${4:-}")
|
|
13
15
|
local source; source=$(eagle_sql_escape "${5:-}")
|
|
14
16
|
local agent; agent=$(eagle_sql_escape "${6:-$(eagle_agent_source)}")
|
|
17
|
+
local prior_project
|
|
18
|
+
prior_project=$(eagle_db "SELECT project FROM sessions WHERE id = '$session_id' LIMIT 1;" 2>/dev/null || true)
|
|
15
19
|
|
|
16
20
|
eagle_db "INSERT INTO sessions (id, project, cwd, model, source, agent, last_activity_at)
|
|
17
21
|
VALUES ('$session_id', '$project', '$cwd', '$model', '$source', '$agent', strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
|
|
@@ -22,6 +26,127 @@ eagle_upsert_session() {
|
|
|
22
26
|
agent = COALESCE(NULLIF(excluded.agent, ''), sessions.agent),
|
|
23
27
|
status = 'active',
|
|
24
28
|
last_activity_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now');"
|
|
29
|
+
|
|
30
|
+
local needs_project_repair=0
|
|
31
|
+
if [ -n "$project_raw" ]; then
|
|
32
|
+
if [ "$prior_project" != "$project_raw" ]; then
|
|
33
|
+
needs_project_repair=1
|
|
34
|
+
else
|
|
35
|
+
local stale_child
|
|
36
|
+
stale_child=$(eagle_db "SELECT 1 WHERE
|
|
37
|
+
EXISTS (SELECT 1 FROM summaries WHERE session_id = '$session_id' AND project != '$project')
|
|
38
|
+
OR EXISTS (SELECT 1 FROM observations WHERE session_id = '$session_id' AND project != '$project')
|
|
39
|
+
OR EXISTS (SELECT 1 FROM agent_tasks WHERE source_session_id = '$session_id' AND project != '$project')
|
|
40
|
+
OR EXISTS (SELECT 1 FROM agent_memories WHERE origin_session_id = '$session_id' AND project != '$project')
|
|
41
|
+
OR EXISTS (SELECT 1 FROM agent_plans WHERE origin_session_id = '$session_id' AND project != '$project')
|
|
42
|
+
OR EXISTS (SELECT 1 FROM pending_feature_verifications WHERE source_session_id = '$session_id' AND project != '$project')
|
|
43
|
+
OR EXISTS (
|
|
44
|
+
SELECT 1
|
|
45
|
+
FROM pending_feature_verifications p
|
|
46
|
+
JOIN features f ON f.id = p.feature_id
|
|
47
|
+
WHERE p.source_session_id = '$session_id'
|
|
48
|
+
AND f.project != '$project'
|
|
49
|
+
)
|
|
50
|
+
LIMIT 1;" 2>/dev/null || true)
|
|
51
|
+
[ "$stale_child" = "1" ] && needs_project_repair=1
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
if [ "$needs_project_repair" = "1" ]; then
|
|
56
|
+
eagle_db_pipe <<SQL >/dev/null 2>&1
|
|
57
|
+
BEGIN;
|
|
58
|
+
UPDATE summaries SET project = '$project' WHERE session_id = '$session_id' AND project != '$project';
|
|
59
|
+
UPDATE observations SET project = '$project' WHERE session_id = '$session_id' AND project != '$project';
|
|
60
|
+
UPDATE agent_tasks SET project = '$project' WHERE source_session_id = '$session_id' AND project != '$project';
|
|
61
|
+
UPDATE agent_memories SET project = '$project' WHERE origin_session_id = '$session_id' AND project != '$project';
|
|
62
|
+
UPDATE agent_plans SET project = '$project' WHERE origin_session_id = '$session_id' AND project != '$project';
|
|
63
|
+
CREATE TEMP TABLE IF NOT EXISTS eagle_feature_repair_map (
|
|
64
|
+
old_feature_id INTEGER PRIMARY KEY,
|
|
65
|
+
new_feature_id INTEGER NOT NULL
|
|
66
|
+
);
|
|
67
|
+
DELETE FROM eagle_feature_repair_map;
|
|
68
|
+
INSERT OR IGNORE INTO features (project, name, description, status, last_verified_at, last_verified_notes)
|
|
69
|
+
SELECT '$project', f_old.name, f_old.description, f_old.status, f_old.last_verified_at, f_old.last_verified_notes
|
|
70
|
+
FROM pending_feature_verifications p
|
|
71
|
+
JOIN features f_old ON f_old.id = p.feature_id
|
|
72
|
+
WHERE p.source_session_id = '$session_id'
|
|
73
|
+
AND (p.project != '$project' OR f_old.project != '$project')
|
|
74
|
+
GROUP BY f_old.name;
|
|
75
|
+
INSERT OR REPLACE INTO eagle_feature_repair_map (old_feature_id, new_feature_id)
|
|
76
|
+
SELECT DISTINCT f_old.id, f_new.id
|
|
77
|
+
FROM pending_feature_verifications p
|
|
78
|
+
JOIN features f_old ON f_old.id = p.feature_id
|
|
79
|
+
JOIN features f_new ON f_new.project = '$project' AND f_new.name = f_old.name
|
|
80
|
+
WHERE p.source_session_id = '$session_id'
|
|
81
|
+
AND (p.project != '$project' OR f_old.project != '$project');
|
|
82
|
+
INSERT OR IGNORE INTO feature_files (feature_id, file_path, role)
|
|
83
|
+
SELECT f_new.id, ff.file_path, ff.role
|
|
84
|
+
FROM pending_feature_verifications p
|
|
85
|
+
JOIN features f_old ON f_old.id = p.feature_id
|
|
86
|
+
JOIN eagle_feature_repair_map m ON m.old_feature_id = f_old.id
|
|
87
|
+
JOIN features f_new ON f_new.id = m.new_feature_id
|
|
88
|
+
JOIN feature_files ff ON ff.feature_id = f_old.id
|
|
89
|
+
WHERE p.source_session_id = '$session_id'
|
|
90
|
+
AND (p.project != '$project' OR f_old.project != '$project');
|
|
91
|
+
INSERT OR IGNORE INTO feature_dependencies (feature_id, kind, target, name, notes)
|
|
92
|
+
SELECT f_new.id, fd.kind, fd.target, fd.name, fd.notes
|
|
93
|
+
FROM pending_feature_verifications p
|
|
94
|
+
JOIN features f_old ON f_old.id = p.feature_id
|
|
95
|
+
JOIN eagle_feature_repair_map m ON m.old_feature_id = f_old.id
|
|
96
|
+
JOIN features f_new ON f_new.id = m.new_feature_id
|
|
97
|
+
JOIN feature_dependencies fd ON fd.feature_id = f_old.id
|
|
98
|
+
WHERE p.source_session_id = '$session_id'
|
|
99
|
+
AND (p.project != '$project' OR f_old.project != '$project');
|
|
100
|
+
INSERT OR IGNORE INTO feature_smoke_tests (feature_id, command, description)
|
|
101
|
+
SELECT f_new.id, fst.command, fst.description
|
|
102
|
+
FROM pending_feature_verifications p
|
|
103
|
+
JOIN features f_old ON f_old.id = p.feature_id
|
|
104
|
+
JOIN eagle_feature_repair_map m ON m.old_feature_id = f_old.id
|
|
105
|
+
JOIN features f_new ON f_new.id = m.new_feature_id
|
|
106
|
+
JOIN feature_smoke_tests fst ON fst.feature_id = f_old.id
|
|
107
|
+
WHERE p.source_session_id = '$session_id'
|
|
108
|
+
AND (p.project != '$project' OR f_old.project != '$project');
|
|
109
|
+
DELETE FROM pending_feature_verifications
|
|
110
|
+
WHERE source_session_id = '$session_id'
|
|
111
|
+
AND status = 'pending'
|
|
112
|
+
AND id NOT IN (
|
|
113
|
+
SELECT MIN(p.id)
|
|
114
|
+
FROM pending_feature_verifications p
|
|
115
|
+
LEFT JOIN eagle_feature_repair_map m ON m.old_feature_id = p.feature_id
|
|
116
|
+
WHERE p.source_session_id = '$session_id'
|
|
117
|
+
AND p.status = 'pending'
|
|
118
|
+
GROUP BY
|
|
119
|
+
CASE WHEN m.new_feature_id IS NOT NULL THEN '$project' ELSE p.project END,
|
|
120
|
+
COALESCE(m.new_feature_id, p.feature_id),
|
|
121
|
+
p.file_path
|
|
122
|
+
)
|
|
123
|
+
AND EXISTS (
|
|
124
|
+
SELECT 1
|
|
125
|
+
FROM eagle_feature_repair_map m
|
|
126
|
+
WHERE m.old_feature_id = pending_feature_verifications.feature_id
|
|
127
|
+
);
|
|
128
|
+
UPDATE pending_feature_verifications
|
|
129
|
+
SET feature_id = COALESCE((SELECT new_feature_id FROM eagle_feature_repair_map WHERE old_feature_id = feature_id), feature_id)
|
|
130
|
+
WHERE source_session_id = '$session_id'
|
|
131
|
+
AND EXISTS (SELECT 1 FROM eagle_feature_repair_map WHERE old_feature_id = pending_feature_verifications.feature_id);
|
|
132
|
+
DELETE FROM pending_feature_verifications
|
|
133
|
+
WHERE source_session_id = '$session_id'
|
|
134
|
+
AND project != '$project'
|
|
135
|
+
AND status = 'pending'
|
|
136
|
+
AND EXISTS (
|
|
137
|
+
SELECT 1
|
|
138
|
+
FROM pending_feature_verifications p2
|
|
139
|
+
WHERE p2.project = '$project'
|
|
140
|
+
AND p2.feature_id = pending_feature_verifications.feature_id
|
|
141
|
+
AND p2.file_path = pending_feature_verifications.file_path
|
|
142
|
+
AND p2.status = 'pending'
|
|
143
|
+
AND p2.id != pending_feature_verifications.id
|
|
144
|
+
);
|
|
145
|
+
UPDATE pending_feature_verifications SET project = '$project' WHERE source_session_id = '$session_id' AND project != '$project';
|
|
146
|
+
UPDATE sessions SET project = '$project' WHERE id = '$session_id' AND project != '$project';
|
|
147
|
+
COMMIT;
|
|
148
|
+
SQL
|
|
149
|
+
fi
|
|
25
150
|
}
|
|
26
151
|
|
|
27
152
|
eagle_end_session() {
|
package/package.json
CHANGED
package/scripts/install.sh
CHANGED
|
@@ -299,6 +299,7 @@ fi
|
|
|
299
299
|
if [ "$claude_found" = true ]; then
|
|
300
300
|
EM_STATUSLINE="$EAGLE_MEM_DIR/scripts/statusline-em.sh"
|
|
301
301
|
existing_sl=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null)
|
|
302
|
+
existing_sl_file=$(eagle_statusline_script_from_command "$existing_sl" 2>/dev/null || true)
|
|
302
303
|
|
|
303
304
|
if [ -z "$existing_sl" ]; then
|
|
304
305
|
# No statusline configured — set up a minimal one that shows Eagle Mem
|
|
@@ -309,29 +310,37 @@ input=$(cat)
|
|
|
309
310
|
project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // ""' 2>/dev/null)
|
|
310
311
|
session_id=$(echo "$input" | jq -r '.session_id // .session.id // ""' 2>/dev/null)
|
|
311
312
|
source "$HOME/.eagle-mem/scripts/statusline-em.sh"
|
|
312
|
-
eagle_mem_statusline "$project_dir" "$session_id"
|
|
313
|
+
eagle_mem_statusline "$project_dir" "$session_id" "$input"
|
|
313
314
|
WRAPPER
|
|
314
315
|
chmod +x "$wrapper"
|
|
315
316
|
tmp=$(mktemp)
|
|
316
317
|
jq --arg cmd "sh $wrapper" '.statusLine = {"type": "command", "command": $cmd, "refreshInterval": 30}' "$SETTINGS" > "$tmp" && mv "$tmp" "$SETTINGS"
|
|
317
318
|
eagle_ok "Statusline ${DIM}(new — Eagle Mem indicator)${RESET}"
|
|
318
|
-
elif echo "$existing_sl" | grep -q "eagle-mem"; then
|
|
319
|
-
eagle_ok "Statusline ${DIM}(already has Eagle Mem)${RESET}"
|
|
320
319
|
else
|
|
321
|
-
# Existing statusline —
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
320
|
+
# Existing statusline — if it points at a shell script, inspect the
|
|
321
|
+
# target file. Custom HUD commands often do not include "eagle-mem" in
|
|
322
|
+
# the command string even when the script contains an embedded block.
|
|
323
|
+
sl_file="$existing_sl_file"
|
|
324
|
+
if [ -n "$sl_file" ] && [ -f "$sl_file" ]; then
|
|
325
|
+
if eagle_patch_statusline_script "$sl_file"; then
|
|
326
|
+
eagle_ok "Statusline ${DIM}(patched existing Eagle Mem block)${RESET}"
|
|
327
|
+
elif eagle_statusline_script_uses_input "$sl_file"; then
|
|
328
|
+
eagle_ok "Statusline ${DIM}(already has Eagle Mem)${RESET}"
|
|
329
|
+
else
|
|
330
|
+
eagle_dim " Statusline detected: $sl_file"
|
|
331
|
+
eagle_dim " To add Eagle Mem, add this snippet before your ASSEMBLE section:"
|
|
332
|
+
echo ""
|
|
333
|
+
eagle_dim " # ── Eagle Mem ──"
|
|
334
|
+
eagle_dim " em_section=\"\""
|
|
335
|
+
eagle_dim " if [ -f \"\$HOME/.eagle-mem/scripts/statusline-em.sh\" ]; then"
|
|
336
|
+
eagle_dim " source \"\$HOME/.eagle-mem/scripts/statusline-em.sh\""
|
|
337
|
+
eagle_dim " em_section=\$(eagle_mem_statusline \"\$project_dir\" \"\$session_id\" \"\$input\")"
|
|
338
|
+
eagle_dim " fi"
|
|
339
|
+
echo ""
|
|
340
|
+
eagle_ok "Statusline ${DIM}(manual patch needed — instructions above)${RESET}"
|
|
341
|
+
fi
|
|
342
|
+
elif echo "$existing_sl" | grep -q "eagle-mem"; then
|
|
343
|
+
eagle_ok "Statusline ${DIM}(already has Eagle Mem)${RESET}"
|
|
335
344
|
else
|
|
336
345
|
eagle_ok "Statusline ${DIM}(existing — cannot auto-patch; add Eagle Mem manually)${RESET}"
|
|
337
346
|
fi
|
package/scripts/statusline-em.sh
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
eagle_mem_statusline() {
|
|
7
7
|
local project_dir="${1:-}"
|
|
8
8
|
local session_id="${2:-}"
|
|
9
|
+
local statusline_input="${3:-}"
|
|
9
10
|
local em_db="$HOME/.eagle-mem/memory.db"
|
|
10
11
|
[ -f "$em_db" ] || return
|
|
11
12
|
|
|
@@ -14,7 +15,7 @@ eagle_mem_statusline() {
|
|
|
14
15
|
|
|
15
16
|
local proj
|
|
16
17
|
[ -z "$project_dir" ] && project_dir="$(pwd)"
|
|
17
|
-
proj=$(
|
|
18
|
+
proj=$(eagle_project_from_statusline_input "$statusline_input" "$project_dir" "$project_dir" "$session_id")
|
|
18
19
|
[ -z "$proj" ] && return
|
|
19
20
|
|
|
20
21
|
proj=$(eagle_sql_escape "$proj")
|
|
@@ -57,5 +58,5 @@ if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
|
57
58
|
fi
|
|
58
59
|
project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // empty' 2>/dev/null)
|
|
59
60
|
session_id=$(echo "$input" | jq -r '.session_id // .session.id // empty' 2>/dev/null)
|
|
60
|
-
eagle_mem_statusline "${project_dir:-$(pwd)}" "$session_id"
|
|
61
|
+
eagle_mem_statusline "${project_dir:-$(pwd)}" "$session_id" "$input"
|
|
61
62
|
fi
|
package/scripts/update.sh
CHANGED
|
@@ -153,12 +153,22 @@ input=$(cat)
|
|
|
153
153
|
project_dir=$(echo "$input" | jq -r '.workspace.project_dir // .workspace.current_dir // .cwd // ""' 2>/dev/null)
|
|
154
154
|
session_id=$(echo "$input" | jq -r '.session_id // .session.id // ""' 2>/dev/null)
|
|
155
155
|
source "$HOME/.eagle-mem/scripts/statusline-em.sh"
|
|
156
|
-
eagle_mem_statusline "$project_dir" "$session_id"
|
|
156
|
+
eagle_mem_statusline "$project_dir" "$session_id" "$input"
|
|
157
157
|
WRAPPER
|
|
158
158
|
chmod +x "$statusline_wrapper"
|
|
159
159
|
eagle_ok "Statusline wrapper updated"
|
|
160
160
|
fi
|
|
161
161
|
|
|
162
|
+
if [ "$claude_found" = true ] && [ -f "$SETTINGS" ] && command -v jq >/dev/null 2>&1; then
|
|
163
|
+
existing_sl=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null)
|
|
164
|
+
existing_sl_file=$(eagle_statusline_script_from_command "$existing_sl" 2>/dev/null || true)
|
|
165
|
+
if eagle_patch_statusline_script "$existing_sl_file"; then
|
|
166
|
+
eagle_ok "Statusline custom Eagle Mem block patched"
|
|
167
|
+
elif [ -n "$existing_sl_file" ] && [ -f "$existing_sl_file" ] && grep -q "eagle-mem" "$existing_sl_file" && ! eagle_statusline_script_uses_input "$existing_sl_file"; then
|
|
168
|
+
eagle_warn "Statusline custom Eagle Mem block needs manual input-aware update"
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
171
|
+
|
|
162
172
|
# ─── Backfill project names ───────────────────────────────
|
|
163
173
|
|
|
164
174
|
backfilled=$(eagle_backfill_projects 2>/dev/null)
|