claude-recall 0.21.0 → 0.21.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.
|
@@ -8,14 +8,14 @@ source: claude-recall
|
|
|
8
8
|
|
|
9
9
|
# Preferences
|
|
10
10
|
|
|
11
|
-
Auto-generated from 5 memories. Last updated: 2026-04-
|
|
11
|
+
Auto-generated from 5 memories. Last updated: 2026-04-11.
|
|
12
12
|
|
|
13
13
|
## Rules
|
|
14
14
|
|
|
15
|
-
- Session test preference
|
|
16
|
-
- Test preference
|
|
17
|
-
- Test preference
|
|
18
|
-
- Test preference
|
|
15
|
+
- Session test preference 1775896807164
|
|
16
|
+
- Test preference 1775896807117-2
|
|
17
|
+
- Test preference 1775896807117-1
|
|
18
|
+
- Test preference 1775896807117-0
|
|
19
19
|
- Test memory content
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"topicId": "preferences",
|
|
3
|
-
"sourceHash": "
|
|
3
|
+
"sourceHash": "47589a75902fabe04a4aab7d8c89e3cdd26c4c1cf7b6e3086a7ea3186413abe4",
|
|
4
4
|
"memoryCount": 5,
|
|
5
|
-
"generatedAt": "2026-04-
|
|
5
|
+
"generatedAt": "2026-04-11T08:40:07.182Z",
|
|
6
6
|
"memoryKeys": [
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
7
|
+
"memory_1775896807165_8gx2muuz6",
|
|
8
|
+
"memory_1775896807142_2zmd3oc2x",
|
|
9
|
+
"memory_1775896807130_nsc3d9wky",
|
|
10
|
+
"memory_1775896807118_3qvm34ozn",
|
|
11
|
+
"memory_1775896807081_saak1fkqp"
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -1,10 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MemoryTools = void 0;
|
|
4
|
+
exports.formatRuleValue = formatRuleValue;
|
|
4
5
|
const config_1 = require("../../services/config");
|
|
5
6
|
const search_monitor_1 = require("../../services/search-monitor");
|
|
6
7
|
const skill_generator_1 = require("../../services/skill-generator");
|
|
7
8
|
const outcome_storage_1 = require("../../services/outcome-storage");
|
|
9
|
+
/**
|
|
10
|
+
* Render any memory.value shape as a readable string for load_rules output.
|
|
11
|
+
*
|
|
12
|
+
* Memory values land in the DB in several historical shapes. The previous
|
|
13
|
+
* rendering used `m.value.content || m.value.value || JSON.stringify(m.value)`
|
|
14
|
+
* which short-circuited on truthy non-string objects, producing "[object Object]"
|
|
15
|
+
* when string interpolation eventually called toString() on the returned object.
|
|
16
|
+
*
|
|
17
|
+
* Rules:
|
|
18
|
+
* 1. strings/numbers pass through (or coerce)
|
|
19
|
+
* 2. null/undefined → empty string
|
|
20
|
+
* 3. objects: prefer the first STRING field in order: content, value, title, description
|
|
21
|
+
* (only string — non-string `content` falls through to title)
|
|
22
|
+
* 4. nested failure shapes: extract `what_failed` (top-level or under `content`)
|
|
23
|
+
* 5. last resort: truncated JSON.stringify (never raw object)
|
|
24
|
+
*
|
|
25
|
+
* Exported for direct unit testing in tests/unit/format-rule-value.test.ts.
|
|
26
|
+
*/
|
|
27
|
+
function formatRuleValue(value) {
|
|
28
|
+
if (value == null)
|
|
29
|
+
return '';
|
|
30
|
+
if (typeof value === 'string')
|
|
31
|
+
return value;
|
|
32
|
+
if (typeof value !== 'object')
|
|
33
|
+
return String(value);
|
|
34
|
+
const v = value;
|
|
35
|
+
// Prefer the first non-empty string field. Order matters:
|
|
36
|
+
// - `content` covers legacy hook failures and promoted lessons (lesson text)
|
|
37
|
+
// - `value` covers preference shape
|
|
38
|
+
// - `title` covers tool-outcome-watcher failures whose `content` is a nested object
|
|
39
|
+
// - `description` is a last-ditch human label
|
|
40
|
+
for (const field of ['content', 'value', 'title', 'description']) {
|
|
41
|
+
const candidate = v[field];
|
|
42
|
+
if (typeof candidate === 'string' && candidate.trim()) {
|
|
43
|
+
return candidate;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Nested failure object — extract what_failed if present
|
|
47
|
+
if (typeof v.what_failed === 'string' && v.what_failed.trim()) {
|
|
48
|
+
return v.what_failed;
|
|
49
|
+
}
|
|
50
|
+
if (v.content && typeof v.content === 'object') {
|
|
51
|
+
const inner = v.content;
|
|
52
|
+
if (typeof inner.what_failed === 'string' && inner.what_failed.trim()) {
|
|
53
|
+
return inner.what_failed;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Last resort: truncated JSON. Never return a raw object.
|
|
57
|
+
try {
|
|
58
|
+
const json = JSON.stringify(value);
|
|
59
|
+
return json.length > 200 ? json.substring(0, 200) + '…' : json;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return String(value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
8
65
|
class MemoryTools {
|
|
9
66
|
constructor(memoryService, logger, onMemoryChanged) {
|
|
10
67
|
this.memoryService = memoryService;
|
|
@@ -287,7 +344,7 @@ class MemoryTools {
|
|
|
287
344
|
const sections = [];
|
|
288
345
|
if (rules.preferences.length > 0) {
|
|
289
346
|
sections.push('## Preferences\n' + rules.preferences.map(m => {
|
|
290
|
-
const val =
|
|
347
|
+
const val = formatRuleValue(m.value);
|
|
291
348
|
// Only show key prefix if it's a meaningful name (not auto-generated)
|
|
292
349
|
const key = m.preference_key || m.key || '';
|
|
293
350
|
const isAutoKey = key.startsWith('memory_') || key.startsWith('auto_') || key.startsWith('pref_');
|
|
@@ -296,7 +353,7 @@ class MemoryTools {
|
|
|
296
353
|
}
|
|
297
354
|
if (rules.corrections.length > 0) {
|
|
298
355
|
sections.push('## Corrections\n' + rules.corrections.map(m => {
|
|
299
|
-
const val =
|
|
356
|
+
const val = formatRuleValue(m.value);
|
|
300
357
|
const isPromoted = m.key.startsWith('promoted_') || m.value?.source === 'promotion-engine';
|
|
301
358
|
const evidence = isPromoted && m.value?.evidence_count ? ` (learned from ${m.value.evidence_count} observations)` : '';
|
|
302
359
|
return isPromoted ? `- [promoted lesson] ${val}${evidence}` : `- ${val}`;
|
|
@@ -308,21 +365,21 @@ class MemoryTools {
|
|
|
308
365
|
const regularFailures = rules.failures.filter(m => !m.key.startsWith('promoted_') && m.value?.source !== 'promotion-engine');
|
|
309
366
|
if (promotedLessons.length > 0) {
|
|
310
367
|
sections.push('## Promoted Lessons (learned from repeated outcomes)\n' + promotedLessons.map(m => {
|
|
311
|
-
const val =
|
|
368
|
+
const val = formatRuleValue(m.value);
|
|
312
369
|
const evidence = m.value?.evidence_count ? ` (seen ${m.value.evidence_count}x)` : '';
|
|
313
370
|
return `- ${val}${evidence}`;
|
|
314
371
|
}).join('\n'));
|
|
315
372
|
}
|
|
316
373
|
if (regularFailures.length > 0) {
|
|
317
374
|
sections.push('## Failures\n' + regularFailures.map(m => {
|
|
318
|
-
const val =
|
|
375
|
+
const val = formatRuleValue(m.value);
|
|
319
376
|
return `- ${val}`;
|
|
320
377
|
}).join('\n'));
|
|
321
378
|
}
|
|
322
379
|
}
|
|
323
380
|
if (rules.devops.length > 0) {
|
|
324
381
|
sections.push('## DevOps Rules\n' + rules.devops.map(m => {
|
|
325
|
-
const val =
|
|
382
|
+
const val = formatRuleValue(m.value);
|
|
326
383
|
return `- ${val}`;
|
|
327
384
|
}).join('\n'));
|
|
328
385
|
}
|
package/package.json
CHANGED