@remnic/core 1.0.2 → 1.0.3

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 (347) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/access-cli.d.ts +13 -3
  4. package/dist/access-cli.js +90 -75
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-http.d.ts +10 -3
  7. package/dist/access-http.js +25 -18
  8. package/dist/access-mcp.d.ts +30 -3
  9. package/dist/access-mcp.js +16 -1
  10. package/dist/access-schema.d.ts +12 -12
  11. package/dist/access-schema.js +1 -1
  12. package/dist/access-service.d.ts +65 -4
  13. package/dist/access-service.js +21 -15
  14. package/dist/active-memory-bridge.d.ts +66 -0
  15. package/dist/active-memory-bridge.js +11 -0
  16. package/dist/active-recall.d.ts +96 -0
  17. package/dist/active-recall.js +308 -0
  18. package/dist/active-recall.js.map +1 -0
  19. package/dist/behavior-learner.js +1 -1
  20. package/dist/bootstrap.d.ts +6 -3
  21. package/dist/bootstrap.js +2 -2
  22. package/dist/boxes.js +2 -2
  23. package/dist/briefing.d.ts +169 -0
  24. package/dist/briefing.js +52 -0
  25. package/dist/briefing.js.map +1 -0
  26. package/dist/buffer.d.ts +19 -5
  27. package/dist/buffer.js +2 -2
  28. package/dist/calibration.js +6 -6
  29. package/dist/causal-behavior.js +5 -5
  30. package/dist/causal-chain.js +3 -3
  31. package/dist/causal-consolidation.d.ts +22 -2
  32. package/dist/causal-consolidation.js +36 -9
  33. package/dist/causal-consolidation.js.map +1 -1
  34. package/dist/causal-retrieval.js +6 -6
  35. package/dist/causal-trajectory-graph.js +1 -1
  36. package/dist/causal-trajectory.d.ts +14 -1
  37. package/dist/causal-trajectory.js +5 -1
  38. package/dist/{chunk-KWBU5S5U.js → chunk-2ODBA7MQ.js} +9 -3
  39. package/dist/chunk-2ODBA7MQ.js.map +1 -0
  40. package/dist/{chunk-6UJQNRIO.js → chunk-2VFW5K5U.js} +93 -36
  41. package/dist/chunk-2VFW5K5U.js.map +1 -0
  42. package/dist/chunk-3PG3H5TD.js +7 -0
  43. package/dist/chunk-3PG3H5TD.js.map +1 -0
  44. package/dist/{chunk-NTTLPF7F.js → chunk-3QFQGRHO.js} +5 -5
  45. package/dist/chunk-4DJQYKMN.js +187 -0
  46. package/dist/chunk-4DJQYKMN.js.map +1 -0
  47. package/dist/chunk-4KAN3GZ3.js +225 -0
  48. package/dist/chunk-4KAN3GZ3.js.map +1 -0
  49. package/dist/{chunk-ORZMT74A.js → chunk-4NRAJUDS.js} +11 -1
  50. package/dist/chunk-4NRAJUDS.js.map +1 -0
  51. package/dist/{chunk-B7LOFDVE.js → chunk-4WMCPJWX.js} +8 -3
  52. package/dist/chunk-4WMCPJWX.js.map +1 -0
  53. package/dist/{chunk-G3AG3KZN.js → chunk-5IZL4DCV.js} +2 -2
  54. package/dist/{chunk-BRK4ODMI.js → chunk-5NPGSAVB.js} +2 -2
  55. package/dist/chunk-6MKAMLQL.js +16 -0
  56. package/dist/chunk-6MKAMLQL.js.map +1 -0
  57. package/dist/{chunk-ESSMF2FR.js → chunk-6PFRXT4K.js} +15 -6
  58. package/dist/chunk-6PFRXT4K.js.map +1 -0
  59. package/dist/chunk-6ZH4TU6I.js +245 -0
  60. package/dist/chunk-6ZH4TU6I.js.map +1 -0
  61. package/dist/{chunk-V4YC4LUK.js → chunk-74JR4N5J.js} +175 -63
  62. package/dist/chunk-74JR4N5J.js.map +1 -0
  63. package/dist/{chunk-L5RPWGFK.js → chunk-7DHTMOND.js} +2 -2
  64. package/dist/{chunk-TVVVQQAK.js → chunk-7PA4OZEU.js} +53 -11
  65. package/dist/chunk-7PA4OZEU.js.map +1 -0
  66. package/dist/{chunk-Q6FETXJA.js → chunk-7SEAZFFB.js} +2 -2
  67. package/dist/chunk-ALXMCZEU.js +332 -0
  68. package/dist/chunk-ALXMCZEU.js.map +1 -0
  69. package/dist/{chunk-QANCTXQF.js → chunk-AYPYCLR7.js} +3 -3
  70. package/dist/{chunk-WWIQTB2Y.js → chunk-BKQJBXXX.js} +9 -2
  71. package/dist/chunk-BKQJBXXX.js.map +1 -0
  72. package/dist/{chunk-LP47L3ZX.js → chunk-BTY5RRRF.js} +7 -7
  73. package/dist/{chunk-SCHEKPYH.js → chunk-C2EFFULQ.js} +1 -1
  74. package/dist/{chunk-GJR6D6KC.js → chunk-D654IBA6.js} +2 -2
  75. package/dist/{chunk-UV2FO7J4.js → chunk-E6K4NIEU.js} +2 -2
  76. package/dist/{chunk-T4WRIV2C.js → chunk-EABGC2TL.js} +2 -2
  77. package/dist/chunk-ECKDIK5F.js +813 -0
  78. package/dist/chunk-ECKDIK5F.js.map +1 -0
  79. package/dist/chunk-EJI5XIBB.js +232 -0
  80. package/dist/chunk-EJI5XIBB.js.map +1 -0
  81. package/dist/{chunk-ONRU4L2N.js → chunk-FEMOX5AD.js} +2 -2
  82. package/dist/{chunk-IFFFR3MR.js → chunk-FSFEQI74.js} +3 -3
  83. package/dist/chunk-G4SK7DSQ.js +121 -0
  84. package/dist/chunk-G4SK7DSQ.js.map +1 -0
  85. package/dist/{chunk-UIYZ5T3I.js → chunk-GJQPH5G3.js} +8 -8
  86. package/dist/{chunk-2PO5ZRKV.js → chunk-GZCUW5IC.js} +16 -3
  87. package/dist/chunk-GZCUW5IC.js.map +1 -0
  88. package/dist/{chunk-IZME7KW2.js → chunk-HITJFT7E.js} +24 -10
  89. package/dist/{chunk-IZME7KW2.js.map → chunk-HITJFT7E.js.map} +1 -1
  90. package/dist/chunk-IQT3XTKW.js +121 -0
  91. package/dist/chunk-IQT3XTKW.js.map +1 -0
  92. package/dist/{chunk-BDFZXRSO.js → chunk-J4IYOZZ5.js} +15 -2
  93. package/dist/chunk-J4IYOZZ5.js.map +1 -0
  94. package/dist/{chunk-ZKYI7UVO.js → chunk-JR4ZC3G4.js} +2 -2
  95. package/dist/{chunk-UCYSTFZR.js → chunk-JRNQ3RNA.js} +2 -2
  96. package/dist/{chunk-UYSKNO6E.js → chunk-JROGC36Y.js} +15 -4
  97. package/dist/chunk-JROGC36Y.js.map +1 -0
  98. package/dist/{chunk-GPGBSNKM.js → chunk-K4FLSOR5.js} +2 -2
  99. package/dist/{chunk-M5ZBBBJI.js → chunk-KEG4GNGI.js} +2 -2
  100. package/dist/chunk-KVE7R4CG.js +320 -0
  101. package/dist/chunk-KVE7R4CG.js.map +1 -0
  102. package/dist/{chunk-L7WO3MZ4.js → chunk-KWP7T3DP.js} +2 -2
  103. package/dist/chunk-LAYN4LDC.js +267 -0
  104. package/dist/chunk-LAYN4LDC.js.map +1 -0
  105. package/dist/{chunk-PGK3VUHN.js → chunk-MTLYEMJB.js} +3 -2
  106. package/dist/chunk-MTLYEMJB.js.map +1 -0
  107. package/dist/{chunk-J47FNDR7.js → chunk-MYQWXITD.js} +7 -7
  108. package/dist/{chunk-YNI4S5WT.js → chunk-N53K2EXC.js} +2 -2
  109. package/dist/{chunk-763GUIOU.js → chunk-NBNN5GOB.js} +2 -2
  110. package/dist/{chunk-CXWFUJR2.js → chunk-NSB3WSYS.js} +125 -6
  111. package/dist/chunk-NSB3WSYS.js.map +1 -0
  112. package/dist/{chunk-KL4CP4SB.js → chunk-O5ETUNBT.js} +17 -5
  113. package/dist/chunk-O5ETUNBT.js.map +1 -0
  114. package/dist/{chunk-OOSWAUYB.js → chunk-ODWDQNRE.js} +2 -2
  115. package/dist/{chunk-ISY75RLM.js → chunk-OJFGVJS6.js} +288 -7
  116. package/dist/chunk-OJFGVJS6.js.map +1 -0
  117. package/dist/{chunk-HLBYLYRD.js → chunk-PAORGQRI.js} +70 -13
  118. package/dist/chunk-PAORGQRI.js.map +1 -0
  119. package/dist/{chunk-ZJLY4QSU.js → chunk-PMB3WGDL.js} +69 -6
  120. package/dist/chunk-PMB3WGDL.js.map +1 -0
  121. package/dist/{chunk-J3BT33K7.js → chunk-POBPGDWI.js} +5 -5
  122. package/dist/{chunk-QWUUMMIK.js → chunk-POMSFKTB.js} +1351 -76
  123. package/dist/chunk-POMSFKTB.js.map +1 -0
  124. package/dist/{chunk-OTAVQCSF.js → chunk-PYXS46O7.js} +2 -2
  125. package/dist/chunk-QDW3E4RD.js +108 -0
  126. package/dist/chunk-QDW3E4RD.js.map +1 -0
  127. package/dist/{chunk-YNCQ7E4M.js → chunk-QDYXG4CS.js} +4 -3
  128. package/dist/chunk-QDYXG4CS.js.map +1 -0
  129. package/dist/{chunk-XUHI52HK.js → chunk-QKAH5B6E.js} +4 -4
  130. package/dist/{chunk-HLXVTBF3.js → chunk-QNJMBKFK.js} +3 -2
  131. package/dist/chunk-QNJMBKFK.js.map +1 -0
  132. package/dist/chunk-RCICHSHL.js +789 -0
  133. package/dist/chunk-RCICHSHL.js.map +1 -0
  134. package/dist/{chunk-HG2NKWR2.js → chunk-S4LX5EBI.js} +2 -2
  135. package/dist/{chunk-4A24LIM2.js → chunk-S75M5ZRK.js} +2 -2
  136. package/dist/{chunk-QCCCQT3O.js → chunk-TBBDFYXW.js} +2 -2
  137. package/dist/chunk-TBBDFYXW.js.map +1 -0
  138. package/dist/{chunk-U4PV25RD.js → chunk-U2IQTSBY.js} +1 -1
  139. package/dist/chunk-U2IQTSBY.js.map +1 -0
  140. package/dist/chunk-U66YHYC7.js +31 -0
  141. package/dist/chunk-U66YHYC7.js.map +1 -0
  142. package/dist/{chunk-MWGVGUIS.js → chunk-UEYA6UC7.js} +36 -4
  143. package/dist/chunk-UEYA6UC7.js.map +1 -0
  144. package/dist/{chunk-MDDAA2AO.js → chunk-UPMD5XND.js} +2 -2
  145. package/dist/{chunk-M5KEYE5E.js → chunk-URB2WSKZ.js} +2 -2
  146. package/dist/chunk-UVJFDP7P.js +202 -0
  147. package/dist/chunk-UVJFDP7P.js.map +1 -0
  148. package/dist/{chunk-QY2BHY5O.js → chunk-V7XCAHIB.js} +265 -25
  149. package/dist/chunk-V7XCAHIB.js.map +1 -0
  150. package/dist/chunk-W6SL7OFG.js +180 -0
  151. package/dist/chunk-W6SL7OFG.js.map +1 -0
  152. package/dist/{chunk-QDOSNLB4.js → chunk-X4WESCKA.js} +17 -15
  153. package/dist/chunk-X4WESCKA.js.map +1 -0
  154. package/dist/{chunk-OTFNI3OO.js → chunk-XMGSSBFX.js} +1738 -383
  155. package/dist/chunk-XMGSSBFX.js.map +1 -0
  156. package/dist/chunk-YDBIWGNI.js +298 -0
  157. package/dist/chunk-YDBIWGNI.js.map +1 -0
  158. package/dist/chunk-YFYL2SIJ.js +7857 -0
  159. package/dist/chunk-YFYL2SIJ.js.map +1 -0
  160. package/dist/chunking.js +1 -1
  161. package/dist/citations.d.ts +67 -0
  162. package/dist/citations.js +13 -0
  163. package/dist/citations.js.map +1 -0
  164. package/dist/cli-DwIBnp2g.d.ts +1240 -0
  165. package/dist/cli.d.ts +31 -1147
  166. package/dist/cli.js +149 -7092
  167. package/dist/cli.js.map +1 -1
  168. package/dist/codex-materialize-CQlLTzke.d.ts +139 -0
  169. package/dist/codex-thread-key.d.ts +3 -0
  170. package/dist/codex-thread-key.js +7 -0
  171. package/dist/codex-thread-key.js.map +1 -0
  172. package/dist/config.js +3 -2
  173. package/dist/connectors/codex/instructions.md +160 -0
  174. package/dist/connectors/codex/resources/namespace-cheatsheet.md +48 -0
  175. package/dist/day-summary.d.ts +7 -2
  176. package/dist/day-summary.js +5 -2
  177. package/dist/embedding-fallback.d.ts +96 -2
  178. package/dist/embedding-fallback.js +6 -4
  179. package/dist/{engine-2A6J4XEX.js → engine-X7X3AAG3.js} +10 -7
  180. package/dist/engine-X7X3AAG3.js.map +1 -0
  181. package/dist/entity-retrieval.d.ts +3 -2
  182. package/dist/entity-retrieval.js +10 -7
  183. package/dist/entity-schema.d.ts +11 -0
  184. package/dist/entity-schema.js +19 -0
  185. package/dist/entity-schema.js.map +1 -0
  186. package/dist/explicit-capture.d.ts +6 -3
  187. package/dist/explicit-capture.js +2 -2
  188. package/dist/extraction-judge.d.ts +66 -0
  189. package/dist/extraction-judge.js +18 -0
  190. package/dist/extraction-judge.js.map +1 -0
  191. package/dist/extraction.d.ts +1 -0
  192. package/dist/extraction.js +12 -10
  193. package/dist/fallback-llm.js +4 -4
  194. package/dist/graph.js +1 -1
  195. package/dist/importance.d.ts +11 -1
  196. package/dist/importance.js +3 -1
  197. package/dist/index.d.ts +1140 -8
  198. package/dist/index.js +3350 -333
  199. package/dist/index.js.map +1 -1
  200. package/dist/intent.d.ts +2 -1
  201. package/dist/intent.js +3 -1
  202. package/dist/lifecycle.js +1 -1
  203. package/dist/local-llm.js +2 -2
  204. package/dist/logger.d.ts +1 -1
  205. package/dist/logger.js +1 -1
  206. package/dist/memory-cache.d.ts +2 -2
  207. package/dist/memory-cache.js +1 -1
  208. package/dist/{memory-projection-store-NxMkbocT.d.ts → memory-projection-store-DeSXPh1j.d.ts} +1 -1
  209. package/dist/memory-projection-store.d.ts +1 -1
  210. package/dist/model-registry.js +2 -2
  211. package/dist/models-json.js +2 -2
  212. package/dist/native-knowledge.js +2 -2
  213. package/dist/negative.js +2 -2
  214. package/dist/operator-toolkit.js +20 -16
  215. package/dist/{orchestrator-zTa-Qo-1.d.ts → orchestrator-B9kwlCep.d.ts} +252 -7
  216. package/dist/orchestrator.d.ts +6 -3
  217. package/dist/orchestrator.js +70 -58
  218. package/dist/page-versioning.d.ts +77 -0
  219. package/dist/page-versioning.js +15 -0
  220. package/dist/page-versioning.js.map +1 -0
  221. package/dist/plugin-id.d.ts +37 -0
  222. package/dist/plugin-id.js +11 -0
  223. package/dist/plugin-id.js.map +1 -0
  224. package/dist/policy-runtime.js +2 -2
  225. package/dist/profiling.js +2 -2
  226. package/dist/qmd.d.ts +5 -2
  227. package/dist/qmd.js +3 -3
  228. package/dist/recall-audit.d.ts +20 -0
  229. package/dist/recall-audit.js +50 -0
  230. package/dist/recall-audit.js.map +1 -0
  231. package/dist/recall-mmr.d.ts +152 -0
  232. package/dist/recall-mmr.js +17 -0
  233. package/dist/recall-mmr.js.map +1 -0
  234. package/dist/recall-qos.js +2 -2
  235. package/dist/recall-state.js +2 -2
  236. package/dist/relevance.js +2 -2
  237. package/dist/resolve-provider-secret.js +2 -2
  238. package/dist/resume-bundles.js +5 -4
  239. package/dist/retrieval-agents.js +2 -2
  240. package/dist/retrieval.js +2 -2
  241. package/dist/schemas.d.ts +398 -40
  242. package/dist/schemas.js +3 -1
  243. package/dist/sdk-compat.d.ts +2 -0
  244. package/dist/sdk-compat.js +6 -3
  245. package/dist/sdk-compat.js.map +1 -1
  246. package/dist/semantic-chunking.d.ts +87 -0
  247. package/dist/semantic-chunking.js +20 -0
  248. package/dist/semantic-chunking.js.map +1 -0
  249. package/dist/semantic-consolidation-DrvSYRdB.d.ts +119 -0
  250. package/dist/semantic-consolidation.d.ts +4 -42
  251. package/dist/semantic-consolidation.js +23 -2
  252. package/dist/semantic-rule-promotion.js +9 -6
  253. package/dist/semantic-rule-verifier.js +10 -7
  254. package/dist/session-observer-state.js +2 -2
  255. package/dist/session-toggles.d.ts +22 -0
  256. package/dist/session-toggles.js +116 -0
  257. package/dist/session-toggles.js.map +1 -0
  258. package/dist/skills-registry.d.ts +47 -0
  259. package/dist/skills-registry.js +48 -0
  260. package/dist/skills-registry.js.map +1 -0
  261. package/dist/source-attribution.d.ts +169 -0
  262. package/dist/source-attribution.js +27 -0
  263. package/dist/source-attribution.js.map +1 -0
  264. package/dist/storage.d.ts +171 -10
  265. package/dist/storage.js +16 -5
  266. package/dist/summarizer.js +7 -7
  267. package/dist/temporal-supersession.d.ts +127 -0
  268. package/dist/temporal-supersession.js +20 -0
  269. package/dist/temporal-supersession.js.map +1 -0
  270. package/dist/threading.js +2 -2
  271. package/dist/tier-migration.d.ts +2 -1
  272. package/dist/tier-routing.js +2 -2
  273. package/dist/tokens.d.ts +21 -1
  274. package/dist/tokens.js +5 -1
  275. package/dist/transcript.js +2 -2
  276. package/dist/types.d.ts +497 -3
  277. package/dist/types.js +1 -1
  278. package/dist/utility-learner.js +2 -2
  279. package/dist/utility-runtime.js +3 -3
  280. package/dist/verified-recall.js +11 -8
  281. package/dist/whitespace.d.ts +4 -0
  282. package/dist/whitespace.js +9 -0
  283. package/dist/whitespace.js.map +1 -0
  284. package/package.json +14 -8
  285. package/dist/chunk-2CJCWDMR.js +0 -87
  286. package/dist/chunk-2CJCWDMR.js.map +0 -1
  287. package/dist/chunk-2PO5ZRKV.js.map +0 -1
  288. package/dist/chunk-6UJQNRIO.js.map +0 -1
  289. package/dist/chunk-B7LOFDVE.js.map +0 -1
  290. package/dist/chunk-BDFZXRSO.js.map +0 -1
  291. package/dist/chunk-CXWFUJR2.js.map +0 -1
  292. package/dist/chunk-DORBM6OB.js +0 -81
  293. package/dist/chunk-DORBM6OB.js.map +0 -1
  294. package/dist/chunk-ESSMF2FR.js.map +0 -1
  295. package/dist/chunk-HLBYLYRD.js.map +0 -1
  296. package/dist/chunk-HLXVTBF3.js.map +0 -1
  297. package/dist/chunk-ISY75RLM.js.map +0 -1
  298. package/dist/chunk-KL4CP4SB.js.map +0 -1
  299. package/dist/chunk-KWBU5S5U.js.map +0 -1
  300. package/dist/chunk-MWGVGUIS.js.map +0 -1
  301. package/dist/chunk-ORZMT74A.js.map +0 -1
  302. package/dist/chunk-OTFNI3OO.js.map +0 -1
  303. package/dist/chunk-PGK3VUHN.js.map +0 -1
  304. package/dist/chunk-QCCCQT3O.js.map +0 -1
  305. package/dist/chunk-QDOSNLB4.js.map +0 -1
  306. package/dist/chunk-QPKFPHOO.js +0 -178
  307. package/dist/chunk-QPKFPHOO.js.map +0 -1
  308. package/dist/chunk-QWUUMMIK.js.map +0 -1
  309. package/dist/chunk-QY2BHY5O.js.map +0 -1
  310. package/dist/chunk-TVVVQQAK.js.map +0 -1
  311. package/dist/chunk-U4PV25RD.js.map +0 -1
  312. package/dist/chunk-UYSKNO6E.js.map +0 -1
  313. package/dist/chunk-V4YC4LUK.js.map +0 -1
  314. package/dist/chunk-WWIQTB2Y.js.map +0 -1
  315. package/dist/chunk-YNCQ7E4M.js.map +0 -1
  316. package/dist/chunk-ZJLY4QSU.js.map +0 -1
  317. /package/dist/{engine-2A6J4XEX.js.map → active-memory-bridge.js.map} +0 -0
  318. /package/dist/{chunk-NTTLPF7F.js.map → chunk-3QFQGRHO.js.map} +0 -0
  319. /package/dist/{chunk-G3AG3KZN.js.map → chunk-5IZL4DCV.js.map} +0 -0
  320. /package/dist/{chunk-BRK4ODMI.js.map → chunk-5NPGSAVB.js.map} +0 -0
  321. /package/dist/{chunk-L5RPWGFK.js.map → chunk-7DHTMOND.js.map} +0 -0
  322. /package/dist/{chunk-Q6FETXJA.js.map → chunk-7SEAZFFB.js.map} +0 -0
  323. /package/dist/{chunk-QANCTXQF.js.map → chunk-AYPYCLR7.js.map} +0 -0
  324. /package/dist/{chunk-LP47L3ZX.js.map → chunk-BTY5RRRF.js.map} +0 -0
  325. /package/dist/{chunk-SCHEKPYH.js.map → chunk-C2EFFULQ.js.map} +0 -0
  326. /package/dist/{chunk-GJR6D6KC.js.map → chunk-D654IBA6.js.map} +0 -0
  327. /package/dist/{chunk-UV2FO7J4.js.map → chunk-E6K4NIEU.js.map} +0 -0
  328. /package/dist/{chunk-T4WRIV2C.js.map → chunk-EABGC2TL.js.map} +0 -0
  329. /package/dist/{chunk-ONRU4L2N.js.map → chunk-FEMOX5AD.js.map} +0 -0
  330. /package/dist/{chunk-IFFFR3MR.js.map → chunk-FSFEQI74.js.map} +0 -0
  331. /package/dist/{chunk-UIYZ5T3I.js.map → chunk-GJQPH5G3.js.map} +0 -0
  332. /package/dist/{chunk-ZKYI7UVO.js.map → chunk-JR4ZC3G4.js.map} +0 -0
  333. /package/dist/{chunk-UCYSTFZR.js.map → chunk-JRNQ3RNA.js.map} +0 -0
  334. /package/dist/{chunk-GPGBSNKM.js.map → chunk-K4FLSOR5.js.map} +0 -0
  335. /package/dist/{chunk-M5ZBBBJI.js.map → chunk-KEG4GNGI.js.map} +0 -0
  336. /package/dist/{chunk-L7WO3MZ4.js.map → chunk-KWP7T3DP.js.map} +0 -0
  337. /package/dist/{chunk-J47FNDR7.js.map → chunk-MYQWXITD.js.map} +0 -0
  338. /package/dist/{chunk-YNI4S5WT.js.map → chunk-N53K2EXC.js.map} +0 -0
  339. /package/dist/{chunk-763GUIOU.js.map → chunk-NBNN5GOB.js.map} +0 -0
  340. /package/dist/{chunk-OOSWAUYB.js.map → chunk-ODWDQNRE.js.map} +0 -0
  341. /package/dist/{chunk-J3BT33K7.js.map → chunk-POBPGDWI.js.map} +0 -0
  342. /package/dist/{chunk-OTAVQCSF.js.map → chunk-PYXS46O7.js.map} +0 -0
  343. /package/dist/{chunk-XUHI52HK.js.map → chunk-QKAH5B6E.js.map} +0 -0
  344. /package/dist/{chunk-HG2NKWR2.js.map → chunk-S4LX5EBI.js.map} +0 -0
  345. /package/dist/{chunk-4A24LIM2.js.map → chunk-S75M5ZRK.js.map} +0 -0
  346. /package/dist/{chunk-MDDAA2AO.js.map → chunk-UPMD5XND.js.map} +0 -0
  347. /package/dist/{chunk-M5KEYE5E.js.map → chunk-URB2WSKZ.js.map} +0 -0
