@aurora-foundation/obsidian-next 0.4.7 → 0.4.9

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 (232) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +628 -190
  3. package/README.md +23 -9
  4. package/dist/auditLog-6WDBDNYL.js +8 -0
  5. package/dist/auditLog-HGPVDSDC.js +8 -0
  6. package/dist/auditLog-TDIKFBM4.js +8 -0
  7. package/dist/auditLog-XC2KY3ZZ.js +8 -0
  8. package/dist/chunk-2I235WNB.js +133 -0
  9. package/dist/chunk-2JWDGXTR.js +42 -0
  10. package/dist/chunk-2NOB6W2B.js +133 -0
  11. package/dist/chunk-3LFKVKKL.js +7199 -0
  12. package/dist/chunk-3U6WHPDX.js +4695 -0
  13. package/dist/chunk-3UCL6RYE.js +7272 -0
  14. package/dist/chunk-4GN2UQLI.js +130 -0
  15. package/dist/chunk-4MW33MZD.js +516 -0
  16. package/dist/chunk-4PUJBUKZ.js +4716 -0
  17. package/dist/chunk-4QHK6H6O.js +130 -0
  18. package/dist/chunk-55CQIHCO.js +133 -0
  19. package/dist/chunk-5LWINFWI.js +676 -0
  20. package/dist/chunk-5OKGLNQW.js +439 -0
  21. package/dist/chunk-5T6ETZEO.js +6183 -0
  22. package/dist/chunk-5WGIFUVL.js +4234 -0
  23. package/dist/chunk-66EW47T3.js +4237 -0
  24. package/dist/chunk-6TXUOTT2.js +581 -0
  25. package/dist/chunk-6YUYSYDA.js +130 -0
  26. package/dist/chunk-74VPNFMX.js +133 -0
  27. package/dist/chunk-77CGJRGV.js +6188 -0
  28. package/dist/chunk-7DS3VT4C.js +7135 -0
  29. package/dist/chunk-7FHX3VBT.js +133 -0
  30. package/dist/chunk-7MHF56YU.js +6178 -0
  31. package/dist/chunk-ABLPMV7G.js +133 -0
  32. package/dist/chunk-B77K6OQZ.js +687 -0
  33. package/dist/chunk-BKOXH66O.js +133 -0
  34. package/dist/chunk-BPP76UN2.js +130 -0
  35. package/dist/chunk-C4D56GRC.js +5936 -0
  36. package/dist/chunk-CCDPY4WE.js +370 -0
  37. package/dist/chunk-CHNVBJN3.js +7272 -0
  38. package/dist/chunk-CKBZI576.js +7229 -0
  39. package/dist/chunk-CW5HBSJ2.js +7198 -0
  40. package/dist/chunk-DGHDJEY7.js +133 -0
  41. package/dist/chunk-DPNIQWKZ.js +439 -0
  42. package/dist/chunk-DU4T3V2T.js +214 -0
  43. package/dist/chunk-DV3WFKNB.js +4679 -0
  44. package/dist/chunk-DZI2OVN2.js +516 -0
  45. package/dist/chunk-E45VILML.js +7198 -0
  46. package/dist/chunk-ECEUUYXC.js +7199 -0
  47. package/dist/chunk-EJRRSHPW.js +685 -0
  48. package/dist/chunk-EMBMLZFE.js +370 -0
  49. package/dist/chunk-EPG5V5OO.js +285 -0
  50. package/dist/chunk-F2R4HXXW.js +130 -0
  51. package/dist/chunk-FK6N66ES.js +581 -0
  52. package/dist/chunk-G3CZKGYA.js +197 -0
  53. package/dist/chunk-GUUPG4A7.js +7111 -0
  54. package/dist/chunk-HBAAUGUN.js +7230 -0
  55. package/dist/chunk-HHFJMK2Q.js +6177 -0
  56. package/dist/chunk-HINRQTCZ.js +196 -0
  57. package/dist/chunk-HRKJ3R2U.js +288 -0
  58. package/dist/chunk-HWVK4CVE.js +439 -0
  59. package/dist/chunk-JEYSADNZ.js +581 -0
  60. package/dist/chunk-JNEIL7UN.js +4252 -0
  61. package/dist/chunk-JTWSK277.js +676 -0
  62. package/dist/chunk-K4CHTTCJ.js +942 -0
  63. package/dist/chunk-K7R5KUDS.js +4695 -0
  64. package/dist/chunk-KNJFOURE.js +7151 -0
  65. package/dist/chunk-KY22FIT3.js +7256 -0
  66. package/dist/chunk-L2OTIJSF.js +4228 -0
  67. package/dist/chunk-LEEBUHP6.js +4655 -0
  68. package/dist/chunk-LK7UP2T7.js +130 -0
  69. package/dist/chunk-LPGNO3PK.js +284 -0
  70. package/dist/chunk-LYQYJMWS.js +133 -0
  71. package/dist/chunk-MBYFJXR3.js +130 -0
  72. package/dist/chunk-N3WX44L3.js +130 -0
  73. package/dist/chunk-N6AQWES3.js +6197 -0
  74. package/dist/chunk-NW4XSTQZ.js +130 -0
  75. package/dist/chunk-NWG2XURH.js +130 -0
  76. package/dist/chunk-O3GF3LJD.js +6142 -0
  77. package/dist/chunk-OHP5LD3Y.js +6188 -0
  78. package/dist/chunk-P5PQSFZT.js +6182 -0
  79. package/dist/chunk-PAADOWNP.js +130 -0
  80. package/dist/chunk-PERGND7L.js +7213 -0
  81. package/dist/chunk-PWA7V4XX.js +179 -0
  82. package/dist/chunk-QGCWEP6L.js +7111 -0
  83. package/dist/chunk-QVT2IHNJ.js +175 -0
  84. package/dist/chunk-QZNGYPMS.js +6161 -0
  85. package/dist/chunk-R6P2E2ZQ.js +207 -0
  86. package/dist/chunk-ROSDMGIL.js +4679 -0
  87. package/dist/chunk-RQZP7IKG.js +196 -0
  88. package/dist/chunk-RUQSPX3U.js +133 -0
  89. package/dist/chunk-S3BYHP5M.js +130 -0
  90. package/dist/chunk-S6GNETVE.js +438 -0
  91. package/dist/chunk-SDT2ZE2R.js +133 -0
  92. package/dist/chunk-SHQBXJFC.js +6166 -0
  93. package/dist/chunk-TJNISYTE.js +42 -0
  94. package/dist/chunk-TJW74HFF.js +130 -0
  95. package/dist/chunk-TPP72DTK.js +7096 -0
  96. package/dist/chunk-UOESII6R.js +42 -0
  97. package/dist/chunk-UWEDGLYJ.js +6142 -0
  98. package/dist/chunk-V5FYNAFX.js +133 -0
  99. package/dist/chunk-VPURF6UT.js +7198 -0
  100. package/dist/chunk-VQH6LWIZ.js +6184 -0
  101. package/dist/chunk-VS22YVX6.js +7111 -0
  102. package/dist/chunk-VSF5KBW7.js +367 -0
  103. package/dist/chunk-VV3JMCKY.js +214 -0
  104. package/dist/chunk-W5L7HOE3.js +133 -0
  105. package/dist/chunk-WFEVQISK.js +676 -0
  106. package/dist/chunk-WJZPSCEP.js +516 -0
  107. package/dist/chunk-WLV4MKEF.js +16 -0
  108. package/dist/chunk-WSEVQFFI.js +5428 -0
  109. package/dist/chunk-X7N2RNR3.js +5428 -0
  110. package/dist/chunk-XKZNMRNO.js +133 -0
  111. package/dist/chunk-Y7BVEC36.js +130 -0
  112. package/dist/chunk-YG7YSNNU.js +4226 -0
  113. package/dist/chunk-YHM62466.js +261 -0
  114. package/dist/chunk-YLTYJLDZ.js +7208 -0
  115. package/dist/chunk-YPMJD4YE.js +56 -0
  116. package/dist/chunk-YTX3FU2A.js +7199 -0
  117. package/dist/chunk-ZEQ3EBBN.js +214 -0
  118. package/dist/chunk-ZIWLQSLK.js +42 -0
  119. package/dist/chunk-ZJELNTEO.js +516 -0
  120. package/dist/chunk-ZOSSVNGK.js +370 -0
  121. package/dist/config-EYK32F2E.js +10 -0
  122. package/dist/config-FJPPPYTY.js +10 -0
  123. package/dist/config-VAHPVILX.js +10 -0
  124. package/dist/context-2YGE4U75.js +10 -0
  125. package/dist/context-5UFVYKES.js +9 -0
  126. package/dist/context-ANZF4J72.js +10 -0
  127. package/dist/context-GLUNCUBQ.js +10 -0
  128. package/dist/context-M5ULPZKQ.js +10 -0
  129. package/dist/context-NYOIRZKV.js +10 -0
  130. package/dist/context-YP2REI6A.js +10 -0
  131. package/dist/database-MP2JBLMF.js +8 -0
  132. package/dist/index.js +6177 -4688
  133. package/dist/keyManager-P2SZONKE.js +8 -0
  134. package/dist/mcp/index.js +127 -47
  135. package/dist/memory-BPGJAL4J.js +13 -0
  136. package/dist/memory-FRQOUI6W.js +13 -0
  137. package/dist/memory-OAMK27IZ.js +13 -0
  138. package/dist/memory-OZ734ALL.js +13 -0
  139. package/dist/memory-PQ2EWRMU.js +13 -0
  140. package/dist/memory-PXL45M6W.js +13 -0
  141. package/dist/memory-QZTBTYPH.js +13 -0
  142. package/dist/migrations-TLJ3WRVW.js +188 -0
  143. package/dist/resume-2NHDK6EI.js +17 -0
  144. package/dist/resume-44L2PDB2.js +17 -0
  145. package/dist/resume-4MXIWUJO.js +7 -0
  146. package/dist/resume-72VJX66I.js +17 -0
  147. package/dist/resume-7ZW4XM3B.js +15 -0
  148. package/dist/resume-AZHYQ657.js +17 -0
  149. package/dist/resume-CNLXSYHV.js +17 -0
  150. package/dist/resume-DPN4Q777.js +16 -0
  151. package/dist/resume-DSFHVNPI.js +15 -0
  152. package/dist/resume-GHLQJJTO.js +17 -0
  153. package/dist/resume-HJ6SBWTF.js +17 -0
  154. package/dist/resume-HRLYHY2L.js +17 -0
  155. package/dist/resume-ISIQFKO6.js +17 -0
  156. package/dist/resume-JQDEA6PS.js +15 -0
  157. package/dist/resume-KP3Y3Y7P.js +17 -0
  158. package/dist/resume-M4KHR5OI.js +17 -0
  159. package/dist/resume-N62OAMBG.js +17 -0
  160. package/dist/resume-NNMA5POT.js +17 -0
  161. package/dist/resume-ODYT3J4H.js +17 -0
  162. package/dist/resume-PCFJXA5O.js +17 -0
  163. package/dist/resume-PLF4XGBD.js +15 -0
  164. package/dist/resume-Q2PFX57V.js +17 -0
  165. package/dist/resume-QB4XI2J5.js +17 -0
  166. package/dist/resume-R5MFTUPF.js +17 -0
  167. package/dist/resume-SVA7223Z.js +17 -0
  168. package/dist/resume-TYKKDJZI.js +17 -0
  169. package/dist/resume-XIS45HKV.js +17 -0
  170. package/dist/resume-YCSEJTU7.js +17 -0
  171. package/dist/resume-YD76GI2J.js +15 -0
  172. package/dist/resume-YDN7EL77.js +17 -0
  173. package/dist/resume-YE7DB4ZA.js +17 -0
  174. package/dist/resume-YKAKOXWV.js +15 -0
  175. package/dist/resume-ZHBCVFDY.js +17 -0
  176. package/dist/scheduler-2CK24A2Q.js +14 -0
  177. package/dist/scheduler-7OAF2XKX.js +14 -0
  178. package/dist/scheduler-AS23AAB5.js +14 -0
  179. package/dist/scheduler-PCOYQJA5.js +14 -0
  180. package/dist/scheduler-V2ECBQPK.js +14 -0
  181. package/dist/scheduler-VEWZ6L7V.js +13 -0
  182. package/dist/scheduler-W37QMGDQ.js +14 -0
  183. package/dist/session-2E2JKPD7.js +15 -0
  184. package/dist/session-2VSF257B.js +14 -0
  185. package/dist/session-4APFTDJU.js +14 -0
  186. package/dist/session-5YS5LNNL.js +16 -0
  187. package/dist/session-6MO5ZPOB.js +16 -0
  188. package/dist/session-6XMGPRTQ.js +14 -0
  189. package/dist/session-7DJR77R7.js +16 -0
  190. package/dist/session-7DQHPWTR.js +14 -0
  191. package/dist/session-ADKIQCR5.js +16 -0
  192. package/dist/session-AOGH2GGI.js +16 -0
  193. package/dist/session-C4W6GDYG.js +16 -0
  194. package/dist/session-DCGNGGMV.js +14 -0
  195. package/dist/session-F5JKZAN2.js +16 -0
  196. package/dist/session-G6F3O2FQ.js +16 -0
  197. package/dist/session-GFBSARRO.js +16 -0
  198. package/dist/session-H5IWAIUI.js +16 -0
  199. package/dist/session-IPFA6AHC.js +14 -0
  200. package/dist/session-IWG2UOAX.js +14 -0
  201. package/dist/session-KJ2K4Y4M.js +14 -0
  202. package/dist/session-KPXFBW6Q.js +14 -0
  203. package/dist/session-KR256UL5.js +16 -0
  204. package/dist/session-M72LJXPR.js +16 -0
  205. package/dist/session-MBK3FODN.js +14 -0
  206. package/dist/session-MOUFAU7G.js +16 -0
  207. package/dist/session-NRC6ZXFQ.js +16 -0
  208. package/dist/session-NRPQMV4K.js +16 -0
  209. package/dist/session-O5IFFJZQ.js +14 -0
  210. package/dist/session-OF5BGKDE.js +16 -0
  211. package/dist/session-OGRZMIM7.js +14 -0
  212. package/dist/session-OJOFAJG3.js +16 -0
  213. package/dist/session-OKU4N3SP.js +16 -0
  214. package/dist/session-P2VAOSFB.js +14 -0
  215. package/dist/session-PKOVZD4M.js +16 -0
  216. package/dist/session-POAIMUVN.js +16 -0
  217. package/dist/session-PSHFONFE.js +16 -0
  218. package/dist/session-QKYVVZFV.js +16 -0
  219. package/dist/session-QPWGBMUS.js +14 -0
  220. package/dist/session-R5UG5PZR.js +14 -0
  221. package/dist/session-RAY6BZRQ.js +16 -0
  222. package/dist/session-S3VATHMU.js +16 -0
  223. package/dist/session-SYTD7RHW.js +14 -0
  224. package/dist/session-UHMMVO4J.js +16 -0
  225. package/dist/session-WEX5K3ZY.js +14 -0
  226. package/dist/session-XFLOXGU3.js +14 -0
  227. package/dist/session-XV2A4HHG.js +14 -0
  228. package/dist/settings-3VPJYD4D.js +8 -0
  229. package/dist/settings-GZTJJTBK.js +8 -0
  230. package/dist/settings-YKJFSKMO.js +8 -0
  231. package/dist/shell-FM34624T.js +8 -0
  232. package/package.json +14 -4
