audrey 0.16.1 → 0.20.0

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.
Files changed (188) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +146 -724
  3. package/dist/mcp-server/config.d.ts +20 -0
  4. package/dist/mcp-server/config.d.ts.map +1 -0
  5. package/dist/mcp-server/config.js +125 -0
  6. package/dist/mcp-server/config.js.map +1 -0
  7. package/dist/mcp-server/index.d.ts +100 -0
  8. package/dist/mcp-server/index.d.ts.map +1 -0
  9. package/dist/mcp-server/index.js +1113 -0
  10. package/dist/mcp-server/index.js.map +1 -0
  11. package/dist/src/adaptive.d.ts +7 -0
  12. package/dist/src/adaptive.d.ts.map +1 -0
  13. package/dist/src/adaptive.js +49 -0
  14. package/dist/src/adaptive.js.map +1 -0
  15. package/dist/src/affect.d.ts +19 -0
  16. package/dist/src/affect.d.ts.map +1 -0
  17. package/dist/src/affect.js +72 -0
  18. package/dist/src/affect.js.map +1 -0
  19. package/dist/src/audrey.d.ts +140 -0
  20. package/dist/src/audrey.d.ts.map +1 -0
  21. package/dist/src/audrey.js +564 -0
  22. package/dist/src/audrey.js.map +1 -0
  23. package/dist/src/capsule.d.ts +68 -0
  24. package/dist/src/capsule.d.ts.map +1 -0
  25. package/dist/src/capsule.js +311 -0
  26. package/dist/src/capsule.js.map +1 -0
  27. package/dist/src/causal.d.ts +28 -0
  28. package/dist/src/causal.d.ts.map +1 -0
  29. package/dist/src/causal.js +65 -0
  30. package/dist/src/causal.js.map +1 -0
  31. package/dist/src/confidence.d.ts +12 -0
  32. package/dist/src/confidence.d.ts.map +1 -0
  33. package/dist/src/confidence.js +63 -0
  34. package/dist/src/confidence.js.map +1 -0
  35. package/dist/src/consolidate.d.ts +8 -0
  36. package/dist/src/consolidate.d.ts.map +1 -0
  37. package/dist/src/consolidate.js +218 -0
  38. package/dist/src/consolidate.js.map +1 -0
  39. package/dist/src/context.d.ts +3 -0
  40. package/dist/src/context.d.ts.map +1 -0
  41. package/dist/src/context.js +19 -0
  42. package/dist/src/context.js.map +1 -0
  43. package/dist/src/db.d.ts +12 -0
  44. package/dist/src/db.d.ts.map +1 -0
  45. package/dist/src/db.js +380 -0
  46. package/dist/src/db.js.map +1 -0
  47. package/dist/src/decay.d.ts +7 -0
  48. package/dist/src/decay.d.ts.map +1 -0
  49. package/dist/src/decay.js +68 -0
  50. package/dist/src/decay.js.map +1 -0
  51. package/dist/src/embedding.d.ts +57 -0
  52. package/dist/src/embedding.d.ts.map +1 -0
  53. package/dist/src/embedding.js +254 -0
  54. package/dist/src/embedding.js.map +1 -0
  55. package/dist/src/encode.d.ts +15 -0
  56. package/dist/src/encode.d.ts.map +1 -0
  57. package/dist/src/encode.js +36 -0
  58. package/dist/src/encode.js.map +1 -0
  59. package/dist/src/events.d.ts +69 -0
  60. package/dist/src/events.d.ts.map +1 -0
  61. package/dist/src/events.js +149 -0
  62. package/dist/src/events.js.map +1 -0
  63. package/dist/src/export.d.ts +3 -0
  64. package/dist/src/export.d.ts.map +1 -0
  65. package/dist/src/export.js +46 -0
  66. package/dist/src/export.js.map +1 -0
  67. package/dist/src/forget.d.ts +11 -0
  68. package/dist/src/forget.d.ts.map +1 -0
  69. package/dist/src/forget.js +105 -0
  70. package/dist/src/forget.js.map +1 -0
  71. package/dist/src/fts.d.ts +34 -0
  72. package/dist/src/fts.d.ts.map +1 -0
  73. package/dist/src/fts.js +117 -0
  74. package/dist/src/fts.js.map +1 -0
  75. package/dist/src/hybrid-recall.d.ts +37 -0
  76. package/dist/src/hybrid-recall.d.ts.map +1 -0
  77. package/dist/src/hybrid-recall.js +213 -0
  78. package/dist/src/hybrid-recall.js.map +1 -0
  79. package/dist/src/import.d.ts +4 -0
  80. package/dist/src/import.d.ts.map +1 -0
  81. package/dist/src/import.js +127 -0
  82. package/dist/src/import.js.map +1 -0
  83. package/dist/src/index.d.ts +22 -0
  84. package/dist/src/index.d.ts.map +1 -0
  85. package/{src → dist/src}/index.js +5 -13
  86. package/dist/src/index.js.map +1 -0
  87. package/dist/src/interference.d.ts +13 -0
  88. package/dist/src/interference.d.ts.map +1 -0
  89. package/dist/src/interference.js +45 -0
  90. package/dist/src/interference.js.map +1 -0
  91. package/dist/src/introspect.d.ts +4 -0
  92. package/dist/src/introspect.d.ts.map +1 -0
  93. package/dist/src/introspect.js +40 -0
  94. package/dist/src/introspect.js.map +1 -0
  95. package/dist/src/llm.d.ts +38 -0
  96. package/dist/src/llm.d.ts.map +1 -0
  97. package/dist/src/llm.js +167 -0
  98. package/dist/src/llm.js.map +1 -0
  99. package/dist/src/migrate.d.ts +6 -0
  100. package/dist/src/migrate.d.ts.map +1 -0
  101. package/dist/src/migrate.js +51 -0
  102. package/dist/src/migrate.js.map +1 -0
  103. package/dist/src/promote.d.ts +40 -0
  104. package/dist/src/promote.d.ts.map +1 -0
  105. package/dist/src/promote.js +200 -0
  106. package/dist/src/promote.js.map +1 -0
  107. package/dist/src/prompts.d.ts +16 -0
  108. package/dist/src/prompts.d.ts.map +1 -0
  109. package/{src → dist/src}/prompts.js +172 -203
  110. package/dist/src/prompts.js.map +1 -0
  111. package/dist/src/recall.d.ts +9 -0
  112. package/dist/src/recall.d.ts.map +1 -0
  113. package/dist/src/recall.js +432 -0
  114. package/dist/src/recall.js.map +1 -0
  115. package/dist/src/redact.d.ts +27 -0
  116. package/dist/src/redact.d.ts.map +1 -0
  117. package/dist/src/redact.js +228 -0
  118. package/dist/src/redact.js.map +1 -0
  119. package/dist/src/rollback.d.ts +8 -0
  120. package/dist/src/rollback.d.ts.map +1 -0
  121. package/dist/src/rollback.js +33 -0
  122. package/dist/src/rollback.js.map +1 -0
  123. package/dist/src/routes.d.ts +7 -0
  124. package/dist/src/routes.d.ts.map +1 -0
  125. package/dist/src/routes.js +226 -0
  126. package/dist/src/routes.js.map +1 -0
  127. package/dist/src/rules-compiler.d.ts +20 -0
  128. package/dist/src/rules-compiler.d.ts.map +1 -0
  129. package/dist/src/rules-compiler.js +143 -0
  130. package/dist/src/rules-compiler.js.map +1 -0
  131. package/dist/src/server.d.ts +12 -0
  132. package/dist/src/server.d.ts.map +1 -0
  133. package/dist/src/server.js +22 -0
  134. package/dist/src/server.js.map +1 -0
  135. package/dist/src/tool-trace.d.ts +37 -0
  136. package/dist/src/tool-trace.d.ts.map +1 -0
  137. package/dist/src/tool-trace.js +142 -0
  138. package/dist/src/tool-trace.js.map +1 -0
  139. package/dist/src/types.d.ts +446 -0
  140. package/dist/src/types.d.ts.map +1 -0
  141. package/dist/src/types.js +6 -0
  142. package/dist/src/types.js.map +1 -0
  143. package/dist/src/ulid.d.ts +3 -0
  144. package/dist/src/ulid.d.ts.map +1 -0
  145. package/dist/src/ulid.js +11 -0
  146. package/dist/src/ulid.js.map +1 -0
  147. package/dist/src/utils.d.ts +10 -0
  148. package/dist/src/utils.d.ts.map +1 -0
  149. package/dist/src/utils.js +41 -0
  150. package/dist/src/utils.js.map +1 -0
  151. package/dist/src/validate.d.ts +22 -0
  152. package/dist/src/validate.d.ts.map +1 -0
  153. package/dist/src/validate.js +109 -0
  154. package/dist/src/validate.js.map +1 -0
  155. package/docs/assets/benchmarks/local-benchmark.svg +45 -0
  156. package/docs/assets/benchmarks/operations-benchmark.svg +45 -0
  157. package/docs/assets/benchmarks/published-memory-standards.svg +50 -0
  158. package/docs/benchmarking.md +151 -0
  159. package/docs/production-readiness.md +124 -0
  160. package/examples/fintech-ops-demo.js +67 -0
  161. package/examples/healthcare-ops-demo.js +67 -0
  162. package/examples/stripe-demo.js +105 -0
  163. package/package.json +53 -13
  164. package/mcp-server/config.js +0 -80
  165. package/mcp-server/index.js +0 -729
  166. package/src/adaptive.js +0 -53
  167. package/src/affect.js +0 -64
  168. package/src/audrey.js +0 -604
  169. package/src/causal.js +0 -95
  170. package/src/confidence.js +0 -120
  171. package/src/consolidate.js +0 -265
  172. package/src/context.js +0 -15
  173. package/src/db.js +0 -370
  174. package/src/decay.js +0 -84
  175. package/src/embedding.js +0 -256
  176. package/src/encode.js +0 -63
  177. package/src/export.js +0 -67
  178. package/src/forget.js +0 -111
  179. package/src/import.js +0 -245
  180. package/src/interference.js +0 -51
  181. package/src/introspect.js +0 -48
  182. package/src/llm.js +0 -246
  183. package/src/migrate.js +0 -58
  184. package/src/recall.js +0 -352
  185. package/src/rollback.js +0 -42
  186. package/src/ulid.js +0 -18
  187. package/src/utils.js +0 -38
  188. package/src/validate.js +0 -172
