@yamo/memory-mesh 3.0.0 → 3.0.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 (107) hide show
  1. package/README.md +8 -2
  2. package/lib/llm/client.d.ts +23 -48
  3. package/lib/llm/client.js +1 -0
  4. package/lib/llm/client.ts +298 -377
  5. package/lib/llm/index.js +1 -0
  6. package/lib/llm/index.ts +1 -2
  7. package/lib/memory/adapters/client.d.ts +22 -85
  8. package/lib/memory/adapters/client.js +1 -0
  9. package/lib/memory/adapters/client.ts +474 -633
  10. package/lib/memory/adapters/config.d.ts +82 -89
  11. package/lib/memory/adapters/config.js +1 -0
  12. package/lib/memory/adapters/config.ts +156 -225
  13. package/lib/memory/adapters/errors.d.ts +28 -20
  14. package/lib/memory/adapters/errors.js +1 -0
  15. package/lib/memory/adapters/errors.ts +83 -120
  16. package/lib/memory/context-manager.d.ts +15 -18
  17. package/lib/memory/context-manager.js +1 -0
  18. package/lib/memory/context-manager.ts +314 -401
  19. package/lib/memory/embeddings/factory.d.ts +18 -20
  20. package/lib/memory/embeddings/factory.js +1 -0
  21. package/lib/memory/embeddings/factory.ts +130 -173
  22. package/lib/memory/embeddings/index.js +1 -0
  23. package/lib/memory/embeddings/index.ts +1 -0
  24. package/lib/memory/embeddings/service.d.ts +36 -66
  25. package/lib/memory/embeddings/service.js +1 -0
  26. package/lib/memory/embeddings/service.ts +479 -616
  27. package/lib/memory/index.d.ts +2 -2
  28. package/lib/memory/index.js +1 -0
  29. package/lib/memory/index.ts +3 -13
  30. package/lib/memory/memory-mesh.d.ts +151 -93
  31. package/lib/memory/memory-mesh.js +1 -0
  32. package/lib/memory/memory-mesh.ts +1406 -1692
  33. package/lib/memory/memory-translator.d.ts +1 -6
  34. package/lib/memory/memory-translator.js +1 -0
  35. package/lib/memory/memory-translator.ts +96 -128
  36. package/lib/memory/schema.d.ts +29 -10
  37. package/lib/memory/schema.js +1 -0
  38. package/lib/memory/schema.ts +102 -185
  39. package/lib/memory/scorer.d.ts +3 -4
  40. package/lib/memory/scorer.js +1 -0
  41. package/lib/memory/scorer.ts +69 -86
  42. package/lib/memory/search/index.js +1 -0
  43. package/lib/memory/search/index.ts +1 -0
  44. package/lib/memory/search/keyword-search.d.ts +10 -26
  45. package/lib/memory/search/keyword-search.js +1 -0
  46. package/lib/memory/search/keyword-search.ts +123 -161
  47. package/lib/scrubber/config/defaults.d.ts +39 -46
  48. package/lib/scrubber/config/defaults.js +1 -0
  49. package/lib/scrubber/config/defaults.ts +50 -112
  50. package/lib/scrubber/errors/scrubber-error.d.ts +22 -0
  51. package/lib/scrubber/errors/scrubber-error.js +39 -0
  52. package/lib/scrubber/errors/scrubber-error.ts +44 -0
  53. package/lib/scrubber/index.d.ts +0 -1
  54. package/lib/scrubber/index.js +1 -0
  55. package/lib/scrubber/index.ts +1 -2
  56. package/lib/scrubber/scrubber.d.ts +14 -31
  57. package/lib/scrubber/scrubber.js +1 -0
  58. package/lib/scrubber/scrubber.ts +93 -152
  59. package/lib/scrubber/stages/chunker.d.ts +22 -10
  60. package/lib/scrubber/stages/chunker.js +86 -0
  61. package/lib/scrubber/stages/chunker.ts +104 -0
  62. package/lib/scrubber/stages/metadata-annotator.d.ts +14 -15
  63. package/lib/scrubber/stages/metadata-annotator.js +64 -0
  64. package/lib/scrubber/stages/metadata-annotator.ts +75 -0
  65. package/lib/scrubber/stages/normalizer.d.ts +13 -10
  66. package/lib/scrubber/stages/normalizer.js +51 -0
  67. package/lib/scrubber/stages/normalizer.ts +60 -0
  68. package/lib/scrubber/stages/semantic-filter.d.ts +13 -10
  69. package/lib/scrubber/stages/semantic-filter.js +51 -0
  70. package/lib/scrubber/stages/semantic-filter.ts +62 -0
  71. package/lib/scrubber/stages/structural-cleaner.d.ts +15 -10
  72. package/lib/scrubber/stages/structural-cleaner.js +73 -0
  73. package/lib/scrubber/stages/structural-cleaner.ts +83 -0
  74. package/lib/scrubber/stages/validator.d.ts +14 -15
  75. package/lib/scrubber/stages/validator.js +56 -0
  76. package/lib/scrubber/stages/validator.ts +67 -0
  77. package/lib/scrubber/telemetry.d.ts +20 -27
  78. package/lib/scrubber/telemetry.js +1 -0
  79. package/lib/scrubber/telemetry.ts +53 -90
  80. package/lib/scrubber/utils/hash.d.ts +14 -0
  81. package/lib/scrubber/utils/hash.js +37 -0
  82. package/lib/scrubber/utils/hash.ts +40 -0
  83. package/lib/scrubber/utils/html-parser.d.ts +14 -0
  84. package/lib/scrubber/utils/html-parser.js +38 -0
  85. package/lib/scrubber/utils/html-parser.ts +46 -0
  86. package/lib/scrubber/utils/pattern-matcher.d.ts +12 -0
  87. package/lib/scrubber/utils/pattern-matcher.js +54 -0
  88. package/lib/scrubber/utils/pattern-matcher.ts +64 -0
  89. package/lib/scrubber/utils/token-counter.d.ts +18 -0
  90. package/lib/scrubber/utils/token-counter.js +30 -0
  91. package/lib/scrubber/utils/token-counter.ts +32 -0
  92. package/lib/utils/logger.d.ts +1 -11
  93. package/lib/utils/logger.js +1 -0
  94. package/lib/utils/logger.ts +43 -63
  95. package/lib/utils/skill-metadata.d.ts +6 -14
  96. package/lib/utils/skill-metadata.js +1 -0
  97. package/lib/utils/skill-metadata.ts +89 -103
  98. package/lib/yamo/emitter.d.ts +8 -35
  99. package/lib/yamo/emitter.js +1 -0
  100. package/lib/yamo/emitter.ts +77 -155
  101. package/lib/yamo/index.d.ts +14 -0
  102. package/lib/yamo/index.js +14 -0
  103. package/lib/yamo/index.ts +16 -0
  104. package/lib/yamo/schema.d.ts +8 -10
  105. package/lib/yamo/schema.js +1 -0
  106. package/lib/yamo/schema.ts +82 -114
  107. package/package.json +4 -2
