@linxiraos/pi-mnemopi 1.0.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 (135) hide show
  1. package/CHANGELOG.md +248 -0
  2. package/README.md +108 -0
  3. package/dist/types/cli.d.ts +35 -0
  4. package/dist/types/config.d.ts +108 -0
  5. package/dist/types/core/aaak.d.ts +55 -0
  6. package/dist/types/core/annotations.d.ts +75 -0
  7. package/dist/types/core/banks.d.ts +33 -0
  8. package/dist/types/core/beam/consolidate.d.ts +38 -0
  9. package/dist/types/core/beam/helpers.d.ts +69 -0
  10. package/dist/types/core/beam/index.d.ts +59 -0
  11. package/dist/types/core/beam/recall.d.ts +52 -0
  12. package/dist/types/core/beam/schema.d.ts +2 -0
  13. package/dist/types/core/beam/store.d.ts +57 -0
  14. package/dist/types/core/beam/types.d.ts +268 -0
  15. package/dist/types/core/binary-vectors.d.ts +54 -0
  16. package/dist/types/core/chat-normalize.d.ts +13 -0
  17. package/dist/types/core/content-sanitizer.d.ts +18 -0
  18. package/dist/types/core/cost-log.d.ts +13 -0
  19. package/dist/types/core/embeddings.d.ts +93 -0
  20. package/dist/types/core/entities.d.ts +9 -0
  21. package/dist/types/core/episodic-graph.d.ts +89 -0
  22. package/dist/types/core/extraction/client.d.ts +35 -0
  23. package/dist/types/core/extraction/diagnostics.d.ts +51 -0
  24. package/dist/types/core/extraction/prompts.d.ts +2 -0
  25. package/dist/types/core/extraction.d.ts +34 -0
  26. package/dist/types/core/fastembed-model-cache.d.ts +2 -0
  27. package/dist/types/core/fastembed-runtime.d.ts +41 -0
  28. package/dist/types/core/index.d.ts +6 -0
  29. package/dist/types/core/llm-backends.d.ts +23 -0
  30. package/dist/types/core/local-llm.d.ts +20 -0
  31. package/dist/types/core/memory.d.ts +186 -0
  32. package/dist/types/core/migrations/e6-triplestore-split.d.ts +17 -0
  33. package/dist/types/core/migrations/index.d.ts +1 -0
  34. package/dist/types/core/mmr.d.ts +8 -0
  35. package/dist/types/core/orchestrator.d.ts +20 -0
  36. package/dist/types/core/patterns.d.ts +61 -0
  37. package/dist/types/core/plugins.d.ts +109 -0
  38. package/dist/types/core/polyphonic-recall.d.ts +66 -0
  39. package/dist/types/core/query-cache.d.ts +45 -0
  40. package/dist/types/core/query-intent.d.ts +20 -0
  41. package/dist/types/core/recall-diagnostics.d.ts +48 -0
  42. package/dist/types/core/runtime-options.d.ts +76 -0
  43. package/dist/types/core/shmr.d.ts +62 -0
  44. package/dist/types/core/streaming.d.ts +136 -0
  45. package/dist/types/core/synonyms.d.ts +46 -0
  46. package/dist/types/core/temporal-parser.d.ts +16 -0
  47. package/dist/types/core/token-counter.d.ts +8 -0
  48. package/dist/types/core/triples.d.ts +63 -0
  49. package/dist/types/core/typed-memory.d.ts +39 -0
  50. package/dist/types/core/vector-index.d.ts +16 -0
  51. package/dist/types/core/vector-math.d.ts +1 -0
  52. package/dist/types/core/veracity-consolidation.d.ts +60 -0
  53. package/dist/types/core/weibull.d.ts +96 -0
  54. package/dist/types/db.d.ts +18 -0
  55. package/dist/types/diagnose.d.ts +24 -0
  56. package/dist/types/dr/index.d.ts +1 -0
  57. package/dist/types/dr/recovery.d.ts +68 -0
  58. package/dist/types/index.d.ts +6 -0
  59. package/dist/types/mcp-server.d.ts +40 -0
  60. package/dist/types/mcp-tools.d.ts +484 -0
  61. package/dist/types/migrations/e6-triplestore-split.d.ts +1 -0
  62. package/dist/types/migrations/index.d.ts +1 -0
  63. package/dist/types/types.d.ts +145 -0
  64. package/dist/types/util/datetime.d.ts +8 -0
  65. package/dist/types/util/env.d.ts +10 -0
  66. package/dist/types/util/ids.d.ts +3 -0
  67. package/dist/types/util/lru.d.ts +12 -0
  68. package/dist/types/util/regex.d.ts +11 -0
  69. package/package.json +108 -0
  70. package/src/cli.ts +398 -0
  71. package/src/config.ts +373 -0
  72. package/src/core/aaak.ts +142 -0
  73. package/src/core/annotations.ts +456 -0
  74. package/src/core/banks.ts +133 -0
  75. package/src/core/beam/consolidate.ts +1132 -0
  76. package/src/core/beam/helpers.ts +831 -0
  77. package/src/core/beam/index.ts +358 -0
  78. package/src/core/beam/recall.ts +1225 -0
  79. package/src/core/beam/schema.ts +426 -0
  80. package/src/core/beam/store.ts +1083 -0
  81. package/src/core/beam/types.ts +303 -0
  82. package/src/core/binary-vectors.ts +317 -0
  83. package/src/core/chat-normalize.ts +160 -0
  84. package/src/core/content-sanitizer.ts +136 -0
  85. package/src/core/cost-log.ts +101 -0
  86. package/src/core/embeddings.ts +624 -0
  87. package/src/core/entities.ts +263 -0
  88. package/src/core/episodic-graph.ts +708 -0
  89. package/src/core/extraction/client.ts +187 -0
  90. package/src/core/extraction/diagnostics.ts +193 -0
  91. package/src/core/extraction/prompts.ts +31 -0
  92. package/src/core/extraction.ts +491 -0
  93. package/src/core/fastembed-model-cache.ts +39 -0
  94. package/src/core/fastembed-runtime.ts +172 -0
  95. package/src/core/index.ts +39 -0
  96. package/src/core/llm-backends.ts +54 -0
  97. package/src/core/local-llm.ts +475 -0
  98. package/src/core/memory.ts +680 -0
  99. package/src/core/migrations/e6-triplestore-split.ts +211 -0
  100. package/src/core/migrations/index.ts +1 -0
  101. package/src/core/mmr.ts +101 -0
  102. package/src/core/orchestrator.ts +62 -0
  103. package/src/core/patterns.ts +484 -0
  104. package/src/core/plugins.ts +375 -0
  105. package/src/core/polyphonic-recall.ts +563 -0
  106. package/src/core/query-cache.ts +351 -0
  107. package/src/core/query-intent.ts +139 -0
  108. package/src/core/recall-diagnostics.ts +157 -0
  109. package/src/core/runtime-options.ts +130 -0
  110. package/src/core/shmr.ts +567 -0
  111. package/src/core/streaming.ts +419 -0
  112. package/src/core/synonyms.ts +197 -0
  113. package/src/core/temporal-parser.ts +363 -0
  114. package/src/core/token-counter.ts +30 -0
  115. package/src/core/triples.ts +452 -0
  116. package/src/core/typed-memory.ts +407 -0
  117. package/src/core/vector-index.ts +83 -0
  118. package/src/core/vector-math.ts +23 -0
  119. package/src/core/veracity-consolidation.ts +477 -0
  120. package/src/core/weibull.ts +124 -0
  121. package/src/db.ts +186 -0
  122. package/src/diagnose.ts +174 -0
  123. package/src/dr/index.ts +1 -0
  124. package/src/dr/recovery.ts +405 -0
  125. package/src/index.ts +33 -0
  126. package/src/mcp-server.ts +155 -0
  127. package/src/mcp-tools.ts +970 -0
  128. package/src/migrations/e6-triplestore-split.ts +1 -0
  129. package/src/migrations/index.ts +1 -0
  130. package/src/types.ts +157 -0
  131. package/src/util/datetime.ts +69 -0
  132. package/src/util/env.ts +65 -0
  133. package/src/util/ids.ts +19 -0
  134. package/src/util/lru.ts +48 -0
  135. package/src/util/regex.ts +165 -0
