@remnic/core 9.57.5 → 9.58.0

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 (476) hide show
  1. package/dist/access-admin-ops-surface.d.ts +12 -11
  2. package/dist/access-admin-ops-surface.js +25 -24
  3. package/dist/access-authorization-probe.d.ts +12 -11
  4. package/dist/access-authorization-probe.js +26 -25
  5. package/dist/access-boundary.d.ts +12 -11
  6. package/dist/access-boundary.js +25 -24
  7. package/dist/access-cli.js +77 -76
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +12 -11
  11. package/dist/access-extraction-force-flush.js +25 -24
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +12 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +12 -11
  15. package/dist/access-http-offline-stream.d.ts +12 -11
  16. package/dist/access-http-query.js +25 -24
  17. package/dist/access-http.d.ts +13 -12
  18. package/dist/access-http.js +36 -35
  19. package/dist/access-identity-continuity-surface.d.ts +10 -9
  20. package/dist/access-identity-continuity-surface.js +25 -24
  21. package/dist/access-lcm-surface.d.ts +12 -11
  22. package/dist/access-lcm-surface.js +25 -24
  23. package/dist/access-mcp.d.ts +12 -11
  24. package/dist/access-mcp.js +32 -31
  25. package/dist/access-memory-search-fanout.d.ts +2 -2
  26. package/dist/{access-namespace-preflight-Bpt-SYP0.d.ts → access-namespace-preflight-TBXz-8s_.d.ts} +1 -1
  27. package/dist/access-namespace-preflight.d.ts +3 -3
  28. package/dist/access-namespace-preflight.js +25 -24
  29. package/dist/access-observe-write-surface.d.ts +12 -11
  30. package/dist/access-observe-write-surface.js +25 -24
  31. package/dist/access-offline-manifest.d.ts +10 -9
  32. package/dist/access-operations-batch.js +27 -26
  33. package/dist/access-operations.d.ts +15 -14
  34. package/dist/access-operations.js +31 -30
  35. package/dist/access-recall-concurrency.d.ts +12 -11
  36. package/dist/access-recall-concurrency.js +25 -24
  37. package/dist/access-recall-response.d.ts +12 -11
  38. package/dist/access-recall-response.js +25 -24
  39. package/dist/access-recall-surface.d.ts +12 -11
  40. package/dist/access-recall-surface.js +25 -24
  41. package/dist/access-schema.d.ts +88 -88
  42. package/dist/access-schema.js +3 -3
  43. package/dist/{access-service-D9xXmKvd.d.ts → access-service-BQkRul4d.d.ts} +71 -71
  44. package/dist/access-service-helpers.d.ts +12 -11
  45. package/dist/access-service.d.ts +12 -11
  46. package/dist/access-service.js +25 -24
  47. package/dist/access-surface-catalog.d.ts +12 -11
  48. package/dist/access-surface-catalog.js +27 -26
  49. package/dist/access-surface-catalog.js.map +1 -1
  50. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  51. package/dist/action-confidence.d.ts +1 -1
  52. package/dist/active-memory-bridge.d.ts +1 -1
  53. package/dist/active-recall.d.ts +1 -1
  54. package/dist/active-recall.js +1 -1
  55. package/dist/ambient-provenance.d.ts +1 -1
  56. package/dist/artifact-search.d.ts +1 -1
  57. package/dist/behavior-learner.d.ts +1 -1
  58. package/dist/behavior-signals.d.ts +1 -1
  59. package/dist/bootstrap.d.ts +10 -9
  60. package/dist/briefing-window.d.ts +2 -2
  61. package/dist/briefing.d.ts +2 -2
  62. package/dist/briefing.js +10 -10
  63. package/dist/buffer-surprise-report.d.ts +1 -1
  64. package/dist/buffer-surprise.js +4 -3
  65. package/dist/buffer-turn-helpers.d.ts +1 -1
  66. package/dist/buffer.d.ts +2 -2
  67. package/dist/bulk-import/index.d.ts +3 -3
  68. package/dist/calibration.d.ts +1 -1
  69. package/dist/capabilities.d.ts +1 -1
  70. package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-GWVG7LGC.js} +2 -2
  71. package/dist/{catalog-BasnO3Bw.d.ts → catalog-z1UerMbh.d.ts} +1 -1
  72. package/dist/causal-behavior.d.ts +2 -1
  73. package/dist/causal-consolidation.d.ts +1 -1
  74. package/dist/causal-consolidation.js +14 -13
  75. package/dist/causal-consolidation.js.map +1 -1
  76. package/dist/causal-trajectory-graph.d.ts +1 -1
  77. package/dist/{chunk-P4BC54KI.js → chunk-2GBFKHBZ.js} +14 -38
  78. package/dist/chunk-2GBFKHBZ.js.map +1 -0
  79. package/dist/{chunk-YTZA7U6Q.js → chunk-2VHCLHZ5.js} +3 -3
  80. package/dist/{chunk-NEJQ65NV.js → chunk-4CLE2LXB.js} +2 -2
  81. package/dist/{chunk-3VFVQDZO.js → chunk-4IIKJOYM.js} +1 -1
  82. package/dist/{chunk-3VFVQDZO.js.map → chunk-4IIKJOYM.js.map} +1 -1
  83. package/dist/{chunk-JLNBQWZ2.js → chunk-5JMAGU26.js} +7 -6
  84. package/dist/{chunk-JLNBQWZ2.js.map → chunk-5JMAGU26.js.map} +1 -1
  85. package/dist/{chunk-VDX2J7OX.js → chunk-5W7CTZ2E.js} +4 -4
  86. package/dist/{chunk-CZUHNJHX.js → chunk-6C7Q6NG3.js} +13 -13
  87. package/dist/chunk-6TBIWIAG.js +201 -0
  88. package/dist/chunk-6TBIWIAG.js.map +1 -0
  89. package/dist/{chunk-4O6R3GPK.js → chunk-6W2ISYUV.js} +4 -4
  90. package/dist/{chunk-3AJOJOFP.js → chunk-77DAFTUU.js} +3 -3
  91. package/dist/{chunk-IKT6ZVO7.js → chunk-7DHFB5SG.js} +3 -3
  92. package/dist/{chunk-SFR7J2G6.js → chunk-7G34CBKS.js} +2 -2
  93. package/dist/{chunk-IT57AOMC.js → chunk-AH2NX6S7.js} +3 -3
  94. package/dist/{chunk-HYQJQGD3.js → chunk-AM4T6CHX.js} +49 -35
  95. package/dist/chunk-AM4T6CHX.js.map +1 -0
  96. package/dist/{chunk-Z54EM5YZ.js → chunk-B2QHVLJO.js} +60 -30
  97. package/dist/chunk-B2QHVLJO.js.map +1 -0
  98. package/dist/{chunk-FI3PIOOI.js → chunk-B4CSPFYN.js} +8 -8
  99. package/dist/{chunk-7PJARJS4.js → chunk-BPM6UHUL.js} +2 -2
  100. package/dist/{chunk-PPUTUOC3.js → chunk-BTHDQOF4.js} +5 -5
  101. package/dist/{chunk-AW4A4XOP.js → chunk-CZGOLAEW.js} +41 -41
  102. package/dist/{chunk-5PGYCWA7.js → chunk-DE6YCZEE.js} +2 -2
  103. package/dist/{chunk-JOA4Q765.js → chunk-EUYWQ7TS.js} +2 -2
  104. package/dist/{chunk-O5AFC5KM.js → chunk-EWL5DICB.js} +2 -2
  105. package/dist/{chunk-4YZCIK5E.js → chunk-EZXGJJXM.js} +2 -2
  106. package/dist/{chunk-GXIY65UH.js → chunk-FI5EAP4N.js} +2 -2
  107. package/dist/{chunk-YOKSRIFI.js → chunk-FUWS2MNJ.js} +4 -4
  108. package/dist/{chunk-6RK2X7BR.js → chunk-G3JFFUKR.js} +2 -2
  109. package/dist/{chunk-VANZKHTN.js → chunk-G5OB4XZX.js} +4 -4
  110. package/dist/{chunk-66SLUXKM.js → chunk-HK6KYIF6.js} +2 -2
  111. package/dist/{chunk-XBGLEOID.js → chunk-I4BLRM7X.js} +9 -9
  112. package/dist/{chunk-5ZIWRMZM.js → chunk-IVKIODHO.js} +7 -6
  113. package/dist/chunk-IVKIODHO.js.map +1 -0
  114. package/dist/{chunk-6SX4MY5Q.js → chunk-J65AKOD6.js} +2 -2
  115. package/dist/{chunk-BPWZDHFM.js → chunk-J6QIAYNR.js} +2 -2
  116. package/dist/{chunk-XL3TATMJ.js → chunk-JHMAYABJ.js} +4 -4
  117. package/dist/{chunk-F7M36OG2.js → chunk-JNWISMYG.js} +10 -10
  118. package/dist/{chunk-VYIXCMUP.js → chunk-KBIIE57I.js} +3 -3
  119. package/dist/{chunk-QKPDN325.js → chunk-KF75ANST.js} +6 -3
  120. package/dist/chunk-KF75ANST.js.map +1 -0
  121. package/dist/{chunk-24PNX2GF.js → chunk-KXYMU4IN.js} +3 -3
  122. package/dist/{chunk-FKTD7IVS.js → chunk-L3JVAM5Q.js} +2 -2
  123. package/dist/{chunk-5QHDXMXP.js → chunk-LLZKOSGM.js} +1 -1
  124. package/dist/{chunk-5QHDXMXP.js.map → chunk-LLZKOSGM.js.map} +1 -1
  125. package/dist/{chunk-LIF6DO6U.js → chunk-MG7GI4TT.js} +2 -2
  126. package/dist/{chunk-RUZM6Z52.js → chunk-MMZK2DWN.js} +1 -1
  127. package/dist/{chunk-NTJ6TY44.js → chunk-ODAE36PG.js} +3 -3
  128. package/dist/{chunk-QFN4U7AG.js → chunk-ODZKV2F7.js} +3 -3
  129. package/dist/{chunk-QFN4U7AG.js.map → chunk-ODZKV2F7.js.map} +1 -1
  130. package/dist/{chunk-YLHM5BQQ.js → chunk-OLX2HJFW.js} +4 -4
  131. package/dist/{chunk-DNC4A7RS.js → chunk-OU7RWWW6.js} +2 -2
  132. package/dist/{chunk-L3LRWDJW.js → chunk-OV36CROW.js} +3 -3
  133. package/dist/{chunk-BXLOS5AJ.js → chunk-OWHERGF2.js} +2 -2
  134. package/dist/{chunk-CSV34HIW.js → chunk-P5OYNV7B.js} +2 -2
  135. package/dist/{chunk-SNW3YRO6.js → chunk-P6GOYLHN.js} +2 -2
  136. package/dist/{chunk-C5B3CIMJ.js → chunk-PFPNUFKZ.js} +109 -59
  137. package/dist/chunk-PFPNUFKZ.js.map +1 -0
  138. package/dist/{chunk-USGKHF36.js → chunk-QUJC22CT.js} +2 -2
  139. package/dist/{chunk-BVRREV3N.js → chunk-R7IV3EUJ.js} +2 -2
  140. package/dist/{chunk-KSXJOC4F.js → chunk-RDFF2NAU.js} +18 -8
  141. package/dist/chunk-RDFF2NAU.js.map +1 -0
  142. package/dist/{chunk-D4LVHPOA.js → chunk-RXN7Z2V5.js} +3 -3
  143. package/dist/{chunk-7VSHDLJQ.js → chunk-T2VJ2EO5.js} +6 -6
  144. package/dist/chunk-TOTT6S2V.js +20 -0
  145. package/dist/chunk-TOTT6S2V.js.map +1 -0
  146. package/dist/{chunk-U7BMN33M.js → chunk-UBSM6TZP.js} +2 -2
  147. package/dist/{chunk-DQEMWVMT.js → chunk-UVYI6VIX.js} +1 -1
  148. package/dist/{chunk-U7XLOSG2.js → chunk-VIM6QH4D.js} +2 -2
  149. package/dist/{chunk-LJJWFV2Q.js → chunk-VJXSAJFW.js} +2 -2
  150. package/dist/{chunk-HZC3OECF.js → chunk-VOKK4WCG.js} +2 -2
  151. package/dist/{chunk-LTAVSOZW.js → chunk-WVP2I6C5.js} +5 -4
  152. package/dist/chunk-WVP2I6C5.js.map +1 -0
  153. package/dist/{chunk-LRDP2AC2.js → chunk-YBCZTBN2.js} +2 -2
  154. package/dist/{chunk-USAUBGBC.js → chunk-YKZFX2HQ.js} +2 -2
  155. package/dist/{chunk-I2GIYTRU.js → chunk-ZOGOOSB3.js} +2 -2
  156. package/dist/{chunk-PBGWYM3H.js → chunk-ZPUIRTIZ.js} +27 -15
  157. package/dist/chunk-ZPUIRTIZ.js.map +1 -0
  158. package/dist/chunking.d.ts +3 -1
  159. package/dist/chunking.js +8 -3
  160. package/dist/{cli-DTOkYhKI.d.ts → cli-DsyVvOFP.d.ts} +5 -5
  161. package/dist/cli.d.ts +14 -13
  162. package/dist/cli.js +57 -56
  163. package/dist/coding/pre-action-gate.d.ts +1 -1
  164. package/dist/compounding/engine.d.ts +2 -2
  165. package/dist/compounding/engine.js +10 -10
  166. package/dist/compounding/preference-consolidator.d.ts +2 -1
  167. package/dist/compression-optimizer.d.ts +1 -1
  168. package/dist/config.d.ts +1 -1
  169. package/dist/config.js +1 -1
  170. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  171. package/dist/connectors/codex-materialize-runner.js +12 -11
  172. package/dist/connectors/codex-materialize.d.ts +7 -12
  173. package/dist/connectors/codex-materialize.js +2 -1
  174. package/dist/connectors/index.d.ts +1 -1
  175. package/dist/connectors/index.js +12 -11
  176. package/dist/consolidation-provenance-check.d.ts +2 -2
  177. package/dist/consolidation-undo.d.ts +2 -2
  178. package/dist/contradiction/index.d.ts +2 -2
  179. package/dist/contradiction/index.js +4 -4
  180. package/dist/converge-config.d.ts +1 -1
  181. package/dist/convergence-refresh.d.ts +2 -2
  182. package/dist/convergence-refresh.js +12 -12
  183. package/dist/conversation-index/backend.d.ts +1 -1
  184. package/dist/conversation-index/chunker.d.ts +1 -1
  185. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  186. package/dist/conversation-index/indexer.d.ts +1 -1
  187. package/dist/conversation-index/search.d.ts +1 -1
  188. package/dist/corpus-watermark.d.ts +1 -1
  189. package/dist/corpus-watermark.js +12 -12
  190. package/dist/day-summary.d.ts +1 -1
  191. package/dist/day-summary.js +3 -2
  192. package/dist/delinearize.d.ts +1 -1
  193. package/dist/dependency-propagation-config.d.ts +1 -1
  194. package/dist/{dependency-propagation-delivery-C_K_AHcv.d.ts → dependency-propagation-delivery-DdwSc1qh.d.ts} +1 -1
  195. package/dist/direct-answer-wiring.d.ts +1 -1
  196. package/dist/direct-answer.d.ts +1 -1
  197. package/dist/embedding-fallback.d.ts +1 -1
  198. package/dist/enrichment/index.d.ts +1 -1
  199. package/dist/entity-retrieval.d.ts +2 -2
  200. package/dist/entity-retrieval.js +10 -10
  201. package/dist/entity-schema.d.ts +1 -1
  202. package/dist/explicit-capture.d.ts +10 -9
  203. package/dist/external-wiki-access.d.ts +12 -11
  204. package/dist/external-wiki-access.js +26 -25
  205. package/dist/external-wiki-collection-registration.d.ts +1 -1
  206. package/dist/external-wiki-collection.d.ts +1 -1
  207. package/dist/external-wiki-mcp-tools.d.ts +12 -11
  208. package/dist/extraction-error-classification.d.ts +1 -1
  209. package/dist/extraction-faithfulness.d.ts +1 -1
  210. package/dist/extraction-judge-telemetry.d.ts +1 -1
  211. package/dist/extraction-judge-training.d.ts +1 -1
  212. package/dist/extraction-judge.d.ts +1 -1
  213. package/dist/extraction-liveness.d.ts +1 -1
  214. package/dist/extraction-normalization.d.ts +1 -1
  215. package/dist/extraction-prompt.d.ts +1 -1
  216. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  217. package/dist/extraction-source-grounding.d.ts +1 -1
  218. package/dist/extraction.d.ts +1 -1
  219. package/dist/extraction.js +16 -15
  220. package/dist/fallback-llm.d.ts +1 -1
  221. package/dist/graph-dashboard-diff.d.ts +1 -1
  222. package/dist/graph-dashboard-key.d.ts +1 -1
  223. package/dist/graph-dashboard-parser.d.ts +1 -1
  224. package/dist/graph-edge-reinforcement.d.ts +1 -1
  225. package/dist/graph-path-reconstruction.d.ts +1 -1
  226. package/dist/graph-path-scoring.d.ts +1 -1
  227. package/dist/graph-snapshot.d.ts +1 -1
  228. package/dist/graph.d.ts +1 -1
  229. package/dist/harmonic-retrieval.js +1 -1
  230. package/dist/importance.d.ts +1 -1
  231. package/dist/importers/index.d.ts +1 -1
  232. package/dist/in-flight-reads.d.ts +1 -1
  233. package/dist/index.d.ts +698 -697
  234. package/dist/index.js +81 -80
  235. package/dist/intent.d.ts +1 -1
  236. package/dist/lcm/archive.d.ts +3 -2
  237. package/dist/lcm/archive.js +2 -1
  238. package/dist/lcm/engine.d.ts +2 -1
  239. package/dist/lcm/engine.js +5 -4
  240. package/dist/lcm/index.d.ts +2 -1
  241. package/dist/lcm/index.js +7 -6
  242. package/dist/lcm/recall.d.ts +1 -0
  243. package/dist/lcm/summarizer.d.ts +1 -0
  244. package/dist/lcm/summarizer.js +3 -2
  245. package/dist/lcm/tools.d.ts +2 -1
  246. package/dist/lifecycle.d.ts +1 -1
  247. package/dist/live-connectors-runner.d.ts +1 -1
  248. package/dist/local-llm.d.ts +2 -3
  249. package/dist/local-llm.js +2 -1
  250. package/dist/local-model-endpoint.d.ts +1 -1
  251. package/dist/maintenance/memory-governance.d.ts +1 -1
  252. package/dist/maintenance/memory-governance.js +10 -10
  253. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  254. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
  255. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  256. package/dist/maintenance/rebuild-memory-projection.js +11 -11
  257. package/dist/{maintenance-DdP931i9.d.ts → maintenance-DvkiF7fm.d.ts} +3 -3
  258. package/dist/mcp-memory-inspector-app.d.ts +12 -11
  259. package/dist/memory-action-policy.d.ts +1 -1
  260. package/dist/memory-cache.d.ts +1 -1
  261. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  262. package/dist/memory-projection-store.d.ts +1 -1
  263. package/dist/memory-provenance.d.ts +1 -1
  264. package/dist/memory-snapshot.d.ts +1 -1
  265. package/dist/memory-worth-outcomes.d.ts +2 -2
  266. package/dist/models-json.d.ts +1 -1
  267. package/dist/namespaces/migrate.d.ts +3 -3
  268. package/dist/namespaces/migrate.js +11 -11
  269. package/dist/namespaces/principal.d.ts +1 -1
  270. package/dist/namespaces/search.d.ts +1 -1
  271. package/dist/namespaces/search.js +7 -7
  272. package/dist/namespaces/storage.d.ts +3 -3
  273. package/dist/namespaces/storage.js +10 -10
  274. package/dist/native-knowledge.d.ts +1 -1
  275. package/dist/offline-sync-impression-drain.d.ts +1 -1
  276. package/dist/operator-doctor-corpus.d.ts +1 -1
  277. package/dist/operator-doctor-corpus.js +13 -13
  278. package/dist/operator-doctor-replica.d.ts +1 -1
  279. package/dist/operator-toolkit.d.ts +3 -3
  280. package/dist/operator-toolkit.js +18 -18
  281. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  282. package/dist/orchestration/maintenance.d.ts +4 -4
  283. package/dist/orchestration/maintenance.js +15 -15
  284. package/dist/{orchestrator-DxUWX7gs.d.ts → orchestrator-CXPIzs3D.d.ts} +9 -9
  285. package/dist/orchestrator.d.ts +10 -9
  286. package/dist/orchestrator.js +77 -76
  287. package/dist/patterns-cli.d.ts +1 -1
  288. package/dist/{pipeline-BKUMU1vU.d.ts → pipeline-BuYWU9rt.d.ts} +1 -1
  289. package/dist/policy-runtime.d.ts +1 -1
  290. package/dist/proactive-contention.d.ts +1 -1
  291. package/dist/provenance.d.ts +1 -1
  292. package/dist/{public-http-C01DLhAp.d.ts → public-http-m9x1Qyzn.d.ts} +1 -1
  293. package/dist/{qmd-DJP-GLFe.d.ts → qmd-DYnrPw-m.d.ts} +1 -1
  294. package/dist/qmd-preflight.d.ts +2 -2
  295. package/dist/qmd-recall-cache.d.ts +1 -1
  296. package/dist/qmd.d.ts +2 -2
  297. package/dist/recall-concurrency-config.d.ts +1 -1
  298. package/dist/recall-disclosure-escalation.d.ts +1 -1
  299. package/dist/recall-explain-renderer.d.ts +1 -1
  300. package/dist/recall-explain-renderer.js +4 -3
  301. package/dist/recall-memory-map.d.ts +1 -1
  302. package/dist/recall-planner-llm.d.ts +1 -1
  303. package/dist/recall-state.d.ts +1 -1
  304. package/dist/recall-tag-filter.d.ts +1 -1
  305. package/dist/recall-timings.d.ts +1 -1
  306. package/dist/recall-xray-cli.d.ts +1 -1
  307. package/dist/recall-xray-cli.js +5 -4
  308. package/dist/recall-xray-renderer.d.ts +1 -1
  309. package/dist/recall-xray-renderer.js +4 -3
  310. package/dist/recall-xray.d.ts +2 -7
  311. package/dist/recall-xray.js +3 -2
  312. package/dist/reconcile/cursor.d.ts +1 -1
  313. package/dist/reconcile/manifest.d.ts +1 -1
  314. package/dist/reconcile/plan.d.ts +1 -1
  315. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  316. package/dist/replay/normalizers/claude.d.ts +1 -1
  317. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  318. package/dist/replay/normalizers/shared.d.ts +1 -1
  319. package/dist/replay/runner.d.ts +1 -1
  320. package/dist/replay/types.d.ts +1 -1
  321. package/dist/replica-divergence.d.ts +1 -1
  322. package/dist/replica-peers-config.d.ts +1 -1
  323. package/dist/resolve-auth-token.d.ts +1 -1
  324. package/dist/resume-bundles.js +4 -3
  325. package/dist/retrieval-agents.d.ts +2 -2
  326. package/dist/retrieval-tiers.d.ts +1 -1
  327. package/dist/routing/engine.d.ts +1 -1
  328. package/dist/routing/store.d.ts +1 -1
  329. package/dist/salvage-envelope.d.ts +1 -1
  330. package/dist/schemas.d.ts +138 -138
  331. package/dist/{scope-profiles-CaKcnB-6.d.ts → scope-profiles-C1QG4Cmv.d.ts} +1 -1
  332. package/dist/search/embed-helper.d.ts +1 -1
  333. package/dist/search/factory.d.ts +1 -1
  334. package/dist/search/factory.js +6 -6
  335. package/dist/search/index.d.ts +1 -1
  336. package/dist/search/index.js +11 -11
  337. package/dist/search/lancedb-backend.d.ts +1 -1
  338. package/dist/search/lancedb-backend.js +2 -2
  339. package/dist/search/meilisearch-backend.d.ts +1 -1
  340. package/dist/search/meilisearch-backend.js +2 -2
  341. package/dist/search/noop-backend.d.ts +1 -1
  342. package/dist/search/orama-backend.d.ts +1 -1
  343. package/dist/search/orama-backend.js +2 -2
  344. package/dist/search/port.d.ts +1 -1
  345. package/dist/search/remote-backend.d.ts +1 -1
  346. package/dist/semantic-chunking.js +3 -2
  347. package/dist/{semantic-consolidation-P0eMWqh-.d.ts → semantic-consolidation-DMeX8XS0.d.ts} +1 -1
  348. package/dist/semantic-consolidation.d.ts +2 -2
  349. package/dist/semantic-consolidation.js +14 -13
  350. package/dist/semantic-rule-promotion.js +10 -10
  351. package/dist/semantic-rule-verifier.d.ts +1 -1
  352. package/dist/semantic-rule-verifier.js +10 -10
  353. package/dist/{service-D5GQLxq_.d.ts → service-CT3ENiTO.d.ts} +2 -2
  354. package/dist/session-observer-bands.d.ts +1 -1
  355. package/dist/session-observer-state.d.ts +1 -1
  356. package/dist/session-observer-state.js +1 -1
  357. package/dist/shared-context/manager.d.ts +9 -9
  358. package/dist/signal.d.ts +1 -1
  359. package/dist/source-agent-qualifier.d.ts +1 -1
  360. package/dist/source-agent-qualifier.js +12 -11
  361. package/dist/{storage-DIyil2ll.d.ts → storage-B0L76y7N.d.ts} +1 -1
  362. package/dist/storage.d.ts +2 -2
  363. package/dist/storage.js +9 -9
  364. package/dist/summarizer.d.ts +1 -1
  365. package/dist/summarizer.js +3 -2
  366. package/dist/summary-snapshot.d.ts +1 -1
  367. package/dist/support-passport/index.d.ts +15 -14
  368. package/dist/support-passport/index.js +28 -27
  369. package/dist/temporal-supersession.d.ts +2 -2
  370. package/dist/temporal-timeline-recall.d.ts +1 -1
  371. package/dist/temporal-validity.d.ts +1 -1
  372. package/dist/threading.d.ts +1 -1
  373. package/dist/tier-migration.d.ts +2 -2
  374. package/dist/tier-routing.d.ts +1 -1
  375. package/dist/token-estimate.d.ts +10 -0
  376. package/dist/token-estimate.js +8 -0
  377. package/dist/token-estimate.js.map +1 -0
  378. package/dist/topics.d.ts +1 -1
  379. package/dist/transcript.d.ts +1 -6
  380. package/dist/transcript.js +2 -1
  381. package/dist/transfer/backup.js +2 -2
  382. package/dist/transfer/capsule-export.js +2 -2
  383. package/dist/transfer/capsule-import.js +2 -2
  384. package/dist/transfer/types.d.ts +66 -66
  385. package/dist/trust-score-stage.d.ts +1 -1
  386. package/dist/trust-score.d.ts +1 -1
  387. package/dist/{types-CbXieHKr.d.ts → types-D7pB0QwO.d.ts} +1 -1
  388. package/dist/types.d.ts +1 -1
  389. package/dist/types.js +1 -1
  390. package/dist/utility-runtime.d.ts +1 -1
  391. package/dist/verified-recall.js +10 -10
  392. package/dist/write-envelope.d.ts +1 -1
  393. package/package.json +12 -2
  394. package/src/chunking.ts +124 -45
  395. package/src/config.ts +2 -0
  396. package/src/connectors/codex-materialize.ts +21 -26
  397. package/src/lcm/archive.ts +4 -5
  398. package/src/lcm/engine.ts +55 -34
  399. package/src/lcm/summarizer.ts +27 -16
  400. package/src/lcm-engine.test.ts +82 -2
  401. package/src/local-llm.ts +4 -6
  402. package/src/memory-extension-host/render-extensions-block.ts +3 -9
  403. package/src/orchestration/recall-section-coordinator.ts +93 -27
  404. package/src/recall-token-budget.test.ts +51 -0
  405. package/src/recall-xray.ts +4 -11
  406. package/src/semantic-chunking.ts +14 -59
  407. package/src/session-observer-state.ts +3 -3
  408. package/src/testing/subjects/recall-budget.test.ts +21 -5
  409. package/src/token-estimate.test.ts +38 -0
  410. package/src/token-estimate.ts +22 -0
  411. package/src/transcript.test.ts +38 -3
  412. package/src/transcript.ts +58 -59
  413. package/src/types.ts +1 -1
  414. package/dist/chunk-5ZIWRMZM.js.map +0 -1
  415. package/dist/chunk-C5B3CIMJ.js.map +0 -1
  416. package/dist/chunk-HYQJQGD3.js.map +0 -1
  417. package/dist/chunk-KSXJOC4F.js.map +0 -1
  418. package/dist/chunk-LTAVSOZW.js.map +0 -1
  419. package/dist/chunk-P4BC54KI.js.map +0 -1
  420. package/dist/chunk-PBGWYM3H.js.map +0 -1
  421. package/dist/chunk-QKPDN325.js.map +0 -1
  422. package/dist/chunk-UQ7RN5HK.js +0 -126
  423. package/dist/chunk-UQ7RN5HK.js.map +0 -1
  424. package/dist/chunk-Z54EM5YZ.js.map +0 -1
  425. /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-GWVG7LGC.js.map} +0 -0
  426. /package/dist/{chunk-YTZA7U6Q.js.map → chunk-2VHCLHZ5.js.map} +0 -0
  427. /package/dist/{chunk-NEJQ65NV.js.map → chunk-4CLE2LXB.js.map} +0 -0
  428. /package/dist/{chunk-VDX2J7OX.js.map → chunk-5W7CTZ2E.js.map} +0 -0
  429. /package/dist/{chunk-CZUHNJHX.js.map → chunk-6C7Q6NG3.js.map} +0 -0
  430. /package/dist/{chunk-4O6R3GPK.js.map → chunk-6W2ISYUV.js.map} +0 -0
  431. /package/dist/{chunk-3AJOJOFP.js.map → chunk-77DAFTUU.js.map} +0 -0
  432. /package/dist/{chunk-IKT6ZVO7.js.map → chunk-7DHFB5SG.js.map} +0 -0
  433. /package/dist/{chunk-SFR7J2G6.js.map → chunk-7G34CBKS.js.map} +0 -0
  434. /package/dist/{chunk-IT57AOMC.js.map → chunk-AH2NX6S7.js.map} +0 -0
  435. /package/dist/{chunk-FI3PIOOI.js.map → chunk-B4CSPFYN.js.map} +0 -0
  436. /package/dist/{chunk-7PJARJS4.js.map → chunk-BPM6UHUL.js.map} +0 -0
  437. /package/dist/{chunk-PPUTUOC3.js.map → chunk-BTHDQOF4.js.map} +0 -0
  438. /package/dist/{chunk-AW4A4XOP.js.map → chunk-CZGOLAEW.js.map} +0 -0
  439. /package/dist/{chunk-5PGYCWA7.js.map → chunk-DE6YCZEE.js.map} +0 -0
  440. /package/dist/{chunk-JOA4Q765.js.map → chunk-EUYWQ7TS.js.map} +0 -0
  441. /package/dist/{chunk-O5AFC5KM.js.map → chunk-EWL5DICB.js.map} +0 -0
  442. /package/dist/{chunk-4YZCIK5E.js.map → chunk-EZXGJJXM.js.map} +0 -0
  443. /package/dist/{chunk-GXIY65UH.js.map → chunk-FI5EAP4N.js.map} +0 -0
  444. /package/dist/{chunk-YOKSRIFI.js.map → chunk-FUWS2MNJ.js.map} +0 -0
  445. /package/dist/{chunk-6RK2X7BR.js.map → chunk-G3JFFUKR.js.map} +0 -0
  446. /package/dist/{chunk-VANZKHTN.js.map → chunk-G5OB4XZX.js.map} +0 -0
  447. /package/dist/{chunk-66SLUXKM.js.map → chunk-HK6KYIF6.js.map} +0 -0
  448. /package/dist/{chunk-XBGLEOID.js.map → chunk-I4BLRM7X.js.map} +0 -0
  449. /package/dist/{chunk-6SX4MY5Q.js.map → chunk-J65AKOD6.js.map} +0 -0
  450. /package/dist/{chunk-BPWZDHFM.js.map → chunk-J6QIAYNR.js.map} +0 -0
  451. /package/dist/{chunk-XL3TATMJ.js.map → chunk-JHMAYABJ.js.map} +0 -0
  452. /package/dist/{chunk-F7M36OG2.js.map → chunk-JNWISMYG.js.map} +0 -0
  453. /package/dist/{chunk-VYIXCMUP.js.map → chunk-KBIIE57I.js.map} +0 -0
  454. /package/dist/{chunk-24PNX2GF.js.map → chunk-KXYMU4IN.js.map} +0 -0
  455. /package/dist/{chunk-FKTD7IVS.js.map → chunk-L3JVAM5Q.js.map} +0 -0
  456. /package/dist/{chunk-LIF6DO6U.js.map → chunk-MG7GI4TT.js.map} +0 -0
  457. /package/dist/{chunk-RUZM6Z52.js.map → chunk-MMZK2DWN.js.map} +0 -0
  458. /package/dist/{chunk-NTJ6TY44.js.map → chunk-ODAE36PG.js.map} +0 -0
  459. /package/dist/{chunk-YLHM5BQQ.js.map → chunk-OLX2HJFW.js.map} +0 -0
  460. /package/dist/{chunk-DNC4A7RS.js.map → chunk-OU7RWWW6.js.map} +0 -0
  461. /package/dist/{chunk-L3LRWDJW.js.map → chunk-OV36CROW.js.map} +0 -0
  462. /package/dist/{chunk-BXLOS5AJ.js.map → chunk-OWHERGF2.js.map} +0 -0
  463. /package/dist/{chunk-CSV34HIW.js.map → chunk-P5OYNV7B.js.map} +0 -0
  464. /package/dist/{chunk-SNW3YRO6.js.map → chunk-P6GOYLHN.js.map} +0 -0
  465. /package/dist/{chunk-USGKHF36.js.map → chunk-QUJC22CT.js.map} +0 -0
  466. /package/dist/{chunk-BVRREV3N.js.map → chunk-R7IV3EUJ.js.map} +0 -0
  467. /package/dist/{chunk-D4LVHPOA.js.map → chunk-RXN7Z2V5.js.map} +0 -0
  468. /package/dist/{chunk-7VSHDLJQ.js.map → chunk-T2VJ2EO5.js.map} +0 -0
  469. /package/dist/{chunk-U7BMN33M.js.map → chunk-UBSM6TZP.js.map} +0 -0
  470. /package/dist/{chunk-DQEMWVMT.js.map → chunk-UVYI6VIX.js.map} +0 -0
  471. /package/dist/{chunk-U7XLOSG2.js.map → chunk-VIM6QH4D.js.map} +0 -0
  472. /package/dist/{chunk-LJJWFV2Q.js.map → chunk-VJXSAJFW.js.map} +0 -0
  473. /package/dist/{chunk-HZC3OECF.js.map → chunk-VOKK4WCG.js.map} +0 -0
  474. /package/dist/{chunk-LRDP2AC2.js.map → chunk-YBCZTBN2.js.map} +0 -0
  475. /package/dist/{chunk-USAUBGBC.js.map → chunk-YKZFX2HQ.js.map} +0 -0
  476. /package/dist/{chunk-I2GIYTRU.js.map → chunk-ZOGOOSB3.js.map} +0 -0