@@ -0,0 +1,245 @@
1
+ // src/page-versioning.ts
2
+ import { createHash } from "crypto";
3
+ import path from "path";
4
+ import {
5
+ access,
6
+ mkdir,
7
+ readFile,
8
+ writeFile,
9
+ unlink
10
+ } from "fs/promises";
11
+ var NOOP_LOGGER = {
12
+ debug: () => {
13
+ },
14
+ warn: () => {
15
+ }
16
+ };
17
+ var writeLocks = /* @__PURE__ */ new Map();
18
+ function withPageLock(pageKey, fn) {
19
+ const prev = writeLocks.get(pageKey) ?? Promise.resolve();
20
+ const next = prev.then(fn, fn);
21
+ writeLocks.set(pageKey, next.then(() => {
22
+ }, () => {
23
+ }));
24
+ return next;
25
+ }
26
+ function contentHash(content) {
27
+ return createHash("sha256").update(content, "utf-8").digest("hex");
28
+ }
29
+ function sidecarKey(pagePath) {
30
+ const withoutExt = pagePath.replace(/\.md$/i, "");
31
+ return withoutExt.replace(/[\\/]/g, "__");
32
+ }
33
+ function sidecarDir(memoryDir, sidecar, pagePath) {
34
+ return path.join(memoryDir, sidecar, sidecarKey(pagePath));
35
+ }
36
+ function manifestPath(memoryDir, sidecar, pagePath) {
37
+ return path.join(sidecarDir(memoryDir, sidecar, pagePath), "manifest.json");
38
+ }
39
+ async function fileExists(p) {
40
+ try {
41
+ await access(p);
42
+ return true;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+ async function readManifest(memoryDir, sidecar, pagePath) {
48
+ const mp = manifestPath(memoryDir, sidecar, pagePath);
49
+ try {
50
+ const raw = await readFile(mp, "utf-8");
51
+ const parsed = JSON.parse(raw);
52
+ if (typeof parsed !== "object" || parsed === null) {
53
+ return { pagePath, versions: [], currentVersion: "0" };
54
+ }
55
+ const obj = parsed;
56
+ const versions = Array.isArray(obj.versions) ? obj.versions : [];
57
+ const currentVersion = typeof obj.currentVersion === "string" ? obj.currentVersion : "0";
58
+ return { pagePath: typeof obj.pagePath === "string" ? obj.pagePath : pagePath, versions, currentVersion };
59
+ } catch {
60
+ return { pagePath, versions: [], currentVersion: "0" };
61
+ }
62
+ }
63
+ async function writeManifest(memoryDir, sidecar, pagePath, history) {
64
+ const dir = sidecarDir(memoryDir, sidecar, pagePath);
65
+ await mkdir(dir, { recursive: true });
66
+ const mp = manifestPath(memoryDir, sidecar, pagePath);
67
+ await writeFile(mp, JSON.stringify(history, null, 2) + "\n", "utf-8");
68
+ }
69
+ async function createVersion(pagePath, content, trigger, config, log = NOOP_LOGGER, note, memoryDir) {
70
+ const { sidecarDir: sidecar, maxVersionsPerPage } = config;
71
+ const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);
72
+ const mPath = manifestPath(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));
73
+ return withPageLock(mPath, async () => {
74
+ const history = await readManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));
75
+ const nextId = String(history.versions.length > 0 ? Math.max(...history.versions.map((v) => Number(v.versionId))) + 1 : 1);
76
+ const hash = contentHash(content);
77
+ const version = {
78
+ versionId: nextId,
79
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
80
+ contentHash: hash,
81
+ sizeBytes: Buffer.byteLength(content, "utf-8"),
82
+ trigger,
83
+ ...note !== void 0 ? { note } : {}
84
+ };
85
+ const dir = sidecarDir(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));
86
+ await mkdir(dir, { recursive: true });
87
+ const ext = path.extname(pagePath) || ".md";
88
+ const snapshotPath = path.join(dir, `${nextId}${ext}`);
89
+ await writeFile(snapshotPath, content, "utf-8");
90
+ history.versions.push(version);
91
+ history.currentVersion = nextId;
92
+ if (maxVersionsPerPage > 0 && history.versions.length > maxVersionsPerPage) {
93
+ const toRemove = history.versions.splice(0, history.versions.length - maxVersionsPerPage);
94
+ for (const old of toRemove) {
95
+ const oldPath = path.join(dir, `${old.versionId}${ext}`);
96
+ try {
97
+ await unlink(oldPath);
98
+ } catch {
99
+ log.debug(`page-versioning: could not remove old snapshot ${oldPath}`);
100
+ }
101
+ }
102
+ }
103
+ await writeManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir), history);
104
+ log.debug(`page-versioning: created version ${nextId} for ${pagePath} (trigger=${trigger})`);
105
+ return version;
106
+ });
107
+ }
108
+ async function listVersions(pagePath, config, memoryDir) {
109
+ const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);
110
+ const rel = relPath(pagePath, resolvedMemoryDir);
111
+ const history = await readManifest(resolvedMemoryDir, config.sidecarDir, rel);
112
+ history.versions.sort((a, b) => Number(a.versionId) - Number(b.versionId));
113
+ return history;
114
+ }
115
+ async function getVersion(pagePath, versionId, config, memoryDir) {
116
+ const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);
117
+ const rel = relPath(pagePath, resolvedMemoryDir);
118
+ const ext = path.extname(pagePath) || ".md";
119
+ const dir = sidecarDir(resolvedMemoryDir, config.sidecarDir, rel);
120
+ const snapshotPath = path.join(dir, `${versionId}${ext}`);
121
+ if (!await fileExists(snapshotPath)) {
122
+ throw new Error(`Version ${versionId} not found for ${pagePath}`);
123
+ }
124
+ return readFile(snapshotPath, "utf-8");
125
+ }
126
+ async function revertToVersion(pagePath, versionId, config, log = NOOP_LOGGER, memoryDir) {
127
+ const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);
128
+ const targetContent = await getVersion(pagePath, versionId, config, resolvedMemoryDir);
129
+ let currentContent = "";
130
+ try {
131
+ currentContent = await readFile(pagePath, "utf-8");
132
+ } catch {
133
+ }
134
+ const version = await createVersion(
135
+ pagePath,
136
+ currentContent,
137
+ "revert",
138
+ config,
139
+ log,
140
+ `reverted to version ${versionId}`,
141
+ resolvedMemoryDir
142
+ );
143
+ await writeFile(pagePath, targetContent, "utf-8");
144
+ log.debug(`page-versioning: reverted ${pagePath} to version ${versionId}`);
145
+ return version;
146
+ }
147
+ async function diffVersions(pagePath, v1, v2, config, memoryDir) {
148
+ const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);
149
+ const content1 = await getVersion(pagePath, v1, config, resolvedMemoryDir);
150
+ const content2 = await getVersion(pagePath, v2, config, resolvedMemoryDir);
151
+ const lines1 = content1.split("\n");
152
+ const lines2 = content2.split("\n");
153
+ const result = [];
154
+ result.push(`--- version ${v1}`);
155
+ result.push(`+++ version ${v2}`);
156
+ const lcs = computeLCS(lines1, lines2);
157
+ let i = 0;
158
+ let j = 0;
159
+ let k = 0;
160
+ while (k < lcs.length) {
161
+ while (i < lines1.length && lines1[i] !== lcs[k]) {
162
+ result.push(`-${lines1[i]}`);
163
+ i++;
164
+ }
165
+ while (j < lines2.length && lines2[j] !== lcs[k]) {
166
+ result.push(`+${lines2[j]}`);
167
+ j++;
168
+ }
169
+ result.push(` ${lcs[k]}`);
170
+ i++;
171
+ j++;
172
+ k++;
173
+ }
174
+ while (i < lines1.length) {
175
+ result.push(`-${lines1[i]}`);
176
+ i++;
177
+ }
178
+ while (j < lines2.length) {
179
+ result.push(`+${lines2[j]}`);
180
+ j++;
181
+ }
182
+ return result.join("\n");
183
+ }
184
+ function computeLCS(a, b) {
185
+ const m = a.length;
186
+ const n = b.length;
187
+ const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
188
+ for (let i2 = 1; i2 <= m; i2++) {
189
+ for (let j2 = 1; j2 <= n; j2++) {
190
+ if (a[i2 - 1] === b[j2 - 1]) {
191
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
192
+ } else {
193
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
194
+ }
195
+ }
196
+ }
197
+ const result = [];
198
+ let i = m;
199
+ let j = n;
200
+ while (i > 0 && j > 0) {
201
+ if (a[i - 1] === b[j - 1]) {
202
+ result.unshift(a[i - 1]);
203
+ i--;
204
+ j--;
205
+ } else if (dp[i - 1][j] > dp[i][j - 1]) {
206
+ i--;
207
+ } else {
208
+ j--;
209
+ }
210
+ }
211
+ return result;
212
+ }
213
+ function resolveMemoryDir(pagePath) {
214
+ const knownSubdirs = /* @__PURE__ */ new Set([
215
+ "facts",
216
+ "corrections",
217
+ "entities",
218
+ "state",
219
+ "artifacts",
220
+ "questions",
221
+ "profiles"
222
+ ]);
223
+ let dir = path.dirname(pagePath);
224
+ for (let depth = 0; depth < 5; depth++) {
225
+ const base = path.basename(dir);
226
+ if (knownSubdirs.has(base) || /^\d{4}-\d{2}-\d{2}$/.test(base)) {
227
+ dir = path.dirname(dir);
228
+ } else {
229
+ break;
230
+ }
231
+ }
232
+ return dir;
233
+ }
234
+ function relPath(pagePath, memoryDir) {
235
+ return path.relative(memoryDir, pagePath);
236
+ }
237
+
238
+ export {
239
+ createVersion,
240
+ listVersions,
241
+ getVersion,
242
+ revertToVersion,
243
+ diffVersions
244
+ };
245
+ //# sourceMappingURL=chunk-6ZH4TU6I.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/page-versioning.ts"],"sourcesContent":["/**\n * Page-level versioning with history and revert (issue #371).\n *\n * Provides snapshot-based versioning for memory files using a sidecar\n * directory layout. Each memory page gets a `.versions/<pageName>/`\n * subdirectory containing numbered snapshots and a `manifest.json` that\n * records the version history.\n *\n * Storage layout:\n * memoryDir/\n * facts/preferences.md <- current file\n * .versions/\n * facts__preferences/\n * manifest.json <- VersionHistory\n * 1.md <- version 1 snapshot\n * 2.md <- version 2 snapshot\n */\n\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n access,\n mkdir,\n readFile,\n writeFile,\n unlink,\n} from \"node:fs/promises\";\n\n// ---------------------------------------------------------------------------\n// Public interfaces\n// ---------------------------------------------------------------------------\n\nexport interface PageVersion {\n versionId: string;\n timestamp: string;\n contentHash: string;\n sizeBytes: number;\n trigger: VersionTrigger;\n note?: string;\n}\n\nexport type VersionTrigger = \"write\" | \"consolidation\" | \"revert\" | \"manual\";\n\nexport interface VersionHistory {\n pagePath: string;\n versions: PageVersion[];\n currentVersion: string;\n}\n\nexport interface VersioningConfig {\n enabled: boolean;\n maxVersionsPerPage: number;\n sidecarDir: string;\n}\n\n// ---------------------------------------------------------------------------\n// Logger interface (minimal, avoids coupling to the host logger)\n// ---------------------------------------------------------------------------\n\nexport interface VersioningLogger {\n debug(msg: string): void;\n warn(msg: string): void;\n}\n\nconst NOOP_LOGGER: VersioningLogger = {\n debug: () => {},\n warn: () => {},\n};\n\n// ---------------------------------------------------------------------------\n// Per-page write lock (promise-chain pattern, see gotcha #40)\n// ---------------------------------------------------------------------------\n\nconst writeLocks = new Map<string, Promise<void>>();\n\nfunction withPageLock<T>(pageKey: string, fn: () => Promise<T>): Promise<T> {\n const prev = writeLocks.get(pageKey) ?? Promise.resolve();\n const next = prev.then(fn, fn); // run fn after previous completes, even if previous failed\n writeLocks.set(pageKey, next.then(() => {}, () => {})); // recover chain per gotcha #40\n return next;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction contentHash(content: string): string {\n return createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\n/**\n * Derive a filesystem-safe sidecar key from a page path relative to memoryDir.\n *\n * `facts/2026-01-15/pref-001.md` -> `facts__2026-01-15__pref-001`\n */\nfunction sidecarKey(pagePath: string): string {\n const withoutExt = pagePath.replace(/\\.md$/i, \"\");\n return withoutExt.replace(/[\\\\/]/g, \"__\");\n}\n\nfunction sidecarDir(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(memoryDir, sidecar, sidecarKey(pagePath));\n}\n\nfunction manifestPath(memoryDir: string, sidecar: string, pagePath: string): string {\n return path.join(sidecarDir(memoryDir, sidecar, pagePath), \"manifest.json\");\n}\n\nasync function fileExists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function readManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n): Promise<VersionHistory> {\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n try {\n const raw = await readFile(mp, \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) {\n return { pagePath, versions: [], currentVersion: \"0\" };\n }\n const obj = parsed as Record<string, unknown>;\n const versions = Array.isArray(obj.versions) ? (obj.versions as PageVersion[]) : [];\n const currentVersion = typeof obj.currentVersion === \"string\" ? obj.currentVersion : \"0\";\n return { pagePath: typeof obj.pagePath === \"string\" ? obj.pagePath : pagePath, versions, currentVersion };\n } catch {\n return { pagePath, versions: [], currentVersion: \"0\" };\n }\n}\n\nasync function writeManifest(\n memoryDir: string,\n sidecar: string,\n pagePath: string,\n history: VersionHistory,\n): Promise<void> {\n const dir = sidecarDir(memoryDir, sidecar, pagePath);\n await mkdir(dir, { recursive: true });\n const mp = manifestPath(memoryDir, sidecar, pagePath);\n await writeFile(mp, JSON.stringify(history, null, 2) + \"\\n\", \"utf-8\");\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Create a new version snapshot for a page.\n *\n * Call this BEFORE overwriting the current file so the previous content is\n * preserved. If the file does not exist yet (first write), the provided\n * `content` is snapshotted as version 1.\n *\n * Pruning: when the number of versions exceeds `config.maxVersionsPerPage`,\n * the oldest snapshots (and their files) are removed.\n */\nexport async function createVersion(\n pagePath: string,\n content: string,\n trigger: VersionTrigger,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n note?: string,\n memoryDir?: string,\n): Promise<PageVersion> {\n const { sidecarDir: sidecar, maxVersionsPerPage } = config;\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const mPath = manifestPath(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n\n return withPageLock(mPath, async () => {\n const history = await readManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n const nextId = String(history.versions.length > 0\n ? Math.max(...history.versions.map((v) => Number(v.versionId))) + 1\n : 1);\n\n const hash = contentHash(content);\n const version: PageVersion = {\n versionId: nextId,\n timestamp: new Date().toISOString(),\n contentHash: hash,\n sizeBytes: Buffer.byteLength(content, \"utf-8\"),\n trigger,\n ...(note !== undefined ? { note } : {}),\n };\n\n // Write snapshot file\n const dir = sidecarDir(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir));\n await mkdir(dir, { recursive: true });\n const ext = path.extname(pagePath) || \".md\";\n const snapshotPath = path.join(dir, `${nextId}${ext}`);\n await writeFile(snapshotPath, content, \"utf-8\");\n\n history.versions.push(version);\n history.currentVersion = nextId;\n\n // Prune old versions if exceeding max\n if (maxVersionsPerPage > 0 && history.versions.length > maxVersionsPerPage) {\n const toRemove = history.versions.splice(0, history.versions.length - maxVersionsPerPage);\n for (const old of toRemove) {\n const oldPath = path.join(dir, `${old.versionId}${ext}`);\n try {\n await unlink(oldPath);\n } catch {\n log.debug(`page-versioning: could not remove old snapshot ${oldPath}`);\n }\n }\n }\n\n await writeManifest(resolvedMemoryDir, sidecar, relPath(pagePath, resolvedMemoryDir), history);\n log.debug(`page-versioning: created version ${nextId} for ${pagePath} (trigger=${trigger})`);\n\n return version;\n });\n}\n\n/**\n * List all versions for a page.\n */\nexport async function listVersions(\n pagePath: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<VersionHistory> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const history = await readManifest(resolvedMemoryDir, config.sidecarDir, rel);\n // Sort ascending by versionId (numeric)\n history.versions.sort((a, b) => Number(a.versionId) - Number(b.versionId));\n return history;\n}\n\n/**\n * Read the content of a specific version.\n */\nexport async function getVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const rel = relPath(pagePath, resolvedMemoryDir);\n const ext = path.extname(pagePath) || \".md\";\n const dir = sidecarDir(resolvedMemoryDir, config.sidecarDir, rel);\n const snapshotPath = path.join(dir, `${versionId}${ext}`);\n\n if (!(await fileExists(snapshotPath))) {\n throw new Error(`Version ${versionId} not found for ${pagePath}`);\n }\n\n return readFile(snapshotPath, \"utf-8\");\n}\n\n/**\n * Revert a page to a previous version.\n *\n * 1. Reads the target version's content.\n * 2. Snapshots the CURRENT content as a new version (trigger: \"revert\").\n * 3. Writes the reverted content to the page file.\n *\n * Returns the newly created version entry for the revert snapshot.\n */\nexport async function revertToVersion(\n pagePath: string,\n versionId: string,\n config: VersioningConfig,\n log: VersioningLogger = NOOP_LOGGER,\n memoryDir?: string,\n): Promise<PageVersion> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n\n // Read target version content\n const targetContent = await getVersion(pagePath, versionId, config, resolvedMemoryDir);\n\n // Snapshot current content before overwriting\n let currentContent = \"\";\n try {\n currentContent = await readFile(pagePath, \"utf-8\");\n } catch {\n // File may not exist; that's okay\n }\n\n const version = await createVersion(\n pagePath,\n currentContent,\n \"revert\",\n config,\n log,\n `reverted to version ${versionId}`,\n resolvedMemoryDir,\n );\n\n // Write the reverted content to the actual page\n await writeFile(pagePath, targetContent, \"utf-8\");\n log.debug(`page-versioning: reverted ${pagePath} to version ${versionId}`);\n\n return version;\n}\n\n/**\n * Simple line-based diff between two versions.\n *\n * Returns a unified-style diff string showing added (+) and removed (-) lines.\n */\nexport async function diffVersions(\n pagePath: string,\n v1: string,\n v2: string,\n config: VersioningConfig,\n memoryDir?: string,\n): Promise<string> {\n const resolvedMemoryDir = memoryDir ?? resolveMemoryDir(pagePath);\n const content1 = await getVersion(pagePath, v1, config, resolvedMemoryDir);\n const content2 = await getVersion(pagePath, v2, config, resolvedMemoryDir);\n\n const lines1 = content1.split(\"\\n\");\n const lines2 = content2.split(\"\\n\");\n\n const result: string[] = [];\n result.push(`--- version ${v1}`);\n result.push(`+++ version ${v2}`);\n\n // Simple LCS-based diff\n const lcs = computeLCS(lines1, lines2);\n let i = 0;\n let j = 0;\n let k = 0;\n\n while (k < lcs.length) {\n // Emit removed lines before the next common line\n while (i < lines1.length && lines1[i] !== lcs[k]) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Emit added lines before the next common line\n while (j < lines2.length && lines2[j] !== lcs[k]) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n // Common line\n result.push(` ${lcs[k]}`);\n i++;\n j++;\n k++;\n }\n // Remaining removed lines\n while (i < lines1.length) {\n result.push(`-${lines1[i]}`);\n i++;\n }\n // Remaining added lines\n while (j < lines2.length) {\n result.push(`+${lines2[j]}`);\n j++;\n }\n\n return result.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// LCS helper for diffVersions\n// ---------------------------------------------------------------------------\n\nfunction computeLCS(a: string[], b: string[]): string[] {\n const m = a.length;\n const n = b.length;\n // Build DP table\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n if (a[i - 1] === b[j - 1]) {\n dp[i][j] = dp[i - 1][j - 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n }\n // Backtrack to build LCS\n const result: string[] = [];\n let i = m;\n let j = n;\n while (i > 0 && j > 0) {\n if (a[i - 1] === b[j - 1]) {\n result.unshift(a[i - 1]);\n i--;\n j--;\n } else if (dp[i - 1][j] > dp[i][j - 1]) {\n i--;\n } else {\n j--;\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Path helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy fallback: given an absolute page path, heuristically resolve the\n * memory directory by walking up past known subdirectory names.\n *\n * Callers should always pass an explicit `memoryDir` instead of relying on\n * this heuristic. It is retained only for backward compatibility when the\n * optional `memoryDir` parameter is omitted.\n */\nfunction resolveMemoryDir(pagePath: string): string {\n const knownSubdirs = new Set([\n \"facts\",\n \"corrections\",\n \"entities\",\n \"state\",\n \"artifacts\",\n \"questions\",\n \"profiles\",\n ]);\n\n let dir = path.dirname(pagePath);\n // Walk up past date directories (YYYY-MM-DD) and known subdirs\n for (let depth = 0; depth < 5; depth++) {\n const base = path.basename(dir);\n if (knownSubdirs.has(base) || /^\\d{4}-\\d{2}-\\d{2}$/.test(base)) {\n dir = path.dirname(dir);\n } else {\n break;\n }\n }\n return dir;\n}\n\n/**\n * Compute relative path of a page within its memory directory.\n */\nfunction relPath(pagePath: string, memoryDir: string): string {\n return path.relative(memoryDir, pagePath);\n}\n"],"mappings":"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","names":["i","j"]}
@@ -1,27 +1,29 @@
1
1
  import {
2
2
  collectNativeKnowledgeChunks
3
- } from "./chunk-Q6FETXJA.js";
3
+ } from "./chunk-7SEAZFFB.js";
4
4
  import {
5
+ compareEntityTimestamps,
5
6
  normalizeEntityName
6
- } from "./chunk-QWUUMMIK.js";
7
+ } from "./chunk-POMSFKTB.js";
7
8
  import {
8
9
  sanitizeMemoryContent
9
10
  } from "./chunk-M62O4P4T.js";
