claude-mem-lite 2.34.4 → 2.34.5
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/package.json
CHANGED
|
@@ -163,6 +163,43 @@ function searchByFile(db, files, project, limit) {
|
|
|
163
163
|
});
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
// v2.34.5 Gap 1: prompts-table fallback. When observations-based paths
|
|
167
|
+
// (FTS / file-recall / sigRows / recent) all return empty, scan the user's
|
|
168
|
+
// own past prompts — meta/UX/"did we discuss this" questions often match
|
|
169
|
+
// prior prompts even when no observation was saved. Uses a simpler BM25
|
|
170
|
+
// ranking with no scoring multipliers and no top-|rel| gate (prompts are
|
|
171
|
+
// sparser and more surface-form than observations; the gate would rarely
|
|
172
|
+
// fire and mostly kill real hits).
|
|
173
|
+
function searchByUserPrompts(db, queryText, project, limit) {
|
|
174
|
+
const ftsQuery = sanitizeFtsQuery(queryText);
|
|
175
|
+
if (!ftsQuery) return [];
|
|
176
|
+
|
|
177
|
+
const cutoff = Date.now() - LOOKBACK_MS;
|
|
178
|
+
const sql = `
|
|
179
|
+
SELECT up.id, up.prompt_text, up.created_at_epoch,
|
|
180
|
+
bm25(user_prompts_fts) as relevance
|
|
181
|
+
FROM user_prompts_fts
|
|
182
|
+
JOIN user_prompts up ON up.id = user_prompts_fts.rowid
|
|
183
|
+
JOIN sdk_sessions s ON s.content_session_id = up.content_session_id
|
|
184
|
+
WHERE user_prompts_fts MATCH ?
|
|
185
|
+
AND s.project = ?
|
|
186
|
+
AND up.created_at_epoch > ?
|
|
187
|
+
ORDER BY relevance
|
|
188
|
+
LIMIT ?
|
|
189
|
+
`;
|
|
190
|
+
|
|
191
|
+
let rows = db.prepare(sql).all(ftsQuery, project, cutoff, limit);
|
|
192
|
+
|
|
193
|
+
if (rows.length === 0) {
|
|
194
|
+
const orQuery = relaxFtsQueryToOr(ftsQuery);
|
|
195
|
+
if (orQuery) {
|
|
196
|
+
try { rows = db.prepare(sql).all(orQuery, project, cutoff, limit); } catch {}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return rows;
|
|
201
|
+
}
|
|
202
|
+
|
|
166
203
|
function searchRecent(db, project, limit) {
|
|
167
204
|
const cutoff = Date.now() - LOOKBACK_MS;
|
|
168
205
|
// R1: exclude LOW_SIGNAL degraded titles from "recent" recall intent
|
|
@@ -225,6 +262,20 @@ function formatResults(rows) {
|
|
|
225
262
|
return lines.join('\n');
|
|
226
263
|
}
|
|
227
264
|
|
|
265
|
+
// v2.34.5 Gap 1: distinct header signals to Claude that these are prior
|
|
266
|
+
// *user questions*, not codebase lessons — helps the reader interpret the
|
|
267
|
+
// row correctly (surface-form match, not a saved insight). Truncate to 80
|
|
268
|
+
// chars (slightly longer than obs titles because prompts carry more context).
|
|
269
|
+
function formatPromptResults(rows) {
|
|
270
|
+
if (!rows || rows.length === 0) return null;
|
|
271
|
+
const lines = ['[mem] Past similar questions:'];
|
|
272
|
+
for (const r of rows) {
|
|
273
|
+
const text = truncate((r.prompt_text || '').replace(/\s+/g, ' '), 80);
|
|
274
|
+
lines.push(`P#${r.id} 💬 ${text}`);
|
|
275
|
+
}
|
|
276
|
+
return lines.join('\n');
|
|
277
|
+
}
|
|
278
|
+
|
|
228
279
|
// ─── Registry Skill Pointer (T4 v2.31) ─────────────────────────────────────
|
|
229
280
|
// Formerly "auto-load": we used to read the full SKILL.md body (up to 16KB)
|
|
230
281
|
// and inject it into stdout on keyword match. Now we only emit a short
|
|
@@ -376,10 +427,24 @@ async function main() {
|
|
|
376
427
|
rows = [...sigRows, ...rows.filter(r => !sigIds.has(r.id))].slice(0, MAX_RESULTS);
|
|
377
428
|
}
|
|
378
429
|
|
|
379
|
-
|
|
430
|
+
// v2.34.5 Gap 1: if observations-based search drew a blank, try the
|
|
431
|
+
// user_prompts corpus. Only fires when `rows` is empty (obs hits
|
|
432
|
+
// suppress the fallback to avoid noise). Namespace prompt IDs with
|
|
433
|
+
// a "P" prefix so shouldSkipByDedup's Set comparison doesn't collide
|
|
434
|
+
// with future observation IDs.
|
|
435
|
+
let promptRows = [];
|
|
436
|
+
if (rows.length === 0) {
|
|
437
|
+
promptRows = searchByUserPrompts(db, promptText, project, 3);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const candidateIds = rows.length > 0
|
|
441
|
+
? rows.map(r => r.id)
|
|
442
|
+
: promptRows.map(r => `P${r.id}`);
|
|
380
443
|
const dedupSkip = shouldSkipByDedup(candidateIds, INJECTED_IDS_FILE);
|
|
381
444
|
|
|
382
|
-
const output = !dedupSkip
|
|
445
|
+
const output = !dedupSkip
|
|
446
|
+
? (rows.length > 0 ? formatResults(rows) : formatPromptResults(promptRows))
|
|
447
|
+
: null;
|
|
383
448
|
if (output) {
|
|
384
449
|
process.stdout.write(output + '\n');
|
|
385
450
|
// Write injected IDs for dedup with hook.mjs handleUserPrompt + self-dedup
|