@@ -1,432 +1,345 @@
1
+ // @ts-nocheck
1
2
  /**
2
3
  * MemoryContextManager - High-level memory management for YAMO
3
4
  */
4
-
5
5
  import { MemoryMesh } from "./memory-mesh.js";
6
6
  import { MemoryScorer } from "./scorer.js";
7
7
  import { MemoryTranslator } from "./memory-translator.js";
8
8
  import { createLogger } from "../utils/logger.js";
9
-
10
9
  const logger = createLogger("context-manager");
11
-
12
- export interface MemoryContextConfig {
13
- mesh?: MemoryMesh;
14
- autoInit?: boolean;
15
- enableCache?: boolean;
16
- recallLimit?: number;
17
- minImportance?: number;
18
- silent?: boolean;
19
- }
20
-
21
- interface CacheEntry {
22
- result: any[];
23
- timestamp: number;
24
- }
25
-
26
10
  export class MemoryContextManager {
27
- #config: MemoryContextConfig;
28
- #mesh: MemoryMesh;
29
- #scorer: MemoryScorer;
30
- #initialized = false;
31
- #queryCache = new Map<string, CacheEntry>();
32
- #cacheConfig = {
33
- maxSize: 100,
34
- ttlMs: 2 * 60 * 1000, // 2 minutes
35
- };
36
- #cleanupTimer: ReturnType<typeof setInterval> | null = null;
37
-
38
- /**
39
- * Create a new MemoryContextManager
40
- */
41
- constructor(config: MemoryContextConfig = {}) {
42
- this.#config = {
43
- autoInit: true,
44
- enableCache: true,
45
- recallLimit: 5,
46
- minImportance: 0.1,
47
- silent: config.silent !== false,
48
- ...config,
11
+ #config;
12
+ #mesh;
13
+ #scorer;
14
+ #initialized = false;
15
+ #queryCache = new Map();
16
+ #cacheConfig = {
17
+ maxSize: 100,
18
+ ttlMs: 2 * 60 * 1000, // 2 minutes
49
19
  };
