claude-mem-lite 3.61.0 → 3.61.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/cli/common.mjs +5 -0
- package/mem-cli.mjs +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/scripts/user-prompt-search.js +1 -1
- package/secret-scrub.mjs +39 -10
- package/server.mjs +4 -1
- package/tool-schemas.mjs +6 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"plugins": [
|
|
11
11
|
{
|
|
12
12
|
"name": "claude-mem-lite",
|
|
13
|
-
"version": "3.61.
|
|
13
|
+
"version": "3.61.1",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark)."
|
|
16
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "3.61.
|
|
3
|
+
"version": "3.61.1",
|
|
4
4
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "sdsrss"
|
package/cli/common.mjs
CHANGED
|
@@ -176,6 +176,11 @@ export const KNOWN_CLI_FLAGS = new Set([
|
|
|
176
176
|
// stay silent about (`adopt --disable/--enable`, `activity --min-importance`,
|
|
177
177
|
// `save --supersedes`). Verified by running each command and checking for a warning.
|
|
178
178
|
'disable', 'enable', 'min-importance', 'supersedes',
|
|
179
|
+
// `doctor --benchmark --prompts-limit N` — read off raw argv in cli/doctor.mjs, so
|
|
180
|
+
// it never appeared in a `flags.x` grep. Caught by independent review after the
|
|
181
|
+
// warn-on-every-unknown-flag flip turned the omission into a false warning on a
|
|
182
|
+
// documented, working command.
|
|
183
|
+
'prompts-limit',
|
|
179
184
|
]);
|
|
180
185
|
|
|
181
186
|
/** Levenshtein distance, early-exit past `max` (cheap enough for a handful of flags). */
|
package/mem-cli.mjs
CHANGED
|
@@ -3194,7 +3194,7 @@ export async function run(argv) {
|
|
|
3194
3194
|
for (const { flag, suggestion } of suggestUnknownFlags(parseArgs(cmdArgs).flags)) {
|
|
3195
3195
|
process.stderr.write(suggestion
|
|
3196
3196
|
? `[mem] Unknown flag --${flag}; did you mean --${suggestion}?\n`
|
|
3197
|
-
: `[mem] Unknown flag --${flag} — ignored
|
|
3197
|
+
: `[mem] Unknown flag --${flag} — ignored, it had no effect. Run "claude-mem-lite help" for this command's flags.\n`);
|
|
3198
3198
|
}
|
|
3199
3199
|
|
|
3200
3200
|
// adopt / unadopt do pure filesystem work on ~/.claude/projects/<encoded>/memory/ —
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "3.61.
|
|
3
|
+
"version": "3.61.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "claude-mem-lite",
|
|
9
|
-
"version": "3.61.
|
|
9
|
+
"version": "3.61.1",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
12
12
|
"better-sqlite3": "^12.6.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-mem-lite",
|
|
3
|
-
"version": "3.61.
|
|
3
|
+
"version": "3.61.1",
|
|
4
4
|
"description": "Persistent long-term memory for Claude Code via MCP — captures coding decisions, bugfixes, and context across sessions. Hybrid FTS5 + TF-IDF search with episode batching. Single SQLite DB, no external services. A lighter, lower-cost alternative to claude-mem (episode batching + a smaller model; cost savings are an internal estimate, not a measured benchmark).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -114,7 +114,7 @@ const OR_TOP_BM25_FLOOR = TOP_REL_FLOOR === 0
|
|
|
114
114
|
? 0
|
|
115
115
|
: Number(process.env.CLAUDE_MEM_UPS_OR_BM25_MIN || 30);
|
|
116
116
|
|
|
117
|
-
// ─── Corpus-size normalization of the absolute floors (v3.
|
|
117
|
+
// ─── Corpus-size normalization of the absolute floors (v3.61.0) ─────────────
|
|
118
118
|
//
|
|
119
119
|
// Both floors above are ABSOLUTE magnitudes, but the quantity they gate is not
|
|
120
120
|
// scale-free: FTS5 bm25 carries an IDF term ≈ ln(N/df), so the SAME hit scores
|
package/secret-scrub.mjs
CHANGED
|
@@ -30,16 +30,45 @@ export const SECRET_PATTERNS = [
|
|
|
30
30
|
// value is covered (the hex-only assignment pattern below misses non-hex values).
|
|
31
31
|
// 1a. `=` assignment → ALWAYS scrub (config syntax, never prose):
|
|
32
32
|
[/((?:\b|_)(?:password|passwd|passphrase|token|bearer|secret)\s*=\s*)(?!process\.env\.)(?!new\s)(?!\w+\()(?!(?:null|undefined|true|false|None|nil|empty|""|''|0)\b)[^\s,;'"}\]]{6,}/gi, '$1***'],
|
|
33
|
-
// 1b. `:` separator, PASSWORD nouns
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
// "<word> password:
|
|
41
|
-
//
|
|
42
|
-
|
|
33
|
+
// 1b. `:` separator, PASSWORD nouns. Position decides how permissive the value
|
|
34
|
+
// class may be, because the two positions have opposite error costs.
|
|
35
|
+
//
|
|
36
|
+
// CONFIG position (start of line, or not preceded by an English word +
|
|
37
|
+
// space) is unambiguous assignment syntax → scrub any value, exactly as
|
|
38
|
+
// before. Pinned by the ` password: hunter2` indent cases.
|
|
39
|
+
//
|
|
40
|
+
// PROSE position ("<word> password: …") is where v3.61.0 first removed the
|
|
41
|
+
// lookbehind outright, to stop "deployed to staging, the db password:
|
|
42
|
+
// hunter2correct" from persisting a credential. That closed a leak by
|
|
43
|
+
// trading it for something worse: scrubbing runs on the WRITE path, and the
|
|
44
|
+
// value class matches ordinary English, so "Reset the password: instructions
|
|
45
|
+
// are in the onboarding doc" was stored irreversibly as "password: *** are
|
|
46
|
+
// in the onboarding doc" (caught by independent pre-tag review). The claim
|
|
47
|
+
// that "<word> password: <6+ chars>" always names a credential was simply
|
|
48
|
+
// false. So in prose position the VALUE must look like a credential: not a
|
|
49
|
+
// run of lowercase letters. A digit, any uppercase, or a symbol qualifies —
|
|
50
|
+
// `hunter2correct`, `S3cretValue`, `correct-horse-battery-staple` all scrub,
|
|
51
|
+
// while `instructions` / `rotation` / `yesterday` are left alone.
|
|
52
|
+
//
|
|
53
|
+
// "Credential-shaped" is spelled as: NOT a single run of ≤15 letters. The
|
|
54
|
+
// patterns carry `i`, so the letter class is case-insensitive by
|
|
55
|
+
// construction — deliberately, because prose capitalizes ("Reset the
|
|
56
|
+
// password: Instructions are in the doc" must survive, and a
|
|
57
|
+
// lowercase-only test would corrupt it). The length bound is what still
|
|
58
|
+
// catches a letters-only secret: English words in prose run short, secrets
|
|
59
|
+
// do not, so `aVeryLongOpaqueSecretToken` (26) scrubs while `instructions`
|
|
60
|
+
// (12) does not.
|
|
61
|
+
//
|
|
62
|
+
// Two known, accepted gaps: a short letters-only password in prose position
|
|
63
|
+
// ("the password: hunter") survives, and an English word longer than 15
|
|
64
|
+
// letters is over-scrubbed. Config position still catches the former; the
|
|
65
|
+
// latter is rare in prose and errs toward protecting a secret. A value
|
|
66
|
+
// indistinguishable from an English word cannot be told from one without
|
|
67
|
+
// corrupting prose — which is exactly the error this arm exists to undo.
|
|
68
|
+
// Both arms emit `***` (3 chars, under the {6,} floor), so they cannot
|
|
69
|
+
// double-apply.
|
|
70
|
+
[/((?<![A-Za-z][ \t])(?:\b|_)(?:password|passwd|passphrase)\s*:\s*)(?!process\.env\.)(?!new\s)(?!\w+\()(?!(?:null|undefined|true|false|None|nil|empty|""|''|0)\b)[^\s,;'"}\]]{6,}/gi, '$1***'],
|
|
71
|
+
[/((?:\b|_)(?:password|passwd|passphrase)\s*:\s*)(?!process\.env\.)(?!new\s)(?!\w+\()(?!(?:null|undefined|true|false|None|nil|empty|""|''|0)\b)(?![A-Za-z]{1,15}(?=[\s,;'"}\]]|$))[^\s,;'"}\]]{6,}/gi, '$1***'],
|
|
43
72
|
// 1c. `:` separator, prose-ambiguous nouns → keep the lookbehind ("the token: alice"):
|
|
44
73
|
[/((?<![A-Za-z][ \t])(?:\b|_)(?:token|bearer|secret)\s*:\s*)(?!process\.env\.)(?!new\s)(?!\w+\()(?!(?:null|undefined|true|false|None|nil|empty|""|''|0)\b)[^\s,;'"}\]]{6,}/gi, '$1***'],
|
|
45
74
|
// access_token / refresh_token are the canonical OAuth2 field names — they were
|
package/server.mjs
CHANGED
|
@@ -1745,7 +1745,10 @@ server.registerTool(
|
|
|
1745
1745
|
},
|
|
1746
1746
|
// verbatim: the export payload feeds `restore` — defanging it would silently
|
|
1747
1747
|
// rewrite backed-up rows whose text legitimately contains these tags.
|
|
1748
|
-
safeHandler(
|
|
1748
|
+
safeHandler(
|
|
1749
|
+
async (args) => runExport(db, applyArgAliases(args, { from: 'date_from', to: 'date_to' })),
|
|
1750
|
+
{ verbatim: true },
|
|
1751
|
+
)
|
|
1749
1752
|
);
|
|
1750
1753
|
|
|
1751
1754
|
// ─── Tool: mem_recall ────────────────────────────────────────────────────────
|
package/tool-schemas.mjs
CHANGED
|
@@ -100,7 +100,7 @@ export const memSearchSchema = {
|
|
|
100
100
|
or: coerceBool.optional().describe('Force OR semantics between query terms from the start (default: AND with automatic OR-fallback when AND returns 0). Aligns with CLI --or.'),
|
|
101
101
|
deep: coerceBool.optional().describe('Tri-state LLM multi-query/HyDE deep search (observations-only). true=force; false=never; omit=AUTO (default ON for mem_search): a normal search that returns weak/few results auto-escalates with ONE Haiku call (query rewritten to keyword/concept/HyDE variants, RRF-fused). Set CLAUDE_MEM_AUTO_DEEP=0 to disable AUTO. Passive recall stays single-query.'),
|
|
102
102
|
rerank: coerceBool.optional().describe('Opt-in: LLM-rerank the deep-search candidates for ranking precision (one extra Haiku call, ~1.4s). Requires deep=true (no effect on AUTO/normal). Reserve for hard, ranking-sensitive queries where the right memory is likely retrieved but mis-ranked — skip for routine search. Default off.'),
|
|
103
|
-
// ── CLI-flag aliases (v3.
|
|
103
|
+
// ── CLI-flag aliases (v3.61.0) ──────────────────────────────────────────────
|
|
104
104
|
// A property the schema doesn't declare is STRIPPED by the validator, so a caller
|
|
105
105
|
// using the CLI vocabulary (`--source` / `--from` / `--to` / `--since`) previously
|
|
106
106
|
// got the UNFILTERED answer with nothing marking the filter as dropped — a wider
|
|
@@ -274,6 +274,11 @@ export const memExportSchema = {
|
|
|
274
274
|
format: z.enum(['json', 'jsonl']).optional().describe('Output format (default: json)'),
|
|
275
275
|
date_from: z.string().optional().describe('Start date (ISO 8601 or YYYY-MM-DD)'),
|
|
276
276
|
date_to: z.string().optional().describe('End date (ISO 8601 or YYYY-MM-DD)'),
|
|
277
|
+
// CLI-flag aliases — `export` reads flags.from / flags.to (mem-cli.mjs). Same
|
|
278
|
+
// silent-drop defect the search/recent aliases fix, and the widest blast radius of
|
|
279
|
+
// the three: an ignored bound exports the whole DB instead of a date slice.
|
|
280
|
+
from: z.string().optional().describe('Alias for `date_from` (CLI `export --from`)'),
|
|
281
|
+
to: z.string().optional().describe('Alias for `date_to` (CLI `export --to`)'),
|
|
277
282
|
include_compressed: coerceBool.optional().describe('Include compressed observations (default: false)'),
|
|
278
283
|
limit: coerceInt.pipe(z.number().int().min(1).max(1000)).optional().describe('Max observations to export (default: 200, max: 1000)'),
|
|
279
284
|
};
|