@remnic/core 1.1.12 → 1.1.14

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 (1324) hide show
  1. package/dist/access-cli.d.ts +2 -1
  2. package/dist/access-cli.js +263 -82
  3. package/dist/access-cli.js.map +1 -1
  4. package/dist/access-http.d.ts +26 -60
  5. package/dist/access-http.js +43 -29
  6. package/dist/access-mcp.d.ts +24 -6
  7. package/dist/access-mcp.js +35 -28
  8. package/dist/access-schema.d.ts +9 -6
  9. package/dist/access-schema.js +7 -5
  10. package/dist/access-service-DcCDmNYC.d.ts +1542 -0
  11. package/dist/access-service.d.ts +25 -7
  12. package/dist/access-service.js +33 -26
  13. package/dist/active-memory-bridge.js +2 -2
  14. package/dist/active-recall.js +11 -3
  15. package/dist/active-recall.js.map +1 -1
  16. package/dist/adapters/claude-code.d.ts +24 -0
  17. package/dist/adapters/claude-code.js +9 -0
  18. package/dist/adapters/codex.d.ts +25 -0
  19. package/dist/adapters/codex.js +9 -0
  20. package/dist/adapters/hermes.d.ts +35 -0
  21. package/dist/adapters/hermes.js +9 -0
  22. package/dist/adapters/index.d.ts +6 -0
  23. package/dist/adapters/index.js +26 -0
  24. package/dist/adapters/registry.d.ts +20 -0
  25. package/dist/adapters/registry.js +13 -0
  26. package/dist/adapters/replit.d.ts +28 -0
  27. package/dist/adapters/replit.js +9 -0
  28. package/dist/adapters/types.d.ts +43 -0
  29. package/dist/adapters/types.js +8 -0
  30. package/dist/bootstrap.d.ts +20 -5
  31. package/dist/boxes.d.ts +7 -0
  32. package/dist/boxes.js +1 -1
  33. package/dist/briefing.d.ts +5 -3
  34. package/dist/briefing.js +9 -6
  35. package/dist/buffer-surprise-report.js +1 -1
  36. package/dist/buffer.d.ts +18 -4
  37. package/dist/buffer.js +1 -1
  38. package/dist/calibration.js +4 -4
  39. package/dist/capsule-cli.d.ts +4 -4
  40. package/dist/capsule-cli.js +1 -1
  41. package/dist/capsule-crypto-5CYAGVC5.js +18 -0
  42. package/dist/capsule-merge-4MGKE7C5.js +189 -0
  43. package/dist/causal-behavior.d.ts +8 -28
  44. package/dist/causal-behavior.js +6 -3
  45. package/dist/causal-behavior.js.map +1 -1
  46. package/dist/causal-chain.js +3 -2
  47. package/dist/causal-consolidation.d.ts +1 -1
  48. package/dist/causal-consolidation.js +24 -13
  49. package/dist/causal-consolidation.js.map +1 -1
  50. package/dist/causal-retrieval.js +3 -3
  51. package/dist/causal-trajectory.js +1 -1
  52. package/dist/chunk-25MQ7IHJ.js +427 -0
  53. package/dist/chunk-25MQ7IHJ.js.map +1 -0
  54. package/dist/chunk-2F2W355T.js +256 -0
  55. package/dist/chunk-2F2W355T.js.map +1 -0
  56. package/dist/chunk-2KI4QFHU.js +228 -0
  57. package/dist/chunk-2KI4QFHU.js.map +1 -0
  58. package/dist/chunk-2PRQG7PV.js +86 -0
  59. package/dist/chunk-2PRQG7PV.js.map +1 -0
  60. package/dist/chunk-2QR3XXIC.js +2272 -0
  61. package/dist/chunk-2QR3XXIC.js.map +1 -0
  62. package/dist/chunk-2WWLHTZY.js +121 -0
  63. package/dist/chunk-326G7DJK.js +2185 -0
  64. package/dist/chunk-326G7DJK.js.map +1 -0
  65. package/dist/chunk-34DQE4KF.js +174 -0
  66. package/dist/chunk-34DQE4KF.js.map +1 -0
  67. package/dist/chunk-3APJ5EVB.js +601 -0
  68. package/dist/chunk-3APJ5EVB.js.map +1 -0
  69. package/dist/chunk-3HPAPHUK.js +51 -0
  70. package/dist/chunk-3HPAPHUK.js.map +1 -0
  71. package/dist/chunk-3JXBXXM2.js +69 -0
  72. package/dist/chunk-3JXBXXM2.js.map +1 -0
  73. package/dist/chunk-3KW65B36.js +681 -0
  74. package/dist/chunk-3KW65B36.js.map +1 -0
  75. package/dist/chunk-3UXOZBHV.js +20 -0
  76. package/dist/chunk-3UXOZBHV.js.map +1 -0
  77. package/dist/chunk-3VAL7ZL2.js +266 -0
  78. package/dist/chunk-3VAL7ZL2.js.map +1 -0
  79. package/dist/chunk-3Y4P7RXM.js +31 -0
  80. package/dist/chunk-3Y4P7RXM.js.map +1 -0
  81. package/dist/chunk-47VWKCAF.js +273 -0
  82. package/dist/chunk-47VWKCAF.js.map +1 -0
  83. package/dist/chunk-4CRG46BG.js +271 -0
  84. package/dist/chunk-5375UYTQ.js +914 -0
  85. package/dist/chunk-5375UYTQ.js.map +1 -0
  86. package/dist/chunk-56K5QLHX.js +506 -0
  87. package/dist/chunk-56K5QLHX.js.map +1 -0
  88. package/dist/chunk-5RGLBDQF.js +596 -0
  89. package/dist/chunk-5RGLBDQF.js.map +1 -0
  90. package/dist/chunk-5UZXUTVO.js +9 -0
  91. package/dist/chunk-5UZXUTVO.js.map +1 -0
  92. package/dist/chunk-65PG43EQ.js +105 -0
  93. package/dist/chunk-65PG43EQ.js.map +1 -0
  94. package/dist/chunk-66DHUKLO.js +57 -0
  95. package/dist/chunk-66DHUKLO.js.map +1 -0
  96. package/dist/chunk-6FC5EGNV.js +46 -0
  97. package/dist/chunk-6FC5EGNV.js.map +1 -0
  98. package/dist/chunk-6H2TESSP.js +62 -0
  99. package/dist/chunk-6H2TESSP.js.map +1 -0
  100. package/dist/chunk-6LVVDPJ4.js +32 -0
  101. package/dist/chunk-6LVVDPJ4.js.map +1 -0
  102. package/dist/chunk-6RVI47ZR.js +159 -0
  103. package/dist/chunk-6RVI47ZR.js.map +1 -0
  104. package/dist/chunk-7AAT6G4Q.js +5117 -0
  105. package/dist/chunk-7AAT6G4Q.js.map +1 -0
  106. package/dist/chunk-7DTASS5T.js +29 -0
  107. package/dist/chunk-7DTASS5T.js.map +1 -0
  108. package/dist/chunk-7IASACLB.js +596 -0
  109. package/dist/chunk-7MNMYOFP.js +32 -0
  110. package/dist/chunk-7MNMYOFP.js.map +1 -0
  111. package/dist/chunk-7N4KAIGN.js +133 -0
  112. package/dist/chunk-7N4KAIGN.js.map +1 -0
  113. package/dist/chunk-7OZ53EXP.js +101 -0
  114. package/dist/chunk-7OZ53EXP.js.map +1 -0
  115. package/dist/chunk-7XYTQGCC.js +134 -0
  116. package/dist/chunk-7XYTQGCC.js.map +1 -0
  117. package/dist/chunk-A2XUIMJ3.js +341 -0
  118. package/dist/chunk-A2XUIMJ3.js.map +1 -0
  119. package/dist/chunk-AGZQD76C.js +201 -0
  120. package/dist/chunk-AGZQD76C.js.map +1 -0
  121. package/dist/chunk-APO3DCMU.js +361 -0
  122. package/dist/chunk-APO3DCMU.js.map +1 -0
  123. package/dist/chunk-BFBF3XEF.js +283 -0
  124. package/dist/chunk-BFBF3XEF.js.map +1 -0
  125. package/dist/chunk-BJ3KMYTB.js +1974 -0
  126. package/dist/chunk-BJ3KMYTB.js.map +1 -0
  127. package/dist/chunk-CHEL3SKB.js +6758 -0
  128. package/dist/chunk-CHEL3SKB.js.map +1 -0
  129. package/dist/chunk-CQZRLNMV.js +1491 -0
  130. package/dist/chunk-CQZRLNMV.js.map +1 -0
  131. package/dist/chunk-D46YSIYX.js +892 -0
  132. package/dist/chunk-D46YSIYX.js.map +1 -0
  133. package/dist/chunk-DINWEURR.js +648 -0
  134. package/dist/chunk-DINWEURR.js.map +1 -0
  135. package/dist/chunk-DK5LDEQM.js +530 -0
  136. package/dist/chunk-DK5LDEQM.js.map +1 -0
  137. package/dist/chunk-DOM4GKSW.js +34 -0
  138. package/dist/chunk-DOM4GKSW.js.map +1 -0
  139. package/dist/chunk-EDTHC6UD.js +1075 -0
  140. package/dist/chunk-EFJ3MQ4V.js +721 -0
  141. package/dist/chunk-EHRTFRWW.js +89 -0
  142. package/dist/chunk-EHRTFRWW.js.map +1 -0
  143. package/dist/chunk-FAJ7FZYM.js +11 -0
  144. package/dist/chunk-FAJ7FZYM.js.map +1 -0
  145. package/dist/chunk-FBYESMQ2.js +570 -0
  146. package/dist/chunk-FDU6HUUL.js +147 -0
  147. package/dist/chunk-FF4KLI5W.js +99 -0
  148. package/dist/chunk-FF4KLI5W.js.map +1 -0
  149. package/dist/chunk-FIT6DMX6.js +310 -0
  150. package/dist/chunk-FIT6DMX6.js.map +1 -0
  151. package/dist/chunk-FJ43PRLT.js +272 -0
  152. package/dist/chunk-FJ43PRLT.js.map +1 -0
  153. package/dist/chunk-FKFMOY3N.js +32 -0
  154. package/dist/chunk-FKFMOY3N.js.map +1 -0
  155. package/dist/chunk-FLTNHQK6.js +262 -0
  156. package/dist/chunk-FLTNHQK6.js.map +1 -0
  157. package/dist/chunk-GA454ALV.js +12436 -0
  158. package/dist/chunk-GA454ALV.js.map +1 -0
  159. package/dist/chunk-GGKRUQOO.js +228 -0
  160. package/dist/chunk-GIF42EW3.js +63 -0
  161. package/dist/chunk-GIF42EW3.js.map +1 -0
  162. package/dist/chunk-GL6I6MEQ.js +647 -0
  163. package/dist/chunk-H3ME6L6D.js +709 -0
  164. package/dist/chunk-H3ME6L6D.js.map +1 -0
  165. package/dist/chunk-HHLLAQGZ.js +1 -0
  166. package/dist/chunk-HXXBL2KD.js +2040 -0
  167. package/dist/chunk-I5V2VDIW.js +219 -0
  168. package/dist/chunk-I5V2VDIW.js.map +1 -0
  169. package/dist/chunk-I6K5FBRQ.js +35 -0
  170. package/dist/chunk-I6K5FBRQ.js.map +1 -0
  171. package/dist/chunk-ICRIXAP2.js +121 -0
  172. package/dist/chunk-ICRIXAP2.js.map +1 -0
  173. package/dist/chunk-J4EB7DNW.js +11 -0
  174. package/dist/chunk-J4EB7DNW.js.map +1 -0
  175. package/dist/chunk-JLFA7DQG.js +62 -0
  176. package/dist/chunk-JLFA7DQG.js.map +1 -0
  177. package/dist/chunk-KJTKLXTH.js +9 -0
  178. package/dist/chunk-KJTKLXTH.js.map +1 -0
  179. package/dist/chunk-KLAO5DGL.js +917 -0
  180. package/dist/chunk-KLAO5DGL.js.map +1 -0
  181. package/dist/chunk-KNKUID7G.js +183 -0
  182. package/dist/chunk-KOSORCJG.js +624 -0
  183. package/dist/chunk-KOSORCJG.js.map +1 -0
  184. package/dist/chunk-KUJVMMZQ.js +1262 -0
  185. package/dist/chunk-KUJVMMZQ.js.map +1 -0
  186. package/dist/chunk-LCR46JY5.js +123 -0
  187. package/dist/chunk-LCR46JY5.js.map +1 -0
  188. package/dist/chunk-LLQ2LLWF.js +148 -0
  189. package/dist/chunk-LLQ2LLWF.js.map +1 -0
  190. package/dist/chunk-LPMVBPA3.js +236 -0
  191. package/dist/chunk-LT3NLYSI.js +50 -0
  192. package/dist/chunk-LT3NLYSI.js.map +1 -0
  193. package/dist/chunk-LUDTDZLK.js +287 -0
  194. package/dist/chunk-LUDTDZLK.js.map +1 -0
  195. package/dist/chunk-M23FSH32.js +3963 -0
  196. package/dist/chunk-M23FSH32.js.map +1 -0
  197. package/dist/chunk-MC26UJIM.js +118 -0
  198. package/dist/chunk-ME6ESPZU.js +119 -0
  199. package/dist/chunk-ME6ESPZU.js.map +1 -0
  200. package/dist/chunk-MGKYQQYF.js +272 -0
  201. package/dist/chunk-MJFNCJXV.js +66 -0
  202. package/dist/chunk-MJFNCJXV.js.map +1 -0
  203. package/dist/chunk-MSWG7JI6.js +237 -0
  204. package/dist/chunk-MSWG7JI6.js.map +1 -0
  205. package/dist/chunk-MT25YHYH.js +141 -0
  206. package/dist/chunk-MT25YHYH.js.map +1 -0
  207. package/dist/chunk-MT4HVDUZ.js +53 -0
  208. package/dist/chunk-MY6TPVXW.js +219 -0
  209. package/dist/chunk-N2D6GXBM.js +267 -0
  210. package/dist/chunk-N2D6GXBM.js.map +1 -0
  211. package/dist/chunk-NJ3MJQZX.js +46 -0
  212. package/dist/chunk-NJ3MJQZX.js.map +1 -0
  213. package/dist/chunk-NMZY542O.js +335 -0
  214. package/dist/chunk-NMZY542O.js.map +1 -0
  215. package/dist/chunk-NNVTUXEB.js +23 -0
  216. package/dist/chunk-NZL6GGQE.js +375 -0
  217. package/dist/chunk-NZL6GGQE.js.map +1 -0
  218. package/dist/chunk-P4NEIHUT.js +108 -0
  219. package/dist/chunk-P7FMDTKL.js +103 -0
  220. package/dist/chunk-P7FMDTKL.js.map +1 -0
  221. package/dist/chunk-PHK3HARR.js +32 -0
  222. package/dist/chunk-PHK3HARR.js.map +1 -0
  223. package/dist/chunk-PIRJPV5T.js +98 -0
  224. package/dist/chunk-PIRJPV5T.js.map +1 -0
  225. package/dist/chunk-PK7H5L6Y.js +159 -0
  226. package/dist/chunk-PK7H5L6Y.js.map +1 -0
  227. package/dist/chunk-PR5FBTFU.js +233 -0
  228. package/dist/chunk-PR5FBTFU.js.map +1 -0
  229. package/dist/chunk-PU63GXWS.js +174 -0
  230. package/dist/chunk-PU63GXWS.js.map +1 -0
  231. package/dist/chunk-PZIAX57I.js +124 -0
  232. package/dist/chunk-PZIAX57I.js.map +1 -0
  233. package/dist/chunk-Q7P4WJDP.js +26 -0
  234. package/dist/chunk-Q7P4WJDP.js.map +1 -0
  235. package/dist/chunk-QQUAB63I.js +63 -0
  236. package/dist/chunk-QQUAB63I.js.map +1 -0
  237. package/dist/chunk-QRNI5JBH.js +18 -0
  238. package/dist/chunk-RHY3HH7P.js +601 -0
  239. package/dist/chunk-RHY3HH7P.js.map +1 -0
  240. package/dist/chunk-RRF5UOBJ.js +91 -0
  241. package/dist/chunk-RXDLTSWT.js +124 -0
  242. package/dist/chunk-RXDLTSWT.js.map +1 -0
  243. package/dist/chunk-RYED3SPJ.js +42 -0
  244. package/dist/chunk-RYED3SPJ.js.map +1 -0
  245. package/dist/chunk-S7KDBTWT.js +106 -0
  246. package/dist/chunk-S7KDBTWT.js.map +1 -0
  247. package/dist/chunk-SEDEKFYQ.js +1 -0
  248. package/dist/chunk-TECVW3JP.js +36 -0
  249. package/dist/chunk-TECVW3JP.js.map +1 -0
  250. package/dist/chunk-TFO23QT4.js +88 -0
  251. package/dist/chunk-TFO23QT4.js.map +1 -0
  252. package/dist/chunk-TK4UEOSK.js +76 -0
  253. package/dist/chunk-TK4UEOSK.js.map +1 -0
  254. package/dist/chunk-TKWGAOLV.js +122 -0
  255. package/dist/chunk-TKWGAOLV.js.map +1 -0
  256. package/dist/chunk-TMM4S4IJ.js +597 -0
  257. package/dist/chunk-TMM4S4IJ.js.map +1 -0
  258. package/dist/chunk-TMQLARTH.js +188 -0
  259. package/dist/chunk-TMQLARTH.js.map +1 -0
  260. package/dist/chunk-TPDBFYEG.js +130 -0
  261. package/dist/chunk-TPDBFYEG.js.map +1 -0
  262. package/dist/chunk-TPMQ3G6Z.js +145 -0
  263. package/dist/chunk-TPMQ3G6Z.js.map +1 -0
  264. package/dist/chunk-TZOLIGIG.js +61 -0
  265. package/dist/chunk-TZOLIGIG.js.map +1 -0
  266. package/dist/chunk-U3PN77QT.js +113 -0
  267. package/dist/chunk-U3WSW6PZ.js +277 -0
  268. package/dist/chunk-U4SCL7B7.js +640 -0
  269. package/dist/chunk-U4SCL7B7.js.map +1 -0
  270. package/dist/chunk-UWK5OXUJ.js +156 -0
  271. package/dist/chunk-UWK5OXUJ.js.map +1 -0
  272. package/dist/chunk-UWVJF25J.js +74 -0
  273. package/dist/chunk-UXHQAFNA.js +1317 -0
  274. package/dist/chunk-UXHQAFNA.js.map +1 -0
  275. package/dist/chunk-V5OCT34X.js +1 -0
  276. package/dist/chunk-VLXA6PI2.js +304 -0
  277. package/dist/chunk-VLXA6PI2.js.map +1 -0
  278. package/dist/chunk-VNO6ZJ35.js +500 -0
  279. package/dist/chunk-VNO6ZJ35.js.map +1 -0
  280. package/dist/chunk-VW676BEI.js +827 -0
  281. package/dist/chunk-VW676BEI.js.map +1 -0
  282. package/dist/chunk-W3LR522O.js +2296 -0
  283. package/dist/chunk-W4L6CZKA.js +96 -0
  284. package/dist/chunk-W4L6CZKA.js.map +1 -0
  285. package/dist/chunk-W4RVMTHR.js +372 -0
  286. package/dist/chunk-W4RVMTHR.js.map +1 -0
  287. package/dist/chunk-WEHSQBFR.js +188 -0
  288. package/dist/chunk-WEHSQBFR.js.map +1 -0
  289. package/dist/chunk-WELDCG6C.js +380 -0
  290. package/dist/chunk-WELDCG6C.js.map +1 -0
  291. package/dist/chunk-WZYKANL3.js +2800 -0
  292. package/dist/chunk-WZYKANL3.js.map +1 -0
  293. package/dist/chunk-XIG5PDM7.js +48 -0
  294. package/dist/chunk-XJNBEDFE.js +193 -0
  295. package/dist/chunk-XJNBEDFE.js.map +1 -0
  296. package/dist/chunk-XVVIG67A.js +291 -0
  297. package/dist/chunk-XVVIG67A.js.map +1 -0
  298. package/dist/chunk-XVZ7B3HG.js +135 -0
  299. package/dist/chunk-YBPYIAA5.js +73 -0
  300. package/dist/chunk-YBPYIAA5.js.map +1 -0
  301. package/dist/chunk-Z734BLO3.js +21 -0
  302. package/dist/chunk-Z734BLO3.js.map +1 -0
  303. package/dist/chunk-ZKSK55RC.js +269 -0
  304. package/dist/chunk-ZKSK55RC.js.map +1 -0
  305. package/dist/chunk-ZTFCYYEZ.js +69 -0
  306. package/dist/chunk-ZTFCYYEZ.js.map +1 -0
  307. package/dist/chunk-ZY2MNJR6.js +329 -0
  308. package/dist/chunk-ZY2MNJR6.js.map +1 -0
  309. package/dist/cli-D3VpkVwB.d.ts +1136 -0
  310. package/dist/cli.d.ts +39 -10
  311. package/dist/cli.js +108 -49
  312. package/dist/commitment-ledger.js +1 -1
  313. package/dist/compat/checks.d.ts +5 -0
  314. package/dist/compat/checks.js +11 -0
  315. package/dist/compat/checks.js.map +1 -0
  316. package/dist/compat/types.d.ts +30 -0
  317. package/dist/compat/types.js +1 -0
  318. package/dist/compat/types.js.map +1 -0
  319. package/dist/compounding/engine.d.ts +221 -0
  320. package/dist/compounding/engine.js +32 -0
  321. package/dist/compounding/engine.js.map +1 -0
  322. package/dist/compounding/preference-consolidator.d.ts +92 -0
  323. package/dist/compounding/preference-consolidator.js +553 -0
  324. package/dist/compounding/preference-consolidator.js.map +1 -0
  325. package/dist/config.d.ts +4 -2
  326. package/dist/config.js +9 -4
  327. package/dist/conflict-policy-DyJ2wd-h.d.ts +4 -0
  328. package/dist/connectors/codex-materialize-runner.d.ts +64 -0
  329. package/dist/connectors/codex-materialize-runner.js +33 -0
  330. package/dist/connectors/codex-materialize-runner.js.map +1 -0
  331. package/dist/connectors/codex-materialize.d.ts +195 -0
  332. package/dist/connectors/codex-materialize.js +38 -0
  333. package/dist/connectors/codex-materialize.js.map +1 -0
  334. package/dist/connectors/index.d.ts +444 -0
  335. package/dist/connectors/index.js +115 -0
  336. package/dist/connectors/index.js.map +1 -0
  337. package/dist/connectors-cli-CwbyjGR7.d.ts +257 -0
  338. package/dist/connectors-cli.d.ts +1 -1
  339. package/dist/consolidation-provenance-check.d.ts +3 -1
  340. package/dist/consolidation-undo.d.ts +3 -1
  341. package/dist/contradiction/index.d.ts +258 -0
  342. package/dist/contradiction/index.js +43 -0
  343. package/dist/contradiction/index.js.map +1 -0
  344. package/dist/contradiction-review-ATP4S6IC.js +30 -0
  345. package/dist/contradiction-review-ATP4S6IC.js.map +1 -0
  346. package/dist/contradiction-scan-5A4IDZV5.js +13 -0
  347. package/dist/contradiction-scan-5A4IDZV5.js.map +1 -0
  348. package/dist/conversation-index/backend.d.ts +97 -0
  349. package/dist/conversation-index/backend.js +13 -0
  350. package/dist/conversation-index/backend.js.map +1 -0
  351. package/dist/conversation-index/chunker.d.ts +16 -0
  352. package/dist/conversation-index/chunker.js +8 -0
  353. package/dist/conversation-index/chunker.js.map +1 -0
  354. package/dist/conversation-index/cleanup.d.ts +11 -0
  355. package/dist/conversation-index/cleanup.js +9 -0
  356. package/dist/conversation-index/cleanup.js.map +1 -0
  357. package/dist/conversation-index/faiss-adapter.d.ts +6 -0
  358. package/dist/conversation-index/faiss-adapter.js +16 -0
  359. package/dist/conversation-index/faiss-adapter.js.map +1 -0
  360. package/dist/conversation-index/indexer.d.ts +23 -0
  361. package/dist/conversation-index/indexer.js +15 -0
  362. package/dist/conversation-index/indexer.js.map +1 -0
  363. package/dist/conversation-index/search.d.ts +6 -0
  364. package/dist/conversation-index/search.js +11 -0
  365. package/dist/conversation-index/search.js.map +1 -0
  366. package/dist/embedding-fallback.js +2 -2
  367. package/dist/enrichment/index.d.ts +163 -0
  368. package/dist/enrichment/index.js +18 -0
  369. package/dist/enrichment/index.js.map +1 -0
  370. package/dist/entity-retrieval.d.ts +4 -2
  371. package/dist/entity-retrieval.js +8 -5
  372. package/dist/evals.js +1 -1
  373. package/dist/explicit-capture.d.ts +20 -5
  374. package/dist/explicit-capture.js +2 -2
  375. package/dist/extraction-judge-training.js +1 -1
  376. package/dist/extraction.js +8 -8
  377. package/dist/faiss-adapter-CzPghc4C.d.ts +70 -0
  378. package/dist/fallback-llm.d.ts +2 -0
  379. package/dist/fallback-llm.js +4 -4
  380. package/dist/graph-edge-decay-5DI5GUNL.js +207 -0
  381. package/dist/index.d.ts +66 -711
  382. package/dist/index.js +556 -2680
  383. package/dist/index.js.map +1 -1
  384. package/dist/lcm/archive.d.ts +89 -0
  385. package/dist/lcm/archive.js +12 -0
  386. package/dist/lcm/archive.js.map +1 -0
  387. package/dist/lcm/dag.d.ts +48 -0
  388. package/dist/lcm/dag.js +8 -0
  389. package/dist/lcm/dag.js.map +1 -0
  390. package/dist/lcm/engine.d.ts +116 -0
  391. package/dist/lcm/engine.js +20 -0
  392. package/dist/lcm/engine.js.map +1 -0
  393. package/dist/lcm/index.d.ts +12 -0
  394. package/dist/lcm/index.js +44 -0
  395. package/dist/lcm/index.js.map +1 -0
  396. package/dist/lcm/queue.d.ts +62 -0
  397. package/dist/lcm/queue.js +8 -0
  398. package/dist/lcm/queue.js.map +1 -0
  399. package/dist/lcm/recall.d.ts +20 -0
  400. package/dist/lcm/recall.js +8 -0
  401. package/dist/lcm/recall.js.map +1 -0
  402. package/dist/lcm/schema.d.ts +16 -0
  403. package/dist/lcm/schema.js +14 -0
  404. package/dist/lcm/schema.js.map +1 -0
  405. package/dist/lcm/summarizer.d.ts +38 -0
  406. package/dist/lcm/summarizer.js +12 -0
  407. package/dist/lcm/summarizer.js.map +1 -0
  408. package/dist/lcm/tools.d.ts +29 -0
  409. package/dist/lcm/tools.js +8 -0
  410. package/dist/lcm/tools.js.map +1 -0
  411. package/dist/live-connectors-runner.js +5 -5
  412. package/dist/local-llm.js +3 -3
  413. package/dist/maintenance/archive-observations.d.ts +18 -0
  414. package/dist/maintenance/archive-observations.js +8 -0
  415. package/dist/maintenance/archive-observations.js.map +1 -0
  416. package/dist/maintenance/backup-stamp.d.ts +3 -0
  417. package/dist/maintenance/backup-stamp.js +8 -0
  418. package/dist/maintenance/backup-stamp.js.map +1 -0
  419. package/dist/maintenance/memory-governance-cron.d.ts +85 -0
  420. package/dist/maintenance/memory-governance-cron.js +22 -0
  421. package/dist/maintenance/memory-governance-cron.js.map +1 -0
  422. package/dist/maintenance/memory-governance.d.ts +137 -0
  423. package/dist/maintenance/memory-governance.js +40 -0
  424. package/dist/maintenance/memory-governance.js.map +1 -0
  425. package/dist/maintenance/migrate-observations.d.ts +18 -0
  426. package/dist/maintenance/migrate-observations.js +9 -0
  427. package/dist/maintenance/migrate-observations.js.map +1 -0
  428. package/dist/maintenance/observation-ledger-utils.d.ts +10 -0
  429. package/dist/maintenance/observation-ledger-utils.js +10 -0
  430. package/dist/maintenance/observation-ledger-utils.js.map +1 -0
  431. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +15 -0
  432. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +28 -0
  433. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js.map +1 -0
  434. package/dist/maintenance/rebuild-memory-projection.d.ts +77 -0
  435. package/dist/maintenance/rebuild-memory-projection.js +35 -0
  436. package/dist/maintenance/rebuild-memory-projection.js.map +1 -0
  437. package/dist/maintenance/rebuild-observations.d.ts +17 -0
  438. package/dist/maintenance/rebuild-observations.js +9 -0
  439. package/dist/maintenance/rebuild-observations.js.map +1 -0
  440. package/dist/mcp-memory-inspector-app.d.ts +24 -6
  441. package/dist/memory-projection-store.d.ts +108 -3
  442. package/dist/memory-projection-store.js +2 -1
  443. package/dist/memory-worth-outcomes.d.ts +4 -2
  444. package/dist/migrate/from-engram.d.ts +24 -0
  445. package/dist/migrate/from-engram.js +12 -0
  446. package/dist/migrate/from-engram.js.map +1 -0
  447. package/dist/namespaces/migrate.d.ts +50 -0
  448. package/dist/namespaces/migrate.js +50 -0
  449. package/dist/namespaces/migrate.js.map +1 -0
  450. package/dist/namespaces/principal.d.ts +17 -0
  451. package/dist/namespaces/principal.js +16 -0
  452. package/dist/namespaces/principal.js.map +1 -0
  453. package/dist/namespaces/search.d.ts +46 -0
  454. package/dist/namespaces/search.js +28 -0
  455. package/dist/namespaces/search.js.map +1 -0
  456. package/dist/namespaces/storage.d.ts +32 -0
  457. package/dist/namespaces/storage.js +28 -0
  458. package/dist/namespaces/storage.js.map +1 -0
  459. package/dist/network/tailscale.d.ts +41 -0
  460. package/dist/network/tailscale.js +9 -0
  461. package/dist/network/tailscale.js.map +1 -0
  462. package/dist/network/webdav.d.ts +39 -0
  463. package/dist/network/webdav.js +10 -0
  464. package/dist/network/webdav.js.map +1 -0
  465. package/dist/objective-state-writers.js +2 -2
  466. package/dist/operator-toolkit.d.ts +4 -2
  467. package/dist/operator-toolkit.js +32 -14
  468. package/dist/opik-exporter.js +2 -2
  469. package/dist/opik-exporter.js.map +1 -1
  470. package/dist/orchestrator-DuWl9Hwx.d.ts +1244 -0
  471. package/dist/orchestrator.d.ts +22 -7
  472. package/dist/orchestrator.js +79 -44
  473. package/dist/path-MR5JPYOP.js +9 -0
  474. package/dist/path-MR5JPYOP.js.map +1 -0
  475. package/dist/qmd-recall-cache.d.ts +1 -1
  476. package/dist/qmd.d.ts +102 -3
  477. package/dist/qmd.js +23 -5
  478. package/dist/recall-explain-renderer.js +3 -3
  479. package/dist/recall-xray-cli.js +4 -4
  480. package/dist/recall-xray-renderer.js +3 -3
  481. package/dist/recall-xray.js +2 -2
  482. package/dist/replay/normalizers/chatgpt.d.ts +6 -0
  483. package/dist/replay/normalizers/chatgpt.js +11 -0
  484. package/dist/replay/normalizers/chatgpt.js.map +1 -0
  485. package/dist/replay/normalizers/claude.d.ts +6 -0
  486. package/dist/replay/normalizers/claude.js +11 -0
  487. package/dist/replay/normalizers/claude.js.map +1 -0
  488. package/dist/replay/normalizers/openclaw.d.ts +6 -0
  489. package/dist/replay/normalizers/openclaw.js +11 -0
  490. package/dist/replay/normalizers/openclaw.js.map +1 -0
  491. package/dist/replay/normalizers/shared.d.ts +16 -0
  492. package/dist/replay/normalizers/shared.js +14 -0
  493. package/dist/replay/normalizers/shared.js.map +1 -0
  494. package/dist/replay/runner.d.ts +35 -0
  495. package/dist/replay/runner.js +16 -0
  496. package/dist/replay/runner.js.map +1 -0
  497. package/dist/replay/types.d.ts +57 -0
  498. package/dist/replay/types.js +19 -0
  499. package/dist/replay/types.js.map +1 -0
  500. package/dist/resolution-B7FNQSSP.js +12 -0
  501. package/dist/resolution-B7FNQSSP.js.map +1 -0
  502. package/dist/resolve-provider-secret.js +2 -2
  503. package/dist/resume-bundles.js +8 -6
  504. package/dist/retrieval-agents.d.ts +1 -1
  505. package/dist/routing/engine.d.ts +35 -0
  506. package/dist/routing/engine.js +16 -0
  507. package/dist/routing/engine.js.map +1 -0
  508. package/dist/routing/store.d.ts +27 -0
  509. package/dist/routing/store.js +10 -0
  510. package/dist/routing/store.js.map +1 -0
  511. package/dist/runtime/better-sqlite.d.ts +8 -0
  512. package/dist/runtime/better-sqlite.js +10 -0
  513. package/dist/runtime/better-sqlite.js.map +1 -0
  514. package/dist/runtime/child-process.d.ts +32 -0
  515. package/dist/runtime/child-process.js +10 -0
  516. package/dist/runtime/child-process.js.map +1 -0
  517. package/dist/runtime/env.d.ts +5 -0
  518. package/dist/runtime/env.js +12 -0
  519. package/dist/runtime/env.js.map +1 -0
  520. package/dist/schemas.d.ts +22 -22
  521. package/dist/sdk-compat.js +1 -1
  522. package/dist/search/document-scanner.d.ts +22 -0
  523. package/dist/search/document-scanner.js +8 -0
  524. package/dist/search/document-scanner.js.map +1 -0
  525. package/dist/search/embed-helper.d.ts +35 -0
  526. package/dist/search/embed-helper.js +9 -0
  527. package/dist/search/embed-helper.js.map +1 -0
  528. package/dist/search/factory.d.ts +32 -0
  529. package/dist/search/factory.js +29 -0
  530. package/dist/search/factory.js.map +1 -0
  531. package/dist/search/index.d.ts +15 -0
  532. package/dist/search/index.js +50 -0
  533. package/dist/search/index.js.map +1 -0
  534. package/dist/search/lancedb-backend.d.ts +51 -0
  535. package/dist/search/lancedb-backend.js +10 -0
  536. package/dist/search/lancedb-backend.js.map +1 -0
  537. package/dist/search/meilisearch-backend.d.ts +48 -0
  538. package/dist/search/meilisearch-backend.js +10 -0
  539. package/dist/search/meilisearch-backend.js.map +1 -0
  540. package/dist/search/noop-backend.d.ts +26 -0
  541. package/dist/search/noop-backend.js +8 -0
  542. package/dist/search/noop-backend.js.map +1 -0
  543. package/dist/search/orama-backend.d.ts +53 -0
  544. package/dist/search/orama-backend.js +10 -0
  545. package/dist/search/orama-backend.js.map +1 -0
  546. package/dist/search/port.d.ts +61 -0
  547. package/dist/search/port.js +1 -0
  548. package/dist/search/port.js.map +1 -0
  549. package/dist/search/remote-backend.d.ts +39 -0
  550. package/dist/search/remote-backend.js +9 -0
  551. package/dist/search/remote-backend.js.map +1 -0
  552. package/dist/secure-store/index.d.ts +890 -0
  553. package/dist/secure-store/index.js +156 -0
  554. package/dist/secure-store/index.js.map +1 -0
  555. package/dist/semantic-VwGI14Ok.d.ts +69 -0
  556. package/dist/semantic-consolidation-4HkHWgeI.d.ts +180 -0
  557. package/dist/semantic-consolidation.d.ts +2 -2
  558. package/dist/semantic-consolidation.js +13 -6
  559. package/dist/semantic-rule-promotion.js +8 -5
  560. package/dist/semantic-rule-verifier.js +8 -5
  561. package/dist/shared-context/manager.d.ts +131 -0
  562. package/dist/shared-context/manager.js +15 -0
  563. package/dist/shared-context/manager.js.map +1 -0
  564. package/dist/skills-registry.js +13 -1
  565. package/dist/skills-registry.js.map +1 -1
  566. package/dist/state-store-VZU2IA53.js +16 -0
  567. package/dist/state-store-VZU2IA53.js.map +1 -0
  568. package/dist/storage-paths.d.ts +9 -0
  569. package/dist/storage-paths.js +20 -0
  570. package/dist/storage-paths.js.map +1 -0
  571. package/dist/storage.d.ts +3 -1
  572. package/dist/storage.js +7 -4
  573. package/dist/summarizer.d.ts +5 -0
  574. package/dist/summarizer.js +9 -8
  575. package/dist/summary-snapshot.js +2 -1
  576. package/dist/surfaces/dreams.d.ts +16 -0
  577. package/dist/surfaces/dreams.js +282 -0
  578. package/dist/surfaces/dreams.js.map +1 -0
  579. package/dist/surfaces/heartbeat.d.ts +17 -0
  580. package/dist/surfaces/heartbeat.js +265 -0
  581. package/dist/surfaces/heartbeat.js.map +1 -0
  582. package/dist/temporal-supersession.d.ts +3 -1
  583. package/dist/threading.d.ts +5 -0
  584. package/dist/threading.js +2 -1
  585. package/dist/tier-migration.d.ts +4 -2
  586. package/dist/tokens.js +2 -2
  587. package/dist/transcript.d.ts +15 -1
  588. package/dist/transcript.js +2 -1
  589. package/dist/transfer/autodetect.d.ts +4 -0
  590. package/dist/transfer/autodetect.js +15 -0
  591. package/dist/transfer/autodetect.js.map +1 -0
  592. package/dist/transfer/backup.d.ts +21 -0
  593. package/dist/transfer/backup.js +17 -0
  594. package/dist/transfer/backup.js.map +1 -0
  595. package/dist/transfer/capsule-export.d.ts +113 -0
  596. package/dist/transfer/capsule-export.js +19 -0
  597. package/dist/transfer/capsule-export.js.map +1 -0
  598. package/dist/transfer/capsule-import.d.ts +124 -0
  599. package/dist/transfer/capsule-import.js +16 -0
  600. package/dist/transfer/capsule-import.js.map +1 -0
  601. package/dist/transfer/constants.d.ts +13 -0
  602. package/dist/transfer/constants.js +12 -0
  603. package/dist/transfer/constants.js.map +1 -0
  604. package/dist/transfer/export-json.d.ts +11 -0
  605. package/dist/transfer/export-json.js +11 -0
  606. package/dist/transfer/export-json.js.map +1 -0
  607. package/dist/transfer/export-md.d.ts +10 -0
  608. package/dist/transfer/export-md.js +13 -0
  609. package/dist/transfer/export-md.js.map +1 -0
  610. package/dist/transfer/export-sqlite.d.ts +9 -0
  611. package/dist/transfer/export-sqlite.js +12 -0
  612. package/dist/transfer/export-sqlite.js.map +1 -0
  613. package/dist/transfer/fs-utils.d.ts +61 -0
  614. package/dist/transfer/fs-utils.js +40 -0
  615. package/dist/transfer/fs-utils.js.map +1 -0
  616. package/dist/transfer/import-json.d.ts +16 -0
  617. package/dist/transfer/import-json.js +13 -0
  618. package/dist/transfer/import-json.js.map +1 -0
  619. package/dist/transfer/import-md.d.ts +14 -0
  620. package/dist/transfer/import-md.js +11 -0
  621. package/dist/transfer/import-md.js.map +1 -0
  622. package/dist/transfer/import-sqlite.d.ts +14 -0
  623. package/dist/transfer/import-sqlite.js +12 -0
  624. package/dist/transfer/import-sqlite.js.map +1 -0
  625. package/dist/transfer/sqlite-schema.d.ts +4 -0
  626. package/dist/transfer/sqlite-schema.js +10 -0
  627. package/dist/transfer/sqlite-schema.js.map +1 -0
  628. package/dist/transfer/types.d.ts +916 -0
  629. package/dist/transfer/types.js +30 -0
  630. package/dist/transfer/types.js.map +1 -0
  631. package/dist/types.d.ts +28 -1
  632. package/dist/types.js +1 -1
  633. package/dist/verified-recall.js +9 -6
  634. package/dist/work/board.d.ts +43 -0
  635. package/dist/work/board.js +14 -0
  636. package/dist/work/board.js.map +1 -0
  637. package/dist/work/boundary.d.ts +8 -0
  638. package/dist/work/boundary.js +14 -0
  639. package/dist/work/boundary.js.map +1 -0
  640. package/dist/work/storage.d.ts +39 -0
  641. package/dist/work/storage.js +11 -0
  642. package/dist/work/storage.js.map +1 -0
  643. package/dist/work/types.d.ts +75 -0
  644. package/dist/work/types.js +1 -0
  645. package/dist/work/types.js.map +1 -0
  646. package/package.json +2767 -6
  647. package/scripts/faiss_index.py +816 -0
  648. package/scripts/faiss_requirements.txt +3 -0
  649. package/skills/remnic-entities/SKILL.md +51 -0
  650. package/skills/remnic-memory-workflow/SKILL.md +61 -0
  651. package/skills/remnic-recall/SKILL.md +51 -0
  652. package/skills/remnic-remember/SKILL.md +56 -0
  653. package/skills/remnic-search/SKILL.md +51 -0
  654. package/skills/remnic-status/SKILL.md +51 -0
  655. package/src/abort-error.test.ts +49 -0
  656. package/src/abort-error.ts +46 -0
  657. package/src/abstraction-nodes.ts +162 -0
  658. package/src/access-audit.test.ts +178 -0
  659. package/src/access-audit.ts +125 -0
  660. package/src/access-cli.test.ts +439 -0
  661. package/src/access-cli.ts +438 -0
  662. package/src/access-http.test.ts +225 -0
  663. package/src/access-http.ts +1899 -0
  664. package/src/access-idempotency.ts +232 -0
  665. package/src/access-mcp.test.ts +568 -0
  666. package/src/access-mcp.ts +3056 -0
  667. package/src/access-schema-pi.test.ts +60 -0
  668. package/src/access-schema.ts +522 -0
  669. package/src/access-service-namespace.test.ts +123 -0
  670. package/src/access-service.ts +5629 -0
  671. package/src/action-confidence.test.ts +206 -0
  672. package/src/action-confidence.ts +466 -0
  673. package/src/active-memory-bridge.test.ts +285 -0
  674. package/src/active-memory-bridge.ts +217 -0
  675. package/src/active-recall.test.ts +484 -0
  676. package/src/active-recall.ts +459 -0
  677. package/src/adapters/claude-code.ts +56 -0
  678. package/src/adapters/codex.ts +57 -0
  679. package/src/adapters/hermes.ts +64 -0
  680. package/src/adapters/index.ts +6 -0
  681. package/src/adapters/registry.ts +41 -0
  682. package/src/adapters/replit.ts +55 -0
  683. package/src/adapters/types.ts +51 -0
  684. package/src/behavior-learner.ts +144 -0
  685. package/src/behavior-signals.ts +73 -0
  686. package/src/binary-lifecycle/backend.ts +117 -0
  687. package/src/binary-lifecycle/index.ts +35 -0
  688. package/src/binary-lifecycle/manifest.ts +79 -0
  689. package/src/binary-lifecycle/pipeline.ts +352 -0
  690. package/src/binary-lifecycle/scanner.ts +89 -0
  691. package/src/binary-lifecycle/types.ts +89 -0
  692. package/src/bootstrap.ts +178 -0
  693. package/src/boxes.ts +521 -0
  694. package/src/briefing.test.ts +1535 -0
  695. package/src/briefing.ts +1382 -0
  696. package/src/buffer-session.test.ts +443 -0
  697. package/src/buffer-surprise-report.ts +176 -0
  698. package/src/buffer-surprise-telemetry.test.ts +606 -0
  699. package/src/buffer-surprise-trigger.test.ts +766 -0
  700. package/src/buffer-surprise.test.ts +339 -0
  701. package/src/buffer-surprise.ts +203 -0
  702. package/src/buffer.ts +900 -0
  703. package/src/bulk-import/cli-command.test.ts +204 -0
  704. package/src/bulk-import/index.ts +34 -0
  705. package/src/bulk-import/pipeline.test.ts +445 -0
  706. package/src/bulk-import/pipeline.ts +178 -0
  707. package/src/bulk-import/registry.test.ts +151 -0
  708. package/src/bulk-import/registry.ts +72 -0
  709. package/src/bulk-import/types.test.ts +272 -0
  710. package/src/bulk-import/types.ts +145 -0
  711. package/src/calibration.ts +394 -0
  712. package/src/capsule-cli.test.ts +398 -0
  713. package/src/capsule-cli.ts +565 -0
  714. package/src/causal-behavior.ts +308 -0
  715. package/src/causal-chain.ts +419 -0
  716. package/src/causal-consolidation.ts +370 -0
  717. package/src/causal-retrieval.ts +286 -0
  718. package/src/causal-trajectory-graph.ts +60 -0
  719. package/src/causal-trajectory.ts +303 -0
  720. package/src/chunking.ts +220 -0
  721. package/src/citations.ts +232 -0
  722. package/src/cli.ts +9403 -0
  723. package/src/codex-cli-fallback.ts +162 -0
  724. package/src/codex-thread-key.ts +1 -0
  725. package/src/coding/access-coding-context.test.ts +197 -0
  726. package/src/coding/coding-branch-scope.test.ts +281 -0
  727. package/src/coding/coding-namespace.test.ts +360 -0
  728. package/src/coding/coding-namespace.ts +412 -0
  729. package/src/coding/coding-orchestrator.test.ts +249 -0
  730. package/src/coding/git-context.test.ts +507 -0
  731. package/src/coding/git-context.ts +336 -0
  732. package/src/coding/mcp-set-coding-context.test.ts +174 -0
  733. package/src/coding/review-context.test.ts +316 -0
  734. package/src/coding/review-context.ts +349 -0
  735. package/src/coding/wire-coding-context.test.ts +468 -0
  736. package/src/commitment-ledger.test.ts +78 -0
  737. package/src/commitment-ledger.ts +337 -0
  738. package/src/compat/checks.test.ts +206 -0
  739. package/src/compat/checks.ts +716 -0
  740. package/src/compat/types.ts +33 -0
  741. package/src/compounding/engine.ts +1686 -0
  742. package/src/compounding/preference-consolidator.ts +778 -0
  743. package/src/compression-optimizer.ts +312 -0
  744. package/src/config.test.ts +930 -0
  745. package/src/config.ts +3807 -0
  746. package/src/connectors/codex/instructions.md +160 -0
  747. package/src/connectors/codex/resources/namespace-cheatsheet.md +48 -0
  748. package/src/connectors/codex-marketplace.ts +500 -0
  749. package/src/connectors/codex-materialize-runner.ts +212 -0
  750. package/src/connectors/codex-materialize.ts +983 -0
  751. package/src/connectors/coerce.ts +62 -0
  752. package/src/connectors/index.test.ts +1570 -0
  753. package/src/connectors/index.ts +3222 -0
  754. package/src/connectors/live/framework.ts +164 -0
  755. package/src/connectors/live/github.test.ts +1218 -0
  756. package/src/connectors/live/github.ts +1068 -0
  757. package/src/connectors/live/gmail.test.ts +1706 -0
  758. package/src/connectors/live/gmail.ts +1293 -0
  759. package/src/connectors/live/google-drive.test.ts +696 -0
  760. package/src/connectors/live/google-drive.ts +724 -0
  761. package/src/connectors/live/index.ts +101 -0
  762. package/src/connectors/live/live-connectors.test.ts +689 -0
  763. package/src/connectors/live/notion.test.ts +1109 -0
  764. package/src/connectors/live/notion.ts +978 -0
  765. package/src/connectors/live/registry.ts +103 -0
  766. package/src/connectors/live/state-store.ts +399 -0
  767. package/src/connectors/live/transient-errors.ts +150 -0
  768. package/src/connectors/weclone-installer.test.ts +850 -0
  769. package/src/connectors-cli.ts +513 -0
  770. package/src/console/state.test.ts +224 -0
  771. package/src/console/state.ts +514 -0
  772. package/src/console/trace.test.ts +813 -0
  773. package/src/console/trace.ts +603 -0
  774. package/src/console/tui.test.ts +582 -0
  775. package/src/console/tui.ts +508 -0
  776. package/src/consolidation-operator.ts +182 -0
  777. package/src/consolidation-provenance-check.ts +551 -0
  778. package/src/consolidation-undo.ts +718 -0
  779. package/src/contradiction/contradiction-judge.test.ts +189 -0
  780. package/src/contradiction/contradiction-judge.ts +333 -0
  781. package/src/contradiction/contradiction-review.ts +574 -0
  782. package/src/contradiction/contradiction-scan.ts +504 -0
  783. package/src/contradiction/contradiction.test.ts +2230 -0
  784. package/src/contradiction/index.ts +37 -0
  785. package/src/contradiction/resolution.ts +383 -0
  786. package/src/conversation-index/backend.ts +323 -0
  787. package/src/conversation-index/chunker.ts +47 -0
  788. package/src/conversation-index/cleanup.ts +53 -0
  789. package/src/conversation-index/faiss-adapter.ts +384 -0
  790. package/src/conversation-index/indexer.test.ts +164 -0
  791. package/src/conversation-index/indexer.ts +192 -0
  792. package/src/conversation-index/search.ts +37 -0
  793. package/src/cross-namespace-budget.test.ts +275 -0
  794. package/src/cross-namespace-budget.ts +365 -0
  795. package/src/cue-anchors.ts +163 -0
  796. package/src/curation/index.ts +544 -0
  797. package/src/dashboard-runtime.ts +337 -0
  798. package/src/day-summary.ts +122 -0
  799. package/src/dedup/index.ts +330 -0
  800. package/src/dedup/semantic.test.ts +1577 -0
  801. package/src/dedup/semantic.ts +148 -0
  802. package/src/delinearize.ts +193 -0
  803. package/src/direct-answer-wiring.test.ts +473 -0
  804. package/src/direct-answer-wiring.ts +180 -0
  805. package/src/direct-answer.test.ts +484 -0
  806. package/src/direct-answer.ts +273 -0
  807. package/src/embedding-fallback.ts +565 -0
  808. package/src/enrichment/audit.ts +89 -0
  809. package/src/enrichment/index.ts +27 -0
  810. package/src/enrichment/pipeline.ts +197 -0
  811. package/src/enrichment/provider-registry.ts +85 -0
  812. package/src/enrichment/types.ts +100 -0
  813. package/src/enrichment/web-search-provider.ts +63 -0
  814. package/src/entity-retrieval.ts +774 -0
  815. package/src/entity-schema.ts +239 -0
  816. package/src/evals.ts +1312 -0
  817. package/src/event-order-recall.test.ts +4164 -0
  818. package/src/event-order-recall.ts +2802 -0
  819. package/src/evidence-pack.test.ts +89 -0
  820. package/src/evidence-pack.ts +388 -0
  821. package/src/explicit-capture.ts +530 -0
  822. package/src/explicit-cue-recall.test.ts +3019 -0
  823. package/src/explicit-cue-recall.ts +5545 -0
  824. package/src/extraction-judge-telemetry.ts +234 -0
  825. package/src/extraction-judge-training.ts +221 -0
  826. package/src/extraction-judge.ts +846 -0
  827. package/src/extraction-timeout.test.ts +265 -0
  828. package/src/extraction.ts +2719 -0
  829. package/src/fallback-llm.test.ts +1060 -0
  830. package/src/fallback-llm.ts +918 -0
  831. package/src/focused-list-recall.test.ts +734 -0
  832. package/src/focused-list-recall.ts +1160 -0
  833. package/src/graph-dashboard-diff.ts +35 -0
  834. package/src/graph-dashboard-key.ts +5 -0
  835. package/src/graph-dashboard-parser.ts +104 -0
  836. package/src/graph-edge-reinforcement.ts +192 -0
  837. package/src/graph-events.ts +151 -0
  838. package/src/graph-recall.test.ts +164 -0
  839. package/src/graph-recall.ts +189 -0
  840. package/src/graph-retrieval.test.ts +809 -0
  841. package/src/graph-retrieval.ts +823 -0
  842. package/src/graph-snapshot.ts +329 -0
  843. package/src/graph.ts +813 -0
  844. package/src/harmonic-retrieval.ts +223 -0
  845. package/src/himem.ts +154 -0
  846. package/src/hygiene.ts +87 -0
  847. package/src/identity-continuity.ts +333 -0
  848. package/src/importance.ts +328 -0
  849. package/src/importers/base.test.ts +294 -0
  850. package/src/importers/base.ts +436 -0
  851. package/src/importers/index.ts +21 -0
  852. package/src/index.ts +1204 -0
  853. package/src/intent.ts +154 -0
  854. package/src/json-extract.ts +85 -0
  855. package/src/json-store.ts +42 -0
  856. package/src/lcm/archive.ts +617 -0
  857. package/src/lcm/dag.ts +199 -0
  858. package/src/lcm/engine.ts +645 -0
  859. package/src/lcm/index.ts +7 -0
  860. package/src/lcm/queue.test.ts +178 -0
  861. package/src/lcm/queue.ts +200 -0
  862. package/src/lcm/recall.ts +117 -0
  863. package/src/lcm/schema.ts +154 -0
  864. package/src/lcm/summarizer.ts +235 -0
  865. package/src/lcm/tools.ts +191 -0
  866. package/src/lcm-engine.test.ts +660 -0
  867. package/src/legacy-hook-compat.test.ts +20 -0
  868. package/src/legacy-hook-compat.ts +45 -0
  869. package/src/lifecycle.ts +289 -0
  870. package/src/live-connectors-runner.ts +385 -0
  871. package/src/local-llm-qos.test.ts +303 -0
  872. package/src/local-llm-thinking.test.ts +292 -0
  873. package/src/local-llm.ts +1464 -0
  874. package/src/logger.ts +49 -0
  875. package/src/maintenance/archive-observations.ts +147 -0
  876. package/src/maintenance/backup-stamp.ts +3 -0
  877. package/src/maintenance/dreams-ledger.ts +516 -0
  878. package/src/maintenance/first-start-migration.ts +362 -0
  879. package/src/maintenance/forget.test.ts +206 -0
  880. package/src/maintenance/forget.ts +126 -0
  881. package/src/maintenance/graph-edge-decay.test.ts +409 -0
  882. package/src/maintenance/graph-edge-decay.ts +394 -0
  883. package/src/maintenance/memory-governance-cron.ts +447 -0
  884. package/src/maintenance/memory-governance.ts +1039 -0
  885. package/src/maintenance/migrate-observations.ts +216 -0
  886. package/src/maintenance/observation-ledger-utils.ts +54 -0
  887. package/src/maintenance/pattern-reinforcement.test.ts +875 -0
  888. package/src/maintenance/pattern-reinforcement.ts +369 -0
  889. package/src/maintenance/purge.ts +334 -0
  890. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +78 -0
  891. package/src/maintenance/rebuild-memory-projection.ts +1234 -0
  892. package/src/maintenance/rebuild-observations.ts +178 -0
  893. package/src/maintenance/tier-stats.test.ts +378 -0
  894. package/src/maintenance/tier-stats.ts +222 -0
  895. package/src/mcp-memory-inspector-app.ts +421 -0
  896. package/src/memory-action-policy.ts +80 -0
  897. package/src/memory-cache.ts +208 -0
  898. package/src/memory-extension/claude-code-publisher.ts +51 -0
  899. package/src/memory-extension/codex-publisher.ts +149 -0
  900. package/src/memory-extension/hermes-publisher.ts +51 -0
  901. package/src/memory-extension/index.ts +100 -0
  902. package/src/memory-extension/shared-instructions.ts +133 -0
  903. package/src/memory-extension/types.ts +86 -0
  904. package/src/memory-extension-host/host-discovery.ts +276 -0
  905. package/src/memory-extension-host/index.ts +14 -0
  906. package/src/memory-extension-host/render-extensions-block.ts +73 -0
  907. package/src/memory-extension-host/types.ts +21 -0
  908. package/src/memory-lifecycle-ledger-utils.ts +116 -0
  909. package/src/memory-projection-format.ts +11 -0
  910. package/src/memory-projection-store.ts +951 -0
  911. package/src/memory-provenance.test.ts +196 -0
  912. package/src/memory-provenance.ts +484 -0
  913. package/src/memory-worth-bench.test.ts +71 -0
  914. package/src/memory-worth-bench.ts +265 -0
  915. package/src/memory-worth-filter.test.ts +209 -0
  916. package/src/memory-worth-filter.ts +204 -0
  917. package/src/memory-worth-frontmatter.test.ts +311 -0
  918. package/src/memory-worth-outcomes.test.ts +316 -0
  919. package/src/memory-worth-outcomes.ts +286 -0
  920. package/src/memory-worth.test.ts +317 -0
  921. package/src/memory-worth.ts +215 -0
  922. package/src/message-parts/index.ts +806 -0
  923. package/src/message-parts/message-parts.test.ts +421 -0
  924. package/src/migrate/from-engram.ts +789 -0
  925. package/src/model-registry.ts +313 -0
  926. package/src/models-json.ts +76 -0
  927. package/src/namespaces/migrate.ts +187 -0
  928. package/src/namespaces/path.ts +25 -0
  929. package/src/namespaces/principal.test.ts +195 -0
  930. package/src/namespaces/principal.ts +86 -0
  931. package/src/namespaces/search.test.ts +105 -0
  932. package/src/namespaces/search.ts +233 -0
  933. package/src/namespaces/storage.ts +74 -0
  934. package/src/native-knowledge.ts +1823 -0
  935. package/src/negative.ts +72 -0
  936. package/src/network/tailscale.ts +179 -0
  937. package/src/network/webdav.ts +385 -0
  938. package/src/objective-state-writers.ts +951 -0
  939. package/src/objective-state.ts +320 -0
  940. package/src/onboarding/index.ts +529 -0
  941. package/src/openai-chat-compat.ts +56 -0
  942. package/src/operator-toolkit.ts +2132 -0
  943. package/src/opik-exporter.test.ts +72 -0
  944. package/src/opik-exporter.ts +587 -0
  945. package/src/orchestrator-extraction-queue.test.ts +197 -0
  946. package/src/orchestrator-flush.test.ts +1171 -0
  947. package/src/orchestrator-pattern-reinforcement.test.ts +128 -0
  948. package/src/orchestrator-source-attribution.test.ts +701 -0
  949. package/src/orchestrator.ts +16368 -0
  950. package/src/page-versioning.ts +450 -0
  951. package/src/patterns-cli.ts +574 -0
  952. package/src/peers/index.ts +54 -0
  953. package/src/peers/migrate-from-identity-anchor.test.ts +291 -0
  954. package/src/peers/migrate-from-identity-anchor.ts +350 -0
  955. package/src/peers/peers.test.ts +419 -0
  956. package/src/peers/profile-reasoner.ts +694 -0
  957. package/src/peers/storage.ts +1350 -0
  958. package/src/peers/types.ts +138 -0
  959. package/src/plugin-id.ts +84 -0
  960. package/src/policy-runtime.ts +209 -0
  961. package/src/procedural/procedure-miner.ts +150 -0
  962. package/src/procedural/procedure-recall.ts +93 -0
  963. package/src/procedural/procedure-stats.ts +213 -0
  964. package/src/procedural/procedure-types.ts +132 -0
  965. package/src/procedural/reinforcement-core.test.ts +132 -0
  966. package/src/procedural/reinforcement-core.ts +73 -0
  967. package/src/profiling.test.ts +263 -0
  968. package/src/profiling.ts +435 -0
  969. package/src/projection/index.ts +398 -0
  970. package/src/qmd-recall-cache.test.ts +138 -0
  971. package/src/qmd-recall-cache.ts +111 -0
  972. package/src/qmd.test.ts +258 -0
  973. package/src/qmd.ts +2614 -0
  974. package/src/reasoning-trace-recall.ts +201 -0
  975. package/src/reasoning-trace-types.ts +235 -0
  976. package/src/recall-audit-anomaly.test.ts +246 -0
  977. package/src/recall-audit-anomaly.ts +297 -0
  978. package/src/recall-audit.test.ts +51 -0
  979. package/src/recall-audit.ts +72 -0
  980. package/src/recall-budget-config.test.ts +87 -0
  981. package/src/recall-disclosure-escalation.test.ts +196 -0
  982. package/src/recall-disclosure-escalation.ts +158 -0
  983. package/src/recall-disclosure-shaping.test.ts +146 -0
  984. package/src/recall-disclosure.test.ts +214 -0
  985. package/src/recall-explain-renderer.test.ts +140 -0
  986. package/src/recall-explain-renderer.ts +356 -0
  987. package/src/recall-mmr.test.ts +808 -0
  988. package/src/recall-mmr.ts +607 -0
  989. package/src/recall-qos.test.ts +85 -0
  990. package/src/recall-qos.ts +82 -0
  991. package/src/recall-query-policy.ts +221 -0
  992. package/src/recall-state.test.ts +233 -0
  993. package/src/recall-state.ts +456 -0
  994. package/src/recall-tag-filter.ts +143 -0
  995. package/src/recall-tokenization.ts +35 -0
  996. package/src/recall-xray-cli.test.ts +118 -0
  997. package/src/recall-xray-cli.ts +100 -0
  998. package/src/recall-xray-disclosure-telemetry.test.ts +183 -0
  999. package/src/recall-xray-renderer.test.ts +539 -0
  1000. package/src/recall-xray-renderer.ts +487 -0
  1001. package/src/recall-xray.test.ts +503 -0
  1002. package/src/recall-xray.ts +621 -0
  1003. package/src/reconstruct.ts +41 -0
  1004. package/src/release-changelog.ts +35 -0
  1005. package/src/relevance.ts +67 -0
  1006. package/src/replay/normalizers/chatgpt.ts +133 -0
  1007. package/src/replay/normalizers/claude.ts +102 -0
  1008. package/src/replay/normalizers/openclaw.ts +119 -0
  1009. package/src/replay/normalizers/shared.ts +69 -0
  1010. package/src/replay/runner.ts +197 -0
  1011. package/src/replay/types.ts +143 -0
  1012. package/src/rerank.test.ts +48 -0
  1013. package/src/rerank.ts +176 -0
  1014. package/src/resolve-auth-token.test.ts +226 -0
  1015. package/src/resolve-auth-token.ts +151 -0
  1016. package/src/resolve-provider-secret.test.ts +187 -0
  1017. package/src/resolve-provider-secret.ts +410 -0
  1018. package/src/response-guidance-recall.test.ts +3952 -0
  1019. package/src/response-guidance-recall.ts +4431 -0
  1020. package/src/resume-bundles.ts +415 -0
  1021. package/src/retrieval-agents.ts +623 -0
  1022. package/src/retrieval-tiers.ts +25 -0
  1023. package/src/retrieval.ts +104 -0
  1024. package/src/review/index.test.ts +201 -0
  1025. package/src/review/index.ts +536 -0
  1026. package/src/routing/engine.ts +162 -0
  1027. package/src/routing/store.ts +321 -0
  1028. package/src/runtime/better-sqlite.test.ts +32 -0
  1029. package/src/runtime/better-sqlite.ts +76 -0
  1030. package/src/runtime/child-process.ts +67 -0
  1031. package/src/runtime/env.ts +48 -0
  1032. package/src/sanitize.ts +58 -0
  1033. package/src/schemas.ts +449 -0
  1034. package/src/sdk-compat.ts +87 -0
  1035. package/src/search/document-scanner.ts +96 -0
  1036. package/src/search/embed-helper.ts +142 -0
  1037. package/src/search/factory.ts +189 -0
  1038. package/src/search/index.ts +10 -0
  1039. package/src/search/lancedb-backend.ts +342 -0
  1040. package/src/search/meilisearch-backend.ts +232 -0
  1041. package/src/search/noop-backend.ts +57 -0
  1042. package/src/search/orama-backend.ts +358 -0
  1043. package/src/search/port.ts +86 -0
  1044. package/src/search/remote-backend.ts +124 -0
  1045. package/src/secure-store/cipher.ts +271 -0
  1046. package/src/secure-store/cli-handlers.ts +355 -0
  1047. package/src/secure-store/cli-renderer.ts +131 -0
  1048. package/src/secure-store/header.ts +373 -0
  1049. package/src/secure-store/index.ts +137 -0
  1050. package/src/secure-store/kdf.ts +263 -0
  1051. package/src/secure-store/keyring.ts +106 -0
  1052. package/src/secure-store/metadata.ts +394 -0
  1053. package/src/secure-store/passphrase-reader.ts +252 -0
  1054. package/src/secure-store/secure-fs.ts +571 -0
  1055. package/src/secure-store/secure-store.test.ts +755 -0
  1056. package/src/semantic-chunking.ts +545 -0
  1057. package/src/semantic-consolidation.test.ts +182 -0
  1058. package/src/semantic-consolidation.ts +432 -0
  1059. package/src/semantic-rule-promotion.ts +183 -0
  1060. package/src/semantic-rule-verifier.ts +160 -0
  1061. package/src/session-integrity.ts +569 -0
  1062. package/src/session-observer-bands.ts +11 -0
  1063. package/src/session-observer-state.ts +346 -0
  1064. package/src/session-toggles.test.ts +96 -0
  1065. package/src/session-toggles.ts +159 -0
  1066. package/src/shared-context/manager.ts +810 -0
  1067. package/src/signal.ts +84 -0
  1068. package/src/skills-registry.test.ts +277 -0
  1069. package/src/skills-registry.ts +120 -0
  1070. package/src/source-attribution-roundtrip.test.ts +215 -0
  1071. package/src/source-attribution.test.ts +1425 -0
  1072. package/src/source-attribution.ts +639 -0
  1073. package/src/spaces/index.ts +627 -0
  1074. package/src/storage-paths.ts +117 -0
  1075. package/src/storage.ts +6657 -0
  1076. package/src/store-contract.ts +55 -0
  1077. package/src/summarizer.ts +844 -0
  1078. package/src/summary-snapshot.test.ts +681 -0
  1079. package/src/summary-snapshot.ts +238 -0
  1080. package/src/surfaces/dreams.test.ts +394 -0
  1081. package/src/surfaces/dreams.ts +346 -0
  1082. package/src/surfaces/heartbeat.test.ts +415 -0
  1083. package/src/surfaces/heartbeat.ts +325 -0
  1084. package/src/sync/index.ts +308 -0
  1085. package/src/targeted-fact-recall.test.ts +1694 -0
  1086. package/src/targeted-fact-recall.ts +2905 -0
  1087. package/src/taxonomy/default-taxonomy.ts +87 -0
  1088. package/src/taxonomy/index.ts +26 -0
  1089. package/src/taxonomy/resolver-doc-generator.ts +57 -0
  1090. package/src/taxonomy/resolver.ts +184 -0
  1091. package/src/taxonomy/taxonomy-loader.ts +186 -0
  1092. package/src/taxonomy/types.ts +48 -0
  1093. package/src/telemetry-transcript.ts +70 -0
  1094. package/src/temporal-index.ts +890 -0
  1095. package/src/temporal-supersession.test.ts +2703 -0
  1096. package/src/temporal-supersession.ts +493 -0
  1097. package/src/temporal-validity.test.ts +448 -0
  1098. package/src/temporal-validity.ts +123 -0
  1099. package/src/threading.ts +395 -0
  1100. package/src/tier-migration.ts +124 -0
  1101. package/src/tier-routing.ts +102 -0
  1102. package/src/tmt.ts +462 -0
  1103. package/src/tokens.test.ts +178 -0
  1104. package/src/tokens.ts +279 -0
  1105. package/src/topics.ts +147 -0
  1106. package/src/training-export/cli-date-validation.test.ts +258 -0
  1107. package/src/training-export/converter.test.ts +452 -0
  1108. package/src/training-export/converter.ts +319 -0
  1109. package/src/training-export/date-parse.ts +117 -0
  1110. package/src/training-export/index.ts +26 -0
  1111. package/src/training-export/registry.test.ts +85 -0
  1112. package/src/training-export/registry.ts +57 -0
  1113. package/src/training-export/types.ts +31 -0
  1114. package/src/transcript.ts +1179 -0
  1115. package/src/transfer/autodetect.ts +30 -0
  1116. package/src/transfer/backup.ts +138 -0
  1117. package/src/transfer/capsule-crypto.ts +485 -0
  1118. package/src/transfer/capsule-encrypt.test.ts +690 -0
  1119. package/src/transfer/capsule-export.ts +543 -0
  1120. package/src/transfer/capsule-fork.ts +375 -0
  1121. package/src/transfer/capsule-import.ts +564 -0
  1122. package/src/transfer/capsule-merge.ts +433 -0
  1123. package/src/transfer/conflict-policy.ts +16 -0
  1124. package/src/transfer/constants.ts +13 -0
  1125. package/src/transfer/exclusions.ts +37 -0
  1126. package/src/transfer/export-json.ts +65 -0
  1127. package/src/transfer/export-md.ts +59 -0
  1128. package/src/transfer/export-sqlite.ts +52 -0
  1129. package/src/transfer/fs-utils.ts +269 -0
  1130. package/src/transfer/import-json.ts +108 -0
  1131. package/src/transfer/import-md.ts +84 -0
  1132. package/src/transfer/import-sqlite.ts +100 -0
  1133. package/src/transfer/integrity.ts +71 -0
  1134. package/src/transfer/sqlite-schema.ts +16 -0
  1135. package/src/transfer/types.ts +297 -0
  1136. package/src/trust-zones.ts +1186 -0
  1137. package/src/types.ts +3074 -0
  1138. package/src/user-model.test.ts +124 -0
  1139. package/src/user-model.ts +162 -0
  1140. package/src/utility-learner.ts +353 -0
  1141. package/src/utility-runtime.ts +88 -0
  1142. package/src/utility-telemetry.ts +215 -0
  1143. package/src/utils/category-dir.ts +44 -0
  1144. package/src/utils/errno.ts +6 -0
  1145. package/src/utils/iso-timestamp.test.ts +37 -0
  1146. package/src/utils/iso-timestamp.ts +164 -0
  1147. package/src/utils/path.ts +26 -0
  1148. package/src/verified-recall.ts +138 -0
  1149. package/src/version-utils.test.ts +10 -0
  1150. package/src/version-utils.ts +9 -0
  1151. package/src/whitespace.ts +10 -0
  1152. package/src/work/board.ts +359 -0
  1153. package/src/work/boundary.ts +107 -0
  1154. package/src/work/storage.ts +436 -0
  1155. package/src/work/types.ts +82 -0
  1156. package/src/work-product-ledger.ts +265 -0
  1157. package/dist/access-service-DDjzFALq.d.ts +0 -2088
  1158. package/dist/capsule-crypto-SJS5VVAP.js +0 -18
  1159. package/dist/capsule-export-7QNCBZOQ.js +0 -17
  1160. package/dist/capsule-import-EPBHD2EN.js +0 -16
  1161. package/dist/capsule-merge-DI7PNQ2H.js +0 -189
  1162. package/dist/chunk-23ZZK64Y.js +0 -26
  1163. package/dist/chunk-23ZZK64Y.js.map +0 -1
  1164. package/dist/chunk-242S3I2A.js +0 -647
  1165. package/dist/chunk-2LGMW3DJ.js +0 -111
  1166. package/dist/chunk-3B6KIRBH.js +0 -5213
  1167. package/dist/chunk-3B6KIRBH.js.map +0 -1
  1168. package/dist/chunk-457A4P3L.js +0 -119
  1169. package/dist/chunk-457A4P3L.js.map +0 -1
  1170. package/dist/chunk-4IS4SXIQ.js +0 -2040
  1171. package/dist/chunk-4YM32CRU.js +0 -721
  1172. package/dist/chunk-6TBWYBJ3.js +0 -236
  1173. package/dist/chunk-74EMIVE4.js +0 -329
  1174. package/dist/chunk-74EMIVE4.js.map +0 -1
  1175. package/dist/chunk-767ODGE6.js +0 -183
  1176. package/dist/chunk-7V22HTMD.js +0 -623
  1177. package/dist/chunk-7V22HTMD.js.map +0 -1
  1178. package/dist/chunk-7ZM3BFKK.js +0 -9705
  1179. package/dist/chunk-7ZM3BFKK.js.map +0 -1
  1180. package/dist/chunk-AQJNPMOA.js +0 -643
  1181. package/dist/chunk-AQJNPMOA.js.map +0 -1
  1182. package/dist/chunk-ASAITVLA.js +0 -64
  1183. package/dist/chunk-ASAITVLA.js.map +0 -1
  1184. package/dist/chunk-BBE34QBJ.js +0 -275
  1185. package/dist/chunk-BBE34QBJ.js.map +0 -1
  1186. package/dist/chunk-BZSQEPRW.js +0 -14710
  1187. package/dist/chunk-BZSQEPRW.js.map +0 -1
  1188. package/dist/chunk-CPKTBRS2.js +0 -891
  1189. package/dist/chunk-CPKTBRS2.js.map +0 -1
  1190. package/dist/chunk-D4GAOFF6.js +0 -562
  1191. package/dist/chunk-D4GAOFF6.js.map +0 -1
  1192. package/dist/chunk-D54LZC5L.js +0 -147
  1193. package/dist/chunk-DF3RVK3X.js +0 -119
  1194. package/dist/chunk-DF3RVK3X.js.map +0 -1
  1195. package/dist/chunk-DZZPC36E.js +0 -1451
  1196. package/dist/chunk-DZZPC36E.js.map +0 -1
  1197. package/dist/chunk-E2UCDP5S.js +0 -570
  1198. package/dist/chunk-E6K4NIEU.js +0 -747
  1199. package/dist/chunk-E6K4NIEU.js.map +0 -1
  1200. package/dist/chunk-EEQLFRUM.js +0 -89
  1201. package/dist/chunk-ETOW6ACV.js +0 -158
  1202. package/dist/chunk-ETOW6ACV.js.map +0 -1
  1203. package/dist/chunk-FMEBPEAO.js +0 -347
  1204. package/dist/chunk-FMEBPEAO.js.map +0 -1
  1205. package/dist/chunk-FQDPCE3I.js +0 -1837
  1206. package/dist/chunk-FQDPCE3I.js.map +0 -1
  1207. package/dist/chunk-FYIYMQ5N.js +0 -221
  1208. package/dist/chunk-FYIYMQ5N.js.map +0 -1
  1209. package/dist/chunk-G2WADRQ3.js +0 -219
  1210. package/dist/chunk-G4SK7DSQ.js +0 -121
  1211. package/dist/chunk-GVPWB7EY.js +0 -390
  1212. package/dist/chunk-GVPWB7EY.js.map +0 -1
  1213. package/dist/chunk-HELQZFZO.js +0 -1075
  1214. package/dist/chunk-HL5LRPNA.js +0 -1914
  1215. package/dist/chunk-HL5LRPNA.js.map +0 -1
  1216. package/dist/chunk-HQZVVSVB.js +0 -147
  1217. package/dist/chunk-HQZVVSVB.js.map +0 -1
  1218. package/dist/chunk-HY3L4WKC.js +0 -2195
  1219. package/dist/chunk-HY3L4WKC.js.map +0 -1
  1220. package/dist/chunk-IB3BFHGN.js +0 -228
  1221. package/dist/chunk-IXEJRKCZ.js +0 -18
  1222. package/dist/chunk-JBMSGZEQ.js +0 -441
  1223. package/dist/chunk-JBMSGZEQ.js.map +0 -1
  1224. package/dist/chunk-JESOB2HO.js +0 -108
  1225. package/dist/chunk-JKDVIE52.js +0 -272
  1226. package/dist/chunk-JRNQ3RNA.js +0 -284
  1227. package/dist/chunk-JRNQ3RNA.js.map +0 -1
  1228. package/dist/chunk-K6WK37A6.js +0 -865
  1229. package/dist/chunk-K6WK37A6.js.map +0 -1
  1230. package/dist/chunk-MARWOCVP.js +0 -48
  1231. package/dist/chunk-MNU6ZBWT.js +0 -4454
  1232. package/dist/chunk-MNU6ZBWT.js.map +0 -1
  1233. package/dist/chunk-N5AKDXAI.js +0 -74
  1234. package/dist/chunk-OA3L7BFR.js +0 -183
  1235. package/dist/chunk-OA3L7BFR.js.map +0 -1
  1236. package/dist/chunk-OR64ZGRZ.js +0 -23
  1237. package/dist/chunk-P77UEOU2.js +0 -1521
  1238. package/dist/chunk-P77UEOU2.js.map +0 -1
  1239. package/dist/chunk-PH4C2U43.js +0 -239
  1240. package/dist/chunk-PH4C2U43.js.map +0 -1
  1241. package/dist/chunk-RVPLBATS.js +0 -1586
  1242. package/dist/chunk-RVPLBATS.js.map +0 -1
  1243. package/dist/chunk-U5JMRGKX.js +0 -340
  1244. package/dist/chunk-U5JMRGKX.js.map +0 -1
  1245. package/dist/chunk-URB2WSKZ.js +0 -350
  1246. package/dist/chunk-URB2WSKZ.js.map +0 -1
  1247. package/dist/chunk-UVMUAWVT.js +0 -596
  1248. package/dist/chunk-WEJG4TB5.js +0 -118
  1249. package/dist/chunk-X7HPGUVG.js +0 -271
  1250. package/dist/chunk-XAMBKFQS.js +0 -2777
  1251. package/dist/chunk-XAMBKFQS.js.map +0 -1
  1252. package/dist/chunk-XJKFSSDW.js +0 -726
  1253. package/dist/chunk-XJKFSSDW.js.map +0 -1
  1254. package/dist/chunk-XMHBH5H6.js +0 -283
  1255. package/dist/chunk-XMHBH5H6.js.map +0 -1
  1256. package/dist/chunk-XMVFHBHT.js +0 -277
  1257. package/dist/chunk-Y3VMVTYX.js +0 -53
  1258. package/dist/chunk-YNB73F22.js +0 -137
  1259. package/dist/chunk-YNB73F22.js.map +0 -1
  1260. package/dist/chunk-Z2E7VW55.js +0 -335
  1261. package/dist/chunk-Z2E7VW55.js.map +0 -1
  1262. package/dist/chunk-ZG7PTKBK.js +0 -2296
  1263. package/dist/chunk-ZNQN6ZTA.js +0 -135
  1264. package/dist/chunk-ZVTKDVVM.js +0 -827
  1265. package/dist/chunk-ZVTKDVVM.js.map +0 -1
  1266. package/dist/cli-BR8KpIU0.d.ts +0 -1259
  1267. package/dist/codex-materialize-CQlLTzke.d.ts +0 -139
  1268. package/dist/connectors-cli-DFGtY2DB.d.ts +0 -257
  1269. package/dist/contradiction-review-5LTTVDQV.js +0 -22
  1270. package/dist/contradiction-scan-QTXAMBUA.js +0 -414
  1271. package/dist/contradiction-scan-QTXAMBUA.js.map +0 -1
  1272. package/dist/engine-35M5BKQ7.js +0 -28
  1273. package/dist/fs-utils-IRVUFB6G.js +0 -30
  1274. package/dist/graph-edge-decay-PWB63GRE.js +0 -207
  1275. package/dist/memory-governance-IMPQZXFC.js +0 -37
  1276. package/dist/memory-projection-store-CY8TU40w.d.ts +0 -222
  1277. package/dist/orchestrator-DDMPqU6R.d.ts +0 -1792
  1278. package/dist/path-RMTY5Y5A.js +0 -9
  1279. package/dist/port-B6VEDIkC.d.ts +0 -53
  1280. package/dist/resolution-YGIBORXI.js +0 -101
  1281. package/dist/resolution-YGIBORXI.js.map +0 -1
  1282. package/dist/secure-store-4R2GSO7S.js +0 -156
  1283. package/dist/semantic-consolidation-ByBXb-sf.d.ts +0 -180
  1284. package/dist/state-store-3EH7HYIN.js +0 -16
  1285. package/dist/types-V3FJ26TF.js +0 -30
  1286. /package/dist/{capsule-crypto-SJS5VVAP.js.map → adapters/claude-code.js.map} +0 -0
  1287. /package/dist/{capsule-export-7QNCBZOQ.js.map → adapters/codex.js.map} +0 -0
  1288. /package/dist/{capsule-import-EPBHD2EN.js.map → adapters/hermes.js.map} +0 -0
  1289. /package/dist/{contradiction-review-5LTTVDQV.js.map → adapters/index.js.map} +0 -0
  1290. /package/dist/{engine-35M5BKQ7.js.map → adapters/registry.js.map} +0 -0
  1291. /package/dist/{fs-utils-IRVUFB6G.js.map → adapters/replit.js.map} +0 -0
  1292. /package/dist/{memory-governance-IMPQZXFC.js.map → adapters/types.js.map} +0 -0
  1293. /package/dist/{path-RMTY5Y5A.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
  1294. /package/dist/{capsule-merge-DI7PNQ2H.js.map → capsule-merge-4MGKE7C5.js.map} +0 -0
  1295. /package/dist/{chunk-G4SK7DSQ.js.map → chunk-2WWLHTZY.js.map} +0 -0
  1296. /package/dist/{chunk-X7HPGUVG.js.map → chunk-4CRG46BG.js.map} +0 -0
  1297. /package/dist/{chunk-UVMUAWVT.js.map → chunk-7IASACLB.js.map} +0 -0
  1298. /package/dist/{chunk-HELQZFZO.js.map → chunk-EDTHC6UD.js.map} +0 -0
  1299. /package/dist/{chunk-4YM32CRU.js.map → chunk-EFJ3MQ4V.js.map} +0 -0
  1300. /package/dist/{chunk-E2UCDP5S.js.map → chunk-FBYESMQ2.js.map} +0 -0
  1301. /package/dist/{chunk-D54LZC5L.js.map → chunk-FDU6HUUL.js.map} +0 -0
  1302. /package/dist/{chunk-IB3BFHGN.js.map → chunk-GGKRUQOO.js.map} +0 -0
  1303. /package/dist/{chunk-242S3I2A.js.map → chunk-GL6I6MEQ.js.map} +0 -0
  1304. /package/dist/{secure-store-4R2GSO7S.js.map → chunk-HHLLAQGZ.js.map} +0 -0
  1305. /package/dist/{chunk-4IS4SXIQ.js.map → chunk-HXXBL2KD.js.map} +0 -0
  1306. /package/dist/{chunk-767ODGE6.js.map → chunk-KNKUID7G.js.map} +0 -0
  1307. /package/dist/{chunk-6TBWYBJ3.js.map → chunk-LPMVBPA3.js.map} +0 -0
  1308. /package/dist/{chunk-WEJG4TB5.js.map → chunk-MC26UJIM.js.map} +0 -0
  1309. /package/dist/{chunk-JKDVIE52.js.map → chunk-MGKYQQYF.js.map} +0 -0
  1310. /package/dist/{chunk-Y3VMVTYX.js.map → chunk-MT4HVDUZ.js.map} +0 -0
  1311. /package/dist/{chunk-G2WADRQ3.js.map → chunk-MY6TPVXW.js.map} +0 -0
  1312. /package/dist/{chunk-OR64ZGRZ.js.map → chunk-NNVTUXEB.js.map} +0 -0
  1313. /package/dist/{chunk-JESOB2HO.js.map → chunk-P4NEIHUT.js.map} +0 -0
  1314. /package/dist/{chunk-IXEJRKCZ.js.map → chunk-QRNI5JBH.js.map} +0 -0
  1315. /package/dist/{chunk-EEQLFRUM.js.map → chunk-RRF5UOBJ.js.map} +0 -0
  1316. /package/dist/{state-store-3EH7HYIN.js.map → chunk-SEDEKFYQ.js.map} +0 -0
  1317. /package/dist/{chunk-2LGMW3DJ.js.map → chunk-U3PN77QT.js.map} +0 -0
  1318. /package/dist/{chunk-XMVFHBHT.js.map → chunk-U3WSW6PZ.js.map} +0 -0
  1319. /package/dist/{chunk-N5AKDXAI.js.map → chunk-UWVJF25J.js.map} +0 -0
  1320. /package/dist/{types-V3FJ26TF.js.map → chunk-V5OCT34X.js.map} +0 -0
  1321. /package/dist/{chunk-ZG7PTKBK.js.map → chunk-W3LR522O.js.map} +0 -0
  1322. /package/dist/{chunk-MARWOCVP.js.map → chunk-XIG5PDM7.js.map} +0 -0
  1323. /package/dist/{chunk-ZNQN6ZTA.js.map → chunk-XVZ7B3HG.js.map} +0 -0
  1324. /package/dist/{graph-edge-decay-PWB63GRE.js.map → graph-edge-decay-5DI5GUNL.js.map} +0 -0
@@ -1,2296 +0,0 @@
1
- import {
2
- looksLikeMechanicalTelemetryTranscript
3
- } from "./chunk-4RA3C3EV.js";
4
- import {
5
- ConsolidationResultSchema,
6
- DaySummaryResultSchema,
7
- ExtractionResultSchema,
8
- IdentityConsolidationResultSchema,
9
- ProactiveExtractionResultSchema,
10
- ProactiveQuestionsResultSchema,
11
- buildProfileConsolidationResultSchema
12
- } from "./chunk-WW3QQF4H.js";
13
- import {
14
- normalizeReasoningTrace
15
- } from "./chunk-54V4BZWP.js";
16
- import {
17
- ModelRegistry
18
- } from "./chunk-QR3C7BKQ.js";
19
- import {
20
- LocalLlmClient
21
- } from "./chunk-HELQZFZO.js";
22
- import {
23
- buildExtensionsFooterForSummary,
24
- formatDaySummaryMemories,
25
- loadDaySummaryPrompt
26
- } from "./chunk-3IQ2TR4N.js";
27
- import {
28
- delinearize
29
- } from "./chunk-VEWZZM3H.js";
30
- import {
31
- FallbackLlmClient
32
- } from "./chunk-AQJNPMOA.js";
33
- import {
34
- buildChatCompletionTokenLimit,
35
- shouldAssumeOpenAiChatCompletions
36
- } from "./chunk-L2EXJQJP.js";
37
- import {
38
- extractJsonCandidates
39
- } from "./chunk-UZB5KHKX.js";
40
- import {
41
- applyWorkExtractionBoundary
42
- } from "./chunk-EEQLFRUM.js";
43
- import {
44
- ProfilingCollector
45
- } from "./chunk-NBNN5GOB.js";
46
- import {
47
- normalizeProcedureSteps
48
- } from "./chunk-QDW3E4RD.js";
49
- import {
50
- sanitizeMemoryContent
51
- } from "./chunk-FVQJYWH7.js";
52
- import {
53
- log
54
- } from "./chunk-2ODBA7MQ.js";
55
-
56
- // src/extraction.ts
57
- import OpenAI from "openai";
58
- var PROACTIVE_MIN_CONFIDENCE = 0.8;
59
- var CONSOLIDATION_RESPONSE_SCHEMA = `{
60
- "items": [
61
- {
62
- "existingId": "id",
63
- "action": "ADD",
64
- "mergeWith": "optional-existing-id",
65
- "updatedContent": "optional replacement content",
66
- "reason": "brief reason for this action"
67
- }
68
- ],
69
- "profileUpdates": ["optional profile update"],
70
- "entityUpdates": [{"name": "person-jane-doe", "type": "person", "facts": ["Now leads the backend team", "Recently migrated the user service to TypeScript"]}]
71
- }`;
72
- function isPlainRecord(value) {
73
- return typeof value === "object" && value !== null && !Array.isArray(value);
74
- }
75
- function normalizeQuestion(question) {
76
- const priority = Number.isFinite(question.priority) ? Math.max(0, Math.min(1, question.priority)) : 0.5;
77
- return {
78
- question: typeof question.question === "string" ? question.question.trim() : "",
79
- context: typeof question.context === "string" ? question.context.trim() : "",
80
- priority
81
- };
82
- }
83
- function normalizeFactKey(fact) {
84
- return `${fact.category}:${fact.content.trim().toLowerCase()}`;
85
- }
86
- function normalizeEntityKey(entity) {
87
- return `${entity.type}:${entity.name.trim().toLowerCase()}`;
88
- }
89
- function normalizeRelationshipKey(relationship) {
90
- return `${relationship.source.trim().toLowerCase()}=>${relationship.target.trim().toLowerCase()}:${relationship.label.trim().toLowerCase()}`;
91
- }
92
- function normalizeProfileUpdateKey(update) {
93
- return update.trim().toLowerCase();
94
- }
95
- var ExtractionEngine = class {
96
- constructor(config, profilerArg, localLlm, gatewayConfig, modelRegistry) {
97
- this.config = config;
98
- this.profiler = profilerArg ?? new ProfilingCollector({ enabled: false, storageDir: "/tmp/engram-profiler-disabled", maxTraces: 0 });
99
- if (config.openaiApiKey) {
100
- this.client = new OpenAI({
101
- apiKey: config.openaiApiKey,
102
- ...config.openaiBaseUrl ? { baseURL: config.openaiBaseUrl } : {}
103
- });
104
- } else {
105
- this.client = null;
106
- log.warn("no OpenAI API key \u2014 direct OpenAI client disabled; local and gateway fallback paths remain available");
107
- }
108
- this.localLlm = localLlm ?? new LocalLlmClient(config, modelRegistry);
109
- this.fallbackLlm = new FallbackLlmClient(gatewayConfig, {
110
- workspaceDir: config.workspaceDir
111
- });
112
- this.modelRegistry = modelRegistry ?? new ModelRegistry(config.memoryDir);
113
- if (config.modelSource === "gateway") {
114
- log.debug(
115
- `extraction engine: gateway model source active; extraction uses the gateway chain as its primary path` + (config.gatewayAgentId ? ` (agent: ${config.gatewayAgentId})` : " (defaults)")
116
- );
117
- }
118
- }
119
- config;
120
- client;
121
- localLlm;
122
- fallbackLlm;
123
- modelRegistry;
124
- profiler;
125
- /**
126
- * Whether LLM calls should be routed through the gateway model chain
127
- * instead of the plugin's own local/OpenAI clients.
128
- */
129
- get useGatewayModelSource() {
130
- return this.config.modelSource === "gateway";
131
- }
132
- /**
133
- * Whether the local LLM path should be attempted.
134
- * Disabled when gateway model source is active (gateway chain replaces local).
135
- */
136
- get shouldUseLocalLlm() {
137
- return this.config.localLlmEnabled && !this.useGatewayModelSource;
138
- }
139
- /**
140
- * Whether the direct OpenAI client should be used.
141
- * Disabled when gateway model source is active.
142
- */
143
- get shouldUseDirectClient() {
144
- return !this.useGatewayModelSource && this.client !== null;
145
- }
146
- /**
147
- * Build FallbackLlmOptions with the configured gateway agent ID injected.
148
- */
149
- withGatewayAgent(options) {
150
- if (!this.useGatewayModelSource) return options;
151
- const agentId = this.config.gatewayAgentId || void 0;
152
- return agentId ? { ...options, agentId } : options;
153
- }
154
- emit(event) {
155
- try {
156
- const cb = globalThis.__openclawEngramTrace;
157
- if (typeof cb === "function") cb(event);
158
- } catch {
159
- }
160
- }
161
- directClientUsesOpenAiTokenSemantics() {
162
- return shouldAssumeOpenAiChatCompletions(this.config.openaiBaseUrl);
163
- }
164
- sanitizeExtractionResult(result, messageTimestamp) {
165
- const proceduralOn = this.config.procedural?.enabled === true;
166
- const ts = messageTimestamp ?? /* @__PURE__ */ new Date();
167
- const facts = result.facts.filter((fact) => proceduralOn || fact.category !== "procedure").map((fact) => {
168
- const sanitized = sanitizeMemoryContent(fact.content);
169
- if (!sanitized.clean) {
170
- log.warn(`extraction fact sanitized; violations=${sanitized.violations.join(", ")}`);
171
- }
172
- let content = sanitized.text;
173
- if (this.config.delinearizeEnabled) {
174
- content = delinearize(content, result.entities, ts);
175
- }
176
- return { ...fact, content };
177
- });
178
- return { ...result, facts };
179
- }
180
- hasExtractionOutputs(result) {
181
- return result.facts.length > 0 || result.entities.length > 0 || result.questions.length > 0 || result.profileUpdates.length > 0 || (result.relationships?.length ?? 0) > 0;
182
- }
183
- normalizeExtractionResultPayload(parsed) {
184
- const entities = Array.isArray(parsed?.entities) ? parsed.entities.map((e) => this.normalizeEntityUpdate(e)).filter((e) => e.name.length > 0) : [];
185
- const facts = Array.isArray(parsed?.facts) ? parsed.facts.map((f) => ({
186
- category: typeof f?.category === "string" ? f.category : "fact",
187
- content: typeof f?.content === "string" ? f.content : typeof f?.text === "string" ? f.text : "",
188
- confidence: typeof f?.confidence === "number" ? f.confidence : 0.7,
189
- tags: Array.isArray(f?.tags) ? f.tags.filter((t) => typeof t === "string") : [],
190
- entityRef: typeof f?.entityRef === "string" ? f.entityRef : void 0,
191
- promptedByQuestion: typeof f?.promptedByQuestion === "string" ? f.promptedByQuestion : void 0,
192
- scope: f?.scope === "global" || f?.scope === "project" ? f.scope : void 0,
193
- structuredAttributes: f?.structuredAttributes && typeof f.structuredAttributes === "object" && !Array.isArray(f.structuredAttributes) ? Object.fromEntries(
194
- Object.entries(f.structuredAttributes).filter(([k, v]) => typeof k === "string" && typeof v === "string")
195
- ) : void 0,
196
- procedureSteps: Array.isArray(f?.procedureSteps) ? normalizeProcedureSteps(f.procedureSteps) : void 0,
197
- reasoningTrace: (() => {
198
- const candidate = f?.reasoningTrace && typeof f.reasoningTrace === "object" && !Array.isArray(f.reasoningTrace) ? f.reasoningTrace : f?.reasoning_trace && typeof f.reasoning_trace === "object" && !Array.isArray(f.reasoning_trace) ? f.reasoning_trace : null;
199
- return candidate ? normalizeReasoningTrace(candidate) ?? void 0 : void 0;
200
- })()
201
- })).filter((f) => f.content.length > 0) : [];
202
- const questions = Array.isArray(parsed?.questions) ? parsed.questions.map((q) => {
203
- if (typeof q === "string") return { question: q, context: "", priority: 0.5 };
204
- return {
205
- question: typeof q?.question === "string" ? q.question : typeof q?.text === "string" ? q.text : "",
206
- context: typeof q?.context === "string" ? q.context : "",
207
- priority: typeof q?.priority === "number" ? q.priority : 0.5
208
- };
209
- }).filter((q) => q.question.length > 0) : [];
210
- return {
211
- facts,
212
- entities,
213
- profileUpdates: Array.isArray(parsed?.profileUpdates) ? parsed.profileUpdates.filter((u) => typeof u === "string" && u.trim().length > 0) : [],
214
- questions,
215
- identityReflection: parsed?.identityReflection ?? void 0,
216
- relationships: Array.isArray(parsed?.relationships) ? parsed.relationships.filter(
217
- (r) => typeof r?.source === "string" && typeof r?.target === "string" && typeof r?.label === "string"
218
- ).map((r) => ({
219
- source: r.source,
220
- target: r.target,
221
- label: r.label,
222
- promptedByQuestion: typeof r?.promptedByQuestion === "string" ? r.promptedByQuestion : void 0
223
- })) : void 0
224
- };
225
- }
226
- normalizeEntityUpdate(entity) {
227
- const rawUpdates = isPlainRecord(entity?.updates) ? entity.updates : null;
228
- const directFacts = Array.isArray(entity?.facts) ? entity.facts.filter((fact) => typeof fact === "string").map((fact) => fact.trim()).filter((fact) => fact.length > 0) : [];
229
- const updateFacts = rawUpdates && Array.isArray(rawUpdates.facts) ? rawUpdates.facts.filter((fact) => typeof fact === "string").map((fact) => fact.trim()).filter((fact) => fact.length > 0) : [];
230
- const scalarUpdateFacts = rawUpdates ? Object.keys(rawUpdates).sort((a, b) => a.localeCompare(b)).filter((key) => !["facts", "name", "promptedByQuestion", "structuredSections", "type"].includes(key)).flatMap((key) => {
231
- const value = rawUpdates[key];
232
- if (typeof value === "string" && value.trim().length > 0) {
233
- return [`${key}: ${value.trim()}`];
234
- }
235
- if (typeof value === "number" || typeof value === "boolean") {
236
- return [`${key}: ${String(value)}`];
237
- }
238
- return [];
239
- }) : [];
240
- const structuredSectionsSource = Array.isArray(entity?.structuredSections) ? entity.structuredSections : Array.isArray(rawUpdates?.structuredSections) ? rawUpdates.structuredSections : [];
241
- const name = typeof entity?.name === "string" ? entity.name.trim() : typeof entity?.entityId === "string" ? entity.entityId.trim() : typeof rawUpdates?.name === "string" ? rawUpdates.name.trim() : "";
242
- const type = typeof entity?.type === "string" && entity.type.trim().length > 0 ? entity.type.trim() : typeof rawUpdates?.type === "string" && rawUpdates.type.trim().length > 0 ? rawUpdates.type.trim() : "other";
243
- return {
244
- name,
245
- type,
246
- facts: [...directFacts, ...updateFacts, ...scalarUpdateFacts],
247
- structuredSections: structuredSectionsSource.length > 0 ? structuredSectionsSource.map((section) => ({
248
- key: typeof section?.key === "string" ? section.key.trim() : "",
249
- title: typeof section?.title === "string" ? section.title.trim() : "",
250
- facts: Array.isArray(section?.facts) ? section.facts.filter((fact) => typeof fact === "string").map((fact) => fact.trim()).filter((fact) => fact.length > 0) : []
251
- })).filter((section) => section.key.length > 0 && section.title.length > 0 && section.facts.length > 0) : void 0,
252
- promptedByQuestion: typeof entity?.promptedByQuestion === "string" ? entity.promptedByQuestion : typeof rawUpdates?.promptedByQuestion === "string" ? rawUpdates.promptedByQuestion : void 0
253
- };
254
- }
255
- parseJsonObject(content) {
256
- const trimmed = content?.trim();
257
- if (!trimmed) return null;
258
- for (const candidate of extractJsonCandidates(trimmed)) {
259
- try {
260
- return JSON.parse(candidate);
261
- } catch {
262
- }
263
- }
264
- return null;
265
- }
266
- normalizeContradictionVerificationResult(parsed) {
267
- if (!parsed || typeof parsed.isContradiction !== "boolean") return null;
268
- const rawWhich = parsed.whichIsNewer ?? parsed.winner;
269
- const normalizedWhich = rawWhich === "first" || rawWhich === "existing" ? "first" : rawWhich === "second" || rawWhich === "new" ? "second" : "unclear";
270
- return {
271
- isContradiction: Boolean(parsed.isContradiction),
272
- confidence: typeof parsed.confidence === "number" ? parsed.confidence : 0.5,
273
- reasoning: typeof parsed.reasoning === "string" ? parsed.reasoning : typeof parsed.explanation === "string" ? parsed.explanation : "",
274
- whichIsNewer: normalizedWhich
275
- };
276
- }
277
- normalizeSuggestedLinksResult(parsed) {
278
- if (!parsed || !Array.isArray(parsed.links)) {
279
- return null;
280
- }
281
- const normalizedLinks = parsed.links.map((link) => {
282
- const rawLinkType = link?.linkType ?? link?.type;
283
- return {
284
- targetId: typeof link?.targetId === "string" ? link.targetId : "",
285
- linkType: rawLinkType === "follows" || rawLinkType === "references" || rawLinkType === "contradicts" || rawLinkType === "supports" || rawLinkType === "related" ? rawLinkType : "related",
286
- strength: typeof link?.strength === "number" ? Math.max(0, Math.min(1, link.strength)) : 0.5,
287
- reason: typeof link?.reason === "string" ? link.reason : void 0
288
- };
289
- }).filter((link) => link.targetId.length > 0);
290
- return { links: normalizedLinks };
291
- }
292
- normalizeMemorySummaryResult(parsed) {
293
- if (!parsed) return null;
294
- const normalized = {
295
- summaryText: typeof parsed.summaryText === "string" ? parsed.summaryText : typeof parsed.summary === "string" ? parsed.summary : "",
296
- keyFacts: Array.isArray(parsed.keyFacts) ? parsed.keyFacts.filter((f) => typeof f === "string") : [],
297
- keyEntities: Array.isArray(parsed.keyEntities) ? parsed.keyEntities.filter((e) => typeof e === "string") : Array.isArray(parsed.entities) ? parsed.entities.filter((e) => typeof e === "string") : []
298
- };
299
- return normalized.summaryText.length > 0 ? normalized : null;
300
- }
301
- normalizeDaySummaryResult(parsed) {
302
- if (!parsed) return null;
303
- const normalized = {
304
- summary: typeof parsed.summary === "string" ? parsed.summary.trim() : "",
305
- bullets: Array.isArray(parsed.bullets) ? parsed.bullets.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean) : [],
306
- next_actions: Array.isArray(parsed.next_actions) ? parsed.next_actions.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean) : [],
307
- risks_or_open_loops: Array.isArray(parsed.risks_or_open_loops) ? parsed.risks_or_open_loops.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean) : []
308
- };
309
- return normalized.summary.length > 0 ? normalized : null;
310
- }
311
- sanitizeConsolidationResult(result) {
312
- const items = [];
313
- for (const item of Array.isArray(result.items) ? result.items : []) {
314
- const rawAction = typeof item?.action === "string" ? item.action.toUpperCase() : "SKIP";
315
- const action = rawAction === "ADD" || rawAction === "MERGE" || rawAction === "UPDATE" || rawAction === "INVALIDATE" || rawAction === "SKIP" ? rawAction : "SKIP";
316
- const existingId = typeof item?.existingId === "string" ? item.existingId.trim() : typeof item?.newMemoryId === "string" ? item.newMemoryId.trim() : typeof item?.memoryId === "string" ? item.memoryId.trim() : "";
317
- if (!existingId) continue;
318
- const mergeWith = typeof item?.mergeWith === "string" ? item.mergeWith : void 0;
319
- const reason = typeof item?.reason === "string" ? item.reason : "";
320
- const rawUpdatedContent = typeof item?.updatedContent === "string" ? item.updatedContent : void 0;
321
- if (!rawUpdatedContent) {
322
- items.push({ existingId, action, mergeWith, updatedContent: void 0, reason });
323
- continue;
324
- }
325
- const sanitized = sanitizeMemoryContent(rawUpdatedContent);
326
- if (!sanitized.clean) {
327
- log.warn(`consolidation item sanitized (${existingId}); violations=${sanitized.violations.join(", ")}`);
328
- }
329
- items.push({
330
- existingId,
331
- action,
332
- mergeWith,
333
- updatedContent: sanitized.text,
334
- reason
335
- });
336
- }
337
- const profileUpdates = (Array.isArray(result.profileUpdates) ? result.profileUpdates : []).map(
338
- (update) => typeof update === "string" ? update.trim() : typeof update?.content === "string" ? update.content.trim() : ""
339
- ).filter((update) => update.length > 0);
340
- const entityUpdates = (Array.isArray(result.entityUpdates) ? result.entityUpdates : []).map((entity) => this.normalizeEntityUpdate(entity)).filter((entity) => entity.name.length > 0);
341
- return { items, profileUpdates, entityUpdates };
342
- }
343
- async applyProactiveQuestionPass(conversation, base) {
344
- if (!this.config.proactiveExtractionEnabled) return base;
345
- const maxAdditional = Math.max(0, Math.floor(this.config.maxProactiveQuestionsPerExtraction));
346
- if (maxAdditional === 0) return base;
347
- if (this.config.proactiveExtractionTimeoutMs === 0) return base;
348
- if (this.config.proactiveExtractionMaxTokens === 0) return base;
349
- try {
350
- const proactive = await this.generateProactiveQuestions(conversation, base, maxAdditional);
351
- if (proactive.length === 0) return base;
352
- const proactiveAdditions = await this.answerProactiveQuestions(
353
- conversation,
354
- base,
355
- proactive,
356
- maxAdditional
357
- );
358
- if (!this.hasExtractionOutputs(proactiveAdditions)) return base;
359
- return this.mergeProactiveExtractionPass(base, proactiveAdditions, maxAdditional);
360
- } catch (err) {
361
- log.debug(`proactive extraction question pass failed (ignored): ${err}`);
362
- return base;
363
- }
364
- }
365
- parseProactiveQuestionsFromText(content, existingQuestionKeys) {
366
- for (const candidate of extractJsonCandidates(content)) {
367
- try {
368
- const parsed = JSON.parse(candidate);
369
- if (!Array.isArray(parsed.questions)) continue;
370
- return parsed.questions.map((q) => normalizeQuestion(q)).filter((q) => q.question.length > 0).filter((q) => !existingQuestionKeys.has(q.question.toLowerCase()));
371
- } catch {
372
- }
373
- }
374
- return [];
375
- }
376
- parseProactiveExtractionResultFromText(content) {
377
- for (const candidate of extractJsonCandidates(content)) {
378
- try {
379
- const parsed = ProactiveExtractionResultSchema.parse(JSON.parse(candidate));
380
- return this.normalizeExtractionResultPayload({
381
- ...parsed,
382
- questions: []
383
- });
384
- } catch {
385
- }
386
- }
387
- return null;
388
- }
389
- async generateProactiveQuestions(conversation, base, maxAdditional) {
390
- const existingQuestionKeys = new Set(
391
- (base.questions ?? []).map((q) => q.question.trim().toLowerCase()).filter((q) => q.length > 0)
392
- );
393
- const factsPreview = base.facts.slice(0, 8).map((f) => `- (${f.category}) ${f.content}`).join("\n");
394
- const existingQuestionsPreview = (base.questions ?? []).slice(0, 8).map((q) => `- ${q.question}`).join("\n");
395
- const prompt = [
396
- "You are doing a proactive second-pass memory extraction.",
397
- `Generate up to ${maxAdditional} additional high-value follow-up questions not already covered.`,
398
- "Return only valid JSON with this shape:",
399
- '{"questions":[{"question":"...","context":"...","priority":0.0}]}',
400
- "",
401
- "Current extracted facts:",
402
- factsPreview || "(none)",
403
- "",
404
- "Questions already extracted (do not repeat):",
405
- existingQuestionsPreview || "(none)",
406
- "",
407
- "Conversation:",
408
- conversation
409
- ].join("\n");
410
- if (this.shouldUseLocalLlm) {
411
- try {
412
- const localResponse = await this.localLlm.chatCompletion(
413
- [
414
- {
415
- role: "system",
416
- content: "You are a proactive memory extraction assistant. Output valid JSON only."
417
- },
418
- { role: "user", content: prompt }
419
- ],
420
- {
421
- temperature: 0.2,
422
- maxTokens: this.config.proactiveExtractionMaxTokens,
423
- timeoutMs: this.config.proactiveExtractionTimeoutMs,
424
- operation: "proactive_extraction",
425
- priority: "background"
426
- }
427
- );
428
- if (localResponse?.content) {
429
- const localParsed = this.parseProactiveQuestionsFromText(
430
- localResponse.content.trim(),
431
- existingQuestionKeys
432
- );
433
- if (localParsed.length > 0) {
434
- return localParsed.slice(0, maxAdditional);
435
- }
436
- }
437
- if (!this.config.localLlmFallback) {
438
- return [];
439
- }
440
- } catch (err) {
441
- if (!this.config.localLlmFallback) {
442
- throw err;
443
- }
444
- }
445
- }
446
- const fallbackResult = await this.fallbackLlm.parseWithSchema(
447
- [
448
- {
449
- role: "system",
450
- content: "Generate additional proactive memory follow-up questions. Return valid JSON only."
451
- },
452
- { role: "user", content: prompt }
453
- ],
454
- ProactiveQuestionsResultSchema,
455
- this.withGatewayAgent({
456
- temperature: 0.2,
457
- maxTokens: this.config.proactiveExtractionMaxTokens,
458
- timeoutMs: this.config.proactiveExtractionTimeoutMs
459
- })
460
- );
461
- if (!fallbackResult?.questions) return [];
462
- return fallbackResult.questions.map((q) => normalizeQuestion(q)).filter((q) => q.question.length > 0).filter((q) => !existingQuestionKeys.has(q.question.toLowerCase())).slice(0, maxAdditional);
463
- }
464
- async answerProactiveQuestions(conversation, base, proactiveQuestions, maxAdditional) {
465
- const factsPreview = base.facts.slice(0, 8).map((f) => `- (${f.category}) ${f.content}`).join("\n");
466
- const entitiesPreview = base.entities.slice(0, 8).map((entity) => `- (${entity.type}) ${entity.name}: ${entity.facts.join("; ") || "(no facts)"}`).join("\n");
467
- const proactivePreview = proactiveQuestions.slice(0, maxAdditional).map((question, index) => `${index + 1}. ${question.question}${question.context ? `
468
- context: ${question.context}` : ""}`).join("\n");
469
- const prompt = [
470
- "You are answering proactive memory follow-up questions using only the provided buffered conversation.",
471
- `Return at most ${maxAdditional} additional high-confidence memory candidates that were omitted from the base extraction.`,
472
- "Only include information directly supported by the conversation. Do not speculate. Do not repeat the base extraction.",
473
- "Return only valid JSON with this shape:",
474
- '{"facts":[{"category":"fact","content":"...","confidence":0.0,"tags":["..."],"entityRef":"optional","promptedByQuestion":"optional"}],"profileUpdates":["..."],"entities":[{"name":"...","type":"person","facts":["..."],"structuredSections":[{"key":"beliefs","title":"Beliefs","facts":["..."]}],"promptedByQuestion":"optional"}],"relationships":[{"source":"...","target":"...","label":"...","promptedByQuestion":"optional"}]}',
475
- "",
476
- "Base extracted facts (do not repeat):",
477
- factsPreview || "(none)",
478
- "",
479
- "Base extracted entities (do not repeat):",
480
- entitiesPreview || "(none)",
481
- "",
482
- "Answer these follow-up questions from the same conversation only:",
483
- proactivePreview || "(none)",
484
- "",
485
- "Conversation:",
486
- conversation
487
- ].join("\n");
488
- if (this.shouldUseLocalLlm) {
489
- try {
490
- const localResponse = await this.localLlm.chatCompletion(
491
- [
492
- {
493
- role: "system",
494
- content: "You are a proactive memory extraction assistant. Output valid JSON only."
495
- },
496
- { role: "user", content: prompt }
497
- ],
498
- {
499
- temperature: 0.2,
500
- maxTokens: this.config.proactiveExtractionMaxTokens,
501
- timeoutMs: this.config.proactiveExtractionTimeoutMs,
502
- operation: "proactive_extraction",
503
- priority: "background"
504
- }
505
- );
506
- if (localResponse?.content) {
507
- const parsed = this.parseProactiveExtractionResultFromText(localResponse.content.trim());
508
- if (parsed) {
509
- return this.sanitizeExtractionResult(parsed);
510
- }
511
- }
512
- if (!this.config.localLlmFallback) {
513
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
514
- }
515
- } catch (err) {
516
- if (!this.config.localLlmFallback) {
517
- throw err;
518
- }
519
- }
520
- }
521
- const fallbackResult = await this.fallbackLlm.parseWithSchema(
522
- [
523
- {
524
- role: "system",
525
- content: "Answer proactive memory follow-up questions from the provided conversation only. Return valid JSON only."
526
- },
527
- { role: "user", content: prompt }
528
- ],
529
- ProactiveExtractionResultSchema,
530
- this.withGatewayAgent({
531
- temperature: 0.2,
532
- maxTokens: this.config.proactiveExtractionMaxTokens,
533
- timeoutMs: this.config.proactiveExtractionTimeoutMs
534
- })
535
- );
536
- if (!fallbackResult) {
537
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
538
- }
539
- return this.sanitizeExtractionResult(
540
- this.normalizeExtractionResultPayload({
541
- ...fallbackResult,
542
- questions: []
543
- })
544
- );
545
- }
546
- mergeProactiveExtractionPass(base, proactive, maxAdditional) {
547
- const allowlist = this.config.proactiveExtractionCategoryAllowlist;
548
- let remainingBudget = Math.max(0, Math.floor(maxAdditional));
549
- const mergedFacts = [...base.facts];
550
- const seenFacts = new Set(base.facts.map((fact) => normalizeFactKey(fact)));
551
- for (const fact of proactive.facts) {
552
- if (remainingBudget <= 0) break;
553
- if (fact.confidence < PROACTIVE_MIN_CONFIDENCE) continue;
554
- if (allowlist && !allowlist.includes(fact.category)) continue;
555
- const key = normalizeFactKey(fact);
556
- if (seenFacts.has(key)) continue;
557
- seenFacts.add(key);
558
- mergedFacts.push({ ...fact, source: "proactive" });
559
- remainingBudget -= 1;
560
- }
561
- const mergedEntities = base.entities.map((entity) => ({
562
- ...entity,
563
- facts: [...entity.facts],
564
- structuredSections: entity.structuredSections ? entity.structuredSections.map((section) => ({
565
- ...section,
566
- facts: [...section.facts]
567
- })) : void 0
568
- }));
569
- const entityIndex = new Map(mergedEntities.map((entity, index) => [normalizeEntityKey(entity), index]));
570
- for (const entity of proactive.entities) {
571
- if (remainingBudget <= 0) break;
572
- const key = normalizeEntityKey(entity);
573
- const existingIndex = entityIndex.get(key);
574
- if (typeof existingIndex === "number") {
575
- const existing = mergedEntities[existingIndex];
576
- const nextFacts = new Set(existing.facts.map((fact) => fact.trim()));
577
- const nextSections = new Map(
578
- (existing.structuredSections ?? []).map((section) => [section.key, {
579
- ...section,
580
- facts: [...section.facts]
581
- }])
582
- );
583
- let changed = false;
584
- for (const fact of entity.facts) {
585
- const trimmed = fact.trim();
586
- if (!trimmed || nextFacts.has(trimmed)) continue;
587
- nextFacts.add(trimmed);
588
- changed = true;
589
- }
590
- for (const section of entity.structuredSections ?? []) {
591
- const existingSection = nextSections.get(section.key);
592
- if (!existingSection) {
593
- nextSections.set(section.key, {
594
- key: section.key,
595
- title: section.title,
596
- facts: [...section.facts]
597
- });
598
- changed = true;
599
- continue;
600
- }
601
- const nextSectionFacts = new Set(existingSection.facts.map((fact) => fact.trim()));
602
- for (const fact of section.facts) {
603
- const trimmed = fact.trim();
604
- if (!trimmed || nextSectionFacts.has(trimmed)) continue;
605
- nextSectionFacts.add(trimmed);
606
- changed = true;
607
- }
608
- existingSection.facts = Array.from(nextSectionFacts);
609
- }
610
- if (changed) {
611
- mergedEntities[existingIndex] = {
612
- ...existing,
613
- facts: Array.from(nextFacts),
614
- structuredSections: Array.from(nextSections.values()),
615
- source: "proactive",
616
- promptedByQuestion: existing.promptedByQuestion ?? entity.promptedByQuestion
617
- };
618
- remainingBudget -= 1;
619
- }
620
- continue;
621
- }
622
- mergedEntities.push({
623
- ...entity,
624
- source: "proactive",
625
- structuredSections: entity.structuredSections ? entity.structuredSections.map((section) => ({
626
- ...section,
627
- facts: [...section.facts]
628
- })) : void 0
629
- });
630
- entityIndex.set(key, mergedEntities.length - 1);
631
- remainingBudget -= 1;
632
- }
633
- const mergedProfileUpdates = [...base.profileUpdates];
634
- const seenProfileUpdates = new Set(base.profileUpdates.map((update) => normalizeProfileUpdateKey(update)));
635
- for (const update of proactive.profileUpdates) {
636
- if (remainingBudget <= 0) break;
637
- const key = normalizeProfileUpdateKey(update);
638
- if (!key || seenProfileUpdates.has(key)) continue;
639
- seenProfileUpdates.add(key);
640
- mergedProfileUpdates.push(update.trim());
641
- remainingBudget -= 1;
642
- }
643
- const mergedRelationships = [...base.relationships ?? []];
644
- const seenRelationships = new Set(mergedRelationships.map((relationship) => normalizeRelationshipKey(relationship)));
645
- for (const relationship of proactive.relationships ?? []) {
646
- if (remainingBudget <= 0) break;
647
- const key = normalizeRelationshipKey(relationship);
648
- if (seenRelationships.has(key)) continue;
649
- seenRelationships.add(key);
650
- mergedRelationships.push({ ...relationship, extractionSource: "proactive" });
651
- remainingBudget -= 1;
652
- }
653
- return {
654
- ...base,
655
- facts: mergedFacts,
656
- entities: mergedEntities,
657
- profileUpdates: mergedProfileUpdates,
658
- relationships: mergedRelationships
659
- };
660
- }
661
- async parseWithGatewayFallback(traceId, operation, startedAtMs, schema, messages, options = {}) {
662
- const detailed = await this.fallbackLlm.parseWithSchemaDetailed(messages, schema, this.withGatewayAgent(options));
663
- if (detailed?.result) {
664
- const durationMs = Date.now() - startedAtMs;
665
- this.emit({
666
- kind: "llm_end",
667
- traceId,
668
- model: detailed.modelUsed,
669
- operation,
670
- durationMs,
671
- output: JSON.stringify(detailed.result).slice(0, 2e3)
672
- });
673
- return detailed.result;
674
- }
675
- return null;
676
- }
677
- async extract(turns, existingEntities) {
678
- const substantiveTurns = turns.filter((t) => t.content.trim().length > 0);
679
- if (substantiveTurns.length === 0) {
680
- log.debug("extraction skipped \u2014 no substantive turns in buffer");
681
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
682
- }
683
- const boundedTurns = substantiveTurns.map((turn) => ({
684
- ...turn,
685
- content: turn.role === "assistant" ? applyWorkExtractionBoundary(turn.content) : turn.content
686
- })).filter((turn) => turn.content.trim().length > 0);
687
- const conversation = boundedTurns.map((t) => {
688
- const roleLabel = t.extractionContextOnly === true ? `context ${t.role}` : t.role;
689
- return `[${roleLabel}] ${t.content}`;
690
- }).join("\n\n");
691
- if (conversation.trim().length === 0) {
692
- log.debug("extraction skipped \u2014 conversation only contained non-memory work-layer context");
693
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
694
- }
695
- if (this.config.extractionTelemetryPrefilterEnabled && looksLikeMechanicalTelemetryTranscript(conversation)) {
696
- log.debug("extraction skipped \u2014 mechanical action/state telemetry without durable-memory cues");
697
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
698
- }
699
- const lastTurnTs = boundedTurns.length > 0 ? new Date(boundedTurns[boundedTurns.length - 1].timestamp) : void 0;
700
- const messageTimestamp = lastTurnTs && !isNaN(lastTurnTs.getTime()) ? lastTurnTs : void 0;
701
- const traceId = crypto.randomUUID();
702
- const emittedDirectStart = !!(this.shouldUseDirectClient || this.shouldUseLocalLlm);
703
- if (emittedDirectStart) {
704
- this.emit({ kind: "llm_start", traceId, model: this.config.model, operation: "extraction", input: conversation });
705
- }
706
- let closedDirectTrace = false;
707
- const startTime = Date.now();
708
- const extractionTraceId = this.profiler.startTrace("extraction", void 0, {
709
- model: this.config.model,
710
- localLlm: this.config.localLlmEnabled
711
- });
712
- this.profiler.startSpan("total", extractionTraceId);
713
- try {
714
- if (this.shouldUseLocalLlm) {
715
- this.profiler.startSpan("local-llm", extractionTraceId);
716
- try {
717
- const localResult = await this.extractWithLocalLlm(conversation, existingEntities);
718
- if (localResult) {
719
- const durationMs = Date.now() - startTime;
720
- this.profiler.endSpan("local-llm", extractionTraceId);
721
- this.emit({ kind: "llm_end", traceId, model: this.config.localLlmModel, operation: "extraction", durationMs });
722
- log.debug(`extraction: used local LLM \u2014 ${localResult.facts.length} facts, ${localResult.entities.length} entities`);
723
- const sanitized = this.sanitizeExtractionResult(localResult, messageTimestamp);
724
- return await this.applyProactiveQuestionPass(conversation, sanitized);
725
- }
726
- if (!this.config.localLlmFallback) {
727
- log.warn("extraction: local LLM failed and fallback disabled");
728
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
729
- }
730
- log.info("extraction: local LLM unavailable, falling back to gateway default AI");
731
- } catch (err) {
732
- if (!this.config.localLlmFallback) {
733
- log.warn("extraction: local LLM error and fallback disabled:", err);
734
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
735
- }
736
- log.info("extraction: local LLM error, falling back to gateway default AI:", err);
737
- } finally {
738
- try {
739
- this.profiler.endSpan("local-llm", extractionTraceId);
740
- } catch {
741
- }
742
- }
743
- }
744
- if (this.shouldUseDirectClient) {
745
- this.profiler.startSpan("direct-client", extractionTraceId);
746
- try {
747
- const directResult = await this.extractWithDirectClient(conversation, existingEntities);
748
- if (directResult) {
749
- const durationMs = Date.now() - startTime;
750
- this.profiler.endSpan("direct-client", extractionTraceId);
751
- this.emit({ kind: "llm_end", traceId, model: this.config.model, operation: "extraction", durationMs });
752
- log.debug(`extraction: used direct client (${this.config.model}) \u2014 ${directResult.facts.length} facts, ${directResult.entities.length} entities`);
753
- const sanitized = this.sanitizeExtractionResult(directResult, messageTimestamp);
754
- return await this.applyProactiveQuestionPass(conversation, sanitized);
755
- }
756
- try {
757
- this.emit({
758
- kind: "llm_error",
759
- traceId,
760
- model: this.config.model,
761
- operation: "extraction",
762
- durationMs: Date.now() - startTime,
763
- error: "direct client returned no result"
764
- });
765
- } catch {
766
- }
767
- closedDirectTrace = true;
768
- log.info("extraction: direct client returned no result, falling back to gateway AI");
769
- } catch (err) {
770
- try {
771
- this.emit({
772
- kind: "llm_error",
773
- traceId,
774
- model: this.config.model,
775
- operation: "extraction",
776
- durationMs: Date.now() - startTime,
777
- error: String(err)
778
- });
779
- } catch {
780
- }
781
- closedDirectTrace = true;
782
- log.info("extraction: direct client failed, falling back to gateway AI:", err);
783
- } finally {
784
- try {
785
- this.profiler.endSpan("direct-client", extractionTraceId);
786
- } catch {
787
- }
788
- }
789
- }
790
- if (emittedDirectStart && !closedDirectTrace) {
791
- try {
792
- this.emit({
793
- kind: "llm_error",
794
- traceId,
795
- model: this.config.model,
796
- operation: "extraction",
797
- durationMs: Date.now() - startTime,
798
- error: "local LLM failed, handing off to gateway fallback"
799
- });
800
- } catch {
801
- }
802
- }
803
- const fallbackTraceId = crypto.randomUUID();
804
- const fallbackStartTime = Date.now();
805
- if (this.useGatewayModelSource) {
806
- log.debug(
807
- `extraction: using gateway model chain as primary path` + (this.config.gatewayAgentId ? ` (agent: ${this.config.gatewayAgentId})` : " (defaults)")
808
- );
809
- } else {
810
- log.info("extraction: falling back to gateway default AI");
811
- }
812
- this.profiler.startSpan("gateway-fallback", extractionTraceId);
813
- try {
814
- const messages = [
815
- { role: "system", content: this.buildExtractionInstructions(existingEntities) },
816
- { role: "user", content: conversation }
817
- ];
818
- this.emit({ kind: "llm_start", traceId: fallbackTraceId, model: "fallback", operation: "extraction", input: conversation });
819
- const detailed = await this.fallbackLlm.parseWithSchemaDetailed(
820
- messages,
821
- ExtractionResultSchema,
822
- this.withGatewayAgent({
823
- temperature: 0.3,
824
- maxTokens: this.config.extractionMaxOutputTokens,
825
- timeoutMs: this.config.localLlmTimeoutMs
826
- })
827
- );
828
- const fallbackDurationMs = Date.now() - fallbackStartTime;
829
- if (detailed?.result && Array.isArray(detailed.result.facts)) {
830
- const result = detailed.result;
831
- this.emit({
832
- kind: "llm_end",
833
- traceId: fallbackTraceId,
834
- model: detailed.modelUsed,
835
- operation: "extraction",
836
- durationMs: fallbackDurationMs,
837
- output: JSON.stringify(result).slice(0, 2e3)
838
- });
839
- log.debug(
840
- `extracted ${result.facts.length} facts, ${result.entities.length} entities, ${(result.questions ?? []).length} questions via fallback (${detailed.modelUsed})`
841
- );
842
- const normalizedFacts = result.facts.map((f) => {
843
- if (!f?.reasoningTrace) return f;
844
- return {
845
- ...f,
846
- reasoningTrace: normalizeReasoningTrace(f.reasoningTrace) ?? void 0
847
- };
848
- });
849
- const sanitized = this.sanitizeExtractionResult({
850
- ...result,
851
- facts: normalizedFacts,
852
- questions: result.questions ?? [],
853
- identityReflection: result.identityReflection ?? void 0
854
- }, messageTimestamp);
855
- return await this.applyProactiveQuestionPass(conversation, sanitized);
856
- }
857
- this.emit({
858
- kind: "llm_error",
859
- traceId: fallbackTraceId,
860
- model: "fallback",
861
- operation: "extraction",
862
- durationMs: fallbackDurationMs,
863
- error: "fallback returned no parsed output"
864
- });
865
- log.warn("extraction fallback returned no parsed output");
866
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
867
- } catch (err) {
868
- this.emit({
869
- kind: "llm_error",
870
- traceId: fallbackTraceId,
871
- model: "fallback",
872
- operation: "extraction",
873
- durationMs: Date.now() - fallbackStartTime,
874
- error: String(err)
875
- });
876
- log.error("extraction fallback failed", err);
877
- return { facts: [], profileUpdates: [], entities: [], questions: [] };
878
- } finally {
879
- try {
880
- this.profiler.endSpan("gateway-fallback", extractionTraceId);
881
- } catch {
882
- }
883
- }
884
- } finally {
885
- this.profiler.endSpan("total", extractionTraceId);
886
- this.profiler.endTrace(extractionTraceId);
887
- }
888
- }
889
- /**
890
- * Extract memories using local LLM with JSON mode.
891
- * Uses a minimal prompt to fit within local model context limits (typically 4k-8k).
892
- */
893
- async extractWithLocalLlm(conversation, existingEntities) {
894
- log.debug(
895
- `extractWithLocalLlm: starting extraction, localLlmEnabled=${this.shouldUseLocalLlm}, model=${this.config.localLlmModel}`
896
- );
897
- const contextSizes = this.modelRegistry.calculateContextSizes(
898
- this.config.localLlmModel,
899
- this.config.localLlmMaxContext
900
- );
901
- log.debug(`Model context: ${contextSizes.description}`);
902
- const maxConversationChars = contextSizes.maxInputChars;
903
- const truncatedConversation = conversation.length > maxConversationChars ? conversation.slice(0, maxConversationChars) + "\n\n[truncated]" : conversation;
904
- const localPrompt = `You are a memory extraction system. Extract durable, reusable memories from this conversation.
905
-
906
- Memory categories \u2014 use the MOST SPECIFIC category that fits:
907
- - fact: Objective information about the world
908
- - preference: User likes, dislikes, or stylistic choices
909
- - correction: User correcting a mistake (highest priority)
910
- - entity: People, projects, tools, companies (use canonical hyphenated names like "my-project")
911
- - decision: Choices made with rationale
912
- - relationship: How entities relate (e.g., "Alice manages Bob")
913
- - principle: Durable rules or operating beliefs (e.g., "never use X API")
914
- - commitment: Promises, obligations, deadlines
915
- - moment: Emotionally significant events
916
- - skill: Demonstrated capabilities
917
- - rule: Explicit operational rules or constraints
918
- - procedure: Repeatable workflows \u2014 use when the user describes a multi-step play (\u22652 ordered steps). Put the human-readable trigger/context in "content" (e.g. "When you deploy\u2026") and list steps in "procedureSteps" as [{"order":1,"intent":"\u2026"}, \u2026] mirroring the gateway extraction schema.
919
- - reasoning_trace: Stored solution chains \u2014 use when the user narrates HOW they solved a specific problem step-by-step ("here's how I figured out\u2026", "the debugging went like this\u2026"). Put a short title in "content" (e.g. "How I debugged the staging latency spike") and the chain in "reasoningTrace": {"steps":[{"order":1,"description":"\u2026"}, \u2026], "finalAnswer":"\u2026", "observedOutcome":"\u2026" (optional)}. Require \u22652 ordered steps and a finalAnswer. Do NOT use for ordinary decisions (prefer "decision") or reusable workflows (prefer "procedure").
920
-
921
- IMPORTANT: Do NOT label everything as "fact". Use "decision" for architectural choices, "commitment" for deadlines/promises, "principle" for reusable rules, "correction" for when the user rejects a suggestion, etc.
922
-
923
- === DO NOT EXTRACT (negative examples) ===
924
- These are operational noise - skip them:
925
- - "The user has a cron job that runs every 30 minutes" (scheduled task descriptions)
926
- - "The user encountered error XYZ at 3:45 PM" (temporary error states)
927
- - "The file is located at /path/to/project/file" (transient file paths)
928
- - "The system is using 4GB of memory" (current resource usage)
929
- - "The user ran the 'git status' command" (individual command executions)
930
- - "The conversation took place on Tuesday" (session metadata)
931
- - "The agent read the file at /path/to/file.txt" (agent's own actions)
932
- - "The user's OpenClaw automation posts to #channel on failures" (automation behavior descriptions)
933
- - "The user stores state in /path/to/state.json" (implementation details)
934
- - "The X-watch automation has been stalled for 58 hours" (system status updates)
935
- - "The user processed 5 batch files and extracted insights" (processing summaries)
936
- - "The user has a cron job that runs a Checkpoint Loop every 2 hours" (automation schedules)
937
- - "The user runs a Morning Surprise cron job daily at 7:30 AM" (automation schedules)
938
- - "The user runs an X Bookmarks \u2192 Insights pipeline hourly at :13" (automation schedules)
939
- - "The user's system mines X/Twitter mentions for ideas every 10a/2p/6p" (automation schedules)
940
- - "The user runs a Health Insights cron job weekday mornings" (automation schedules)
941
- - "The system monitors the showcase page every 12 hours" (system monitoring configurations)
942
-
943
- === DO EXTRACT (positive examples) ===
944
- These are durable insights - capture them:
945
- - "The user prefers dark mode interfaces and finds light mode uncomfortable" (preference)
946
- - "The user works primarily with TypeScript and avoids Python for frontend code" (long-term fact)
947
- - "The user's side project 'alpha-trader' uses a custom algorithm for arbitrage" (entity + detail)
948
- - "The user corrected that PostgreSQL 15 is required, not version 14" (correction)
949
- - "The user never commits code without running tests first" (principle)
950
- - "The user has a meeting with the design team every Friday at 2pm" (commitment)
951
-
952
- === Rules ===
953
- - Extract only NEW information worth remembering across sessions
954
- - Skip transient details (file paths, current errors, temporary states, agent actions)
955
- - Confidence: Explicit (0.95-1.0), Implied (0.70-0.94), Inferred (0.40-0.69), Speculative (0.00-0.39)
956
- - Corrections get highest confidence (0.95+)
957
- - Each fact should be standalone and self-contained
958
- - Lines labelled [context user] or [context assistant] are reference context only. Use them to resolve pronouns and adjacent question/answer pairs, but do not extract a memory stated only in context lines unless a normal [user] or [assistant] line confirms or completes it.
959
- - CRITICAL: Use canonical hyphenated entity names (e.g., "jane-doe" not "janedoe")
960
- - CRITICAL: NEVER extract the same fact twice - check for duplicates before adding to facts array
961
- - CRITICAL: NEVER extract cron job schedules, automation configurations, or system monitoring details (these are operational noise)
962
- - If uncertain about relevance, prefer NOT extracting${this.config.extractionScopeClassificationEnabled ? `
963
- - For each fact, set "scope" to "global" (cross-project knowledge: framework bugs, library behavior, user preferences, tool configs, general patterns) or "project" (codebase-specific: file paths, env configs, deployment details, project workarounds). When in doubt, prefer "project".` : ""}
964
-
965
- === Structured Attributes ===
966
- When a fact contains measurable, categorical, or precisely valued data, add a "structuredAttributes" object with key-value string pairs. This captures exact values for precise retrieval later.
967
- Examples of when to add structuredAttributes:
968
- - Product details: {"price": "29.99", "brand": "Sony", "color": "black", "rating": "4.5"}
969
- - Person details: {"age": "32", "occupation": "engineer", "city": "Austin"}
970
- - Events with dates: {"date": "2024-03-15", "location": "San Francisco"}
971
- - Decisions: {"chosen": "PostgreSQL", "rejected": "MongoDB", "reason": "ACID compliance"}
972
- - Quantities/measurements: {"budget": "50000", "team_size": "5", "deadline": "2024-06-01"}
973
- Only add structuredAttributes when there are concrete values. Skip for abstract or narrative facts.
974
-
975
- Also generate:
976
- 1. 1-3 genuine questions you're curious about from this conversation
977
- 2. Profile updates about user patterns/behaviors (if any)
978
- 3. Relationships between entities (max 5). Use normalized names like "person-jane-doe", "company-acme-corp".
979
- 4. For entity facts that fit a durable named heading, include entity.structuredSections with {key, title, facts}.
980
-
981
- Output JSON:
982
- {
983
- "facts": [{"category": "decision", "content": "Chose PostgreSQL over MongoDB for the user service", "importance": 8, "confidence": 0.9, "scope": "project", "structuredAttributes": {"chosen": "PostgreSQL", "rejected": "MongoDB"}}, {"category": "procedure", "content": "When you cut a hotfix release, follow the checklist", "importance": 8, "confidence": 0.9, "scope": "project", "procedureSteps": [{"order": 1, "intent": "Branch from main and cherry-pick the fix"}, {"order": 2, "intent": "Run CI and tag the release"}]}, {"category": "reasoning_trace", "content": "How I debugged the staging latency spike", "importance": 7, "confidence": 0.9, "scope": "project", "reasoningTrace": {"steps": [{"order": 1, "description": "Checked CPU/memory dashboards \u2014 both were flat"}, {"order": 2, "description": "Ran a traceroute and saw retries against the cache tier"}, {"order": 3, "description": "Tailed cache-tier logs and spotted eviction storms"}], "finalAnswer": "Root cause was an undersized eviction policy on the session cache", "observedOutcome": "Increased cache size, p95 returned to baseline within 10 minutes"}}, {"category": "commitment", "content": "Must ship v2.0 API by end of March", "importance": 10, "confidence": 1.0, "scope": "project", "structuredAttributes": {"deadline": "end of March", "deliverable": "v2.0 API"}}, {"category": "fact", "content": "The store backend uses Redis for session caching", "importance": 6, "confidence": 0.95, "scope": "project", "entityRef": "project-acme-store"}, {"category": "principle", "content": "Always run migrations in a transaction to avoid partial schema updates", "importance": 8, "confidence": 0.9, "scope": "global"}],
984
- "entities": [{"name": "person-jane-doe", "type": "person", "facts": ["Works at Acme Corp", "Prefers Python over JavaScript"], "structuredSections": [{"key": "beliefs", "title": "Beliefs", "facts": ["Python is a better fit than JavaScript for backend work."]}]}, {"name": "project-acme-store", "type": "project", "facts": ["Built with Next.js", "Deployed on Vercel"]}],
985
- "profileUpdates": ["User prefers dark mode in all editors"],
986
- "questions": [{"question": "Which cloud provider hosts the staging environment?", "context": "Came up during deployment discussion", "priority": 0.5}],
987
- "relationships": [{"source": "person-jane-doe", "target": "company-acme-corp", "label": "works at"}]
988
- }
989
-
990
- Conversation:
991
- ${truncatedConversation}`;
992
- log.debug(
993
- `extractWithLocalLlm: calling localLlm.chatCompletion with prompt length ${localPrompt.length}...`
994
- );
995
- const response = await this.localLlm.chatCompletion(
996
- [
997
- { role: "system", content: "You are a memory extraction system. Output valid JSON only." },
998
- { role: "user", content: localPrompt }
999
- ],
1000
- {
1001
- temperature: 0.1,
1002
- maxTokens: contextSizes.maxOutputTokens,
1003
- operation: "extraction",
1004
- priority: "background"
1005
- }
1006
- );
1007
- if (!response?.content) {
1008
- log.debug("extractWithLocalLlm: chatCompletion returned null or empty content");
1009
- return null;
1010
- }
1011
- const content = response.content.trim();
1012
- log.debug(`extractWithLocalLlm: got response content, length=${content.length}`);
1013
- try {
1014
- for (const candidate of extractJsonCandidates(content)) {
1015
- try {
1016
- log.debug(`extractWithLocalLlm: attempting JSON parse, candidate length=${candidate.length}`);
1017
- const parsed = JSON.parse(candidate);
1018
- const result = this.normalizeExtractionResultPayload(parsed);
1019
- log.debug(
1020
- `extractWithLocalLlm: successfully parsed response, facts=${result.facts.length}, entities=${result.entities.length}, profileUpdates=${result.profileUpdates.length}, questions=${result.questions.length}`
1021
- );
1022
- return result;
1023
- } catch {
1024
- }
1025
- }
1026
- return null;
1027
- } catch (err) {
1028
- log.debug("extractWithLocalLlm: JSON parse failed, attempting partial extraction...");
1029
- const partial = this.extractPartialFacts(content);
1030
- if (partial.facts.length > 0 || partial.entities.length > 0) {
1031
- log.debug(
1032
- `extractWithLocalLlm: extracted ${partial.facts.length} partial facts from truncated JSON`
1033
- );
1034
- return partial;
1035
- }
1036
- const errMsg = err instanceof Error ? err.message : String(err);
1037
- log.debug(`extractWithLocalLlm: JSON parse error: ${errMsg}`);
1038
- return null;
1039
- }
1040
- }
1041
- /**
1042
- * Extract memories using direct OpenAI-compatible client (Chat Completions API).
1043
- * Works with Scryr, OpenRouter, and other OpenAI-compatible endpoints.
1044
- */
1045
- async extractWithDirectClient(conversation, existingEntities) {
1046
- if (!this.client) return null;
1047
- const tokenParams = buildChatCompletionTokenLimit(this.config.model, this.config.extractionMaxOutputTokens, {
1048
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
1049
- });
1050
- log.debug(`extractWithDirectClient: calling model=${this.config.model} tokenParams=${JSON.stringify(tokenParams)}`);
1051
- const response = await this.client.chat.completions.create({
1052
- model: this.config.model,
1053
- messages: [
1054
- {
1055
- role: "system",
1056
- content: this.buildExtractionInstructions(existingEntities) + `
1057
-
1058
- Respond with valid JSON matching this schema:
1059
- {
1060
- "facts": [{"category": "decision", "content": "Chose React over Vue for the dashboard rewrite", "importance": 8, "confidence": 0.9, "tags": ["frontend"], "scope": "project", "structuredAttributes": {"chosen": "React", "rejected": "Vue"}}, {"category": "fact", "content": "The API gateway uses rate limiting at 1000 req/min", "importance": 6, "confidence": 0.95, "tags": ["infra"], "scope": "project", "entityRef": "project-dashboard", "structuredAttributes": {"rate_limit": "1000 req/min"}}, {"category": "reasoning_trace", "content": "How I chose the dashboard rewrite framework", "confidence": 0.9, "tags": ["frontend"], "scope": "project", "reasoningTrace": {"steps": [{"order": 1, "description": "Listed constraints: SSR needed, team mostly JS"}, {"order": 2, "description": "Ran a spike in Vue 3 \u2014 worked, but ecosystem felt thin for our needs"}, {"order": 3, "description": "Ran the same spike in React \u2014 integrated faster with Next.js"}], "finalAnswer": "Picked React with Next.js for SSR + ecosystem fit"}}],
1061
- "entities": [{"name": "person-sarah-chen", "type": "person", "facts": ["Leads the backend team", "Joined from Google in 2024"], "structuredSections": [{"key": "beliefs", "title": "Beliefs", "facts": ["Small teams should own whole systems."]}]}, {"name": "project-dashboard", "type": "project", "facts": ["React-based admin panel", "Deployed on AWS ECS"]}],
1062
- "profileUpdates": ["User prefers TypeScript over plain JavaScript"],
1063
- "questions": [{"question": "What database does the analytics service use?", "context": "Came up during discussion of migration plan", "priority": 0.5}],
1064
- "relationships": [{"source": "person-sarah-chen", "target": "project-dashboard", "label": "leads development of"}]
1065
- }`
1066
- },
1067
- { role: "user", content: conversation }
1068
- ],
1069
- ...tokenParams
1070
- });
1071
- const content = response.choices?.[0]?.message?.content?.trim();
1072
- if (!content) {
1073
- log.info(`extractWithDirectClient: empty response \u2014 choices=${JSON.stringify(response.choices?.length ?? 0)} finishReason=${response.choices?.[0]?.finish_reason ?? "n/a"}`);
1074
- return null;
1075
- }
1076
- log.info(
1077
- `extractWithDirectClient: got response, length=${content.length}`
1078
- );
1079
- for (const candidate of extractJsonCandidates(content)) {
1080
- try {
1081
- const parsed = JSON.parse(candidate);
1082
- return this.normalizeExtractionResultPayload(parsed);
1083
- } catch {
1084
- }
1085
- }
1086
- log.info(`extractWithDirectClient: failed to parse JSON from response (first 200 chars: ${content.slice(0, 200)})`);
1087
- return null;
1088
- }
1089
- /**
1090
- * Extract partial facts from truncated JSON responses.
1091
- * Local LLMs sometimes hit token limits mid-JSON. This tries to salvage valid facts.
1092
- */
1093
- extractPartialFacts(jsonStr) {
1094
- const allowedCategories = /* @__PURE__ */ new Set([
1095
- "fact",
1096
- "preference",
1097
- "correction",
1098
- "entity",
1099
- "decision",
1100
- "relationship",
1101
- "principle",
1102
- "commitment",
1103
- "moment",
1104
- "skill",
1105
- "rule",
1106
- "procedure",
1107
- "reasoning_trace"
1108
- ]);
1109
- const allowedEntityTypes = /* @__PURE__ */ new Set([
1110
- "person",
1111
- "project",
1112
- "tool",
1113
- "company",
1114
- "place",
1115
- "other"
1116
- ]);
1117
- const facts = [];
1118
- const entities = [];
1119
- try {
1120
- const factRegex = /\{\s*"category"\s*:\s*"([^"]+)"\s*,\s*"content"\s*:\s*"([^"]+)"\s*,\s*"confidence"\s*:\s*([0-9.]+)/g;
1121
- let match;
1122
- while ((match = factRegex.exec(jsonStr)) !== null) {
1123
- const rawCat = match[1];
1124
- const category = allowedCategories.has(rawCat) ? rawCat : "fact";
1125
- facts.push({
1126
- category,
1127
- content: match[2].replace(/\\n/g, "\n").replace(/\\"/g, '"'),
1128
- confidence: parseFloat(match[3]),
1129
- tags: []
1130
- });
1131
- }
1132
- const entityRegex = /\{\s*"name"\s*:\s*"([^"]+)"\s*,\s*"type"\s*:\s*"([^"]+)"/g;
1133
- while ((match = entityRegex.exec(jsonStr)) !== null) {
1134
- const rawType = match[2];
1135
- const type = allowedEntityTypes.has(rawType) ? rawType : "other";
1136
- entities.push({
1137
- name: match[1],
1138
- type,
1139
- facts: []
1140
- });
1141
- }
1142
- } catch {
1143
- }
1144
- return { facts, entities, profileUpdates: [], questions: [] };
1145
- }
1146
- /**
1147
- * Build extraction instructions shared between local and cloud LLM.
1148
- */
1149
- buildExtractionInstructions(existingEntities) {
1150
- return `You are a memory extraction system. Analyze the following conversation and extract durable, reusable memories.
1151
-
1152
- Memory categories:
1153
- - fact: Objective information about the world
1154
- - preference: User likes, dislikes, or stylistic choices
1155
- - correction: User correcting a mistake or misconception (highest priority)
1156
- - entity: Information about a specific person, project, tool, or company
1157
- - decision: A choice that was made with rationale
1158
- - relationship: How two entities relate to each other (e.g., "Alice is Bob's manager", "Acme Corp uses Shopify")
1159
- - principle: Durable rules, values, or operating beliefs (e.g., "never use Chat Completions API")
1160
- - commitment: Promises, obligations, or deadlines (e.g., "deploy by Friday", "call accountant Monday")
1161
- - moment: Emotionally significant events or milestones (e.g., "first successful deployment of engram")
1162
- - skill: Capabilities the user or agent has demonstrated (e.g., "user is proficient with Kubernetes")${this.config.causalRuleExtractionEnabled ? `
1163
- - rule: Causal rules discovered through experience (format: "IF <condition> THEN <action/outcome>", e.g., "IF Shopify API returns 401 THEN the admin token is missing read_products scope")` : ""}
1164
- - procedure: A reusable workflow the user wants remembered the same way across sessions. Set category to "procedure". Use "content" for a short title that includes explicit trigger phrasing (e.g. "When you deploy to production\u2026", "Whenever you ship a release\u2026"). Add "procedureSteps": an array of at least two objects {"order": number, "intent": "concrete step description"} in execution order. Optional per-step "toolCall": {"kind": "\u2026", "signature": "\u2026"}, "expectedOutcome", "optional": true.
1165
- - reasoning_trace: A stored solution chain / chain-of-thought the user walked through to solve a problem (e.g. "Here's how I debugged the latency spike: first I checked\u2026, then I\u2026, finally I\u2026"). Set category to "reasoning_trace". Use "content" for a short title summarising the problem (e.g. "How I debugged the staging latency spike"). Add "reasoningTrace": {"steps": [{"order": number, "description": "what happened at this step"}, \u2026], "finalAnswer": "the conclusion or answer", "observedOutcome": "optional confirmation of how it played out"}. Require at least two ordered steps AND a finalAnswer. Use this category only when the user explicitly narrates their reasoning \u2014 not for ordinary decisions (use "decision") or reusable workflows (use "procedure").
1166
-
1167
- Rules:
1168
- - Only extract genuinely NEW information worth remembering across sessions
1169
- - Skip transient task details (file paths being edited, current errors, etc.)
1170
- - Priority: corrections > principles${this.config.causalRuleExtractionEnabled ? " > rules" : ""} > preferences > commitments > decisions > relationships > entities > moments > skills > facts
1171
- - Corrections (user saying "actually, don't do X" or "I prefer Y") get highest confidence
1172
- - Each fact should be a standalone, self-contained statement
1173
- - Lines labelled [context user] or [context assistant] are reference context only. Use them to resolve pronouns and adjacent question/answer pairs, but do not extract a memory stated only in context lines unless a normal [user] or [assistant] line confirms or completes it.
1174
- - Entity references should use normalized names (lowercase, hyphenated: "jane-doe", "acme-corp")
1175
- - CRITICAL: Entity names must be CANONICAL. Always use the hyphenated multi-word form: "acme-corp" NOT "acmecorp" or "acme". "jane-doe" NOT "janedoe" or "jane". If unsure, prefer the most specific full name.
1176
- - Avoid creating entities typed as "other" when a more specific type fits (company, project, tool, person, place)
1177
- - When entity facts clearly belong under a durable named heading, add them to entity.structuredSections as {key, title, facts}. Example person headings: "Beliefs", "Communication Style", "Building / Working On". Leave structuredSections empty when no stable heading fits.
1178
- - Tags should be concise and reusable (e.g., "coding-style", "personal", "tools")
1179
- - When a fact contains measurable, categorical, or precisely valued data, include a "structuredAttributes" field with key-value string pairs (e.g., {"price": "29.99", "brand": "Sony"}, {"date": "2024-03-15", "location": "SF"}, {"chosen": "PostgreSQL", "rejected": "MongoDB"}). Only for concrete values, not narrative content.
1180
- - Set confidence using these tiers:
1181
- * Explicit (0.95-1.0): Direct user statements \u2014 "I prefer X", "my name is Y"
1182
- * Implied (0.70-0.94): Strong contextual inference \u2014 user consistently does X, clear from conversation flow
1183
- * Inferred (0.40-0.69): Pattern recognition \u2014 reasonable guess from limited evidence
1184
- * Speculative (0.00-0.39): Tentative hypothesis \u2014 weak signal, needs future confirmation. Speculative memories auto-expire after 30 days if not confirmed.
1185
- - For commitments: include any deadline or timeframe mentioned${this.config.extractionScopeClassificationEnabled ? `
1186
-
1187
- Scope classification:
1188
- For each fact, set "scope" to one of:
1189
- - "global" \u2014 knowledge that applies across projects: core framework/library bugs, API behavior patterns, user preferences (editor, language, style), tool configurations, general coding patterns, infrastructure knowledge, technology facts not tied to one codebase
1190
- - "project" \u2014 knowledge specific to one codebase: file paths, environment configs, deployment details, project-specific workarounds, team/stakeholder info tied to one project, repo-specific conventions
1191
- When in doubt, prefer "project" \u2014 it is safer to keep knowledge scoped narrowly.
1192
- Examples:
1193
- "Magento 2.4.8 has a race condition in checkout" \u2192 "global"
1194
- "User prefers dark mode in all editors" \u2192 "global"
1195
- "The staging server is at staging.acme.com" \u2192 "project"
1196
- "The deploy script lives at scripts/deploy.sh" \u2192 "project"
1197
- "PostgreSQL 15 requires the uuid-ossp extension for gen_random_uuid()" \u2192 "global"
1198
- "The acme-store repo uses a custom Webpack config for SSR" \u2192 "project"` : ""}
1199
-
1200
- Entity creation rules (STRICT):
1201
- - Only create entities for DURABLE things: real people, companies, products, tools, ongoing projects
1202
- - NEVER create entities for transient items: individual PRs, branches, Jira tickets, meetings, agent task IDs, log files, database tables, cron job runs, sessions
1203
- - When you learn something about a transient item (e.g., PR #58 fixed a bug), store it as a FACT with an entityRef to the parent project \u2014 do NOT create an entity for the PR itself
1204
- - Prefer attaching facts to broad parent entities rather than creating sub-entities. E.g., "acme-store uses Algolia for search" is a fact on entity "acme-store", NOT a new entity "acme-store-algolia-connector"
1205
- - The entity list should be SHORT \u2014 think "things that would have their own Wikipedia page" not "things mentioned in passing"
1206
-
1207
- ${existingEntities && existingEntities.length > 0 ? `
1208
- KNOWN ENTITIES (use these exact names when referencing existing things):
1209
- ${existingEntities.join(", ")}
1210
-
1211
- When you see something that matches a known entity, use THAT name exactly. Only create a NEW entity if nothing in this list represents it.
1212
- ` : ""}
1213
- Also extract relationships between entities mentioned in the conversation.
1214
- - Format: {source: "entity-name", target: "entity-name", label: "relationship description"}
1215
- - Max 5 relationships per extraction
1216
- - Only include clear, durable relationships (e.g., "works at", "created", "manages", "uses")
1217
- - Use normalized entity names (e.g., "person-jane-doe", "company-acme-corp")
1218
-
1219
- Also generate 1-3 genuine questions you're curious about based on this conversation. These should be things you'd actually want answers to in future sessions \u2014 not prompts, but real curiosity.
1220
-
1221
- Finally, write a brief identity reflection about the AGENT who had this conversation (not about you, the extraction system). Based on what the agent said and did in the conversation:
1222
- - What communication patterns did the agent show? (e.g., proactive vs reactive, verbose vs concise)
1223
- - Did the agent handle the user's needs well or miss something?
1224
- - What behavioral tendencies are visible? (e.g., cautious, creative, thorough, impatient)
1225
- - What could the agent improve next time?
1226
- Do NOT write about the extraction process itself. Do NOT say things like "I extracted durable facts" \u2014 that's about YOUR job, not the agent's behavior.`;
1227
- }
1228
- async consolidate(newMemories, existingMemories, currentProfile) {
1229
- const newList = newMemories.map(
1230
- (m) => `[${m.frontmatter.id}] (${m.frontmatter.category}) ${m.content}`
1231
- ).join("\n");
1232
- const existingList = existingMemories.slice(-50).map(
1233
- (m) => `[${m.frontmatter.id}] (${m.frontmatter.category}) ${m.content}`
1234
- ).join("\n");
1235
- const cTraceId = crypto.randomUUID();
1236
- this.emit({ kind: "llm_start", traceId: cTraceId, model: this.config.model, operation: "consolidation", input: newList });
1237
- const cStartTime = Date.now();
1238
- if (this.shouldUseLocalLlm) {
1239
- try {
1240
- const localResult = await this.consolidateWithLocalLlm(newList, existingList, currentProfile);
1241
- if (localResult) {
1242
- const durationMs = Date.now() - cStartTime;
1243
- this.emit({ kind: "llm_end", traceId: cTraceId, model: this.config.localLlmModel, operation: "consolidation", durationMs });
1244
- log.debug(`consolidation: used local LLM \u2014 ${localResult.items.length} decisions`);
1245
- return this.sanitizeConsolidationResult(localResult);
1246
- }
1247
- if (!this.config.localLlmFallback) {
1248
- log.warn("consolidation: local LLM failed and fallback disabled");
1249
- return { items: [], profileUpdates: [], entityUpdates: [] };
1250
- }
1251
- log.info("consolidation: local LLM unavailable, falling back to gateway AI");
1252
- } catch (err) {
1253
- if (!this.config.localLlmFallback) {
1254
- log.warn("consolidation: local LLM error and fallback disabled:", err);
1255
- return { items: [], profileUpdates: [], entityUpdates: [] };
1256
- }
1257
- log.info("consolidation: local LLM error, falling back to gateway AI:", err);
1258
- }
1259
- }
1260
- const fallbackResult = await this.parseWithGatewayFallback(
1261
- cTraceId,
1262
- "consolidation",
1263
- cStartTime,
1264
- ConsolidationResultSchema,
1265
- [
1266
- {
1267
- role: "system",
1268
- content: `You are a memory consolidation system. Compare new memories against existing ones and decide what to do with each.
1269
-
1270
- Actions:
1271
- - ADD: Keep the new memory as-is (no duplicate exists)
1272
- - MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
1273
- - UPDATE: Replace existing memory content (provide updated content)
1274
- - INVALIDATE: Remove existing memory (it's been superseded or is wrong)
1275
- - SKIP: This new memory is redundant (exact duplicate or subset of existing)
1276
-
1277
- Also:
1278
- - Suggest profile updates based on patterns across memories
1279
- - Identify entity updates for entity tracking${this.config.causalRuleExtractionEnabled ? `
1280
- - When merging or updating memories, look for IF\u2192THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}`
1281
- },
1282
- {
1283
- role: "user",
1284
- content: `Current behavioral profile:
1285
- ${currentProfile || "(empty)"}
1286
-
1287
- Existing memories:
1288
- ${existingList || "(none)"}
1289
-
1290
- New memories to consolidate:
1291
- ${newList}
1292
-
1293
- Consolidate the new memories against existing ones.`
1294
- }
1295
- ],
1296
- { temperature: 0.3, maxTokens: 4096 }
1297
- );
1298
- if (fallbackResult) {
1299
- log.debug(`consolidation: ${fallbackResult.items.length} decisions via fallback`);
1300
- return this.sanitizeConsolidationResult({
1301
- items: fallbackResult.items,
1302
- profileUpdates: fallbackResult.profileUpdates,
1303
- entityUpdates: fallbackResult.entityUpdates
1304
- });
1305
- }
1306
- if (!this.client) {
1307
- log.warn("consolidation skipped \u2014 no OpenAI API key and local LLM failed/disabled");
1308
- return { items: [], profileUpdates: [], entityUpdates: [] };
1309
- }
1310
- try {
1311
- const instructionText = `You are a memory consolidation system. Compare new memories against existing ones and decide what to do with each.
1312
-
1313
- Actions:
1314
- - ADD: Keep the new memory as-is (no duplicate exists)
1315
- - MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
1316
- - UPDATE: Replace existing memory content (provide updated content)
1317
- - INVALIDATE: Remove existing memory (it's been superseded or is wrong)
1318
- - SKIP: This new memory is redundant (exact duplicate or subset of existing)
1319
-
1320
- Also:
1321
- - Suggest profile updates based on patterns across memories
1322
- - Identify entity updates for entity tracking${this.config.causalRuleExtractionEnabled ? `
1323
- - When merging or updating memories, look for IF\u2192THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}
1324
-
1325
- Current behavioral profile:
1326
- ${currentProfile || "(empty)"}
1327
-
1328
- Existing memories:
1329
- ${existingList || "(none)"}
1330
-
1331
- New memories to consolidate:
1332
- ${newList}
1333
-
1334
- Respond with valid JSON only, matching this schema:
1335
- ${CONSOLIDATION_RESPONSE_SCHEMA}`;
1336
- const response = await this.client.chat.completions.create({
1337
- model: this.config.model,
1338
- messages: [
1339
- { role: "system", content: instructionText },
1340
- { role: "user", content: "Consolidate the new memories against existing ones." }
1341
- ],
1342
- ...this.config.reasoningEffort !== "none" ? { reasoning_effort: this.config.reasoningEffort } : {},
1343
- ...buildChatCompletionTokenLimit(this.config.model, 4096, {
1344
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
1345
- })
1346
- });
1347
- const rawContent = response.choices?.[0]?.message?.content?.trim();
1348
- const cDurationMs = Date.now() - cStartTime;
1349
- const cUsage = response.usage;
1350
- let parsed = null;
1351
- if (rawContent) {
1352
- for (const candidate of extractJsonCandidates(rawContent)) {
1353
- try {
1354
- parsed = JSON.parse(candidate);
1355
- break;
1356
- } catch {
1357
- }
1358
- }
1359
- }
1360
- this.emit({
1361
- kind: "llm_end",
1362
- traceId: cTraceId,
1363
- model: this.config.model,
1364
- operation: "consolidation",
1365
- durationMs: cDurationMs,
1366
- output: parsed ? JSON.stringify(parsed).slice(0, 2e3) : void 0,
1367
- tokenUsage: cUsage ? { input: cUsage.prompt_tokens, output: cUsage.completion_tokens, total: cUsage.total_tokens } : void 0
1368
- });
1369
- if (parsed && Array.isArray(parsed.items)) {
1370
- log.debug(
1371
- `consolidation: ${parsed.items.length} decisions`
1372
- );
1373
- return this.sanitizeConsolidationResult({
1374
- items: parsed.items,
1375
- profileUpdates: Array.isArray(parsed.profileUpdates) ? parsed.profileUpdates : [],
1376
- entityUpdates: Array.isArray(parsed.entityUpdates) ? parsed.entityUpdates : []
1377
- });
1378
- }
1379
- log.warn("consolidation returned no parsed output");
1380
- return { items: [], profileUpdates: [], entityUpdates: [] };
1381
- } catch (err) {
1382
- this.emit({
1383
- kind: "llm_error",
1384
- traceId: cTraceId,
1385
- model: this.config.model,
1386
- operation: "consolidation",
1387
- durationMs: Date.now() - cStartTime,
1388
- error: String(err)
1389
- });
1390
- log.error("consolidation failed", err);
1391
- return { items: [], profileUpdates: [], entityUpdates: [] };
1392
- }
1393
- }
1394
- /**
1395
- * Consolidate memories using local LLM.
1396
- */
1397
- async consolidateWithLocalLlm(newList, existingList, currentProfile) {
1398
- const contextSizes = this.modelRegistry.calculateContextSizes(
1399
- this.config.localLlmModel,
1400
- this.config.localLlmMaxContext
1401
- );
1402
- log.debug(`Consolidation model context: ${contextSizes.description}`);
1403
- const prompt = `You are a memory consolidation system. Compare new memories against existing ones and decide what to do with each.
1404
-
1405
- Actions:
1406
- - ADD: Keep the new memory as-is (no duplicate exists)
1407
- - MERGE: Combine with an existing memory (provide mergeWith ID and updated content)
1408
- - UPDATE: Replace existing memory content (provide updated content)
1409
- - INVALIDATE: Remove existing memory (it's been superseded or is wrong)
1410
- - SKIP: This new memory is redundant (exact duplicate or subset of existing)
1411
-
1412
- Also:
1413
- - Suggest profile updates based on patterns across memories
1414
- - Identify entity updates for entity tracking${this.config.causalRuleExtractionEnabled ? `
1415
- - When merging or updating memories, look for IF\u2192THEN causal patterns. If a memory describes "X failed/succeeded because Y" or "doing X led to Y", rewrite its content to make the causal rule explicit in the form "IF <condition> THEN <action/outcome>".` : ""}
1416
-
1417
- Current behavioral profile:
1418
- ${currentProfile || "(empty)"}
1419
-
1420
- Existing memories:
1421
- ${existingList || "(none)"}
1422
-
1423
- New memories to consolidate:
1424
- ${newList}
1425
-
1426
- Respond with valid JSON matching this schema:
1427
- ${CONSOLIDATION_RESPONSE_SCHEMA}`;
1428
- const response = await this.localLlm.chatCompletion(
1429
- [
1430
- { role: "system", content: "You are a memory consolidation system. Output valid JSON only." },
1431
- { role: "user", content: prompt }
1432
- ],
1433
- {
1434
- temperature: 0.3,
1435
- maxTokens: contextSizes.maxOutputTokens,
1436
- operation: "consolidation",
1437
- priority: "background"
1438
- }
1439
- );
1440
- if (!response?.content) {
1441
- return null;
1442
- }
1443
- try {
1444
- const content = response.content.trim();
1445
- for (const candidate of extractJsonCandidates(content)) {
1446
- try {
1447
- const parsed = JSON.parse(candidate);
1448
- return {
1449
- items: Array.isArray(parsed.items) ? parsed.items : [],
1450
- profileUpdates: Array.isArray(parsed.profileUpdates) ? parsed.profileUpdates : [],
1451
- entityUpdates: Array.isArray(parsed.entityUpdates) ? parsed.entityUpdates : []
1452
- };
1453
- } catch {
1454
- }
1455
- }
1456
- return null;
1457
- } catch (err) {
1458
- log.warn("local LLM consolidation: failed to parse JSON response:", err);
1459
- return null;
1460
- }
1461
- }
1462
- /**
1463
- * Consolidate a bloated profile.md into a compact version.
1464
- * The LLM merges duplicates, removes stale info, and preserves section structure.
1465
- * Returns the consolidated markdown or null on failure.
1466
- */
1467
- async consolidateProfile(fullProfileContent, targetLines = 50) {
1468
- const pTraceId = crypto.randomUUID();
1469
- this.emit({ kind: "llm_start", traceId: pTraceId, model: this.config.model, operation: "profile_consolidation", input: fullProfileContent.slice(0, 2e3) });
1470
- const pStartTime = Date.now();
1471
- if (this.shouldUseLocalLlm) {
1472
- try {
1473
- const localResult = await this.consolidateProfileWithLocalLlm(fullProfileContent, targetLines);
1474
- if (localResult) {
1475
- const durationMs = Date.now() - pStartTime;
1476
- this.emit({ kind: "llm_end", traceId: pTraceId, model: this.config.localLlmModel, operation: "profile_consolidation", durationMs });
1477
- log.debug(`profile consolidation: used local LLM \u2014 removed ${localResult.removedCount} items`);
1478
- return localResult;
1479
- }
1480
- if (!this.config.localLlmFallback) {
1481
- log.warn("profile consolidation: local LLM failed and fallback disabled");
1482
- return null;
1483
- }
1484
- log.info("profile consolidation: local LLM unavailable, falling back to gateway AI");
1485
- } catch (err) {
1486
- if (!this.config.localLlmFallback) {
1487
- log.warn("profile consolidation: local LLM error and fallback disabled:", err);
1488
- return null;
1489
- }
1490
- log.info("profile consolidation: local LLM error, falling back to gateway AI:", err);
1491
- }
1492
- }
1493
- const profileFallback = await this.parseWithGatewayFallback(
1494
- pTraceId,
1495
- "profile_consolidation",
1496
- pStartTime,
1497
- buildProfileConsolidationResultSchema(targetLines),
1498
- [
1499
- {
1500
- role: "system",
1501
- content: `You are a profile consolidation system. You are given a behavioral profile (markdown) that has grown too large. Your job is to produce a CONSOLIDATED version that:
1502
-
1503
- 1. PRESERVES all ## section headers and their structure
1504
- 2. MERGES duplicate or near-duplicate bullet points into single, clear statements
1505
- 3. REMOVES stale information that has been superseded by newer bullets
1506
- 4. REMOVES trivial or overly specific operational details that won't be useful across sessions
1507
- 5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
1508
- 6. Target roughly ${targetLines} lines \u2014 this is a soft target, prioritize quality over length
1509
- 7. Write in the same style as the existing profile \u2014 concise bullets, no fluff
1510
-
1511
- The output should be the COMPLETE consolidated profile as valid markdown, starting with "# Behavioral Profile".`
1512
- },
1513
- { role: "user", content: fullProfileContent }
1514
- ],
1515
- { temperature: 0.3, maxTokens: 4096 }
1516
- );
1517
- if (profileFallback) {
1518
- log.debug(
1519
- `profile consolidation: removed ${profileFallback.removedCount} items \u2014 ${profileFallback.summary} (fallback)`
1520
- );
1521
- return profileFallback;
1522
- }
1523
- if (!this.client) {
1524
- log.warn("profile consolidation skipped \u2014 no OpenAI API key and local LLM failed/disabled");
1525
- return null;
1526
- }
1527
- try {
1528
- const instructionText = `You are a profile consolidation system. You are given a behavioral profile (markdown) that has grown too large. Your job is to produce a CONSOLIDATED version that:
1529
-
1530
- 1. PRESERVES all ## section headers and their structure
1531
- 2. MERGES duplicate or near-duplicate bullet points into single, clear statements
1532
- 3. REMOVES stale information that has been superseded by newer bullets
1533
- 4. REMOVES trivial or overly specific operational details that won't be useful across sessions
1534
- 5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
1535
- 6. Target roughly ${targetLines} lines \u2014 this is a soft target, prioritize quality over length
1536
- 7. Write in the same style as the existing profile \u2014 concise bullets, no fluff
1537
-
1538
- The output should be the COMPLETE consolidated profile as valid markdown, starting with "# Behavioral Profile".
1539
-
1540
- Respond with valid JSON matching this schema:
1541
- {
1542
- "consolidatedProfile": "# Behavioral Profile\\n\\n... (complete markdown)",
1543
- "removedCount": 42,
1544
- "summary": "brief summary of what was consolidated"
1545
- }`;
1546
- const response = await this.client.chat.completions.create({
1547
- model: this.config.model,
1548
- messages: [
1549
- { role: "system", content: instructionText },
1550
- { role: "user", content: fullProfileContent }
1551
- ],
1552
- ...this.config.reasoningEffort !== "none" ? { reasoning_effort: this.config.reasoningEffort } : {},
1553
- ...buildChatCompletionTokenLimit(this.config.model, 4096, {
1554
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
1555
- })
1556
- });
1557
- const rawContent = response.choices?.[0]?.message?.content?.trim();
1558
- const pDurationMs = Date.now() - pStartTime;
1559
- const pUsage = response.usage;
1560
- let parsed = null;
1561
- if (rawContent) {
1562
- for (const candidate of extractJsonCandidates(rawContent)) {
1563
- try {
1564
- parsed = JSON.parse(candidate);
1565
- break;
1566
- } catch {
1567
- }
1568
- }
1569
- }
1570
- this.emit({
1571
- kind: "llm_end",
1572
- traceId: pTraceId,
1573
- model: this.config.model,
1574
- operation: "profile_consolidation",
1575
- durationMs: pDurationMs,
1576
- output: parsed ? parsed.summary : void 0,
1577
- tokenUsage: pUsage ? { input: pUsage.prompt_tokens, output: pUsage.completion_tokens, total: pUsage.total_tokens } : void 0
1578
- });
1579
- if (parsed && typeof parsed.consolidatedProfile === "string") {
1580
- log.debug(
1581
- `profile consolidation: removed ${parsed.removedCount ?? 0} items \u2014 ${parsed.summary ?? ""}`
1582
- );
1583
- return {
1584
- consolidatedProfile: parsed.consolidatedProfile,
1585
- removedCount: Number(parsed.removedCount || 0),
1586
- summary: String(parsed.summary || "")
1587
- };
1588
- }
1589
- log.warn("profile consolidation returned no parsed output");
1590
- return null;
1591
- } catch (err) {
1592
- this.emit({
1593
- kind: "llm_error",
1594
- traceId: pTraceId,
1595
- model: this.config.model,
1596
- operation: "profile_consolidation",
1597
- durationMs: Date.now() - pStartTime,
1598
- error: String(err)
1599
- });
1600
- log.error("profile consolidation failed", err);
1601
- return null;
1602
- }
1603
- }
1604
- /**
1605
- * Consolidate profile using local LLM.
1606
- */
1607
- async consolidateProfileWithLocalLlm(fullProfileContent, targetLines = 50) {
1608
- const contextSizes = this.modelRegistry.calculateContextSizes(
1609
- this.config.localLlmModel,
1610
- this.config.localLlmMaxContext
1611
- );
1612
- log.debug(`Profile consolidation model context: ${contextSizes.description}`);
1613
- const prompt = `You are a profile consolidation system. You are given a behavioral profile (markdown) that has grown too large. Your job is to produce a CONSOLIDATED version that:
1614
-
1615
- 1. PRESERVES all ## section headers and their structure
1616
- 2. MERGES duplicate or near-duplicate bullet points into single, clear statements
1617
- 3. REMOVES stale information that has been superseded by newer bullets
1618
- 4. REMOVES trivial or overly specific operational details that won't be useful across sessions
1619
- 5. KEEPS the most important, durable observations about the user's preferences, habits, identity, and working style
1620
- 6. Target roughly ${targetLines} lines \u2014 this is a soft target, prioritize quality over length
1621
- 7. Write in the same style as the existing profile \u2014 concise bullets, no fluff
1622
-
1623
- Profile to consolidate:
1624
- ${fullProfileContent}
1625
-
1626
- Respond with valid JSON matching this schema:
1627
- {
1628
- "consolidatedProfile": "# Behavioral Profile\\n\\n... (complete markdown)",
1629
- "removedCount": 42,
1630
- "summary": "brief summary of what was consolidated"
1631
- }`;
1632
- const response = await this.localLlm.chatCompletion(
1633
- [
1634
- { role: "system", content: "You are a profile consolidation system. Output valid JSON only." },
1635
- { role: "user", content: prompt }
1636
- ],
1637
- {
1638
- temperature: 0.3,
1639
- maxTokens: contextSizes.maxOutputTokens,
1640
- operation: "profile_consolidation",
1641
- priority: "background"
1642
- }
1643
- );
1644
- if (!response?.content) {
1645
- return null;
1646
- }
1647
- try {
1648
- const content = response.content.trim();
1649
- for (const candidate of extractJsonCandidates(content)) {
1650
- try {
1651
- const parsed = JSON.parse(candidate);
1652
- return {
1653
- consolidatedProfile: String(parsed.consolidatedProfile || ""),
1654
- removedCount: Number(parsed.removedCount || 0),
1655
- summary: String(parsed.summary || "")
1656
- };
1657
- } catch {
1658
- }
1659
- }
1660
- return null;
1661
- } catch (err) {
1662
- log.warn("local LLM profile consolidation: failed to parse JSON response:", err);
1663
- return null;
1664
- }
1665
- }
1666
- /**
1667
- * Consolidate IDENTITY.md reflections into a concise "Learned Patterns" section.
1668
- * Returns the new content for the IDENTITY.md file (everything below the static header).
1669
- */
1670
- async consolidateIdentity(fullIdentityContent, staticHeaderEndMarker) {
1671
- const iTraceId = crypto.randomUUID();
1672
- this.emit({ kind: "llm_start", traceId: iTraceId, model: this.config.model, operation: "identity_consolidation", input: fullIdentityContent.slice(0, 2e3) });
1673
- const iStartTime = Date.now();
1674
- if (this.shouldUseLocalLlm) {
1675
- try {
1676
- const localResult = await this.consolidateIdentityWithLocalLlm(fullIdentityContent);
1677
- if (localResult) {
1678
- const durationMs = Date.now() - iStartTime;
1679
- this.emit({ kind: "llm_end", traceId: iTraceId, model: this.config.localLlmModel, operation: "identity_consolidation", durationMs });
1680
- log.debug(`identity consolidation: used local LLM \u2014 ${localResult.learnedPatterns.length} patterns`);
1681
- return localResult;
1682
- }
1683
- if (!this.config.localLlmFallback) {
1684
- log.warn("identity consolidation: local LLM failed and fallback disabled");
1685
- return null;
1686
- }
1687
- log.info("identity consolidation: local LLM unavailable, falling back to gateway AI");
1688
- } catch (err) {
1689
- if (!this.config.localLlmFallback) {
1690
- log.warn("identity consolidation: local LLM error and fallback disabled:", err);
1691
- return null;
1692
- }
1693
- log.info("identity consolidation: local LLM error, falling back to gateway AI:", err);
1694
- }
1695
- }
1696
- const identityFallback = await this.parseWithGatewayFallback(
1697
- iTraceId,
1698
- "identity_consolidation",
1699
- iStartTime,
1700
- IdentityConsolidationResultSchema,
1701
- [
1702
- {
1703
- role: "system",
1704
- content: `You are an identity consolidation system. You are given the full contents of an IDENTITY.md file that contains many individual reflection entries. Your job is to:
1705
-
1706
- 1. Read all the reflection entries (sections starting with "## Reflection")
1707
- 2. Extract the most important, durable behavioral patterns and lessons learned
1708
- 3. Consolidate them into concise, standalone statements (aim for 10-25 key patterns)
1709
- 4. Remove redundancy \u2014 if multiple reflections say the same thing, merge into one clear statement
1710
- 5. Prioritize patterns that are actionable and recurring over one-off observations
1711
- 6. Write a brief summary paragraph
1712
-
1713
- The goal is to reduce a bloated file to a compact, high-signal set of learned patterns while preserving all genuinely useful self-knowledge.`
1714
- },
1715
- { role: "user", content: fullIdentityContent }
1716
- ],
1717
- { temperature: 0.3, maxTokens: 4096 }
1718
- );
1719
- if (identityFallback) {
1720
- log.debug(
1721
- `identity consolidation: ${identityFallback.learnedPatterns.length} patterns (fallback)`
1722
- );
1723
- return identityFallback;
1724
- }
1725
- if (!this.client) {
1726
- log.warn("identity consolidation skipped \u2014 no OpenAI API key and local LLM failed/disabled");
1727
- return null;
1728
- }
1729
- try {
1730
- const instructionText = `You are an identity consolidation system. You are given the full contents of an IDENTITY.md file that contains many individual reflection entries. Your job is to:
1731
-
1732
- 1. Read all the reflection entries (sections starting with "## Reflection")
1733
- 2. Extract the most important, durable behavioral patterns and lessons learned
1734
- 3. Consolidate them into concise, standalone statements (aim for 10-25 key patterns)
1735
- 4. Remove redundancy \u2014 if multiple reflections say the same thing, merge into one clear statement
1736
- 5. Prioritize patterns that are actionable and recurring over one-off observations
1737
- 6. Write a brief summary paragraph
1738
-
1739
- The goal is to reduce a bloated file to a compact, high-signal set of learned patterns while preserving all genuinely useful self-knowledge.
1740
-
1741
- Respond with valid JSON matching this schema:
1742
- {
1743
- "learnedPatterns": ["pattern 1", "pattern 2", "pattern 3"],
1744
- "summary": "brief summary of consolidation"
1745
- }`;
1746
- const response = await this.client.chat.completions.create({
1747
- model: this.config.model,
1748
- messages: [
1749
- { role: "system", content: instructionText },
1750
- { role: "user", content: fullIdentityContent }
1751
- ],
1752
- ...this.config.reasoningEffort !== "none" ? { reasoning_effort: this.config.reasoningEffort } : {},
1753
- ...buildChatCompletionTokenLimit(this.config.model, 4096, {
1754
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
1755
- })
1756
- });
1757
- const rawContent = response.choices?.[0]?.message?.content?.trim();
1758
- const iDurationMs = Date.now() - iStartTime;
1759
- const iUsage = response.usage;
1760
- let parsed = null;
1761
- if (rawContent) {
1762
- for (const candidate of extractJsonCandidates(rawContent)) {
1763
- try {
1764
- parsed = JSON.parse(candidate);
1765
- break;
1766
- } catch {
1767
- }
1768
- }
1769
- }
1770
- this.emit({
1771
- kind: "llm_end",
1772
- traceId: iTraceId,
1773
- model: this.config.model,
1774
- operation: "identity_consolidation",
1775
- durationMs: iDurationMs,
1776
- output: parsed ? parsed.summary : void 0,
1777
- tokenUsage: iUsage ? { input: iUsage.prompt_tokens, output: iUsage.completion_tokens, total: iUsage.total_tokens } : void 0
1778
- });
1779
- if (parsed && Array.isArray(parsed.learnedPatterns)) {
1780
- const learnedPatterns = parsed.learnedPatterns.filter((pattern) => typeof pattern === "string").map((pattern) => pattern.trim()).filter((pattern) => pattern.length > 0);
1781
- log.debug(
1782
- `identity consolidation: ${learnedPatterns.length} patterns`
1783
- );
1784
- return {
1785
- learnedPatterns,
1786
- summary: String(parsed.summary || "")
1787
- };
1788
- }
1789
- log.warn("identity consolidation returned no parsed output");
1790
- return null;
1791
- } catch (err) {
1792
- this.emit({
1793
- kind: "llm_error",
1794
- traceId: iTraceId,
1795
- model: this.config.model,
1796
- operation: "identity_consolidation",
1797
- durationMs: Date.now() - iStartTime,
1798
- error: String(err)
1799
- });
1800
- log.error("identity consolidation failed", err);
1801
- return null;
1802
- }
1803
- }
1804
- /**
1805
- * Consolidate identity using local LLM.
1806
- */
1807
- async consolidateIdentityWithLocalLlm(fullIdentityContent) {
1808
- const contextSizes = this.modelRegistry.calculateContextSizes(
1809
- this.config.localLlmModel,
1810
- this.config.localLlmMaxContext
1811
- );
1812
- log.debug(`Identity consolidation model context: ${contextSizes.description}`);
1813
- const prompt = `You are an identity consolidation system. You are given the full contents of an IDENTITY.md file that contains many individual reflection entries. Your job is to:
1814
-
1815
- 1. Read all the reflection entries (sections starting with "## Reflection")
1816
- 2. Extract the most important, durable behavioral patterns and lessons learned
1817
- 3. Consolidate them into concise, standalone statements (aim for 10-25 key patterns)
1818
- 4. Remove redundancy \u2014 if multiple reflections say the same thing, merge into one clear statement
1819
- 5. Prioritize patterns that are actionable and recurring over one-off observations
1820
- 6. Write a brief summary paragraph
1821
-
1822
- The goal is to reduce a bloated file to a compact, high-signal set of learned patterns while preserving all genuinely useful self-knowledge.
1823
-
1824
- IDENTITY.md content:
1825
- ${fullIdentityContent}
1826
-
1827
- Respond with valid JSON matching this schema:
1828
- {
1829
- "learnedPatterns": ["pattern 1", "pattern 2", "pattern 3"],
1830
- "summary": "brief summary of consolidation"
1831
- }`;
1832
- const response = await this.localLlm.chatCompletion(
1833
- [
1834
- { role: "system", content: "You are an identity consolidation system. Output valid JSON only." },
1835
- { role: "user", content: prompt }
1836
- ],
1837
- {
1838
- temperature: 0.3,
1839
- maxTokens: contextSizes.maxOutputTokens,
1840
- operation: "identity_consolidation",
1841
- priority: "background"
1842
- }
1843
- );
1844
- if (!response?.content) {
1845
- return null;
1846
- }
1847
- try {
1848
- const content = response.content.trim();
1849
- for (const candidate of extractJsonCandidates(content)) {
1850
- try {
1851
- const parsed = JSON.parse(candidate);
1852
- return {
1853
- learnedPatterns: Array.isArray(parsed.learnedPatterns) ? parsed.learnedPatterns : [],
1854
- summary: String(parsed.summary || "")
1855
- };
1856
- } catch {
1857
- }
1858
- }
1859
- return null;
1860
- } catch (err) {
1861
- log.warn("local LLM identity consolidation: failed to parse JSON response:", err);
1862
- return null;
1863
- }
1864
- }
1865
- /**
1866
- * Verify if two memories contradict each other using LLM.
1867
- * Called when QMD finds semantically similar memories (Phase 2B).
1868
- */
1869
- async verifyContradiction(newMemory, existingMemory) {
1870
- const input = `Memory 1 (existing, created ${existingMemory.created}):
1871
- Category: ${existingMemory.category}
1872
- Content: ${existingMemory.content}
1873
-
1874
- Memory 2 (new):
1875
- Category: ${newMemory.category}
1876
- Content: ${newMemory.content}`;
1877
- try {
1878
- const instructionText = `You are a contradiction detection system. Analyze whether two memories contradict each other.
1879
-
1880
- IMPORTANT: Not all similar memories are contradictions!
1881
- - "User likes TypeScript" and "User likes Python" are NOT contradictions (preferences can coexist)
1882
- - "User prefers dark mode" and "User prefers light mode" ARE contradictions (mutually exclusive)
1883
- - "User's email is a@b.com" and "User's email is c@d.com" ARE contradictions (only one email)
1884
- - "User works at Acme" and "User used to work at Acme" might be a contradiction (temporal change)
1885
-
1886
- Only mark as contradiction if the two statements CANNOT both be true at the same time.
1887
-
1888
- If they ARE contradictory, determine which represents the more recent/current state based on:
1889
- - Explicit time references ("now", "currently", "used to", "no longer")
1890
- - The fact that newer corrections often start with "actually" or "correction"
1891
- - Context clues about change over time
1892
-
1893
- Respond with valid JSON matching this schema:
1894
- {
1895
- "isContradiction": true,
1896
- "confidence": 0.95,
1897
- "reasoning": "why they contradict or don't",
1898
- "whichIsNewer": "first"
1899
- }`;
1900
- if (this.shouldUseLocalLlm) {
1901
- try {
1902
- const localResponse = await this.localLlm.chatCompletion(
1903
- [
1904
- { role: "system", content: instructionText },
1905
- { role: "user", content: input }
1906
- ],
1907
- {
1908
- temperature: 0.3,
1909
- maxTokens: 2048,
1910
- operation: "contradiction_verification",
1911
- priority: "background"
1912
- }
1913
- );
1914
- const normalized2 = this.normalizeContradictionVerificationResult(
1915
- this.parseJsonObject(localResponse?.content)
1916
- );
1917
- if (normalized2) {
1918
- log.debug(
1919
- `contradiction check via local LLM: ${normalized2.isContradiction ? "YES" : "NO"} (confidence: ${normalized2.confidence})`
1920
- );
1921
- return normalized2;
1922
- }
1923
- if (!this.config.localLlmFallback) {
1924
- log.warn("contradiction verification skipped \u2014 local LLM returned invalid JSON and cloud fallback is disabled");
1925
- return null;
1926
- }
1927
- } catch (err) {
1928
- if (!this.config.localLlmFallback) {
1929
- log.warn(`contradiction verification skipped \u2014 local LLM failed and cloud fallback is disabled: ${err}`);
1930
- return null;
1931
- }
1932
- }
1933
- }
1934
- if (!this.shouldUseDirectClient) {
1935
- const fallbackResponse = await this.fallbackLlm.chatCompletion(
1936
- [
1937
- { role: "system", content: instructionText },
1938
- { role: "user", content: input }
1939
- ],
1940
- this.withGatewayAgent({ temperature: 0.3, maxTokens: 2048 })
1941
- );
1942
- const normalized2 = this.normalizeContradictionVerificationResult(
1943
- this.parseJsonObject(fallbackResponse?.content)
1944
- );
1945
- if (normalized2) {
1946
- log.debug(
1947
- `contradiction check via fallback: ${normalized2.isContradiction ? "YES" : "NO"} (confidence: ${normalized2.confidence})`
1948
- );
1949
- return normalized2;
1950
- }
1951
- log.warn("contradiction verification skipped \u2014 no OpenAI API key and fallback unavailable");
1952
- return null;
1953
- }
1954
- const response = await this.client.chat.completions.create({
1955
- model: this.config.model,
1956
- messages: [
1957
- { role: "system", content: instructionText },
1958
- { role: "user", content: input }
1959
- ],
1960
- ...buildChatCompletionTokenLimit(this.config.model, 2048, {
1961
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
1962
- })
1963
- });
1964
- const normalized = this.normalizeContradictionVerificationResult(
1965
- this.parseJsonObject(response.choices?.[0]?.message?.content)
1966
- );
1967
- if (normalized) {
1968
- log.debug(
1969
- `contradiction check: ${normalized.isContradiction ? "YES" : "NO"} (confidence: ${normalized.confidence})`
1970
- );
1971
- return normalized;
1972
- }
1973
- return null;
1974
- } catch (err) {
1975
- log.error("contradiction verification failed", err);
1976
- return null;
1977
- }
1978
- }
1979
- /**
1980
- * Suggest links between a new memory and existing memories (Phase 3A).
1981
- * Called during extraction to build the knowledge graph.
1982
- */
1983
- async suggestLinks(newMemory, candidateMemories) {
1984
- if (candidateMemories.length === 0) {
1985
- return { links: [] };
1986
- }
1987
- const candidateList = candidateMemories.map((m, i) => `[${i + 1}] ID: ${m.id}
1988
- Category: ${m.category}
1989
- Content: ${m.content}`).join("\n\n");
1990
- const input = `New memory:
1991
- Category: ${newMemory.category}
1992
- Content: ${newMemory.content}
1993
-
1994
- Candidate memories to link to:
1995
- ${candidateList}`;
1996
- try {
1997
- const instructionText = `You are a memory linking system. Analyze the new memory and suggest relationships to existing memories.
1998
-
1999
- Link types:
2000
- - follows: This memory is a continuation or next step (e.g., decision follows discussion)
2001
- - references: This memory mentions or refers to the other (e.g., fact references entity)
2002
- - contradicts: This memory conflicts with the other (use sparingly, only for true contradictions)
2003
- - supports: This memory provides evidence or reinforcement (e.g., example supports principle)
2004
- - related: General topical relationship
2005
-
2006
- Rules:
2007
- - Only suggest links with strength > 0.5
2008
- - Quality over quantity \u2014 0-3 links is typical
2009
- - Prefer specific link types over generic "related"
2010
- - Consider entity references, topics, and causal relationships
2011
-
2012
- Respond with valid JSON matching this schema:
2013
- {
2014
- "links": [{"targetId": "memory-id", "linkType": "follows|references|contradicts|supports|related", "strength": 0.8, "reason": "why"}]
2015
- }`;
2016
- if (this.shouldUseLocalLlm) {
2017
- try {
2018
- const localResponse = await this.localLlm.chatCompletion(
2019
- [
2020
- { role: "system", content: instructionText },
2021
- { role: "user", content: input }
2022
- ],
2023
- {
2024
- temperature: 0.3,
2025
- maxTokens: 2048,
2026
- operation: "link_suggestion",
2027
- priority: "background"
2028
- }
2029
- );
2030
- const normalized2 = this.normalizeSuggestedLinksResult(this.parseJsonObject(localResponse?.content));
2031
- if (normalized2) {
2032
- log.debug(`suggested ${normalized2.links.length} links via local LLM`);
2033
- return normalized2;
2034
- }
2035
- if (!this.config.localLlmFallback) {
2036
- log.warn("link suggestion skipped \u2014 local LLM returned invalid JSON and cloud fallback is disabled");
2037
- return null;
2038
- }
2039
- } catch (err) {
2040
- if (!this.config.localLlmFallback) {
2041
- log.warn(`link suggestion skipped \u2014 local LLM failed and cloud fallback is disabled: ${err}`);
2042
- return null;
2043
- }
2044
- }
2045
- }
2046
- if (!this.shouldUseDirectClient) {
2047
- const fallbackResponse = await this.fallbackLlm.chatCompletion(
2048
- [
2049
- { role: "system", content: instructionText },
2050
- { role: "user", content: input }
2051
- ],
2052
- this.withGatewayAgent({ temperature: 0.3, maxTokens: 2048 })
2053
- );
2054
- const normalized2 = this.normalizeSuggestedLinksResult(this.parseJsonObject(fallbackResponse?.content));
2055
- if (normalized2) {
2056
- log.debug(`suggested ${normalized2.links.length} links via fallback`);
2057
- return normalized2;
2058
- }
2059
- log.warn("link suggestion skipped \u2014 no OpenAI API key and fallback unavailable");
2060
- return null;
2061
- }
2062
- const response = await this.client.chat.completions.create({
2063
- model: this.config.model,
2064
- messages: [
2065
- { role: "system", content: instructionText },
2066
- { role: "user", content: input }
2067
- ],
2068
- ...buildChatCompletionTokenLimit(this.config.model, 2048, {
2069
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
2070
- })
2071
- });
2072
- const normalized = this.normalizeSuggestedLinksResult(
2073
- this.parseJsonObject(response.choices?.[0]?.message?.content)
2074
- );
2075
- if (normalized) {
2076
- log.debug(`suggested ${normalized.links.length} links`);
2077
- return normalized;
2078
- }
2079
- return null;
2080
- } catch (err) {
2081
- log.error("link suggestion failed", err);
2082
- return null;
2083
- }
2084
- }
2085
- async generateDaySummary(memories) {
2086
- if (!this.config.daySummaryEnabled) {
2087
- log.warn("day summary skipped \u2014 disabled by config");
2088
- return null;
2089
- }
2090
- const memoryContext = formatDaySummaryMemories(memories);
2091
- if (memoryContext.length === 0) return null;
2092
- const instructionText = await loadDaySummaryPrompt();
2093
- let extensionsFooter = "";
2094
- try {
2095
- extensionsFooter = await buildExtensionsFooterForSummary(this.config);
2096
- } catch {
2097
- }
2098
- const userPrompt = `Generate an end-of-day summary from this Remnic memory context:
2099
-
2100
- ${memoryContext}${extensionsFooter.length > 0 ? `
2101
-
2102
- ${extensionsFooter}` : ""}`;
2103
- const traceId = crypto.randomUUID();
2104
- const startedAt = Date.now();
2105
- this.emit({ kind: "llm_start", traceId, model: this.config.model, operation: "day_summary", input: memoryContext.slice(0, 4e3) });
2106
- if (this.shouldUseLocalLlm) {
2107
- try {
2108
- const localResponse = await this.localLlm.chatCompletion(
2109
- [
2110
- { role: "system", content: `${instructionText}
2111
-
2112
- Return valid JSON only.` },
2113
- { role: "user", content: userPrompt }
2114
- ],
2115
- {
2116
- temperature: 0.2,
2117
- maxTokens: 2048,
2118
- operation: "day_summary",
2119
- priority: "background"
2120
- }
2121
- );
2122
- const normalized = this.normalizeDaySummaryResult(this.parseJsonObject(localResponse?.content));
2123
- if (normalized) {
2124
- this.emit({ kind: "llm_end", traceId, model: this.config.localLlmModel, operation: "day_summary", durationMs: Date.now() - startedAt, output: JSON.stringify(normalized).slice(0, 2e3) });
2125
- log.debug(`generated day summary via local LLM (${normalized.bullets.length} bullets)`);
2126
- return normalized;
2127
- }
2128
- if (!this.config.localLlmFallback) {
2129
- this.emit({ kind: "llm_error", traceId, model: this.config.localLlmModel, operation: "day_summary", durationMs: Date.now() - startedAt, error: "local LLM returned invalid JSON and fallback disabled" });
2130
- log.warn("day summary skipped \u2014 local LLM returned invalid JSON and fallback disabled");
2131
- return null;
2132
- }
2133
- } catch (err) {
2134
- if (!this.config.localLlmFallback) {
2135
- this.emit({ kind: "llm_error", traceId, model: this.config.localLlmModel, operation: "day_summary", durationMs: Date.now() - startedAt, error: String(err) });
2136
- log.warn(`day summary skipped \u2014 local LLM failed and fallback disabled: ${err}`);
2137
- return null;
2138
- }
2139
- }
2140
- }
2141
- const fallbackResult = await this.parseWithGatewayFallback(
2142
- traceId,
2143
- "day_summary",
2144
- startedAt,
2145
- DaySummaryResultSchema,
2146
- [
2147
- { role: "system", content: `${instructionText}
2148
-
2149
- Return valid JSON only.` },
2150
- { role: "user", content: userPrompt }
2151
- ],
2152
- { temperature: 0.2, maxTokens: 2048 }
2153
- );
2154
- if (fallbackResult) {
2155
- const normalized = this.normalizeDaySummaryResult(fallbackResult);
2156
- if (normalized) {
2157
- log.debug(`generated day summary via fallback (${normalized.bullets.length} bullets)`);
2158
- return normalized;
2159
- }
2160
- }
2161
- if (this.shouldUseDirectClient) {
2162
- try {
2163
- const response = await this.client.responses.create({
2164
- model: this.config.model,
2165
- instructions: `${instructionText}
2166
-
2167
- Return valid JSON only.`,
2168
- input: userPrompt,
2169
- max_output_tokens: 2048
2170
- });
2171
- const rawText = typeof response.output_text === "string" ? response.output_text : JSON.stringify(response.output_text ?? "");
2172
- const normalized = this.normalizeDaySummaryResult(this.parseJsonObject(rawText));
2173
- if (normalized) {
2174
- this.emit({ kind: "llm_end", traceId, model: this.config.model, operation: "day_summary", durationMs: Date.now() - startedAt, output: JSON.stringify(normalized).slice(0, 2e3) });
2175
- log.debug(`generated day summary via Responses API (${normalized.bullets.length} bullets)`);
2176
- return normalized;
2177
- }
2178
- this.emit({ kind: "llm_error", traceId, model: this.config.model, operation: "day_summary", durationMs: Date.now() - startedAt, error: "Responses API returned unparseable output" });
2179
- } catch (err) {
2180
- this.emit({ kind: "llm_error", traceId, model: this.config.model, operation: "day_summary", durationMs: Date.now() - startedAt, error: `Responses API failed: ${err}` });
2181
- }
2182
- }
2183
- this.emit({ kind: "llm_error", traceId, model: this.config.model, operation: "day_summary", durationMs: Date.now() - startedAt, error: "all generation paths exhausted (local LLM + gateway + Responses API)" });
2184
- log.warn("day summary skipped \u2014 all generation paths exhausted");
2185
- return null;
2186
- }
2187
- /**
2188
- * Summarize a batch of old memories into a compact summary (Phase 4A).
2189
- */
2190
- async summarizeMemories(memories) {
2191
- if (memories.length === 0) return null;
2192
- const memoryList = memories.map((m) => `[${m.id}] (${m.category}, ${m.created.slice(0, 10)})
2193
- ${m.content}`).join("\n\n");
2194
- try {
2195
- const instructionText = `You are a memory summarization system. You are given a batch of old memories that need to be compressed into a summary.
2196
-
2197
- Your task:
2198
- 1. Write a concise summary paragraph (2-4 sentences) capturing the essence of these memories
2199
- 2. Extract the 5-10 most important facts that should be preserved
2200
- 3. List the key entities mentioned
2201
-
2202
- Guidelines:
2203
- - Preserve specific, actionable information
2204
- - Merge redundant details into single statements
2205
- - Focus on durable insights, not transient details
2206
- - Maintain any preferences, decisions, or corrections as key facts
2207
-
2208
- Respond with valid JSON matching this schema:
2209
- {
2210
- "summaryText": "concise summary paragraph",
2211
- "keyFacts": ["fact 1", "fact 2"],
2212
- "keyEntities": ["entity-1", "entity-2"]
2213
- }`;
2214
- if (this.shouldUseLocalLlm) {
2215
- try {
2216
- const localResponse = await this.localLlm.chatCompletion(
2217
- [
2218
- { role: "system", content: instructionText },
2219
- { role: "user", content: `Summarize these ${memories.length} memories:
2220
-
2221
- ${memoryList}` }
2222
- ],
2223
- {
2224
- temperature: 0.3,
2225
- maxTokens: 4096,
2226
- operation: "memory_summarization",
2227
- priority: "background"
2228
- }
2229
- );
2230
- const normalized2 = this.normalizeMemorySummaryResult(this.parseJsonObject(localResponse?.content));
2231
- if (normalized2) {
2232
- log.debug(
2233
- `summarized ${memories.length} memories into ${normalized2.keyFacts.length} key facts via local LLM`
2234
- );
2235
- return normalized2;
2236
- }
2237
- if (!this.config.localLlmFallback) {
2238
- log.warn("summarization skipped \u2014 local LLM returned invalid JSON and cloud fallback is disabled");
2239
- return null;
2240
- }
2241
- } catch (err) {
2242
- if (!this.config.localLlmFallback) {
2243
- log.warn(`summarization skipped \u2014 local LLM failed and cloud fallback is disabled: ${err}`);
2244
- return null;
2245
- }
2246
- }
2247
- }
2248
- if (!this.shouldUseDirectClient) {
2249
- const fallbackResponse = await this.fallbackLlm.chatCompletion(
2250
- [
2251
- { role: "system", content: instructionText },
2252
- { role: "user", content: `Summarize these ${memories.length} memories:
2253
-
2254
- ${memoryList}` }
2255
- ],
2256
- this.withGatewayAgent({ temperature: 0.3, maxTokens: 4096 })
2257
- );
2258
- const normalized2 = this.normalizeMemorySummaryResult(this.parseJsonObject(fallbackResponse?.content));
2259
- if (normalized2) {
2260
- log.debug(`summarized ${memories.length} memories into ${normalized2.keyFacts.length} key facts via fallback`);
2261
- return normalized2;
2262
- }
2263
- log.warn("summarization skipped \u2014 no OpenAI API key and fallback unavailable");
2264
- return null;
2265
- }
2266
- const response = await this.client.chat.completions.create({
2267
- model: this.config.model,
2268
- messages: [
2269
- { role: "system", content: instructionText },
2270
- { role: "user", content: `Summarize these ${memories.length} memories:
2271
-
2272
- ${memoryList}` }
2273
- ],
2274
- ...buildChatCompletionTokenLimit(this.config.model, 4096, {
2275
- assumeOpenAI: this.directClientUsesOpenAiTokenSemantics()
2276
- })
2277
- });
2278
- const normalized = this.normalizeMemorySummaryResult(
2279
- this.parseJsonObject(response.choices?.[0]?.message?.content)
2280
- );
2281
- if (normalized) {
2282
- log.debug(`summarized ${memories.length} memories into ${normalized.keyFacts.length} key facts`);
2283
- return normalized;
2284
- }
2285
- return null;
2286
- } catch (err) {
2287
- log.error("memory summarization failed", err);
2288
- return null;
2289
- }
2290
- }
2291
- };
2292
-
2293
- export {
2294
- ExtractionEngine
2295
- };
2296
- //# sourceMappingURL=chunk-ZG7PTKBK.js.map