50
-
51
- // Use provided mesh or create new instance
52
- this.#mesh = config.mesh || new MemoryMesh();
53
- this.#scorer = new MemoryScorer(this.#mesh);
54
-
55
- // Start periodic cleanup timer (every 60 seconds)
56
- this.#startCleanupTimer();
57
- }
58
-
59
- /**
60
- * Initialize the memory context manager
61
- */
62
- async initialize(): Promise<void> {
63
- if (this.#initialized) {
64
- return;
65
- }
66
-
67
- try {
68
- await this.#mesh.init();
69
- this.#initialized = true;
70
- } catch (error: any) {
71
- this.#logWarn(`Initialization failed: ${error.message}`);
72
- this.#initialized = false;
73
- }
74
- }
75
-
76
- /**
77
- * Capture an interaction as memory
78
- */
79
- async captureInteraction(
80
- prompt: string,
81
- response: string,
82
- context: any = {},
83
- ): Promise<any> {
84
- try {
85
- if (this.#config.autoInit && !this.#initialized) {
86
- await this.initialize();
87
- }
88
-
89
- if (!this.#initialized) {
90
- return null;
91
- }
92
-
93
- const content = this.#formatInteraction(prompt, response);
94
- const metadata = this.#buildMetadata(context);
95
-
96
- const isDuplicate = await this.#scorer.isDuplicate(content);
97
- if (isDuplicate) {
98
- return null;
99
- }
100
-
101
- const importance = this.#scorer.calculateImportance(content, metadata);
102
-
103
- if (importance < (this.#config.minImportance ?? 0.1)) {
104
- return null;
105
- }
106
-
107
- const memory = await this.#mesh.add(content, {
108
- ...metadata,
109
- importanceScore: importance,
110
- });
111
-
112
- return memory;
113
- } catch (error: any) {
114
- this.#logWarn(`Failed to capture interaction: ${error.message}`);
115
- return null;
20
+ #cleanupTimer = null;
21
+ /**
22
+ * Create a new MemoryContextManager
23
+ */
24
+ constructor(config = {}) {
25
+ this.#config = {
26
+ autoInit: true,
27
+ enableCache: true,
28
+ recallLimit: 5,
29
+ minImportance: 0.1,
30
+ silent: config.silent !== false,
31
+ ...config,
32
+ };
33
+ // Use provided mesh or create new instance
34
+ this.#mesh = config.mesh || new MemoryMesh();
35
+ this.#scorer = new MemoryScorer(this.#mesh);
36
+ // Start periodic cleanup timer (every 60 seconds)
37
+ this.#startCleanupTimer();
116
38
  }
