chat-recall 0.5.4 → 0.5.6
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/dist/cli.js +1506 -733
- package/dist/cli.js.map +1 -1
- package/dist/mcp-diagnostics.d.ts +45 -0
- package/dist/mcp-diagnostics.d.ts.map +1 -0
- package/dist/mcp-diagnostics.js +98 -0
- package/dist/mcp-diagnostics.js.map +1 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +2096 -1151
- package/dist/mcp.js.map +1 -1
- package/dist/project-tasks.d.ts.map +1 -1
- package/dist/project-tasks.js +12 -7
- package/dist/project-tasks.js.map +1 -1
- package/dist/service-installer.d.ts +1 -1
- package/dist/service-installer.d.ts.map +1 -1
- package/dist/service-installer.js +20 -6
- package/dist/service-installer.js.map +1 -1
- package/dist/sync-client.d.ts +1 -0
- package/dist/sync-client.d.ts.map +1 -1
- package/dist/sync-client.js +179 -92
- package/dist/sync-client.js.map +1 -1
- package/dist/sync-ledger.d.ts +22 -0
- package/dist/sync-ledger.d.ts.map +1 -1
- package/dist/sync-ledger.js +108 -1
- package/dist/sync-ledger.js.map +1 -1
- package/dist/watch.js +1104 -481
- package/hooks/chat_recall_escalate_hook.sh +28 -2
- package/hooks/chat_recall_save_hook.sh +17 -11
- package/hooks/chat_recall_wakeup_hook.sh +27 -1
- package/package.json +7 -3
- package/skills/chat-recall/SKILL.md +3 -2
|
@@ -33,6 +33,32 @@ fi
|
|
|
33
33
|
CHAT_RECALL_BIN="${CHAT_RECALL_BIN:-$(command -v chat-recall || true)}"
|
|
34
34
|
if [[ -z "$CHAT_RECALL_BIN" ]] || [[ ! -x "$CHAT_RECALL_BIN" ]]; then exit 0; fi
|
|
35
35
|
|
|
36
|
+
# Run a command under a time limit, on any platform.
|
|
37
|
+
#
|
|
38
|
+
# `timeout` is GNU coreutils and macOS does not ship it. Both hooks that used it
|
|
39
|
+
# swallowed the failure with `|| true`, so on every Mac the command never ran at
|
|
40
|
+
# all — silently, while `chat-recall doctor` reported the hook installed and
|
|
41
|
+
# healthy. Homebrew's coreutils installs it as `gtimeout`, so prefer whichever
|
|
42
|
+
# exists and fall back to a plain shell watchdog when neither does.
|
|
43
|
+
run_limited() {
|
|
44
|
+
local secs="$1"; shift
|
|
45
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
46
|
+
timeout "$secs" "$@"
|
|
47
|
+
elif command -v gtimeout >/dev/null 2>&1; then
|
|
48
|
+
gtimeout "$secs" "$@"
|
|
49
|
+
else
|
|
50
|
+
# Watchdog: run in the background, kill it if it outlives the budget.
|
|
51
|
+
"$@" &
|
|
52
|
+
local cmd_pid=$!
|
|
53
|
+
( sleep "$secs"; kill -TERM "$cmd_pid" 2>/dev/null || true ) &
|
|
54
|
+
local watch_pid=$!
|
|
55
|
+
wait "$cmd_pid" 2>/dev/null
|
|
56
|
+
local rc=$?
|
|
57
|
+
kill -TERM "$watch_pid" 2>/dev/null || true
|
|
58
|
+
return $rc
|
|
59
|
+
fi
|
|
60
|
+
}
|
|
61
|
+
|
|
36
62
|
TIMEOUT="${CHAT_RECALL_ESCALATE_TIMEOUT:-60}"
|
|
37
63
|
DELAY="${CHAT_RECALL_ESCALATE_DELAY:-20}"
|
|
38
64
|
|
|
@@ -42,9 +68,9 @@ DELAY="${CHAT_RECALL_ESCALATE_DELAY:-20}"
|
|
|
42
68
|
sleep "$DELAY"
|
|
43
69
|
cd "$CWD" 2>/dev/null || true
|
|
44
70
|
if [[ -n "$SESSION_ID" ]]; then
|
|
45
|
-
|
|
71
|
+
run_limited "$TIMEOUT" "$CHAT_RECALL_BIN" escalate "$SESSION_ID" >/dev/null 2>&1 || true
|
|
46
72
|
else
|
|
47
|
-
|
|
73
|
+
run_limited "$TIMEOUT" "$CHAT_RECALL_BIN" escalate --latest >/dev/null 2>&1 || true
|
|
48
74
|
fi
|
|
49
75
|
) </dev/null >/dev/null 2>&1 &
|
|
50
76
|
|
|
@@ -109,7 +109,7 @@ extract_facts() {
|
|
|
109
109
|
"tool_uses": $tools,
|
|
110
110
|
"first_topic": "$(echo "$first_topic" | jq -Rs '.' 2>/dev/null || echo "\"$first_topic\"")",
|
|
111
111
|
"decisions": "$(echo "$decisions" | jq -Rs '.' 2>/dev/null || echo "\"\"")",
|
|
112
|
-
"saved_at": "$(date -
|
|
112
|
+
"saved_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
113
113
|
}
|
|
114
114
|
EOF
|
|
115
115
|
}
|
|
@@ -176,7 +176,12 @@ do_save() {
|
|
|
176
176
|
fi
|
|
177
177
|
|
|
178
178
|
# Track this save
|
|
179
|
-
|
|
179
|
+
# `date -Iseconds` is GNU-only: BSD date (macOS) rejects -I and prints an
|
|
180
|
+
# empty string, so this field was blank on every Mac. -u +format works on
|
|
181
|
+
# both. saved_at_epoch is written alongside it because reading the ISO value
|
|
182
|
+
# BACK needed `date -d`, which BSD also lacks — storing the number means
|
|
183
|
+
# nothing has to parse a date at all.
|
|
184
|
+
echo "{\"session_id\": \"$SESSION_ID\", \"saved_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\", \"saved_at_epoch\": $(date +%s), \"precompact\": $precompact}" > "${STATE_FILE}"
|
|
180
185
|
|
|
181
186
|
if [[ "$precompact" == "true" ]]; then
|
|
182
187
|
log "[PRECOMPACT] Emergency save for $SESSION_ID"
|
|
@@ -193,17 +198,18 @@ should_save() {
|
|
|
193
198
|
return 0
|
|
194
199
|
fi
|
|
195
200
|
|
|
196
|
-
#
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
+
# Read the epoch we stored. The old code kept only an ISO string and parsed
|
|
202
|
+
# it with `date -d`, which does not exist on BSD date — so on macOS this
|
|
203
|
+
# always resolved to 0, the throttle never engaged, and the hook re-scanned
|
|
204
|
+
# the entire transcript on EVERY Stop event.
|
|
205
|
+
local last_save_epoch
|
|
206
|
+
last_save_epoch=$(jq -r '.saved_at_epoch // empty' "${STATE_FILE}" 2>/dev/null || echo "")
|
|
207
|
+
|
|
208
|
+
if [[ -z "$last_save_epoch" ]]; then
|
|
209
|
+
# A state file written before saved_at_epoch existed. Treat it as due
|
|
210
|
+
# rather than trying to parse its timestamp portably.
|
|
201
211
|
return 0
|
|
202
212
|
fi
|
|
203
|
-
|
|
204
|
-
# Don't save more than once per 30 seconds
|
|
205
|
-
local last_save_epoch
|
|
206
|
-
last_save_epoch=$(date -d "$last_save" +%s 2>/dev/null || echo 0)
|
|
207
213
|
local now_epoch
|
|
208
214
|
now_epoch=$(date +%s)
|
|
209
215
|
|
|
@@ -27,7 +27,33 @@ CHAT_RECALL_BIN="${CHAT_RECALL_BIN:-$(command -v chat-recall || true)}"
|
|
|
27
27
|
if [[ -z "$CHAT_RECALL_BIN" ]] || [[ ! -x "$CHAT_RECALL_BIN" ]]; then exit 0; fi
|
|
28
28
|
|
|
29
29
|
TIMEOUT="${CHAT_RECALL_WAKEUP_TIMEOUT:-10}"
|
|
30
|
-
|
|
30
|
+
# Run a command under a time limit, on any platform.
|
|
31
|
+
#
|
|
32
|
+
# `timeout` is GNU coreutils and macOS does not ship it. Both hooks that used it
|
|
33
|
+
# swallowed the failure with `|| true`, so on every Mac the command never ran at
|
|
34
|
+
# all — silently, while `chat-recall doctor` reported the hook installed and
|
|
35
|
+
# healthy. Homebrew's coreutils installs it as `gtimeout`, so prefer whichever
|
|
36
|
+
# exists and fall back to a plain shell watchdog when neither does.
|
|
37
|
+
run_limited() {
|
|
38
|
+
local secs="$1"; shift
|
|
39
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
40
|
+
timeout "$secs" "$@"
|
|
41
|
+
elif command -v gtimeout >/dev/null 2>&1; then
|
|
42
|
+
gtimeout "$secs" "$@"
|
|
43
|
+
else
|
|
44
|
+
# Watchdog: run in the background, kill it if it outlives the budget.
|
|
45
|
+
"$@" &
|
|
46
|
+
local cmd_pid=$!
|
|
47
|
+
( sleep "$secs"; kill -TERM "$cmd_pid" 2>/dev/null || true ) &
|
|
48
|
+
local watch_pid=$!
|
|
49
|
+
wait "$cmd_pid" 2>/dev/null
|
|
50
|
+
local rc=$?
|
|
51
|
+
kill -TERM "$watch_pid" 2>/dev/null || true
|
|
52
|
+
return $rc
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
OUT="$(run_limited "$TIMEOUT" "$CHAT_RECALL_BIN" memory wake-up -p "$PROJECT" 2>/dev/null || true)"
|
|
31
57
|
[[ -z "$OUT" ]] && exit 0
|
|
32
58
|
|
|
33
59
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chat-recall",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/munhq/chat-recall.git"
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
},
|
|
12
12
|
"description": "Local-first memory for AI coding tools \u2014 indexes Claude Code / Gemini CLI / OpenCode / Codex sessions, exposes them over MCP, optionally syncs redacted history to a chat-recall server",
|
|
13
13
|
"type": "module",
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22.5.0"
|
|
16
|
+
},
|
|
14
17
|
"license": "Elastic-2.0",
|
|
15
18
|
"bin": {
|
|
16
19
|
"chat-recall": "./dist/cli.js",
|
|
@@ -25,9 +28,10 @@
|
|
|
25
28
|
"LICENSE"
|
|
26
29
|
],
|
|
27
30
|
"scripts": {
|
|
28
|
-
"build": "tsc -b && node scripts/bundle.mjs && node scripts/postbuild.mjs",
|
|
31
|
+
"build": "tsc -b && tsc -p tsconfig.daemon.json && node scripts/bundle.mjs && node scripts/postbuild.mjs",
|
|
29
32
|
"build:types": "tsc -b",
|
|
30
|
-
"auto-indexer": "tsx auto-indexer/indexer.ts"
|
|
33
|
+
"auto-indexer": "tsx auto-indexer/indexer.ts",
|
|
34
|
+
"typecheck:daemon": "tsc -p tsconfig.daemon.json"
|
|
31
35
|
},
|
|
32
36
|
"dependencies": {
|
|
33
37
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
@@ -31,6 +31,7 @@ read except these, which change stored memory or state — treat each as an edit
|
|
|
31
31
|
and apply the test in `chat-recall-memory` before calling one:
|
|
32
32
|
`recall_kg_add`, `recall_kg_invalidate`, `recall_decision_record`,
|
|
33
33
|
`recall_diary_write`, `recall_set`, `recall_task_create`, `recall_task_update`,
|
|
34
|
+
`recall_task_comment`,
|
|
34
35
|
`recall_security_dismiss`, `recall_rename_session`, `recall_regenerate_summary`,
|
|
35
36
|
`recall_reclassify`, `recall_index`, `recall_code_index`.
|
|
36
37
|
|
|
@@ -65,9 +66,9 @@ tool is registered and never named here, so adding a tool means placing it.
|
|
|
65
66
|
**Findings, ranked** — `recall_claude_suggestions` (every finding that becomes an agent-instruction change — the CLAUDE.md rules and skill installs — merged across account scope and every indexed project) and `recall_improvements` (everything else, most urgent first; `create_tasks: true` opens one team task per item). They split the same engines, so an item never appears in both. Neither needs the codeindex binary: without it you still get the account-level half.
|
|
66
67
|
**What changed** — `recall_edits_timeline` (cross-tool edits), `recall_diff` (per-session diffs), `recall_commits` (did it actually land), `recall_markers` (where a session went sideways).
|
|
67
68
|
**Durable memory / KG** — `recall_kg_query` / `recall_kg_add` / `recall_kg_invalidate` / `recall_kg_timeline` / `recall_kg_stats`, `recall_decision_record`, `recall_diary_write` / `recall_diary_read`, `recall_set` / `recall_get`.
|
|
68
|
-
**Team** — `recall_tasks` (the shared task board), `recall_task_create`, `recall_task_update` (status, assignee,
|
|
69
|
+
**Team** — `recall_tasks` (the shared task board), `recall_task_create`, `recall_task_update` (status, assignee, linked session; task ids look like `t_…`; when you start work on a task, set it `in_progress` and pass your session id as `linked_session_id` so the board can verify the work shipped), `recall_task_comment` (leave a progress note on a card), `recall_team_activity` (per-teammate × per-project rollup), `recall_shares` (which projects are shared — private by default, nothing is visible to teammates until shared).
|
|
69
70
|
**Security** — `recall_security_summary` (leaked secrets that still need action — start here for "did I paste a key somewhere"), `recall_security_session` (findings for one session), `recall_security_dismiss` (mark rotated / false positive — do this only when the user confirms which), `recall_security_rules` (tenant detection rules; also tests a regex).
|
|
70
|
-
**Health / maintenance** — `recall_status` (is the index alive, what is synced), `recall_index` (sync now), `recall_heal_audit` (sessions whose rendered text is thinner than the raw archive, i.e. truncated upstream), `recall_regenerate_summary` (stored summary is stale or wrong), `recall_reclassify` (re-run the classifier over old chunks), `recall_rename_session`.
|
|
71
|
+
**Health / maintenance** — `recall_status` (is the index alive, what is synced), `recall_index` (sync now), `recall_help` (names the tools the lean profile leaves unlisted — they all still work by name), `recall_heal_audit` (sessions whose rendered text is thinner than the raw archive, i.e. truncated upstream), `recall_regenerate_summary` (stored summary is stale or wrong), `recall_reclassify` (re-run the classifier over old chunks), `recall_rename_session`.
|
|
71
72
|
|
|
72
73
|
## If you're unsure where to start
|
|
73
74
|
|