@prometheus-ai/memory 0.5.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 (128) hide show
  1. package/README.md +107 -0
  2. package/dist/types/cli.d.ts +35 -0
  3. package/dist/types/config.d.ts +77 -0
  4. package/dist/types/core/aaak.d.ts +55 -0
  5. package/dist/types/core/annotations.d.ts +75 -0
  6. package/dist/types/core/banks.d.ts +33 -0
  7. package/dist/types/core/beam/consolidate.d.ts +32 -0
  8. package/dist/types/core/beam/helpers.d.ts +76 -0
  9. package/dist/types/core/beam/index.d.ts +59 -0
  10. package/dist/types/core/beam/recall.d.ts +32 -0
  11. package/dist/types/core/beam/schema.d.ts +2 -0
  12. package/dist/types/core/beam/store.d.ts +35 -0
  13. package/dist/types/core/beam/types.d.ts +233 -0
  14. package/dist/types/core/binary-vectors.d.ts +54 -0
  15. package/dist/types/core/chat-normalize.d.ts +13 -0
  16. package/dist/types/core/content-sanitizer.d.ts +18 -0
  17. package/dist/types/core/cost-log.d.ts +13 -0
  18. package/dist/types/core/embeddings.d.ts +44 -0
  19. package/dist/types/core/entities.d.ts +7 -0
  20. package/dist/types/core/episodic-graph.d.ts +89 -0
  21. package/dist/types/core/extraction/client.d.ts +31 -0
  22. package/dist/types/core/extraction/diagnostics.d.ts +51 -0
  23. package/dist/types/core/extraction/prompts.d.ts +2 -0
  24. package/dist/types/core/extraction.d.ts +6 -0
  25. package/dist/types/core/index.d.ts +4 -0
  26. package/dist/types/core/llm-backends.d.ts +21 -0
  27. package/dist/types/core/local-llm.d.ts +15 -0
  28. package/dist/types/core/memory.d.ts +160 -0
  29. package/dist/types/core/migrations/e6-triplestore-split.d.ts +17 -0
  30. package/dist/types/core/migrations/index.d.ts +1 -0
  31. package/dist/types/core/mmr.d.ts +8 -0
  32. package/dist/types/core/orchestrator.d.ts +20 -0
  33. package/dist/types/core/patterns.d.ts +61 -0
  34. package/dist/types/core/plugins.d.ts +109 -0
  35. package/dist/types/core/polyphonic-recall.d.ts +66 -0
  36. package/dist/types/core/query-cache.d.ts +46 -0
  37. package/dist/types/core/query-intent.d.ts +20 -0
  38. package/dist/types/core/recall-diagnostics.d.ts +48 -0
  39. package/dist/types/core/runtime-options.d.ts +68 -0
  40. package/dist/types/core/shmr.d.ts +56 -0
  41. package/dist/types/core/streaming.d.ts +136 -0
  42. package/dist/types/core/synonyms.d.ts +46 -0
  43. package/dist/types/core/temporal-parser.d.ts +16 -0
  44. package/dist/types/core/token-counter.d.ts +8 -0
  45. package/dist/types/core/triples.d.ts +63 -0
  46. package/dist/types/core/typed-memory.d.ts +39 -0
  47. package/dist/types/core/vector-math.d.ts +1 -0
  48. package/dist/types/core/veracity-consolidation.d.ts +60 -0
  49. package/dist/types/core/weibull.d.ts +96 -0
  50. package/dist/types/db.d.ts +16 -0
  51. package/dist/types/diagnose.d.ts +24 -0
  52. package/dist/types/dr/index.d.ts +1 -0
  53. package/dist/types/dr/recovery.d.ts +68 -0
  54. package/dist/types/index.d.ts +5 -0
  55. package/dist/types/mcp-server.d.ts +40 -0
  56. package/dist/types/mcp-tools.d.ts +484 -0
  57. package/dist/types/migrations/e6-triplestore-split.d.ts +1 -0
  58. package/dist/types/migrations/index.d.ts +1 -0
  59. package/dist/types/types.d.ts +145 -0
  60. package/dist/types/util/datetime.d.ts +8 -0
  61. package/dist/types/util/env.d.ts +10 -0
  62. package/dist/types/util/ids.d.ts +3 -0
  63. package/dist/types/util/lru.d.ts +12 -0
  64. package/dist/types/util/regex.d.ts +10 -0
  65. package/package.json +85 -0
  66. package/src/cli.ts +398 -0
  67. package/src/config.ts +326 -0
  68. package/src/core/aaak.ts +142 -0
  69. package/src/core/annotations.ts +457 -0
  70. package/src/core/banks.ts +133 -0
  71. package/src/core/beam/consolidate.ts +965 -0
  72. package/src/core/beam/helpers.ts +977 -0
  73. package/src/core/beam/index.ts +353 -0
  74. package/src/core/beam/recall.ts +1100 -0
  75. package/src/core/beam/schema.ts +423 -0
  76. package/src/core/beam/store.ts +829 -0
  77. package/src/core/beam/types.ts +268 -0
  78. package/src/core/binary-vectors.ts +317 -0
  79. package/src/core/chat-normalize.ts +160 -0
  80. package/src/core/content-sanitizer.ts +136 -0
  81. package/src/core/cost-log.ts +103 -0
  82. package/src/core/embeddings.ts +423 -0
  83. package/src/core/entities.ts +259 -0
  84. package/src/core/episodic-graph.ts +708 -0
  85. package/src/core/extraction/client.ts +162 -0
  86. package/src/core/extraction/diagnostics.ts +193 -0
  87. package/src/core/extraction/prompts.ts +31 -0
  88. package/src/core/extraction.ts +335 -0
  89. package/src/core/index.ts +30 -0
  90. package/src/core/llm-backends.ts +51 -0
  91. package/src/core/local-llm.ts +436 -0
  92. package/src/core/memory.ts +630 -0
  93. package/src/core/migrations/e6-triplestore-split.ts +211 -0
  94. package/src/core/migrations/index.ts +1 -0
  95. package/src/core/mmr.ts +71 -0
  96. package/src/core/orchestrator.ts +62 -0
  97. package/src/core/patterns.ts +484 -0
  98. package/src/core/plugins.ts +375 -0
  99. package/src/core/polyphonic-recall.ts +563 -0
  100. package/src/core/query-cache.ts +354 -0
  101. package/src/core/query-intent.ts +139 -0
  102. package/src/core/recall-diagnostics.ts +157 -0
  103. package/src/core/runtime-options.ts +119 -0
  104. package/src/core/shmr.ts +460 -0
  105. package/src/core/streaming.ts +419 -0
  106. package/src/core/synonyms.ts +197 -0
  107. package/src/core/temporal-parser.ts +363 -0
  108. package/src/core/token-counter.ts +30 -0
  109. package/src/core/triples.ts +454 -0
  110. package/src/core/typed-memory.ts +407 -0
  111. package/src/core/vector-math.ts +23 -0
  112. package/src/core/veracity-consolidation.ts +477 -0
  113. package/src/core/weibull.ts +124 -0
  114. package/src/db.ts +128 -0
  115. package/src/diagnose.ts +174 -0
  116. package/src/dr/index.ts +1 -0
  117. package/src/dr/recovery.ts +405 -0
  118. package/src/index.ts +33 -0
  119. package/src/mcp-server.ts +155 -0
  120. package/src/mcp-tools.ts +970 -0
  121. package/src/migrations/e6-triplestore-split.ts +1 -0
  122. package/src/migrations/index.ts +1 -0
  123. package/src/types.ts +157 -0
  124. package/src/util/datetime.ts +69 -0
  125. package/src/util/env.ts +65 -0
  126. package/src/util/ids.ts +19 -0
  127. package/src/util/lru.ts +48 -0
  128. package/src/util/regex.ts +165 -0