117
- }
118
-
119
- /**
120
- * Recall relevant memories for a query
121
- */
122
- async recallMemories(query: string, options: any = {}): Promise<any[]> {
123
- try {
124
- if (this.#config.autoInit && !this.#initialized) {
125
- await this.initialize();
126
- }
127
-
128
- if (!this.#initialized) {
129
- return [];
130
- }
131
-
132
- const {
133
- limit = this.#config.recallLimit,
134
- useCache = this.#config.enableCache,
135
- memoryType = null,
136
- skillName = null,
137
- } = options;
138
-
139
- if (useCache) {
140
- const cacheKey = this.#cacheKey(query, {
141
- limit,
142
- memoryType,
143
- skillName,
144
- });
145
- const cached = this.#getCached(cacheKey);
146
- if (cached) {
147
- return cached;
39
+ /**
40
+ * Initialize the memory context manager
41
+ */
42
+ async initialize() {
43
+ if (this.#initialized) {
44
+ return;
148
45
  }
149
- }
150
-
151
- const filter = memoryType ? `memoryType == '${memoryType}'` : null;
152
- // Fetch extra when skill-scoping — some results will be filtered out post-query
153
- const fetchLimit = skillName ? limit * 2 : limit;
154
-
155
- let memories: any[] = [];
156
- if (
157
- memoryType === "synthesized_skill" &&
158
- typeof this.#mesh.searchSkills === "function"
159
- ) {
160
- memories = await this.#mesh.searchSkills(query, { limit: fetchLimit });
161
- } else {
162
- memories = await this.#mesh.search(query, {
163
- limit: fetchLimit,
164
- filter,
165
- useCache: false,
166
- });
167
- }
168
-
169
- memories = memories.map((memory) => {
170
- const metadata =
171
- typeof memory.metadata === "string"
172
- ? JSON.parse(memory.metadata)
173
- : memory.metadata || {};
174
-
175
- return {
176
- ...memory,
177
- importanceScore: memory.score || metadata.importanceScore || 0,
178
- memoryType:
179
- metadata.memoryType ||
180
- (memoryType === "synthesized_skill"
181
- ? "synthesized_skill"
182
- : "global"),
183
- };
184
- });
185
-
186
- // Deduplicate by content — results are already sorted by score, so first occurrence wins
187
- const seen = new Set<string>();
188
- memories = memories.filter((memory) => {
189
- if (seen.has(memory.content)) {
190
- return false;
46
+ try {
47
+ await this.#mesh.init();
48
+ this.#initialized = true;
49
+ }
50
+ catch (error) {
51
+ this.#logWarn(`Initialization failed: ${error.message}`);
52
+ this.#initialized = false;
191
53
  }
192
- seen.add(memory.content);
193
- return true;
194
- });
195
-
196
- // Skill-scope filter: keep memories tagged with this skill OR untagged (global).
197
- // Untagged memories are shared context; tagged memories are skill-private.
198
- if (skillName) {
199
- memories = memories.filter((memory) => {
200
- const meta =
201
- typeof memory.metadata === "string"
202
- ? JSON.parse(memory.metadata)
203
- : memory.metadata || {};
204
- return !meta.skill_name || meta.skill_name === skillName;
205
- });
206
- memories = memories.slice(0, limit);
207
- }
208
-
209
- if (useCache) {
210
- const cacheKey = this.#cacheKey(query, {
211
- limit,
212
- memoryType,
213
- skillName,
214
- });
215
- this.#setCached(cacheKey, memories);
216
- }
217
-
218
- return memories;
219
- } catch (error: any) {
220
- this.#logWarn(`Failed to recall memories: ${error.message}`);
221
- return [];
222
- }
223
- }
224
-
225
- /**
226
- * Format memories for inclusion in prompt
227
- */
228
- formatMemoriesForPrompt(memories: any[], options: any = {}): string {
229
- try {
230
- if (!memories || memories.length === 0) {
231
- return "";
232
- }
233
-
234
- return MemoryTranslator.toYAMOContext(memories, options);
235
- } catch (error: any) {
236
- this.#logWarn(`Failed to format memories: ${error.message}`);
237
- return "";
238
54
  }
239
- }
240
-
241
- #logWarn(message: string): void {
242
- if (!this.#config.silent || process.env.YAMO_DEBUG === "true") {
243
- logger.warn(message);
55
+ /**
56
+ * Capture an interaction as memory
57
+ */
58
+ async captureInteraction(prompt, response, context = {}) {
59
+ try {
60
+ if (this.#config.autoInit && !this.#initialized) {
61
+ await this.initialize();
62
+ }
63
+ if (!this.#initialized) {
64
+ return null;
65
+ }
66
+ const content = this.#formatInteraction(prompt, response);
67
+ const metadata = this.#buildMetadata(context);
68
+ const isDuplicate = await this.#scorer.isDuplicate(content);
69
+ if (isDuplicate) {
70
+ return null;
71
+ }
72
+ const importance = this.#scorer.calculateImportance(content, metadata);
73
+ if (importance < (this.#config.minImportance ?? 0.1)) {
74
+ return null;
75
+ }
76
+ const memory = await this.#mesh.add(content, {
77
+ ...metadata,
78
+ importanceScore: importance,
79
+ });
80
+ return memory;
81
+ }
82
+ catch (error) {
83
+ this.#logWarn(`Failed to capture interaction: ${error.message}`);
84
+ return null;
85
+ }
244
86
  }
