@vheins/local-memory-mcp 0.5.33 → 0.6.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 (506) hide show
  1. package/README.md +9 -6
  2. package/dist/chunk-EQTLHCFK.js +3619 -0
  3. package/dist/dashboard/public/assets/{index-C8FB4maW.css → index-Bd7v94SO.css} +1 -1
  4. package/dist/dashboard/public/assets/index-Df97JpLg.js +84 -0
  5. package/dist/dashboard/public/index.html +2 -2
  6. package/dist/dashboard/server.js +790 -451
  7. package/dist/mcp/server.js +2121 -305
  8. package/dist/{mcp/prompts/definitions → prompts}/create-task.md +4 -3
  9. package/dist/{mcp/prompts/definitions → prompts}/memory-agent-core.md +2 -0
  10. package/dist/{mcp/prompts/definitions → prompts}/memory-index-policy.md +2 -0
  11. package/dist/{mcp/prompts/definitions → prompts}/review-and-audit.md +3 -1
  12. package/dist/{mcp/prompts/definitions → prompts}/review-and-post-issue.md +3 -1
  13. package/dist/prompts/task-management-guidelines.md +28 -0
  14. package/dist/{mcp/prompts/definitions → prompts}/task-memory-executor.md +6 -5
  15. package/package.json +22 -6
  16. package/dist/capabilities.d.ts +0 -22
  17. package/dist/capabilities.d.ts.map +0 -1
  18. package/dist/capabilities.js +0 -38
  19. package/dist/capabilities.js.map +0 -1
  20. package/dist/completion.d.ts +0 -25
  21. package/dist/completion.d.ts.map +0 -1
  22. package/dist/completion.js +0 -127
  23. package/dist/completion.js.map +0 -1
  24. package/dist/dashboard/dashboard.test.d.ts +0 -2
  25. package/dist/dashboard/dashboard.test.d.ts.map +0 -1
  26. package/dist/dashboard/dashboard.test.js +0 -370
  27. package/dist/dashboard/dashboard.test.js.map +0 -1
  28. package/dist/dashboard/public/assets/index-DIhCu9qA.js +0 -78
  29. package/dist/dashboard/server.d.ts +0 -3
  30. package/dist/dashboard/server.d.ts.map +0 -1
  31. package/dist/dashboard/server.js.map +0 -1
  32. package/dist/e2e.test.d.ts +0 -2
  33. package/dist/e2e.test.d.ts.map +0 -1
  34. package/dist/e2e.test.js +0 -250
  35. package/dist/e2e.test.js.map +0 -1
  36. package/dist/mcp/capabilities.d.ts +0 -22
  37. package/dist/mcp/capabilities.d.ts.map +0 -1
  38. package/dist/mcp/capabilities.js +0 -38
  39. package/dist/mcp/capabilities.js.map +0 -1
  40. package/dist/mcp/client.d.ts +0 -34
  41. package/dist/mcp/client.d.ts.map +0 -1
  42. package/dist/mcp/client.js +0 -188
  43. package/dist/mcp/client.js.map +0 -1
  44. package/dist/mcp/client.test.d.ts +0 -2
  45. package/dist/mcp/client.test.d.ts.map +0 -1
  46. package/dist/mcp/client.test.js +0 -130
  47. package/dist/mcp/client.test.js.map +0 -1
  48. package/dist/mcp/completion.d.ts +0 -25
  49. package/dist/mcp/completion.d.ts.map +0 -1
  50. package/dist/mcp/completion.js +0 -127
  51. package/dist/mcp/completion.js.map +0 -1
  52. package/dist/mcp/elicitation.d.ts +0 -24
  53. package/dist/mcp/elicitation.d.ts.map +0 -1
  54. package/dist/mcp/elicitation.js +0 -13
  55. package/dist/mcp/elicitation.js.map +0 -1
  56. package/dist/mcp/prompts/definitions/task-management-guidelines.md +0 -30
  57. package/dist/mcp/prompts/loader.d.ts +0 -10
  58. package/dist/mcp/prompts/loader.d.ts.map +0 -1
  59. package/dist/mcp/prompts/loader.js +0 -31
  60. package/dist/mcp/prompts/loader.js.map +0 -1
  61. package/dist/mcp/prompts/registry.d.ts +0 -35
  62. package/dist/mcp/prompts/registry.d.ts.map +0 -1
  63. package/dist/mcp/prompts/registry.js +0 -95
  64. package/dist/mcp/prompts/registry.js.map +0 -1
  65. package/dist/mcp/resources/index.d.ts +0 -68
  66. package/dist/mcp/resources/index.d.ts.map +0 -1
  67. package/dist/mcp/resources/index.js +0 -359
  68. package/dist/mcp/resources/index.js.map +0 -1
  69. package/dist/mcp/router.d.ts +0 -14
  70. package/dist/mcp/router.d.ts.map +0 -1
  71. package/dist/mcp/router.js +0 -255
  72. package/dist/mcp/router.js.map +0 -1
  73. package/dist/mcp/sampling.d.ts +0 -69
  74. package/dist/mcp/sampling.d.ts.map +0 -1
  75. package/dist/mcp/sampling.js +0 -13
  76. package/dist/mcp/sampling.js.map +0 -1
  77. package/dist/mcp/server.d.ts +0 -3
  78. package/dist/mcp/server.d.ts.map +0 -1
  79. package/dist/mcp/server.js.map +0 -1
  80. package/dist/mcp/session.d.ts +0 -28
  81. package/dist/mcp/session.d.ts.map +0 -1
  82. package/dist/mcp/session.js +0 -106
  83. package/dist/mcp/session.js.map +0 -1
  84. package/dist/mcp/storage/sqlite.d.ts +0 -87
  85. package/dist/mcp/storage/sqlite.d.ts.map +0 -1
  86. package/dist/mcp/storage/sqlite.js +0 -1327
  87. package/dist/mcp/storage/sqlite.js.map +0 -1
  88. package/dist/mcp/storage/vectors.d.ts +0 -19
  89. package/dist/mcp/storage/vectors.d.ts.map +0 -1
  90. package/dist/mcp/storage/vectors.js +0 -74
  91. package/dist/mcp/storage/vectors.js.map +0 -1
  92. package/dist/mcp/storage/vectors.stub.d.ts +0 -12
  93. package/dist/mcp/storage/vectors.stub.d.ts.map +0 -1
  94. package/dist/mcp/storage/vectors.stub.js +0 -88
  95. package/dist/mcp/storage/vectors.stub.js.map +0 -1
  96. package/dist/mcp/tests/client.test.d.ts +0 -2
  97. package/dist/mcp/tests/client.test.d.ts.map +0 -1
  98. package/dist/mcp/tests/client.test.js +0 -130
  99. package/dist/mcp/tests/client.test.js.map +0 -1
  100. package/dist/mcp/tests/dashboard.test.d.ts +0 -2
  101. package/dist/mcp/tests/dashboard.test.d.ts.map +0 -1
  102. package/dist/mcp/tests/dashboard.test.js +0 -370
  103. package/dist/mcp/tests/dashboard.test.js.map +0 -1
  104. package/dist/mcp/tests/detail-tools.test.d.ts +0 -2
  105. package/dist/mcp/tests/detail-tools.test.d.ts.map +0 -1
  106. package/dist/mcp/tests/detail-tools.test.js +0 -109
  107. package/dist/mcp/tests/detail-tools.test.js.map +0 -1
  108. package/dist/mcp/tests/e2e.test.d.ts +0 -2
  109. package/dist/mcp/tests/e2e.test.d.ts.map +0 -1
  110. package/dist/mcp/tests/e2e.test.js +0 -255
  111. package/dist/mcp/tests/e2e.test.js.map +0 -1
  112. package/dist/mcp/tests/index.test.d.ts +0 -2
  113. package/dist/mcp/tests/index.test.d.ts.map +0 -1
  114. package/dist/mcp/tests/index.test.js +0 -185
  115. package/dist/mcp/tests/index.test.js.map +0 -1
  116. package/dist/mcp/tests/logger.test.d.ts +0 -2
  117. package/dist/mcp/tests/logger.test.d.ts.map +0 -1
  118. package/dist/mcp/tests/logger.test.js +0 -104
  119. package/dist/mcp/tests/logger.test.js.map +0 -1
  120. package/dist/mcp/tests/memory.bulk.test.d.ts +0 -2
  121. package/dist/mcp/tests/memory.bulk.test.d.ts.map +0 -1
  122. package/dist/mcp/tests/memory.bulk.test.js +0 -53
  123. package/dist/mcp/tests/memory.bulk.test.js.map +0 -1
  124. package/dist/mcp/tests/memory.search.test.d.ts +0 -2
  125. package/dist/mcp/tests/memory.search.test.d.ts.map +0 -1
  126. package/dist/mcp/tests/memory.search.test.js +0 -181
  127. package/dist/mcp/tests/memory.search.test.js.map +0 -1
  128. package/dist/mcp/tests/normalize.test.d.ts +0 -2
  129. package/dist/mcp/tests/normalize.test.d.ts.map +0 -1
  130. package/dist/mcp/tests/normalize.test.js +0 -181
  131. package/dist/mcp/tests/normalize.test.js.map +0 -1
  132. package/dist/mcp/tests/query-expander.test.d.ts +0 -2
  133. package/dist/mcp/tests/query-expander.test.d.ts.map +0 -1
  134. package/dist/mcp/tests/query-expander.test.js +0 -33
  135. package/dist/mcp/tests/query-expander.test.js.map +0 -1
  136. package/dist/mcp/tests/router.test.d.ts +0 -2
  137. package/dist/mcp/tests/router.test.d.ts.map +0 -1
  138. package/dist/mcp/tests/router.test.js +0 -481
  139. package/dist/mcp/tests/router.test.js.map +0 -1
  140. package/dist/mcp/tests/spec_compliance.test.d.ts +0 -2
  141. package/dist/mcp/tests/spec_compliance.test.d.ts.map +0 -1
  142. package/dist/mcp/tests/spec_compliance.test.js +0 -61
  143. package/dist/mcp/tests/spec_compliance.test.js.map +0 -1
  144. package/dist/mcp/tests/sqlite.test.d.ts +0 -2
  145. package/dist/mcp/tests/sqlite.test.d.ts.map +0 -1
  146. package/dist/mcp/tests/sqlite.test.js +0 -367
  147. package/dist/mcp/tests/sqlite.test.js.map +0 -1
  148. package/dist/mcp/tests/tasks-search.test.d.ts +0 -2
  149. package/dist/mcp/tests/tasks-search.test.d.ts.map +0 -1
  150. package/dist/mcp/tests/tasks-search.test.js +0 -156
  151. package/dist/mcp/tests/tasks-search.test.js.map +0 -1
  152. package/dist/mcp/tests/tasks-transition.test.d.ts +0 -2
  153. package/dist/mcp/tests/tasks-transition.test.d.ts.map +0 -1
  154. package/dist/mcp/tests/tasks-transition.test.js +0 -174
  155. package/dist/mcp/tests/tasks-transition.test.js.map +0 -1
  156. package/dist/mcp/tests/tasks.bulk.test.d.ts +0 -2
  157. package/dist/mcp/tests/tasks.bulk.test.d.ts.map +0 -1
  158. package/dist/mcp/tests/tasks.bulk.test.js +0 -410
  159. package/dist/mcp/tests/tasks.bulk.test.js.map +0 -1
  160. package/dist/mcp/tests/tasks.e2e.test.d.ts +0 -2
  161. package/dist/mcp/tests/tasks.e2e.test.d.ts.map +0 -1
  162. package/dist/mcp/tests/tasks.e2e.test.js +0 -289
  163. package/dist/mcp/tests/tasks.e2e.test.js.map +0 -1
  164. package/dist/mcp/tests/tasks.pending-limit-refined.test.d.ts +0 -2
  165. package/dist/mcp/tests/tasks.pending-limit-refined.test.d.ts.map +0 -1
  166. package/dist/mcp/tests/tasks.pending-limit-refined.test.js +0 -72
  167. package/dist/mcp/tests/tasks.pending-limit-refined.test.js.map +0 -1
  168. package/dist/mcp/tests/v2-features.test.d.ts +0 -2
  169. package/dist/mcp/tests/v2-features.test.d.ts.map +0 -1
  170. package/dist/mcp/tests/v2-features.test.js +0 -209
  171. package/dist/mcp/tests/v2-features.test.js.map +0 -1
  172. package/dist/mcp/tools/memory.acknowledge.d.ts +0 -4
  173. package/dist/mcp/tools/memory.acknowledge.d.ts.map +0 -1
  174. package/dist/mcp/tools/memory.acknowledge.js +0 -32
  175. package/dist/mcp/tools/memory.acknowledge.js.map +0 -1
  176. package/dist/mcp/tools/memory.bulk-delete.d.ts +0 -4
  177. package/dist/mcp/tools/memory.bulk-delete.d.ts.map +0 -1
  178. package/dist/mcp/tools/memory.bulk-delete.js +0 -40
  179. package/dist/mcp/tools/memory.bulk-delete.js.map +0 -1
  180. package/dist/mcp/tools/memory.delete.d.ts +0 -9
  181. package/dist/mcp/tools/memory.delete.d.ts.map +0 -1
  182. package/dist/mcp/tools/memory.delete.js +0 -40
  183. package/dist/mcp/tools/memory.delete.js.map +0 -1
  184. package/dist/mcp/tools/memory.get.d.ts +0 -3
  185. package/dist/mcp/tools/memory.get.d.ts.map +0 -1
  186. package/dist/mcp/tools/memory.get.js +0 -24
  187. package/dist/mcp/tools/memory.get.js.map +0 -1
  188. package/dist/mcp/tools/memory.recap.d.ts +0 -4
  189. package/dist/mcp/tools/memory.recap.d.ts.map +0 -1
  190. package/dist/mcp/tools/memory.recap.js +0 -52
  191. package/dist/mcp/tools/memory.recap.js.map +0 -1
  192. package/dist/mcp/tools/memory.search.d.ts +0 -5
  193. package/dist/mcp/tools/memory.search.d.ts.map +0 -1
  194. package/dist/mcp/tools/memory.search.js +0 -144
  195. package/dist/mcp/tools/memory.search.js.map +0 -1
  196. package/dist/mcp/tools/memory.store.d.ts +0 -5
  197. package/dist/mcp/tools/memory.store.d.ts.map +0 -1
  198. package/dist/mcp/tools/memory.store.js +0 -120
  199. package/dist/mcp/tools/memory.store.js.map +0 -1
  200. package/dist/mcp/tools/memory.summarize.d.ts +0 -4
  201. package/dist/mcp/tools/memory.summarize.d.ts.map +0 -1
  202. package/dist/mcp/tools/memory.summarize.js +0 -32
  203. package/dist/mcp/tools/memory.summarize.js.map +0 -1
  204. package/dist/mcp/tools/memory.synthesize.d.ts +0 -14
  205. package/dist/mcp/tools/memory.synthesize.d.ts.map +0 -1
  206. package/dist/mcp/tools/memory.synthesize.js +0 -230
  207. package/dist/mcp/tools/memory.synthesize.js.map +0 -1
  208. package/dist/mcp/tools/memory.update.d.ts +0 -5
  209. package/dist/mcp/tools/memory.update.d.ts.map +0 -1
  210. package/dist/mcp/tools/memory.update.js +0 -74
  211. package/dist/mcp/tools/memory.update.js.map +0 -1
  212. package/dist/mcp/tools/schemas.d.ts +0 -3177
  213. package/dist/mcp/tools/schemas.d.ts.map +0 -1
  214. package/dist/mcp/tools/schemas.js +0 -1081
  215. package/dist/mcp/tools/schemas.js.map +0 -1
  216. package/dist/mcp/tools/task.bulk-manage.d.ts +0 -4
  217. package/dist/mcp/tools/task.bulk-manage.d.ts.map +0 -1
  218. package/dist/mcp/tools/task.bulk-manage.js +0 -190
  219. package/dist/mcp/tools/task.bulk-manage.js.map +0 -1
  220. package/dist/mcp/tools/task.get.d.ts +0 -3
  221. package/dist/mcp/tools/task.get.d.ts.map +0 -1
  222. package/dist/mcp/tools/task.get.js +0 -32
  223. package/dist/mcp/tools/task.get.js.map +0 -1
  224. package/dist/mcp/tools/task.manage.d.ts +0 -18
  225. package/dist/mcp/tools/task.manage.d.ts.map +0 -1
  226. package/dist/mcp/tools/task.manage.js +0 -477
  227. package/dist/mcp/tools/task.manage.js.map +0 -1
  228. package/dist/mcp/types.d.ts +0 -87
  229. package/dist/mcp/types.d.ts.map +0 -1
  230. package/dist/mcp/types.js +0 -3
  231. package/dist/mcp/types.js.map +0 -1
  232. package/dist/mcp/utils/completion.d.ts +0 -2
  233. package/dist/mcp/utils/completion.d.ts.map +0 -1
  234. package/dist/mcp/utils/completion.js +0 -28
  235. package/dist/mcp/utils/completion.js.map +0 -1
  236. package/dist/mcp/utils/git-scope.d.ts +0 -8
  237. package/dist/mcp/utils/git-scope.d.ts.map +0 -1
  238. package/dist/mcp/utils/git-scope.js +0 -38
  239. package/dist/mcp/utils/git-scope.js.map +0 -1
  240. package/dist/mcp/utils/logger.d.ts +0 -25
  241. package/dist/mcp/utils/logger.d.ts.map +0 -1
  242. package/dist/mcp/utils/logger.js +0 -152
  243. package/dist/mcp/utils/logger.js.map +0 -1
  244. package/dist/mcp/utils/mcp-response.d.ts +0 -82
  245. package/dist/mcp/utils/mcp-response.d.ts.map +0 -1
  246. package/dist/mcp/utils/mcp-response.js +0 -182
  247. package/dist/mcp/utils/mcp-response.js.map +0 -1
  248. package/dist/mcp/utils/normalize.d.ts +0 -9
  249. package/dist/mcp/utils/normalize.d.ts.map +0 -1
  250. package/dist/mcp/utils/normalize.js +0 -62
  251. package/dist/mcp/utils/normalize.js.map +0 -1
  252. package/dist/mcp/utils/pagination.d.ts +0 -6
  253. package/dist/mcp/utils/pagination.d.ts.map +0 -1
  254. package/dist/mcp/utils/pagination.js +0 -32
  255. package/dist/mcp/utils/pagination.js.map +0 -1
  256. package/dist/mcp/utils/query-expander.d.ts +0 -2
  257. package/dist/mcp/utils/query-expander.d.ts.map +0 -1
  258. package/dist/mcp/utils/query-expander.js +0 -29
  259. package/dist/mcp/utils/query-expander.js.map +0 -1
  260. package/dist/memory.bulk.test.d.ts +0 -2
  261. package/dist/memory.bulk.test.d.ts.map +0 -1
  262. package/dist/memory.bulk.test.js +0 -52
  263. package/dist/memory.bulk.test.js.map +0 -1
  264. package/dist/memory.db +0 -0
  265. package/dist/prompts/registry.d.ts +0 -314
  266. package/dist/prompts/registry.d.ts.map +0 -1
  267. package/dist/prompts/registry.js +0 -936
  268. package/dist/prompts/registry.js.map +0 -1
  269. package/dist/resources/index.d.ts +0 -68
  270. package/dist/resources/index.d.ts.map +0 -1
  271. package/dist/resources/index.js +0 -323
  272. package/dist/resources/index.js.map +0 -1
  273. package/dist/resources/index.test.d.ts +0 -2
  274. package/dist/resources/index.test.d.ts.map +0 -1
  275. package/dist/resources/index.test.js +0 -105
  276. package/dist/resources/index.test.js.map +0 -1
  277. package/dist/router.d.ts +0 -14
  278. package/dist/router.d.ts.map +0 -1
  279. package/dist/router.js +0 -242
  280. package/dist/router.js.map +0 -1
  281. package/dist/router.test.d.ts +0 -2
  282. package/dist/router.test.d.ts.map +0 -1
  283. package/dist/router.test.js +0 -122
  284. package/dist/router.test.js.map +0 -1
  285. package/dist/server.d.ts +0 -3
  286. package/dist/server.d.ts.map +0 -1
  287. package/dist/server.js +0 -338
  288. package/dist/server.js.map +0 -1
  289. package/dist/storage/sqlite.d.ts +0 -79
  290. package/dist/storage/sqlite.d.ts.map +0 -1
  291. package/dist/storage/sqlite.js +0 -1148
  292. package/dist/storage/sqlite.js.map +0 -1
  293. package/dist/storage/sqlite.test.d.ts +0 -2
  294. package/dist/storage/sqlite.test.d.ts.map +0 -1
  295. package/dist/storage/sqlite.test.js +0 -367
  296. package/dist/storage/sqlite.test.js.map +0 -1
  297. package/dist/storage/vectors.d.ts +0 -19
  298. package/dist/storage/vectors.d.ts.map +0 -1
  299. package/dist/storage/vectors.js +0 -74
  300. package/dist/storage/vectors.js.map +0 -1
  301. package/dist/storage/vectors.stub.d.ts +0 -12
  302. package/dist/storage/vectors.stub.d.ts.map +0 -1
  303. package/dist/storage/vectors.stub.js +0 -88
  304. package/dist/storage/vectors.stub.js.map +0 -1
  305. package/dist/tasks.archive.test.d.ts +0 -2
  306. package/dist/tasks.archive.test.d.ts.map +0 -1
  307. package/dist/tasks.archive.test.js +0 -75
  308. package/dist/tasks.archive.test.js.map +0 -1
  309. package/dist/tasks.bulk.test.d.ts +0 -2
  310. package/dist/tasks.bulk.test.d.ts.map +0 -1
  311. package/dist/tasks.bulk.test.js +0 -250
  312. package/dist/tasks.bulk.test.js.map +0 -1
  313. package/dist/tasks.e2e.test.d.ts +0 -2
  314. package/dist/tasks.e2e.test.d.ts.map +0 -1
  315. package/dist/tasks.e2e.test.js +0 -289
  316. package/dist/tasks.e2e.test.js.map +0 -1
  317. package/dist/tests/client.test.d.ts +0 -2
  318. package/dist/tests/client.test.d.ts.map +0 -1
  319. package/dist/tests/client.test.js +0 -130
  320. package/dist/tests/client.test.js.map +0 -1
  321. package/dist/tests/dashboard.test.d.ts +0 -2
  322. package/dist/tests/dashboard.test.d.ts.map +0 -1
  323. package/dist/tests/dashboard.test.js +0 -370
  324. package/dist/tests/dashboard.test.js.map +0 -1
  325. package/dist/tests/e2e.test.d.ts +0 -2
  326. package/dist/tests/e2e.test.d.ts.map +0 -1
  327. package/dist/tests/e2e.test.js +0 -250
  328. package/dist/tests/e2e.test.js.map +0 -1
  329. package/dist/tests/index.test.d.ts +0 -2
  330. package/dist/tests/index.test.d.ts.map +0 -1
  331. package/dist/tests/index.test.js +0 -185
  332. package/dist/tests/index.test.js.map +0 -1
  333. package/dist/tests/logger.test.d.ts +0 -2
  334. package/dist/tests/logger.test.d.ts.map +0 -1
  335. package/dist/tests/logger.test.js +0 -104
  336. package/dist/tests/logger.test.js.map +0 -1
  337. package/dist/tests/memory.bulk.test.d.ts +0 -2
  338. package/dist/tests/memory.bulk.test.d.ts.map +0 -1
  339. package/dist/tests/memory.bulk.test.js +0 -52
  340. package/dist/tests/memory.bulk.test.js.map +0 -1
  341. package/dist/tests/memory.search.test.d.ts +0 -2
  342. package/dist/tests/memory.search.test.d.ts.map +0 -1
  343. package/dist/tests/memory.search.test.js +0 -181
  344. package/dist/tests/memory.search.test.js.map +0 -1
  345. package/dist/tests/normalize.test.d.ts +0 -2
  346. package/dist/tests/normalize.test.d.ts.map +0 -1
  347. package/dist/tests/normalize.test.js +0 -181
  348. package/dist/tests/normalize.test.js.map +0 -1
  349. package/dist/tests/query-expander.test.d.ts +0 -2
  350. package/dist/tests/query-expander.test.d.ts.map +0 -1
  351. package/dist/tests/query-expander.test.js +0 -33
  352. package/dist/tests/query-expander.test.js.map +0 -1
  353. package/dist/tests/router.test.d.ts +0 -2
  354. package/dist/tests/router.test.d.ts.map +0 -1
  355. package/dist/tests/router.test.js +0 -470
  356. package/dist/tests/router.test.js.map +0 -1
  357. package/dist/tests/sqlite.test.d.ts +0 -2
  358. package/dist/tests/sqlite.test.d.ts.map +0 -1
  359. package/dist/tests/sqlite.test.js +0 -367
  360. package/dist/tests/sqlite.test.js.map +0 -1
  361. package/dist/tests/tasks-search.test.d.ts +0 -2
  362. package/dist/tests/tasks-search.test.d.ts.map +0 -1
  363. package/dist/tests/tasks-search.test.js +0 -154
  364. package/dist/tests/tasks-search.test.js.map +0 -1
  365. package/dist/tests/tasks-transition.test.d.ts +0 -2
  366. package/dist/tests/tasks-transition.test.d.ts.map +0 -1
  367. package/dist/tests/tasks-transition.test.js +0 -174
  368. package/dist/tests/tasks-transition.test.js.map +0 -1
  369. package/dist/tests/tasks.bulk.test.d.ts +0 -2
  370. package/dist/tests/tasks.bulk.test.d.ts.map +0 -1
  371. package/dist/tests/tasks.bulk.test.js +0 -254
  372. package/dist/tests/tasks.bulk.test.js.map +0 -1
  373. package/dist/tests/tasks.e2e.test.d.ts +0 -2
  374. package/dist/tests/tasks.e2e.test.d.ts.map +0 -1
  375. package/dist/tests/tasks.e2e.test.js +0 -289
  376. package/dist/tests/tasks.e2e.test.js.map +0 -1
  377. package/dist/tests/tasks.pending-limit-refined.test.d.ts +0 -2
  378. package/dist/tests/tasks.pending-limit-refined.test.d.ts.map +0 -1
  379. package/dist/tests/tasks.pending-limit-refined.test.js +0 -72
  380. package/dist/tests/tasks.pending-limit-refined.test.js.map +0 -1
  381. package/dist/tests/v2-features.test.d.ts +0 -2
  382. package/dist/tests/v2-features.test.d.ts.map +0 -1
  383. package/dist/tests/v2-features.test.js +0 -209
  384. package/dist/tests/v2-features.test.js.map +0 -1
  385. package/dist/tools/memory.acknowledge.d.ts +0 -4
  386. package/dist/tools/memory.acknowledge.d.ts.map +0 -1
  387. package/dist/tools/memory.acknowledge.js +0 -30
  388. package/dist/tools/memory.acknowledge.js.map +0 -1
  389. package/dist/tools/memory.bulk-delete.d.ts +0 -4
  390. package/dist/tools/memory.bulk-delete.d.ts.map +0 -1
  391. package/dist/tools/memory.bulk-delete.js +0 -39
  392. package/dist/tools/memory.bulk-delete.js.map +0 -1
  393. package/dist/tools/memory.delete.d.ts +0 -9
  394. package/dist/tools/memory.delete.d.ts.map +0 -1
  395. package/dist/tools/memory.delete.js +0 -39
  396. package/dist/tools/memory.delete.js.map +0 -1
  397. package/dist/tools/memory.recap.d.ts +0 -4
  398. package/dist/tools/memory.recap.d.ts.map +0 -1
  399. package/dist/tools/memory.recap.js +0 -90
  400. package/dist/tools/memory.recap.js.map +0 -1
  401. package/dist/tools/memory.search.d.ts +0 -5
  402. package/dist/tools/memory.search.d.ts.map +0 -1
  403. package/dist/tools/memory.search.js +0 -134
  404. package/dist/tools/memory.search.js.map +0 -1
  405. package/dist/tools/memory.search.test.d.ts +0 -2
  406. package/dist/tools/memory.search.test.d.ts.map +0 -1
  407. package/dist/tools/memory.search.test.js +0 -181
  408. package/dist/tools/memory.search.test.js.map +0 -1
  409. package/dist/tools/memory.store.d.ts +0 -5
  410. package/dist/tools/memory.store.d.ts.map +0 -1
  411. package/dist/tools/memory.store.js +0 -117
  412. package/dist/tools/memory.store.js.map +0 -1
  413. package/dist/tools/memory.summarize.d.ts +0 -4
  414. package/dist/tools/memory.summarize.d.ts.map +0 -1
  415. package/dist/tools/memory.summarize.js +0 -31
  416. package/dist/tools/memory.summarize.js.map +0 -1
  417. package/dist/tools/memory.synthesize.d.ts +0 -14
  418. package/dist/tools/memory.synthesize.d.ts.map +0 -1
  419. package/dist/tools/memory.synthesize.js +0 -228
  420. package/dist/tools/memory.synthesize.js.map +0 -1
  421. package/dist/tools/memory.update.d.ts +0 -5
  422. package/dist/tools/memory.update.d.ts.map +0 -1
  423. package/dist/tools/memory.update.js +0 -73
  424. package/dist/tools/memory.update.js.map +0 -1
  425. package/dist/tools/schemas.d.ts +0 -2762
  426. package/dist/tools/schemas.d.ts.map +0 -1
  427. package/dist/tools/schemas.js +0 -952
  428. package/dist/tools/schemas.js.map +0 -1
  429. package/dist/tools/task.bulk-manage.d.ts +0 -4
  430. package/dist/tools/task.bulk-manage.d.ts.map +0 -1
  431. package/dist/tools/task.bulk-manage.js +0 -146
  432. package/dist/tools/task.bulk-manage.js.map +0 -1
  433. package/dist/tools/task.manage.d.ts +0 -16
  434. package/dist/tools/task.manage.d.ts.map +0 -1
  435. package/dist/tools/task.manage.js +0 -395
  436. package/dist/tools/task.manage.js.map +0 -1
  437. package/dist/tools/tasks-transition.test.d.ts +0 -2
  438. package/dist/tools/tasks-transition.test.d.ts.map +0 -1
  439. package/dist/tools/tasks-transition.test.js +0 -174
  440. package/dist/tools/tasks-transition.test.js.map +0 -1
  441. package/dist/tools/tasks.pending-limit-refined.test.d.ts +0 -2
  442. package/dist/tools/tasks.pending-limit-refined.test.d.ts.map +0 -1
  443. package/dist/tools/tasks.pending-limit-refined.test.js +0 -72
  444. package/dist/tools/tasks.pending-limit-refined.test.js.map +0 -1
  445. package/dist/types.d.ts +0 -87
  446. package/dist/types.d.ts.map +0 -1
  447. package/dist/types.js +0 -3
  448. package/dist/types.js.map +0 -1
  449. package/dist/utils/completion.d.ts +0 -2
  450. package/dist/utils/completion.d.ts.map +0 -1
  451. package/dist/utils/completion.js +0 -28
  452. package/dist/utils/completion.js.map +0 -1
  453. package/dist/utils/git-scope.d.ts +0 -8
  454. package/dist/utils/git-scope.d.ts.map +0 -1
  455. package/dist/utils/git-scope.js +0 -38
  456. package/dist/utils/git-scope.js.map +0 -1
  457. package/dist/utils/logger.d.ts +0 -25
  458. package/dist/utils/logger.d.ts.map +0 -1
  459. package/dist/utils/logger.js +0 -152
  460. package/dist/utils/logger.js.map +0 -1
  461. package/dist/utils/logger.test.d.ts +0 -2
  462. package/dist/utils/logger.test.d.ts.map +0 -1
  463. package/dist/utils/logger.test.js +0 -76
  464. package/dist/utils/logger.test.js.map +0 -1
  465. package/dist/utils/mcp-response.d.ts +0 -96
  466. package/dist/utils/mcp-response.d.ts.map +0 -1
  467. package/dist/utils/mcp-response.js +0 -131
  468. package/dist/utils/mcp-response.js.map +0 -1
  469. package/dist/utils/normalize.d.ts +0 -9
  470. package/dist/utils/normalize.d.ts.map +0 -1
  471. package/dist/utils/normalize.js +0 -62
  472. package/dist/utils/normalize.js.map +0 -1
  473. package/dist/utils/normalize.test.d.ts +0 -2
  474. package/dist/utils/normalize.test.d.ts.map +0 -1
  475. package/dist/utils/normalize.test.js +0 -159
  476. package/dist/utils/normalize.test.js.map +0 -1
  477. package/dist/utils/pagination.d.ts +0 -6
  478. package/dist/utils/pagination.d.ts.map +0 -1
  479. package/dist/utils/pagination.js +0 -32
  480. package/dist/utils/pagination.js.map +0 -1
  481. package/dist/utils/query-expander.d.ts +0 -2
  482. package/dist/utils/query-expander.d.ts.map +0 -1
  483. package/dist/utils/query-expander.js +0 -29
  484. package/dist/utils/query-expander.js.map +0 -1
  485. package/dist/utils/query-expander.test.d.ts +0 -2
  486. package/dist/utils/query-expander.test.d.ts.map +0 -1
  487. package/dist/utils/query-expander.test.js +0 -33
  488. package/dist/utils/query-expander.test.js.map +0 -1
  489. package/dist/v2-features.test.d.ts +0 -2
  490. package/dist/v2-features.test.d.ts.map +0 -1
  491. package/dist/v2-features.test.js +0 -209
  492. package/dist/v2-features.test.js.map +0 -1
  493. /package/dist/{mcp/prompts/definitions → prompts}/architecture-design.md +0 -0
  494. /package/dist/{mcp/prompts/definitions → prompts}/documentation-sync.md +0 -0
  495. /package/dist/{mcp/prompts/definitions → prompts}/fix-suggestion.md +0 -0
  496. /package/dist/{mcp/prompts/definitions → prompts}/import-github-issues.md +0 -0
  497. /package/dist/{mcp/prompts/definitions → prompts}/learning-retrospective.md +0 -0
  498. /package/dist/{mcp/prompts/definitions → prompts}/memory-guided-review.md +0 -0
  499. /package/dist/{mcp/prompts/definitions → prompts}/project-briefing.md +0 -0
  500. /package/dist/{mcp/prompts/definitions → prompts}/root-cause-analysis.md +0 -0
  501. /package/dist/{mcp/prompts/definitions → prompts}/security-triage.md +0 -0
  502. /package/dist/{mcp/prompts/definitions → prompts}/senior-code-review.md +0 -0
  503. /package/dist/{mcp/prompts/definitions → prompts}/session-planner.md +0 -0
  504. /package/dist/{mcp/prompts/definitions → prompts}/tech-affinity-scout.md +0 -0
  505. /package/dist/{mcp/prompts/definitions → prompts}/technical-planning.md +0 -0
  506. /package/dist/{mcp/prompts/definitions → prompts}/tool-usage-guidelines.md +0 -0