package/src/db.ts ADDED
@@ -0,0 +1,186 @@
1
+ import { Database } from "bun:sqlite";
2
+ import { mkdirSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { dbPath } from "./config";
5
+
6
+ export type SqlitePageSize = number | "os";
7
+
8
+ const MIN_SQLITE_PAGE_SIZE = 512;
9
+ const MAX_SQLITE_PAGE_SIZE = 65536;
10
+ let detectedSystemPageSize: number | null | undefined;
11
+
12
+ function isValidPageSize(size: number): boolean {
13
+ return (
14
+ Number.isInteger(size) &&
15
+ size >= MIN_SQLITE_PAGE_SIZE &&
16
+ size <= MAX_SQLITE_PAGE_SIZE &&
17
+ (size & (size - 1)) === 0
18
+ );
19
+ }
20
+
21
+ function detectSystemPageSize(): number | undefined {
22
+ if (detectedSystemPageSize !== undefined) return detectedSystemPageSize ?? undefined;
23
+ try {
24
+ const proc = Bun.spawnSync(["getconf", "PAGE_SIZE"], { stdout: "pipe" });
25
+ if (proc.exitCode === 0) {
26
+ const size = Number(proc.stdout.toString().trim());
27
+ if (isValidPageSize(size)) {
28
+ detectedSystemPageSize = size;
29
+ return size;
30
+ }
31
+ }
32
+ } catch {
33
+ /* fall through */
34
+ }
35
+ detectedSystemPageSize = null;
36
+ return undefined;
37
+ }
38
+
39
+ function configuredPageSize(): SqlitePageSize | undefined {
40
+ const raw = process.env.MNEMOPI_DB_PAGE_SIZE?.trim();
41
+ if (!raw) return undefined;
42
+ if (raw.toLowerCase() === "os") return "os";
43
+ const size = Number(raw);
44
+ return isValidPageSize(size) ? size : undefined;
45
+ }
46
+
47
+ function resolvePageSize(requested?: SqlitePageSize): number | undefined {
48
+ const pageSize = requested ?? configuredPageSize();
49
+ if (pageSize === "os") return detectSystemPageSize();
50
+ return pageSize !== undefined && isValidPageSize(pageSize) ? pageSize : undefined;
51
+ }
52
+
53
+ function applyPageSize(db: Database, path: DatabasePath, requested?: SqlitePageSize): void {
54
+ if (path === ":memory:") return;
55
+ const pageSize = resolvePageSize(requested);
56
+ if (pageSize !== undefined) db.exec(`PRAGMA page_size=${pageSize}`);
57
+ }
58
+
59
+ export type DatabasePath = string | ":memory:";
60
+
61
+ export interface OpenDatabaseOptions {
62
+ readonly create?: boolean;
63
+ readonly readwrite?: boolean;
64
+ readonly strict?: boolean;
65
+ readonly loadExtension?: string | readonly string[];
66
+ readonly pragmas?: boolean;
67
+ readonly pageSize?: SqlitePageSize;
68
+ }
69
+
70
+ interface TxState {
71
+ depth: number;
72
+ }
73
+
74
+ const TX_STATE = Symbol("mnemopi.txState");
75
+
76
+ type TxDatabase = Database & { [TX_STATE]?: TxState };
77
+ type ExtensionDatabase = Database & { loadExtension(path: string): void };
78
+
79
+ export function openDatabase(path: DatabasePath = dbPath(), options: OpenDatabaseOptions = {}): Database {
80
+ if (path !== ":memory:") mkdirSync(dirname(path), { recursive: true });
81
+ const db = new Database(path, {
82
+ create: options.create ?? true,
83
+ readwrite: options.readwrite ?? true,
84
+ strict: options.strict ?? true,
85
+ });
86
+ if (options.pragmas !== false) enablePragmas(db, path, options.pageSize);
87
+ else if (options.readwrite !== false) applyPageSize(db, path, options.pageSize);
88
+ if (options.loadExtension !== undefined) loadExtensions(db, options.loadExtension);
89
+ return db;
90
+ }
91
+
92
+ export function enablePragmas(db: Database, path?: DatabasePath, pageSize?: SqlitePageSize): void {
93
+ db.exec("PRAGMA foreign_keys=ON");
94
+ db.exec("PRAGMA busy_timeout=5000");
95
+ if (path !== ":memory:") {
96
+ applyPageSize(db, path ?? dbPath(), pageSize);
97
+ db.exec("PRAGMA journal_mode=WAL");
98
+ }
99
+ }
100
+
101
+ export function loadExtensions(db: Database, extensions: string | readonly string[]): void {
102
+ if (typeof extensions === "string") {
103
+ if (extensions) (db as ExtensionDatabase).loadExtension(extensions);
104
+ return;
105
+ }
106
+ for (const extension of extensions) {
107
+ if (extension) (db as ExtensionDatabase).loadExtension(extension);
108
+ }
109
+ }
110
+
111
+ export function transaction<T>(db: Database, fn: () => T): T {
112
+ const txDb = db as TxDatabase;
113
+ let state = txDb[TX_STATE];
114
+ if (state !== undefined && state.depth > 0) {
115
+ state.depth++;
116
+ try {
117
+ return fn();
118
+ } finally {
119
+ state.depth--;
120
+ }
121
+ }
122
+
123
+ state = { depth: 1 };
124
+ txDb[TX_STATE] = state;
125
+ db.exec("BEGIN DEFERRED");
126
+ try {
127
+ const result = fn();
128
+ state.depth = 0;
129
+ db.exec("COMMIT");
130
+ return result;
131
+ } catch (error) {
132
+ state.depth = 0;
133
+ try {
134
+ db.exec("ROLLBACK");
135
+ } catch {
136
+ // Preserve the original error; rollback can fail if SQLite already closed the transaction.
137
+ }
138
+ throw error;
139
+ } finally {
140
+ delete txDb[TX_STATE];
141
+ }
142
+ }
143
+
144
+ export const deferredTransaction = transaction;
145
+
146
+ export async function transactionAsync<T>(db: Database, fn: () => Promise<T>): Promise<T> {
147
+ const txDb = db as TxDatabase;
148
+ let state = txDb[TX_STATE];
149
+ if (state !== undefined && state.depth > 0) {
150
+ state.depth++;
151
+ try {
152
+ return await fn();
153
+ } finally {
154
+ state.depth--;
155
+ }
156
+ }
157
+
158
+ state = { depth: 1 };
159
+ txDb[TX_STATE] = state;
160
+ db.exec("BEGIN DEFERRED");
161
+ try {
162
+ const result = await fn();
163
+ state.depth = 0;
164
+ db.exec("COMMIT");
165
+ return result;
166
+ } catch (error) {
167
+ state.depth = 0;
168
+ try {
169
+ db.exec("ROLLBACK");
170
+ } catch {
171
+ // Preserve the original error; rollback can fail if SQLite already closed the transaction.
172
+ }
173
+ throw error;
174
+ } finally {
175
+ delete txDb[TX_STATE];
176
+ }
177
+ }
178
+
179
+ export function closeQuietly(db: Database | undefined | null): void {
180
+ if (db === undefined || db === null) return;
181
+ try {
182
+ db.close();
183
+ } catch {
184
+ // Best-effort cleanup.
185
+ }
186
+ }
@@ -0,0 +1,174 @@
1
+ import type { Database } from "bun:sqlite";
2
+ import { existsSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+
5
+ import { dataDir as configuredDataDir, dbPath as configuredDbPath } from "./config";
6
+ import { initBeam } from "./core/beam";
7
+ import { closeQuietly, openDatabase } from "./db";
8
+
9
+ export interface DiagnosticEntry {
10
+ readonly ts: string;
11
+ readonly category: string;
12
+ readonly check: string;
13
+ readonly status: string;
14
+ readonly detail?: string;
15
+ }
16
+
17
+ export interface DiagnosticSummary {
18
+ readonly checks_total: number;
19
+ readonly checks_passed: number;
20
+ readonly checks_failed: number;
21
+ readonly key_findings: string[];
22
+ readonly entries: DiagnosticEntry[];
23
+ readonly database: string;
24
+ }
25
+
26
+ export interface DiagnosticOptions {
27
+ readonly db?: Database;
28
+ readonly dbPath?: string;
29
+ readonly dataDir?: string;
30
+ readonly initialize?: boolean;
31
+ }
32
+
33
+ type CountRow = { count: number };
34
+ type IntegrityRow = { integrity_check: string };
35
+ type TableRow = { name: string };
36
+ type ColumnRow = { name: string };
37
+
38
+ const REQUIRED_TABLES = [
39
+ "working_memory",
40
+ "episodic_memory",
41
+ "scratchpad",
42
+ "fts_working",
43
+ "fts_episodes",
44
+ "memoria_facts",
45
+ "memoria_timelines",
46
+ "memoria_kg",
47
+ "memoria_instructions",
48
+ "memoria_preferences",
49
+ "consolidation_log",
50
+ "annotations",
51
+ "triples",
52
+ ] as const;
53
+
54
+ const REQUIRED_COLUMNS: Readonly<Record<string, readonly string[]>> = {
55
+ working_memory: ["id", "content", "source", "timestamp", "session_id", "importance"],
56
+ episodic_memory: ["id", "content", "source", "timestamp", "session_id", "importance"],
57
+ scratchpad: ["id", "content", "session_id"],
58
+ triples: ["id", "subject", "predicate", "object"],
59
+ annotations: ["id", "memory_id", "kind", "value"],
60
+ };
61
+
62
+ function nowIso(): string {
63
+ return new Date().toISOString();
64
+ }
65
+
66
+ function hasTable(db: Database, table: string): boolean {
67
+ return (
68
+ (db
69
+ .query("SELECT name FROM sqlite_master WHERE type IN ('table', 'view') AND name = ? LIMIT 1")
70
+ .get(table) as TableRow | null) !== null
71
+ );
72
+ }
73
+
74
+ function tableColumns(db: Database, table: string): Set<string> {
75
+ return new Set((db.query(`PRAGMA table_info(${table})`).all() as ColumnRow[]).map(row => row.name));
76
+ }
77
+
78
+ function safeCount(db: Database, table: string): number | null {
79
+ if (!hasTable(db, table)) return null;
80
+ return (db.query(`SELECT COUNT(*) AS count FROM ${table}`).get() as CountRow).count;
81
+ }
82
+
83
+ function safeEnv(name: string): string {
84
+ return process.env[name] ? "set" : "unset";
85
+ }
86
+
87
+ function passStatus(status: string): boolean {
88
+ return status === "OK" || status === "YES" || status === "set" || status === "0";
89
+ }
90
+
91
+ function failStatus(status: string): boolean {
92
+ return status === "MISSING" || status === "NO" || status === "ERROR" || status === "FAIL";
93
+ }
94
+
95
+ export function inspectDatabase(options: DiagnosticOptions = {}): DiagnosticSummary {
96
+ const path = options.dbPath ?? configuredDbPath();
97
+ const entries: DiagnosticEntry[] = [];
98
+ const log = (category: string, check: string, status: string, detail = ""): void => {
99
+ entries.push({ ts: nowIso(), category, check, status, detail });
100
+ };
101
+
102
+ log("env", "bun_version", Bun.version);
103
+ log("env", "platform", `${process.platform}-${process.arch}`);
104
+ log("env", "MNEMOPI_DATA_DIR", safeEnv("MNEMOPI_DATA_DIR"));
105
+ log("env", "MNEMOPI_VEC_TYPE", safeEnv("MNEMOPI_VEC_TYPE"));
106
+ log("db", "db_path", "OK", path);
107
+ log("db", "data_dir", "OK", options.dataDir ?? configuredDataDir());
108
+ log("db", "data_dir_parent", existsSync(dirname(path)) ? "OK" : "MISSING", dirname(path));
109
+
110
+ let db = options.db;
111
+ let owned = false;
112
+ try {
113
+ if (!db) {
114
+ db = openDatabase(path);
115
+ owned = true;
116
+ }
117
+ if (options.initialize !== false) initBeam(db);
118
+
119
+ const integrity = db.query("PRAGMA integrity_check").get() as IntegrityRow;
120
+ log("db", "integrity_check", integrity.integrity_check === "ok" ? "OK" : "FAIL", integrity.integrity_check);
121
+
122
+ for (const table of REQUIRED_TABLES) {
123
+ log("schema", `table:${table}`, hasTable(db, table) ? "OK" : "MISSING");
124
+ }
125
+ for (const table in REQUIRED_COLUMNS) {
126
+ if (!hasTable(db, table)) continue;
127
+ const columns = REQUIRED_COLUMNS[table];
128
+ if (!columns) continue;
129
+ const present = tableColumns(db, table);
130
+ const missing = columns.filter(column => !present.has(column));
131
+ log(
132
+ "schema",
133
+ `columns:${table}`,
134
+ missing.length === 0 ? "OK" : "MISSING",
135
+ missing.length === 0 ? `${present.size} columns` : `missing=${missing.join(",")}`,
136
+ );
137
+ }
138
+
139
+ for (const table of ["working_memory", "episodic_memory", "scratchpad", "triples", "annotations"] as const) {
140
+ const count = safeCount(db, table);
141
+ log("db", `${table}_count`, count === null ? "MISSING" : String(count));
142
+ }
143
+ } catch (error) {
144
+ log("db", "open_or_inspect", "ERROR", error instanceof Error ? error.message : String(error));
145
+ } finally {
146
+ if (owned) closeQuietly(db);
147
+ }
148
+
149
+ const keyFindings: string[] = [];
150
+ for (const entry of entries) {
151
+ if (entry.status === "MISSING") keyFindings.push(`${entry.check} missing`);
152
+ else if (entry.status === "FAIL" || entry.status === "ERROR") {
153
+ keyFindings.push(`${entry.check}: ${entry.detail ?? entry.status}`);
154
+ }
155
+ }
156
+
157
+ return {
158
+ checks_total: entries.length,
159
+ checks_passed: entries.filter(entry => passStatus(entry.status) || /^\d+$/.test(entry.status)).length,
160
+ checks_failed: entries.filter(entry => failStatus(entry.status)).length,
161
+ key_findings: keyFindings,
162
+ entries,
163
+ database: path,
164
+ };
165
+ }
166
+
167
+ export function runDiagnostics(options: DiagnosticOptions = {}): DiagnosticSummary {
168
+ return inspectDatabase(options);
169
+ }
170
+ if (import.meta.main) {
171
+ const summary = runDiagnostics();
172
+ console.log(JSON.stringify(summary, null, 2));
173
+ process.exit(summary.checks_failed === 0 ? 0 : 1);
174
+ }
@@ -0,0 +1 @@
1
+ export * from "./recovery";