245
- }
246
-
247
- #formatInteraction(prompt: string, response: string): string {
248
- const lines = [
249
- `[USER] ${prompt}`,
250
- `[ASSISTANT] ${response.substring(0, 500)}${response.length > 500 ? "..." : ""}`,
251
- ];
252
-
253
- return lines.join("\n\n");
254
- }
255
-
256
- #buildMetadata(context: any): any {
257
- const metadata: any = {
258
- interaction_type: context.interactionType || "llm_response",
259
- created_at: new Date().toISOString(),
260
- };
261
-
262
- if (context.toolsUsed?.length > 0) {
263
- metadata.tools_used = context.toolsUsed;
87
+ /**
88
+ * Recall relevant memories for a query
89
+ */
90
+ async recallMemories(query, options = {}) {
91
+ try {
92
+ if (this.#config.autoInit && !this.#initialized) {
93
+ await this.initialize();
94
+ }
95
+ if (!this.#initialized) {
96
+ return [];
97
+ }
98
+ const { limit = this.#config.recallLimit, useCache = this.#config.enableCache, memoryType = null, skillName = null, } = options;
99
+ if (useCache) {
100
+ const cacheKey = this.#cacheKey(query, {
101
+ limit,
102
+ memoryType,
103
+ skillName,
104
+ });
105
+ const cached = this.#getCached(cacheKey);
106
+ if (cached) {
107
+ return cached;
108
+ }
109
+ }
110
+ const filter = memoryType ? `memoryType == '${memoryType}'` : null;
111
+ // Fetch extra when skill-scoping — some results will be filtered out post-query
112
+ const fetchLimit = skillName ? limit * 2 : limit;
113
+ let memories = [];
114
+ if (memoryType === "synthesized_skill" &&
115
+ typeof this.#mesh.searchSkills === "function") {
116
+ memories = await this.#mesh.searchSkills(query, { limit: fetchLimit });
117
+ }
118
+ else {
119
+ memories = await this.#mesh.search(query, {
120
+ limit: fetchLimit,
121
+ filter,
122
+ useCache: false,
123
+ });
124
+ }
125
+ memories = memories.map((memory) => {
126
+ const metadata = typeof memory.metadata === "string"
127
+ ? JSON.parse(memory.metadata)
128
+ : memory.metadata || {};
129
+ return {
130
+ ...memory,
131
+ importanceScore: memory.score || metadata.importanceScore || 0,
132
+ memoryType: metadata.memoryType ||
133
+ (memoryType === "synthesized_skill"
134
+ ? "synthesized_skill"
135
+ : "global"),
136
+ };
137
+ });
138
+ // Deduplicate by content — results are already sorted by score, so first occurrence wins
139
+ const seen = new Set();
140
+ memories = memories.filter((memory) => {
141
+ if (seen.has(memory.content)) {
142
+ return false;
143
+ }
144
+ seen.add(memory.content);
145
+ return true;
146
+ });
147
+ // Skill-scope filter: keep memories tagged with this skill OR untagged (global).
148
+ // Untagged memories are shared context; tagged memories are skill-private.
149
+ if (skillName) {
150
+ memories = memories.filter((memory) => {
151
+ const meta = typeof memory.metadata === "string"
152
+ ? JSON.parse(memory.metadata)
153
+ : memory.metadata || {};
154
+ return !meta.skill_name || meta.skill_name === skillName;
155
+ });
156
+ memories = memories.slice(0, limit);
157
+ }
158
+ if (useCache) {
159
+ const cacheKey = this.#cacheKey(query, {
160
+ limit,
161
+ memoryType,
162
+ skillName,
163
+ });
164
+ this.#setCached(cacheKey, memories);
165
+ }
166
+ return memories;
167
+ }
168
+ catch (error) {
169
+ this.#logWarn(`Failed to recall memories: ${error.message}`);
170
+ return [];
171
+ }
264
172
  }
