@mnemoai/core 1.1.0 → 1.1.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.
Files changed (220) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +7 -0
  4. package/dist/cli.js.map +7 -0
  5. package/dist/index.d.ts +128 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/{index.ts → dist/index.js} +526 -1333
  8. package/dist/index.js.map +7 -0
  9. package/dist/src/access-tracker.d.ts +97 -0
  10. package/dist/src/access-tracker.d.ts.map +1 -0
  11. package/dist/src/access-tracker.js +184 -0
  12. package/dist/src/access-tracker.js.map +7 -0
  13. package/dist/src/adapters/chroma.d.ts +31 -0
  14. package/dist/src/adapters/chroma.d.ts.map +1 -0
  15. package/{src/adapters/chroma.ts → dist/src/adapters/chroma.js} +45 -107
  16. package/dist/src/adapters/chroma.js.map +7 -0
  17. package/dist/src/adapters/lancedb.d.ts +29 -0
  18. package/dist/src/adapters/lancedb.d.ts.map +1 -0
  19. package/{src/adapters/lancedb.ts → dist/src/adapters/lancedb.js} +41 -109
  20. package/dist/src/adapters/lancedb.js.map +7 -0
  21. package/dist/src/adapters/pgvector.d.ts +33 -0
  22. package/dist/src/adapters/pgvector.d.ts.map +1 -0
  23. package/{src/adapters/pgvector.ts → dist/src/adapters/pgvector.js} +42 -104
  24. package/dist/src/adapters/pgvector.js.map +7 -0
  25. package/dist/src/adapters/qdrant.d.ts +34 -0
  26. package/dist/src/adapters/qdrant.d.ts.map +1 -0
  27. package/dist/src/adapters/qdrant.js +132 -0
  28. package/dist/src/adapters/qdrant.js.map +7 -0
  29. package/dist/src/adaptive-retrieval.d.ts +14 -0
  30. package/dist/src/adaptive-retrieval.d.ts.map +1 -0
  31. package/dist/src/adaptive-retrieval.js +52 -0
  32. package/dist/src/adaptive-retrieval.js.map +7 -0
  33. package/dist/src/audit-log.d.ts +56 -0
  34. package/dist/src/audit-log.d.ts.map +1 -0
  35. package/dist/src/audit-log.js +139 -0
  36. package/dist/src/audit-log.js.map +7 -0
  37. package/dist/src/chunker.d.ts +45 -0
  38. package/dist/src/chunker.d.ts.map +1 -0
  39. package/dist/src/chunker.js +157 -0
  40. package/dist/src/chunker.js.map +7 -0
  41. package/dist/src/config.d.ts +70 -0
  42. package/dist/src/config.d.ts.map +1 -0
  43. package/dist/src/config.js +142 -0
  44. package/dist/src/config.js.map +7 -0
  45. package/dist/src/decay-engine.d.ts +73 -0
  46. package/dist/src/decay-engine.d.ts.map +1 -0
  47. package/dist/src/decay-engine.js +119 -0
  48. package/dist/src/decay-engine.js.map +7 -0
  49. package/dist/src/embedder.d.ts +94 -0
  50. package/dist/src/embedder.d.ts.map +1 -0
  51. package/{src/embedder.ts → dist/src/embedder.js} +119 -317
  52. package/dist/src/embedder.js.map +7 -0
  53. package/dist/src/extraction-prompts.d.ts +12 -0
  54. package/dist/src/extraction-prompts.d.ts.map +1 -0
  55. package/dist/src/extraction-prompts.js +311 -0
  56. package/dist/src/extraction-prompts.js.map +7 -0
  57. package/dist/src/license.d.ts +29 -0
  58. package/dist/src/license.d.ts.map +1 -0
  59. package/{src/license.ts → dist/src/license.js} +42 -113
  60. package/dist/src/license.js.map +7 -0
  61. package/dist/src/llm-client.d.ts +23 -0
  62. package/dist/src/llm-client.d.ts.map +1 -0
  63. package/{src/llm-client.ts → dist/src/llm-client.js} +22 -55
  64. package/dist/src/llm-client.js.map +7 -0
  65. package/dist/src/logger.d.ts +33 -0
  66. package/dist/src/logger.d.ts.map +1 -0
  67. package/dist/src/logger.js +35 -0
  68. package/dist/src/logger.js.map +7 -0
  69. package/dist/src/mcp-server.d.ts +16 -0
  70. package/dist/src/mcp-server.d.ts.map +1 -0
  71. package/{src/mcp-server.ts → dist/src/mcp-server.js} +81 -181
  72. package/dist/src/mcp-server.js.map +7 -0
  73. package/dist/src/memory-categories.d.ts +40 -0
  74. package/dist/src/memory-categories.d.ts.map +1 -0
  75. package/dist/src/memory-categories.js +33 -0
  76. package/dist/src/memory-categories.js.map +7 -0
  77. package/dist/src/memory-upgrader.d.ts +71 -0
  78. package/dist/src/memory-upgrader.d.ts.map +1 -0
  79. package/dist/src/memory-upgrader.js +238 -0
  80. package/dist/src/memory-upgrader.js.map +7 -0
  81. package/dist/src/migrate.d.ts +47 -0
  82. package/dist/src/migrate.d.ts.map +1 -0
  83. package/{src/migrate.ts → dist/src/migrate.js} +57 -165
  84. package/dist/src/migrate.js.map +7 -0
  85. package/dist/src/mnemo.d.ts +67 -0
  86. package/dist/src/mnemo.d.ts.map +1 -0
  87. package/dist/src/mnemo.js +66 -0
  88. package/dist/src/mnemo.js.map +7 -0
  89. package/dist/src/noise-filter.d.ts +23 -0
  90. package/dist/src/noise-filter.d.ts.map +1 -0
  91. package/dist/src/noise-filter.js +62 -0
  92. package/dist/src/noise-filter.js.map +7 -0
  93. package/dist/src/noise-prototypes.d.ts +40 -0
  94. package/dist/src/noise-prototypes.d.ts.map +1 -0
  95. package/dist/src/noise-prototypes.js +116 -0
  96. package/dist/src/noise-prototypes.js.map +7 -0
  97. package/dist/src/observability.d.ts +16 -0
  98. package/dist/src/observability.d.ts.map +1 -0
  99. package/dist/src/observability.js +53 -0
  100. package/dist/src/observability.js.map +7 -0
  101. package/dist/src/query-tracker.d.ts +27 -0
  102. package/dist/src/query-tracker.d.ts.map +1 -0
  103. package/dist/src/query-tracker.js +32 -0
  104. package/dist/src/query-tracker.js.map +7 -0
  105. package/dist/src/reflection-event-store.d.ts +44 -0
  106. package/dist/src/reflection-event-store.d.ts.map +1 -0
  107. package/dist/src/reflection-event-store.js +50 -0
  108. package/dist/src/reflection-event-store.js.map +7 -0
  109. package/dist/src/reflection-item-store.d.ts +58 -0
  110. package/dist/src/reflection-item-store.d.ts.map +1 -0
  111. package/dist/src/reflection-item-store.js +69 -0
  112. package/dist/src/reflection-item-store.js.map +7 -0
  113. package/dist/src/reflection-mapped-metadata.d.ts +47 -0
  114. package/dist/src/reflection-mapped-metadata.d.ts.map +1 -0
  115. package/dist/src/reflection-mapped-metadata.js +40 -0
  116. package/dist/src/reflection-mapped-metadata.js.map +7 -0
  117. package/dist/src/reflection-metadata.d.ts +11 -0
  118. package/dist/src/reflection-metadata.d.ts.map +1 -0
  119. package/dist/src/reflection-metadata.js +24 -0
  120. package/dist/src/reflection-metadata.js.map +7 -0
  121. package/dist/src/reflection-ranking.d.ts +13 -0
  122. package/dist/src/reflection-ranking.d.ts.map +1 -0
  123. package/{src/reflection-ranking.ts → dist/src/reflection-ranking.js} +12 -21
  124. package/dist/src/reflection-ranking.js.map +7 -0
  125. package/dist/src/reflection-retry.d.ts +30 -0
  126. package/dist/src/reflection-retry.d.ts.map +1 -0
  127. package/{src/reflection-retry.ts → dist/src/reflection-retry.js} +24 -64
  128. package/dist/src/reflection-retry.js.map +7 -0
  129. package/dist/src/reflection-slices.d.ts +42 -0
  130. package/dist/src/reflection-slices.d.ts.map +1 -0
  131. package/{src/reflection-slices.ts → dist/src/reflection-slices.js} +60 -136
  132. package/dist/src/reflection-slices.js.map +7 -0
  133. package/dist/src/reflection-store.d.ts +85 -0
  134. package/dist/src/reflection-store.d.ts.map +1 -0
  135. package/dist/src/reflection-store.js +407 -0
  136. package/dist/src/reflection-store.js.map +7 -0
  137. package/dist/src/resonance-state.d.ts +19 -0
  138. package/dist/src/resonance-state.d.ts.map +1 -0
  139. package/{src/resonance-state.ts → dist/src/resonance-state.js} +13 -42
  140. package/dist/src/resonance-state.js.map +7 -0
  141. package/dist/src/retriever.d.ts +228 -0
  142. package/dist/src/retriever.d.ts.map +1 -0
  143. package/dist/src/retriever.js +1006 -0
  144. package/dist/src/retriever.js.map +7 -0
  145. package/dist/src/scopes.d.ts +58 -0
  146. package/dist/src/scopes.d.ts.map +1 -0
  147. package/dist/src/scopes.js +252 -0
  148. package/dist/src/scopes.js.map +7 -0
  149. package/dist/src/self-improvement-files.d.ts +20 -0
  150. package/dist/src/self-improvement-files.d.ts.map +1 -0
  151. package/{src/self-improvement-files.ts → dist/src/self-improvement-files.js} +24 -49
  152. package/dist/src/self-improvement-files.js.map +7 -0
  153. package/dist/src/semantic-gate.d.ts +24 -0
  154. package/dist/src/semantic-gate.d.ts.map +1 -0
  155. package/dist/src/semantic-gate.js +86 -0
  156. package/dist/src/semantic-gate.js.map +7 -0
  157. package/dist/src/session-recovery.d.ts +9 -0
  158. package/dist/src/session-recovery.d.ts.map +1 -0
  159. package/{src/session-recovery.ts → dist/src/session-recovery.js} +40 -57
  160. package/dist/src/session-recovery.js.map +7 -0
  161. package/dist/src/smart-extractor.d.ts +107 -0
  162. package/dist/src/smart-extractor.d.ts.map +1 -0
  163. package/{src/smart-extractor.ts → dist/src/smart-extractor.js} +130 -383
  164. package/dist/src/smart-extractor.js.map +7 -0
  165. package/dist/src/smart-metadata.d.ts +103 -0
  166. package/dist/src/smart-metadata.d.ts.map +1 -0
  167. package/dist/src/smart-metadata.js +361 -0
  168. package/dist/src/smart-metadata.js.map +7 -0
  169. package/dist/src/storage-adapter.d.ts +102 -0
  170. package/dist/src/storage-adapter.d.ts.map +1 -0
  171. package/dist/src/storage-adapter.js +22 -0
  172. package/dist/src/storage-adapter.js.map +7 -0
  173. package/dist/src/store.d.ts +108 -0
  174. package/dist/src/store.d.ts.map +1 -0
  175. package/dist/src/store.js +939 -0
  176. package/dist/src/store.js.map +7 -0
  177. package/dist/src/tier-manager.d.ts +57 -0
  178. package/dist/src/tier-manager.d.ts.map +1 -0
  179. package/dist/src/tier-manager.js +80 -0
  180. package/dist/src/tier-manager.js.map +7 -0
  181. package/dist/src/tools.d.ts +43 -0
  182. package/dist/src/tools.d.ts.map +1 -0
  183. package/dist/src/tools.js +1075 -0
  184. package/dist/src/tools.js.map +7 -0
  185. package/dist/src/wal-recovery.d.ts +30 -0
  186. package/dist/src/wal-recovery.d.ts.map +1 -0
  187. package/{src/wal-recovery.ts → dist/src/wal-recovery.js} +26 -79
  188. package/dist/src/wal-recovery.js.map +7 -0
  189. package/package.json +21 -2
  190. package/openclaw.plugin.json +0 -815
  191. package/src/access-tracker.ts +0 -341
  192. package/src/adapters/README.md +0 -78
  193. package/src/adapters/qdrant.ts +0 -191
  194. package/src/adaptive-retrieval.ts +0 -90
  195. package/src/audit-log.ts +0 -238
  196. package/src/chunker.ts +0 -254
  197. package/src/config.ts +0 -271
  198. package/src/decay-engine.ts +0 -238
  199. package/src/extraction-prompts.ts +0 -339
  200. package/src/memory-categories.ts +0 -71
  201. package/src/memory-upgrader.ts +0 -388
  202. package/src/mnemo.ts +0 -142
  203. package/src/noise-filter.ts +0 -97
  204. package/src/noise-prototypes.ts +0 -164
  205. package/src/observability.ts +0 -81
  206. package/src/query-tracker.ts +0 -57
  207. package/src/reflection-event-store.ts +0 -98
  208. package/src/reflection-item-store.ts +0 -112
  209. package/src/reflection-mapped-metadata.ts +0 -84
  210. package/src/reflection-metadata.ts +0 -23
  211. package/src/reflection-store.ts +0 -602
  212. package/src/retriever.ts +0 -1510
  213. package/src/scopes.ts +0 -375
  214. package/src/semantic-gate.ts +0 -121
  215. package/src/smart-metadata.ts +0 -561
  216. package/src/storage-adapter.ts +0 -153
  217. package/src/store.ts +0 -1330
  218. package/src/tier-manager.ts +0 -189
  219. package/src/tools.ts +0 -1292
  220. package/test/core.test.mjs +0 -301
