claude-mem-lite 2.79.1 → 2.80.1
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/install.mjs +32 -8
- package/lib/citation-tracker.mjs +11 -2
- package/package.json +1 -1
- package/scripts/setup.sh +1 -1
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ Source files stay in the cloned repo. Update via `git pull && node install.mjs i
|
|
|
161
161
|
### What happens during installation
|
|
162
162
|
|
|
163
163
|
1. **Install dependencies** -- `npm install --omit=dev` (compiles native `better-sqlite3`)
|
|
164
|
-
2. **Register MCP server** -- `mem-lite` server with
|
|
164
|
+
2. **Register MCP server** -- `mem-lite` server with 20 tools (9 core exposed via `tools/list` + 11 hidden-but-callable; see the Usage section for the full table). The pre-v2.78 generic server name `mem` is renamed to `mem-lite` for namespace hygiene; the tool names themselves (`mem_search`, `mem_recall`, ...) are unchanged.
|
|
165
165
|
3. **Configure hooks** -- `PostToolUse`, `SessionStart`, `Stop`, `UserPromptSubmit` lifecycle hooks
|
|
166
166
|
4. **Create data directory** -- `~/.claude-mem-lite/` (hidden) for database, runtime, and managed resource files
|
|
167
167
|
5. **Auto-migrate** -- If `~/.claude-mem/` (original claude-mem) or `~/claude-mem-lite/` (pre-v0.5 unhidden) exists, migrates database and runtime files to `~/.claude-mem-lite/`, preserving the original untouched
|
package/README.zh-CN.md
CHANGED
|
@@ -146,7 +146,7 @@ node install.mjs install
|
|
|
146
146
|
### 安装过程
|
|
147
147
|
|
|
148
148
|
1. **安装依赖** -- `npm install --omit=dev`(编译原生 `better-sqlite3`)
|
|
149
|
-
2. **注册 MCP 服务器** -- `mem-lite` 服务器,包含
|
|
149
|
+
2. **注册 MCP 服务器** -- `mem-lite` 服务器,包含 20 个工具(9 个核心通过 `tools/list` 暴露 + 11 个隐藏但可调;完整表见 Usage 段)。v2.78 前服务器名为通用的 `mem`,现已改名为 `mem-lite` 避免与用户其它 `.mcp.json` 冲突;工具名(`mem_search`/`mem_recall` 等)保持不变。
|
|
150
150
|
|
|
151
151
|
> **每个项目第一次使用,跑一次 `/adopt`。** Plugin 安装给你 MCP server + hooks + slash commands,但**邀请式 memory 哨兵**(一条提升 Claude 主动调用 `mem_recall` / `mem_save` 的 system-authority 指针)是按项目 opt-in 的。不跑 `/adopt` 时 hooks 仍记录观察、注入上下文,但 Claude 不太会主动调 MCP 工具。一次性、按项目:`/adopt`;撤销 `/unadopt`。
|
|
152
152
|
3. **配置钩子** -- `PostToolUse`、`PreToolUse`、`SessionStart`、`Stop`、`UserPromptSubmit` 生命周期钩子
|
package/install.mjs
CHANGED
|
@@ -1517,11 +1517,28 @@ function hasMemHooksConfigured(settings) {
|
|
|
1517
1517
|
* node "/home/sds/.claude-mem-lite/hook.mjs" session-start
|
|
1518
1518
|
* bash "/home/sds/.claude-mem-lite/scripts/post-tool-use.sh"
|
|
1519
1519
|
* node "/home/sds/.claude-mem-lite/scripts/pre-tool-recall.js"
|
|
1520
|
-
*
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1520
|
+
*
|
|
1521
|
+
* Scan order (v2.80+): walk EVERY quoted token via matchAll, prefer ones that
|
|
1522
|
+
* look like a hook path (absolute + ends in a known hook-runtime extension).
|
|
1523
|
+
* If no quoted token qualifies, fall back to the first path-shaped token from
|
|
1524
|
+
* a whitespace-split of the command. If both miss, skip the entry entirely —
|
|
1525
|
+
* deliberate bias toward **under-reporting over false-flagging**: a wrapper
|
|
1526
|
+
* like `bash -c "inline" "/real/path.sh"` should report the real path, not
|
|
1527
|
+
* the inline string. ${CLAUDE_PLUGIN_ROOT}-templated commands are ignored —
|
|
1528
|
+
* those are plugin-owned hooks resolved by Claude Code at runtime, not by us.
|
|
1529
|
+
*
|
|
1530
|
+
* Extension list (HOOK_PATH_EXTS) is hardcoded for the runtimes this plugin
|
|
1531
|
+
* actually registers (node/bash). Extend if Claude Code ever supports new
|
|
1532
|
+
* hook runtimes (e.g. python/.py). Currently safe because isMemHook() filters
|
|
1533
|
+
* to claude-mem-lite-owned hooks only — foreign runtimes can't reach here.
|
|
1524
1534
|
*/
|
|
1535
|
+
const HOOK_PATH_EXTS = ['.mjs', '.js', '.cjs', '.sh'];
|
|
1536
|
+
|
|
1537
|
+
function looksLikeHookPath(p) {
|
|
1538
|
+
if (!p || !p.startsWith('/')) return false;
|
|
1539
|
+
return HOOK_PATH_EXTS.some(ext => p.endsWith(ext));
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1525
1542
|
export function collectOrphanHookPaths(settings) {
|
|
1526
1543
|
if (!settings?.hooks) return [];
|
|
1527
1544
|
const out = [];
|
|
@@ -1532,12 +1549,19 @@ export function collectOrphanHookPaths(settings) {
|
|
|
1532
1549
|
for (const h of cfg.hooks || []) {
|
|
1533
1550
|
const cmd = h.command || '';
|
|
1534
1551
|
if (cmd.includes('${CLAUDE_PLUGIN_ROOT}')) continue;
|
|
1535
|
-
|
|
1536
|
-
|
|
1552
|
+
// v2.80: scan ALL quoted tokens (was: only the first), prefer ones
|
|
1553
|
+
// that look like a hook path. Fixes a footgun where a wrapper command
|
|
1554
|
+
// like `bash -c "some inline" "/real/path.sh"` would pick "some inline"
|
|
1555
|
+
// and flag a false orphan. If no quoted token looks like a path, fall
|
|
1556
|
+
// through to the unquoted scanner; if that also misses, skip the
|
|
1557
|
+
// entry — we'd rather under-report than false-flag.
|
|
1558
|
+
let path = null;
|
|
1559
|
+
for (const m of cmd.matchAll(/"([^"]+)"/g)) {
|
|
1560
|
+
if (looksLikeHookPath(m[1])) { path = m[1]; break; }
|
|
1561
|
+
}
|
|
1537
1562
|
if (!path) {
|
|
1538
|
-
// unquoted: split on whitespace, take the first arg that looks like an absolute path
|
|
1539
1563
|
const parts = cmd.split(/\s+/);
|
|
1540
|
-
path = parts.find(p =>
|
|
1564
|
+
path = parts.find(p => looksLikeHookPath(p)) || null;
|
|
1541
1565
|
}
|
|
1542
1566
|
if (!path) continue;
|
|
1543
1567
|
if (!existsSync(path) && !out.includes(path)) out.push(path);
|
package/lib/citation-tracker.mjs
CHANGED
|
@@ -283,8 +283,17 @@ export function hasMainThreadAssistantText(transcriptPath) {
|
|
|
283
283
|
if (!transcriptPath || !existsSync(transcriptPath)) return false;
|
|
284
284
|
let raw;
|
|
285
285
|
try { raw = readFileSync(transcriptPath, 'utf8'); } catch { return false; }
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
// Reverse-iterate so a turn that just produced text returns true on the
|
|
287
|
+
// FIRST line examined instead of walking the entire transcript. Common case
|
|
288
|
+
// (model wrote a paragraph → Stop fires) short-circuits in O(1) line parses;
|
|
289
|
+
// pathological case (no text anywhere) still walks all entries but that's
|
|
290
|
+
// the degenerate state we want false for anyway. v2.80 perf polish — the
|
|
291
|
+
// pre-v2.80 forward scan held the full transcript in memory and walked
|
|
292
|
+
// every line on the common case too.
|
|
293
|
+
const lines = raw.split('\n');
|
|
294
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
295
|
+
const line = lines[i];
|
|
296
|
+
if (!line || !line.trim()) continue;
|
|
288
297
|
let entry;
|
|
289
298
|
try { entry = JSON.parse(line); } catch { continue; }
|
|
290
299
|
if (entry.type !== 'assistant' || !entry.message) continue;
|
package/package.json
CHANGED
package/scripts/setup.sh
CHANGED
|
@@ -85,7 +85,7 @@ mark_deps_broken() {
|
|
|
85
85
|
# Embed reason + repair command so hook.mjs renders a complete error without
|
|
86
86
|
# having to re-derive them. Delegate JSON serialization to node so embedded
|
|
87
87
|
# quotes / shell metachars in $ROOT or $reason can't produce an invalid file
|
|
88
|
-
# (bash `printf '"..%s.."'` cannot escape arbitrary strings safely; v2.79 fix).
|
|
88
|
+
# (bash `printf '"..%s.."'` cannot escape arbitrary strings safely; v2.79.1 fix).
|
|
89
89
|
MARK_REASON="$reason" MARK_ROOT="$ROOT" MARK_FLAG="$DEPS_FLAG" node -e '
|
|
90
90
|
const fs = require("fs");
|
|
91
91
|
const reason = process.env.MARK_REASON || "unknown";
|