@@ -0,0 +1,109 @@
1
+ import { generateId } from './ulid.js';
2
+ import { safeJsonParse } from './utils.js';
3
+ import { buildContradictionDetectionPrompt } from './prompts.js';
4
+ const REINFORCEMENT_THRESHOLD = 0.85;
5
+ const CONTRADICTION_THRESHOLD = 0.60;
6
+ export async function validateMemory(db, embeddingProvider, episode, options = {}) {
7
+ const { threshold = REINFORCEMENT_THRESHOLD, contradictionThreshold = CONTRADICTION_THRESHOLD, llmProvider, } = options;
8
+ const episodeVector = await embeddingProvider.embed(episode.content);
9
+ const episodeBuffer = embeddingProvider.vectorToBuffer(episodeVector);
10
+ const nearestSemantic = db.prepare(`
11
+ SELECT s.*, (1.0 - v.distance) AS similarity
12
+ FROM vec_semantics v
13
+ JOIN semantics s ON s.id = v.id
14
+ WHERE v.embedding MATCH ?
15
+ AND k = 1
16
+ AND (v.state = 'active' OR v.state = 'context_dependent')
17
+ `).get(episodeBuffer);
18
+ let bestMatch = null;
19
+ let bestSimilarity = 0;
20
+ if (nearestSemantic) {
21
+ bestMatch = nearestSemantic;
22
+ bestSimilarity = nearestSemantic.similarity;
23
+ }
24
+ if (bestMatch && bestSimilarity >= threshold) {
25
+ const evidenceIds = safeJsonParse(bestMatch.evidence_episode_ids, []);
26
+ if (!evidenceIds.includes(episode.id)) {
27
+ evidenceIds.push(episode.id);
28
+ }
29
+ const diversity = computeSourceDiversity(db, evidenceIds, episode);
30
+ const now = new Date().toISOString();
31
+ db.prepare(`
32
+ UPDATE semantics SET
33
+ supporting_count = supporting_count + 1,
34
+ evidence_episode_ids = ?,
35
+ evidence_count = ?,
36
+ source_type_diversity = ?,
37
+ last_reinforced_at = ?
38
+ WHERE id = ?
39
+ `).run(JSON.stringify(evidenceIds), evidenceIds.length, diversity, now, bestMatch.id);
40
+ return {
41
+ action: 'reinforced',
42
+ semanticId: bestMatch.id,
43
+ similarity: bestSimilarity,
44
+ };
45
+ }
46
+ if (bestMatch && bestSimilarity >= contradictionThreshold && llmProvider) {
47
+ const messages = buildContradictionDetectionPrompt(episode.content, bestMatch.content);
48
+ const verdict = await llmProvider.json(messages);
49
+ if (verdict.contradicts) {
50
+ const resolution = verdict.resolution === 'context_dependent'
51
+ ? { type: 'context_dependent', conditions: verdict.conditions, explanation: verdict.explanation }
52
+ : verdict.resolution
53
+ ? { type: verdict.resolution, explanation: verdict.explanation }
54
+ : null;
55
+ const contradictionId = createContradiction(db, bestMatch.id, 'semantic', episode.id, 'episodic', resolution);
56
+ if (verdict.resolution === 'new_wins') {
57
+ db.prepare("UPDATE semantics SET state = 'disputed' WHERE id = ?").run(bestMatch.id);
58
+ }
59
+ else if (verdict.resolution === 'context_dependent' && verdict.conditions) {
60
+ db.prepare("UPDATE semantics SET state = 'context_dependent', conditions = ? WHERE id = ?")
61
+ .run(JSON.stringify(verdict.conditions), bestMatch.id);
62
+ }
63
+ return {
64
+ action: 'contradiction',
65
+ contradictionId,
66
+ semanticId: bestMatch.id,
67
+ similarity: bestSimilarity,
68
+ resolution: verdict.resolution || null,
69
+ };
70
+ }
71
+ }
72
+ return { action: 'none' };
73
+ }
74
+ function computeSourceDiversity(db, evidenceIds, currentEpisode) {
75
+ const sourceTypes = new Set();
76
+ sourceTypes.add(currentEpisode.source);
77
+ if (evidenceIds.length > 0) {
78
+ const placeholders = evidenceIds.map(() => '?').join(',');
79
+ const rows = db.prepare(`SELECT DISTINCT source FROM episodes WHERE id IN (${placeholders})`).all(...evidenceIds);
80
+ for (const row of rows) {
81
+ sourceTypes.add(row.source);
82
+ }
83
+ }
84
+ return sourceTypes.size;
85
+ }
86
+ export function createContradiction(db, claimAId, claimAType, claimBId, claimBType, resolution) {
87
+ const id = generateId();
88
+ const now = new Date().toISOString();
89
+ const state = resolution ? 'resolved' : 'open';
90
+ const resolvedAt = resolution ? now : null;
91
+ const resolutionJson = resolution ? JSON.stringify(resolution) : null;
92
+ db.prepare(`
93
+ INSERT INTO contradictions (id, claim_a_id, claim_a_type, claim_b_id, claim_b_type,
94
+ state, resolution, resolved_at, created_at)
95
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
96
+ `).run(id, claimAId, claimAType, claimBId, claimBType, state, resolutionJson, resolvedAt, now);
97
+ return id;
98
+ }
99
+ export function reopenContradiction(db, contradictionId, newEvidenceId) {
100
+ const now = new Date().toISOString();
101
+ db.prepare(`
102
+ UPDATE contradictions SET
103
+ state = 'reopened',
104
+ reopen_evidence_id = ?,
105
+ reopened_at = ?
106
+ WHERE id = ?
107
+ `).run(newEvidenceId, now, contradictionId);
108
+ }
109
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="960" height="420" viewBox="0 0 960 420" role="img" aria-label="Audrey vs Local Memory Baselines">
3
+ <rect width="100%" height="100%" fill="white" />
4
+ <text x="64" y="34" font-size="24" font-weight="700" fill="#111827">Audrey vs Local Memory Baselines</text>
5
+
6
+ <line x1="64" y1="332" x2="928" y2="332" stroke="#cbd5e1" stroke-dasharray="4 4" />
7
+ <text x="54" y="337" text-anchor="end" font-size="13" fill="#6b7280">0%</text>
8
+
9
+
10
+ <line x1="64" y1="263" x2="928" y2="263" stroke="#cbd5e1" stroke-dasharray="4 4" />
11
+ <text x="54" y="268" text-anchor="end" font-size="13" fill="#6b7280">25%</text>
12
+
13
+
14
+ <line x1="64" y1="194" x2="928" y2="194" stroke="#cbd5e1" stroke-dasharray="4 4" />
15
+ <text x="54" y="199" text-anchor="end" font-size="13" fill="#6b7280">50%</text>
16
+
17
+
18
+ <line x1="64" y1="125" x2="928" y2="125" stroke="#cbd5e1" stroke-dasharray="4 4" />
19
+ <text x="54" y="130" text-anchor="end" font-size="13" fill="#6b7280">75%</text>
20
+
21
+
22
+ <line x1="64" y1="56" x2="928" y2="56" stroke="#cbd5e1" stroke-dasharray="4 4" />
23
+ <text x="54" y="61" text-anchor="end" font-size="13" fill="#6b7280">100%</text>
24
+
25
+
26
+ <rect x="64" y="56" width="198" height="276" rx="8" fill="#0f766e" />
27
+ <text x="163" y="46" text-anchor="middle" font-size="15" fill="#111827">100.0%</text>
28
+ <text x="163" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Audrey</text>
29
+
30
+
31
+ <rect x="286" y="217" width="198" height="115.00000000000001" rx="8" fill="#0369a1" />
32
+ <text x="385" y="207" text-anchor="middle" font-size="15" fill="#111827">41.7%</text>
33
+ <text x="385" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Vector Only</text>
34
+
35
+
36
+ <rect x="508" y="217" width="198" height="115.00000000000001" rx="8" fill="#6d28d9" />
37
+ <text x="607" y="207" text-anchor="middle" font-size="15" fill="#111827">41.7%</text>
38
+ <text x="607" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Keyword + Recency</text>
39
+
40
+
41
+ <rect x="730" y="228.5" width="198" height="103.5" rx="8" fill="#b45309" />
42
+ <text x="829" y="218.5" text-anchor="middle" font-size="15" fill="#111827">37.5%</text>
43
+ <text x="829" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Recent Window</text>
44
+
45
+ </svg>
@@ -0,0 +1,45 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="960" height="420" viewBox="0 0 960 420" role="img" aria-label="Audrey Memory Operations Benchmark">
3
+ <rect width="100%" height="100%" fill="white" />
4
+ <text x="64" y="34" font-size="24" font-weight="700" fill="#111827">Audrey Memory Operations Benchmark</text>
5
+
6
+ <line x1="64" y1="332" x2="928" y2="332" stroke="#cbd5e1" stroke-dasharray="4 4" />
7
+ <text x="54" y="337" text-anchor="end" font-size="13" fill="#6b7280">0%</text>
8
+
9
+
10
+ <line x1="64" y1="263" x2="928" y2="263" stroke="#cbd5e1" stroke-dasharray="4 4" />
11
+ <text x="54" y="268" text-anchor="end" font-size="13" fill="#6b7280">25%</text>
12
+
13
+
14
+ <line x1="64" y1="194" x2="928" y2="194" stroke="#cbd5e1" stroke-dasharray="4 4" />
15
+ <text x="54" y="199" text-anchor="end" font-size="13" fill="#6b7280">50%</text>
16
+
17
+
18
+ <line x1="64" y1="125" x2="928" y2="125" stroke="#cbd5e1" stroke-dasharray="4 4" />
19
+ <text x="54" y="130" text-anchor="end" font-size="13" fill="#6b7280">75%</text>
20
+
21
+
22
+ <line x1="64" y1="56" x2="928" y2="56" stroke="#cbd5e1" stroke-dasharray="4 4" />
23
+ <text x="54" y="61" text-anchor="end" font-size="13" fill="#6b7280">100%</text>
24
+
25
+
26
+ <rect x="64" y="56" width="198" height="276" rx="8" fill="#0f766e" />
27
+ <text x="163" y="46" text-anchor="middle" font-size="15" fill="#111827">100.0%</text>
28
+ <text x="163" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Audrey</text>
29
+
30
+
31
+ <rect x="286" y="263" width="198" height="69" rx="8" fill="#6d28d9" />
32
+ <text x="385" y="253" text-anchor="middle" font-size="15" fill="#111827">25.0%</text>
33
+ <text x="385" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Keyword + Recency</text>
34
+
35
+
36
+ <rect x="508" y="297.5" width="198" height="34.5" rx="8" fill="#0369a1" />
37
+ <text x="607" y="287.5" text-anchor="middle" font-size="15" fill="#111827">12.5%</text>
38
+ <text x="607" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Vector Only</text>
39
+
40
+
41
+ <rect x="730" y="297.5" width="198" height="34.5" rx="8" fill="#b45309" />
42
+ <text x="829" y="287.5" text-anchor="middle" font-size="15" fill="#111827">12.5%</text>
43
+ <text x="829" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Recent Window</text>
44
+
45
+ </svg>
@@ -0,0 +1,50 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="960" height="420" viewBox="0 0 960 420" role="img" aria-label="Published LLM Memory Standards (LoCoMo)">
3
+ <rect width="100%" height="100%" fill="white" />
4
+ <text x="64" y="34" font-size="24" font-weight="700" fill="#111827">Published LLM Memory Standards (LoCoMo)</text>
5
+
6
+ <line x1="64" y1="332" x2="928" y2="332" stroke="#cbd5e1" stroke-dasharray="4 4" />
7
+ <text x="54" y="337" text-anchor="end" font-size="13" fill="#6b7280">0%</text>
8
+
9
+
10
+ <line x1="64" y1="263" x2="928" y2="263" stroke="#cbd5e1" stroke-dasharray="4 4" />
11
+ <text x="54" y="268" text-anchor="end" font-size="13" fill="#6b7280">25%</text>
12
+
13
+
14
+ <line x1="64" y1="194" x2="928" y2="194" stroke="#cbd5e1" stroke-dasharray="4 4" />
15
+ <text x="54" y="199" text-anchor="end" font-size="13" fill="#6b7280">50%</text>
16
+
17
+
18
+ <line x1="64" y1="125" x2="928" y2="125" stroke="#cbd5e1" stroke-dasharray="4 4" />
19
+ <text x="54" y="130" text-anchor="end" font-size="13" fill="#6b7280">75%</text>
20
+
21
+
22
+ <line x1="64" y1="56" x2="928" y2="56" stroke="#cbd5e1" stroke-dasharray="4 4" />
23
+ <text x="54" y="61" text-anchor="end" font-size="13" fill="#6b7280">100%</text>
24
+
25
+
26
+ <rect x="64" y="96.29599999999996" width="154" height="235.70400000000004" rx="8" fill="#1d4ed8" />
27
+ <text x="141" y="86.29599999999996" text-anchor="middle" font-size="15" fill="#111827">85.4%</text>
28
+ <text x="141" y="378" text-anchor="middle" font-size="14" fill="#6b7280">MIRIX</text>
29
+
30
+
31
+ <rect x="241.5" y="127.75999999999999" width="154" height="204.24" rx="8" fill="#1d4ed8" />
32
+ <text x="318.5" y="117.75999999999999" text-anchor="middle" font-size="15" fill="#111827">74.0%</text>
33
+ <text x="318.5" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Letta Filesystem</text>
34
+
35
+
36
+ <rect x="419" y="142.94" width="154" height="189.06" rx="8" fill="#1d4ed8" />
37
+ <text x="496" y="132.94" text-anchor="middle" font-size="15" fill="#111827">68.5%</text>
38
+ <text x="496" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Mem0 Graph Memory</text>
39
+
40
+
41
+ <rect x="596.5" y="147.356" width="154" height="184.644" rx="8" fill="#1d4ed8" />
42
+ <text x="673.5" y="137.356" text-anchor="middle" font-size="15" fill="#111827">66.9%</text>
43
+ <text x="673.5" y="378" text-anchor="middle" font-size="14" fill="#6b7280">Mem0</text>
44
+
45
+
46
+ <rect x="774" y="185.99599999999998" width="154" height="146.00400000000002" rx="8" fill="#1d4ed8" />
47
+ <text x="851" y="175.99599999999998" text-anchor="middle" font-size="15" fill="#111827">52.9%</text>
48
+ <text x="851" y="378" text-anchor="middle" font-size="14" fill="#6b7280">OpenAI Memory</text>
49
+
50
+ </svg>
@@ -0,0 +1,151 @@
1
+ # Benchmarking Audrey
2
+
3
+ Audrey now ships with a memory benchmark harness that does three different jobs:
4
+
5
+ 1. It runs Audrey against a local retrieval suite inspired by LongMemEval, plus privacy and abstention checks that matter in production.
6
+ 2. It runs Audrey against an operation-level suite for update, overwrite, delete, merge, and abstain behavior.
7
+ 3. It overlays published leaderboard numbers from leading memory systems on LoCoMo so you can place Audrey in the current market and research landscape without pretending the measurements are identical.
8
+
9
+ That split is deliberate. A lot of memory tooling mixes internal demos with external benchmark claims. Audrey should not do that.
10
+
11
+ ## Run It
12
+
13
+ ```bash
14
+ npm run bench:memory
15
+ ```
16
+
17
+ The package script is the intended operator entrypoint:
18
+
19
+ ```bash
20
+ npm run bench:memory
21
+ ```
22
+
23
+ Artifacts are written to `benchmarks/output/`:
24
+
25
+ - `summary.json`
26
+ - `report.html`
27
+ - `local-overall.svg`
28
+ - `retrieval-overall.svg`
29
+ - `operations-overall.svg`
30
+ - `published-locomo.svg`
31
+
32
+ For CI, JSON-only output is available:
33
+
34
+ ```bash
35
+ npm run bench:memory:json
36
+ ```
37
+
38
+ For regression gating, use:
39
+
40
+ ```bash
41
+ npm run bench:memory:check
42
+ ```
43
+
44
+ That command fails if Audrey falls below its minimum local score, pass rate, or required lead over the strongest naive baseline.
45
+
46
+ To refresh the committed SVGs used in the README:
47
+
48
+ ```bash
49
+ npm run bench:memory:readme-assets
50
+ ```
51
+
52
+ That writes stable chart assets to `docs/assets/benchmarks/` so the GitHub repo surface shows the same benchmark posture as the generated report.
53
+
54
+ To run a single local track:
55
+
56
+ ```bash
57
+ npm run bench:memory:retrieval
58
+ npm run bench:memory:operations
59
+ ```
60
+
61
+ ## What The Local Retrieval Benchmark Measures
62
+
63
+ The retrieval suite covers eight memory families:
64
+
65
+ - `information_extraction`
66
+ - `knowledge_updates`
67
+ - `multi_session_reasoning`
68
+ - `temporal_reasoning`
69
+ - `abstention`
70
+ - `conflict_resolution`
71
+ - `procedural_learning`
72
+ - `privacy_boundary`
73
+
74
+ This is intentionally closer to how operators evaluate memory in production than a single retrieval-accuracy number. Audrey should not only retrieve facts. It should:
75
+
76
+ - prefer fresh state over stale state
77
+ - avoid leaking private memory
78
+ - consolidate repeated episodes into reusable procedures
79
+ - handle conflict without amplifying low-reliability noise
80
+
81
+ ## What The Local Operations Benchmark Measures
82
+
83
+ The operations suite covers four lifecycle families:
84
+
85
+ - `update_overwrite`
86
+ - `delete_and_abstain`
87
+ - `semantic_merge`
88
+ - `procedural_merge`
89
+
90
+ This suite exists because leading memory systems are often compared on offline recall, while real agent memory succeeds or fails on memory operations:
91
+
92
+ - can a newer fact overwrite stale state without leaking both
93
+ - can a delete actually prevent future recall
94
+ - can repeated raw events merge into reusable semantic knowledge
95
+ - can repeated events merge into an actionable procedure instead of another inert blob of text
96
+
97
+ Those are not implementation details. They are the actual product surface of memory.
98
+
99
+ ## What The Published Leaderboard Means
100
+
101
+ The LoCoMo chart in the generated report is a research context layer, not a claim that Audrey has already reproduced those exact scores.
102
+
103
+ Current published anchors included in the report:
104
+
105
+ - MIRIX: LoCoMo `85.4` from the MIRIX paper
106
+ - Letta Filesystem: LoCoMo `74.0` from Letta's benchmark write-up
107
+ - Mem0 Graph Memory: LoCoMo `68.5` from the Mem0 paper
108
+ - Mem0: LoCoMo `66.9` from the Mem0 paper
109
+ - OpenAI Memory baseline: LoCoMo `52.9` as reported in the Mem0 paper
110
+
111
+ Use this chart to answer: "Where is the frontier today?" not "Has Audrey already matched that exact benchmark protocol?"
112
+
113
+ ## March 23, 2026 Research Readout
114
+
115
+ The most important memory trends right now:
116
+
117
+ 1. Typed memory systems are replacing flat retrieval.
118
+ MemOS frames memory as an operating system concern with scheduling and memory-object abstractions, not just vector lookup.
119
+
120
+ 2. Realistic long-horizon benchmarks are replacing toy recall tests.
121
+ LongMemEval emphasizes multi-session reasoning, temporal updates, abstraction, and knowledge revision.
122
+
123
+ 3. Context engineering is now a first-class competitor to retrieval-only memory.
124
+ Letta's filesystem and memory-block work argues that editable context structure can outperform simpler retrieval-only designs.
125
+
126
+ 4. Production memory is now judged on latency and token cost too.
127
+ Mem0 explicitly reports quality alongside lower token and latency overhead.
128
+
129
+ 5. Temporal and multimodal memory are moving into the frontier.
130
+ MIRIX pushes beyond text-only episodic recall into typed multimodal memory with compression.
131
+
132
+ ## What Audrey Should Do Next
133
+
134
+ The benchmark highlights the next credible roadmap for Audrey:
135
+
136
+ - first-party LoCoMo and LongMemEval adapters so Audrey can publish directly reproducible external benchmark numbers
137
+ - contradiction-state and truth-resolution benchmark cases, not just retrieval outcomes
138
+ - cost, latency, and storage curves against long-context baselines and simpler memory systems
139
+ - a typed memory graph layer for cross-memory state transitions and time-aware reasoning
140
+
141
+ ## Source Links
142
+
143
+ - LongMemEval: [arXiv 2410.10813](https://arxiv.org/abs/2410.10813)
144
+ - Mem0: [arXiv 2504.19413](https://arxiv.org/abs/2504.19413)
145
+ - MIRIX: [arXiv 2507.07957](https://arxiv.org/abs/2507.07957)
146
+ - MemOS: [arXiv 2507.03724](https://arxiv.org/abs/2507.03724)
147
+ - MemGPT: [arXiv 2310.08560](https://arxiv.org/abs/2310.08560)
148
+ - Letta memory blocks: [Letta blog](https://www.letta.com/blog/memory-blocks)
149
+ - Letta benchmarking: [Letta benchmark write-up](https://www.letta.com/blog/benchmarking-ai-agent-memory)
150
+ - LoCoMo benchmark repo: [snap-research/locomo](https://github.com/snap-research/locomo)
151
+ - LongMemEval repo: [xiaowu0162/LongMemEval](https://github.com/xiaowu0162/LongMemEval)
@@ -0,0 +1,124 @@
1
+ # Audrey Production Readiness
2
+
3
+ Audrey is ready to be the memory layer inside a production agent system, but it is not a complete regulated-platform package by itself. Treat it as stateful infrastructure: pin providers, isolate tenants, monitor health, and wrap it with the controls your environment requires.
4
+
5
+ First contact should now go through `npx audrey init sidecar-prod` for the sidecar path or `npx audrey init` for the default Claude Code path, then `npx audrey doctor` before exposing Audrey to real traffic.
6
+
7
+ ## Best Vertical Fit
8
+
9
+ ### 1. Financial Services Operations
10
+
11
+ Best fit:
12
+
13
+ - Payments operations copilots
14
+ - Fraud and dispute investigation agents
15
+ - KYC/KYB review assistants
16
+ - Internal support agents that need durable incident and policy memory
17
+
18
+ Why Audrey fits:
19
+
20
+ - Contradiction tracking helps surface conflicting customer, tool, and policy evidence.
21
+ - Confidence scoring and source lineage make escalations more reviewable.
22
+ - Local SQLite storage keeps memory close to the application boundary.
23
+ - Dream-cycle consolidation turns repeated incidents into reusable operational principles.
24
+
25
+ Guardrails:
26
+
27
+ - Do not store PAN, CVV, raw bank credentials, or secrets in memory.
28
+ - Isolate memory stores by environment, customer, and business unit.
29
+ - Keep export and purge paths in your incident-response runbook.
30
+ - Add encryption at rest and backup retention outside Audrey.
31
+
32
+ ### 2. Healthcare Operations
33
+
34
+ Best fit:
35
+
36
+ - Care coordination assistants
37
+ - Prior-authorization workflow agents
38
+ - Intake, referral, and scheduling copilots
39
+ - Internal knowledge assistants for clinical operations teams
40
+
41
+ Why Audrey fits:
42
+
43
+ - Longitudinal recall preserves operational context across multi-step handoffs.
44
+ - Private memories support role-specific context without making it part of public recall.
45
+ - Contradiction detection helps catch conflicting workflow instructions and stale operating assumptions.
46
+ - Local embeddings allow offline-first or reduced-data-egress deployments.
47
+
48
+ Guardrails:
49
+
50
+ - Audrey is not a medical device and should not be treated as a clinical decision engine.
51
+ - Use de-identified or minimum-necessary data unless the full deployment boundary is HIPAA-ready.
52
+ - Enforce access controls and audit logging in the host application, not just in Audrey.
53
+ - Separate patient-facing and staff-only memory scopes.
54
+
55
+ ## Production Checklist
56
+
57
+ 1. Pin `AUDREY_EMBEDDING_PROVIDER` and `AUDREY_LLM_PROVIDER` explicitly. Do not rely on key-based auto-detection in production.
58
+ 2. Set a dedicated `AUDREY_DATA_DIR` per environment and per tenant boundary.
59
+ 3. Add a health check that runs `npx audrey status --json --fail-on-unhealthy`.
60
+ 4. Alert on `health.healthy=false` or `health.reembed_recommended=true`.
61
+ 5. Schedule `npx audrey dream` during low-traffic windows so consolidation and decay stay current.
62
+ 6. Backup the SQLite data directory before changing embedding dimensions or providers.
63
+ 7. Treat re-embedding as a controlled maintenance action and validate with `npx audrey status`.
64
+ 8. Keep API keys, bearer tokens, and raw credentials out of encoded memory content.
65
+ 9. Decide whether `private` memories are allowed for your use case and document who can create them.
66
+ 10. Add application-level encryption, access control, logging, and retention policies around Audrey.
67
+ 11. On graceful shutdown paths, call `await brain.waitForIdle()` before `brain.close()` so tracked background work drains cleanly.
68
+
69
+ ## Operations Commands
70
+
71
+ ```bash
72
+ # Human-readable health
73
+ npx audrey status
74
+
75
+ # Monitoring-friendly health
76
+ npx audrey status --json
77
+
78
+ # Fail the process if the index is unhealthy or unreadable
79
+ npx audrey status --json --fail-on-unhealthy
80
+
81
+ # Nightly memory maintenance
82
+ npx audrey dream
83
+
84
+ # Repair vector/index drift after provider or dimension changes
85
+ npx audrey reembed
86
+ ```
87
+
88
+ ## Example Deployment Pattern
89
+
90
+ Use Audrey as a local sidecar to the agent service:
91
+
92
+ - One Audrey data directory per tenant or deployment shard
93
+ - Health checks wired to `status --json`
94
+ - Scheduled dream/reembed jobs
95
+ - Backups handled by the host platform
96
+ - Regulated-data filtering handled before `memory_encode`
97
+
98
+ That keeps Audrey focused on memory integrity while the host system owns compliance, tenancy, and transport security.
99
+
100
+ ## Docker Deployment
101
+
102
+ Audrey now ships with a first-party container path for the REST API:
103
+
104
+ ```bash
105
+ npx audrey init sidecar-prod
106
+ docker compose up -d --build
107
+ ```
108
+
109
+ Operational notes:
110
+
111
+ - The container persists SQLite data in the named volume `audrey-data`.
112
+ - Set `AUDREY_API_KEY` before exposing the service beyond localhost.
113
+ - For CI or very fast smoke checks, prefer `AUDREY_EMBEDDING_PROVIDER=mock` and `AUDREY_LLM_PROVIDER=mock`.
114
+ - For stable local/offline container use, keep `AUDREY_EMBEDDING_PROVIDER=local` and `AUDREY_DEVICE=cpu`.
115
+ - If you map the service to a different host port, keep the container port at `3487`.
116
+
117
+ Suggested smoke check:
118
+
119
+ ```bash
120
+ AUDREY_API_KEY=secret docker compose up -d --build
121
+ curl -H "Authorization: Bearer secret" http://localhost:3487/health
122
+ curl -H "Authorization: Bearer secret" http://localhost:3487/status
123
+ docker compose logs --tail=100 audrey
124
+ ```
@@ -0,0 +1,67 @@
1
+ import { Audrey } from '../dist/src/index.js';
2
+
3
+ async function demo() {
4
+ console.log('=== Audrey Demo: Financial Services Operations ===\n');
5
+
6
+ const brain = new Audrey({
7
+ dataDir: './fintech-demo-data',
8
+ agent: 'payments-ops-agent',
9
+ embedding: { provider: 'mock', dimensions: 64 },
10
+ });
11
+
12
+ console.log('--- Encoding payment-operations incidents ---');
13
+ await brain.encode({
14
+ content: 'Processor X returned HTTP 429 when payout retries exceeded 120 requests per minute for marketplace merchants.',
15
+ source: 'direct-observation',
16
+ salience: 0.9,
17
+ tags: ['payments', 'payouts', 'rate-limit'],
18
+ context: { domain: 'finserv', workflow: 'payout-incident' },
19
+ });
20
+
21
+ await brain.encode({
22
+ content: 'On-call notes show payout incident volume drops after retry batches are capped at 50 merchants per worker.',
23
+ source: 'tool-result',
24
+ salience: 0.8,
25
+ tags: ['payments', 'payouts', 'ops'],
26
+ context: { domain: 'finserv', workflow: 'payout-incident' },
27
+ });
28
+
29
+ await brain.encode({
30
+ content: 'Risk operations requested automatic escalation when payout failures affect more than three merchants in the same hour.',
31
+ source: 'told-by-user',
32
+ salience: 0.7,
33
+ tags: ['payments', 'escalation', 'risk'],
34
+ context: { domain: 'finserv', workflow: 'payout-incident' },
35
+ });
36
+
37
+ console.log('\n--- Consolidating incidents into an ops principle ---');
38
+ await brain.consolidate({
39
+ minClusterSize: 3,
40
+ similarityThreshold: -0.3,
41
+ extractPrinciple: () => ({
42
+ content: 'When payout retries spike, cap retry batches and escalate once multiple merchants are affected in the same hour.',
43
+ type: 'procedural',
44
+ conditions: ['payout failures > 3 merchants per hour', 'processor returns 429 or throttling errors'],
45
+ }),
46
+ });
47
+
48
+ console.log('\n--- Recalling during a live payout incident ---');
49
+ const recalled = await brain.recall('payout retries throttled by processor', {
50
+ limit: 5,
51
+ context: { domain: 'finserv', workflow: 'payout-incident' },
52
+ });
53
+
54
+ for (const memory of recalled) {
55
+ console.log(`[${memory.type}] ${memory.content}`);
56
+ }
57
+
58
+ brain.close();
59
+
60
+ const { rmSync } = await import('node:fs');
61
+ rmSync('./fintech-demo-data', { recursive: true, force: true });
62
+ }
63
+
64
+ demo().catch(err => {
65
+ console.error(err);
66
+ process.exit(1);
67
+ });