@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,12 @@
1
+ export declare class LruCache<K, V> {
2
+ #private;
3
+ readonly maxSize: number;
4
+ constructor(maxSize: number);
5
+ get size(): number;
6
+ has(key: K): boolean;
7
+ get(key: K): V | undefined;
8
+ set(key: K, value: V): this;
9
+ delete(key: K): boolean;
10
+ clear(): void;
11
+ entries(): IterableIterator<[K, V]>;
12
+ }
@@ -0,0 +1,10 @@
1
+ export declare const FACT_MATCH_STOPWORDS: Set<string>;
2
+ export declare const RECALL_SYNONYMS: Readonly<Record<string, readonly string[]>>;
3
+ export declare function hasCjk(text: string): boolean;
4
+ export declare const containsSpacelessCjk: typeof hasCjk;
5
+ export declare function recallTokens(text: string): string[];
6
+ export declare function factMatchTokens(text: string): Set<string>;
7
+ export declare function expandedQueryTokens(tokens: readonly string[]): string[];
8
+ export declare function minimumRecallRelevance(queryTokens: readonly string[]): number;
9
+ export declare function cjkFtsTerms(text: string): string[];
10
+ export declare function ftsQueryTerms(query: string): string[];
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "type": "module",
3
+ "name": "@prometheus-ai/memory",
4
+ "version": "0.5.0",
5
+ "description": "Local SQLite memory engine for Prometheus agents",
6
+ "homepage": "https://prometheus.trivlab.com",
7
+ "author": "Uttam Trivedi",
8
+ "contributors": [
9
+ "Abdias J"
10
+ ],
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/uttamtrivedi/Prometheus.git",
15
+ "directory": "packages/mnemopi"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/uttamtrivedi/Prometheus/issues"
19
+ },
20
+ "keywords": [
21
+ "memory",
22
+ "sqlite",
23
+ "agent",
24
+ "embeddings",
25
+ "mcp"
26
+ ],
27
+ "main": "./src/index.ts",
28
+ "module": "./src/index.ts",
29
+ "types": "./dist/types/index.d.ts",
30
+ "bin": {
31
+ "prometheus-memory": "src/cli.ts"
32
+ },
33
+ "scripts": {
34
+ "check": "biome check . && bun run check:types",
35
+ "check:types": "tsgo -p tsconfig.json --noEmit",
36
+ "lint": "biome lint .",
37
+ "test": "bun test --parallel",
38
+ "fix": "biome check --write --unsafe .",
39
+ "fmt": "biome format --write ."
40
+ },
41
+ "dependencies": {
42
+ "@prometheus-ai/ai": "0.5.0",
43
+ "@prometheus-ai/utils": "0.5.0",
44
+ "fastembed": "2.1.0",
45
+ "lru-cache": "11.5.1",
46
+ "onnxruntime-node": "1.24.3"
47
+ },
48
+ "devDependencies": {
49
+ "@types/bun": "^1.3.14"
50
+ },
51
+ "engines": {
52
+ "bun": ">=1.3.14"
53
+ },
54
+ "files": [
55
+ "src",
56
+ "README.md",
57
+ "dist/types"
58
+ ],
59
+ "exports": {
60
+ ".": {
61
+ "types": "./dist/types/index.d.ts",
62
+ "import": "./src/index.ts"
63
+ },
64
+ "./core": {
65
+ "types": "./dist/types/core/index.d.ts",
66
+ "import": "./src/core/index.ts"
67
+ },
68
+ "./beam": {
69
+ "types": "./dist/types/core/beam/index.d.ts",
70
+ "import": "./src/core/beam/index.ts"
71
+ },
72
+ "./diagnose": {
73
+ "types": "./dist/types/diagnose.d.ts",
74
+ "import": "./src/diagnose.ts"
75
+ },
76
+ "./mcp": {
77
+ "types": "./dist/types/mcp-tools.d.ts",
78
+ "import": "./src/mcp-tools.ts"
79
+ },
80
+ "./cli": {
81
+ "types": "./dist/types/cli.d.ts",
82
+ "import": "./src/cli.ts"
83
+ }
84
+ }
85
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,398 @@
1
+ #!/usr/bin/env bun
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+
5
+ import { dataDir as configuredDataDir, dbPath as configuredDbPath } from "./config";
6
+ import { BankManager, ValueError } from "./core/banks";
7
+ import { BeamMemory } from "./core/beam";
8
+ import type { ImportStats, RecallResult } from "./core/beam/types";
9
+ import { runDiagnostics } from "./diagnose";
10
+ import { main as runMcpMain } from "./mcp-server";
11
+
12
+ export interface CliIo {
13
+ write(data: string): void;
14
+ }
15
+
16
+ export interface CliContext {
17
+ readonly dataDir?: string;
18
+ readonly dbPath?: string;
19
+ readonly memory?: BeamMemory;
20
+ readonly createMemory?: () => BeamMemory;
21
+ readonly stdout?: CliIo;
22
+ readonly stderr?: CliIo;
23
+ }
24
+
25
+ export class CliError extends Error {
26
+ constructor(
27
+ message: string,
28
+ readonly exitCode = 2,
29
+ ) {
30
+ super(message);
31
+ this.name = "CliError";
32
+ }
33
+ }
34
+
35
+ type CommandHandler = (args: readonly string[], context?: CliContext) => number | Promise<number>;
36
+
37
+ function out(context: CliContext | undefined, text = ""): void {
38
+ (context?.stdout ?? Bun.stdout).write(`${text}\n`);
39
+ }
40
+
41
+ function err(context: CliContext | undefined, text = ""): void {
42
+ (context?.stderr ?? Bun.stderr).write(`${text}\n`);
43
+ }
44
+
45
+ function fail(message: string, exitCode = 2): never {
46
+ throw new CliError(`Error: ${message}`, exitCode);
47
+ }
48
+
49
+ function usage(message: string): never {
50
+ throw new CliError(message, 2);
51
+ }
52
+
53
+ function parseFloatArg(value: string, name: string): number {
54
+ const parsed = Number(value);
55
+ if (!Number.isFinite(parsed)) fail(`${name} must be a number: ${value}`);
56
+ return parsed;
57
+ }
58
+
59
+ function parseIntArg(value: string, name: string): number {
60
+ if (!/^[+-]?\d+$/.test(value)) fail(`${name} must be an integer: ${value}`);
61
+ const parsed = Number(value);
62
+ if (!Number.isSafeInteger(parsed)) fail(`${name} must be an integer: ${value}`);
63
+ return parsed;
64
+ }
65
+
66
+ function resolveDataDir(context?: CliContext): string {
67
+ return context?.dataDir ?? configuredDataDir();
68
+ }
69
+
70
+ function resolveDbPath(context?: CliContext): string {
71
+ return context?.dbPath ?? (context?.dataDir ? join(context.dataDir, "prometheus-memory.db") : configuredDbPath());
72
+ }
73
+
74
+ function getMemory(context?: CliContext): { memory: BeamMemory; owned: boolean } {
75
+ if (context?.memory) return { memory: context.memory, owned: false };
76
+ if (context?.createMemory) return { memory: context.createMemory(), owned: true };
77
+ return { memory: new BeamMemory({ dbPath: resolveDbPath(context) }), owned: true };
78
+ }
79
+
80
+ async function withMemory<T>(context: CliContext | undefined, fn: (memory: BeamMemory) => T | Promise<T>): Promise<T> {
81
+ const { memory, owned } = getMemory(context);
82
+ try {
83
+ const result = await fn(memory);
84
+ // Drain background fact-extraction and embedding tasks before close so
85
+ // short-lived owners (e.g. `prometheus-memory store …` / `prometheus-memory sleep …`) don't
86
+ // race the SQLite handle shut from under in-flight `embed()` writes.
87
+ if (owned) await memory.flushExtractions();
88
+ return result;
89
+ } finally {
90
+ if (owned) memory.close();
91
+ }
92
+ }
93
+
94
+ function asCount(value: unknown): number {
95
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
96
+ }
97
+
98
+ export function memoryStats(memory: BeamMemory, dataDir?: string): Record<string, unknown> {
99
+ const working = memory.getWorkingStats();
100
+ const episodic = memory.getEpisodicStats();
101
+ const triples = memory.db.query("SELECT COUNT(*) AS total FROM triples").get() as {
102
+ total: number;
103
+ };
104
+ const banks = new BankManager(dataDir).listBanks();
105
+ return {
106
+ total_memories: asCount(working.total) + asCount(episodic.total),
107
+ beam: {
108
+ working_memory: working,
109
+ episodic_memory: episodic,
110
+ triples: { total: asCount(triples.total) },
111
+ },
112
+ banks,
113
+ database: memory.dbPath ?? ":memory:",
114
+ };
115
+ }
116
+
117
+ function formatImportStats(stats: ImportStats): string {
118
+ const working = stats.working_memory;
119
+ const episodic = stats.episodic_memory;
120
+ const scratchpad = stats.scratchpad;
121
+ const consolidation = stats.consolidation_log;
122
+ return [
123
+ `${asCount(working.inserted)} working`,
124
+ `${asCount(episodic.inserted)} episodic`,
125
+ `${asCount(scratchpad.inserted)} scratchpad`,
126
+ `${asCount(consolidation.inserted)} consolidation`,
127
+ `${asCount(working.skipped) + asCount(episodic.skipped)} skipped`,
128
+ `${asCount(working.overwritten) + asCount(episodic.overwritten)} overwritten`,
129
+ ].join(", ");
130
+ }
131
+
132
+ export const cmdExport: CommandHandler = (args, context) => {
133
+ if (args.length === 0) usage("Usage: prometheus-memory export <file.json>");
134
+ const outputPath = args[0] ?? "";
135
+ return withMemory(context, memory => {
136
+ mkdirSync(dirname(outputPath), { recursive: true });
137
+ const data = memory.exportToDict();
138
+ writeFileSync(outputPath, JSON.stringify(data, null, 2));
139
+ const working = Array.isArray(data.working_memory) ? data.working_memory.length : 0;
140
+ const episodic = Array.isArray(data.episodic_memory) ? data.episodic_memory.length : 0;
141
+ const scratchpad = Array.isArray(data.scratchpad) ? data.scratchpad.length : 0;
142
+ const consolidation = Array.isArray(data.consolidation_log) ? data.consolidation_log.length : 0;
143
+ out(
144
+ context,
145
+ `Exported ${working} working, ${episodic} episodic, ${scratchpad} scratchpad, ${consolidation} consolidation to ${outputPath}`,
146
+ );
147
+ return 0;
148
+ });
149
+ };
150
+
151
+ export const cmdImport: CommandHandler = (args, context) => {
152
+ if (args.length === 0) usage("Usage: prometheus-memory import <file.json>");
153
+ const inputPath = args[0] ?? "";
154
+ if (!existsSync(inputPath)) fail(`Import file not found: ${inputPath}`, 1);
155
+ let parsed: unknown;
156
+ try {
157
+ parsed = JSON.parse(readFileSync(inputPath, "utf8"));
158
+ } catch (error) {
159
+ if (error instanceof SyntaxError) fail(`Invalid JSON: ${error.message}`, 1);
160
+ throw error;
161
+ }
162
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
163
+ fail("Import file must contain a Prometheus Memory export object", 1);
164
+ return withMemory(context, memory => {
165
+ const stats = memory.importFromDict(parsed as Record<string, unknown>);
166
+ out(context, `Imported ${formatImportStats(stats)} from ${inputPath}`);
167
+ return 0;
168
+ });
169
+ };
170
+
171
+ export const cmdMcp: CommandHandler = async args => {
172
+ await runMcpMain(args);
173
+ return 0;
174
+ };
175
+
176
+ export const cmdRemember: CommandHandler = (args, context) => {
177
+ if (args.length === 0) usage("Usage: prometheus-memory store <content> [source] [importance]");
178
+ const content = args[0] ?? "";
179
+ const source = args[1] ?? "cli";
180
+ const importance = args[2] === undefined ? 0.5 : parseFloatArg(args[2], "importance");
181
+ return withMemory(context, memory => {
182
+ const memoryId = memory.remember(content, { source, importance, extractEntities: true });
183
+ out(context, `Stored: ${memoryId}`);
184
+ return 0;
185
+ });
186
+ };
187
+
188
+ export const cmdRecall: CommandHandler = async (args, context) => {
189
+ if (args.length === 0) usage("Usage: prometheus-memory recall <query> [top_k]");
190
+ const query = args[0] ?? "";
191
+ const topK = args[1] === undefined ? 5 : parseIntArg(args[1], "top_k");
192
+ const { memory, owned } = getMemory(context);
193
+ try {
194
+ const results = await memory.recall(query, topK);
195
+ out(context, `\nResults for: ${query}\n`);
196
+ for (const result of results) {
197
+ const content = result.content ?? "";
198
+ const score = typeof result.score === "number" ? result.score : 0;
199
+ out(context, ` ID: ${result.id ?? "?"}`);
200
+ out(context, ` Content: ${content.slice(0, 150)}${content.length > 150 ? "..." : ""}`);
201
+ out(context, ` Score: ${score.toFixed(3)}`);
202
+ if ((result as RecallResult & { entity_match?: unknown }).entity_match) out(context, " [entity match]");
203
+ out(context);
204
+ }
205
+ return 0;
206
+ } finally {
207
+ if (owned) memory.close();
208
+ }
209
+ };
210
+
211
+ export const cmdUpdate: CommandHandler = (args, context) => {
212
+ if (args.length < 2) usage("Usage: prometheus-memory update <memory_id> <new_content> [importance]");
213
+ const memoryId = args[0] ?? "";
214
+ const content = args[1] ?? "";
215
+ const importance = args[2] === undefined ? null : parseFloatArg(args[2], "importance");
216
+ return withMemory(context, memory => {
217
+ if (!memory.updateWorking(memoryId, content, importance)) fail(`Memory not found: ${memoryId}`, 1);
218
+ out(context, `Updated: ${memoryId}`);
219
+ return 0;
220
+ });
221
+ };
222
+
223
+ export const cmdDelete: CommandHandler = (args, context) => {
224
+ if (args.length === 0) usage("Usage: prometheus-memory delete <memory_id>");
225
+ const memoryId = args[0] ?? "";
226
+ return withMemory(context, memory => {
227
+ if (!memory.forgetWorking(memoryId)) fail(`Memory not found: ${memoryId}`, 1);
228
+ out(context, `Deleted: ${memoryId}`);
229
+ return 0;
230
+ });
231
+ };
232
+
233
+ export const cmdStats: CommandHandler = (_args, context) =>
234
+ withMemory(context, memory => {
235
+ const stats = memoryStats(memory, resolveDataDir(context));
236
+ const beam = stats.beam as Record<string, Record<string, unknown>>;
237
+ const wm = beam.working_memory ?? {};
238
+ const ep = beam.episodic_memory ?? {};
239
+ const triples = beam.triples ?? {};
240
+ out(context, "\nPrometheus Memory Stats\n");
241
+ out(context, ` Total memories: ${asCount(stats.total_memories)}`);
242
+ out(context, ` Working memory: ${asCount(wm.total)}`);
243
+ out(context, ` Episodic memory: ${asCount(ep.total)}`);
244
+ out(context, ` Knowledge triples: ${asCount(triples.total)}`);
245
+ const banks = Array.isArray(stats.banks) ? stats.banks : [];
246
+ if (banks.length > 0) out(context, `\n Banks: ${banks.join(", ")}`);
247
+ out(context, ` DB path: ${typeof stats.database === "string" ? stats.database : "N/A"}`);
248
+ return 0;
249
+ });
250
+
251
+ export const cmdSleep: CommandHandler = (_args, context) =>
252
+ withMemory(context, memory => {
253
+ const result = memory.sleepAllSessions(false);
254
+ out(context, `Consolidation complete: ${JSON.stringify(result)}`);
255
+ return 0;
256
+ });
257
+
258
+ export const cmdScratchpad: CommandHandler = (args, context) => {
259
+ if (args.length === 0) usage("Usage: prometheus-memory scratchpad <read|write|clear> [content]");
260
+ const subcmd = args[0];
261
+ return withMemory(context, memory => {
262
+ if (subcmd === "read") {
263
+ for (const item of memory.scratchpadRead() as Array<{ id?: string; content?: string }>) {
264
+ out(context, ` ID: ${item.id ?? "?"}`);
265
+ out(context, ` Content: ${item.content ?? ""}`);
266
+ }
267
+ return 0;
268
+ }
269
+ if (subcmd === "write") {
270
+ if (args.length < 2) usage("Usage: prometheus-memory scratchpad write <content>");
271
+ const id = memory.scratchpadWrite(args[1] ?? "");
272
+ out(context, `Scratchpad stored: ${id}`);
273
+ return 0;
274
+ }
275
+ if (subcmd === "clear") {
276
+ memory.scratchpadClear();
277
+ out(context, "Scratchpad cleared");
278
+ return 0;
279
+ }
280
+ fail(`Unknown scratchpad command: ${subcmd}`);
281
+ });
282
+ };
283
+
284
+ export const cmdBank: CommandHandler = (args, context) => {
285
+ if (args.length === 0) usage("Usage: prometheus-memory bank <list|create|delete> [name]");
286
+ const manager = new BankManager(resolveDataDir(context));
287
+ const subcmd = args[0];
288
+ try {
289
+ if (subcmd === "list") {
290
+ out(context, "\nMemory Banks:\n");
291
+ for (const bank of manager.listBanks()) out(context, ` - ${bank}`);
292
+ return 0;
293
+ }
294
+ if (subcmd === "create") {
295
+ if (args.length < 2) fail("Usage: prometheus-memory bank create <name>");
296
+ const name = args[1] ?? "";
297
+ manager.createBank(name);
298
+ out(context, `Created bank: ${name}`);
299
+ return 0;
300
+ }
301
+ if (subcmd === "delete") {
302
+ if (args.length < 2) fail("Usage: prometheus-memory bank delete <name>");
303
+ const name = args[1] ?? "";
304
+ if (!manager.deleteBank(name)) fail(`Bank not found: ${name}`, 1);
305
+ out(context, `Deleted bank: ${name}`);
306
+ return 0;
307
+ }
308
+ fail(`Unknown bank command: ${subcmd}`);
309
+ } catch (error) {
310
+ if (error instanceof CliError) throw error;
311
+ if (error instanceof ValueError) fail(error.message);
312
+ throw error;
313
+ }
314
+ };
315
+
316
+ export const cmdDiagnose: CommandHandler = (_args, context) => {
317
+ const result = runDiagnostics({
318
+ dbPath: resolveDbPath(context),
319
+ dataDir: resolveDataDir(context),
320
+ });
321
+ out(context, "\nPrometheus Memory Diagnostics\n");
322
+ out(context, ` Checks passed: ${result.checks_passed}/${result.checks_total}`);
323
+ if (result.key_findings.length > 0) {
324
+ out(context, "\n Key findings:");
325
+ for (const finding of result.key_findings) out(context, ` - ${finding}`);
326
+ } else {
327
+ out(context, "\n No issues detected");
328
+ }
329
+ return result.checks_failed === 0 ? 0 : 1;
330
+ };
331
+
332
+ export const COMMANDS: Readonly<Record<string, CommandHandler>> = {
333
+ store: cmdRemember,
334
+ remember: cmdRemember,
335
+ recall: cmdRecall,
336
+ search: cmdRecall,
337
+ update: cmdUpdate,
338
+ edit: cmdUpdate,
339
+ delete: cmdDelete,
340
+ forget: cmdDelete,
341
+ stats: cmdStats,
342
+ export: cmdExport,
343
+ import: cmdImport,
344
+ sleep: cmdSleep,
345
+ consolidate: cmdSleep,
346
+ scratchpad: cmdScratchpad,
347
+ sp: cmdScratchpad,
348
+ bank: cmdBank,
349
+ diagnose: cmdDiagnose,
350
+ doctor: cmdDiagnose,
351
+ mcp: cmdMcp,
352
+ };
353
+
354
+ export function printHelp(context?: CliContext): void {
355
+ out(context, "Prometheus Memory - Local AI Memory System\n");
356
+ out(context, "Usage: prometheus-memory <command> [args]\n");
357
+ out(context, "Commands:");
358
+ out(context, " store <content> [source] [importance] Store a memory");
359
+ out(context, " recall <query> [top_k] Search memories");
360
+ out(context, " update <id> <content> [importance] Update a memory");
361
+ out(context, " delete <id> Delete a memory");
362
+ out(context, " export <file.json> Export memories");
363
+ out(context, " import <file.json> Import memories");
364
+ out(context, " stats Show statistics");
365
+ out(context, " sleep Run consolidation");
366
+ out(context, " scratchpad read|write|clear [content] Manage scratchpad");
367
+ out(context, " diagnose Run diagnostics");
368
+ out(context, " bank list|create|delete [name] Manage memory banks");
369
+ out(context, " mcp [args] Run MCP server");
370
+ }
371
+
372
+ export async function runCli(args: readonly string[] = Bun.argv.slice(2), context?: CliContext): Promise<number> {
373
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h" || args[0] === "help") {
374
+ printHelp(context);
375
+ return 0;
376
+ }
377
+ const command = args[0] ?? "";
378
+ const handler = COMMANDS[command];
379
+ if (!handler) {
380
+ err(context, `Unknown command: ${command}`);
381
+ err(context, "Run 'prometheus-memory --help' for usage.");
382
+ return 2;
383
+ }
384
+ try {
385
+ return await handler(args.slice(1), context);
386
+ } catch (error) {
387
+ if (error instanceof CliError) {
388
+ err(context, error.message);
389
+ return error.exitCode;
390
+ }
391
+ throw error;
392
+ }
393
+ }
394
+
395
+ if (import.meta.main) {
396
+ const code = await runCli();
397
+ process.exit(code);
398
+ }