@@ -1,388 +0,0 @@
1
- // SPDX-License-Identifier: LicenseRef-Mnemo-Pro
2
- /**
3
- * Memory Upgrader — Convert legacy memories to new smart memory format
4
- *
5
- * Legacy memories lack L0/L1/L2 metadata, memory_category (6-category),
6
- * tier, access_count, and confidence fields. This module enriches them
7
- * to enable unified memory lifecycle management (decay, tier promotion,
8
- * smart dedup).
9
- *
10
- * Pipeline per memory:
11
- * 1. Detect legacy format (missing `memory_category` in metadata)
12
- * 2. Reverse-map 5-category → 6-category
13
- * 3. Generate L0/L1/L2 via LLM (or fallback to simple rules)
14
- * 4. Write enriched metadata back via store.update()
15
- */
16
-
17
- import type { MemoryStore, MemoryEntry } from "./store.js";
18
- import type { LlmClient } from "./llm-client.js";
19
- import type { MemoryCategory } from "./memory-categories.js";
20
- import type { MemoryTier } from "./memory-categories.js";
21
- import { buildSmartMetadata, stringifySmartMetadata } from "./smart-metadata.js";
22
-
23
- // ============================================================================
24
- // Types
25
- // ============================================================================
26
-
27
- export interface UpgradeOptions {
28
- /** Only report counts without modifying data (default: false) */
29
- dryRun?: boolean;
30
- /** Number of memories to process per batch (default: 10) */
31
- batchSize?: number;
32
- /** Skip LLM calls; use simple text truncation for L0/L1 (default: false) */
33
- noLlm?: boolean;
34
- /** Maximum number of memories to upgrade (default: unlimited) */
35
- limit?: number;
36
- /** Scope filter — only upgrade memories in these scopes */
37
- scopeFilter?: string[];
38
- /** Logger function */
39
- log?: (msg: string) => void;
40
- }
41
-
42
- export interface UpgradeResult {
43
- /** Total legacy memories found */
44
- totalLegacy: number;
45
- /** Successfully upgraded count */
46
- upgraded: number;
47
- /** Skipped (already new format) */
48
- skipped: number;
49
- /** Errors encountered */
50
- errors: string[];
51
- }
52
-
53
- interface EnrichedMetadata {
54
- l0_abstract: string;
55
- l1_overview: string;
56
- l2_content: string;
57
- memory_category: MemoryCategory;
58
- tier: MemoryTier;
59
- access_count: number;
60
- confidence: number;
61
- last_accessed_at: number;
62
- upgraded_from: string; // original 5-category
63
- upgraded_at: number; // timestamp of upgrade
64
- }
65
-
66
- // ============================================================================
67
- // Reverse Category Mapping
68
- // ============================================================================
69
-
70
- /**
71
- * Reverse-map old 5-category → new 6-category.
72
- *
73
- * Ambiguous case: `fact` maps to both `profile` and `cases`.
74
- * Without LLM, defaults to `cases` (conservative).
75
- * With LLM, the enrichment prompt will determine the correct category.
76
- */
77
- function reverseMapCategory(
78
- oldCategory: MemoryEntry["category"],
79
- text: string,
80
- ): MemoryCategory {
81
- switch (oldCategory) {
82
- case "preference":
83
- return "preferences";
84
- case "entity":
85
- return "entities";
86
- case "decision":
87
- return "events";
88
- case "other":
89
- return "patterns";
90
- case "fact":
91
- // Heuristic: if text looks like personal identity info, map to profile
92
- if (
93
- /\b(my |i am |i'm |name is |叫我|我的|我是)\b/i.test(text) &&
94
- text.length < 200
95
- ) {
96
- return "profile";
97
- }
98
- return "cases";
99
- default:
100
- return "patterns";
101
- }
102
- }
103
-
104
- // ============================================================================
105
- // LLM Upgrade Prompt
106
- // ============================================================================
107
-
108
- function buildUpgradePrompt(text: string, category: MemoryCategory): string {
109
- return `You are a memory librarian. Given a raw memory text and its category, produce a structured 3-layer summary.
110
-
111
- **Category**: ${category}
112
-
113
- **Raw memory text**:
114
- """
115
- ${text.slice(0, 2000)}
116
- """
117
-
118
- Return ONLY valid JSON (no markdown fences):
119
- {
120
- "l0_abstract": "One sentence (≤30 words) summarizing the core fact/preference/event",
121
- "l1_overview": "A structured markdown summary (2-5 bullet points)",
122
- "l2_content": "The full original text, cleaned up if needed",
123
- "resolved_category": "${category}"
124
- }
125
-
126
- Rules:
127
- - l0_abstract must be a single concise sentence, suitable as a search index key
128
- - l1_overview should use markdown bullet points to structure the information
129
- - l2_content should preserve the original meaning; may clean up formatting
130
- - resolved_category: if the text is clearly about personal identity/profile info (name, age, role, etc.), set to "profile"; if it's a reusable problem-solution pair, set to "cases"; otherwise keep "${category}"
131
- - Respond in the SAME language as the raw memory text`;
132
- }
133
-
134
- // ============================================================================
135
- // Simple (No-LLM) Enrichment
136
- // ============================================================================
137
-
138
- function simpleEnrich(
139
- text: string,
140
- category: MemoryCategory,
141
- ): Pick<EnrichedMetadata, "l0_abstract" | "l1_overview" | "l2_content"> {
142
- // L0: first sentence or first 80 chars
143
- const firstSentence = text.match(/^[^.!?。!?\n]+[.!?。!?]?/)?.[0] || text;
144
- const l0 = firstSentence.slice(0, 100).trim();
145
-
146
- // L1: structured as a single bullet
147
- const l1 = `- ${l0}`;
148
-
149
- // L2: full text
150
- return {
151
- l0_abstract: l0,
152
- l1_overview: l1,
153
- l2_content: text,
154
- };
155
- }
156
-
157
- // ============================================================================
158
- // Memory Upgrader
159
- // ============================================================================
160
-
161
- export class MemoryUpgrader {
162
- private log: (msg: string) => void;
163
-
164
- constructor(
165
- private store: MemoryStore,
166
- private llm: LlmClient | null,
167
- private options: UpgradeOptions = {},
168
- ) {
169
- this.log = options.log ?? console.log;
170
- }
171
-
172
- /**
173
- * Check if a memory entry is in legacy format (needs upgrade).
174
- * Legacy = no metadata, or metadata lacks `memory_category`.
175
- */
176
- isLegacyMemory(entry: MemoryEntry): boolean {
177
- if (!entry.metadata) return true;
178
- try {
179
- const meta = JSON.parse(entry.metadata);
180
- // If it has memory_category, it was created by SmartExtractor → new format
181
- return !meta.memory_category;
182
- } catch {
183
- return true;
184
- }
185
- }
186
-
187
- /**
188
- * Scan and count legacy memories without modifying them.
189
- */
190
- async countLegacy(scopeFilter?: string[]): Promise<{
191
- total: number;
192
- legacy: number;
193
- byCategory: Record<string, number>;
194
- }> {
195
- const allMemories = await this.store.list(scopeFilter, undefined, 10000, 0);
196
- let legacy = 0;
197
- const byCategory: Record<string, number> = {};
198
-
199
- for (const entry of allMemories) {
200
- if (this.isLegacyMemory(entry)) {
201
- legacy++;
202
- byCategory[entry.category] = (byCategory[entry.category] || 0) + 1;
203
- }
204
- }
205
-
206
- return { total: allMemories.length, legacy, byCategory };
207
- }
208
-
209
- /**
210
- * Main upgrade entry point.
211
- * Scans all memories, filters legacy ones, and enriches them.
212
- */
213
- async upgrade(options: UpgradeOptions = {}): Promise<UpgradeResult> {
214
- const batchSize = options.batchSize ?? this.options.batchSize ?? 10;
215
- const noLlm = options.noLlm ?? this.options.noLlm ?? false;
216
- const dryRun = options.dryRun ?? this.options.dryRun ?? false;
217
- const limit = options.limit ?? this.options.limit;
218
-
219
- const result: UpgradeResult = {
220
- totalLegacy: 0,
221
- upgraded: 0,
222
- skipped: 0,
223
- errors: [],
224
- };
225
-
226
- // Load all memories
227
- this.log("memory-upgrader: scanning memories...");
228
- const allMemories = await this.store.list(
229
- options.scopeFilter ?? this.options.scopeFilter,
230
- undefined,
231
- 10000,
232
- 0,
233
- );
234
-
235
- // Filter legacy memories
236
- const legacyMemories = allMemories.filter((m) => this.isLegacyMemory(m));
237
- result.totalLegacy = legacyMemories.length;
238
- result.skipped = allMemories.length - legacyMemories.length;
239
-
240
- if (legacyMemories.length === 0) {
241
- this.log("memory-upgrader: no legacy memories found — all memories are already in new format");
242
- return result;
243
- }
244
-
245
- this.log(
246
- `memory-upgrader: found ${legacyMemories.length} legacy memories out of ${allMemories.length} total`,
247
- );
248
-
249
- if (dryRun) {
250
- const byCategory: Record<string, number> = {};
251
- for (const m of legacyMemories) {
252
- byCategory[m.category] = (byCategory[m.category] || 0) + 1;
253
- }
254
- this.log(
255
- `memory-upgrader: [DRY-RUN] would upgrade ${legacyMemories.length} memories`,
256
- );
257
- this.log(`memory-upgrader: [DRY-RUN] breakdown: ${JSON.stringify(byCategory)}`);
258
- return result;
259
- }
260
-
261
- // Process in batches
262
- const toProcess = limit
263
- ? legacyMemories.slice(0, limit)
264
- : legacyMemories;
265
-
266
- for (let i = 0; i < toProcess.length; i += batchSize) {
267
- const batch = toProcess.slice(i, i + batchSize);
268
- this.log(
269
- `memory-upgrader: processing batch ${Math.floor(i / batchSize) + 1}/${Math.ceil(toProcess.length / batchSize)} (${batch.length} memories)`,
270
- );
271
-
272
- for (const entry of batch) {
273
- try {
274
- await this.upgradeEntry(entry, noLlm);
275
- result.upgraded++;
276
- } catch (err) {
277
- const errMsg = `Failed to upgrade ${entry.id}: ${String(err)}`;
278
- result.errors.push(errMsg);
279
- this.log(`memory-upgrader: ERROR — ${errMsg}`);
280
- }
281
- }
282
-
283
- // Progress report
284
- this.log(
285
- `memory-upgrader: progress — ${result.upgraded} upgraded, ${result.errors.length} errors`,
286
- );
287
- }
288
-
289
- this.log(
290
- `memory-upgrader: upgrade complete — ${result.upgraded} upgraded, ${result.skipped} already new, ${result.errors.length} errors`,
291
- );
292
- return result;
293
- }
294
-
295
- /**
296
- * Upgrade a single legacy memory entry.
297
- */
298
- private async upgradeEntry(
299
- entry: MemoryEntry,
300
- noLlm: boolean,
301
- ): Promise<void> {
302
- // Step 1: Reverse-map category
303
- let newCategory = reverseMapCategory(entry.category, entry.text);
304
-
305
- // Step 2: Generate L0/L1/L2
306
- let enriched: Pick<EnrichedMetadata, "l0_abstract" | "l1_overview" | "l2_content">;
307
-
308
- if (!noLlm && this.llm) {
309
- try {
310
- const prompt = buildUpgradePrompt(entry.text, newCategory);
311
- const llmResult = await this.llm.completeJson<{
312
- l0_abstract: string;
313
- l1_overview: string;
314
- l2_content: string;
315
- resolved_category?: string;
316
- }>(prompt);
317
-
318
- if (!llmResult) {
319
- throw new Error("LLM returned null");
320
- }
321
-
322
- enriched = {
323
- l0_abstract: llmResult.l0_abstract || simpleEnrich(entry.text, newCategory).l0_abstract,
324
- l1_overview: llmResult.l1_overview || simpleEnrich(entry.text, newCategory).l1_overview,
325
- l2_content: llmResult.l2_content || entry.text,
326
- };
327
-
328
- // LLM may have resolved the ambiguous fact→profile/cases
329
- if (llmResult.resolved_category) {
330
- const validCategories = new Set([
331
- "profile", "preferences", "entities", "events", "cases", "patterns",
332
- ]);
333
- if (validCategories.has(llmResult.resolved_category)) {
334
- newCategory = llmResult.resolved_category as MemoryCategory;
335
- }
336
- }
337
- } catch (err) {
338
- this.log(
339
- `memory-upgrader: LLM enrichment failed for ${entry.id}, falling back to simple — ${String(err)}`,
340
- );
341
- enriched = simpleEnrich(entry.text, newCategory);
342
- }
343
- } else {
344
- enriched = simpleEnrich(entry.text, newCategory);
345
- }
346
-
347
- // Step 3: Build enriched metadata
348
- const existingMeta = entry.metadata ? (() => {
349
- try { return JSON.parse(entry.metadata!); } catch { return {}; }
350
- })() : {};
351
-
352
- const newMetadata: EnrichedMetadata = {
353
- ...buildSmartMetadata(
354
- { ...entry, metadata: JSON.stringify(existingMeta) },
355
- {
356
- l0_abstract: enriched.l0_abstract,
357
- l1_overview: enriched.l1_overview,
358
- l2_content: enriched.l2_content,
359
- memory_category: newCategory,
360
- tier: "working" as MemoryTier,
361
- access_count: 0,
362
- confidence: 0.7,
363
- },
364
- ),
365
- upgraded_from: entry.category,
366
- upgraded_at: Date.now(),
367
- };
368
-
369
- // Step 4: Update the memory entry
370
- await this.store.update(entry.id, {
371
- // Update text to L0 abstract for better search indexing
372
- text: enriched.l0_abstract,
373
- metadata: stringifySmartMetadata(newMetadata),
374
- });
375
- }
376
- }
377
-
378
- // ============================================================================
379
- // Factory
380
- // ============================================================================
381
-
382
- export function createMemoryUpgrader(
383
- store: MemoryStore,
384
- llm: LlmClient | null,
385
- options: UpgradeOptions = {},
386
- ): MemoryUpgrader {
387
- return new MemoryUpgrader(store, llm, options);
388
- }
package/src/mnemo.ts DELETED
@@ -1,142 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- /**
3
- * Mnemo Core — simplified entry point
4
- * Usage: const mnemo = await createMnemo(config)
5
- */
6
-
7
- import { MemoryStore } from "./store.js";
8
- import { createRetriever, DEFAULT_RETRIEVAL_CONFIG } from "./retriever.js";
9
- import { Embedder } from "./embedder.js";
10
- import { createDecayEngine, DEFAULT_DECAY_CONFIG } from "./decay-engine.js";
11
- import { SmartExtractor } from "./smart-extractor.js";
12
- import { createLlmClient } from "./llm-client.js";
13
-
14
- export interface MnemoConfig {
15
- embedding: {
16
- provider: "openai-compatible";
17
- apiKey: string;
18
- baseURL?: string;
19
- model?: string;
20
- dimensions?: number;
21
- taskQuery?: string;
22
- taskPassage?: string;
23
- };
24
- dbPath: string;
25
- decay?: {
26
- recencyHalfLifeDays?: number;
27
- recencyWeight?: number;
28
- frequencyWeight?: number;
29
- intrinsicWeight?: number;
30
- };
31
- tier?: {
32
- coreAccessThreshold?: number;
33
- coreImportanceThreshold?: number;
34
- peripheralAgeDays?: number;
35
- };
36
- llm?: {
37
- model?: string;
38
- baseURL?: string;
39
- apiKey?: string;
40
- };
41
- retrieval?: {
42
- candidatePoolSize?: number;
43
- rerank?: "cross-encoder" | "lightweight" | "none";
44
- rerankApiKey?: string;
45
- rerankModel?: string;
46
- rerankEndpoint?: string;
47
- rerankProvider?: string;
48
- };
49
- }
50
-
51
- export interface MnemoInstance {
52
- store(entry: {
53
- text: string;
54
- category?: string;
55
- importance?: number;
56
- scope?: string;
57
- }): Promise<{ id: string }>;
58
-
59
- recall(query: string, options?: {
60
- limit?: number;
61
- scopeFilter?: string[];
62
- category?: string;
63
- }): Promise<Array<{
64
- text: string;
65
- score: number;
66
- category: string;
67
- importance: number;
68
- timestamp: number;
69
- }>>;
70
-
71
- stats(): Promise<{ totalEntries: number }>;
72
-
73
- close(): Promise<void>;
74
- }
75
-
76
- export async function createMnemo(config: MnemoConfig): Promise<MnemoInstance> {
77
- const embedder = new Embedder({
78
- apiKey: config.embedding.apiKey,
79
- baseURL: config.embedding.baseURL,
80
- model: config.embedding.model || "voyage-3-large",
81
- dimensions: config.embedding.dimensions || 1024,
82
- taskQuery: config.embedding.taskQuery,
83
- taskPassage: config.embedding.taskPassage,
84
- });
85
-
86
- const store = new MemoryStore({
87
- dbPath: config.dbPath,
88
- embedder,
89
- });
90
-
91
- await store.initialize();
92
-
93
- const decayEngine = createDecayEngine({
94
- ...DEFAULT_DECAY_CONFIG,
95
- ...(config.decay || {}),
96
- });
97
-
98
- const retriever = createRetriever(store, embedder, {
99
- ...DEFAULT_RETRIEVAL_CONFIG,
100
- ...(config.retrieval || {}),
101
- }, { decayEngine });
102
-
103
- return {
104
- async store(entry) {
105
- const vector = await embedder.embed(entry.text);
106
- const result = await store.store({
107
- text: entry.text,
108
- vector,
109
- category: entry.category || "fact",
110
- importance: entry.importance ?? 0.7,
111
- scope: entry.scope || "global",
112
- });
113
- return { id: result.id };
114
- },
115
-
116
- async recall(query, options = {}) {
117
- const results = await retriever.retrieve({
118
- query,
119
- limit: options.limit ?? 5,
120
- scopeFilter: options.scopeFilter,
121
- category: options.category,
122
- source: "manual",
123
- });
124
- return results.map(r => ({
125
- text: r.entry.text,
126
- score: r.score,
127
- category: r.entry.category || "fact",
128
- importance: r.entry.importance ?? 0.7,
129
- timestamp: r.entry.timestamp ?? Date.now(),
130
- }));
131
- },
132
-
133
- async stats() {
134
- const count = await store.count();
135
- return { totalEntries: count };
136
- },
137
-
138
- async close() {
139
- // LanceDB handles cleanup automatically
140
- },
141
- };
142
- }
@@ -1,97 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
- /**
3
- * Noise Filter
4
- * Filters out low-quality memories (meta-questions, agent denials, session boilerplate)
5
- * Inspired by openclaw-plugin-continuity's noise filtering approach.
6
- */
7
-
8
- // Agent-side denial patterns
9
- const DENIAL_PATTERNS = [
10
- /i don'?t have (any )?(information|data|memory|record)/i,
11
- /i'?m not sure about/i,
12
- /i don'?t recall/i,
13
- /i don'?t remember/i,
14
- /it looks like i don'?t/i,
15
- /i wasn'?t able to find/i,
16
- /no (relevant )?memories found/i,
17
- /i don'?t have access to/i,
18
- ];
19
-
20
- // User-side meta-question patterns (about memory itself, not content)
21
- const META_QUESTION_PATTERNS = [
22
- /\bdo you (remember|recall|know about)\b/i,
23
- /\bcan you (remember|recall)\b/i,
24
- /\bdid i (tell|mention|say|share)\b/i,
25
- /\bhave i (told|mentioned|said)\b/i,
26
- /\bwhat did i (tell|say|mention)\b/i,
27
- /如果你知道.+只回复/i,
28
- /如果不知道.+只回复\s*none/i,
29
- /只回复精确代号/i,
30
- /只回复\s*none/i,
31
- // Chinese recall / meta-question patterns
32
- /你还?记得/,
33
- /记不记得/,
34
- /还记得.*吗/,
35
- /你[知晓]道.+吗/,
36
- /我(?:之前|上次|以前)(?:说|提|讲).*(?:吗|呢|?|\?)/,
37
- ];
38
-
39
- // Session boilerplate
40
- const BOILERPLATE_PATTERNS = [
41
- /^(hi|hello|hey|good morning|good evening|greetings)/i,
42
- /^fresh session/i,
43
- /^new session/i,
44
- /^HEARTBEAT/i,
45
- ];
46
-
47
- // Extractor artifacts from validation prompts / synthetic summaries
48
- const DIAGNOSTIC_ARTIFACT_PATTERNS = [
49
- /\bquery\s*->\s*(none|no explicit solution|unknown|not found)\b/i,
50
- /\buser asked for\b.*\b(none|no explicit solution|unknown|not found)\b/i,
51
- /\bno explicit solution\b/i,
52
- ];
53
-
54
- export interface NoiseFilterOptions {
55
- /** Filter agent denial responses (default: true) */
56
- filterDenials?: boolean;
57
- /** Filter meta-questions about memory (default: true) */
58
- filterMetaQuestions?: boolean;
59
- /** Filter session boilerplate (default: true) */
60
- filterBoilerplate?: boolean;
61
- }
62
-
63
- const DEFAULT_OPTIONS: Required<NoiseFilterOptions> = {
64
- filterDenials: true,
65
- filterMetaQuestions: true,
66
- filterBoilerplate: true,
67
- };
68
-
69
- /**
70
- * Check if a memory text is noise that should be filtered out.
71
- * Returns true if the text is noise.
72
- */
73
- export function isNoise(text: string, options: NoiseFilterOptions = {}): boolean {
74
- const opts = { ...DEFAULT_OPTIONS, ...options };
75
- const trimmed = text.trim();
76
-
77
- if (trimmed.length < 5) return true;
78
-
79
- if (opts.filterDenials && DENIAL_PATTERNS.some(p => p.test(trimmed))) return true;
80
- if (opts.filterMetaQuestions && META_QUESTION_PATTERNS.some(p => p.test(trimmed))) return true;
81
- if (opts.filterBoilerplate && BOILERPLATE_PATTERNS.some(p => p.test(trimmed))) return true;
82
- if (DIAGNOSTIC_ARTIFACT_PATTERNS.some(p => p.test(trimmed))) return true;
83
-
84
- return false;
85
- }
86
-
87
- /**
88
- * Filter an array of items, removing noise entries.
89
- */
90
- export function filterNoise<T>(
91
- items: T[],
92
- getText: (item: T) => string,
93
- options?: NoiseFilterOptions
94
- ): T[] {
95
- const opts = { ...DEFAULT_OPTIONS, ...options };
96
- return items.filter(item => !isNoise(getText(item), opts));
97
- }