@@ -1,3 +1,7 @@
1
+ import {
2
+ estimateTokenCount
3
+ } from "./chunk-TOTT6S2V.js";
4
+
1
5
  // src/memory-extension-host/host-discovery.ts
2
6
  import { readdir, readFile, lstat, realpath } from "fs/promises";
3
7
  import path from "path";
@@ -225,9 +229,6 @@ function resolveExtensionsRoot(config) {
225
229
  }
226
230
 
227
231
  // src/memory-extension-host/render-extensions-block.ts
228
- function estimateTokens(text) {
229
- return Math.ceil(text.length / 4);
230
- }
231
232
  function renderExtensionsBlock(extensions) {
232
233
  if (extensions.length === 0) return "";
233
234
  const header = `## Active memory extensions
@@ -238,7 +239,7 @@ extension produces or curates.
238
239
 
239
240
  `;
240
241
  let budget = REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT;
241
- budget -= estimateTokens(header);
242
+ budget -= estimateTokenCount(header);
242
243
  const inlined = [];
243
244
  const omitted = [];
244
245
  for (const ext of extensions) {
@@ -248,7 +249,7 @@ ${ext.instructions}
248
249
  \`\`\`
249
250
 
250
251
  `;
251
- const cost = estimateTokens(block);
252
+ const cost = estimateTokenCount(block);
252
253
  if (cost <= budget) {
253
254
  inlined.push(block);
254
255
  budget -= cost;
@@ -277,4 +278,4 @@ export {
277
278
  renderExtensionsBlock,
278
279
  renderExtensionsFooter
279
280
  };
280
- //# sourceMappingURL=chunk-JLNBQWZ2.js.map
281
+ //# sourceMappingURL=chunk-5JMAGU26.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory-extension-host/host-discovery.ts","../src/memory-extension-host/render-extensions-block.ts"],"sourcesContent":["/**\n * memory-extension-host/host-discovery.ts — Discover third-party memory extensions.\n *\n * Scans a root directory (typically ~/.remnic/memory_extensions/) for valid\n * extension subdirectories. Each extension must contain an instructions.md.\n * The discovery process is read-only and NEVER reads or executes files under\n * any extension's scripts/ directory.\n */\n\nimport { readdir, readFile, lstat, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { LoggerBackend } from \"../logger.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport type { DiscoveredExtension, ExtensionSchema } from \"./types.js\";\n\n/** Total token budget for all discovered extension instructions combined. */\nexport const REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT = 5_000;\n\n/** Per-extension instructions read cap, using the same 4 chars/token budget heuristic. */\nexport const REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT =\n REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT * 4;\n\n/** Optional schemas are metadata only; refuse unusually large schema files. */\nexport const REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT = 64 * 1024;\n\n/** Maximum number of example files collected per extension. */\nconst MAX_EXAMPLES_PER_EXTENSION = 10;\n\n/** Slug validation: lowercase letters, digits, hyphens, 1-64 chars. */\nconst VALID_SLUG_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;\n\nconst VALID_MEMORY_TYPES = new Set([\"fact\", \"preference\", \"procedure\", \"reference\"]);\n\n/**\n * Discover all valid memory extensions under the given root directory.\n *\n * Returns extensions sorted by name. Skips entries with warnings when:\n * - The slug is invalid (not lowercase alphanumeric + hyphens, or > 64 chars)\n * - instructions.md is missing\n * - schema.json is malformed (extension still returned but schema is undefined)\n *\n * NEVER reads files under any extension's scripts/ directory.\n */\nexport async function discoverMemoryExtensions(\n root: string,\n log: Pick<LoggerBackend, \"warn\" | \"debug\">,\n): Promise<DiscoveredExtension[]> {\n // If root doesn't exist, return empty silently (not even a warning).\n // Use lstat() for root — a symlinked extensions root could redirect\n // discovery to an untrusted directory tree (#428 P2). When the root\n // IS a symlink, resolve it and verify it still lives under the parent\n // memory directory so that an attacker-controlled symlink can't point\n // discovery at /etc or another user's home.\n let rootStat;\n try {\n rootStat = await lstat(root);\n } catch {\n return [];\n }\n if (rootStat.isSymbolicLink()) {\n // Resolve and verify the real path is inside the expected parent.\n let resolved: string;\n try {\n resolved = await realpath(root);\n } catch {\n return [];\n }\n // Normalize the parent path through realpath so that:\n // 1. Relative roots (e.g. \"memory_extensions\") become absolute (#431 Finding 1)\n // 2. Intermediate symlinks (e.g. macOS /var -> /private/var) are resolved (#431 Finding 2)\n let expectedParent: string;\n try {\n expectedParent = await realpath(path.resolve(path.dirname(root)));\n } catch {\n // Parent directory doesn't exist or is inaccessible — reject.\n return [];\n }\n if (!resolved.startsWith(expectedParent + path.sep) && resolved !== expectedParent) {\n log.warn?.(\n `[memory-extensions] root \"${root}\" is a symlink resolving outside the expected parent directory, skipping`,\n );\n return [];\n }\n // Re-check the resolved path is a directory.\n try {\n rootStat = await lstat(resolved);\n } catch {\n return [];\n }\n }\n if (!rootStat.isDirectory()) {\n return [];\n }\n\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return [];\n }\n\n const extensions: DiscoveredExtension[] = [];\n\n for (const entry of entries) {\n const entryPath = path.join(root, entry);\n\n // Must be a real directory (not a symlink) — lstat() blocks symlink\n // traversal that could escape the extensions root (#382 P2).\n let entryStat;\n try {\n entryStat = await lstat(entryPath);\n } catch {\n continue;\n }\n if (entryStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": symlinks are not followed for security`,\n );\n continue;\n }\n if (!entryStat.isDirectory()) continue;\n\n // Validate slug\n if (!VALID_SLUG_RE.test(entry)) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": invalid slug (must be lowercase alphanumeric + hyphens, 1-64 chars)`,\n );\n continue;\n }\n\n // Require instructions.md — reject symlinked files (#428 P1)\n const instructionsPath = path.join(entryPath, \"instructions.md\");\n if (await isSymlink(instructionsPath)) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": instructions.md is a symlink`,\n );\n continue;\n }\n let instructions: string;\n try {\n instructions = await readUtf8FileWithinLimit(\n instructionsPath,\n REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT,\n );\n } catch (err) {\n const reason = err instanceof FileTooLargeError\n ? `instructions.md exceeds ${REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT} bytes`\n : \"missing instructions.md\";\n log.warn?.(`[memory-extensions] skipping \"${entry}\": ${reason}`);\n continue;\n }\n\n // Read optional schema.json — reject symlinked files (#428 P1)\n let schema: ExtensionSchema | undefined;\n const schemaPath = path.join(entryPath, \"schema.json\");\n if (await isSymlink(schemaPath)) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json is a symlink, ignoring schema`,\n );\n } else {\n try {\n const schemaRaw = await readUtf8FileWithinLimit(\n schemaPath,\n REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT,\n );\n const parsed = JSON.parse(schemaRaw);\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n schema = validateSchema(parsed);\n } else {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json is not a valid object, ignoring schema`,\n );\n }\n } catch (err) {\n // File doesn't exist → fine, no warning needed\n if (isFileNotFoundError(err)) {\n // schema remains undefined\n } else if (err instanceof FileTooLargeError) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json exceeds ${REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT} bytes, ignoring schema`,\n );\n } else {\n log.warn?.(\n `[memory-extensions] \"${entry}\": malformed schema.json, ignoring schema`,\n );\n }\n }\n }\n\n // Collect examples/*.md (cap at MAX_EXAMPLES_PER_EXTENSION)\n // NEVER read from scripts/ directory\n const examplesPaths: string[] = [];\n const examplesDir = path.join(entryPath, \"examples\");\n try {\n const examplesStat = await lstat(examplesDir);\n if (examplesStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": examples/ is a symlink, ignoring examples`,\n );\n throw new Error(\"skip symlinked examples directory\");\n }\n if (!examplesStat.isDirectory()) {\n throw new Error(\"skip non-directory examples path\");\n }\n const exampleEntries = await readdir(examplesDir);\n const mdFiles = exampleEntries\n .filter((f) => f.endsWith(\".md\"))\n .sort()\n .slice(0, MAX_EXAMPLES_PER_EXTENSION);\n for (const f of mdFiles) {\n const examplePath = path.join(examplesDir, f);\n const exampleStat = await lstat(examplePath);\n if (exampleStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": examples/${f} is a symlink, ignoring example`,\n );\n continue;\n }\n if (!exampleStat.isFile()) {\n continue;\n }\n examplesPaths.push(examplePath);\n }\n } catch {\n // No examples dir — fine\n }\n\n extensions.push({\n name: entry,\n root: entryPath,\n instructionsPath,\n instructions,\n schema,\n examplesPaths,\n });\n }\n\n // Sort by name for deterministic ordering\n extensions.sort((a, b) => {\n if (a.name < b.name) return -1;\n if (a.name > b.name) return 1;\n return 0;\n });\n\n return extensions;\n}\n\nclass FileTooLargeError extends Error {\n constructor(filePath: string, limitBytes: number, actualBytes: number) {\n super(`${filePath} is ${actualBytes} bytes; limit is ${limitBytes} bytes`);\n this.name = \"FileTooLargeError\";\n }\n}\n\nasync function readUtf8FileWithinLimit(filePath: string, limitBytes: number): Promise<string> {\n const stat = await lstat(filePath);\n if (!stat.isFile()) {\n throw new Error(`${filePath} is not a file`);\n }\n if (stat.size > limitBytes) {\n throw new FileTooLargeError(filePath, limitBytes, stat.size);\n }\n return readFile(filePath, \"utf-8\");\n}\n\nfunction validateSchema(raw: Record<string, unknown>): ExtensionSchema {\n const memoryTypes: ExtensionSchema[\"memoryTypes\"] = (() => {\n if (!Array.isArray(raw.memoryTypes)) return undefined;\n const valid = raw.memoryTypes.filter(\n (t): t is \"fact\" | \"preference\" | \"procedure\" | \"reference\" =>\n typeof t === \"string\" && VALID_MEMORY_TYPES.has(t),\n );\n return valid.length > 0 ? valid : undefined;\n })();\n\n const groupingHints: ExtensionSchema[\"groupingHints\"] = (() => {\n if (!Array.isArray(raw.groupingHints)) return undefined;\n const valid = raw.groupingHints.filter(\n (h): h is string => typeof h === \"string\" && h.length > 0,\n );\n return valid.length > 0 ? valid : undefined;\n })();\n\n const version: ExtensionSchema[\"version\"] =\n typeof raw.version === \"string\" && raw.version.length > 0\n ? raw.version\n : undefined;\n\n return {\n ...(memoryTypes ? { memoryTypes } : {}),\n ...(groupingHints ? { groupingHints } : {}),\n ...(version ? { version } : {}),\n };\n}\n\nfunction isFileNotFoundError(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n );\n}\n\n/**\n * Returns true if the path exists and is a symlink.\n * Returns false if the path does not exist or is not a symlink.\n */\nasync function isSymlink(filePath: string): Promise<boolean> {\n try {\n const s = await lstat(filePath);\n return s.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve the memory extensions root directory from config.\n * If memoryExtensionsRoot is empty, derive from memoryDir by going up to\n * the Remnic home dir and appending memory_extensions.\n *\n * Moved here from semantic-consolidation.ts (#428 Finding 3) because this\n * is a generic config-to-path resolver with no consolidation logic.\n */\nexport function resolveExtensionsRoot(config: PluginConfig): string {\n if (config.memoryExtensionsRoot.length > 0) {\n return config.memoryExtensionsRoot;\n }\n // Default: memoryDir is typically ~/.openclaw/workspace/memory/local\n // Go up to the parent that owns the memory tree and append memory_extensions\n return path.join(path.dirname(config.memoryDir), \"memory_extensions\");\n}\n","/**\n * memory-extension-host/render-extensions-block.ts — Render discovered extensions\n * into a markdown block for injection into consolidation prompts.\n *\n * Respects the global token budget (REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT) and\n * truncates with a footer listing omitted extensions when over budget.\n */\n\nimport { REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT } from \"./host-discovery.js\";\nimport type { DiscoveredExtension } from \"./types.js\";\n\n/**\n * Approximate token count using the 4 chars per token heuristic.\n */\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\n/**\n * Render a markdown block containing extension instructions for injection\n * into consolidation prompts.\n *\n * If the list is empty, returns \"\".\n * Inlines extensions in name order until the token budget is exhausted.\n * If the budget is exceeded, appends a truncation footer listing omitted extensions.\n */\nexport function renderExtensionsBlock(extensions: DiscoveredExtension[]): string {\n if (extensions.length === 0) return \"\";\n\n const header = `## Active memory extensions\n\nYou are running with the following third-party memory extensions. Each\nextension's \\`instructions.md\\` tells you how to interpret memories that\nextension produces or curates.\n\n`;\n\n let budget = REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT;\n budget -= estimateTokens(header);\n\n const inlined: string[] = [];\n const omitted: string[] = [];\n\n for (const ext of extensions) {\n const block = `### remnic-extension/${ext.name}\\n\\`\\`\\`\\n${ext.instructions}\\n\\`\\`\\`\\n\\n`;\n const cost = estimateTokens(block);\n if (cost <= budget) {\n inlined.push(block);\n budget -= cost;\n } else {\n omitted.push(ext.name);\n }\n }\n\n let result = header;\n result += inlined.join(\"\");\n\n if (omitted.length > 0) {\n result += `> **Note:** ${omitted.length} extension(s) omitted due to token budget: ${omitted.join(\", \")}\\n`;\n }\n\n return result;\n}\n\n/**\n * Render a compact one-line footer listing active extension names.\n * Used by day-summary and summary-snapshot where full instructions are not needed.\n */\nexport function renderExtensionsFooter(extensions: DiscoveredExtension[]): string {\n if (extensions.length === 0) return \"\";\n const names = extensions.map((ext) => ext.name).join(\", \");\n return `Active extensions: ${names}`;\n}\n"],"mappings":";AASA,SAAS,SAAS,UAAU,OAAO,gBAAgB;AACnD,OAAO,UAAU;AAMV,IAAM,sCAAsC;AAG5C,IAAM,2CACX,sCAAsC;AAGjC,IAAM,qCAAqC,KAAK;AAGvD,IAAM,6BAA6B;AAGnC,IAAM,gBAAgB;AAEtB,IAAM,qBAAqB,oBAAI,IAAI,CAAC,QAAQ,cAAc,aAAa,WAAW,CAAC;AAYnF,eAAsB,yBACpB,MACA,KACgC;AAOhC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,IAAI;AAAA,EAC7B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,MAAI,SAAS,eAAe,GAAG;AAE7B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,SAAS,IAAI;AAAA,IAChC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAIA,QAAI;AACJ,QAAI;AACF,uBAAiB,MAAM,SAAS,KAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC;AAAA,IAClE,QAAQ;AAEN,aAAO,CAAC;AAAA,IACV;AACA,QAAI,CAAC,SAAS,WAAW,iBAAiB,KAAK,GAAG,KAAK,aAAa,gBAAgB;AAClF,UAAI;AAAA,QACF,6BAA6B,IAAI;AAAA,MACnC;AACA,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,iBAAW,MAAM,MAAM,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACA,MAAI,CAAC,SAAS,YAAY,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,QAAQ,IAAI;AAAA,EAC9B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,aAAoC,CAAC;AAE3C,aAAW,SAAS,SAAS;AAC3B,UAAM,YAAY,KAAK,KAAK,MAAM,KAAK;AAIvC,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,MAAM,SAAS;AAAA,IACnC,QAAQ;AACN;AAAA,IACF;AACA,QAAI,UAAU,eAAe,GAAG;AAC9B,UAAI;AAAA,QACF,iCAAiC,KAAK;AAAA,MACxC;AACA;AAAA,IACF;AACA,QAAI,CAAC,UAAU,YAAY,EAAG;AAG9B,QAAI,CAAC,cAAc,KAAK,KAAK,GAAG;AAC9B,UAAI;AAAA,QACF,iCAAiC,KAAK;AAAA,MACxC;AACA;AAAA,IACF;AAGA,UAAM,mBAAmB,KAAK,KAAK,WAAW,iBAAiB;AAC/D,QAAI,MAAM,UAAU,gBAAgB,GAAG;AACrC,UAAI;AAAA,QACF,iCAAiC,KAAK;AAAA,MACxC;AACA;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,qBAAe,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,SAAS,eAAe,oBAC1B,2BAA2B,wCAAwC,WACnE;AACJ,UAAI,OAAO,iCAAiC,KAAK,MAAM,MAAM,EAAE;AAC/D;AAAA,IACF;AAGA,QAAI;AACJ,UAAM,aAAa,KAAK,KAAK,WAAW,aAAa;AACrD,QAAI,MAAM,UAAU,UAAU,GAAG;AAC/B,UAAI;AAAA,QACF,wBAAwB,KAAK;AAAA,MAC/B;AAAA,IACF,OAAO;AACL,UAAI;AACF,cAAM,YAAY,MAAM;AAAA,UACtB;AAAA,UACA;AAAA,QACF;AACA,cAAM,SAAS,KAAK,MAAM,SAAS;AACnC,YAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC3E,mBAAS,eAAe,MAAM;AAAA,QAChC,OAAO;AACL,cAAI;AAAA,YACF,wBAAwB,KAAK;AAAA,UAC/B;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AAEZ,YAAI,oBAAoB,GAAG,GAAG;AAAA,QAE9B,WAAW,eAAe,mBAAmB;AAC3C,cAAI;AAAA,YACF,wBAAwB,KAAK,0BAA0B,kCAAkC;AAAA,UAC3F;AAAA,QACF,OAAO;AACL,cAAI;AAAA,YACF,wBAAwB,KAAK;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAIA,UAAM,gBAA0B,CAAC;AACjC,UAAM,cAAc,KAAK,KAAK,WAAW,UAAU;AACnD,QAAI;AACF,YAAM,eAAe,MAAM,MAAM,WAAW;AAC5C,UAAI,aAAa,eAAe,GAAG;AACjC,YAAI;AAAA,UACF,wBAAwB,KAAK;AAAA,QAC/B;AACA,cAAM,IAAI,MAAM,mCAAmC;AAAA,MACrD;AACA,UAAI,CAAC,aAAa,YAAY,GAAG;AAC/B,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AACA,YAAM,iBAAiB,MAAM,QAAQ,WAAW;AAChD,YAAM,UAAU,eACb,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,KAAK,EACL,MAAM,GAAG,0BAA0B;AACtC,iBAAW,KAAK,SAAS;AACvB,cAAM,cAAc,KAAK,KAAK,aAAa,CAAC;AAC5C,cAAM,cAAc,MAAM,MAAM,WAAW;AAC3C,YAAI,YAAY,eAAe,GAAG;AAChC,cAAI;AAAA,YACF,wBAAwB,KAAK,eAAe,CAAC;AAAA,UAC/C;AACA;AAAA,QACF;AACA,YAAI,CAAC,YAAY,OAAO,GAAG;AACzB;AAAA,QACF;AACA,sBAAc,KAAK,WAAW;AAAA,MAChC;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,eAAW,KAAK;AAAA,MACd,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAGA,aAAW,KAAK,CAAC,GAAG,MAAM;AACxB,QAAI,EAAE,OAAO,EAAE,KAAM,QAAO;AAC5B,QAAI,EAAE,OAAO,EAAE,KAAM,QAAO;AAC5B,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAEA,IAAM,oBAAN,cAAgC,MAAM;AAAA,EACpC,YAAY,UAAkB,YAAoB,aAAqB;AACrE,UAAM,GAAG,QAAQ,OAAO,WAAW,oBAAoB,UAAU,QAAQ;AACzE,SAAK,OAAO;AAAA,EACd;AACF;AAEA,eAAe,wBAAwB,UAAkB,YAAqC;AAC5F,QAAM,OAAO,MAAM,MAAM,QAAQ;AACjC,MAAI,CAAC,KAAK,OAAO,GAAG;AAClB,UAAM,IAAI,MAAM,GAAG,QAAQ,gBAAgB;AAAA,EAC7C;AACA,MAAI,KAAK,OAAO,YAAY;AAC1B,UAAM,IAAI,kBAAkB,UAAU,YAAY,KAAK,IAAI;AAAA,EAC7D;AACA,SAAO,SAAS,UAAU,OAAO;AACnC;AAEA,SAAS,eAAe,KAA+C;AACrE,QAAM,eAA+C,MAAM;AACzD,QAAI,CAAC,MAAM,QAAQ,IAAI,WAAW,EAAG,QAAO;AAC5C,UAAM,QAAQ,IAAI,YAAY;AAAA,MAC5B,CAAC,MACC,OAAO,MAAM,YAAY,mBAAmB,IAAI,CAAC;AAAA,IACrD;AACA,WAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,EACpC,GAAG;AAEH,QAAM,iBAAmD,MAAM;AAC7D,QAAI,CAAC,MAAM,QAAQ,IAAI,aAAa,EAAG,QAAO;AAC9C,UAAM,QAAQ,IAAI,cAAc;AAAA,MAC9B,CAAC,MAAmB,OAAO,MAAM,YAAY,EAAE,SAAS;AAAA,IAC1D;AACA,WAAO,MAAM,SAAS,IAAI,QAAQ;AAAA,EACpC,GAAG;AAEH,QAAM,UACJ,OAAO,IAAI,YAAY,YAAY,IAAI,QAAQ,SAAS,IACpD,IAAI,UACJ;AAEN,SAAO;AAAA,IACL,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACrC,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,IACzC,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;AAEA,SAAS,oBAAoB,KAAuB;AAClD,SACE,OAAO,QAAQ,YACf,QAAQ,QACR,UAAU,OACT,IAAyB,SAAS;AAEvC;AAMA,eAAe,UAAU,UAAoC;AAC3D,MAAI;AACF,UAAM,IAAI,MAAM,MAAM,QAAQ;AAC9B,WAAO,EAAE,eAAe;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUO,SAAS,sBAAsB,QAA8B;AAClE,MAAI,OAAO,qBAAqB,SAAS,GAAG;AAC1C,WAAO,OAAO;AAAA,EAChB;AAGA,SAAO,KAAK,KAAK,KAAK,QAAQ,OAAO,SAAS,GAAG,mBAAmB;AACtE;;;AC9TA,SAAS,eAAe,MAAsB;AAC5C,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAUO,SAAS,sBAAsB,YAA2C;AAC/E,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,QAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQf,MAAI,SAAS;AACb,YAAU,eAAe,MAAM;AAE/B,QAAM,UAAoB,CAAC;AAC3B,QAAM,UAAoB,CAAC;AAE3B,aAAW,OAAO,YAAY;AAC5B,UAAM,QAAQ,wBAAwB,IAAI,IAAI;AAAA;AAAA,EAAa,IAAI,YAAY;AAAA;AAAA;AAAA;AAC3E,UAAM,OAAO,eAAe,KAAK;AACjC,QAAI,QAAQ,QAAQ;AAClB,cAAQ,KAAK,KAAK;AAClB,gBAAU;AAAA,IACZ,OAAO;AACL,cAAQ,KAAK,IAAI,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,MAAI,SAAS;AACb,YAAU,QAAQ,KAAK,EAAE;AAEzB,MAAI,QAAQ,SAAS,GAAG;AACtB,cAAU,eAAe,QAAQ,MAAM,8CAA8C,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EACzG;AAEA,SAAO;AACT;AAMO,SAAS,uBAAuB,YAA2C;AAChF,MAAI,WAAW,WAAW,EAAG,QAAO;AACpC,QAAM,QAAQ,WAAW,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,KAAK,IAAI;AACzD,SAAO,sBAAsB,KAAK;AACpC;","names":[]}
1
+ {"version":3,"sources":["../src/memory-extension-host/host-discovery.ts","../src/memory-extension-host/render-extensions-block.ts"],"sourcesContent":["/**\n * memory-extension-host/host-discovery.ts — Discover third-party memory extensions.\n *\n * Scans a root directory (typically ~/.remnic/memory_extensions/) for valid\n * extension subdirectories. Each extension must contain an instructions.md.\n * The discovery process is read-only and NEVER reads or executes files under\n * any extension's scripts/ directory.\n */\n\nimport { readdir, readFile, lstat, realpath } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { LoggerBackend } from \"../logger.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport type { DiscoveredExtension, ExtensionSchema } from \"./types.js\";\n\n/** Total token budget for all discovered extension instructions combined. */\nexport const REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT = 5_000;\n\n/** Per-extension instructions read cap, using the same 4 chars/token budget heuristic. */\nexport const REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT =\n REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT * 4;\n\n/** Optional schemas are metadata only; refuse unusually large schema files. */\nexport const REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT = 64 * 1024;\n\n/** Maximum number of example files collected per extension. */\nconst MAX_EXAMPLES_PER_EXTENSION = 10;\n\n/** Slug validation: lowercase letters, digits, hyphens, 1-64 chars. */\nconst VALID_SLUG_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;\n\nconst VALID_MEMORY_TYPES = new Set([\"fact\", \"preference\", \"procedure\", \"reference\"]);\n\n/**\n * Discover all valid memory extensions under the given root directory.\n *\n * Returns extensions sorted by name. Skips entries with warnings when:\n * - The slug is invalid (not lowercase alphanumeric + hyphens, or > 64 chars)\n * - instructions.md is missing\n * - schema.json is malformed (extension still returned but schema is undefined)\n *\n * NEVER reads files under any extension's scripts/ directory.\n */\nexport async function discoverMemoryExtensions(\n root: string,\n log: Pick<LoggerBackend, \"warn\" | \"debug\">,\n): Promise<DiscoveredExtension[]> {\n // If root doesn't exist, return empty silently (not even a warning).\n // Use lstat() for root — a symlinked extensions root could redirect\n // discovery to an untrusted directory tree (#428 P2). When the root\n // IS a symlink, resolve it and verify it still lives under the parent\n // memory directory so that an attacker-controlled symlink can't point\n // discovery at /etc or another user's home.\n let rootStat;\n try {\n rootStat = await lstat(root);\n } catch {\n return [];\n }\n if (rootStat.isSymbolicLink()) {\n // Resolve and verify the real path is inside the expected parent.\n let resolved: string;\n try {\n resolved = await realpath(root);\n } catch {\n return [];\n }\n // Normalize the parent path through realpath so that:\n // 1. Relative roots (e.g. \"memory_extensions\") become absolute (#431 Finding 1)\n // 2. Intermediate symlinks (e.g. macOS /var -> /private/var) are resolved (#431 Finding 2)\n let expectedParent: string;\n try {\n expectedParent = await realpath(path.resolve(path.dirname(root)));\n } catch {\n // Parent directory doesn't exist or is inaccessible — reject.\n return [];\n }\n if (!resolved.startsWith(expectedParent + path.sep) && resolved !== expectedParent) {\n log.warn?.(\n `[memory-extensions] root \"${root}\" is a symlink resolving outside the expected parent directory, skipping`,\n );\n return [];\n }\n // Re-check the resolved path is a directory.\n try {\n rootStat = await lstat(resolved);\n } catch {\n return [];\n }\n }\n if (!rootStat.isDirectory()) {\n return [];\n }\n\n let entries: string[];\n try {\n entries = await readdir(root);\n } catch {\n return [];\n }\n\n const extensions: DiscoveredExtension[] = [];\n\n for (const entry of entries) {\n const entryPath = path.join(root, entry);\n\n // Must be a real directory (not a symlink) — lstat() blocks symlink\n // traversal that could escape the extensions root (#382 P2).\n let entryStat;\n try {\n entryStat = await lstat(entryPath);\n } catch {\n continue;\n }\n if (entryStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": symlinks are not followed for security`,\n );\n continue;\n }\n if (!entryStat.isDirectory()) continue;\n\n // Validate slug\n if (!VALID_SLUG_RE.test(entry)) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": invalid slug (must be lowercase alphanumeric + hyphens, 1-64 chars)`,\n );\n continue;\n }\n\n // Require instructions.md — reject symlinked files (#428 P1)\n const instructionsPath = path.join(entryPath, \"instructions.md\");\n if (await isSymlink(instructionsPath)) {\n log.warn?.(\n `[memory-extensions] skipping \"${entry}\": instructions.md is a symlink`,\n );\n continue;\n }\n let instructions: string;\n try {\n instructions = await readUtf8FileWithinLimit(\n instructionsPath,\n REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT,\n );\n } catch (err) {\n const reason = err instanceof FileTooLargeError\n ? `instructions.md exceeds ${REMNIC_EXTENSION_INSTRUCTIONS_BYTE_LIMIT} bytes`\n : \"missing instructions.md\";\n log.warn?.(`[memory-extensions] skipping \"${entry}\": ${reason}`);\n continue;\n }\n\n // Read optional schema.json — reject symlinked files (#428 P1)\n let schema: ExtensionSchema | undefined;\n const schemaPath = path.join(entryPath, \"schema.json\");\n if (await isSymlink(schemaPath)) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json is a symlink, ignoring schema`,\n );\n } else {\n try {\n const schemaRaw = await readUtf8FileWithinLimit(\n schemaPath,\n REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT,\n );\n const parsed = JSON.parse(schemaRaw);\n if (typeof parsed === \"object\" && parsed !== null && !Array.isArray(parsed)) {\n schema = validateSchema(parsed);\n } else {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json is not a valid object, ignoring schema`,\n );\n }\n } catch (err) {\n // File doesn't exist → fine, no warning needed\n if (isFileNotFoundError(err)) {\n // schema remains undefined\n } else if (err instanceof FileTooLargeError) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": schema.json exceeds ${REMNIC_EXTENSION_SCHEMA_BYTE_LIMIT} bytes, ignoring schema`,\n );\n } else {\n log.warn?.(\n `[memory-extensions] \"${entry}\": malformed schema.json, ignoring schema`,\n );\n }\n }\n }\n\n // Collect examples/*.md (cap at MAX_EXAMPLES_PER_EXTENSION)\n // NEVER read from scripts/ directory\n const examplesPaths: string[] = [];\n const examplesDir = path.join(entryPath, \"examples\");\n try {\n const examplesStat = await lstat(examplesDir);\n if (examplesStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": examples/ is a symlink, ignoring examples`,\n );\n throw new Error(\"skip symlinked examples directory\");\n }\n if (!examplesStat.isDirectory()) {\n throw new Error(\"skip non-directory examples path\");\n }\n const exampleEntries = await readdir(examplesDir);\n const mdFiles = exampleEntries\n .filter((f) => f.endsWith(\".md\"))\n .sort()\n .slice(0, MAX_EXAMPLES_PER_EXTENSION);\n for (const f of mdFiles) {\n const examplePath = path.join(examplesDir, f);\n const exampleStat = await lstat(examplePath);\n if (exampleStat.isSymbolicLink()) {\n log.warn?.(\n `[memory-extensions] \"${entry}\": examples/${f} is a symlink, ignoring example`,\n );\n continue;\n }\n if (!exampleStat.isFile()) {\n continue;\n }\n examplesPaths.push(examplePath);\n }\n } catch {\n // No examples dir — fine\n }\n\n extensions.push({\n name: entry,\n root: entryPath,\n instructionsPath,\n instructions,\n schema,\n examplesPaths,\n });\n }\n\n // Sort by name for deterministic ordering\n extensions.sort((a, b) => {\n if (a.name < b.name) return -1;\n if (a.name > b.name) return 1;\n return 0;\n });\n\n return extensions;\n}\n\nclass FileTooLargeError extends Error {\n constructor(filePath: string, limitBytes: number, actualBytes: number) {\n super(`${filePath} is ${actualBytes} bytes; limit is ${limitBytes} bytes`);\n this.name = \"FileTooLargeError\";\n }\n}\n\nasync function readUtf8FileWithinLimit(filePath: string, limitBytes: number): Promise<string> {\n const stat = await lstat(filePath);\n if (!stat.isFile()) {\n throw new Error(`${filePath} is not a file`);\n }\n if (stat.size > limitBytes) {\n throw new FileTooLargeError(filePath, limitBytes, stat.size);\n }\n return readFile(filePath, \"utf-8\");\n}\n\nfunction validateSchema(raw: Record<string, unknown>): ExtensionSchema {\n const memoryTypes: ExtensionSchema[\"memoryTypes\"] = (() => {\n if (!Array.isArray(raw.memoryTypes)) return undefined;\n const valid = raw.memoryTypes.filter(\n (t): t is \"fact\" | \"preference\" | \"procedure\" | \"reference\" =>\n typeof t === \"string\" && VALID_MEMORY_TYPES.has(t),\n );\n return valid.length > 0 ? valid : undefined;\n })();\n\n const groupingHints: ExtensionSchema[\"groupingHints\"] = (() => {\n if (!Array.isArray(raw.groupingHints)) return undefined;\n const valid = raw.groupingHints.filter(\n (h): h is string => typeof h === \"string\" && h.length > 0,\n );\n return valid.length > 0 ? valid : undefined;\n })();\n\n const version: ExtensionSchema[\"version\"] =\n typeof raw.version === \"string\" && raw.version.length > 0\n ? raw.version\n : undefined;\n\n return {\n ...(memoryTypes ? { memoryTypes } : {}),\n ...(groupingHints ? { groupingHints } : {}),\n ...(version ? { version } : {}),\n };\n}\n\nfunction isFileNotFoundError(err: unknown): boolean {\n return (\n typeof err === \"object\" &&\n err !== null &&\n \"code\" in err &&\n (err as { code: string }).code === \"ENOENT\"\n );\n}\n\n/**\n * Returns true if the path exists and is a symlink.\n * Returns false if the path does not exist or is not a symlink.\n */\nasync function isSymlink(filePath: string): Promise<boolean> {\n try {\n const s = await lstat(filePath);\n return s.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve the memory extensions root directory from config.\n * If memoryExtensionsRoot is empty, derive from memoryDir by going up to\n * the Remnic home dir and appending memory_extensions.\n *\n * Moved here from semantic-consolidation.ts (#428 Finding 3) because this\n * is a generic config-to-path resolver with no consolidation logic.\n */\nexport function resolveExtensionsRoot(config: PluginConfig): string {\n if (config.memoryExtensionsRoot.length > 0) {\n return config.memoryExtensionsRoot;\n }\n // Default: memoryDir is typically ~/.openclaw/workspace/memory/local\n // Go up to the parent that owns the memory tree and append memory_extensions\n return path.join(path.dirname(config.memoryDir), \"memory_extensions\");\n}\n","/**\n * memory-extension-host/render-extensions-block.ts — Render discovered extensions\n * into a markdown block for injection into consolidation prompts.\n *\n * Respects the global token budget (REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT) and\n * truncates with a footer listing omitted extensions when over budget.\n */\n\nimport { estimateTokenCount } from \"../token-estimate.js\";\nimport { REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT } from \"./host-discovery.js\";\nimport type { DiscoveredExtension } from \"./types.js\";\n\n/**\n * Render a markdown block containing extension instructions for injection\n * into consolidation prompts.\n *\n * If the list is empty, returns \"\".\n * Inlines extensions in name order until the token budget is exhausted.\n * If the budget is exceeded, appends a truncation footer listing omitted extensions.\n */\nexport function renderExtensionsBlock(extensions: DiscoveredExtension[]): string {\n if (extensions.length === 0) return \"\";\n\n const header = `## Active memory extensions\n\nYou are running with the following third-party memory extensions. Each\nextension's \\`instructions.md\\` tells you how to interpret memories that\nextension produces or curates.\n\n`;\n\n let budget = REMNIC_EXTENSIONS_TOTAL_TOKEN_LIMIT;\n budget -= estimateTokenCount(header);\n\n const inlined: string[] = [];\n const omitted: string[] = [];\n\n for (const ext of extensions) {\n const block = `### remnic-extension/${ext.name}\\n\\`\\`\\`\\n${ext.instructions}\\n\\`\\`\\`\\n\\n`;\n const cost = estimateTokenCount(block);\n if (cost <= budget) {\n inlined.push(block);\n budget -= cost;\n } else {\n omitted.push(ext.name);\n }\n }\n\n let result = header;\n result += inlined.join(\"\");\n\n if (omitted.length > 0) {\n result += `> **Note:** ${omitted.length} extension(s) omitted due to token budget: ${omitted.join(\", \")}\\n`;\n }\n\n return result;\n}\n\n/**\n * Render a compact one-line footer listing active extension names.\n * Used by day-summary and summary-snapshot where full instructions are not needed.\n */\nexport function renderExtensionsFooter(extensions: DiscoveredExtension[]): string {\n if (extensions.length === 0) return \"\";\n const names = extensions.map((ext) => ext.name).join(\", \");\n return `Active extensions: ${names}`;\n}\n"],"mappings":"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","names":[]}
@@ -1,12 +1,12 @@
1
+ import {
2
+ encryptCapsuleFile
3
+ } from "./chunk-UVYI6VIX.js";
1
4
  import {
2
5
  CAPSULE_ID_PATTERN,
3
6
  CapsuleBlockSchema,
4
7
  ExportBundleV2Schema,
5
8
  ExportManifestV2Schema
6
9
  } from "./chunk-WEHSQBFR.js";
7
- import {
8
- encryptCapsuleFile
9
- } from "./chunk-DQEMWVMT.js";
10
10
  import {
11
11
  CAPSULE_SCHEMA_VERSION,
12
12
  EXPORT_FORMAT
@@ -261,4 +261,4 @@ export {
261
261
  exportCapsule,
262
262
  isValidCapsuleSince
263
263
  };
264
- //# sourceMappingURL=chunk-VDX2J7OX.js.map
264
+ //# sourceMappingURL=chunk-5W7CTZ2E.js.map
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-GDB4J2H3.js";
9
9
  import {
10
10
  importCapsule
11
- } from "./chunk-PPUTUOC3.js";
11
+ } from "./chunk-BTHDQOF4.js";
12
12
  import {
13
13
  WriteQuarantineStore
14
14
  } from "./chunk-PJSK6OJM.js";
@@ -35,13 +35,13 @@ import {
35
35
  } from "./chunk-H7XKCNR6.js";
36
36
  import {
37
37
  toRecallExplainJson
38
- } from "./chunk-U7BMN33M.js";
38
+ } from "./chunk-UBSM6TZP.js";
39
39
  import {
40
40
  estimateRecallTokens
41
- } from "./chunk-QKPDN325.js";
41
+ } from "./chunk-KF75ANST.js";
42
42
  import {
43
43
  readAggregateExtractionWatermark
44
- } from "./chunk-5PGYCWA7.js";
44
+ } from "./chunk-DE6YCZEE.js";
45
45
  import {
46
46
  ReplicaDivergenceMonitor
47
47
  } from "./chunk-CVILPI77.js";