265
-
266
- if (context.filesInvolved?.length > 0) {
267
- metadata.files_involved = context.filesInvolved;
173
+ /**
174
+ * Format memories for inclusion in prompt
175
+ */
176
+ formatMemoriesForPrompt(memories, options = {}) {
177
+ try {
178
+ if (!memories || memories.length === 0) {
179
+ return "";
180
+ }
181
+ return MemoryTranslator.toYAMOContext(memories, options);
182
+ }
183
+ catch (error) {
184
+ this.#logWarn(`Failed to format memories: ${error.message}`);
185
+ return "";
186
+ }
268
187
  }
269
-
270
- if (context.tags?.length > 0) {
271
- metadata.tags = context.tags;
188
+ #logWarn(message) {
189
+ if (!this.#config.silent || process.env.YAMO_DEBUG === "true") {
190
+ logger.warn(message);
191
+ }
272
192
  }
273
-
274
- if (context.skillName) {
275
- metadata.skill_name = context.skillName;
193
+ #formatInteraction(prompt, response) {
194
+ const lines = [
195
+ `[USER] ${prompt}`,
196
+ `[ASSISTANT] ${response.substring(0, 500)}${response.length > 500 ? "..." : ""}`,
197
+ ];
198
+ return lines.join("\n\n");
276
199
  }
277
-
278
- if (context.sessionId) {
279
- metadata.session_id = context.sessionId;
200
+ #buildMetadata(context) {
201
+ const metadata = {
202
+ interaction_type: context.interactionType || "llm_response",
203
+ created_at: new Date().toISOString(),
204
+ };
205
+ if (context.toolsUsed?.length > 0) {
206
+ metadata.tools_used = context.toolsUsed;
207
+ }
208
+ if (context.filesInvolved?.length > 0) {
209
+ metadata.files_involved = context.filesInvolved;
210
+ }
211
+ if (context.tags?.length > 0) {
212
+ metadata.tags = context.tags;
213
+ }
214
+ if (context.skillName) {
215
+ metadata.skill_name = context.skillName;
216
+ }
217
+ if (context.sessionId) {
218
+ metadata.session_id = context.sessionId;
219
+ }
220
+ return metadata;
280
221
  }
281
-
282
- return metadata;
283
- }
284
-
285
- #cacheKey(query: string, options: any): string {
286
- return `recall:${query}:${JSON.stringify(options)}`;
287
- }
288
-
289
- /**
290
- * Get cached result if valid
291
- * Race condition fix: Update timestamp atomically for LRU tracking
292
- */
293
- #getCached(key: string): any {
294
- const entry = this.#queryCache.get(key);
295
- if (!entry) {
296
- return null;
222
+ #cacheKey(query, options) {
223
+ return `recall:${query}:${JSON.stringify(options)}`;
297
224
  }