@@ -1,1327 +0,0 @@
1
- import Database from "better-sqlite3";
2
- import path from "path";
3
- import fs from "fs";
4
- import os from "os";
5
- import { fileURLToPath } from "url";
6
- import { tokenize } from "../utils/normalize.js";
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
- /**
9
- * Resolve database path with following priority:
10
- * 1. MEMORY_DB_PATH env var
11
- * 2. ~/.config/local-memory-mcp/memory.db (standard user config)
12
- * 3. Local storage/ folder in CWD (for npx/global usage)
13
- * 4. Project root storage/ folder
14
- */
15
- function resolveDbPath() {
16
- if (process.env.MEMORY_DB_PATH) {
17
- return process.env.MEMORY_DB_PATH;
18
- }
19
- // 1. Define the standard global path for this platform
20
- const standardConfigDir = process.platform === "win32"
21
- ? path.join(os.homedir(), ".local-memory-mcp")
22
- : process.platform === "darwin"
23
- ? path.join(os.homedir(), "Library", "Application Support", "local-memory-mcp")
24
- : path.join(os.homedir(), ".config", "local-memory-mcp");
25
- const standardPath = path.join(standardConfigDir, "memory.db");
26
- // 2. If the global database already exists, ALWAYS use it to ensure consistency
27
- if (fs.existsSync(standardPath)) {
28
- return standardPath;
29
- }
30
- // 3. Migration/Legacy check: ~/.config/local-memory-mcp/memory.db
31
- const legacyPath = path.join(os.homedir(), ".config", "local-memory-mcp", "memory.db");
32
- if (fs.existsSync(legacyPath)) {
33
- return legacyPath;
34
- }
35
- // 4. Development/Portable check: ONLY use local storage if the FILE actually exists.
36
- // This prevents divergence when one process sees a 'storage/' folder and another doesn't.
37
- const localCwdFile = path.join(process.cwd(), "storage", "memory.db");
38
- if (fs.existsSync(localCwdFile)) {
39
- return localCwdFile;
40
- }
41
- const localProjFile = path.join(__dirname, "../../storage", "memory.db");
42
- if (fs.existsSync(localProjFile)) {
43
- return localProjFile;
44
- }
45
- // 5. Default: Return the standard global path (it will be created by the constructor)
46
- return standardPath;
47
- }
48
- const DB_PATH = resolveDbPath();
49
- export class SQLiteStore {
50
- db;
51
- constructor(dbPath) {
52
- const finalPath = dbPath ?? DB_PATH;
53
- const dbDir = path.dirname(finalPath);
54
- if (!fs.existsSync(dbDir)) {
55
- fs.mkdirSync(dbDir, { recursive: true });
56
- }
57
- this.db = new Database(finalPath);
58
- this.db.pragma("journal_mode = WAL");
59
- this.db.pragma("synchronous = NORMAL");
60
- this.db.pragma("busy_timeout = 5000");
61
- this.migrate();
62
- }
63
- getDbPath() {
64
- return DB_PATH;
65
- }
66
- migrate() {
67
- // 1. Create base tables first
68
- this.db.exec(`
69
- CREATE TABLE IF NOT EXISTS memories (
70
- id TEXT PRIMARY KEY,
71
- repo TEXT NOT NULL,
72
- type TEXT NOT NULL,
73
- title TEXT,
74
- content TEXT NOT NULL,
75
- importance INTEGER NOT NULL CHECK (importance BETWEEN 1 AND 5),
76
- folder TEXT,
77
- language TEXT,
78
- created_at TEXT NOT NULL,
79
- updated_at TEXT NOT NULL,
80
- hit_count INTEGER NOT NULL DEFAULT 0,
81
- recall_count INTEGER NOT NULL DEFAULT 0,
82
- last_used_at TEXT,
83
- agent TEXT NOT NULL DEFAULT 'unknown',
84
- role TEXT NOT NULL DEFAULT 'unknown',
85
- model TEXT NOT NULL DEFAULT 'unknown',
86
- completed_at TEXT
87
- );
88
-
89
- CREATE INDEX IF NOT EXISTS idx_memories_repo ON memories(repo);
90
- CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
91
- CREATE INDEX IF NOT EXISTS idx_memories_importance ON memories(importance);
92
- CREATE INDEX IF NOT EXISTS idx_memories_hit_count ON memories(hit_count);
93
- CREATE INDEX IF NOT EXISTS idx_memories_created_at ON memories(created_at);
94
- CREATE INDEX IF NOT EXISTS idx_memories_updated_at ON memories(updated_at);
95
- CREATE INDEX IF NOT EXISTS idx_memories_repo_created_at ON memories(repo, created_at DESC);
96
- CREATE INDEX IF NOT EXISTS idx_memories_repo_hit_count ON memories(repo, hit_count DESC);
97
- CREATE INDEX IF NOT EXISTS idx_memories_title ON memories(title);
98
-
99
- CREATE TABLE IF NOT EXISTS memory_summary (
100
- repo TEXT PRIMARY KEY,
101
- summary TEXT NOT NULL,
102
- updated_at TEXT NOT NULL
103
- );
104
-
105
- CREATE TABLE IF NOT EXISTS memory_vectors (
106
- memory_id TEXT PRIMARY KEY,
107
- vector TEXT NOT NULL,
108
- updated_at TEXT NOT NULL,
109
- FOREIGN KEY (memory_id) REFERENCES memories(id) ON DELETE CASCADE
110
- );
111
-
112
- CREATE TABLE IF NOT EXISTS tasks (
113
- id TEXT PRIMARY KEY,
114
- repo TEXT NOT NULL,
115
- task_code TEXT NOT NULL,
116
- phase TEXT,
117
- title TEXT NOT NULL,
118
- description TEXT,
119
- status TEXT NOT NULL DEFAULT 'backlog',
120
- priority INTEGER NOT NULL DEFAULT 3,
121
- agent TEXT NOT NULL DEFAULT 'unknown',
122
- role TEXT NOT NULL DEFAULT 'unknown',
123
- doc_path TEXT,
124
- created_at TEXT NOT NULL,
125
- updated_at TEXT NOT NULL,
126
- finished_at TEXT,
127
- canceled_at TEXT,
128
- tags TEXT,
129
- metadata TEXT,
130
- parent_id TEXT,
131
- depends_on TEXT,
132
- est_tokens INTEGER NOT NULL DEFAULT 0,
133
- in_progress_at TEXT,
134
- FOREIGN KEY (parent_id) REFERENCES tasks(id) ON DELETE SET NULL,
135
- FOREIGN KEY (depends_on) REFERENCES tasks(id) ON DELETE SET NULL
136
- );
137
-
138
- CREATE INDEX IF NOT EXISTS idx_tasks_repo ON tasks(repo);
139
- CREATE INDEX IF NOT EXISTS idx_tasks_code ON tasks(task_code);
140
- CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
141
- CREATE INDEX IF NOT EXISTS idx_tasks_phase ON tasks(phase);
142
- CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
143
- CREATE INDEX IF NOT EXISTS idx_tasks_created_at ON tasks(created_at);
144
-
145
- CREATE TABLE IF NOT EXISTS task_comments (
146
- id TEXT PRIMARY KEY,
147
- task_id TEXT NOT NULL,
148
- repo TEXT NOT NULL,
149
- comment TEXT NOT NULL,
150
- agent TEXT NOT NULL DEFAULT 'unknown',
151
- role TEXT NOT NULL DEFAULT 'unknown',
152
- model TEXT NOT NULL DEFAULT 'unknown',
153
- previous_status TEXT,
154
- next_status TEXT,
155
- created_at TEXT NOT NULL,
156
- FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
157
- );
158
-
159
- CREATE INDEX IF NOT EXISTS idx_task_comments_task_id ON task_comments(task_id);
160
- CREATE INDEX IF NOT EXISTS idx_task_comments_repo ON task_comments(repo);
161
- CREATE INDEX IF NOT EXISTS idx_task_comments_created_at ON task_comments(created_at DESC);
162
-
163
- CREATE TABLE IF NOT EXISTS memories_archive (
164
- id TEXT PRIMARY KEY,
165
- repo TEXT NOT NULL,
166
- type TEXT NOT NULL,
167
- content TEXT NOT NULL,
168
- importance INTEGER NOT NULL,
169
- folder TEXT,
170
- language TEXT,
171
- created_at TEXT NOT NULL,
172
- updated_at TEXT NOT NULL,
173
- hit_count INTEGER NOT NULL DEFAULT 0,
174
- recall_count INTEGER NOT NULL DEFAULT 0,
175
- last_used_at TEXT,
176
- expires_at TEXT,
177
- archived_at TEXT NOT NULL,
178
- agent TEXT NOT NULL DEFAULT 'unknown',
179
- role TEXT NOT NULL DEFAULT 'unknown',
180
- model TEXT NOT NULL DEFAULT 'unknown',
181
- completed_at TEXT
182
- );
183
-
184
- CREATE TABLE IF NOT EXISTS action_log (
185
- id INTEGER PRIMARY KEY AUTOINCREMENT,
186
- action TEXT NOT NULL,
187
- query TEXT,
188
- response TEXT,
189
- memory_id TEXT,
190
- task_id TEXT,
191
- repo TEXT NOT NULL,
192
- result_count INTEGER NOT NULL DEFAULT 0,
193
- created_at TEXT NOT NULL
194
- );
195
-
196
- CREATE INDEX IF NOT EXISTS idx_action_log_repo ON action_log(repo);
197
- CREATE INDEX IF NOT EXISTS idx_action_log_created_at ON action_log(created_at);
198
- `);
199
- // 2. Safely add missing columns for existing tables
200
- const columnsToAdd = [
201
- { name: "title", table: "memories", definition: "ALTER TABLE memories ADD COLUMN title TEXT" },
202
- { name: "hit_count", table: "memories", definition: "ALTER TABLE memories ADD COLUMN hit_count INTEGER NOT NULL DEFAULT 0" },
203
- { name: "recall_count", table: "memories", definition: "ALTER TABLE memories ADD COLUMN recall_count INTEGER NOT NULL DEFAULT 0" },
204
- { name: "last_used_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN last_used_at TEXT" },
205
- { name: "expires_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN expires_at TEXT" },
206
- { name: "supersedes", table: "memories", definition: "ALTER TABLE memories ADD COLUMN supersedes TEXT" },
207
- { name: "status", table: "memories", definition: "ALTER TABLE memories ADD COLUMN status TEXT NOT NULL DEFAULT 'active'" },
208
- { name: "is_global", table: "memories", definition: "ALTER TABLE memories ADD COLUMN is_global INTEGER NOT NULL DEFAULT 0" },
209
- { name: "tags", table: "memories", definition: "ALTER TABLE memories ADD COLUMN tags TEXT" },
210
- { name: "metadata", table: "memories", definition: "ALTER TABLE memories ADD COLUMN metadata TEXT" },
211
- { name: "vector_version", table: "memory_vectors", definition: "ALTER TABLE memory_vectors ADD COLUMN vector_version INTEGER NOT NULL DEFAULT 1" },
212
- { name: "depends_on", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN depends_on TEXT" },
213
- { name: "est_tokens", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN est_tokens INTEGER NOT NULL DEFAULT 0" },
214
- { name: "in_progress_at", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN in_progress_at TEXT" },
215
- { name: "task_code", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN task_code TEXT" },
216
- { name: "task_id", table: "action_log", definition: "ALTER TABLE action_log ADD COLUMN task_id TEXT" },
217
- { name: "agent", table: "memories", definition: "ALTER TABLE memories ADD COLUMN agent TEXT NOT NULL DEFAULT 'unknown'" },
218
- { name: "role", table: "memories", definition: "ALTER TABLE memories ADD COLUMN role TEXT NOT NULL DEFAULT 'unknown'" },
219
- { name: "model", table: "memories", definition: "ALTER TABLE memories ADD COLUMN model TEXT NOT NULL DEFAULT 'unknown'" },
220
- { name: "completed_at", table: "memories", definition: "ALTER TABLE memories ADD COLUMN completed_at TEXT" },
221
- { name: "agent", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN agent TEXT NOT NULL DEFAULT 'unknown'" },
222
- { name: "role", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN role TEXT NOT NULL DEFAULT 'unknown'" },
223
- { name: "doc_path", table: "tasks", definition: "ALTER TABLE tasks ADD COLUMN doc_path TEXT" },
224
- { name: "response", table: "action_log", definition: "ALTER TABLE action_log ADD COLUMN response TEXT" },
225
- ];
226
- for (const col of columnsToAdd) {
227
- try {
228
- const tableInfo = this.db.prepare(`PRAGMA table_info(${col.table})`).all();
229
- const existingTableColumns = tableInfo.map((c) => c.name);
230
- // Only run ALTER TABLE if table exists and column doesn't
231
- if (tableInfo.length > 0 && !existingTableColumns.includes(col.name)) {
232
- this.db.exec(col.definition);
233
- }
234
- }
235
- catch (e) {
236
- // Skip safely
237
- }
238
- }
239
- this.ensureMemoryTypeConstraint();
240
- this.ensureTaskStatusConstraintRemoved();
241
- this.ensureMemoryStatusConstraintRemoved();
242
- this.db.exec(`
243
- CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
244
- CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes);
245
- CREATE INDEX IF NOT EXISTS idx_memories_is_global ON memories(is_global);
246
- `);
247
- // Backfill task_code if it was added via migration
248
- try {
249
- this.db.exec("UPDATE tasks SET task_code = substr(id, 1, 8) WHERE task_code IS NULL");
250
- }
251
- catch (e) { }
252
- }
253
- insert(entry) {
254
- const stmt = this.db.prepare(`
255
- INSERT INTO memories (
256
- id, repo, type, title, content, importance, folder, language,
257
- created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
258
- supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
259
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
260
- `);
261
- stmt.run(entry.id, entry.scope.repo, entry.type, entry.title || null, entry.content, entry.importance, entry.scope.folder || null, entry.scope.language || null, entry.created_at, entry.updated_at, entry.expires_at ?? null, entry.supersedes ?? null, entry.status || "active", entry.is_global ? 1 : 0, entry.tags ? JSON.stringify(entry.tags) : null, entry.metadata ? JSON.stringify(entry.metadata) : null, entry.agent || 'unknown', entry.role || 'unknown', entry.model || 'unknown', entry.completed_at || null);
262
- }
263
- update(id, updates) {
264
- const fields = [];
265
- const values = [];
266
- Object.keys(updates).forEach(key => {
267
- if (updates[key] !== undefined) {
268
- if (key === 'tags') {
269
- fields.push(`tags = ?`);
270
- values.push(JSON.stringify(updates[key]));
271
- }
272
- else if (key === 'metadata') {
273
- fields.push(`metadata = ?`);
274
- values.push(JSON.stringify(updates[key]));
275
- }
276
- else if (key === 'is_global') {
277
- fields.push(`is_global = ?`);
278
- values.push(updates[key] ? 1 : 0);
279
- }
280
- else {
281
- fields.push(`${key} = ?`);
282
- values.push(updates[key]);
283
- }
284
- }
285
- });
286
- if (fields.length === 0)
287
- return;
288
- fields.push("updated_at = ?");
289
- values.push(new Date().toISOString());
290
- values.push(id);
291
- const stmt = this.db.prepare(`UPDATE memories SET ${fields.join(", ")} WHERE id = ?`);
292
- stmt.run(...values);
293
- }
294
- ensureMemoryTypeConstraint() {
295
- const tableSql = this.db
296
- .prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'")
297
- .get();
298
- if (!tableSql?.sql || !tableSql.sql.includes("CHECK (type IN")) {
299
- return;
300
- }
301
- this.db.exec(`
302
- BEGIN TRANSACTION;
303
-
304
- CREATE TABLE memories__migrated (
305
- id TEXT PRIMARY KEY,
306
- repo TEXT NOT NULL,
307
- type TEXT NOT NULL,
308
- title TEXT,
309
- content TEXT NOT NULL,
310
- importance INTEGER NOT NULL CHECK (importance BETWEEN 1 AND 5),
311
- folder TEXT,
312
- language TEXT,
313
- created_at TEXT NOT NULL,
314
- updated_at TEXT NOT NULL,
315
- hit_count INTEGER NOT NULL DEFAULT 0,
316
- recall_count INTEGER NOT NULL DEFAULT 0,
317
- last_used_at TEXT,
318
- expires_at TEXT,
319
- supersedes TEXT,
320
- status TEXT NOT NULL DEFAULT 'active',
321
- is_global INTEGER NOT NULL DEFAULT 0,
322
- tags TEXT,
323
- metadata TEXT,
324
- agent TEXT NOT NULL DEFAULT 'unknown',
325
- role TEXT NOT NULL DEFAULT 'unknown',
326
- model TEXT NOT NULL DEFAULT 'unknown',
327
- completed_at TEXT
328
- );
329
-
330
- INSERT INTO memories__migrated (
331
- id, repo, type, title, content, importance, folder, language,
332
- created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
333
- supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
334
- )
335
- SELECT
336
- id, repo, type, title, content, importance, folder, language,
337
- created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
338
- supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
339
- FROM memories;
340
-
341
- DROP TABLE memories;
342
- ALTER TABLE memories__migrated RENAME TO memories;
343
-
344
- COMMIT;
345
- `);
346
- }
347
- ensureTaskStatusConstraintRemoved() {
348
- const tableSql = this.db
349
- .prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'tasks'")
350
- .get();
351
- // Check if status column has the old restrictive CHECK constraint or old default 'pending'
352
- if (!tableSql?.sql || (!tableSql.sql.includes("CHECK (status IN") && !tableSql.sql.includes("DEFAULT 'pending'"))) {
353
- return;
354
- }
355
- this.db.exec(`
356
- BEGIN TRANSACTION;
357
-
358
- CREATE TABLE tasks__migrated (
359
- id TEXT PRIMARY KEY,
360
- repo TEXT NOT NULL,
361
- task_code TEXT NOT NULL,
362
- phase TEXT,
363
- title TEXT NOT NULL,
364
- description TEXT,
365
- status TEXT NOT NULL DEFAULT 'backlog',
366
- priority INTEGER NOT NULL DEFAULT 3,
367
- agent TEXT NOT NULL DEFAULT 'unknown',
368
- role TEXT NOT NULL DEFAULT 'unknown',
369
- doc_path TEXT,
370
- created_at TEXT NOT NULL,
371
- updated_at TEXT NOT NULL,
372
- finished_at TEXT,
373
- canceled_at TEXT,
374
- tags TEXT,
375
- metadata TEXT,
376
- parent_id TEXT,
377
- depends_on TEXT,
378
- est_tokens INTEGER NOT NULL DEFAULT 0,
379
- in_progress_at TEXT,
380
- FOREIGN KEY (parent_id) REFERENCES tasks(id) ON DELETE SET NULL,
381
- FOREIGN KEY (depends_on) REFERENCES tasks(id) ON DELETE SET NULL
382
- );
383
-
384
- INSERT INTO tasks__migrated (
385
- id, repo, task_code, phase, title, description, status, priority,
386
- agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
387
- )
388
- SELECT
389
- id, repo, task_code, phase, title, description, status, priority,
390
- agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
391
- FROM tasks;
392
-
393
- DROP TABLE tasks;
394
- ALTER TABLE tasks__migrated RENAME TO tasks;
395
-
396
- COMMIT;
397
- `);
398
- }
399
- ensureMemoryStatusConstraintRemoved() {
400
- const tableSql = this.db
401
- .prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'memories'")
402
- .get();
403
- // Check if status column has any check constraint
404
- if (!tableSql?.sql || !tableSql.sql.includes("status TEXT NOT NULL DEFAULT 'active' CHECK")) {
405
- if (!tableSql?.sql?.includes("status TEXT NOT NULL DEFAULT 'active'")) {
406
- // If it doesn't even have the status column, it will be added by the general migration loop anyway
407
- }
408
- else if (!tableSql.sql.includes("CHECK")) {
409
- // Already removed or not present
410
- return;
411
- }
412
- }
413
- else {
414
- // Continue to migration
415
- }
416
- // Re-use ensureMemoryTypeConstraint logic or specifically target status if needed.
417
- // Since ensureMemoryTypeConstraint already rebuilds the table without checks on type,
418
- // we just need to make sure it also doesn't have checks on status in its target schema.
419
- // The ensureMemoryTypeConstraint target schema (memories__migrated) already has no status check.
420
- }
421
- getById(id) {
422
- const row = this.db.prepare("SELECT * FROM memories WHERE id = ?").get(id);
423
- return row ? this.rowToMemoryEntry(row) : null;
424
- }
425
- getByIdWithStats(id) {
426
- const row = this.db.prepare(`
427
- SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate
428
- FROM memories WHERE id = ?
429
- `).get(id);
430
- return row ? { ...this.rowToMemoryEntry(row), recall_rate: row.recall_rate ?? 0 } : null;
431
- }
432
- getByIds(ids, filters) {
433
- if (ids.length === 0)
434
- return [];
435
- let query = "SELECT * FROM memories WHERE id IN (" + ids.map(() => "?").join(",") + ")";
436
- const params = [...ids];
437
- if (filters?.type) {
438
- query += " AND type = ?";
439
- params.push(filters.type);
440
- }
441
- if (filters?.status) {
442
- query += " AND status = ?";
443
- params.push(filters.status);
444
- }
445
- const rows = this.db.prepare(query).all(...params);
446
- return rows.map(r => this.rowToMemoryEntry(r));
447
- }
448
- searchByRepo(repo, options = {}) {
449
- let where = ["(repo = ? OR is_global = 1)"];
450
- const params = [repo];
451
- if (options.tags?.length) {
452
- const tagConditions = options.tags.map(() => "tags LIKE ?").join(" OR ");
453
- where.push(`(${tagConditions})`);
454
- options.tags.forEach((tag) => params.push(`%${tag}%`));
455
- }
456
- let query = `SELECT * FROM memories WHERE ${where.join(" AND ")} AND (expires_at IS NULL OR expires_at > datetime('now'))`;
457
- if (!options.includeArchived)
458
- query += " AND status = 'active'";
459
- if (options.types?.length) {
460
- query += ` AND type IN (${options.types.map(() => "?").join(",")})`;
461
- params.push(...options.types);
462
- }
463
- if (options.minImportance) {
464
- query += " AND importance >= ?";
465
- params.push(options.minImportance);
466
- }
467
- query += " ORDER BY CASE WHEN repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC";
468
- params.push(repo);
469
- if (options.limit) {
470
- query += " LIMIT ?";
471
- params.push(options.limit);
472
- }
473
- const rows = this.db.prepare(query).all(...params);
474
- return rows.map(r => this.rowToMemoryEntry(r));
475
- }
476
- searchBySimilarity(query, repo, limit = 10, includeArchived = false, currentTags = []) {
477
- const queryVector = this.computeVector(query);
478
- const now = new Date();
479
- let where = ["(repo = ? OR is_global = 1)"];
480
- const params = [repo];
481
- if (currentTags.length > 0) {
482
- const tagConditions = currentTags.map(() => "tags LIKE ?").join(" OR ");
483
- where.push(`(${tagConditions})`);
484
- currentTags.forEach(tag => params.push(`%${tag}%`));
485
- }
486
- let sql = `SELECT * FROM memories WHERE (${where.join(" OR ")}) AND (expires_at IS NULL OR expires_at > ?)`;
487
- if (!includeArchived)
488
- sql += " AND status = 'active'";
489
- sql += ` ORDER BY CASE WHEN repo = ? THEN 0 ELSE 1 END, importance DESC, created_at DESC LIMIT 100`;
490
- let candidates = this.db.prepare(sql).all(...params, now.toISOString(), repo);
491
- // Ensure we have at least some candidates for re-ranking
492
- if (candidates.length < 5) {
493
- const recentSql = `SELECT * FROM memories WHERE (${where.join(" OR ")}) AND status = 'active' AND (expires_at IS NULL OR expires_at > ?) ORDER BY created_at DESC LIMIT 10`;
494
- const recent = this.db.prepare(recentSql).all(...params, now.toISOString());
495
- for (const r of recent) {
496
- if (!candidates.find(c => c.id === r.id))
497
- candidates.push(r);
498
- }
499
- }
500
- return candidates.map(row => {
501
- const memory = this.rowToMemoryEntry(row);
502
- // Strict validity check
503
- const isExpired = row.expires_at && new Date(row.expires_at) <= now;
504
- const isArchived = row.status === 'archived' && !includeArchived;
505
- if (isExpired || isArchived) {
506
- return { ...memory, similarity: 0 };
507
- }
508
- const similarity = this.cosineSimilarity(queryVector, this.computeVector(memory.content));
509
- let score = similarity;
510
- if (!score) {
511
- score = 0.16; // Baseline for active candidates
512
- }
513
- if (row.repo === repo)
514
- score += 0.1;
515
- return { ...memory, similarity: score };
516
- }).filter(r => r.similarity > 0)
517
- .sort((a, b) => b.similarity - a.similarity)
518
- .slice(0, limit);
519
- }
520
- archiveExpiredMemories(force = false) {
521
- if (process.env.ENABLE_AUTO_ARCHIVE !== "true" && !force)
522
- return 0;
523
- const now = new Date().toISOString();
524
- const result = this.db.prepare(`
525
- UPDATE memories SET status = 'archived', updated_at = ?
526
- WHERE expires_at IS NOT NULL AND expires_at <= ? AND status = 'active'
527
- `).run(now, now);
528
- return result.changes;
529
- }
530
- archiveLowScoreMemories(force = false) {
531
- if (process.env.ENABLE_AUTO_ARCHIVE !== "true" && !force)
532
- return 0;
533
- const result = this.db.prepare(`
534
- UPDATE memories SET status = 'archived', updated_at = ?
535
- WHERE status = 'active' AND (
536
- (julianday('now') - julianday(COALESCE(last_used_at, created_at)) > 90 AND importance < 3)
537
- OR (hit_count > 10 AND recall_count = 0)
538
- )
539
- `).run(new Date().toISOString());
540
- return result.changes;
541
- }
542
- listRecent(limit = 10) {
543
- const stmt = this.db.prepare("SELECT id, type, repo FROM memories ORDER BY created_at DESC LIMIT ?");
544
- return stmt.all(limit);
545
- }
546
- getStats(repo) {
547
- let query = "SELECT type, COUNT(*) as count FROM memories";
548
- const params = [];
549
- if (repo) {
550
- query += " WHERE repo = ?";
551
- params.push(repo);
552
- }
553
- query += " GROUP BY type";
554
- const rows = this.db.prepare(query).all(...params);
555
- const byType = {};
556
- let total = 0;
557
- for (const row of rows) {
558
- byType[row.type] = row.count;
559
- total += row.count;
560
- }
561
- const unusedStmt = repo
562
- ? this.db.prepare("SELECT COUNT(*) as count FROM memories WHERE hit_count = 0 AND repo = ?")
563
- : this.db.prepare("SELECT COUNT(*) as count FROM memories WHERE hit_count = 0");
564
- const unused = (repo ? unusedStmt.get(repo) : unusedStmt.get());
565
- return { total, byType, unused: unused?.count || 0 };
566
- }
567
- getTaskStats(repo) {
568
- let query = "SELECT status, COUNT(*) as count FROM tasks";
569
- const params = [];
570
- if (repo) {
571
- query += " WHERE repo = ?";
572
- params.push(repo);
573
- }
574
- query += " GROUP BY status";
575
- const rows = this.db.prepare(query).all(...params);
576
- const stats = {
577
- total: 0,
578
- backlog: 0,
579
- todo: 0,
580
- inProgress: 0,
581
- completed: 0,
582
- blocked: 0,
583
- canceled: 0
584
- };
585
- for (const row of rows) {
586
- stats.total += row.count;
587
- if (row.status === "backlog")
588
- stats.backlog = row.count;
589
- else if (row.status === "pending")
590
- stats.todo = row.count;
591
- else if (row.status === "in_progress")
592
- stats.inProgress = row.count;
593
- else if (row.status === "completed")
594
- stats.completed = row.count;
595
- else if (row.status === "blocked")
596
- stats.blocked = row.count;
597
- else if (row.status === "canceled")
598
- stats.canceled = row.count;
599
- }
600
- return stats;
601
- }
602
- getDashboardStats(repo) {
603
- const memoryStats = this.getStats(repo);
604
- const taskStats = this.getTaskStats(repo);
605
- // Additional stats for dashboard
606
- let importanceSql = "SELECT AVG(importance) as avg FROM memories";
607
- let hitsSql = "SELECT SUM(hit_count) as totalHits FROM memories";
608
- let expiringSql = "SELECT COUNT(*) as count FROM memories WHERE expires_at IS NOT NULL AND expires_at < date('now', '+7 days')";
609
- const params = [];
610
- if (repo) {
611
- importanceSql += " WHERE repo = ?";
612
- hitsSql += " WHERE repo = ?";
613
- expiringSql += " AND repo = ?";
614
- params.push(repo);
615
- }
616
- const avgImportance = this.db.prepare(importanceSql).get(...params)?.avg || 0;
617
- const totalHitCount = this.db.prepare(hitsSql).get(...params)?.totalHits || 0;
618
- const expiringSoon = this.db.prepare(expiringSql).get(...params)?.count || 0;
619
- // Today's stats
620
- const today = new Date().toISOString().split('T')[0];
621
- let todayAddedSql = "SELECT COUNT(*) as count FROM tasks WHERE date(created_at) = ?";
622
- let todayCompletedSql = "SELECT COUNT(*) as count FROM tasks WHERE status = 'completed' AND date(updated_at) = ?";
623
- let todayProcessedSql = "SELECT COUNT(*) as count FROM task_comments WHERE date(created_at) = ?";
624
- const todayParams = [today];
625
- if (repo) {
626
- todayAddedSql += " AND repo = ?";
627
- todayCompletedSql += " AND repo = ?";
628
- todayProcessedSql += " AND repo = ?";
629
- todayParams.push(repo);
630
- }
631
- const todayAdded = this.db.prepare(todayAddedSql).get(...todayParams)?.count || 0;
632
- const todayCompleted = this.db.prepare(todayCompletedSql).get(...todayParams)?.count || 0;
633
- const todayProcessed = this.db.prepare(todayProcessedSql).get(...todayParams)?.count || 0;
634
- let todayTokensSql = "SELECT SUM(est_tokens) as total FROM tasks WHERE date(updated_at) = ?";
635
- if (repo) {
636
- todayTokensSql += " AND repo = ?";
637
- }
638
- const todayTokens = this.db.prepare(todayTokensSql).get(...todayParams)?.total || 0;
639
- let avgDurationSql = `
640
- SELECT AVG(
641
- (julianday(finished_at) - julianday(in_progress_at)) * 86400.0
642
- ) as avg_seconds
643
- FROM tasks
644
- WHERE status = 'completed'
645
- AND in_progress_at IS NOT NULL
646
- AND finished_at IS NOT NULL
647
- AND date(finished_at) = ?
648
- `;
649
- if (repo) {
650
- avgDurationSql += " AND repo = ?";
651
- }
652
- const avgDurationSeconds = this.db.prepare(avgDurationSql).get(...todayParams)?.avg_seconds || 0;
653
- return {
654
- ...memoryStats,
655
- avgImportance: avgImportance.toFixed(1),
656
- totalHitCount,
657
- expiringSoon,
658
- todayAdded,
659
- todayCompleted,
660
- todayProcessed,
661
- todayTokens,
662
- todayAvgDuration: avgDurationSeconds,
663
- taskStats
664
- };
665
- }
666
- listRepoNavigation() {
667
- return this.db.prepare(`
668
- SELECT
669
- repo,
670
- SUM(memory_count) as memory_count,
671
- MAX(last_updated_at) as last_updated_at,
672
- SUM(pending_count) as pending_count,
673
- SUM(in_progress_count) as in_progress_count,
674
- SUM(blocked_count) as blocked_count,
675
- SUM(backlog_count) as backlog_count
676
- FROM (
677
- SELECT
678
- repo,
679
- COUNT(id) as memory_count,
680
- MAX(COALESCE(updated_at, created_at)) as last_updated_at,
681
- 0 as pending_count,
682
- 0 as in_progress_count,
683
- 0 as blocked_count,
684
- 0 as backlog_count
685
- FROM memories
686
- GROUP BY repo
687
- UNION ALL
688
- SELECT
689
- repo,
690
- 0 as memory_count,
691
- MAX(COALESCE(updated_at, created_at)) as last_updated_at,
692
- SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_count,
693
- SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END) as in_progress_count,
694
- SUM(CASE WHEN status = 'blocked' THEN 1 ELSE 0 END) as blocked_count,
695
- SUM(CASE WHEN status = 'backlog' THEN 1 ELSE 0 END) as backlog_count
696
- FROM tasks
697
- GROUP BY repo
698
- )
699
- GROUP BY repo
700
- ORDER BY last_updated_at DESC, repo ASC
701
- `).all();
702
- }
703
- getAllMemoriesWithStats(repo) {
704
- let sql = `SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate FROM memories`;
705
- if (repo)
706
- return this.db.prepare(sql + " WHERE repo = ?").all(repo);
707
- return this.db.prepare(sql).all();
708
- }
709
- getLastActionId() {
710
- const row = this.db.prepare("SELECT MAX(id) as id FROM action_log").get();
711
- return row?.id || 0;
712
- }
713
- getActionsAfter(id) {
714
- return this.db.prepare(`
715
- SELECT a.*, m.title as memory_title, m.type as memory_type
716
- FROM action_log a LEFT JOIN memories m ON a.memory_id = m.id
717
- WHERE a.id > ? ORDER BY a.created_at ASC
718
- `).all(id);
719
- }
720
- getActionStatsByDate(repo, days = 30) {
721
- let sql = `
722
- SELECT
723
- strftime('%Y-%m-%d', created_at) as date,
724
- action,
725
- COUNT(*) as count
726
- FROM action_log
727
- WHERE created_at >= date('now', '-' || ? || ' days')
728
- `;
729
- const params = [days];
730
- if (repo) {
731
- sql += " AND repo = ?";
732
- params.push(repo);
733
- }
734
- sql += " GROUP BY date, action ORDER BY date ASC";
735
- return this.db.prepare(sql).all(...params);
736
- }
737
- listMemoriesForDashboard(options) {
738
- const { repo, type, tag, isGlobal, minImportance, search, offset = 0, limit = 50, sortBy = 'created_at', sortOrder = 'DESC' } = options;
739
- let where = ["1=1"];
740
- const params = [];
741
- if (repo) {
742
- where.push("repo = ?");
743
- params.push(repo);
744
- }
745
- if (type) {
746
- where.push("type = ?");
747
- params.push(type);
748
- }
749
- if (tag) {
750
- where.push("tags LIKE ?");
751
- params.push(`%${tag}%`);
752
- }
753
- if (isGlobal !== undefined) {
754
- where.push("is_global = ?");
755
- params.push(isGlobal ? 1 : 0);
756
- }
757
- if (minImportance) {
758
- where.push("importance >= ?");
759
- params.push(minImportance);
760
- }
761
- if (search) {
762
- where.push("(title LIKE ? OR content LIKE ? OR tags LIKE ?)");
763
- params.push(`%${search}%`, `%${search}%`, `%${search}%`);
764
- }
765
- const countStmt = this.db.prepare(`SELECT COUNT(*) as count FROM memories WHERE ${where.join(" AND ")}`);
766
- const total = countStmt.get(...params).count;
767
- let orderBy = "";
768
- if (sortBy && sortOrder) {
769
- orderBy = `ORDER BY ${sortBy} ${sortOrder}`;
770
- }
771
- else {
772
- orderBy = `ORDER BY importance DESC, created_at ASC`;
773
- }
774
- const dataStmt = this.db.prepare(`
775
- SELECT *, CASE WHEN hit_count > 0 THEN CAST(recall_count AS REAL) / hit_count ELSE 0 END AS recall_rate
776
- FROM memories WHERE ${where.join(" AND ")}
777
- ${orderBy} LIMIT ? OFFSET ?
778
- `);
779
- const rows = dataStmt.all(...params, limit, offset);
780
- const items = rows.map(row => ({
781
- ...this.rowToMemoryEntry(row),
782
- recall_rate: row.recall_rate ?? 0
783
- }));
784
- return { items, memories: items, total, limit, offset };
785
- }
786
- getSummary(repo) {
787
- return this.db.prepare("SELECT summary, updated_at FROM memory_summary WHERE repo = ?").get(repo);
788
- }
789
- upsertSummary(repo, summary) {
790
- this.db.prepare(`
791
- INSERT INTO memory_summary (repo, summary, updated_at) VALUES (?, ?, ?)
792
- ON CONFLICT(repo) DO UPDATE SET summary = excluded.summary, updated_at = excluded.updated_at
793
- `).run(repo, summary, new Date().toISOString());
794
- }
795
- delete(id) {
796
- this.db.prepare("DELETE FROM memories WHERE id = ?").run(id);
797
- }
798
- bulkInsertMemories(entries) {
799
- const insert = this.db.prepare(`
800
- INSERT INTO memories (
801
- id, repo, type, title, content, importance, folder, language,
802
- created_at, updated_at, hit_count, recall_count, last_used_at, expires_at,
803
- supersedes, status, is_global, tags, metadata, agent, role, model, completed_at
804
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
805
- `);
806
- const insertMany = this.db.transaction((entries) => {
807
- let count = 0;
808
- for (const entry of entries) {
809
- insert.run(entry.id, entry.scope.repo, entry.type, entry.title || null, entry.content, entry.importance, entry.scope.folder || null, entry.scope.language || null, entry.created_at, entry.updated_at, entry.expires_at ?? null, entry.supersedes ?? null, entry.status || "active", entry.is_global ? 1 : 0, entry.tags ? JSON.stringify(entry.tags) : null, entry.metadata ? JSON.stringify(entry.metadata) : null, entry.agent || 'unknown', entry.role || 'unknown', entry.model || 'unknown', entry.completed_at || null);
810
- count++;
811
- }
812
- return count;
813
- });
814
- return insertMany(entries);
815
- }
816
- bulkInsertTasks(tasks) {
817
- const insert = this.db.prepare(`
818
- INSERT INTO tasks (
819
- id, repo, task_code, phase, title, description, status, priority,
820
- agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
821
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
822
- `);
823
- const insertMany = this.db.transaction((tasks) => {
824
- let count = 0;
825
- for (const task of tasks) {
826
- insert.run(task.id, task.repo, task.task_code, task.phase || null, task.title, task.description || null, task.status || "backlog", task.priority || 3, task.agent || 'unknown', task.role || 'unknown', task.doc_path || null, task.created_at, task.updated_at, task.finished_at || null, task.canceled_at || null, task.tags ? JSON.stringify(task.tags) : null, task.metadata ? JSON.stringify(task.metadata) : null, task.parent_id || null, task.depends_on || null, task.est_tokens || 0, task.in_progress_at || null);
827
- count++;
828
- }
829
- return count;
830
- });
831
- return insertMany(tasks);
832
- }
833
- bulkUpdateMemories(ids, updates) {
834
- if (ids.length === 0)
835
- return 0;
836
- const fields = [];
837
- const values = [];
838
- Object.keys(updates).forEach(key => {
839
- if (updates[key] !== undefined) {
840
- if (key === 'tags' || key === 'metadata') {
841
- fields.push(`${key} = ?`);
842
- values.push(JSON.stringify(updates[key]));
843
- }
844
- else if (key === 'is_global') {
845
- fields.push(`${key} = ?`);
846
- values.push(updates[key] ? 1 : 0);
847
- }
848
- else {
849
- fields.push(`${key} = ?`);
850
- values.push(updates[key]);
851
- }
852
- }
853
- });
854
- if (fields.length === 0)
855
- return 0;
856
- fields.push("updated_at = ?");
857
- values.push(new Date().toISOString());
858
- const updateMany = this.db.transaction((ids, fields, values) => {
859
- let count = 0;
860
- const chunkSize = 500;
861
- for (let i = 0; i < ids.length; i += chunkSize) {
862
- const chunk = ids.slice(i, i + chunkSize);
863
- const stmt = this.db.prepare(`UPDATE memories SET ${fields.join(", ")} WHERE id IN (${chunk.map(() => '?').join(',')})`);
864
- const result = stmt.run(...values, ...chunk);
865
- count += result.changes;
866
- }
867
- return count;
868
- });
869
- return updateMany(ids, fields, values);
870
- }
871
- bulkDeleteMemories(ids) {
872
- if (ids.length === 0)
873
- return 0;
874
- const deleteMany = this.db.transaction((ids) => {
875
- let count = 0;
876
- const chunkSize = 500;
877
- for (let i = 0; i < ids.length; i += chunkSize) {
878
- const chunk = ids.slice(i, i + chunkSize);
879
- const stmt = this.db.prepare(`DELETE FROM memories WHERE id IN (${chunk.map(() => '?').join(',')})`);
880
- const result = stmt.run(...chunk);
881
- count += result.changes;
882
- }
883
- return count;
884
- });
885
- return deleteMany(ids);
886
- }
887
- listRepos() {
888
- return this.db.prepare("SELECT DISTINCT repo FROM memories ORDER BY repo").all().map(r => r.repo);
889
- }
890
- incrementHitCount(id) {
891
- this.db.prepare("UPDATE memories SET hit_count = hit_count + 1, last_used_at = ? WHERE id = ?").run(new Date().toISOString(), id);
892
- }
893
- incrementHitCounts(ids) {
894
- if (!ids || ids.length === 0)
895
- return;
896
- const stmt = this.db.prepare("UPDATE memories SET hit_count = hit_count + 1, last_used_at = ? WHERE id = ?");
897
- const now = new Date().toISOString();
898
- const transaction = this.db.transaction((idsToUpdate) => {
899
- for (const id of idsToUpdate) {
900
- stmt.run(now, id);
901
- }
902
- });
903
- transaction(ids);
904
- }
905
- incrementRecallCount(id) {
906
- this.db.prepare("UPDATE memories SET recall_count = recall_count + 1, last_used_at = ? WHERE id = ?").run(new Date().toISOString(), id);
907
- }
908
- insertTask(task) {
909
- const stmt = this.db.prepare(`
910
- INSERT INTO tasks (
911
- id, repo, task_code, phase, title, description, status, priority,
912
- agent, role, doc_path, created_at, updated_at, finished_at, canceled_at, tags, metadata, parent_id, depends_on, est_tokens, in_progress_at
913
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
914
- `);
915
- stmt.run(task.id, task.repo, task.task_code, task.phase || null, task.title, task.description || null, task.status || "backlog", task.priority || 3, task.agent || 'unknown', task.role || 'unknown', task.doc_path || null, task.created_at, task.updated_at, task.finished_at || null, task.canceled_at || null, task.tags ? JSON.stringify(task.tags) : null, task.metadata ? JSON.stringify(task.metadata) : null, task.parent_id || null, task.depends_on || null, task.est_tokens || 0, task.in_progress_at || null);
916
- }
917
- updateTask(id, updates) {
918
- const fields = [];
919
- const values = [];
920
- Object.keys(updates).forEach(key => {
921
- if (key !== "comment" && key !== "model" && updates[key] !== undefined) {
922
- if (key === 'tags' || key === 'metadata') {
923
- fields.push(`${key} = ?`);
924
- values.push(JSON.stringify(updates[key]));
925
- }
926
- else {
927
- fields.push(`${key} = ?`);
928
- values.push(updates[key]);
929
- }
930
- }
931
- });
932
- if (fields.length === 0)
933
- return;
934
- fields.push("updated_at = ?");
935
- values.push(new Date().toISOString());
936
- values.push(id);
937
- const stmt = this.db.prepare(`UPDATE tasks SET ${fields.join(", ")} WHERE id = ?`);
938
- stmt.run(...values);
939
- }
940
- getTasksByRepo(repo, status, limit, offset, search) {
941
- let query = `
942
- SELECT t.*, d.task_code as depends_on_code,
943
- (SELECT COUNT(*) FROM task_comments WHERE task_id = t.id) as comments_count
944
- FROM tasks t
945
- LEFT JOIN tasks d ON t.depends_on = d.id
946
- WHERE t.repo = ?
947
- `;
948
- const params = [repo];
949
- if (status) {
950
- query += " AND t.status = ?";
951
- params.push(status);
952
- }
953
- if (search) {
954
- query += " AND (t.title LIKE ? OR t.description LIKE ? OR t.task_code LIKE ?)";
955
- const searchPattern = `%${search}%`;
956
- params.push(searchPattern, searchPattern, searchPattern);
957
- }
958
- // Default sorting logic for the unified list:
959
- // 1. Completed tasks at the bottom (or top if specified)
960
- // 2. Priority for others
961
- // 3. Updated date (newest first for completed)
962
- query += ` ORDER BY
963
- CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END ASC,
964
- CASE WHEN t.status = 'completed' THEN t.updated_at ELSE NULL END DESC,
965
- CASE WHEN t.status = 'in_progress' THEN 0
966
- WHEN t.status = 'pending' THEN 1
967
- WHEN t.status = 'backlog' THEN 2
968
- WHEN t.status = 'blocked' THEN 3
969
- WHEN t.status = 'canceled' THEN 4
970
- ELSE 5 END ASC,
971
- t.priority DESC,
972
- t.created_at ASC`;
973
- if (limit !== undefined) {
974
- query += " LIMIT ?";
975
- params.push(limit);
976
- if (offset !== undefined) {
977
- query += " OFFSET ?";
978
- params.push(offset);
979
- }
980
- }
981
- const rows = this.db.prepare(query).all(...params);
982
- return rows.map(r => this.rowToTask(r));
983
- }
984
- getTasksByMultipleStatuses(repo, statuses, limit, offset, search) {
985
- if (!statuses.length)
986
- return this.getTasksByRepo(repo, undefined, limit, offset, search);
987
- let query = `
988
- SELECT t.*, d.task_code as depends_on_code,
989
- (SELECT COUNT(*) FROM task_comments WHERE task_id = t.id) as comments_count
990
- FROM tasks t
991
- LEFT JOIN tasks d ON t.depends_on = d.id
992
- WHERE t.repo = ? AND t.status IN (${statuses.map(() => '?').join(',')})
993
- `;
994
- const params = [repo, ...statuses];
995
- if (search) {
996
- query += " AND (t.title LIKE ? OR t.description LIKE ? OR t.task_code LIKE ?)";
997
- const searchPattern = `%${search}%`;
998
- params.push(searchPattern, searchPattern, searchPattern);
999
- }
1000
- query += ` ORDER BY
1001
- CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END ASC,
1002
- CASE WHEN t.status = 'completed' THEN t.updated_at ELSE NULL END DESC,
1003
- CASE WHEN t.status = 'in_progress' THEN 0
1004
- WHEN t.status = 'pending' THEN 1
1005
- WHEN t.status = 'backlog' THEN 2
1006
- WHEN t.status = 'blocked' THEN 3
1007
- WHEN t.status = 'canceled' THEN 4
1008
- ELSE 5 END ASC,
1009
- t.priority DESC,
1010
- t.created_at ASC`;
1011
- if (limit !== undefined) {
1012
- query += " LIMIT ?";
1013
- params.push(limit);
1014
- if (offset !== undefined) {
1015
- query += " OFFSET ?";
1016
- params.push(offset);
1017
- }
1018
- }
1019
- const rows = this.db.prepare(query).all(...params);
1020
- return rows.map(r => this.rowToTask(r));
1021
- }
1022
- deleteTask(id) {
1023
- this.db.prepare("DELETE FROM task_comments WHERE task_id = ?").run(id);
1024
- this.db.prepare("DELETE FROM tasks WHERE id = ?").run(id);
1025
- }
1026
- getTaskById(id) {
1027
- const row = this.db.prepare(`
1028
- SELECT t.*, d.task_code as depends_on_code
1029
- FROM tasks t
1030
- LEFT JOIN tasks d ON t.depends_on = d.id
1031
- WHERE t.id = ?
1032
- `).get(id);
1033
- return row ? { ...this.rowToTask(row), comments: this.getTaskCommentsByTaskId(id) } : null;
1034
- }
1035
- getTaskByCode(repo, taskCode) {
1036
- const row = this.db.prepare(`
1037
- SELECT t.*, d.task_code as depends_on_code
1038
- FROM tasks t
1039
- LEFT JOIN tasks d ON t.depends_on = d.id
1040
- WHERE t.repo = ? AND t.task_code = ?
1041
- `).get(repo, taskCode);
1042
- return row ? { ...this.rowToTask(row), comments: this.getTaskCommentsByTaskId(row.id) } : null;
1043
- }
1044
- isTaskCodeDuplicate(repo, task_code, excludeId) {
1045
- let query = "SELECT COUNT(*) as count FROM tasks WHERE repo = ? AND task_code = ?";
1046
- const params = [repo, task_code];
1047
- if (excludeId) {
1048
- query += " AND id != ?";
1049
- params.push(excludeId);
1050
- }
1051
- const row = this.db.prepare(query).get(...params);
1052
- return row.count > 0;
1053
- }
1054
- rowToTask(row) {
1055
- let tags = [];
1056
- let metadata = {};
1057
- try {
1058
- if (row.tags)
1059
- tags = JSON.parse(row.tags);
1060
- if (row.metadata)
1061
- metadata = JSON.parse(row.metadata);
1062
- }
1063
- catch (e) { }
1064
- return {
1065
- ...row,
1066
- agent: row.agent || 'unknown',
1067
- role: row.role || 'unknown',
1068
- doc_path: row.doc_path || null,
1069
- tags,
1070
- metadata,
1071
- est_tokens: row.est_tokens || 0,
1072
- in_progress_at: row.in_progress_at || null
1073
- };
1074
- }
1075
- insertTaskComment(comment) {
1076
- this.db.prepare(`
1077
- INSERT INTO task_comments (
1078
- id, task_id, repo, comment, agent, role, model, previous_status, next_status, created_at
1079
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
1080
- `).run(comment.id, comment.task_id, comment.repo, comment.comment, comment.agent || "unknown", comment.role || "unknown", comment.model || "unknown", comment.previous_status || null, comment.next_status || null, comment.created_at);
1081
- }
1082
- getTaskCommentsByTaskId(taskId) {
1083
- return this.db.prepare(`
1084
- SELECT * FROM task_comments
1085
- WHERE task_id = ?
1086
- ORDER BY created_at DESC, id DESC
1087
- `).all(taskId);
1088
- }
1089
- getAllTaskCommentsByRepo(repo) {
1090
- return this.db.prepare(`
1091
- SELECT * FROM task_comments
1092
- WHERE repo = ?
1093
- ORDER BY created_at DESC, id DESC
1094
- `).all(repo);
1095
- }
1096
- getRecentMemories(repo, limit, offset = 0, includeArchived = false, excludeTypes = []) {
1097
- let query = "SELECT * FROM memories WHERE repo = ?";
1098
- const params = [repo];
1099
- if (!includeArchived) {
1100
- query += " AND status = 'active'";
1101
- }
1102
- if (excludeTypes.length > 0) {
1103
- query += ` AND type NOT IN (${excludeTypes.map(() => '?').join(',')})`;
1104
- params.push(...excludeTypes);
1105
- }
1106
- query += " ORDER BY created_at DESC LIMIT ? OFFSET ?";
1107
- params.push(limit, offset);
1108
- const stmt = this.db.prepare(query);
1109
- const rows = stmt.all(...params);
1110
- return rows.map((row) => this.rowToMemoryEntry(row));
1111
- }
1112
- getTotalCount(repo, includeArchived = false, excludeTypes = []) {
1113
- let sql = "SELECT COUNT(*) as count FROM memories WHERE repo = ?";
1114
- const params = [repo];
1115
- if (!includeArchived)
1116
- sql += " AND status = 'active'";
1117
- if (excludeTypes.length > 0) {
1118
- sql += ` AND type NOT IN (${excludeTypes.map(() => '?').join(',')})`;
1119
- params.push(...excludeTypes);
1120
- }
1121
- return this.db.prepare(sql).get(...params).count;
1122
- }
1123
- getVectorCandidates(repo, limit = 100) {
1124
- let sql = `SELECT mv.memory_id, mv.vector FROM memory_vectors mv JOIN memories m ON mv.memory_id = m.id`;
1125
- const params = [];
1126
- if (repo) {
1127
- sql += " WHERE m.repo = ?";
1128
- params.push(repo);
1129
- }
1130
- sql += " LIMIT ?";
1131
- params.push(limit);
1132
- return this.db.prepare(sql).all(...params);
1133
- }
1134
- upsertVectorEmbedding(memoryId, vector) {
1135
- this.db.prepare(`
1136
- INSERT INTO memory_vectors (memory_id, vector, updated_at) VALUES (?, ?, ?)
1137
- ON CONFLICT(memory_id) DO UPDATE SET vector = excluded.vector, updated_at = excluded.updated_at
1138
- `).run(memoryId, JSON.stringify(vector), new Date().toISOString());
1139
- }
1140
- async checkConflicts(content, repo, type, vectors, threshold = 0.55) {
1141
- const vectorResults = await vectors.search(content, 10, repo);
1142
- const candidateIds = vectorResults
1143
- .filter((vr) => vr.score > threshold)
1144
- .map((vr) => vr.id);
1145
- if (candidateIds.length === 0)
1146
- return null;
1147
- const memories = this.getByIds(candidateIds, { type, status: "active" });
1148
- const memoryMap = new Map(memories.map(m => [m.id, m]));
1149
- // Iterate through original vector results to maintain score priority
1150
- for (const vr of vectorResults) {
1151
- if (vr.score > threshold) {
1152
- const memory = memoryMap.get(vr.id);
1153
- if (memory)
1154
- return memory;
1155
- }
1156
- }
1157
- return null;
1158
- }
1159
- logAction(action, repo, options = {}) {
1160
- this.db.prepare(`INSERT INTO action_log (action, query, response, memory_id, task_id, repo, result_count, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(action, options.query || null, options.response ? (typeof options.response === 'string' ? options.response : JSON.stringify(options.response)) : null, options.memoryId || null, options.taskId || null, repo, options.resultCount || 0, new Date().toISOString());
1161
- }
1162
- getRecentActions(repo, limit = 20) {
1163
- let sql = `
1164
- SELECT
1165
- a.*,
1166
- m.title as memory_title,
1167
- m.type as memory_type,
1168
- t.title as task_title,
1169
- t.task_code as task_code
1170
- FROM action_log a
1171
- LEFT JOIN memories m ON a.memory_id = m.id
1172
- LEFT JOIN tasks t ON a.task_id = t.id
1173
- `;
1174
- const params = [];
1175
- if (repo) {
1176
- sql += ` WHERE a.repo = ?`;
1177
- params.push(repo);
1178
- }
1179
- sql += ` ORDER BY a.created_at DESC, a.id DESC LIMIT ?`;
1180
- params.push(limit);
1181
- return this.db.prepare(sql).all(...params);
1182
- }
1183
- computeVector(text) {
1184
- const tokens = tokenize(text);
1185
- const vector = {};
1186
- for (const token of tokens)
1187
- vector[token] = (vector[token] || 0) + 1;
1188
- return vector;
1189
- }
1190
- cosineSimilarity(v1, v2) {
1191
- const keys1 = Object.keys(v1);
1192
- if (!keys1.length || !Object.keys(v2).length)
1193
- return 0;
1194
- let dotProduct = 0;
1195
- for (const key of keys1)
1196
- if (v2[key])
1197
- dotProduct += v1[key] * v2[key];
1198
- const mag1 = Math.sqrt(keys1.reduce((sum, k) => sum + v1[k] * v1[k], 0));
1199
- const mag2 = Math.sqrt(Object.keys(v2).reduce((sum, k) => sum + v2[k] * v2[k], 0));
1200
- return (mag1 && mag2) ? dotProduct / (mag1 * mag2) : 0;
1201
- }
1202
- rowToMemoryEntry(row) {
1203
- let tags = [];
1204
- let metadata = {};
1205
- try {
1206
- if (row.tags)
1207
- tags = JSON.parse(row.tags);
1208
- if (row.metadata)
1209
- metadata = JSON.parse(row.metadata);
1210
- }
1211
- catch (e) { }
1212
- return {
1213
- id: row.id, type: row.type, title: row.title || "Untitled", content: row.content, importance: row.importance,
1214
- agent: row.agent || 'unknown',
1215
- role: row.role || 'unknown',
1216
- model: row.model || 'unknown',
1217
- scope: { repo: row.repo, folder: row.folder || undefined, language: row.language || undefined },
1218
- created_at: row.created_at, updated_at: row.updated_at,
1219
- completed_at: row.completed_at || null,
1220
- hit_count: row.hit_count ?? 0, recall_count: row.recall_count ?? 0,
1221
- last_used_at: row.last_used_at ?? null, expires_at: row.expires_at ?? null, supersedes: row.supersedes ?? null, status: row.status || "active",
1222
- is_global: row.is_global === 1, tags, metadata
1223
- };
1224
- }
1225
- getTaskTimeStats(repo, period) {
1226
- let dateFilter = "";
1227
- if (period === 'daily')
1228
- dateFilter = "AND date(COALESCE(finished_at, updated_at)) = date('now')";
1229
- else if (period === 'weekly')
1230
- dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-7 days')";
1231
- else if (period === 'monthly')
1232
- dateFilter = "AND date(COALESCE(finished_at, updated_at)) >= date('now', '-30 days')";
1233
- const stats = this.db.prepare(`
1234
- SELECT
1235
- COUNT(*) as completed_count,
1236
- SUM(est_tokens) as total_tokens,
1237
- AVG(
1238
- CASE
1239
- WHEN in_progress_at IS NOT NULL AND finished_at IS NOT NULL
1240
- THEN (julianday(finished_at) - julianday(in_progress_at)) * 86400.0
1241
- ELSE NULL
1242
- END
1243
- ) as avg_duration_seconds
1244
- FROM tasks
1245
- WHERE repo = ?
1246
- AND status = 'completed'
1247
- ${dateFilter}
1248
- `).get(repo);
1249
- let addedDateFilter = "";
1250
- if (period === 'daily')
1251
- addedDateFilter = "AND date(created_at) = date('now')";
1252
- else if (period === 'weekly')
1253
- addedDateFilter = "AND date(created_at) >= date('now', '-7 days')";
1254
- else if (period === 'monthly')
1255
- addedDateFilter = "AND date(created_at) >= date('now', '-30 days')";
1256
- const added = this.db.prepare(`
1257
- SELECT COUNT(*) as count FROM tasks
1258
- WHERE repo = ?
1259
- ${addedDateFilter}
1260
- `).get(repo);
1261
- return {
1262
- completed: stats?.completed_count || 0,
1263
- tokens: stats?.total_tokens || 0,
1264
- avgDuration: stats?.avg_duration_seconds || 0,
1265
- added: added?.count || 0
1266
- };
1267
- }
1268
- getTaskComparisonSeries(repo, period) {
1269
- let labelFormat = "";
1270
- let dateFilter = "";
1271
- if (period === 'daily') {
1272
- labelFormat = "%H:00";
1273
- dateFilter = "date(COALESCE(finished_at, created_at)) = date('now')";
1274
- }
1275
- else if (period === 'weekly') {
1276
- labelFormat = "%Y-%m-%d";
1277
- dateFilter = "date(COALESCE(finished_at, created_at)) >= date('now', '-6 days')";
1278
- }
1279
- else if (period === 'monthly') {
1280
- labelFormat = "W%W";
1281
- dateFilter = "date(COALESCE(finished_at, created_at)) >= date('now', '-30 days')";
1282
- }
1283
- else {
1284
- labelFormat = "%Y-%m";
1285
- dateFilter = "1=1";
1286
- }
1287
- const query = `
1288
- SELECT label, SUM(created) as created, SUM(completed) as completed
1289
- FROM (
1290
- SELECT strftime(?, created_at) as label, 1 as created, 0 as completed
1291
- FROM tasks
1292
- WHERE repo = ? AND ${dateFilter.replace("COALESCE(finished_at, created_at)", "created_at")}
1293
- UNION ALL
1294
- SELECT strftime(?, COALESCE(finished_at, updated_at)) as label, 0 as created, 1 as completed
1295
- FROM tasks
1296
- WHERE repo = ? AND status = 'completed' AND ${dateFilter.replace("COALESCE(finished_at, created_at)", "COALESCE(finished_at, updated_at)")}
1297
- )
1298
- GROUP BY label
1299
- ORDER BY label ASC
1300
- LIMIT 100
1301
- `;
1302
- return this.db.prepare(query).all(labelFormat, repo, labelFormat, repo);
1303
- }
1304
- updateTaskComment(id, updates) {
1305
- const fields = [];
1306
- const values = [];
1307
- Object.keys(updates).forEach(key => {
1308
- if (updates[key] !== undefined) {
1309
- fields.push(`${key} = ?`);
1310
- values.push(updates[key]);
1311
- }
1312
- });
1313
- if (fields.length === 0)
1314
- return;
1315
- values.push(id);
1316
- const stmt = this.db.prepare(`UPDATE task_comments SET ${fields.join(", ")} WHERE id = ?`);
1317
- stmt.run(...values);
1318
- }
1319
- deleteTaskComment(id) {
1320
- this.db.prepare("DELETE FROM task_comments WHERE id = ?").run(id);
1321
- }
1322
- getTaskCommentById(id) {
1323
- return this.db.prepare("SELECT * FROM task_comments WHERE id = ?").get(id);
1324
- }
1325
- close() { this.db.close(); }
1326
- }
1327
- //# sourceMappingURL=sqlite.js.map