@@ -71,7 +71,7 @@ import {
71
71
  } from "./chunk-NLE6TSLG.js";
72
72
  import {
73
73
  LocalLlmClient
74
- } from "./chunk-5ZIWRMZM.js";
74
+ } from "./chunk-IVKIODHO.js";
75
75
  import {
76
76
  buildProcedurePersistBody,
77
77
  normalizeProcedureSteps
@@ -99,11 +99,11 @@ import {
99
99
  listMemoryGovernanceRuns,
100
100
  readMemoryGovernanceRunArtifact,
101
101
  runMemoryGovernance
102
- } from "./chunk-6RK2X7BR.js";
102
+ } from "./chunk-G3JFFUKR.js";
103
103
  import {
104
104
  CorpusWatermarkCache,
105
105
  computeServiceCorpusCensus
106
- } from "./chunk-LJJWFV2Q.js";
106
+ } from "./chunk-VJXSAJFW.js";
107
107
  import {
108
108
  CrossNamespaceBudget,
109
109
  toBudgetWarning
@@ -127,21 +127,21 @@ import {
127
127
  enqueuePassiveCorrectionNotification,
128
128
  parseBriefingFocus,
129
129
  parseBriefingWindow
130
- } from "./chunk-CSV34HIW.js";
130
+ } from "./chunk-P5OYNV7B.js";
131
131
  import {
132
132
  parseEntityFile,
133
133
  parseFrontmatter,
134
134
  qmdCollectionPathParts,
135
135
  qmdResultPathCandidates,
136
136
  selfDeps
137
- } from "./chunk-YTZA7U6Q.js";
137
+ } from "./chunk-2VHCLHZ5.js";
138
138
  import {
139
139
  namespaceCollectionName
140
- } from "./chunk-SNW3YRO6.js";
140
+ } from "./chunk-P6GOYLHN.js";
141
141
  import {
142
142
  DEFAULT_RECALL_DISCLOSURE,
143
143
  isRecallDisclosure
144
- } from "./chunk-5QHDXMXP.js";
144
+ } from "./chunk-LLZKOSGM.js";
145
145
  import {
146
146
  normalizeProjectionPreview,
147
147
  normalizeProjectionTags
@@ -179,7 +179,7 @@ import {
179
179
  } from "./chunk-JV3C2MNQ.js";
180
180
  import {
181
181
  exportCapsule
182
- } from "./chunk-VDX2J7OX.js";
182
+ } from "./chunk-5W7CTZ2E.js";
183
183
  import {
184
184
  evaluateActionConfidence
185
185
  } from "./chunk-Z2YFLXHU.js";