298
-
299
- // Check TTL before any mutation
300
- const now = Date.now();
301
- if (now - entry.timestamp > this.#cacheConfig.ttlMs) {
302
- this.#queryCache.delete(key);
303
- return null;
225
+ /**
226
+ * Get cached result if valid
227
+ * Race condition fix: Update timestamp atomically for LRU tracking
228
+ */
229
+ #getCached(key) {
230
+ const entry = this.#queryCache.get(key);
231
+ if (!entry) {
232
+ return null;
233
+ }
234
+ // Check TTL before any mutation
235
+ const now = Date.now();
236
+ if (now - entry.timestamp > this.#cacheConfig.ttlMs) {
237
+ this.#queryCache.delete(key);
238
+ return null;
239
+ }
240
+ // Move to end (most recently used) - delete and re-add with updated timestamp
241
+ this.#queryCache.delete(key);
242
+ this.#queryCache.set(key, {
243
+ ...entry,
244
+ timestamp: now, // Update timestamp for LRU tracking
245
+ });
246
+ return entry.result;
304
247
  }
305
-
306
- // Move to end (most recently used) - delete and re-add with updated timestamp
307
- this.#queryCache.delete(key);
308
- this.#queryCache.set(key, {
309
- ...entry,
310
- timestamp: now, // Update timestamp for LRU tracking
311
- });
312
-
313
- return entry.result;
314
- }
315
-
316
- #setCached(key: string, result: any): void {
317
- if (this.#queryCache.size >= this.#cacheConfig.maxSize) {
318
- const firstKey = this.#queryCache.keys().next().value;
319
- if (firstKey !== undefined) {
320
- this.#queryCache.delete(firstKey);
321
- }
248
+ #setCached(key, result) {
249
+ if (this.#queryCache.size >= this.#cacheConfig.maxSize) {
250
+ const firstKey = this.#queryCache.keys().next().value;
251
+ if (firstKey !== undefined) {
252
+ this.#queryCache.delete(firstKey);
253
+ }
254
+ }
255
+ this.#queryCache.set(key, {
256
+ result,
257
+ timestamp: Date.now(),
258
+ });
322
259
  }
323
-
324
- this.#queryCache.set(key, {
325
- result,
326
- timestamp: Date.now(),
327
- });
328
- }
329
-
330
- clearCache(): void {
331
- this.#queryCache.clear();
332
- }
333
-
334
- getCacheStats(): any {
335
- return {
336
- size: this.#queryCache.size,
337
- maxSize: this.#cacheConfig.maxSize,
338
- ttlMs: this.#cacheConfig.ttlMs,
339
- };
340
- }
341
-
342
- async healthCheck(): Promise<any> {
343
- const health: any = {
344
- status: "healthy",
345
- timestamp: new Date().toISOString(),
346
- initialized: this.#initialized,
347
- checks: {},
348
- };
349
-
350
- try {
351
- health.checks.mesh = await this.#mesh.stats(); // brain.ts has stats()
352
- if (health.checks.mesh.isConnected === false) {
353
- health.status = "degraded";
354
- }
355
- } catch (error: any) {
356
- health.checks.mesh = {
357
- status: "error",
358
- error: error.message,
359
- };
360
- health.status = "unhealthy";
260
+ clearCache() {
261
+ this.#queryCache.clear();
361
262
  }
362
-
363
- health.checks.cache = {
364
- status: "up",
365
- size: this.#queryCache.size,
366
- maxSize: this.#cacheConfig.maxSize,
367
- };
368
-
369
- return health;
370
- }
371
-
372
- /**
373
- * Start periodic cleanup timer to remove expired cache entries
374
- * @private
375
- */
376
- #startCleanupTimer(): void {
377
- // Clear any existing timer
378
- if (this.#cleanupTimer) {
379
- clearInterval(this.#cleanupTimer);
263
+ getCacheStats() {
264
+ return {
265
+ size: this.#queryCache.size,
266
+ maxSize: this.#cacheConfig.maxSize,
267
+ ttlMs: this.#cacheConfig.ttlMs,
268
+ };
380
269
  }
381
-
382
- // Run cleanup every 60 seconds
383
- this.#cleanupTimer = setInterval(() => {
384
- this.#cleanupExpired();
385
- }, 60000);
386
- }
387
-
388
- /**
389
- * Clean up expired cache entries
390
- * @private
391
- */
392
- #cleanupExpired(): void {
393
- const now = Date.now();
394
- const expiredKeys: string[] = [];
395
-
396
- // Find expired entries
397
- for (const [key, entry] of this.#queryCache.entries()) {
398
- if (now - entry.timestamp > this.#cacheConfig.ttlMs) {
399
- expiredKeys.push(key);
400
- }
270
+ async healthCheck() {
271
+ const health = {
272
+ status: "healthy",
273
+ timestamp: new Date().toISOString(),
274
+ initialized: this.#initialized,
275
+ checks: {},
276
+ };
277
+ try {
278
+ health.checks.mesh = await this.#mesh.stats(); // brain.ts has stats()
279
+ if (health.checks.mesh.isConnected === false) {
280
+ health.status = "degraded";
281
+ }
282
+ }
283
+ catch (error) {
284
+ health.checks.mesh = {
285
+ status: "error",
286
+ error: error.message,
287
+ };
288
+ health.status = "unhealthy";
289
+ }
290
+ health.checks.cache = {
291
+ status: "up",
292
+ size: this.#queryCache.size,
293
+ maxSize: this.#cacheConfig.maxSize,
294
+ };
295
+ return health;
401
296
  }
402
-
403
- // Remove expired entries
404
- for (const key of expiredKeys) {
405
- this.#queryCache.delete(key);
297
+ /**
298
+ * Start periodic cleanup timer to remove expired cache entries
299
+ * @private
300
+ */
301
+ #startCleanupTimer() {
302
+ // Clear any existing timer
303
+ if (this.#cleanupTimer) {
304
+ clearInterval(this.#cleanupTimer);
305
+ }
306
+ // Run cleanup every 60 seconds
307
+ this.#cleanupTimer = setInterval(() => {
308
+ this.#cleanupExpired();
309
+ }, 60000);
406
310
  }
