@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
@@ -0,0 +1,132 @@
1
+ import { registerAdapter } from "../storage-adapter.js";
2
+ const COLLECTION = "mnemo_memories";
3
+ class QdrantAdapter {
4
+ name = "qdrant";
5
+ client = null;
6
+ url = "http://localhost:6333";
7
+ apiKey;
8
+ vectorDim = 0;
9
+ constructor(config) {
10
+ if (config?.url) this.url = config.url;
11
+ if (config?.apiKey) this.apiKey = config.apiKey;
12
+ }
13
+ async connect() {
14
+ const { QdrantClient } = await import("@qdrant/js-client-rest");
15
+ this.client = new QdrantClient({
16
+ url: this.url,
17
+ ...this.apiKey ? { apiKey: this.apiKey } : {}
18
+ });
19
+ }
20
+ async ensureTable(vectorDimensions) {
21
+ this.vectorDim = vectorDimensions;
22
+ const collections = await this.client.getCollections();
23
+ const exists = collections.collections.some((c) => c.name === COLLECTION);
24
+ if (!exists) {
25
+ await this.client.createCollection(COLLECTION, {
26
+ vectors: { size: vectorDimensions, distance: "Cosine" }
27
+ });
28
+ await this.client.createPayloadIndex(COLLECTION, {
29
+ field_name: "scope",
30
+ field_schema: "keyword"
31
+ });
32
+ await this.client.createPayloadIndex(COLLECTION, {
33
+ field_name: "category",
34
+ field_schema: "keyword"
35
+ });
36
+ }
37
+ }
38
+ async add(records) {
39
+ const points = records.map((r) => ({
40
+ id: r.id,
41
+ vector: r.vector,
42
+ payload: {
43
+ text: r.text,
44
+ timestamp: r.timestamp,
45
+ scope: r.scope,
46
+ importance: r.importance,
47
+ category: r.category,
48
+ metadata: r.metadata
49
+ }
50
+ }));
51
+ await this.client.upsert(COLLECTION, { points });
52
+ }
53
+ async update(id, record) {
54
+ await this.add([record]);
55
+ }
56
+ async delete(filter) {
57
+ const idMatch = filter.match(/id\s*=\s*'([^']+)'/);
58
+ if (idMatch) {
59
+ await this.client.delete(COLLECTION, {
60
+ points: [idMatch[1]]
61
+ });
62
+ }
63
+ }
64
+ async vectorSearch(vector, limit, minScore = 0, scopeFilter) {
65
+ const filter = scopeFilter?.length ? { must: [{ key: "scope", match: { any: scopeFilter } }] } : void 0;
66
+ const results = await this.client.search(COLLECTION, {
67
+ vector,
68
+ limit,
69
+ with_payload: true,
70
+ score_threshold: minScore,
71
+ ...filter ? { filter } : {}
72
+ });
73
+ return results.map((r) => ({
74
+ record: this.toRecord(r.id, r.payload),
75
+ score: r.score
76
+ }));
77
+ }
78
+ async fullTextSearch(_query, _limit, _scopeFilter) {
79
+ return [];
80
+ }
81
+ async query(options) {
82
+ const filter = options.where ? this.parseFilter(options.where) : void 0;
83
+ const result = await this.client.scroll(COLLECTION, {
84
+ limit: options.limit || 100,
85
+ with_payload: true,
86
+ with_vectors: true,
87
+ ...filter ? { filter } : {}
88
+ });
89
+ return result.points.map((p) => this.toRecord(p.id, p.payload, p.vector));
90
+ }
91
+ async count(filter) {
92
+ const result = await this.client.count(COLLECTION, {
93
+ ...filter ? { filter: this.parseFilter(filter) } : {},
94
+ exact: true
95
+ });
96
+ return result.count;
97
+ }
98
+ async ensureFullTextIndex() {
99
+ }
100
+ hasFullTextSearch() {
101
+ return false;
102
+ }
103
+ async close() {
104
+ this.client = null;
105
+ }
106
+ // ── Helpers ──
107
+ toRecord(id, payload, vector) {
108
+ return {
109
+ id,
110
+ text: payload.text ?? "",
111
+ vector: vector ? Array.from(vector) : [],
112
+ timestamp: payload.timestamp ?? 0,
113
+ scope: payload.scope ?? "global",
114
+ importance: payload.importance ?? 0.5,
115
+ category: payload.category ?? "other",
116
+ metadata: payload.metadata ?? "{}"
117
+ };
118
+ }
119
+ parseFilter(where) {
120
+ const scopeMatch = where.match(/scope\s+IN\s*\(([^)]+)\)/i);
121
+ if (scopeMatch) {
122
+ const scopes = scopeMatch[1].split(",").map((s) => s.trim().replace(/'/g, ""));
123
+ return { must: [{ key: "scope", match: { any: scopes } }] };
124
+ }
125
+ return void 0;
126
+ }
127
+ }
128
+ registerAdapter("qdrant", (config) => new QdrantAdapter(config));
129
+ export {
130
+ QdrantAdapter
131
+ };
132
+ //# sourceMappingURL=qdrant.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/adapters/qdrant.ts"],
4
+ "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Qdrant Storage Adapter for Mnemo\n *\n * Requirements:\n * npm install @qdrant/js-client-rest\n *\n * Config:\n * storage: \"qdrant\"\n * storageConfig: { url: \"http://localhost:6333\", apiKey?: \"...\" }\n */\n\nimport type {\n StorageAdapter,\n MemoryRecord,\n SearchResult,\n QueryOptions,\n} from \"../storage-adapter.js\";\nimport { registerAdapter } from \"../storage-adapter.js\";\n\nconst COLLECTION = \"mnemo_memories\";\n\nexport class QdrantAdapter implements StorageAdapter {\n readonly name = \"qdrant\";\n\n private client: any = null;\n private url: string = \"http://localhost:6333\";\n private apiKey?: string;\n private vectorDim = 0;\n\n constructor(config?: Record<string, unknown>) {\n if (config?.url) this.url = config.url as string;\n if (config?.apiKey) this.apiKey = config.apiKey as string;\n }\n\n async connect(): Promise<void> {\n const { QdrantClient } = await import(\"@qdrant/js-client-rest\");\n this.client = new QdrantClient({\n url: this.url,\n ...(this.apiKey ? { apiKey: this.apiKey } : {}),\n });\n }\n\n async ensureTable(vectorDimensions: number): Promise<void> {\n this.vectorDim = vectorDimensions;\n const collections = await this.client.getCollections();\n const exists = collections.collections.some((c: any) => c.name === COLLECTION);\n\n if (!exists) {\n await this.client.createCollection(COLLECTION, {\n vectors: { size: vectorDimensions, distance: \"Cosine\" },\n });\n // Create payload indices for filtering\n await this.client.createPayloadIndex(COLLECTION, {\n field_name: \"scope\",\n field_schema: \"keyword\",\n });\n await this.client.createPayloadIndex(COLLECTION, {\n field_name: \"category\",\n field_schema: \"keyword\",\n });\n }\n }\n\n async add(records: MemoryRecord[]): Promise<void> {\n const points = records.map((r) => ({\n id: r.id,\n vector: r.vector,\n payload: {\n text: r.text,\n timestamp: r.timestamp,\n scope: r.scope,\n importance: r.importance,\n category: r.category,\n metadata: r.metadata,\n },\n }));\n await this.client.upsert(COLLECTION, { points });\n }\n\n async update(id: string, record: MemoryRecord): Promise<void> {\n await this.add([record]);\n }\n\n async delete(filter: string): Promise<void> {\n // Parse simple \"id = 'xxx'\" filter\n const idMatch = filter.match(/id\\s*=\\s*'([^']+)'/);\n if (idMatch) {\n await this.client.delete(COLLECTION, {\n points: [idMatch[1]],\n });\n }\n }\n\n async vectorSearch(\n vector: number[],\n limit: number,\n minScore = 0,\n scopeFilter?: string[],\n ): Promise<SearchResult[]> {\n const filter = scopeFilter?.length\n ? { must: [{ key: \"scope\", match: { any: scopeFilter } }] }\n : undefined;\n\n const results = await this.client.search(COLLECTION, {\n vector,\n limit,\n with_payload: true,\n score_threshold: minScore,\n ...(filter ? { filter } : {}),\n });\n\n return results.map((r: any) => ({\n record: this.toRecord(r.id, r.payload),\n score: r.score,\n }));\n }\n\n async fullTextSearch(\n _query: string,\n _limit: number,\n _scopeFilter?: string[],\n ): Promise<SearchResult[]> {\n // Qdrant doesn't have native BM25 \u2014 fall back to empty\n // Users should pair with a separate FTS engine or use vector search\n return [];\n }\n\n async query(options: QueryOptions): Promise<MemoryRecord[]> {\n const filter = options.where\n ? this.parseFilter(options.where)\n : undefined;\n\n const result = await this.client.scroll(COLLECTION, {\n limit: options.limit || 100,\n with_payload: true,\n with_vectors: true,\n ...(filter ? { filter } : {}),\n });\n\n return result.points.map((p: any) => this.toRecord(p.id, p.payload, p.vector));\n }\n\n async count(filter?: string): Promise<number> {\n const result = await this.client.count(COLLECTION, {\n ...(filter ? { filter: this.parseFilter(filter) } : {}),\n exact: true,\n });\n return result.count;\n }\n\n async ensureFullTextIndex(): Promise<void> {\n // Qdrant uses payload indices, not FTS indices\n // Text search via Qdrant requires external FTS or payload keyword match\n }\n\n hasFullTextSearch(): boolean {\n return false; // Qdrant doesn't have native BM25\n }\n\n async close(): Promise<void> {\n this.client = null;\n }\n\n // \u2500\u2500 Helpers \u2500\u2500\n\n private toRecord(id: string, payload: any, vector?: number[]): MemoryRecord {\n return {\n id,\n text: payload.text ?? \"\",\n vector: vector ? Array.from(vector) : [],\n timestamp: payload.timestamp ?? 0,\n scope: payload.scope ?? \"global\",\n importance: payload.importance ?? 0.5,\n category: payload.category ?? \"other\",\n metadata: payload.metadata ?? \"{}\",\n };\n }\n\n private parseFilter(where: string): any {\n // Simple parser for common filters\n const scopeMatch = where.match(/scope\\s+IN\\s*\\(([^)]+)\\)/i);\n if (scopeMatch) {\n const scopes = scopeMatch[1].split(\",\").map((s) => s.trim().replace(/'/g, \"\"));\n return { must: [{ key: \"scope\", match: { any: scopes } }] };\n }\n return undefined;\n }\n}\n\nregisterAdapter(\"qdrant\", (config) => new QdrantAdapter(config));\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Adaptive Retrieval
3
+ * Determines whether a query needs memory retrieval at all.
4
+ * Skips retrieval for greetings, commands, simple instructions, and system messages.
5
+ * Saves embedding API calls and reduces noise injection.
6
+ */
7
+ /**
8
+ * Determine if a query should skip memory retrieval.
9
+ * Returns true if retrieval should be skipped.
10
+ * @param query The raw prompt text
11
+ * @param minLength Optional minimum length override (if set, overrides built-in thresholds)
12
+ */
13
+ export declare function shouldSkipRetrieval(query: string, minLength?: number): boolean;
14
+ //# sourceMappingURL=adaptive-retrieval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-retrieval.d.ts","sourceRoot":"","sources":["../../src/adaptive-retrieval.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAkDH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CA2B9E"}
@@ -0,0 +1,52 @@
1
+ const SKIP_PATTERNS = [
2
+ // Greetings & pleasantries
3
+ /^(hi|hello|hey|good\s*(morning|afternoon|evening|night)|greetings|yo|sup|howdy|what'?s up)\b/i,
4
+ // System/bot commands
5
+ /^\//,
6
+ // slash commands
7
+ /^(run|build|test|ls|cd|git|npm|pip|docker|curl|cat|grep|find|make|sudo)\b/i,
8
+ // Simple affirmations/negations
9
+ /^(yes|no|yep|nope|ok|okay|sure|fine|thanks|thank you|thx|ty|got it|understood|cool|nice|great|good|perfect|awesome)\s*[.!]?$/i,
10
+ // Continuation prompts
11
+ /^(go ahead|continue|proceed|do it|start|begin|next)\s*[.!]?$/i,
12
+ // Pure emoji
13
+ /^[\p{Emoji}\s]+$/u,
14
+ // Heartbeat/system (match anywhere, not just at start, to handle prefixed formats)
15
+ /HEARTBEAT/i,
16
+ /^\[System/i,
17
+ // Single-word utility pings
18
+ /^(ping|pong|test|debug)\s*[.!?]?$/i
19
+ ];
20
+ const FORCE_RETRIEVE_PATTERNS = [
21
+ /\b(remember|recall|forgot|memory|memories)\b/i,
22
+ /\b(last time|before|previously|earlier|yesterday|ago)\b/i,
23
+ /\b(my (name|email|phone|address|birthday|preference))\b/i,
24
+ /\b(what did (i|we)|did i (tell|say|mention))\b/i
25
+ ];
26
+ function normalizeQuery(query) {
27
+ let s = query.trim();
28
+ const metadataPattern = /^(Conversation info|Sender) \(untrusted metadata\):[\s\S]*?\n\s*\n/gim;
29
+ s = s.replace(metadataPattern, "");
30
+ s = s.trim().replace(/^\[cron:[^\]]+\]\s*/i, "");
31
+ s = s.trim().replace(/^\[[A-Za-z]{3}\s\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}\s[^\]]+\]\s*/, "");
32
+ const result = s.trim();
33
+ return result;
34
+ }
35
+ function shouldSkipRetrieval(query, minLength) {
36
+ const trimmed = normalizeQuery(query);
37
+ if (FORCE_RETRIEVE_PATTERNS.some((p) => p.test(trimmed))) return false;
38
+ if (trimmed.length < 5) return true;
39
+ if (SKIP_PATTERNS.some((p) => p.test(trimmed))) return true;
40
+ if (minLength !== void 0 && minLength > 0) {
41
+ if (trimmed.length < minLength && !trimmed.includes("?")) return true;
42
+ return false;
43
+ }
44
+ const hasCJK = /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(trimmed);
45
+ const defaultMinLength = hasCJK ? 6 : 15;
46
+ if (trimmed.length < defaultMinLength && !trimmed.includes("?")) return true;
47
+ return false;
48
+ }
49
+ export {
50
+ shouldSkipRetrieval
51
+ };
52
+ //# sourceMappingURL=adaptive-retrieval.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/adaptive-retrieval.ts"],
4
+ "sourcesContent": ["// SPDX-License-Identifier: MIT\n/**\n * Adaptive Retrieval\n * Determines whether a query needs memory retrieval at all.\n * Skips retrieval for greetings, commands, simple instructions, and system messages.\n * Saves embedding API calls and reduces noise injection.\n */\n\n// Queries that are clearly NOT memory-retrieval candidates\nconst SKIP_PATTERNS = [\n // Greetings & pleasantries\n /^(hi|hello|hey|good\\s*(morning|afternoon|evening|night)|greetings|yo|sup|howdy|what'?s up)\\b/i,\n // System/bot commands\n /^\\//, // slash commands\n /^(run|build|test|ls|cd|git|npm|pip|docker|curl|cat|grep|find|make|sudo)\\b/i,\n // Simple affirmations/negations\n /^(yes|no|yep|nope|ok|okay|sure|fine|thanks|thank you|thx|ty|got it|understood|cool|nice|great|good|perfect|awesome)\\s*[.!]?$/i,\n // Continuation prompts\n /^(go ahead|continue|proceed|do it|start|begin|next)\\s*[.!]?$/i,\n // Pure emoji\n /^[\\p{Emoji}\\s]+$/u,\n // Heartbeat/system (match anywhere, not just at start, to handle prefixed formats)\n /HEARTBEAT/i,\n /^\\[System/i,\n // Single-word utility pings\n /^(ping|pong|test|debug)\\s*[.!?]?$/i,\n];\n\n// Queries that SHOULD trigger retrieval even if short\nconst FORCE_RETRIEVE_PATTERNS = [\n /\\b(remember|recall|forgot|memory|memories)\\b/i,\n /\\b(last time|before|previously|earlier|yesterday|ago)\\b/i,\n /\\b(my (name|email|phone|address|birthday|preference))\\b/i,\n /\\b(what did (i|we)|did i (tell|say|mention))\\b/i,\n];\n\n/**\n * Normalize the raw prompt before applying skip/force rules.\n */\nfunction normalizeQuery(query: string): string {\n let s = query.trim();\n\n // 1. Strip injected metadata headers.\n const metadataPattern = /^(Conversation info|Sender) \\(untrusted metadata\\):[\\s\\S]*?\\n\\s*\\n/gim;\n s = s.replace(metadataPattern, \"\");\n\n // 2. Strip cron wrapper prefix.\n s = s.trim().replace(/^\\[cron:[^\\]]+\\]\\s*/i, \"\");\n\n // 3. Strip timestamp prefix [Mon 2026-03-02 04:21 GMT+8].\n s = s.trim().replace(/^\\[[A-Za-z]{3}\\s\\d{4}-\\d{2}-\\d{2}\\s\\d{2}:\\d{2}\\s[^\\]]+\\]\\s*/, \"\");\n\n const result = s.trim();\n return result;\n}\n\n/**\n * Determine if a query should skip memory retrieval.\n * Returns true if retrieval should be skipped.\n * @param query The raw prompt text\n * @param minLength Optional minimum length override (if set, overrides built-in thresholds)\n */\nexport function shouldSkipRetrieval(query: string, minLength?: number): boolean {\n const trimmed = normalizeQuery(query);\n\n // Force retrieve if query has memory-related intent (checked FIRST,\n // before length check, so short CJK queries aren't skipped)\n if (FORCE_RETRIEVE_PATTERNS.some(p => p.test(trimmed))) return false;\n\n // Too short to be meaningful\n if (trimmed.length < 5) return true;\n\n // Skip if matches any skip pattern\n if (SKIP_PATTERNS.some(p => p.test(trimmed))) return true;\n\n // If caller provides a custom minimum length, use it\n if (minLength !== undefined && minLength > 0) {\n if (trimmed.length < minLength && !trimmed.includes('?')) return true;\n return false;\n }\n\n // Skip very short non-question messages (likely commands or affirmations)\n // CJK characters carry more meaning per character, so use a lower threshold\n const hasCJK = /[\\u4e00-\\u9fff\\u3040-\\u309f\\u30a0-\\u30ff\\uac00-\\ud7af]/.test(trimmed);\n const defaultMinLength = hasCJK ? 6 : 15;\n if (trimmed.length < defaultMinLength && !trimmed.includes('?')) return true;\n\n // Default: do retrieve\n return false;\n}\n"],
5
+ "mappings": "AASA,MAAM,gBAAgB;AAAA;AAAA,EAEpB;AAAA;AAAA,EAEA;AAAA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAEA;AACF;AAGA,MAAM,0BAA0B;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,eAAe,OAAuB;AAC7C,MAAI,IAAI,MAAM,KAAK;AAGnB,QAAM,kBAAkB;AACxB,MAAI,EAAE,QAAQ,iBAAiB,EAAE;AAGjC,MAAI,EAAE,KAAK,EAAE,QAAQ,wBAAwB,EAAE;AAG/C,MAAI,EAAE,KAAK,EAAE,QAAQ,+DAA+D,EAAE;AAEtF,QAAM,SAAS,EAAE,KAAK;AACtB,SAAO;AACT;AAQO,SAAS,oBAAoB,OAAe,WAA6B;AAC9E,QAAM,UAAU,eAAe,KAAK;AAIpC,MAAI,wBAAwB,KAAK,OAAK,EAAE,KAAK,OAAO,CAAC,EAAG,QAAO;AAG/D,MAAI,QAAQ,SAAS,EAAG,QAAO;AAG/B,MAAI,cAAc,KAAK,OAAK,EAAE,KAAK,OAAO,CAAC,EAAG,QAAO;AAGrD,MAAI,cAAc,UAAa,YAAY,GAAG;AAC5C,QAAI,QAAQ,SAAS,aAAa,CAAC,QAAQ,SAAS,GAAG,EAAG,QAAO;AACjE,WAAO;AAAA,EACT;AAIA,QAAM,SAAS,yDAAyD,KAAK,OAAO;AACpF,QAAM,mBAAmB,SAAS,IAAI;AACtC,MAAI,QAAQ,SAAS,oBAAoB,CAAC,QAAQ,SAAS,GAAG,EAAG,QAAO;AAGxE,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Mnemo Audit Log — GDPR/EU AI Act compliance
3
+ *
4
+ * Records all memory CRUD operations with:
5
+ * - WHO: agent/user identity
6
+ * - WHAT: operation type + affected memory IDs
7
+ * - WHEN: ISO timestamp
8
+ * - WHY: source/trigger (auto-capture, manual, contradiction, etc.)
9
+ *
10
+ * Stored as append-only JSONL file. Supports retention policies.
11
+ */
12
+ export type AuditAction = "create" | "update" | "delete" | "bulk_delete" | "expire" | "merge" | "recall" | "export";
13
+ export interface AuditEntry {
14
+ timestamp: string;
15
+ action: AuditAction;
16
+ actor: string;
17
+ memoryIds: string[];
18
+ scope?: string;
19
+ reason?: string;
20
+ details?: string;
21
+ ip?: string;
22
+ }
23
+ /**
24
+ * Append an audit entry. Fire-and-forget — never blocks the main flow.
25
+ */
26
+ export declare function audit(entry: AuditEntry): Promise<void>;
27
+ /**
28
+ * Convenience: log a memory creation.
29
+ */
30
+ export declare function auditCreate(memoryId: string, actor: string, scope: string, reason: string, textPreview?: string): void;
31
+ /**
32
+ * Convenience: log a memory deletion.
33
+ */
34
+ export declare function auditDelete(memoryIds: string[], actor: string, reason: string): void;
35
+ /**
36
+ * Convenience: log a memory update (e.g., importance change, tier change).
37
+ */
38
+ export declare function auditUpdate(memoryId: string, actor: string, reason: string, details?: string): void;
39
+ /**
40
+ * Convenience: log a memory expiration (contradiction resolution).
41
+ */
42
+ export declare function auditExpire(memoryId: string, actor: string, reason: string, details?: string): void;
43
+ /**
44
+ * Convenience: log a memory recall (for access audit trail).
45
+ */
46
+ export declare function auditRecall(memoryIds: string[], actor: string, query?: string): void;
47
+ /**
48
+ * Read audit log entries for a date range.
49
+ * Useful for compliance exports.
50
+ */
51
+ export declare function readAuditLog(startDate: string, endDate: string): Promise<AuditEntry[]>;
52
+ /**
53
+ * Enable or disable audit logging.
54
+ */
55
+ export declare function setAuditEnabled(enabled: boolean): void;
56
+ //# sourceMappingURL=audit-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log.d.ts","sourceRoot":"","sources":["../../src/audit-log.ts"],"names":[],"mappings":"AACA;;;;;;;;;;GAUG;AASH,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,aAAa,GACb,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAyBD;;GAEG;AACH,wBAAsB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,GACnB,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,IAAI,CAQN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CASN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CASN;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CASN;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,UAAU,EAAE,CAAC,CA4BvB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,139 @@
1
+ import { appendFile, mkdir, readFile, stat } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ const AUDIT_DIR = join(homedir(), ".mnemo", "audit");
5
+ const MAX_FILE_SIZE = 10 * 1024 * 1024;
6
+ let _initialized = false;
7
+ let _currentFile = "";
8
+ let _enabled = true;
9
+ async function ensureDir() {
10
+ if (_initialized) return;
11
+ try {
12
+ await mkdir(AUDIT_DIR, { recursive: true });
13
+ _currentFile = getLogFileName();
14
+ _initialized = true;
15
+ } catch {
16
+ _enabled = false;
17
+ }
18
+ }
19
+ function getLogFileName() {
20
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
21
+ return join(AUDIT_DIR, `audit-${date}.jsonl`);
22
+ }
23
+ async function audit(entry) {
24
+ if (!_enabled) return;
25
+ try {
26
+ await ensureDir();
27
+ const expectedFile = getLogFileName();
28
+ if (expectedFile !== _currentFile) {
29
+ _currentFile = expectedFile;
30
+ }
31
+ try {
32
+ const stats = await stat(_currentFile);
33
+ if (stats.size > MAX_FILE_SIZE) {
34
+ const rotatedName = _currentFile.replace(".jsonl", `-${Date.now()}.jsonl`);
35
+ _currentFile = rotatedName;
36
+ }
37
+ } catch {
38
+ }
39
+ const line = JSON.stringify({
40
+ ...entry,
41
+ timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString()
42
+ }) + "\n";
43
+ await appendFile(_currentFile, line);
44
+ } catch {
45
+ }
46
+ }
47
+ function auditCreate(memoryId, actor, scope, reason, textPreview) {
48
+ audit({
49
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
50
+ action: "create",
51
+ actor,
52
+ memoryIds: [memoryId],
53
+ scope,
54
+ reason,
55
+ details: textPreview ? textPreview.slice(0, 200) : void 0
56
+ }).catch(() => {
57
+ });
58
+ }
59
+ function auditDelete(memoryIds, actor, reason) {
60
+ audit({
61
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
62
+ action: memoryIds.length > 1 ? "bulk_delete" : "delete",
63
+ actor,
64
+ memoryIds,
65
+ reason
66
+ }).catch(() => {
67
+ });
68
+ }
69
+ function auditUpdate(memoryId, actor, reason, details) {
70
+ audit({
71
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
72
+ action: "update",
73
+ actor,
74
+ memoryIds: [memoryId],
75
+ reason,
76
+ details
77
+ }).catch(() => {
78
+ });
79
+ }
80
+ function auditExpire(memoryId, actor, reason, details) {
81
+ audit({
82
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
83
+ action: "expire",
84
+ actor,
85
+ memoryIds: [memoryId],
86
+ reason,
87
+ details
88
+ }).catch(() => {
89
+ });
90
+ }
91
+ function auditRecall(memoryIds, actor, query) {
92
+ audit({
93
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
94
+ action: "recall",
95
+ actor,
96
+ memoryIds,
97
+ reason: "retrieval",
98
+ details: query ? query.slice(0, 200) : void 0
99
+ }).catch(() => {
100
+ });
101
+ }
102
+ async function readAuditLog(startDate, endDate) {
103
+ await ensureDir();
104
+ const entries = [];
105
+ const start = new Date(startDate);
106
+ const end = new Date(endDate);
107
+ const current = new Date(start);
108
+ while (current <= end) {
109
+ const dateStr = current.toISOString().slice(0, 10);
110
+ const filePath = join(AUDIT_DIR, `audit-${dateStr}.jsonl`);
111
+ try {
112
+ const content = await readFile(filePath, "utf8");
113
+ const lines = content.trim().split("\n").filter(Boolean);
114
+ for (const line of lines) {
115
+ try {
116
+ entries.push(JSON.parse(line));
117
+ } catch {
118
+ }
119
+ }
120
+ } catch {
121
+ }
122
+ current.setDate(current.getDate() + 1);
123
+ }
124
+ return entries;
125
+ }
126
+ function setAuditEnabled(enabled) {
127
+ _enabled = enabled;
128
+ }
129
+ export {
130
+ audit,
131
+ auditCreate,
132
+ auditDelete,
133
+ auditExpire,
134
+ auditRecall,
135
+ auditUpdate,
136
+ readAuditLog,
137
+ setAuditEnabled
138
+ };
139
+ //# sourceMappingURL=audit-log.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/audit-log.ts"],
4
+ "sourcesContent": ["// SPDX-License-Identifier: LicenseRef-Mnemo-Pro\n/**\n * Mnemo Audit Log \u2014 GDPR/EU AI Act compliance\n *\n * Records all memory CRUD operations with:\n * - WHO: agent/user identity\n * - WHAT: operation type + affected memory IDs\n * - WHEN: ISO timestamp\n * - WHY: source/trigger (auto-capture, manual, contradiction, etc.)\n *\n * Stored as append-only JSONL file. Supports retention policies.\n */\n\nimport { appendFile, mkdir, readFile, stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst AUDIT_DIR = join(homedir(), \".mnemo\", \"audit\");\nconst MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB per file, then rotate\n\nexport type AuditAction =\n | \"create\"\n | \"update\"\n | \"delete\"\n | \"bulk_delete\"\n | \"expire\"\n | \"merge\"\n | \"recall\"\n | \"export\";\n\nexport interface AuditEntry {\n timestamp: string;\n action: AuditAction;\n actor: string; // agent ID, user ID, or \"system\"\n memoryIds: string[]; // affected memory IDs\n scope?: string;\n reason?: string; // \"auto-capture\", \"contradiction\", \"user-request\", \"decay\", etc.\n details?: string; // additional context (text preview, old\u2192new value, etc.)\n ip?: string; // for API-based access\n}\n\nlet _initialized = false;\nlet _currentFile = \"\";\nlet _enabled = true;\n\n/**\n * Initialize the audit log directory.\n */\nasync function ensureDir(): Promise<void> {\n if (_initialized) return;\n try {\n await mkdir(AUDIT_DIR, { recursive: true });\n _currentFile = getLogFileName();\n _initialized = true;\n } catch {\n _enabled = false;\n }\n}\n\nfunction getLogFileName(): string {\n const date = new Date().toISOString().slice(0, 10); // YYYY-MM-DD\n return join(AUDIT_DIR, `audit-${date}.jsonl`);\n}\n\n/**\n * Append an audit entry. Fire-and-forget \u2014 never blocks the main flow.\n */\nexport async function audit(entry: AuditEntry): Promise<void> {\n if (!_enabled) return;\n\n try {\n await ensureDir();\n\n // Rotate file daily\n const expectedFile = getLogFileName();\n if (expectedFile !== _currentFile) {\n _currentFile = expectedFile;\n }\n\n // Check file size for rotation\n try {\n const stats = await stat(_currentFile);\n if (stats.size > MAX_FILE_SIZE) {\n const rotatedName = _currentFile.replace(\".jsonl\", `-${Date.now()}.jsonl`);\n _currentFile = rotatedName;\n }\n } catch {\n // File doesn't exist yet, that's fine\n }\n\n const line = JSON.stringify({\n ...entry,\n timestamp: entry.timestamp || new Date().toISOString(),\n }) + \"\\n\";\n\n await appendFile(_currentFile, line);\n } catch {\n // Audit log failure should never break the main flow\n }\n}\n\n/**\n * Convenience: log a memory creation.\n */\nexport function auditCreate(\n memoryId: string,\n actor: string,\n scope: string,\n reason: string,\n textPreview?: string,\n): void {\n audit({\n timestamp: new Date().toISOString(),\n action: \"create\",\n actor,\n memoryIds: [memoryId],\n scope,\n reason,\n details: textPreview ? textPreview.slice(0, 200) : undefined,\n }).catch(() => {});\n}\n\n/**\n * Convenience: log a memory deletion.\n */\nexport function auditDelete(\n memoryIds: string[],\n actor: string,\n reason: string,\n): void {\n audit({\n timestamp: new Date().toISOString(),\n action: memoryIds.length > 1 ? \"bulk_delete\" : \"delete\",\n actor,\n memoryIds,\n reason,\n }).catch(() => {});\n}\n\n/**\n * Convenience: log a memory update (e.g., importance change, tier change).\n */\nexport function auditUpdate(\n memoryId: string,\n actor: string,\n reason: string,\n details?: string,\n): void {\n audit({\n timestamp: new Date().toISOString(),\n action: \"update\",\n actor,\n memoryIds: [memoryId],\n reason,\n details,\n }).catch(() => {});\n}\n\n/**\n * Convenience: log a memory expiration (contradiction resolution).\n */\nexport function auditExpire(\n memoryId: string,\n actor: string,\n reason: string,\n details?: string,\n): void {\n audit({\n timestamp: new Date().toISOString(),\n action: \"expire\",\n actor,\n memoryIds: [memoryId],\n reason,\n details,\n }).catch(() => {});\n}\n\n/**\n * Convenience: log a memory recall (for access audit trail).\n */\nexport function auditRecall(\n memoryIds: string[],\n actor: string,\n query?: string,\n): void {\n audit({\n timestamp: new Date().toISOString(),\n action: \"recall\",\n actor,\n memoryIds,\n reason: \"retrieval\",\n details: query ? query.slice(0, 200) : undefined,\n }).catch(() => {});\n}\n\n/**\n * Read audit log entries for a date range.\n * Useful for compliance exports.\n */\nexport async function readAuditLog(\n startDate: string,\n endDate: string,\n): Promise<AuditEntry[]> {\n await ensureDir();\n const entries: AuditEntry[] = [];\n\n const start = new Date(startDate);\n const end = new Date(endDate);\n const current = new Date(start);\n\n while (current <= end) {\n const dateStr = current.toISOString().slice(0, 10);\n const filePath = join(AUDIT_DIR, `audit-${dateStr}.jsonl`);\n\n try {\n const content = await readFile(filePath, \"utf8\");\n const lines = content.trim().split(\"\\n\").filter(Boolean);\n for (const line of lines) {\n try {\n entries.push(JSON.parse(line));\n } catch { /* skip malformed */ }\n }\n } catch {\n // File doesn't exist for this date, skip\n }\n\n current.setDate(current.getDate() + 1);\n }\n\n return entries;\n}\n\n/**\n * Enable or disable audit logging.\n */\nexport function setAuditEnabled(enabled: boolean): void {\n _enabled = enabled;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Long Context Chunking System
3
+ *
4
+ * Goal: split documents that exceed embedding model context limits into smaller,
5
+ * semantically coherent chunks with overlap.
6
+ *
7
+ * Notes:
8
+ * - We use *character counts* as a conservative proxy for tokens.
9
+ * - The embedder triggers this only after a provider throws a context-length error.
10
+ */
11
+ export interface ChunkMetadata {
12
+ startIndex: number;
13
+ endIndex: number;
14
+ length: number;
15
+ }
16
+ export interface ChunkResult {
17
+ chunks: string[];
18
+ metadatas: ChunkMetadata[];
19
+ totalOriginalLength: number;
20
+ chunkCount: number;
21
+ }
22
+ export interface ChunkerConfig {
23
+ /** Maximum characters per chunk. */
24
+ maxChunkSize: number;
25
+ /** Overlap between chunks in characters. */
26
+ overlapSize: number;
27
+ /** Minimum chunk size (except the final chunk). */
28
+ minChunkSize: number;
29
+ /** Attempt to split on sentence boundaries for better semantic coherence. */
30
+ semanticSplit: boolean;
31
+ /** Max lines per chunk before we try to split earlier on a line boundary. */
32
+ maxLinesPerChunk: number;
33
+ }
34
+ export declare const EMBEDDING_CONTEXT_LIMITS: Record<string, number>;
35
+ export declare const DEFAULT_CHUNKER_CONFIG: ChunkerConfig;
36
+ export declare function chunkDocument(text: string, config?: ChunkerConfig): ChunkResult;
37
+ /**
38
+ * Smart chunker that adapts to model context limits.
39
+ *
40
+ * We intentionally pick conservative char limits (70% of the reported limit)
41
+ * since token/char ratios vary.
42
+ */
43
+ export declare function smartChunk(text: string, embedderModel?: string): ChunkResult;
44
+ export default chunkDocument;
45
+ //# sourceMappingURL=chunker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunker.d.ts","sourceRoot":"","sources":["../../src/chunker.ts"],"names":[],"mappings":"AACA;;;;;;;;;GASG;AAMH,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,aAAa,EAAE,OAAO,CAAC;IACvB,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAID,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiB3D,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,aAMpC,CAAC;AAoGF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,aAAsC,GAAG,WAAW,CA6DvG;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,WAAW,CAa5E;AAED,eAAe,aAAa,CAAC"}