@@ -17672,4 +17672,4 @@ export {
17672
17672
  EngramAccessService,
17673
17673
  AccessAdminOpsSurface
17674
17674
  };
17675
- //# sourceMappingURL=chunk-CZUHNJHX.js.map
17675
+ //# sourceMappingURL=chunk-6C7Q6NG3.js.map
@@ -0,0 +1,201 @@
1
+ import {
2
+ estimateTokenCount
3
+ } from "./chunk-TOTT6S2V.js";
4
+
5
+ // src/chunking.ts
6
+ var DEFAULT_CHUNKING_CONFIG = {
7
+ targetTokens: 200,
8
+ minTokens: 150,
9
+ overlapSentences: 2
10
+ };
11
+ var UNICODE_SENTENCE_TERMINATORS = "\u3002\uFF0E\uFF01\uFF1F\u061F\u06D4\u0964\u0965\uFF61\u2026";
12
+ var ASCII_SENTENCE_TERMINATORS = ".!?";
13
+ var CJK_NO_SPACE_TERMINATORS = "\u3002\uFF0E\uFF01\uFF1F\uFF61";
14
+ var CLOSING_PUNCTUATION = `"'\u201D\u2019\xBB\u300D\u300F\uFF09\uFF3D\u3011\u3009\u300B)]}`;
15
+ var DIGITS = "0123456789\uFF10\uFF11\uFF12\uFF13\uFF14\uFF15\uFF16\uFF17\uFF18\uFF19";
16
+ var SENTENCE_SEGMENTER = typeof Intl.Segmenter === "function" ? new Intl.Segmenter(void 0, { granularity: "sentence" }) : void 0;
17
+ function isSentenceTerminator(character) {
18
+ return ASCII_SENTENCE_TERMINATORS.includes(character) || UNICODE_SENTENCE_TERMINATORS.includes(character);
19
+ }
20
+ function isCjk(character) {
21
+ return /[\u3000-\u9fff\uf900-\ufaff\uac00-\ud7af]/u.test(character);
22
+ }
23
+ function splitSentencesFallback(text) {
24
+ const sentences = [];
25
+ Object.defineProperty(sentences, "separators", {
26
+ value: [],
27
+ writable: true
28
+ });
29
+ let start = 0;
30
+ let separator = "";
31
+ for (let i = 0; i < text.length; i++) {
32
+ const ch = text[i];
33
+ if (!isSentenceTerminator(ch)) continue;
34
+ let end = i;
35
+ let hasUnicodeTerminator = UNICODE_SENTENCE_TERMINATORS.includes(ch);
36
+ while (end + 1 < text.length && isSentenceTerminator(text[end + 1])) {
37
+ end++;
38
+ hasUnicodeTerminator ||= UNICODE_SENTENCE_TERMINATORS.includes(text[end]);
39
+ }
40
+ const isFullwidthDecimal = ch === "\uFF0E" && DIGITS.includes(text[i - 1] ?? "") && DIGITS.includes(text[end + 1] ?? "");
41
+ while (end + 1 < text.length && CLOSING_PUNCTUATION.includes(text[end + 1])) {
42
+ end++;
43
+ }
44
+ const after = text[end + 1];
45
+ const boundary = !isFullwidthDecimal && (hasUnicodeTerminator || after === void 0 || /\s/u.test(after));
46
+ if (boundary) {
47
+ const sentence = text.slice(start, end + 1).trim();
48
+ if (sentence.length > 0) {
49
+ sentences.push(sentence);
50
+ if (sentences.length > 1) sentences.separators.push(separator);
51
+ }
52
+ let nextStart = end + 1;
53
+ while (nextStart < text.length && /\s/u.test(text[nextStart])) nextStart++;
54
+ separator = text.slice(end + 1, nextStart);
55
+ start = nextStart;
56
+ }
57
+ i = end;
58
+ }
59
+ const remaining = text.slice(start).trim();
60
+ if (remaining.length > 0) {
61
+ sentences.push(remaining);
62
+ if (sentences.length > 1) sentences.separators.push(separator);
63
+ }
64
+ return sentences;
65
+ }
66
+ function splitSentences(text) {
67
+ const canUseSegmenter = SENTENCE_SEGMENTER !== void 0 && !/\s/u.test(text) && [...text].some((character) => UNICODE_SENTENCE_TERMINATORS.includes(character));
68
+ if (canUseSegmenter) {
69
+ const segments = Array.from(
70
+ SENTENCE_SEGMENTER.segment(text),
71
+ ({ segment }) => segment.trim()
72
+ ).filter((segment) => segment.length > 0);
73
+ if (segments.length > 1 && segments.slice(0, -1).every(
74
+ (segment) => [...segment].some(
75
+ (character) => UNICODE_SENTENCE_TERMINATORS.includes(character)
76
+ )
77
+ )) {
78
+ Object.defineProperty(segments, "separators", {
79
+ value: Array(segments.length - 1).fill(""),
80
+ writable: true
81
+ });
82
+ return segments;
83
+ }
84
+ }
85
+ return splitSentencesFallback(text);
86
+ }
87
+ function endsWithoutSpace(text) {
88
+ let index = text.length - 1;
89
+ while (index >= 0 && CLOSING_PUNCTUATION.includes(text[index])) index--;
90
+ const terminator = text[index] ?? "";
91
+ if (CJK_NO_SPACE_TERMINATORS.includes(terminator)) {
92
+ return isCjk(text[index - 1] ?? "");
93
+ }
94
+ return terminator === "\u2026" && isCjk(text[index - 1] ?? "");
95
+ }
96
+ function joinSentences(sentences) {
97
+ let result = "";
98
+ const separators = sentences.separators;
99
+ for (let i = 0; i < sentences.length; i++) {
100
+ const sentence = sentences[i];
101
+ if (result.length > 0) {
102
+ const separator = separators?.[i - 1];
103
+ result += separator ?? (endsWithoutSpace(result) ? "" : " ");
104
+ }
105
+ result += sentence;
106
+ }
107
+ return result;
108
+ }
109
+ function chunkContent(content, config = DEFAULT_CHUNKING_CONFIG) {
110
+ const totalTokens = estimateTokenCount(content);
111
+ if (totalTokens < config.minTokens) {
112
+ return {
113
+ chunked: false,
114
+ chunks: [{
115
+ content,
116
+ index: 0,
117
+ tokenCount: totalTokens
118
+ }]
119
+ };
120
+ }
121
+ const sentences = splitSentences(content);
122
+ if (sentences.length <= 1) {
123
+ return {
124
+ chunked: false,
125
+ chunks: [{
126
+ content,
127
+ index: 0,
128
+ tokenCount: totalTokens
129
+ }]
130
+ };
131
+ }
132
+ const chunks = [];
133
+ let currentChunkSentences = [];
134
+ let currentTokens = 0;
135
+ let chunkIndex = 0;
136
+ for (let i = 0; i < sentences.length; i++) {
137
+ const sentence = sentences[i];
138
+ const sentenceTokens = estimateTokenCount(sentence);
139
+ currentChunkSentences.push(sentence);
140
+ currentTokens += sentenceTokens;
141
+ const atTarget = currentTokens >= config.targetTokens;
142
+ const isLastSentence = i === sentences.length - 1;
143
+ if (atTarget || isLastSentence) {
144
+ const chunkContent2 = joinSentences(currentChunkSentences);
145
+ chunks.push({
146
+ content: chunkContent2,
147
+ index: chunkIndex,
148
+ tokenCount: estimateTokenCount(chunkContent2)
149
+ });
150
+ chunkIndex++;
151
+ if (!isLastSentence) {
152
+ const overlapCount = Math.min(config.overlapSentences, currentChunkSentences.length);
153
+ if (overlapCount <= 0) {
154
+ currentChunkSentences = [];
155
+ currentTokens = 0;
156
+ } else {
157
+ currentChunkSentences = currentChunkSentences.slice(-overlapCount);
158
+ currentTokens = currentChunkSentences.reduce((sum, s) => sum + estimateTokenCount(s), 0);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ return {
164
+ chunked: chunks.length > 1,
165
+ chunks
166
+ };
167
+ }
168
+ function reassembleChunks(chunks) {
169
+ if (chunks.length === 0) return "";
170
+ if (chunks.length === 1) return chunks[0];
171
+ const result = [chunks[0]];
172
+ for (let i = 1; i < chunks.length; i++) {
173
+ const prevChunk = chunks[i - 1];
174
+ const currChunk = chunks[i];
175
+ const prevSentences = splitSentences(prevChunk);
176
+ const currSentences = splitSentences(currChunk);
177
+ let overlapCount = 0;
178
+ for (let j = 0; j < Math.min(prevSentences.length, currSentences.length); j++) {
179
+ const prevEnd = prevSentences.slice(-(j + 1));
180
+ const currStart = currSentences.slice(0, j + 1);
181
+ if (joinSentences(prevEnd) === joinSentences(currStart)) {
182
+ overlapCount = j + 1;
183
+ }
184
+ }
185
+ if (overlapCount > 0 && overlapCount < currSentences.length) {
186
+ result.push(joinSentences(currSentences.slice(overlapCount)));
187
+ } else if (overlapCount === 0) {
188
+ result.push(currChunk);
189
+ }
190
+ }
191
+ return joinSentences(result);
192
+ }
193
+
194
+ export {
195
+ DEFAULT_CHUNKING_CONFIG,
196
+ splitSentences,
197
+ joinSentences,
198
+ chunkContent,
199
+ reassembleChunks
200
+ };
201
+ //# sourceMappingURL=chunk-6TBIWIAG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chunking.ts"],"sourcesContent":["/**\n * Automatic Chunking with Overlap (Phase 2A)\n *\n * Sentence-boundary chunking for long memories.\n * Preserves coherent thoughts by never splitting mid-sentence.\n */\n\nimport { estimateTokenCount } from \"./token-estimate.js\";\n\nexport interface ChunkingConfig {\n /** Target tokens per chunk (default 200) */\n targetTokens: number;\n /** Minimum tokens to trigger chunking (default 150) */\n minTokens: number;\n /** Number of sentences to overlap between chunks (default 2) */\n overlapSentences: number;\n}\n\nexport interface Chunk {\n /** Chunk content */\n content: string;\n /** 0-based index */\n index: number;\n /** Approximate token count */\n tokenCount: number;\n}\n\nexport interface ChunkResult {\n /** Whether content was chunked */\n chunked: boolean;\n /** Array of chunks (length 1 if not chunked) */\n chunks: Chunk[];\n}\n\n/** Default chunking configuration */\nexport const DEFAULT_CHUNKING_CONFIG: ChunkingConfig = {\n targetTokens: 200,\n minTokens: 150,\n overlapSentences: 2,\n};\n\n/**\n * Split text into sentences.\n *\n * The scan stays linear and does not use a backtracking regular expression.\n * ASCII punctuation keeps its old whitespace rule. Unicode terminators also\n * split when the next sentence starts immediately, as in CJK text.\n */\nconst UNICODE_SENTENCE_TERMINATORS = \"。.!?؟۔।॥。…\";\nconst ASCII_SENTENCE_TERMINATORS = \".!?\";\nconst CJK_NO_SPACE_TERMINATORS = \"。.!?。\";\nconst CLOSING_PUNCTUATION = \"\\\"'”’»」』)]】〉》)]}\";\nconst DIGITS = \"01234567890123456789\";\nconst SENTENCE_SEGMENTER =\n typeof Intl.Segmenter === \"function\"\n ? new Intl.Segmenter(undefined, { granularity: \"sentence\" })\n : undefined;\n\nfunction isSentenceTerminator(character: string): boolean {\n return (\n ASCII_SENTENCE_TERMINATORS.includes(character) ||\n UNICODE_SENTENCE_TERMINATORS.includes(character)\n );\n}\n\nfunction isCjk(character: string): boolean {\n return /[\\u3000-\\u9fff\\uf900-\\ufaff\\uac00-\\ud7af]/u.test(character);\n}\n\ntype SentenceList = string[] & { separators: string[] };\n\nfunction splitSentencesFallback(text: string): SentenceList {\n const sentences = [] as unknown as SentenceList;\n Object.defineProperty(sentences, \"separators\", {\n value: [],\n writable: true,\n });\n let start = 0;\n let separator = \"\";\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (!isSentenceTerminator(ch)) continue;\n\n let end = i;\n let hasUnicodeTerminator = UNICODE_SENTENCE_TERMINATORS.includes(ch);\n while (end + 1 < text.length && isSentenceTerminator(text[end + 1])) {\n end++;\n hasUnicodeTerminator ||= UNICODE_SENTENCE_TERMINATORS.includes(text[end]);\n }\n\n const isFullwidthDecimal =\n ch === \".\" &&\n DIGITS.includes(text[i - 1] ?? \"\") &&\n DIGITS.includes(text[end + 1] ?? \"\");\n while (end + 1 < text.length && CLOSING_PUNCTUATION.includes(text[end + 1])) {\n end++;\n }\n\n const after = text[end + 1];\n const boundary =\n !isFullwidthDecimal &&\n (hasUnicodeTerminator || after === undefined || /\\s/u.test(after));\n if (boundary) {\n const sentence = text.slice(start, end + 1).trim();\n if (sentence.length > 0) {\n sentences.push(sentence);\n if (sentences.length > 1) sentences.separators.push(separator);\n }\n let nextStart = end + 1;\n while (nextStart < text.length && /\\s/u.test(text[nextStart])) nextStart++;\n separator = text.slice(end + 1, nextStart);\n start = nextStart;\n }\n i = end;\n }\n\n const remaining = text.slice(start).trim();\n if (remaining.length > 0) {\n sentences.push(remaining);\n if (sentences.length > 1) sentences.separators.push(separator);\n }\n return sentences;\n}\nexport function splitSentences(text: string): string[] {\n const canUseSegmenter =\n SENTENCE_SEGMENTER !== undefined &&\n !/\\s/u.test(text) &&\n [...text].some((character) => UNICODE_SENTENCE_TERMINATORS.includes(character));\n if (canUseSegmenter) {\n const segments = Array.from(SENTENCE_SEGMENTER.segment(text), ({ segment }) =>\n segment.trim(),\n ).filter((segment) => segment.length > 0) as SentenceList;\n if (\n segments.length > 1 &&\n segments.slice(0, -1).every((segment) =>\n [...segment].some((character) =>\n UNICODE_SENTENCE_TERMINATORS.includes(character),\n ),\n )\n ) {\n Object.defineProperty(segments, \"separators\", {\n value: Array(segments.length - 1).fill(\"\"),\n writable: true,\n });\n return segments;\n }\n }\n return splitSentencesFallback(text);\n}\n\nfunction endsWithoutSpace(text: string): boolean {\n let index = text.length - 1;\n while (index >= 0 && CLOSING_PUNCTUATION.includes(text[index])) index--;\n const terminator = text[index] ?? \"\";\n if (CJK_NO_SPACE_TERMINATORS.includes(terminator)) {\n return isCjk(text[index - 1] ?? \"\");\n }\n return terminator === \"…\" && isCjk(text[index - 1] ?? \"\");\n}\nexport function joinSentences(sentences: string[]): string {\n let result = \"\";\n const separators = (sentences as Partial<SentenceList>).separators;\n for (let i = 0; i < sentences.length; i++) {\n const sentence = sentences[i];\n if (result.length > 0) {\n const separator = separators?.[i - 1];\n result += separator ?? (endsWithoutSpace(result) ? \"\" : \" \");\n }\n result += sentence;\n }\n return result;\n}\n\n\n/**\n * Chunk content into overlapping segments at sentence boundaries.\n *\n * @param content - The text content to chunk\n * @param config - Chunking configuration\n * @returns ChunkResult with chunks array\n */\nexport function chunkContent(\n content: string,\n config: ChunkingConfig = DEFAULT_CHUNKING_CONFIG,\n): ChunkResult {\n const totalTokens = estimateTokenCount(content);\n\n // Don't chunk if below minimum threshold\n if (totalTokens < config.minTokens) {\n return {\n chunked: false,\n chunks: [{\n content,\n index: 0,\n tokenCount: totalTokens,\n }],\n };\n }\n\n const sentences = splitSentences(content);\n\n // If we couldn't split into multiple sentences, don't chunk\n if (sentences.length <= 1) {\n return {\n chunked: false,\n chunks: [{\n content,\n index: 0,\n tokenCount: totalTokens,\n }],\n };\n }\n\n const chunks: Chunk[] = [];\n let currentChunkSentences: string[] = [];\n let currentTokens = 0;\n let chunkIndex = 0;\n\n for (let i = 0; i < sentences.length; i++) {\n const sentence = sentences[i];\n const sentenceTokens = estimateTokenCount(sentence);\n\n // Add sentence to current chunk\n currentChunkSentences.push(sentence);\n currentTokens += sentenceTokens;\n\n // Check if we've reached target size (with some flexibility)\n // Allow going over by up to 50% to avoid tiny final chunks\n const atTarget = currentTokens >= config.targetTokens;\n const isLastSentence = i === sentences.length - 1;\n\n if (atTarget || isLastSentence) {\n // Create chunk from accumulated sentences\n const chunkContent = joinSentences(currentChunkSentences);\n chunks.push({\n content: chunkContent,\n index: chunkIndex,\n tokenCount: estimateTokenCount(chunkContent),\n });\n chunkIndex++;\n\n // Start new chunk with overlap (if not at end)\n if (!isLastSentence) {\n // Keep last N sentences for overlap.\n // Guard: slice(-0) === slice(0), which returns the ENTIRE array\n // (CLAUDE.md gotcha #27). When overlapSentences is 0, clear fully.\n const overlapCount = Math.min(config.overlapSentences, currentChunkSentences.length);\n if (overlapCount <= 0) {\n currentChunkSentences = [];\n currentTokens = 0;\n } else {\n currentChunkSentences = currentChunkSentences.slice(-overlapCount);\n currentTokens = currentChunkSentences.reduce((sum, s) => sum + estimateTokenCount(s), 0);\n }\n }\n }\n }\n\n // Only consider it \"chunked\" if we got multiple chunks\n return {\n chunked: chunks.length > 1,\n chunks,\n };\n}\n\n/**\n * Get parent content by reassembling chunks.\n * Useful for displaying full context when a chunk is retrieved.\n *\n * @param chunks - Array of chunk contents in order\n * @returns Reassembled parent content (with overlap removed)\n */\nexport function reassembleChunks(chunks: string[]): string {\n if (chunks.length === 0) return \"\";\n if (chunks.length === 1) return chunks[0];\n\n // For overlapping chunks, we need to deduplicate\n // Simple approach: use full first chunk, then non-overlapping parts of subsequent chunks\n // This is imperfect but handles most cases\n const result: string[] = [chunks[0]];\n\n for (let i = 1; i < chunks.length; i++) {\n const prevChunk = chunks[i - 1];\n const currChunk = chunks[i];\n\n // Find overlap by looking for common suffix/prefix\n // Try to find where the previous chunk ends in the current chunk\n const prevSentences = splitSentences(prevChunk);\n const currSentences = splitSentences(currChunk);\n\n // Find how many sentences from prev are at the start of curr\n let overlapCount = 0;\n for (let j = 0; j < Math.min(prevSentences.length, currSentences.length); j++) {\n // Check if last N sentences of prev match first N sentences of curr\n const prevEnd = prevSentences.slice(-(j + 1));\n const currStart = currSentences.slice(0, j + 1);\n\n if (joinSentences(prevEnd) === joinSentences(currStart)) {\n overlapCount = j + 1;\n }\n }\n\n // Add non-overlapping portion\n if (overlapCount > 0 && overlapCount < currSentences.length) {\n result.push(joinSentences(currSentences.slice(overlapCount)));\n } else if (overlapCount === 0) {\n // No detected overlap, add full chunk\n result.push(currChunk);\n }\n // If overlapCount === currSentences.length, skip (fully contained)\n }\n\n return joinSentences(result);\n}\n"],"mappings":";;;;;AAmCO,IAAM,0BAA0C;AAAA,EACrD,cAAc;AAAA,EACd,WAAW;AAAA,EACX,kBAAkB;AACpB;AASA,IAAM,+BAA+B;AACrC,IAAM,6BAA6B;AACnC,IAAM,2BAA2B;AACjC,IAAM,sBAAsB;AAC5B,IAAM,SAAS;AACf,IAAM,qBACJ,OAAO,KAAK,cAAc,aACtB,IAAI,KAAK,UAAU,QAAW,EAAE,aAAa,WAAW,CAAC,IACzD;AAEN,SAAS,qBAAqB,WAA4B;AACxD,SACE,2BAA2B,SAAS,SAAS,KAC7C,6BAA6B,SAAS,SAAS;AAEnD;AAEA,SAAS,MAAM,WAA4B;AACzC,SAAO,6CAA6C,KAAK,SAAS;AACpE;AAIA,SAAS,uBAAuB,MAA4B;AAC1D,QAAM,YAAY,CAAC;AACnB,SAAO,eAAe,WAAW,cAAc;AAAA,IAC7C,OAAO,CAAC;AAAA,IACR,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,QAAQ;AACZ,MAAI,YAAY;AAChB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,KAAK,KAAK,CAAC;AACjB,QAAI,CAAC,qBAAqB,EAAE,EAAG;AAE/B,QAAI,MAAM;AACV,QAAI,uBAAuB,6BAA6B,SAAS,EAAE;AACnE,WAAO,MAAM,IAAI,KAAK,UAAU,qBAAqB,KAAK,MAAM,CAAC,CAAC,GAAG;AACnE;AACA,+BAAyB,6BAA6B,SAAS,KAAK,GAAG,CAAC;AAAA,IAC1E;AAEA,UAAM,qBACJ,OAAO,YACP,OAAO,SAAS,KAAK,IAAI,CAAC,KAAK,EAAE,KACjC,OAAO,SAAS,KAAK,MAAM,CAAC,KAAK,EAAE;AACrC,WAAO,MAAM,IAAI,KAAK,UAAU,oBAAoB,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3E;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,UAAM,WACJ,CAAC,uBACA,wBAAwB,UAAU,UAAa,MAAM,KAAK,KAAK;AAClE,QAAI,UAAU;AACZ,YAAM,WAAW,KAAK,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AACjD,UAAI,SAAS,SAAS,GAAG;AACvB,kBAAU,KAAK,QAAQ;AACvB,YAAI,UAAU,SAAS,EAAG,WAAU,WAAW,KAAK,SAAS;AAAA,MAC/D;AACA,UAAI,YAAY,MAAM;AACtB,aAAO,YAAY,KAAK,UAAU,MAAM,KAAK,KAAK,SAAS,CAAC,EAAG;AAC/D,kBAAY,KAAK,MAAM,MAAM,GAAG,SAAS;AACzC,cAAQ;AAAA,IACV;AACA,QAAI;AAAA,EACN;AAEA,QAAM,YAAY,KAAK,MAAM,KAAK,EAAE,KAAK;AACzC,MAAI,UAAU,SAAS,GAAG;AACxB,cAAU,KAAK,SAAS;AACxB,QAAI,UAAU,SAAS,EAAG,WAAU,WAAW,KAAK,SAAS;AAAA,EAC/D;AACA,SAAO;AACT;AACO,SAAS,eAAe,MAAwB;AACrD,QAAM,kBACJ,uBAAuB,UACvB,CAAC,MAAM,KAAK,IAAI,KAChB,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,cAAc,6BAA6B,SAAS,SAAS,CAAC;AAChF,MAAI,iBAAiB;AACnB,UAAM,WAAW,MAAM;AAAA,MAAK,mBAAmB,QAAQ,IAAI;AAAA,MAAG,CAAC,EAAE,QAAQ,MACvE,QAAQ,KAAK;AAAA,IACf,EAAE,OAAO,CAAC,YAAY,QAAQ,SAAS,CAAC;AACxC,QACE,SAAS,SAAS,KAClB,SAAS,MAAM,GAAG,EAAE,EAAE;AAAA,MAAM,CAAC,YAC3B,CAAC,GAAG,OAAO,EAAE;AAAA,QAAK,CAAC,cACjB,6BAA6B,SAAS,SAAS;AAAA,MACjD;AAAA,IACF,GACA;AACA,aAAO,eAAe,UAAU,cAAc;AAAA,QAC5C,OAAO,MAAM,SAAS,SAAS,CAAC,EAAE,KAAK,EAAE;AAAA,QACzC,UAAU;AAAA,MACZ,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,uBAAuB,IAAI;AACpC;AAEA,SAAS,iBAAiB,MAAuB;AAC/C,MAAI,QAAQ,KAAK,SAAS;AAC1B,SAAO,SAAS,KAAK,oBAAoB,SAAS,KAAK,KAAK,CAAC,EAAG;AAChE,QAAM,aAAa,KAAK,KAAK,KAAK;AAClC,MAAI,yBAAyB,SAAS,UAAU,GAAG;AACjD,WAAO,MAAM,KAAK,QAAQ,CAAC,KAAK,EAAE;AAAA,EACpC;AACA,SAAO,eAAe,YAAO,MAAM,KAAK,QAAQ,CAAC,KAAK,EAAE;AAC1D;AACO,SAAS,cAAc,WAA6B;AACzD,MAAI,SAAS;AACb,QAAM,aAAc,UAAoC;AACxD,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,WAAW,UAAU,CAAC;AAC5B,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,YAAY,aAAa,IAAI,CAAC;AACpC,gBAAU,cAAc,iBAAiB,MAAM,IAAI,KAAK;AAAA,IAC1D;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAUO,SAAS,aACd,SACA,SAAyB,yBACZ;AACb,QAAM,cAAc,mBAAmB,OAAO;AAG9C,MAAI,cAAc,OAAO,WAAW;AAClC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,QACP;AAAA,QACA,OAAO;AAAA,QACP,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,eAAe,OAAO;AAGxC,MAAI,UAAU,UAAU,GAAG;AACzB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,QACP;AAAA,QACA,OAAO;AAAA,QACP,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,SAAkB,CAAC;AACzB,MAAI,wBAAkC,CAAC;AACvC,MAAI,gBAAgB;AACpB,MAAI,aAAa;AAEjB,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,UAAM,WAAW,UAAU,CAAC;AAC5B,UAAM,iBAAiB,mBAAmB,QAAQ;AAGlD,0BAAsB,KAAK,QAAQ;AACnC,qBAAiB;AAIjB,UAAM,WAAW,iBAAiB,OAAO;AACzC,UAAM,iBAAiB,MAAM,UAAU,SAAS;AAEhD,QAAI,YAAY,gBAAgB;AAE9B,YAAMA,gBAAe,cAAc,qBAAqB;AACxD,aAAO,KAAK;AAAA,QACV,SAASA;AAAA,QACT,OAAO;AAAA,QACP,YAAY,mBAAmBA,aAAY;AAAA,MAC7C,CAAC;AACD;AAGA,UAAI,CAAC,gBAAgB;AAInB,cAAM,eAAe,KAAK,IAAI,OAAO,kBAAkB,sBAAsB,MAAM;AACnF,YAAI,gBAAgB,GAAG;AACrB,kCAAwB,CAAC;AACzB,0BAAgB;AAAA,QAClB,OAAO;AACL,kCAAwB,sBAAsB,MAAM,CAAC,YAAY;AACjE,0BAAgB,sBAAsB,OAAO,CAAC,KAAK,MAAM,MAAM,mBAAmB,CAAC,GAAG,CAAC;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AAAA,IACL,SAAS,OAAO,SAAS;AAAA,IACzB;AAAA,EACF;AACF;AASO,SAAS,iBAAiB,QAA0B;AACzD,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,MAAI,OAAO,WAAW,EAAG,QAAO,OAAO,CAAC;AAKxC,QAAM,SAAmB,CAAC,OAAO,CAAC,CAAC;AAEnC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,YAAY,OAAO,IAAI,CAAC;AAC9B,UAAM,YAAY,OAAO,CAAC;AAI1B,UAAM,gBAAgB,eAAe,SAAS;AAC9C,UAAM,gBAAgB,eAAe,SAAS;AAG9C,QAAI,eAAe;AACnB,aAAS,IAAI,GAAG,IAAI,KAAK,IAAI,cAAc,QAAQ,cAAc,MAAM,GAAG,KAAK;AAE7E,YAAM,UAAU,cAAc,MAAM,EAAE,IAAI,EAAE;AAC5C,YAAM,YAAY,cAAc,MAAM,GAAG,IAAI,CAAC;AAE9C,UAAI,cAAc,OAAO,MAAM,cAAc,SAAS,GAAG;AACvD,uBAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAGA,QAAI,eAAe,KAAK,eAAe,cAAc,QAAQ;AAC3D,aAAO,KAAK,cAAc,cAAc,MAAM,YAAY,CAAC,CAAC;AAAA,IAC9D,WAAW,iBAAiB,GAAG;AAE7B,aAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EAEF;AAEA,SAAO,cAAc,MAAM;AAC7B;","names":["chunkContent"]}
@@ -9,14 +9,14 @@ import {
9
9
  } from "./chunk-666A3MOW.js";
10
10
  import {
11
11
  rebuildMemoryLifecycleLedger
12
- } from "./chunk-DNC4A7RS.js";
12
+ } from "./chunk-OU7RWWW6.js";
13
13
  import {
14
14
  planNamespaceMaintenance,
15
15
  runNamespaceMaintenanceBatchPlan
16
- } from "./chunk-4YZCIK5E.js";
16
+ } from "./chunk-EZXGJJXM.js";
17
17
  import {
18
18
  rebuildMemoryProjection
19
- } from "./chunk-IT57AOMC.js";
19
+ } from "./chunk-AH2NX6S7.js";
20
20
  import {
21
21
  activityDayWindow,
22
22
  activityDigestPath,
@@ -1719,4 +1719,4 @@ export {
1719
1719
  ActivitySyncScheduler,
1720
1720
  MaintenanceScheduler
1721
1721
  };
1722
- //# sourceMappingURL=chunk-4O6R3GPK.js.map
1722
+ //# sourceMappingURL=chunk-6W2ISYUV.js.map
@@ -2,10 +2,10 @@ import {
2
2
  discoverMemoryExtensions,
3
3
  renderExtensionsBlock,
4
4
  resolveExtensionsRoot
5
- } from "./chunk-JLNBQWZ2.js";
5
+ } from "./chunk-5JMAGU26.js";
6
6
  import {
7
7
  runPostConsolidationMaterialize
8
- } from "./chunk-VYIXCMUP.js";
8
+ } from "./chunk-KBIIE57I.js";
9
9
  import {
10
10
  isSemanticConsolidationLlmOperator
11
11
  } from "./chunk-G7D6GZ5J.js";
