@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,133 @@
1
+ import {
2
+ history,
3
+ session,
4
+ tasks
5
+ } from "./chunk-5T6ETZEO.js";
6
+ import {
7
+ context
8
+ } from "./chunk-DPNIQWKZ.js";
9
+ import {
10
+ bus
11
+ } from "./chunk-WQM6FFSD.js";
12
+
13
+ // src/commands/resume.ts
14
+ import path from "path";
15
+ var resumeCommand = async (args) => {
16
+ if (args[0] === "--delete" || args[0] === "-d") {
17
+ const sessionId = args[1];
18
+ if (!sessionId) {
19
+ bus.emitAgent({
20
+ type: "error",
21
+ message: "Usage: /resume --delete <session_id>"
22
+ });
23
+ return;
24
+ }
25
+ const deleted = await session.delete(sessionId);
26
+ if (deleted) {
27
+ bus.emitAgent({
28
+ type: "done",
29
+ summary: `Session ${sessionId} deleted.`
30
+ });
31
+ } else {
32
+ bus.emitAgent({
33
+ type: "error",
34
+ message: `Session ${sessionId} not found.`
35
+ });
36
+ }
37
+ return;
38
+ }
39
+ if (args[0] === "--last" || args[0] === "-l") {
40
+ const sessions = await session.list();
41
+ if (sessions.length === 0) {
42
+ bus.emitAgent({
43
+ type: "error",
44
+ message: "No saved sessions found."
45
+ });
46
+ return;
47
+ }
48
+ args[0] = sessions[0].id;
49
+ }
50
+ if (!args[0]) {
51
+ const sessions = await session.list();
52
+ if (sessions.length === 0) {
53
+ bus.emitAgent({
54
+ type: "thought",
55
+ content: "No saved sessions found.\n\nSessions are created when you run /exit."
56
+ });
57
+ bus.emitAgent({
58
+ type: "done",
59
+ summary: "No sessions available."
60
+ });
61
+ return;
62
+ }
63
+ const content2 = [
64
+ "Saved Session Registry",
65
+ ...sessions.slice(0, 10).map((s) => {
66
+ const date = new Date(s.savedAt);
67
+ const dateStr = date.toLocaleDateString();
68
+ const timeStr = date.toLocaleTimeString([], {
69
+ hour: "2-digit",
70
+ minute: "2-digit"
71
+ });
72
+ const workspaceName = path.basename(s.workspace);
73
+ return [
74
+ ` \u23BF [${s.id}]`,
75
+ ` \u23BF Date ${dateStr} ${timeStr}`,
76
+ ` \u23BF Workspace ${workspaceName}`,
77
+ s.task ? ` \u23BF Task ${s.task}` : null,
78
+ ` \u23BF Activity ${s.filesModified} files handled`,
79
+ ""
80
+ ].filter(Boolean).join("\n");
81
+ }),
82
+ sessions.length > 10 ? ` ... and ${sessions.length - 10} more sessions
83
+ ` : "",
84
+ " [Usage]",
85
+ " \u23BF /resume <id> Restore session",
86
+ " \u23BF /resume --last Restore latest",
87
+ ""
88
+ ].join("\n");
89
+ bus.emitAgent({
90
+ type: "thought",
91
+ content: content2
92
+ });
93
+ bus.emitAgent({
94
+ type: "done",
95
+ summary: `${sessions.length} session(s) available.`
96
+ });
97
+ return;
98
+ }
99
+ const sessionIdArg = args[0];
100
+ const result = await session.restore(sessionIdArg);
101
+ if (!result.success) {
102
+ bus.emitAgent({
103
+ type: "error",
104
+ message: result.error || "Failed to restore session"
105
+ });
106
+ return;
107
+ }
108
+ const currentTask = tasks.get();
109
+ const currentContext = context.get();
110
+ const content = [
111
+ "Session Restored Successfully",
112
+ ` \u23BF ID ${sessionIdArg}`,
113
+ ` \u23BF Root ${path.basename(process.cwd())}`,
114
+ "",
115
+ " [Restored State]",
116
+ ` \u23BF Context ${currentContext.files_read.length} files in set`,
117
+ ` \u23BF History ${(await history.load()).length} events rehydrated`,
118
+ ` \u23BF Task ${currentTask?.title || "None"}`,
119
+ ""
120
+ ].join("\n");
121
+ bus.emitAgent({
122
+ type: "thought",
123
+ content
124
+ });
125
+ bus.emitAgent({
126
+ type: "done",
127
+ summary: `Session ${sessionIdArg} restored.`
128
+ });
129
+ };
130
+
131
+ export {
132
+ resumeCommand
133
+ };
@@ -0,0 +1,439 @@
1
+ import {
2
+ config
3
+ } from "./chunk-G3CZKGYA.js";
4
+ import {
5
+ settings
6
+ } from "./chunk-HRKJ3R2U.js";
7
+ import {
8
+ bus
9
+ } from "./chunk-WQM6FFSD.js";
10
+ import {
11
+ db
12
+ } from "./chunk-R6P2E2ZQ.js";
13
+
14
+ // src/core/context.ts
15
+ import path from "path";
16
+ var CONTEXT_CONFIG = {
17
+ DECAY_HALF_LIFE_MS: 36e5,
18
+ // 1 hour - files lose half their score every hour
19
+ MAX_WORKING_SET_SIZE: 50,
20
+ // Limit working set to prevent unbounded growth
21
+ IMPORTANCE_MODIFIED: 2,
22
+ // 2x weight for modified files
23
+ IMPORTANCE_ENTRY_POINT: 1.5,
24
+ // Higher weight for index.ts, main.ts, etc.
25
+ IMPORTANCE_RECENT_EDIT: 1.3,
26
+ // Files edited in last 5 interactions
27
+ TOKEN_ESTIMATE_PER_LINE: 4
28
+ // Rough estimate: 4 tokens per line
29
+ };
30
+ var ENTRY_POINT_PATTERNS = [
31
+ /^index\.(ts|tsx|js|jsx)$/,
32
+ /^main\.(ts|tsx|js|jsx)$/,
33
+ /^app\.(ts|tsx|js|jsx)$/,
34
+ /^server\.(ts|tsx|js|jsx)$/
35
+ ];
36
+ function calculateRankScore(accessCount, lastAccessed, isModified, isEntryPoint) {
37
+ const ageMs = Date.now() - lastAccessed;
38
+ const decayFactor = Math.pow(0.5, ageMs / CONTEXT_CONFIG.DECAY_HALF_LIFE_MS);
39
+ let importanceMultiplier = 1;
40
+ if (isModified) importanceMultiplier *= CONTEXT_CONFIG.IMPORTANCE_MODIFIED;
41
+ if (isEntryPoint)
42
+ importanceMultiplier *= CONTEXT_CONFIG.IMPORTANCE_ENTRY_POINT;
43
+ return accessCount * decayFactor * importanceMultiplier;
44
+ }
45
+ function isEntryPointFile(filePath) {
46
+ const filename = path.basename(filePath);
47
+ return ENTRY_POINT_PATTERNS.some((pattern) => pattern.test(filename));
48
+ }
49
+ function generateSessionId() {
50
+ return Date.now().toString(36) + Math.random().toString(36).slice(2, 8);
51
+ }
52
+ function createEmptyContext() {
53
+ const now = (/* @__PURE__ */ new Date()).toISOString();
54
+ return {
55
+ session_id: generateSessionId(),
56
+ mode: "safe",
57
+ current_task: null,
58
+ files_read: [],
59
+ files_modified: [],
60
+ working_set: [],
61
+ last_action: null,
62
+ created_at: now,
63
+ updated_at: now
64
+ };
65
+ }
66
+ var ContextManager = class {
67
+ ctx = createEmptyContext();
68
+ constructor() {
69
+ }
70
+ async init() {
71
+ try {
72
+ const lastSession = db.getDb().prepare(
73
+ `
74
+ SELECT id, created_at, source, permissions
75
+ FROM sessions
76
+ ORDER BY created_at DESC
77
+ LIMIT 1
78
+ `
79
+ ).get();
80
+ if (lastSession) {
81
+ await this.load(lastSession.id);
82
+ } else {
83
+ this.ctx = createEmptyContext();
84
+ await this.save();
85
+ }
86
+ } catch (e) {
87
+ bus.emitAgent({
88
+ type: "error",
89
+ message: `[Context] Failed to init from DB: ${e instanceof Error ? e.message : String(e)}`
90
+ });
91
+ this.ctx = createEmptyContext();
92
+ await this.save();
93
+ }
94
+ }
95
+ async load(sessionId) {
96
+ if (!sessionId) return;
97
+ try {
98
+ const session = db.getDb().prepare(`SELECT * FROM sessions WHERE id = ?`).get(sessionId);
99
+ if (!session) return;
100
+ const workingSetRows = db.getDb().prepare(
101
+ `
102
+ SELECT file_path
103
+ FROM working_set
104
+ WHERE session_id = ?
105
+ ORDER BY rank_score DESC
106
+ `
107
+ ).all(sessionId);
108
+ this.ctx = {
109
+ session_id: session.id,
110
+ mode: "safe",
111
+ // Mode loaded from settings usually, but DB could store it if we added column
112
+ current_task: null,
113
+ // Tasks are now in 'tasks' table
114
+ files_read: [],
115
+ // Reset on load, or we could store this in DB if needed
116
+ files_modified: [],
117
+ working_set: workingSetRows.map((r) => r.file_path),
118
+ last_action: null,
119
+ created_at: new Date(session.created_at).toISOString(),
120
+ updated_at: (/* @__PURE__ */ new Date()).toISOString()
121
+ // Refreshed
122
+ };
123
+ await this.syncModeFromSettings();
124
+ } catch (e) {
125
+ bus.emitAgent({
126
+ type: "error",
127
+ message: `[Context] Failed to load session: ${e instanceof Error ? e.message : String(e)}`
128
+ });
129
+ }
130
+ }
131
+ async save() {
132
+ this.ctx.updated_at = (/* @__PURE__ */ new Date()).toISOString();
133
+ const cfg = await config.load();
134
+ try {
135
+ const timestamp = Date.now();
136
+ db.getDb().prepare(
137
+ `
138
+ INSERT INTO sessions (id, created_at, workspace)
139
+ VALUES (?, ?, ?)
140
+ ON CONFLICT(id) DO UPDATE SET
141
+ workspace = excluded.workspace,
142
+ created_at = excluded.created_at
143
+ `
144
+ ).run(this.ctx.session_id, timestamp, cfg.workspaceRoot);
145
+ const insertFile = db.getDb().prepare(`
146
+ INSERT INTO working_set (session_id, file_path, rank_score, last_accessed, access_count)
147
+ VALUES (?, ?, ?, ?, 1)
148
+ ON CONFLICT(session_id, file_path) DO UPDATE SET
149
+ access_count = access_count + 1,
150
+ last_accessed = ?
151
+ `);
152
+ const transaction = db.getDb().transaction(() => {
153
+ for (const file of this.ctx.working_set) {
154
+ insertFile.run(this.ctx.session_id, file, 1, timestamp, timestamp);
155
+ }
156
+ });
157
+ transaction();
158
+ } catch (e) {
159
+ bus.emitAgent({
160
+ type: "error",
161
+ message: `[Context] Failed to save: ${e instanceof Error ? e.message : String(e)}`
162
+ });
163
+ }
164
+ }
165
+ async archive() {
166
+ }
167
+ async startNewSession() {
168
+ const oldMode = this.ctx.mode;
169
+ this.ctx = createEmptyContext();
170
+ this.ctx.mode = oldMode;
171
+ await this.save();
172
+ await settings.set("mode", this.ctx.mode);
173
+ }
174
+ // Getters
175
+ get() {
176
+ return { ...this.ctx };
177
+ }
178
+ getMode() {
179
+ return this.ctx.mode;
180
+ }
181
+ async syncModeFromSettings() {
182
+ const s = await settings.load();
183
+ this.ctx.mode = s.mode;
184
+ }
185
+ getCurrentTask() {
186
+ return this.ctx.current_task;
187
+ }
188
+ getWorkingSet() {
189
+ return [...this.ctx.working_set];
190
+ }
191
+ // Setters
192
+ async setMode(mode) {
193
+ this.ctx.mode = mode;
194
+ await settings.set("mode", mode);
195
+ }
196
+ async setTask(task) {
197
+ this.ctx.current_task = task;
198
+ }
199
+ // Tracking
200
+ async trackRead(filePath, tokenEstimate = 0) {
201
+ const cfg = await config.load();
202
+ const normalized = path.relative(cfg.workspaceRoot, path.resolve(filePath));
203
+ if (!this.ctx.files_read.includes(normalized)) {
204
+ this.ctx.files_read.push(normalized);
205
+ }
206
+ if (!this.ctx.working_set.includes(normalized)) {
207
+ this.ctx.working_set.push(normalized);
208
+ }
209
+ try {
210
+ const timestamp = Date.now();
211
+ const isModified = this.ctx.files_modified.includes(normalized);
212
+ const isEntryPoint = isEntryPointFile(normalized);
213
+ const existing = db.getDb().prepare(
214
+ `
215
+ SELECT access_count FROM working_set
216
+ WHERE session_id = ? AND file_path = ?
217
+ `
218
+ ).get(this.ctx.session_id, normalized);
219
+ const newAccessCount = (existing?.access_count || 0) + 1;
220
+ const rankScore = calculateRankScore(
221
+ newAccessCount,
222
+ timestamp,
223
+ isModified,
224
+ isEntryPoint
225
+ );
226
+ db.getDb().prepare(
227
+ `
228
+ INSERT INTO working_set (session_id, file_path, rank_score, last_accessed, access_count)
229
+ VALUES (?, ?, ?, ?, 1)
230
+ ON CONFLICT(session_id, file_path) DO UPDATE SET
231
+ access_count = access_count + 1,
232
+ last_accessed = ?,
233
+ rank_score = ?
234
+ `
235
+ ).run(
236
+ this.ctx.session_id,
237
+ normalized,
238
+ rankScore,
239
+ timestamp,
240
+ timestamp,
241
+ rankScore
242
+ );
243
+ await this.pruneWorkingSet();
244
+ } catch (e) {
245
+ bus.emitAgent({
246
+ type: "thought",
247
+ content: `[Context] Failed to track read for ${normalized}: ${e instanceof Error ? e.message : String(e)}`,
248
+ hidden: true
249
+ });
250
+ }
251
+ }
252
+ async trackModified(filePath, tokenEstimate = 0) {
253
+ const cfg = await config.load();
254
+ const normalized = path.relative(cfg.workspaceRoot, path.resolve(filePath));
255
+ if (!this.ctx.files_modified.includes(normalized)) {
256
+ this.ctx.files_modified.push(normalized);
257
+ }
258
+ try {
259
+ const timestamp = Date.now();
260
+ const existing = db.getDb().prepare(
261
+ `
262
+ SELECT access_count FROM working_set
263
+ WHERE session_id = ? AND file_path = ?
264
+ `
265
+ ).get(this.ctx.session_id, normalized);
266
+ const accessCount = existing?.access_count || 1;
267
+ const isEntryPoint = isEntryPointFile(normalized);
268
+ const rankScore = calculateRankScore(
269
+ accessCount,
270
+ timestamp,
271
+ true,
272
+ isEntryPoint
273
+ );
274
+ db.getDb().prepare(
275
+ `
276
+ UPDATE working_set SET rank_score = ?, last_accessed = ?
277
+ WHERE session_id = ? AND file_path = ?
278
+ `
279
+ ).run(rankScore, timestamp, this.ctx.session_id, normalized);
280
+ } catch (e) {
281
+ await this.trackRead(filePath, tokenEstimate);
282
+ }
283
+ }
284
+ /**
285
+ * Prune working set to prevent unbounded growth
286
+ * Keeps top N files by rank score
287
+ */
288
+ async pruneWorkingSet() {
289
+ try {
290
+ const count = db.getDb().prepare(
291
+ `
292
+ SELECT COUNT(*) as count FROM working_set WHERE session_id = ?
293
+ `
294
+ ).get(this.ctx.session_id);
295
+ if (count.count > CONTEXT_CONFIG.MAX_WORKING_SET_SIZE) {
296
+ db.getDb().prepare(
297
+ `
298
+ DELETE FROM working_set
299
+ WHERE session_id = ? AND file_path NOT IN (
300
+ SELECT file_path FROM working_set
301
+ WHERE session_id = ?
302
+ ORDER BY rank_score DESC
303
+ LIMIT ?
304
+ )
305
+ `
306
+ ).run(
307
+ this.ctx.session_id,
308
+ this.ctx.session_id,
309
+ CONTEXT_CONFIG.MAX_WORKING_SET_SIZE
310
+ );
311
+ const remaining = db.getDb().prepare(
312
+ `
313
+ SELECT file_path FROM working_set
314
+ WHERE session_id = ?
315
+ ORDER BY rank_score DESC
316
+ `
317
+ ).all(this.ctx.session_id);
318
+ this.ctx.working_set = remaining.map((r) => r.file_path);
319
+ }
320
+ } catch (e) {
321
+ bus.emitAgent({
322
+ type: "thought",
323
+ content: `[Context] Working set pruning failed: ${e instanceof Error ? e.message : String(e)}`,
324
+ hidden: true
325
+ });
326
+ }
327
+ }
328
+ /**
329
+ * Get working set entries with full metadata
330
+ */
331
+ getWorkingSetWithMetadata() {
332
+ try {
333
+ const rows = db.getDb().prepare(
334
+ `
335
+ SELECT file_path, access_count, last_accessed, rank_score
336
+ FROM working_set
337
+ WHERE session_id = ?
338
+ ORDER BY rank_score DESC
339
+ `
340
+ ).all(this.ctx.session_id);
341
+ return rows.map((r) => ({
342
+ filePath: r.file_path,
343
+ accessCount: r.access_count,
344
+ lastAccessed: r.last_accessed,
345
+ isModified: this.ctx.files_modified.includes(r.file_path),
346
+ tokenEstimate: 0
347
+ // Would need to read file to estimate
348
+ }));
349
+ } catch (e) {
350
+ return [];
351
+ }
352
+ }
353
+ /**
354
+ * Recalculate all rank scores (useful for periodic refresh)
355
+ */
356
+ async recalculateRankScores() {
357
+ try {
358
+ const rows = db.getDb().prepare(
359
+ `
360
+ SELECT file_path, access_count, last_accessed
361
+ FROM working_set
362
+ WHERE session_id = ?
363
+ `
364
+ ).all(this.ctx.session_id);
365
+ const updateStmt = db.getDb().prepare(`
366
+ UPDATE working_set SET rank_score = ?
367
+ WHERE session_id = ? AND file_path = ?
368
+ `);
369
+ db.getDb().transaction(() => {
370
+ for (const row of rows) {
371
+ const isModified = this.ctx.files_modified.includes(row.file_path);
372
+ const isEntryPoint = isEntryPointFile(row.file_path);
373
+ const newScore = calculateRankScore(
374
+ row.access_count,
375
+ row.last_accessed,
376
+ isModified,
377
+ isEntryPoint
378
+ );
379
+ updateStmt.run(newScore, this.ctx.session_id, row.file_path);
380
+ }
381
+ })();
382
+ } catch (e) {
383
+ bus.emitAgent({
384
+ type: "thought",
385
+ content: `[Context] Rank recalculation failed: ${e instanceof Error ? e.message : String(e)}`,
386
+ hidden: true
387
+ });
388
+ }
389
+ }
390
+ async setLastAction(action) {
391
+ this.ctx.last_action = action;
392
+ }
393
+ // Reset
394
+ async reset() {
395
+ this.ctx = createEmptyContext();
396
+ await this.save();
397
+ }
398
+ async clearWorkingSet() {
399
+ this.ctx.working_set = [];
400
+ db.getDb().prepare("DELETE FROM working_set WHERE session_id = ?").run(this.ctx.session_id);
401
+ }
402
+ // Summary for LLM
403
+ getSummary() {
404
+ const lines = [];
405
+ if (this.ctx.current_task) {
406
+ lines.push(`Task: ${this.ctx.current_task}`);
407
+ }
408
+ const topFiles = this.getWorkingSetWithMetadata().slice(0, 5);
409
+ if (topFiles.length > 0) {
410
+ const fileList = topFiles.map((f) => {
411
+ const modified = f.isModified ? "*" : "";
412
+ return `${modified}${f.filePath}`;
413
+ }).join(", ");
414
+ lines.push(`Working set (top 5): ${fileList}`);
415
+ }
416
+ if (this.ctx.files_modified.length > 0) {
417
+ lines.push(
418
+ `Modified this session: ${this.ctx.files_modified.slice(-3).join(", ")}`
419
+ );
420
+ }
421
+ return lines.join("\n");
422
+ }
423
+ /**
424
+ * Get context statistics for monitoring
425
+ */
426
+ getStats() {
427
+ return {
428
+ totalFilesRead: this.ctx.files_read.length,
429
+ totalFilesModified: this.ctx.files_modified.length,
430
+ workingSetSize: this.ctx.working_set.length,
431
+ sessionAge: Date.now() - new Date(this.ctx.created_at).getTime()
432
+ };
433
+ }
434
+ };
435
+ var context = new ContextManager();
436
+
437
+ export {
438
+ context
439
+ };