11
+ import {
12
+ normalizeEntityText,
13
+ resolveRequestedEntitySectionKeys
14
+ } from "./chunk-4DJQYKMN.js";
10
15
 
11
16
  // src/entity-retrieval.ts
12
17
  import { createHash } from "crypto";
13
18
  import { mkdir, readFile, writeFile } from "fs/promises";
14
19
  import path from "path";
15
- var ENTITY_INDEX_VERSION = 1;
20
+ var ENTITY_INDEX_VERSION = 3;
16
21
  var RECENT_TRANSCRIPT_LOOKBACK_HOURS = 24;
17
22
  var INSTRUCTION_LIKE_RE = /\b(always|never|must|should|remember to|do not|don't|process|workflow|template|checklist|instruction)\b/i;
18
23
  var METADATA_WRAPPER_RE = /^(source|context|metadata|notes?):/i;
19
24
  var ENTITY_PRONOUN_RE = /\b(he|him|his|she|her|they|them|their|it|its)\b/i;
20
- function normalizeText(value) {
21
- return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
22
- }
23
25
  function tokenize(value) {
24
- return normalizeText(value).split(/\s+/).filter((token) => token.length >= 2);
26
+ return normalizeEntityText(value).split(/\s+/).filter((token) => token.length >= 2);
25
27
  }
26
28
  function uniqueStrings(values) {
27
29
  return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
@@ -36,18 +38,37 @@ function compactLine(value, maxLength = 220) {
36
38
  if (normalized.length <= maxLength) return normalized;
37
39
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}\u2026`;
38
40
  }
41
+ function dedupeHintSnippetsByText(snippets) {
42
+ const seen = /* @__PURE__ */ new Set();
43
+ const result = [];
44
+ for (const snippet of snippets) {
45
+ const key = normalizeEntityText(snippet.text);
46
+ if (seen.has(key)) continue;
47
+ seen.add(key);
48
+ result.push(snippet);
49
+ }
50
+ return result;
51
+ }
39
52
  function relationLine(entry, relationship) {
40
53
  const normalizedLabel = relationship.label.replace(/\s+/g, " ").trim();
41
54
  if (normalizedLabel.length === 0) return `${entry.name} is connected to ${relationship.target}`;
42
55
  return `${entry.name} ${normalizedLabel} ${relationship.target}`;
43
56
  }
44
57
  function detectEntityQueryMode(query) {
45
- const normalized = normalizeText(query);
58
+ const normalized = normalizeEntityText(query);
46
59
  if (!normalized) return null;
47
60
  if (/^(what about|and what about|how about|what happened (with|to) (he|him|his|she|her|they|them|their|it|its)|did (he|she|they|it)|is (he|she|they|it)|was (he|she|they|it))\b/.test(normalized)) {
48
61
  return "follow_up";
49
62
  }
50
- if (/^(who is|who s|what do we know about|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\b/.test(normalized)) {
63
+ if (/^(who is|who s|what do we know about|what does|tell me about|what can you tell me about|what s new with|what happened with|what happened to|status of|where is|how is)\b/.test(normalized)) {
64
+ if (/^what does\b/.test(normalized)) {
65
+ if (/^what does (?:this|that|it|the|a|an|my|our|your|their)\b/.test(normalized)) {
66
+ return null;
67
+ }
68
+ if (/^what does [a-z0-9-]+ (?:error|warning|exception|failure|stack|trace|code|message|log)\b/.test(normalized) && /\b(mean|means|indicate|indicates|imply|implies)\b/.test(normalized)) {
69
+ return null;
70
+ }
71
+ }
51
72
  return /what happened|what s new|status of|how is|where is/.test(normalized) ? "timeline" : "direct";
52
73
  }
53
74
  if (ENTITY_PRONOUN_RE.test(normalized) && normalized.split(/\s+/).length <= 8) {
@@ -56,8 +77,8 @@ function detectEntityQueryMode(query) {
56
77
  return null;
57
78
  }
58
79
  function scoreAliasMatch(query, alias) {
59
- const normalizedQuery = normalizeText(query);
60
- const normalizedAlias = normalizeText(alias);
80
+ const normalizedQuery = normalizeEntityText(query);
81
+ const normalizedAlias = normalizeEntityText(alias);
61
82
  if (!normalizedAlias) return 0;
62
83
  if (normalizedQuery === normalizedAlias) return 10;
63
84
  if (containsPhrase(normalizedQuery, normalizedAlias)) return 8 + Math.min(normalizedAlias.split(/\s+/).length, 3);
@@ -77,6 +98,26 @@ function sanitizeEntityFact(fact) {
77
98
  if (INSTRUCTION_LIKE_RE.test(clean) && clean.length > 100) return "";
78
99
  return clean;
79
100
  }
101
+ function scoreHintSnippet(snippet, queryTokens) {
102
+ const normalized = normalizeEntityText(snippet.text);
103
+ if (!normalized) return null;
104
+ const scored = { ...snippet };
105
+ if (isLikelyInstructionLike(scored.text) && scored.kind !== "summary") {
106
+ scored.score -= 3;
107
+ }
108
+ const overlap = queryTokens.filter((token) => normalized.includes(token)).length;
109
+ scored.score += overlap * 2;
110
+ if (METADATA_WRAPPER_RE.test(scored.text)) scored.score -= 2;
111
+ if (scored.text.length <= 160) scored.score += 1;
112
+ return scored.score > 0 ? scored : null;
113
+ }
114
+ function sortTimelineEntriesDesc(left, right) {
115
+ const timestampOrder = compareEntityTimestamps(right.timestamp, left.timestamp);
116
+ if (timestampOrder !== 0) {
117
+ return timestampOrder;
118
+ }
119
+ return right.text.localeCompare(left.text);
120
+ }
80
121
  function jaccardSimilarity(a, b) {
81
122
  const aTokens = new Set(tokenize(a));
82
123
  const bTokens = new Set(tokenize(b));
@@ -91,7 +132,7 @@ function jaccardSimilarity(a, b) {
91
132
  function buildAliasIndex(entries) {
92
133
  const index = /* @__PURE__ */ new Map();
93
134
  for (const entry of entries) {
94
- const aliases = uniqueStrings([entry.name, ...entry.aliases]).map(normalizeText).filter(Boolean);
135
+ const aliases = uniqueStrings([entry.name, ...entry.aliases]).map(normalizeEntityText).filter(Boolean);
95
136
  for (const alias of aliases) {
96
137
  const existing = index.get(alias) ?? [];
97
138
  existing.push(entry);
@@ -143,6 +184,9 @@ function createPseudoNativeEntry(chunk) {
143
184
  type: chunk.sourceKind,
144
185
  aliases: uniqueStrings(chunk.aliases ?? []),
145
186
  facts: [],
187
+ structuredSections: [],
188
+ timelineFacts: [],
189
+ timeline: [],
146
190
  relationships: [],
147
191
  activity: [],
148
192
  factCount: 0,
@@ -183,13 +227,21 @@ async function buildEntityMentionIndex(storage, config, recallNamespaces) {
183
227
  for (const entity of entityFiles) {
184
228
  const canonicalId = normalizeEntityName(entity.name, entity.type);
185
229
  const sanitizedFacts = entity.facts.map((fact) => sanitizeEntityFact(fact)).filter(Boolean).map((fact) => compactLine(fact, 180));
230
+ const sanitizedTimelineFacts = entity.timeline.map((entry) => sanitizeEntityFact(entry.text)).filter(Boolean).map((fact) => compactLine(fact, 180));
186
231
  entities.set(canonicalId, {
187
232
  canonicalId,
188
233
  name: entity.name,
189
234
  type: entity.type,
190
235
  aliases: uniqueStrings(entity.aliases),
191
- summary: entity.summary,
236
+ summary: entity.synthesis?.trim() || entity.summary?.trim() || void 0,
192
237
  facts: sanitizedFacts,
238
+ timelineFacts: uniqueStrings(sanitizedTimelineFacts),
239
+ structuredSections: (entity.structuredSections ?? []).map((section) => ({
240
+ key: section.key,
241
+ title: section.title,
242
+ facts: section.facts.map((fact) => sanitizeEntityFact(fact)).filter(Boolean).map((fact) => compactLine(fact, 180))
243
+ })).filter((section) => section.facts.length > 0),
244
+ timeline: entity.timeline.map((entry) => ({ ...entry })),
193
245
  relationships: entity.relationships.map((relationship) => ({ ...relationship })),
194
246
  activity: entity.activity.map((activity) => ({ ...activity })),
195
247
  factCount: sanitizedFacts.length,
@@ -214,7 +266,7 @@ async function buildEntityMentionIndex(storage, config, recallNamespaces) {
214
266
  mergeNativeChunk(existingPseudo, chunk);
215
267
  continue;
216
268
  }
217
- const candidateAliases = uniqueStrings([chunk.title, ...chunk.aliases ?? []]).map(normalizeText).filter(Boolean);
269
+ const candidateAliases = uniqueStrings([chunk.title, ...chunk.aliases ?? []]).map(normalizeEntityText).filter(Boolean);
218
270
  let matched = false;
219
271
  for (const alias of candidateAliases) {
220
272
  for (const entry of aliasIndex.get(alias) ?? []) {
@@ -287,60 +339,86 @@ async function readMemorySnippet(memory) {
287
339
  const content = memory.content.replace(/\s+/g, " ").trim();
288
340
  return compactLine(content, 180);
289
341
  }
290
- async function buildHintSnippets(entry, queryTokens, mode, maxSupportingFacts) {
342
+ async function buildHintSnippets(entry, queryTokens, mode, maxSupportingFacts, requestedSectionKeys) {
291
343
  const snippets = [];
344
+ const aliasTokens = new Set(tokenize(uniqueStrings([entry.name, ...entry.aliases]).join(" ")));
292
345
  if (entry.summary) {
293
346
  snippets.push({ text: compactLine(entry.summary, 180), score: 10, kind: "summary" });
294
347
  }
295
- for (const fact of entry.facts) {
296
- snippets.push({ text: fact, score: 7, kind: "fact" });
297
- }
298
- for (const relationship of entry.relationships) {
299
- snippets.push({
300
- text: compactLine(relationLine(entry, relationship), 180),
301
- score: mode === "direct" && entry.type.toLowerCase() === "person" ? 6 : 4,
302
- kind: "relationship"
303
- });
304
- }
305
- for (const activity of entry.activity) {
306
- snippets.push({
307
- text: compactLine(`${activity.date}: ${activity.note}`, 180),
308
- score: 4,
309
- kind: "activity"
310
- });
311
- }
312
- for (const memorySnippet of entry.memorySnippets.slice(0, Math.min(maxSupportingFacts, 4))) {
313
- snippets.push({
314
- text: memorySnippet,
315
- score: 5,
316
- kind: "memory"
317
- });
348
+ if (requestedSectionKeys.size > 0) {
349
+ for (const section of entry.structuredSections) {
350
+ if (!requestedSectionKeys.has(normalizeEntityText(section.key).replace(/\s+/g, "_"))) continue;
351
+ for (const fact of section.facts) {
352
+ snippets.push({ text: fact, score: mode === "direct" ? 8 : 9, kind: "section" });
353
+ }
354
+ }
355
+ } else {
356
+ for (const fact of entry.timelineFacts) {
357
+ snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
358
+ }
359
+ for (const section of entry.structuredSections) {
360
+ for (const fact of section.facts) {
361
+ const normalizedFact = normalizeEntityText(fact);
362
+ const hasNonAliasQueryOverlap = queryTokens.some(
363
+ (token) => !aliasTokens.has(token) && normalizedFact.includes(token)
364
+ );
365
+ if (entry.timelineFacts.length > 0 && !hasNonAliasQueryOverlap) {
366
+ continue;
367
+ }
368
+ snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
369
+ }
370
+ }
371
+ if (entry.timelineFacts.length === 0 && entry.structuredSections.length === 0) {
372
+ for (const fact of entry.facts) {
373
+ if (!fact.trim()) continue;
374
+ snippets.push({ text: fact, score: mode === "direct" ? 6 : 7, kind: "fact" });
375
+ }
376
+ }
318
377
  }
319
- for (const chunk of entry.nativeChunks) {
320
- snippets.push({
321
- text: compactLine(chunk.snippet, 180),
322
- score: 3,
323
- kind: "native"
324
- });
378
+ if (requestedSectionKeys.size === 0) {
379
+ for (const relationship of entry.relationships) {
380
+ snippets.push({
381
+ text: compactLine(relationLine(entry, relationship), 180),
382
+ score: mode === "direct" && entry.type.toLowerCase() === "person" ? 6 : 4,
383
+ kind: "relationship"
384
+ });
385
+ }
386
+ for (const activity of entry.activity) {
387
+ snippets.push({
388
+ text: compactLine(`${activity.date}: ${activity.note}`, 180),
389
+ score: 4,
390
+ kind: "activity"
391
+ });
392
+ }
393
+ for (const memorySnippet of entry.memorySnippets.slice(0, Math.min(maxSupportingFacts, 4))) {
394
+ snippets.push({
395
+ text: memorySnippet,
396
+ score: 5,
397
+ kind: "memory"
398
+ });
399
+ }
400
+ for (const chunk of entry.nativeChunks) {
401
+ snippets.push({
402
+ text: compactLine(chunk.snippet, 180),
403
+ score: 3,
404
+ kind: "native"
405
+ });
406
+ }
325
407
  }
326
408
  const deduped = /* @__PURE__ */ new Map();
327
409
  for (const snippet of snippets) {
328
- const normalized = normalizeText(snippet.text);
329
- if (!normalized) continue;
330
- if (isLikelyInstructionLike(snippet.text) && snippet.kind !== "summary") {
331
- snippet.score -= 3;
332
- }
333
- const overlap = queryTokens.filter((token) => normalizeText(snippet.text).includes(token)).length;
334
- snippet.score += overlap * 2;
335
- if (METADATA_WRAPPER_RE.test(snippet.text)) snippet.score -= 2;
336
- if (snippet.text.length <= 160) snippet.score += 1;
410
+ const scored = scoreHintSnippet(snippet, queryTokens);
411
+ if (!scored) continue;
412
+ const normalized = normalizeEntityText(scored.text);
337
413
  const existing = deduped.get(normalized);
338
- if (!existing || snippet.score > existing.score) deduped.set(normalized, snippet);
414
+ if (!existing || scored.score > existing.score) deduped.set(normalized, scored);
339
415
  }
340
416
  return [...deduped.values()].filter((snippet) => snippet.score > 0).sort((left, right) => right.score - left.score).slice(0, maxSupportingFacts);
341
417
  }
342
418
  function summarizeUncertainty(snippets) {
343
- const direct = snippets.filter((snippet) => snippet.kind === "summary" || snippet.kind === "fact" || snippet.kind === "memory");
419
+ const direct = snippets.filter(
420
+ (snippet) => snippet.kind === "summary" || snippet.kind === "fact" || snippet.kind === "section" || snippet.kind === "memory"
421
+ );
344
422
  if (direct.length < 2) return null;
345
423
  for (let index = 0; index < direct.length; index += 1) {
346
424
  for (let compare = index + 1; compare < direct.length; compare += 1) {
@@ -351,12 +429,36 @@ function summarizeUncertainty(snippets) {
351
429
  }
352
430
  return null;
353
431
  }
354
- function formatEntityHintSection(candidates, mode, maxRelatedEntities, maxChars) {
432
+ function formatEntityHintSection(candidates, queryTokens, mode, maxRelatedEntities, maxChars) {
355
433
  if (candidates.length === 0) return null;
356
434
  const lines = ["## entity_answer_hints", ""];
357
435
  for (const { candidate, snippets, uncertainty } of candidates) {
358
- const topSnippets = snippets.slice(0, 3);
359
- const topSnippetTexts = new Set(topSnippets.map((snippet) => normalizeText(snippet.text)));
436
+ const hasSummary = Boolean(candidate.entry.summary?.trim());
437
+ const preferredTopSnippets = hasSummary ? snippets.filter((snippet) => snippet.kind !== "fact") : snippets;
438
+ let topSnippets = (preferredTopSnippets.length > 0 ? preferredTopSnippets : snippets).slice(0, 3);
439
+ const buildTimelineSnippets = (seedExcludedTexts) => {
440
+ const explicitTimelinePool = dedupeHintSnippetsByText(
441
+ (candidate.entry.timeline ?? []).slice().sort(sortTimelineEntriesDesc).map((entry) => sanitizeEntityFact(entry.text)).filter(Boolean).map((text) => scoreHintSnippet({
442
+ text: compactLine(text, 180),
443
+ score: 7,
444
+ kind: "activity"
445
+ }, queryTokens)).filter((snippet) => snippet !== null).filter((snippet) => !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
446
+ ).slice(0, 2);
447
+ const activityTimelinePool = dedupeHintSnippetsByText(
448
+ snippets.filter((snippet) => (snippet.kind === "activity" || snippet.kind === "memory") && !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
449
+ ).slice(0, 2);
450
+ return explicitTimelinePool.length > 0 ? explicitTimelinePool : activityTimelinePool.length > 0 ? activityTimelinePool : dedupeHintSnippetsByText(
451
+ snippets.filter((snippet) => (snippet.kind === "fact" || snippet.kind === "summary") && !seedExcludedTexts.has(normalizeEntityText(snippet.text)))
452
+ ).slice(0, 2);
453
+ };
454
+ const baseTopSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));
455
+ const timelinePool = mode !== "direct" ? buildTimelineSnippets(baseTopSnippetTexts) : [];
456
+ if (mode !== "direct" && hasSummary && topSnippets.length < 2) {
457
+ if (timelinePool.length > 0) {
458
+ topSnippets = [...topSnippets, timelinePool[0]].slice(0, 3);
459
+ }
460
+ }
461
+ const topSnippetTexts = new Set(topSnippets.map((snippet) => normalizeEntityText(snippet.text)));
360
462
  lines.push(`- target: ${candidate.entry.name} (${candidate.entry.type})`);
361
463
  if (candidate.source === "recent_turn") {
362
464
  lines.push(`- resolution: carried forward from recent turns via alias "${candidate.alias}"`);
@@ -371,8 +473,9 @@ function formatEntityHintSection(candidates, mode, maxRelatedEntities, maxChars)
371
473
  }
372
474
  }
373
475
  if (mode !== "direct") {
374
- const timeline = snippets.filter((snippet) => (snippet.kind === "activity" || snippet.kind === "memory") && !topSnippetTexts.has(normalizeText(snippet.text))).slice(0, 2);
375
- const fallbackTimeline = timeline.length > 0 ? timeline : snippets.filter((snippet) => (snippet.kind === "fact" || snippet.kind === "summary") && !topSnippetTexts.has(normalizeText(snippet.text))).slice(0, 2);
476
+ const fallbackTimeline = timelinePool.filter(
477
+ (snippet) => !topSnippetTexts.has(normalizeEntityText(snippet.text))
478
+ );
376
479
  if (fallbackTimeline.length > 0) {
377
480
  lines.push("- recent timeline:");
378
481
  for (const snippet of fallbackTimeline) {
@@ -409,11 +512,20 @@ async function buildEntityRecallSection(options) {
409
512
  const rankedCandidates = candidates.slice(0, candidateLimit);
410
513
  const enriched = await Promise.all(
411
514
  rankedCandidates.map(async (candidate) => {
515
+ const requestedSectionKeys = new Set(
516
+ resolveRequestedEntitySectionKeys(
517
+ options.query,
518
+ candidate.entry.type,
519
+ candidate.entry.structuredSections,
520
+ options.config.entitySchemas
521
+ )
522
+ );
412
523
  const snippets = await buildHintSnippets(
413
524
  candidate.entry,
414
525
  queryTokens,
415
526
  mode,
416
- options.maxSupportingFacts
527
+ options.maxSupportingFacts,
528
+ requestedSectionKeys
417
529
  );
418
530
  return {
419
531
  candidate,
@@ -422,7 +534,7 @@ async function buildEntityRecallSection(options) {
422
534
  };
423
535
  })
424
536
  );
425
- const section = formatEntityHintSection(enriched, mode, options.maxRelatedEntities, options.maxChars);
537
+ const section = formatEntityHintSection(enriched, queryTokens, mode, options.maxRelatedEntities, options.maxChars);
426
538
  if (!section) return null;
427
539
  return section;
428
540
  }
@@ -441,4 +553,4 @@ export {
441
553
  entityIndexVersion,
442
554
  entityRecentTranscriptLookbackHours
443
555
  };
444
- //# sourceMappingURL=chunk-V4YC4LUK.js.map
556
+ //# sourceMappingURL=chunk-74JR4N5J.js.map