@@ -220,4 +220,4 @@ export {
220
220
  buildExtensionsBlockForConsolidation,
221
221
  materializeAfterSemanticConsolidation
222
222
  };
223
- //# sourceMappingURL=chunk-3AJOJOFP.js.map
223
+ //# sourceMappingURL=chunk-77DAFTUU.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  parseXrayFormat
3
- } from "./chunk-U7BMN33M.js";
3
+ } from "./chunk-UBSM6TZP.js";
4
4
  import {
5
5
  RECALL_DISCLOSURE_LEVELS,
6
6
  isRecallDisclosure
7
- } from "./chunk-5QHDXMXP.js";
7
+ } from "./chunk-LLZKOSGM.js";
8
8
 
9
9
  // src/recall-xray-cli.ts
10
10
  function parseXrayDisclosureFlag(value) {
@@ -50,4 +50,4 @@ export {
50
50
  parseXrayBudgetFlag,
51
51
  parseXrayCliOptions
52
52
  };
53
- //# sourceMappingURL=chunk-IKT6ZVO7.js.map
53
+ //# sourceMappingURL=chunk-7DHFB5SG.js.map
@@ -2,7 +2,7 @@ import {
2
2
  SupportPassportError,
3
3
  SupportPassportOwnerCreateGrantRequestSchema,
4
4
  getOperation
5
- } from "./chunk-CZUHNJHX.js";
5
+ } from "./chunk-6C7Q6NG3.js";
6
6
 