407
-
408
- if (
409
- expiredKeys.length > 0 &&
410
- (process.env.YAMO_DEBUG === "true" || !this.#config.silent)
411
- ) {
412
- logger.debug(
413
- { count: expiredKeys.length },
414
- "Cleaned up expired cache entries",
415
- );
311
+ /**
312
+ * Clean up expired cache entries
313
+ * @private
314
+ */
315
+ #cleanupExpired() {
316
+ const now = Date.now();
317
+ const expiredKeys = [];
318
+ // Find expired entries
319
+ for (const [key, entry] of this.#queryCache.entries()) {
320
+ if (now - entry.timestamp > this.#cacheConfig.ttlMs) {
321
+ expiredKeys.push(key);
322
+ }
323
+ }
324
+ // Remove expired entries
325
+ for (const key of expiredKeys) {
326
+ this.#queryCache.delete(key);
327
+ }
328
+ if (expiredKeys.length > 0 &&
329
+ (process.env.YAMO_DEBUG === "true" || !this.#config.silent)) {
330
+ logger.debug({ count: expiredKeys.length }, "Cleaned up expired cache entries");
331
+ }
416
332
  }
417
- }
418
-
419
- /**
420
- * Dispose of resources (cleanup timer and cache)
421
- * Call this when the MemoryContextManager is no longer needed
422
- */
423
- dispose(): void {
424
- if (this.#cleanupTimer) {
425
- clearInterval(this.#cleanupTimer);
426
- this.#cleanupTimer = null;
333
+ /**
334
+ * Dispose of resources (cleanup timer and cache)
335
+ * Call this when the MemoryContextManager is no longer needed
336
+ */
337
+ dispose() {
338
+ if (this.#cleanupTimer) {
339
+ clearInterval(this.#cleanupTimer);
340
+ this.#cleanupTimer = null;
341
+ }
342
+ this.clearCache();
427
343
  }
428
- this.clearCache();
429
- }
430
344
  }
431
-
432
345
  export default MemoryContextManager;