@@ -0,0 +1,375 @@
1
+ import { existsSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+
5
+ export const DEFAULT_PLUGIN_DIR = join(homedir(), ".prometheus", "memory", "plugins");
6
+
7
+ export type PluginConfig = Record<string, unknown>;
8
+ export type MemoryDict = Record<string, unknown>;
9
+
10
+ export class MnemopiPlugin {
11
+ static readonly abstractBase = true;
12
+ name = "";
13
+ version = "1.0.0";
14
+ enabled = true;
15
+ protected initialized = false;
16
+ readonly config: PluginConfig;
17
+
18
+ constructor(config: PluginConfig = {}) {
19
+ if (new.target === MnemopiPlugin) throw new TypeError("MnemopiPlugin is abstract");
20
+ this.config = config;
21
+ const ctor = this.constructor as typeof MnemopiPlugin;
22
+ this.name =
23
+ (ctor.prototype.name as string | undefined) ?? (ctor as unknown as { name?: string }).name ?? this.name;
24
+ this.version = (ctor.prototype.version as string | undefined) ?? this.version;
25
+ this.enabled = (ctor.prototype.enabled as boolean | undefined) ?? this.enabled;
26
+ }
27
+
28
+ initialize(): void {
29
+ this.initialized = true;
30
+ }
31
+
32
+ shutdown(): void {
33
+ this.initialized = false;
34
+ }
35
+
36
+ onRemember(_memory: MemoryDict): void {
37
+ throw new TypeError("Plugin must implement onRemember");
38
+ }
39
+ onRecall(_memory: MemoryDict): void {
40
+ throw new TypeError("Plugin must implement onRecall");
41
+ }
42
+ onConsolidate(_summary: MemoryDict): void {
43
+ throw new TypeError("Plugin must implement onConsolidate");
44
+ }
45
+ onInvalidate(_memoryId: string): void {
46
+ throw new TypeError("Plugin must implement onInvalidate");
47
+ }
48
+ toDict(): Record<string, unknown> {
49
+ return {
50
+ name: this.name,
51
+ version: this.version,
52
+ enabled: this.enabled,
53
+ initialized: this.initialized,
54
+ config: this.config,
55
+ };
56
+ }
57
+ }
58
+
59
+ function previewContent(content: unknown, maxLen = 80): string {
60
+ const text = typeof content === "string" ? content : "";
61
+ if (text.length <= maxLen) return text;
62
+ return `${text.slice(0, maxLen)}...`;
63
+ }
64
+
65
+ export class LoggingPlugin extends MnemopiPlugin {
66
+ override name = "logging";
67
+ override version = "1.0.0";
68
+ private readonly memoryLog: MemoryDict[] = [];
69
+ private readonly maxEntries: number;
70
+ constructor(config: PluginConfig = {}) {
71
+ super(config);
72
+ const configured = config.max_entries ?? config.maxEntries;
73
+ this.maxEntries = typeof configured === "number" && Number.isFinite(configured) ? configured : 10000;
74
+ }
75
+ private append(entry: MemoryDict): void {
76
+ this.memoryLog.push(entry);
77
+ if (this.memoryLog.length > this.maxEntries) this.memoryLog.shift();
78
+ }
79
+ override onRemember(memory: MemoryDict): void {
80
+ this.append({
81
+ event: "remember",
82
+ timestamp: new Date().toISOString(),
83
+ memory_id: memory.id,
84
+ content_preview: previewContent(memory.content),
85
+ });
86
+ }
87
+ override onRecall(memory: MemoryDict): void {
88
+ this.append({
89
+ event: "recall",
90
+ timestamp: new Date().toISOString(),
91
+ memory_id: memory.id,
92
+ content_preview: previewContent(memory.content),
93
+ });
94
+ }
95
+ override onConsolidate(summary: MemoryDict): void {
96
+ const ids = Array.isArray(summary.source_wm_ids) ? summary.source_wm_ids : [];
97
+ this.append({
98
+ event: "consolidate",
99
+ timestamp: new Date().toISOString(),
100
+ summary_preview: previewContent(summary.summary),
101
+ source_count: ids.length,
102
+ });
103
+ }
104
+ override onInvalidate(memoryId: string): void {
105
+ this.append({ event: "invalidate", timestamp: new Date().toISOString(), memory_id: memoryId });
106
+ }
107
+ getLog(): MemoryDict[] {
108
+ return this.memoryLog.slice();
109
+ }
110
+ clearLog(): void {
111
+ this.memoryLog.length = 0;
112
+ }
113
+ }
114
+
115
+ type MetricsEvent = "remember" | "recall" | "consolidate" | "invalidate";
116
+
117
+ export class MetricsPlugin extends MnemopiPlugin {
118
+ override name = "metrics";
119
+ override version = "1.0.0";
120
+ private readonly counters: Record<MetricsEvent, number> = {
121
+ remember: 0,
122
+ recall: 0,
123
+ consolidate: 0,
124
+ invalidate: 0,
125
+ };
126
+ private readonly timings: Record<string, number[]> = {
127
+ remember: [],
128
+ recall: [],
129
+ consolidate: [],
130
+ invalidate: [],
131
+ };
132
+ private readonly maxTimingSamples: number;
133
+ constructor(config: PluginConfig = {}) {
134
+ super(config);
135
+ const configured = config.max_timing_samples ?? config.maxTimingSamples;
136
+ this.maxTimingSamples = typeof configured === "number" && Number.isFinite(configured) ? configured : 1000;
137
+ }
138
+ override onRemember(_memory: MemoryDict): void {
139
+ this.counters.remember += 1;
140
+ }
141
+ override onRecall(_memory: MemoryDict): void {
142
+ this.counters.recall += 1;
143
+ }
144
+ override onConsolidate(_summary: MemoryDict): void {
145
+ this.counters.consolidate += 1;
146
+ }
147
+ override onInvalidate(_memoryId: string): void {
148
+ this.counters.invalidate += 1;
149
+ }
150
+ recordTiming(event: string, durationMs: number): void {
151
+ const samples = this.timings[event] ?? [];
152
+ if (this.timings[event] === undefined) this.timings[event] = samples;
153
+ samples.push(durationMs);
154
+ if (samples.length > this.maxTimingSamples) samples.shift();
155
+ }
156
+ getCounters(): Record<string, number> {
157
+ return { ...this.counters };
158
+ }
159
+ getTimings(event: string): number[] {
160
+ return (this.timings[event] ?? []).slice();
161
+ }
162
+ getAverageTiming(event: string): number | null {
163
+ const samples = this.timings[event] ?? [];
164
+ if (samples.length === 0) return null;
165
+ let total = 0;
166
+ for (const sample of samples) total += sample;
167
+ return total / samples.length;
168
+ }
169
+ reset(): void {
170
+ for (const key of Object.keys(this.counters) as MetricsEvent[]) this.counters[key] = 0;
171
+ for (const samples of Object.values(this.timings)) samples.length = 0;
172
+ }
173
+ getSummary(): Record<string, unknown> {
174
+ const averages: Record<string, number | null> = {};
175
+ for (const event of Object.keys(this.timings)) averages[event] = this.getAverageTiming(event);
176
+ return { counters: this.getCounters(), averages };
177
+ }
178
+ }
179
+
180
+ export type FilterRule = (item: MemoryDict) => boolean;
181
+
182
+ export class FilterPlugin extends MnemopiPlugin {
183
+ override name = "filter";
184
+ override version = "1.0.0";
185
+ private readonly rules: FilterRule[] = [];
186
+ private readonly blocked: MemoryDict[] = [];
187
+ private readonly maxBlocked: number;
188
+ constructor(config: PluginConfig = {}) {
189
+ super(config);
190
+ const configured = config.max_blocked ?? config.maxBlocked;
191
+ this.maxBlocked = typeof configured === "number" && Number.isFinite(configured) ? configured : 1000;
192
+ }
193
+ addRule(rule: FilterRule): void {
194
+ this.rules.push(rule);
195
+ }
196
+ removeRule(rule: FilterRule): void {
197
+ const index = this.rules.indexOf(rule);
198
+ if (index >= 0) this.rules.splice(index, 1);
199
+ }
200
+ clearRules(): void {
201
+ this.rules.length = 0;
202
+ }
203
+ override onRemember(memory: MemoryDict): void {
204
+ if (!this.passes(memory)) this.block(memory);
205
+ }
206
+ override onRecall(memory: MemoryDict): void {
207
+ if (!this.passes(memory)) this.block(memory);
208
+ }
209
+ override onConsolidate(summary: MemoryDict): void {
210
+ if (!this.passes(summary)) this.block(summary);
211
+ }
212
+ override onInvalidate(_memoryId: string): void {}
213
+ private passes(item: MemoryDict): boolean {
214
+ for (const rule of this.rules) {
215
+ try {
216
+ if (!rule(item)) return false;
217
+ } catch {
218
+ return false;
219
+ }
220
+ }
221
+ return true;
222
+ }
223
+ private block(item: MemoryDict): void {
224
+ this.blocked.push({ timestamp: new Date().toISOString(), item });
225
+ if (this.blocked.length > this.maxBlocked) this.blocked.shift();
226
+ }
227
+ getBlocked(): MemoryDict[] {
228
+ return this.blocked.slice();
229
+ }
230
+ isBlocked(memoryId: string): boolean {
231
+ for (const entry of this.blocked) {
232
+ const item = entry.item as MemoryDict | undefined;
233
+ if (item?.id === memoryId) return true;
234
+ }
235
+ return false;
236
+ }
237
+ }
238
+
239
+ export class CompressionPlugin extends MnemopiPlugin {
240
+ override name = "compression";
241
+ override version = "1.0.0";
242
+ override enabled = false;
243
+ private readonly threshold: number;
244
+ constructor(config: PluginConfig = {}) {
245
+ super(config);
246
+ this.enabled = Boolean(config.enabled);
247
+ const configured = config.threshold_chars ?? config.thresholdChars;
248
+ this.threshold = typeof configured === "number" && Number.isFinite(configured) ? configured : 20;
249
+ }
250
+ compressLines(lines: string[]): string[] {
251
+ if (!this.enabled || this.threshold < 0) return lines;
252
+ return lines;
253
+ }
254
+ override onRemember(_memory: MemoryDict): void {}
255
+ override onRecall(_memory: MemoryDict): void {}
256
+ override onConsolidate(_summary: MemoryDict): void {}
257
+ override onInvalidate(_memoryId: string): void {}
258
+ }
259
+
260
+ export type PluginConstructor<T extends MnemopiPlugin = MnemopiPlugin> = new (config?: PluginConfig) => T;
261
+
262
+ export class PluginManager {
263
+ private readonly registry = new Map<string, PluginConstructor>();
264
+ private readonly instances = new Map<string, MnemopiPlugin>();
265
+ constructor(private readonly pluginDir = DEFAULT_PLUGIN_DIR) {
266
+ this.registerPlugin("logging", LoggingPlugin);
267
+ this.registerPlugin("metrics", MetricsPlugin);
268
+ this.registerPlugin("filter", FilterPlugin);
269
+ this.registerPlugin("compression", CompressionPlugin);
270
+ }
271
+ registerPlugin(name: string, pluginClass: PluginConstructor): void {
272
+ if (typeof pluginClass !== "function" || !(pluginClass.prototype instanceof MnemopiPlugin)) {
273
+ throw new TypeError("pluginClass must be a MnemopiPlugin subclass");
274
+ }
275
+ if (this.registry.has(name)) throw new ValueError(`Plugin '${name}' is already registered`);
276
+ this.registry.set(name, pluginClass);
277
+ }
278
+ loadPlugin(name: string, config: PluginConfig = {}): MnemopiPlugin {
279
+ const pluginClass = this.registry.get(name);
280
+ if (pluginClass === undefined) throw new ValueError(`Plugin '${name}' is not registered`);
281
+ if (this.instances.has(name)) throw new Error(`Plugin '${name}' is already loaded`);
282
+ const instance = new pluginClass(config);
283
+ instance.initialize();
284
+ this.instances.set(name, instance);
285
+ return instance;
286
+ }
287
+ unloadPlugin(name: string): void {
288
+ const instance = this.instances.get(name);
289
+ if (instance === undefined) throw new ValueError(`Plugin '${name}' is not loaded`);
290
+ this.instances.delete(name);
291
+ instance.shutdown();
292
+ }
293
+ listPlugins(): Array<Record<string, unknown>> {
294
+ const result: Array<Record<string, unknown>> = [];
295
+ for (const [name, pluginClass] of this.registry)
296
+ result.push({
297
+ name,
298
+ class: pluginClass.name,
299
+ loaded: this.instances.has(name),
300
+ instance: this.instances.get(name) ?? null,
301
+ });
302
+ return result;
303
+ }
304
+ getPlugin(name: string): MnemopiPlugin | null {
305
+ const loaded = this.instances.get(name);
306
+ if (loaded !== undefined) return loaded;
307
+ if (this.registry.has(name)) return this.loadPlugin(name);
308
+ return null;
309
+ }
310
+ isLoaded(name: string): boolean {
311
+ return this.instances.has(name);
312
+ }
313
+ isRegistered(name: string): boolean {
314
+ return this.registry.has(name);
315
+ }
316
+ loadAll(configs: Record<string, PluginConfig> = {}): MnemopiPlugin[] {
317
+ const loaded: MnemopiPlugin[] = [];
318
+ for (const name of this.registry.keys())
319
+ if (!this.instances.has(name)) loaded.push(this.loadPlugin(name, configs[name] ?? {}));
320
+ return loaded;
321
+ }
322
+ unloadAll(): void {
323
+ for (const name of Array.from(this.instances.keys())) this.unloadPlugin(name);
324
+ }
325
+ discoverPlugins(): string[] {
326
+ if (!existsSync(this.pluginDir)) return [];
327
+ return [];
328
+ }
329
+ notifyRemember(memory: MemoryDict): void {
330
+ for (const instance of this.instances.values())
331
+ if (instance.enabled) {
332
+ try {
333
+ instance.onRemember(memory);
334
+ } catch {}
335
+ }
336
+ }
337
+ notifyRecall(memory: MemoryDict): void {
338
+ for (const instance of this.instances.values())
339
+ if (instance.enabled) {
340
+ try {
341
+ instance.onRecall(memory);
342
+ } catch {}
343
+ }
344
+ }
345
+ notifyConsolidate(summary: MemoryDict): void {
346
+ for (const instance of this.instances.values())
347
+ if (instance.enabled) {
348
+ try {
349
+ instance.onConsolidate(summary);
350
+ } catch {}
351
+ }
352
+ }
353
+ notifyInvalidate(memoryId: string): void {
354
+ for (const instance of this.instances.values())
355
+ if (instance.enabled) {
356
+ try {
357
+ instance.onInvalidate(memoryId);
358
+ } catch {}
359
+ }
360
+ }
361
+ }
362
+
363
+ export class ValueError extends Error {
364
+ override name = "ValueError";
365
+ }
366
+
367
+ let defaultManager: PluginManager | null = null;
368
+ export function getManager(): PluginManager {
369
+ if (defaultManager === null) defaultManager = new PluginManager();
370
+ return defaultManager;
371
+ }
372
+ export function resetManager(): void {
373
+ if (defaultManager !== null) defaultManager.unloadAll();
374
+ defaultManager = null;
375
+ }