7
7
  // src/support-passport/access-http.ts
8
8
  var OWNER_ROOT = "/engram/v1/support-passport";
@@ -137,4 +137,4 @@ export {
137
137
  SUPPORT_PASSPORT_OWNER_HTTP_ROUTES,
138
138
  handleSupportPassportOwnerHttp
139
139
  };
140
- //# sourceMappingURL=chunk-SFR7J2G6.js.map
140
+ //# sourceMappingURL=chunk-7G34CBKS.js.map
@@ -7,10 +7,10 @@ import {
7
7
  import {
8
8
  listMemoryGovernanceRuns,
9
9
  readMemoryGovernanceRunArtifact
10
- } from "./chunk-6RK2X7BR.js";
10
+ } from "./chunk-G3JFFUKR.js";
11
11
  import {
12
12
  StorageManager
13
- } from "./chunk-YTZA7U6Q.js";
13
+ } from "./chunk-2VHCLHZ5.js";
14
14
  import {
15
15
  normalizeProjectionPreview,
16
16
  normalizeProjectionTags
@@ -1005,4 +1005,4 @@ export {
1005
1005
  verifyMemoryProjection,
1006
1006
  repairMemoryProjection
1007
1007
  };
1008
- //# sourceMappingURL=chunk-IT57AOMC.js.map
1008
+ //# sourceMappingURL=chunk-AH2NX6S7.js.map