@@ -0,0 +1,516 @@
1
+ import {
2
+ context
3
+ } from "./chunk-EMBMLZFE.js";
4
+ import {
5
+ bus
6
+ } from "./chunk-WQM6FFSD.js";
7
+ import {
8
+ db
9
+ } from "./chunk-FNLWB54Z.js";
10
+
11
+ // src/core/memory.ts
12
+ import fs from "fs/promises";
13
+ import path from "path";
14
+ import os from "os";
15
+ import { pipeline } from "@xenova/transformers";
16
+ import chokidar from "chokidar";
17
+ var MemoryManager = class {
18
+ initialized = false;
19
+ extractor = null;
20
+ watcher = null;
21
+ async init() {
22
+ if (this.initialized) return;
23
+ try {
24
+ this.extractor = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
25
+ } catch (e) {
26
+ bus.emitAgent({ type: "error", message: `[Memory] Embedding pipeline failed to initialize: ${e instanceof Error ? e.message : String(e)}` });
27
+ }
28
+ this.initialized = true;
29
+ this.startWatcher();
30
+ }
31
+ startWatcher() {
32
+ const memoryPath = path.join(os.homedir(), ".obsidian-next", "MEMORY.md");
33
+ if (this.watcher) return;
34
+ this.watcher = chokidar.watch(memoryPath, {
35
+ persistent: true,
36
+ ignoreInitial: true
37
+ });
38
+ this.watcher.on("change", async () => {
39
+ try {
40
+ await this.importFromMarkdown(memoryPath);
41
+ } catch (e) {
42
+ }
43
+ });
44
+ }
45
+ async importFromMarkdown(filePath) {
46
+ try {
47
+ const content = await fs.readFile(filePath, "utf-8");
48
+ const sections = content.split("## ").slice(1);
49
+ const typeMap = {
50
+ "User Preferences": "user_preference",
51
+ "Project Facts": "project_fact",
52
+ "Decision Log": "decision_log",
53
+ "Learned Patterns": "learned_pattern",
54
+ "Daily Summaries": "daily_summary"
55
+ };
56
+ for (const section of sections) {
57
+ const lines = section.split("\n");
58
+ const typeHeader = lines[0].trim();
59
+ const type = typeMap[typeHeader];
60
+ if (!type) continue;
61
+ const memoBlocks = section.split("### ").slice(1);
62
+ for (const block of memoBlocks) {
63
+ const blockLines = block.split("\n");
64
+ const key = blockLines[0].trim();
65
+ const memoContent = blockLines.slice(1).filter((l) => !l.trim().startsWith("*Last updated:")).join("\n").trim();
66
+ if (key && memoContent) {
67
+ await this.store(type, key, memoContent);
68
+ }
69
+ }
70
+ }
71
+ } catch {
72
+ }
73
+ }
74
+ async getEmbedding(text) {
75
+ await this.init();
76
+ if (!this.extractor) throw new Error("Embedding pipeline not initialized");
77
+ const output = await this.extractor(text, { pooling: "mean", normalize: true });
78
+ return Float32Array.from(output.data);
79
+ }
80
+ /**
81
+ * Store a memory/fact
82
+ */
83
+ async store(type, key, content) {
84
+ await this.init();
85
+ const sessionId = context.get().session_id;
86
+ try {
87
+ const embeddingArray = await this.getEmbedding(`${key}: ${content}`);
88
+ const embedding = Buffer.from(embeddingArray.buffer);
89
+ const transaction = db.getDb().transaction(() => {
90
+ const existing = db.getDb().prepare(`
91
+ SELECT id FROM memos WHERE type = ? AND key = ?
92
+ `).get(type, key);
93
+ let memoId;
94
+ if (existing) {
95
+ db.getDb().prepare(`
96
+ UPDATE memos SET content = ?, updated_at = strftime('%s', 'now'), session_id = ?
97
+ WHERE id = ?
98
+ `).run(content, sessionId, existing.id);
99
+ memoId = existing.id;
100
+ } else {
101
+ const result = db.getDb().prepare(`
102
+ INSERT INTO memos (session_id, type, key, content)
103
+ VALUES (?, ?, ?, ?)
104
+ `).run(sessionId, type, key, content);
105
+ memoId = Number(result.lastInsertRowid);
106
+ }
107
+ db.getDb().prepare("DELETE FROM vec_memos WHERE rowid = ?").run(BigInt(memoId));
108
+ db.getDb().prepare(`
109
+ INSERT INTO vec_memos (rowid, embedding)
110
+ VALUES (?, ?)
111
+ `).run(BigInt(memoId), embedding);
112
+ });
113
+ transaction();
114
+ return true;
115
+ } catch (e) {
116
+ console.error("Failed to store memory:", e);
117
+ bus.emitAgent({ type: "error", message: `Memory Store Error: ${e instanceof Error ? e.message : String(e)}` });
118
+ return false;
119
+ }
120
+ }
121
+ /**
122
+ * Recall a specific memory by key
123
+ */
124
+ async recall(key) {
125
+ await this.init();
126
+ try {
127
+ const row = db.getDb().prepare(`
128
+ SELECT id, type, key, content, created_at, updated_at, access_count, last_accessed
129
+ FROM memos
130
+ WHERE key = ?
131
+ ORDER BY updated_at DESC
132
+ LIMIT 1
133
+ `).get(key);
134
+ if (!row) return null;
135
+ return {
136
+ id: row.id,
137
+ type: row.type,
138
+ key: row.key,
139
+ content: row.content,
140
+ created_at: new Date(row.created_at * 1e3).toISOString(),
141
+ updated_at: new Date(row.updated_at * 1e3).toISOString(),
142
+ access_count: row.access_count || 0,
143
+ last_accessed: row.last_accessed ? new Date(row.last_accessed * 1e3).toISOString() : void 0
144
+ };
145
+ } catch (e) {
146
+ bus.emitAgent({ type: "error", message: `[Memory] Recall failed for key "${key}": ${e instanceof Error ? e.message : String(e)}` });
147
+ return null;
148
+ }
149
+ }
150
+ /**
151
+ * Search memories by type or content (Semantic Search)
152
+ */
153
+ async search(query, type) {
154
+ await this.init();
155
+ try {
156
+ const embeddingArray = await this.getEmbedding(query);
157
+ const embedding = Buffer.from(embeddingArray.buffer);
158
+ let sql = `
159
+ SELECT m.id, m.type, m.key, m.content, m.created_at, m.updated_at,
160
+ v.distance
161
+ FROM vec_memos v
162
+ JOIN memos m ON v.rowid = m.id
163
+ WHERE v.embedding MATCH ?
164
+ AND k = 20
165
+ `;
166
+ const params = [embedding];
167
+ if (type) {
168
+ sql = sql.replace("AND k = 20", "AND m.type = ? AND k = 20");
169
+ params.push(type);
170
+ }
171
+ const rows = db.getDb().prepare(sql).all(...params);
172
+ if (rows.length === 0) {
173
+ return this.keywordSearch(query, type);
174
+ }
175
+ return rows.map((row) => ({
176
+ id: row.id,
177
+ type: row.type,
178
+ key: row.key,
179
+ content: row.content,
180
+ created_at: new Date(row.created_at * 1e3).toISOString(),
181
+ updated_at: new Date(row.updated_at * 1e3).toISOString()
182
+ }));
183
+ } catch (e) {
184
+ bus.emitAgent({ type: "thought", content: `[Memory] Semantic search failed, falling back to keyword search.`, hidden: true });
185
+ return this.keywordSearch(query, type);
186
+ }
187
+ }
188
+ async keywordSearch(query, type) {
189
+ try {
190
+ let sql = `
191
+ SELECT id, type, key, content, created_at, updated_at
192
+ FROM memos
193
+ WHERE (key LIKE ? OR content LIKE ?)
194
+ `;
195
+ const params = [`%${query}%`, `%${query}%`];
196
+ if (type) {
197
+ sql += " AND type = ?";
198
+ params.push(type);
199
+ }
200
+ sql += " ORDER BY updated_at DESC LIMIT 20";
201
+ const rows = db.getDb().prepare(sql).all(...params);
202
+ return rows.map((row) => ({
203
+ id: row.id,
204
+ type: row.type,
205
+ key: row.key,
206
+ content: row.content,
207
+ created_at: new Date(row.created_at * 1e3).toISOString(),
208
+ updated_at: new Date(row.updated_at * 1e3).toISOString()
209
+ }));
210
+ } catch (e) {
211
+ return [];
212
+ }
213
+ }
214
+ /**
215
+ * Get all memories of a specific type
216
+ */
217
+ async getByType(type) {
218
+ await this.init();
219
+ try {
220
+ const rows = db.getDb().prepare(`
221
+ SELECT id, type, key, content, created_at, updated_at
222
+ FROM memos
223
+ WHERE type = ?
224
+ ORDER BY updated_at DESC
225
+ `).all(type);
226
+ return rows.map((row) => ({
227
+ id: row.id,
228
+ type: row.type,
229
+ key: row.key,
230
+ content: row.content,
231
+ created_at: new Date(row.created_at * 1e3).toISOString(),
232
+ updated_at: new Date(row.updated_at * 1e3).toISOString()
233
+ }));
234
+ } catch (e) {
235
+ bus.emitAgent({ type: "error", message: `[Memory] Failed to get memories by type "${type}": ${e instanceof Error ? e.message : String(e)}` });
236
+ return [];
237
+ }
238
+ }
239
+ /**
240
+ * Get user preferences summary for context injection
241
+ */
242
+ async getUserContext() {
243
+ await this.init();
244
+ try {
245
+ const prefs = await this.getByType("user_preference");
246
+ const facts = await this.getByType("project_fact");
247
+ if (prefs.length === 0 && facts.length === 0) {
248
+ return "";
249
+ }
250
+ const lines = ["[RECALL]"];
251
+ if (prefs.length > 0) {
252
+ for (const p of prefs.slice(0, 5)) {
253
+ lines.push(`${p.key}: ${p.content}`);
254
+ }
255
+ }
256
+ if (facts.length > 0) {
257
+ for (const f of facts.slice(0, 10)) {
258
+ lines.push(`${f.key}: ${f.content}`);
259
+ }
260
+ }
261
+ if (lines.length === 1) return "";
262
+ return lines.join("\n");
263
+ } catch (e) {
264
+ return "";
265
+ }
266
+ }
267
+ /**
268
+ * Delete a memory
269
+ */
270
+ async forget(key) {
271
+ await this.init();
272
+ try {
273
+ db.getDb().prepare("DELETE FROM memos WHERE key = ?").run(key);
274
+ return true;
275
+ } catch (e) {
276
+ bus.emitAgent({ type: "error", message: `[Memory] Failed to forget key "${key}": ${e instanceof Error ? e.message : String(e)}` });
277
+ return false;
278
+ }
279
+ }
280
+ /**
281
+ * Clear all memories (use with caution)
282
+ */
283
+ async clearAll() {
284
+ await this.init();
285
+ try {
286
+ db.getDb().prepare("DELETE FROM memos").run();
287
+ return true;
288
+ } catch (e) {
289
+ bus.emitAgent({ type: "error", message: `[Memory] Failed to clear all memories: ${e instanceof Error ? e.message : String(e)}` });
290
+ return false;
291
+ }
292
+ }
293
+ /**
294
+ * Get memory statistics
295
+ */
296
+ async getStats() {
297
+ await this.init();
298
+ try {
299
+ const total = db.getDb().prepare("SELECT COUNT(*) as count FROM memos").get();
300
+ const byTypeRows = db.getDb().prepare(`
301
+ SELECT type, COUNT(*) as count FROM memos GROUP BY type
302
+ `).all();
303
+ const byType = {};
304
+ for (const row of byTypeRows) {
305
+ byType[row.type] = row.count;
306
+ }
307
+ return {
308
+ total: total.count,
309
+ byType
310
+ };
311
+ } catch (e) {
312
+ return { total: 0, byType: {} };
313
+ }
314
+ }
315
+ /**
316
+ * Export all memories to a Markdown file for human readability
317
+ */
318
+ async exportToMarkdown() {
319
+ await this.init();
320
+ try {
321
+ const rows = db.getDb().prepare(`
322
+ SELECT type, key, content, updated_at
323
+ FROM memos
324
+ ORDER BY type, key
325
+ `).all();
326
+ if (rows.length === 0) {
327
+ return "No memories to export.";
328
+ }
329
+ let markdown = "# Obsidian Memory Bank\n\n";
330
+ markdown += `Generated on: ${(/* @__PURE__ */ new Date()).toLocaleString()}
331
+
332
+ `;
333
+ const grouped = {};
334
+ for (const row of rows) {
335
+ if (!grouped[row.type]) grouped[row.type] = [];
336
+ grouped[row.type].push(row);
337
+ }
338
+ const typeNames = {
339
+ "user_preference": "User Preferences",
340
+ "project_fact": "Project Facts",
341
+ "decision_log": "Decision Log",
342
+ "learned_pattern": "Learned Patterns",
343
+ "daily_summary": "Daily Summaries"
344
+ };
345
+ for (const type of Object.keys(grouped)) {
346
+ markdown += `## ${typeNames[type] || type}
347
+
348
+ `;
349
+ for (const memo of grouped[type]) {
350
+ markdown += `### ${memo.key}
351
+ `;
352
+ markdown += `${memo.content}
353
+
354
+ `;
355
+ markdown += `*Last updated: ${new Date(memo.updated_at * 1e3).toLocaleString()}*
356
+
357
+ `;
358
+ }
359
+ }
360
+ const { config } = await import("./config-FJPPPYTY.js");
361
+ const cfg = await config.load();
362
+ const exportDir = path.join(os.homedir(), ".obsidian-next");
363
+ const exportPath = path.join(exportDir, "MEMORY.md");
364
+ await fs.mkdir(exportDir, { recursive: true });
365
+ await fs.writeFile(exportPath, markdown, "utf-8");
366
+ return exportPath;
367
+ } catch (error) {
368
+ bus.emitAgent({ type: "error", message: `[Memory] Export failed: ${error.message}` });
369
+ throw new Error(`Failed to export memory: ${error.message}`);
370
+ }
371
+ }
372
+ // ==================== Memory Graph Methods ====================
373
+ /**
374
+ * Add a relationship between two memos
375
+ */
376
+ async addRelation(sourceKey, targetKey, relationType, strength = 1) {
377
+ await this.init();
378
+ try {
379
+ const source = await this.recall(sourceKey);
380
+ const target = await this.recall(targetKey);
381
+ if (!source || !target) {
382
+ return false;
383
+ }
384
+ db.getDb().prepare(`
385
+ INSERT OR REPLACE INTO memo_relations (source_id, target_id, relation_type, strength)
386
+ VALUES (?, ?, ?, ?)
387
+ `).run(source.id, target.id, relationType, Math.max(0, Math.min(1, strength)));
388
+ return true;
389
+ } catch (e) {
390
+ bus.emitAgent({ type: "error", message: `[Memory] Failed to add relation: ${e instanceof Error ? e.message : String(e)}` });
391
+ return false;
392
+ }
393
+ }
394
+ /**
395
+ * Get all relationships for a memo
396
+ */
397
+ async getRelations(key) {
398
+ await this.init();
399
+ try {
400
+ const memo = await this.recall(key);
401
+ if (!memo) return [];
402
+ const rows = db.getDb().prepare(`
403
+ SELECT id, source_id, target_id, relation_type, strength, created_at
404
+ FROM memo_relations
405
+ WHERE source_id = ? OR target_id = ?
406
+ `).all(memo.id, memo.id);
407
+ return rows.map((row) => ({
408
+ id: row.id,
409
+ sourceId: row.source_id,
410
+ targetId: row.target_id,
411
+ relationType: row.relation_type,
412
+ strength: row.strength,
413
+ createdAt: new Date(row.created_at * 1e3).toISOString()
414
+ }));
415
+ } catch (e) {
416
+ return [];
417
+ }
418
+ }
419
+ /**
420
+ * Get related memos with their relationships
421
+ */
422
+ async getRelatedMemos(key) {
423
+ await this.init();
424
+ try {
425
+ const memo = await this.recall(key);
426
+ if (!memo) return [];
427
+ const rows = db.getDb().prepare(`
428
+ SELECT
429
+ m.id, m.type, m.key, m.content, m.created_at, m.updated_at,
430
+ m.access_count, m.last_accessed,
431
+ r.id as rel_id, r.source_id, r.target_id, r.relation_type, r.strength, r.created_at as rel_created
432
+ FROM memo_relations r
433
+ JOIN memos m ON (
434
+ (r.source_id = ? AND r.target_id = m.id) OR
435
+ (r.target_id = ? AND r.source_id = m.id)
436
+ )
437
+ WHERE (r.source_id = ? OR r.target_id = ?)
438
+ ORDER BY r.strength DESC
439
+ `).all(memo.id, memo.id, memo.id, memo.id);
440
+ return rows.map((row) => ({
441
+ memo: {
442
+ id: row.id,
443
+ type: row.type,
444
+ key: row.key,
445
+ content: row.content,
446
+ created_at: new Date(row.created_at * 1e3).toISOString(),
447
+ updated_at: new Date(row.updated_at * 1e3).toISOString(),
448
+ access_count: row.access_count || 0,
449
+ last_accessed: row.last_accessed ? new Date(row.last_accessed * 1e3).toISOString() : void 0
450
+ },
451
+ relation: {
452
+ id: row.rel_id,
453
+ sourceId: row.source_id,
454
+ targetId: row.target_id,
455
+ relationType: row.relation_type,
456
+ strength: row.strength,
457
+ createdAt: new Date(row.rel_created * 1e3).toISOString()
458
+ }
459
+ }));
460
+ } catch (e) {
461
+ return [];
462
+ }
463
+ }
464
+ /**
465
+ * Calculate relevance score with temporal decay
466
+ * Score decays exponentially based on time since last access and access frequency
467
+ */
468
+ getRelevanceScore(memo) {
469
+ const now = Date.now();
470
+ const lastAccessed = memo.last_accessed ? new Date(memo.last_accessed).getTime() : now;
471
+ const accessCount = memo.access_count || 1;
472
+ const halfLife = 7 * 24 * 60 * 60 * 1e3;
473
+ const timeSinceAccess = now - lastAccessed;
474
+ const decayFactor = Math.pow(0.5, timeSinceAccess / halfLife);
475
+ const frequencyBoost = 1 + Math.log10(accessCount + 1) * 0.2;
476
+ return decayFactor * frequencyBoost;
477
+ }
478
+ /**
479
+ * Update access stats for a memo (call when memo is retrieved/used)
480
+ */
481
+ async updateAccessStats(key) {
482
+ await this.init();
483
+ try {
484
+ db.getDb().prepare(`
485
+ UPDATE memos
486
+ SET access_count = COALESCE(access_count, 0) + 1,
487
+ last_accessed = strftime('%s', 'now')
488
+ WHERE key = ?
489
+ `).run(key);
490
+ } catch (e) {
491
+ }
492
+ }
493
+ /**
494
+ * Search with relationship awareness - includes related memos in results
495
+ */
496
+ async searchWithRelations(query, type) {
497
+ await this.init();
498
+ const baseResults = await this.search(query, type);
499
+ const enriched = await Promise.all(baseResults.map(async (memo) => {
500
+ await this.updateAccessStats(memo.key);
501
+ const freshMemo = await this.recall(memo.key);
502
+ const memoWithStats = freshMemo || memo;
503
+ const score = this.getRelevanceScore(memoWithStats);
504
+ const relatedResults = await this.getRelatedMemos(memo.key);
505
+ const related = relatedResults.map((r) => r.memo);
506
+ return { memo: memoWithStats, score, related };
507
+ }));
508
+ return enriched.sort((a, b) => b.score - a.score);
509
+ }
510
+ };
511
+ var memory = new MemoryManager();
512
+
513
+ export {
514
+ MemoryManager,
515
+ memory
516
+ };