@remnic/core 9.69.27 → 9.69.29

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 (388) hide show
  1. package/dist/access-admin-ops-surface.d.ts +1 -1
  2. package/dist/access-admin-ops-surface.js +57 -57
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-authorization-probe.d.ts +1 -1
  5. package/dist/access-authorization-probe.js +58 -58
  6. package/dist/access-boundary.d.ts +1 -1
  7. package/dist/access-boundary.js +57 -57
  8. package/dist/access-cli.js +140 -139
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-coding-context-resolution.js +4 -4
  11. package/dist/access-extraction-force-flush.d.ts +1 -1
  12. package/dist/access-extraction-force-flush.js +57 -57
  13. package/dist/access-http-briefing.d.ts +1 -1
  14. package/dist/access-http-briefing.js +58 -58
  15. package/dist/access-http-lcm-compaction.d.ts +1 -1
  16. package/dist/access-http-lifecycle-flush.d.ts +1 -1
  17. package/dist/access-http-offline-stream.d.ts +1 -1
  18. package/dist/access-http-query.js +59 -59
  19. package/dist/access-http.d.ts +2 -2
  20. package/dist/access-http.js +76 -76
  21. package/dist/access-identity-continuity-surface.js +57 -57
  22. package/dist/access-lcm-surface.d.ts +1 -1
  23. package/dist/access-lcm-surface.js +57 -57
  24. package/dist/access-mcp.d.ts +1 -1
  25. package/dist/access-mcp.js +65 -65
  26. package/dist/access-namespace-preflight.js +57 -57
  27. package/dist/access-observe-transcript.js +4 -4
  28. package/dist/access-observe-write-surface.d.ts +1 -1
  29. package/dist/access-observe-write-surface.js +57 -57
  30. package/dist/access-offline-manifest.js +8 -8
  31. package/dist/access-operations-batch.js +59 -59
  32. package/dist/access-operations.d.ts +6 -6
  33. package/dist/access-operations.js +64 -64
  34. package/dist/access-recall-concurrency.d.ts +1 -1
  35. package/dist/access-recall-concurrency.js +57 -57
  36. package/dist/access-recall-response.d.ts +1 -1
  37. package/dist/access-recall-response.js +57 -57
  38. package/dist/access-recall-surface.d.ts +1 -1
  39. package/dist/access-recall-surface.js +57 -57
  40. package/dist/access-schema.d.ts +91 -91
  41. package/dist/access-schema.js +3 -3
  42. package/dist/access-service-helpers.d.ts +1 -1
  43. package/dist/access-service.d.ts +1 -1
  44. package/dist/access-service.js +57 -57
  45. package/dist/access-surface-catalog.d.ts +1 -1
  46. package/dist/access-surface-catalog.js +59 -59
  47. package/dist/active-recall.js +8 -8
  48. package/dist/adapters/index.js +4 -4
  49. package/dist/adapters/registry.js +2 -2
  50. package/dist/{auto-sync-WNGG2GC2.js → auto-sync-NSHLUAQI.js} +7 -7
  51. package/dist/briefing.js +20 -20
  52. package/dist/buffer.js +8 -8
  53. package/dist/calibration.js +4 -4
  54. package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
  55. package/dist/causal-consolidation.js +22 -22
  56. package/dist/{chunk-GRCREL6Q.js → chunk-22JQEBN3.js} +9 -9
  57. package/dist/{chunk-6LLLREDJ.js → chunk-2E3CG66I.js} +2 -2
  58. package/dist/{chunk-OO42R444.js → chunk-2MFH376S.js} +3 -3
  59. package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
  60. package/dist/{chunk-NXH34IPL.js → chunk-353KGBKY.js} +2 -2
  61. package/dist/{chunk-DZD3WGCD.js → chunk-3JVLGJCY.js} +2 -2
  62. package/dist/{chunk-W24T5YMW.js → chunk-47DEYNMR.js} +2 -2
  63. package/dist/chunk-4NZQ7IID.js +63 -0
  64. package/dist/chunk-4NZQ7IID.js.map +1 -0
  65. package/dist/{chunk-QOOBICJF.js → chunk-565C6ZFO.js} +2 -2
  66. package/dist/{chunk-ZY4DSWZ5.js → chunk-5OOSADXP.js} +5 -5
  67. package/dist/{chunk-EYIEWJNI.js → chunk-6KH5NLQS.js} +2 -2
  68. package/dist/{chunk-EMDLM3LW.js → chunk-7IRZK6MM.js} +2 -2
  69. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  70. package/dist/{chunk-6CVNSDCZ.js → chunk-7VJXIDOC.js} +12 -12
  71. package/dist/{chunk-SO4IYSGT.js → chunk-A5JPK3MZ.js} +75 -75
  72. package/dist/{chunk-IVKIODHO.js → chunk-A7XEPMQ6.js} +5 -5
  73. package/dist/{chunk-K6MV3TRQ.js → chunk-ADXCCZL2.js} +2 -2
  74. package/dist/{chunk-SJDQ5RSN.js → chunk-AOCP6JA7.js} +4 -4
  75. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  76. package/dist/{chunk-GNMELJGM.js → chunk-AYAIV5V5.js} +6 -6
  77. package/dist/{chunk-ND6IQGSZ.js → chunk-BA6WOZOT.js} +2 -2
  78. package/dist/{chunk-JI7U6AS3.js → chunk-C6FQJ52H.js} +2 -2
  79. package/dist/{chunk-IN673LEP.js → chunk-CARRTDKC.js} +2 -2
  80. package/dist/{chunk-6NXSYYGP.js → chunk-CBCNKKZD.js} +2 -2
  81. package/dist/{chunk-DXFG2VGN.js → chunk-CGC5UQCF.js} +2 -2
  82. package/dist/{chunk-QBH7M7Q4.js → chunk-CLALC6ZB.js} +2 -2
  83. package/dist/{chunk-YSSAGB2O.js → chunk-CLLPJ6QT.js} +5 -5
  84. package/dist/{chunk-KAXCYM66.js → chunk-D5LORF7A.js} +3 -3
  85. package/dist/{chunk-CEH2AFXG.js → chunk-DBQWVT2H.js} +7 -7
  86. package/dist/{chunk-XSTNGNJP.js → chunk-DCJ3YFIC.js} +2 -2
  87. package/dist/{chunk-MWN6QEI2.js → chunk-DITMGZOL.js} +2 -2
  88. package/dist/{chunk-LVE64P5Y.js → chunk-E2ZHGBAK.js} +2 -2
  89. package/dist/{chunk-2EKJDQZB.js → chunk-EZZV7OQL.js} +2 -2
  90. package/dist/{chunk-N3SS45OW.js → chunk-FCSZ4K2X.js} +3 -3
  91. package/dist/{chunk-TWF35IC6.js → chunk-FDLDOEO6.js} +28 -23
  92. package/dist/chunk-FDLDOEO6.js.map +1 -0
  93. package/dist/{chunk-5ATKSPEQ.js → chunk-FGGYSN4P.js} +2 -2
  94. package/dist/{chunk-2Z4GS5E6.js → chunk-FHQSPTPZ.js} +2 -2
  95. package/dist/{chunk-3GGUMRS4.js → chunk-FJ5B36V2.js} +2 -2
  96. package/dist/{chunk-5IEV3YBY.js → chunk-GAYZTUIF.js} +2 -2
  97. package/dist/{chunk-KH6PK4EQ.js → chunk-GBYCFJGV.js} +6 -6
  98. package/dist/{chunk-6VF3R3XQ.js → chunk-GCRGBE72.js} +2 -2
  99. package/dist/{chunk-6GUG4YNM.js → chunk-GGRRF4PZ.js} +2 -2
  100. package/dist/{chunk-ZUNNRGJX.js → chunk-GL4EC4RG.js} +8 -8
  101. package/dist/{chunk-UCKYTA2T.js → chunk-GTWHVXPA.js} +3 -3
  102. package/dist/{chunk-XSGUMQQQ.js → chunk-GVG3JYBI.js} +4 -4
  103. package/dist/{chunk-MY5EDR46.js → chunk-GY5WZBA6.js} +2 -2
  104. package/dist/{chunk-3GCK6ONU.js → chunk-HK32G473.js} +2 -2
  105. package/dist/{chunk-EWCNCQOU.js → chunk-HRICDLBE.js} +2 -2
  106. package/dist/{chunk-46ZPIGWI.js → chunk-HY55QQD7.js} +2 -2
  107. package/dist/{chunk-WMLEPWMO.js → chunk-I27RSQRR.js} +2 -2
  108. package/dist/{chunk-QIEUU4UK.js → chunk-I55KAVET.js} +2 -2
  109. package/dist/{chunk-XM24CDZX.js → chunk-IY2FVXM6.js} +3 -3
  110. package/dist/{chunk-CGJV2YIY.js → chunk-J5Q2YTOB.js} +2 -2
  111. package/dist/{chunk-N3ZOP7KC.js → chunk-JEIXTYVG.js} +2 -2
  112. package/dist/{chunk-ZO2AZIRT.js → chunk-JJPRWTOW.js} +2 -2
  113. package/dist/{chunk-ODW5GDFE.js → chunk-JT3EB7ZL.js} +2 -2
  114. package/dist/{chunk-OU4K7IFP.js → chunk-K5DSKAVF.js} +39 -39
  115. package/dist/{chunk-VDX2J7OX.js → chunk-KQAFEZQX.js} +2 -2
  116. package/dist/{chunk-3K7V3HE6.js → chunk-KXRX7YC2.js} +2 -2
  117. package/dist/{chunk-DDB3S53L.js → chunk-L5JP37BO.js} +7 -7
  118. package/dist/{chunk-227UFSEQ.js → chunk-LEPOP46W.js} +4 -4
  119. package/dist/{chunk-54WHLA65.js → chunk-LRICZIGN.js} +3 -3
  120. package/dist/{chunk-TVEONGBU.js → chunk-MFJBANPX.js} +2 -2
  121. package/dist/{chunk-OB3XMWX5.js → chunk-MKWKYHXJ.js} +4 -4
  122. package/dist/{chunk-HMKPFW7R.js → chunk-MPAJFFP3.js} +2 -2
  123. package/dist/{chunk-R7RTXEYG.js → chunk-MPYD657E.js} +2 -2
  124. package/dist/{chunk-V4ZBR7CW.js → chunk-N2CAORTC.js} +4 -4
  125. package/dist/{chunk-NLDVVWCL.js → chunk-NDNTNE3S.js} +2 -2
  126. package/dist/{chunk-JJ4XK25O.js → chunk-NEFKNR4V.js} +9 -9
  127. package/dist/{chunk-U6N5IBVY.js → chunk-NWWXSJX5.js} +2 -2
  128. package/dist/{chunk-QBC33MPY.js → chunk-NZXEK3UF.js} +2 -2
  129. package/dist/{chunk-JUC24CTX.js → chunk-P2QRMMVQ.js} +6 -1
  130. package/dist/chunk-P2QRMMVQ.js.map +1 -0
  131. package/dist/{chunk-EOQ6FSQP.js → chunk-PHNAB54Q.js} +2 -2
  132. package/dist/{chunk-BD7JTBYP.js → chunk-PSPABFN2.js} +4 -4
  133. package/dist/{chunk-RBCQVOVJ.js → chunk-PV36INNL.js} +3 -3
  134. package/dist/{chunk-E2P7TZTF.js → chunk-ROKKIMON.js} +2 -2
  135. package/dist/{chunk-OEYZXDQI.js → chunk-RSVEP77Y.js} +2 -2
  136. package/dist/{chunk-FQ7HAWWC.js → chunk-RZN4LQ5Y.js} +17 -2
  137. package/dist/{chunk-FQ7HAWWC.js.map → chunk-RZN4LQ5Y.js.map} +1 -1
  138. package/dist/{chunk-SV4Z2S67.js → chunk-S5G2LAL7.js} +4 -4
  139. package/dist/{chunk-AQ7SYDVO.js → chunk-S65WXHNK.js} +2 -2
  140. package/dist/{chunk-6XL73HQ4.js → chunk-SB6PSOP7.js} +1 -1
  141. package/dist/{chunk-JALOAKSZ.js → chunk-TLPZ6MKZ.js} +4 -4
  142. package/dist/{chunk-XTJC7CVX.js → chunk-TXMAF7FZ.js} +5 -5
  143. package/dist/{chunk-3NYTZE5G.js → chunk-UFDMVGUQ.js} +2 -2
  144. package/dist/{chunk-DFEODULB.js → chunk-V2HHAAPI.js} +2 -2
  145. package/dist/{chunk-KEF46KL2.js → chunk-V6EGNVUT.js} +3 -3
  146. package/dist/{chunk-ESNFSSO4.js → chunk-VGXM5B4H.js} +2 -2
  147. package/dist/{chunk-FHYVNJBN.js → chunk-VLLEWQIU.js} +4 -4
  148. package/dist/{chunk-MJUCDM3C.js → chunk-VLXBE57O.js} +2 -2
  149. package/dist/{chunk-4TKJGOCJ.js → chunk-VP67GZ7T.js} +2 -2
  150. package/dist/{chunk-RX3SC4C5.js → chunk-VT4MK674.js} +2 -2
  151. package/dist/{chunk-GHTSNGBZ.js → chunk-VZWXFXLX.js} +2 -2
  152. package/dist/{chunk-WJHGDE7X.js → chunk-W64HKJJM.js} +3 -3
  153. package/dist/{chunk-Y2MZGBOY.js → chunk-W7SECYCQ.js} +2 -2
  154. package/dist/{chunk-2L5FSNPC.js → chunk-X2NFFBTO.js} +7 -7
  155. package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
  156. package/dist/{chunk-EGALNSZ4.js → chunk-XU6OEECT.js} +3 -3
  157. package/dist/{chunk-MZLV2OJE.js → chunk-XWSMJXIG.js} +53 -53
  158. package/dist/{chunk-THQTFTQS.js → chunk-Y3BGA7L5.js} +17 -17
  159. package/dist/{chunk-4FIH6MPS.js → chunk-YHLWPYHT.js} +3 -3
  160. package/dist/{chunk-PAZY2ZKP.js → chunk-YQAXP5AC.js} +2 -2
  161. package/dist/{chunk-JEC4DVM3.js → chunk-YUMDFDUA.js} +3 -3
  162. package/dist/{chunk-7HYPN2GC.js → chunk-ZG74PWRW.js} +2 -2
  163. package/dist/{chunk-VVX5PZFS.js → chunk-ZHXSOMYH.js} +2 -2
  164. package/dist/{chunk-TNSCIPBQ.js → chunk-ZNJSBIP4.js} +4 -4
  165. package/dist/{cli-DD0P-lu8.d.ts → cli-B_YwqoIr.d.ts} +1 -1
  166. package/dist/cli.d.ts +2 -2
  167. package/dist/cli.js +101 -101
  168. package/dist/coding/export-okf-codegraph.js +22 -22
  169. package/dist/compounding/engine.js +21 -21
  170. package/dist/config-discovery.d.ts +26 -0
  171. package/dist/config-discovery.js +11 -0
  172. package/dist/config-security.js +2 -2
  173. package/dist/config.js +8 -8
  174. package/dist/connectors/codex-materialize-runner.js +21 -21
  175. package/dist/connectors/codex-materialize.js +3 -3
  176. package/dist/connectors/index.js +24 -24
  177. package/dist/convergence-refresh.js +22 -22
  178. package/dist/conversation-index/backend.js +2 -2
  179. package/dist/corpus-watermark.js +22 -22
  180. package/dist/deep-recall-http-glue.d.ts +1 -1
  181. package/dist/deep-recall-http-glue.js +4 -4
  182. package/dist/deep-recall-mcp-tools.d.ts +1 -1
  183. package/dist/deep-recall-policy-llm.js +5 -5
  184. package/dist/deep-recall.js +2 -2
  185. package/dist/embedding-fallback.js +2 -2
  186. package/dist/emit-legacy-tools.js +3 -3
  187. package/dist/entity-retrieval.js +20 -20
  188. package/dist/external-wiki-access.d.ts +1 -1
  189. package/dist/external-wiki-access.js +58 -58
  190. package/dist/external-wiki-config.js +3 -3
  191. package/dist/external-wiki-mcp-tools.d.ts +1 -1
  192. package/dist/extraction-faithfulness.js +5 -5
  193. package/dist/extraction-judge.js +5 -5
  194. package/dist/extraction-source-grounding.js +3 -3
  195. package/dist/extraction.js +33 -33
  196. package/dist/fallback-llm.js +4 -4
  197. package/dist/harmonic-retrieval.js +1 -1
  198. package/dist/http-retry.d.ts +83 -0
  199. package/dist/http-retry.js +101 -0
  200. package/dist/http-retry.js.map +1 -0
  201. package/dist/importers/index.d.ts +21 -1
  202. package/dist/importers/index.js +3 -1
  203. package/dist/importers/test-utils.d.ts +24 -0
  204. package/dist/importers/test-utils.js +31 -0
  205. package/dist/importers/test-utils.js.map +1 -0
  206. package/dist/index.d.ts +683 -681
  207. package/dist/index.js +177 -166
  208. package/dist/lcm/engine.js +3 -3
  209. package/dist/lcm/index.js +6 -6
  210. package/dist/live-connectors-runner.js +5 -5
  211. package/dist/local-llm.js +3 -3
  212. package/dist/location/index.js +22 -22
  213. package/dist/maintenance/memory-governance.js +20 -20
  214. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -20
  215. package/dist/maintenance/rebuild-memory-projection.js +21 -21
  216. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  217. package/dist/memory-subject-cli.d.ts +1 -1
  218. package/dist/memory-subject.d.ts +1 -1
  219. package/dist/migrate/from-engram.js +2 -2
  220. package/dist/namespaces/migrate.js +21 -21
  221. package/dist/namespaces/search.js +12 -12
  222. package/dist/namespaces/storage.js +20 -20
  223. package/dist/offline-sync-impression-drain.js +6 -6
  224. package/dist/operator-doctor-corpus.js +23 -23
  225. package/dist/operator-toolkit.js +36 -36
  226. package/dist/opik-exporter.js +1 -1
  227. package/dist/orchestration/maintenance.js +31 -31
  228. package/dist/orchestrator.js +141 -140
  229. package/dist/provenance.js +2 -2
  230. package/dist/{public-http-C4i8Opxc.d.ts → public-http-D6d4W8x-.d.ts} +1 -1
  231. package/dist/qmd.js +5 -5
  232. package/dist/recall-planner-llm.js +4 -4
  233. package/dist/reconcile/manifest.js +1 -1
  234. package/dist/resolve-provider-secret.js +2 -2
  235. package/dist/resume-bundles.js +9 -9
  236. package/dist/runtime/env.d.ts +9 -1
  237. package/dist/runtime/env.js +3 -1
  238. package/dist/schemas.d.ts +176 -176
  239. package/dist/sdk-compat.js +1 -1
  240. package/dist/search/factory.js +11 -11
  241. package/dist/search/index.js +16 -16
  242. package/dist/search/lancedb-backend.js +2 -2
  243. package/dist/search/meilisearch-backend.js +2 -2
  244. package/dist/search/orama-backend.js +2 -2
  245. package/dist/semantic-consolidation.js +22 -22
  246. package/dist/semantic-rule-promotion.js +20 -20
  247. package/dist/semantic-rule-verifier.js +20 -20
  248. package/dist/shared-context/manager.d.ts +6 -6
  249. package/dist/shared-context/manager.js +3 -3
  250. package/dist/source-agent-qualifier.js +30 -30
  251. package/dist/standup/build.js +20 -20
  252. package/dist/{state-store-Z3EN56O5.js → state-store-I5HLZTZT.js} +4 -4
  253. package/dist/state-store-I5HLZTZT.js.map +1 -0
  254. package/dist/storage.js +19 -19
  255. package/dist/summarizer.js +7 -7
  256. package/dist/support-passport/index.d.ts +4 -4
  257. package/dist/support-passport/index.js +60 -60
  258. package/dist/tokens.js +2 -2
  259. package/dist/transfer/backup.js +2 -2
  260. package/dist/transfer/capsule-export.js +2 -2
  261. package/dist/transfer/capsule-import.js +2 -2
  262. package/dist/transfer/export-okf.js +21 -21
  263. package/dist/transfer/types.d.ts +78 -78
  264. package/dist/utils/path.js +2 -2
  265. package/dist/verified-recall.js +20 -20
  266. package/dist/who-knows-cli.d.ts +1 -1
  267. package/dist/who-knows-cli.js +21 -21
  268. package/dist/who-knows.d.ts +1 -1
  269. package/dist/who-knows.js +20 -20
  270. package/package.json +22 -2
  271. package/src/config-discovery.test.ts +63 -0
  272. package/src/config-discovery.ts +90 -0
  273. package/src/http-retry.test.ts +281 -0
  274. package/src/http-retry.ts +183 -0
  275. package/src/importers/base.ts +45 -0
  276. package/src/importers/index.test.ts +42 -0
  277. package/src/importers/index.ts +5 -0
  278. package/src/importers/test-utils.ts +44 -0
  279. package/src/index.ts +5 -0
  280. package/src/reconcile/manifest.ts +59 -50
  281. package/src/runtime/env.ts +11 -0
  282. package/dist/chunk-JUC24CTX.js.map +0 -1
  283. package/dist/chunk-TWF35IC6.js.map +0 -1
  284. package/dist/{access-service-DWdY9Mlk.d.ts → access-service-Cv8Rizo0.d.ts} +64 -64
  285. /package/dist/{auto-sync-WNGG2GC2.js.map → auto-sync-NSHLUAQI.js.map} +0 -0
  286. /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
  287. /package/dist/{chunk-GRCREL6Q.js.map → chunk-22JQEBN3.js.map} +0 -0
  288. /package/dist/{chunk-6LLLREDJ.js.map → chunk-2E3CG66I.js.map} +0 -0
  289. /package/dist/{chunk-OO42R444.js.map → chunk-2MFH376S.js.map} +0 -0
  290. /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
  291. /package/dist/{chunk-NXH34IPL.js.map → chunk-353KGBKY.js.map} +0 -0
  292. /package/dist/{chunk-DZD3WGCD.js.map → chunk-3JVLGJCY.js.map} +0 -0
  293. /package/dist/{chunk-W24T5YMW.js.map → chunk-47DEYNMR.js.map} +0 -0
  294. /package/dist/{chunk-QOOBICJF.js.map → chunk-565C6ZFO.js.map} +0 -0
  295. /package/dist/{chunk-ZY4DSWZ5.js.map → chunk-5OOSADXP.js.map} +0 -0
  296. /package/dist/{chunk-EYIEWJNI.js.map → chunk-6KH5NLQS.js.map} +0 -0
  297. /package/dist/{chunk-EMDLM3LW.js.map → chunk-7IRZK6MM.js.map} +0 -0
  298. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  299. /package/dist/{chunk-6CVNSDCZ.js.map → chunk-7VJXIDOC.js.map} +0 -0
  300. /package/dist/{chunk-SO4IYSGT.js.map → chunk-A5JPK3MZ.js.map} +0 -0
  301. /package/dist/{chunk-IVKIODHO.js.map → chunk-A7XEPMQ6.js.map} +0 -0
  302. /package/dist/{chunk-K6MV3TRQ.js.map → chunk-ADXCCZL2.js.map} +0 -0
  303. /package/dist/{chunk-SJDQ5RSN.js.map → chunk-AOCP6JA7.js.map} +0 -0
  304. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  305. /package/dist/{chunk-GNMELJGM.js.map → chunk-AYAIV5V5.js.map} +0 -0
  306. /package/dist/{chunk-ND6IQGSZ.js.map → chunk-BA6WOZOT.js.map} +0 -0
  307. /package/dist/{chunk-JI7U6AS3.js.map → chunk-C6FQJ52H.js.map} +0 -0
  308. /package/dist/{chunk-IN673LEP.js.map → chunk-CARRTDKC.js.map} +0 -0
  309. /package/dist/{chunk-6NXSYYGP.js.map → chunk-CBCNKKZD.js.map} +0 -0
  310. /package/dist/{chunk-DXFG2VGN.js.map → chunk-CGC5UQCF.js.map} +0 -0
  311. /package/dist/{chunk-QBH7M7Q4.js.map → chunk-CLALC6ZB.js.map} +0 -0
  312. /package/dist/{chunk-YSSAGB2O.js.map → chunk-CLLPJ6QT.js.map} +0 -0
  313. /package/dist/{chunk-KAXCYM66.js.map → chunk-D5LORF7A.js.map} +0 -0
  314. /package/dist/{chunk-CEH2AFXG.js.map → chunk-DBQWVT2H.js.map} +0 -0
  315. /package/dist/{chunk-XSTNGNJP.js.map → chunk-DCJ3YFIC.js.map} +0 -0
  316. /package/dist/{chunk-MWN6QEI2.js.map → chunk-DITMGZOL.js.map} +0 -0
  317. /package/dist/{chunk-LVE64P5Y.js.map → chunk-E2ZHGBAK.js.map} +0 -0
  318. /package/dist/{chunk-2EKJDQZB.js.map → chunk-EZZV7OQL.js.map} +0 -0
  319. /package/dist/{chunk-N3SS45OW.js.map → chunk-FCSZ4K2X.js.map} +0 -0
  320. /package/dist/{chunk-5ATKSPEQ.js.map → chunk-FGGYSN4P.js.map} +0 -0
  321. /package/dist/{chunk-2Z4GS5E6.js.map → chunk-FHQSPTPZ.js.map} +0 -0
  322. /package/dist/{chunk-3GGUMRS4.js.map → chunk-FJ5B36V2.js.map} +0 -0
  323. /package/dist/{chunk-5IEV3YBY.js.map → chunk-GAYZTUIF.js.map} +0 -0
  324. /package/dist/{chunk-KH6PK4EQ.js.map → chunk-GBYCFJGV.js.map} +0 -0
  325. /package/dist/{chunk-6VF3R3XQ.js.map → chunk-GCRGBE72.js.map} +0 -0
  326. /package/dist/{chunk-6GUG4YNM.js.map → chunk-GGRRF4PZ.js.map} +0 -0
  327. /package/dist/{chunk-ZUNNRGJX.js.map → chunk-GL4EC4RG.js.map} +0 -0
  328. /package/dist/{chunk-UCKYTA2T.js.map → chunk-GTWHVXPA.js.map} +0 -0
  329. /package/dist/{chunk-XSGUMQQQ.js.map → chunk-GVG3JYBI.js.map} +0 -0
  330. /package/dist/{chunk-MY5EDR46.js.map → chunk-GY5WZBA6.js.map} +0 -0
  331. /package/dist/{chunk-3GCK6ONU.js.map → chunk-HK32G473.js.map} +0 -0
  332. /package/dist/{chunk-EWCNCQOU.js.map → chunk-HRICDLBE.js.map} +0 -0
  333. /package/dist/{chunk-46ZPIGWI.js.map → chunk-HY55QQD7.js.map} +0 -0
  334. /package/dist/{chunk-WMLEPWMO.js.map → chunk-I27RSQRR.js.map} +0 -0
  335. /package/dist/{chunk-QIEUU4UK.js.map → chunk-I55KAVET.js.map} +0 -0
  336. /package/dist/{chunk-XM24CDZX.js.map → chunk-IY2FVXM6.js.map} +0 -0
  337. /package/dist/{chunk-CGJV2YIY.js.map → chunk-J5Q2YTOB.js.map} +0 -0
  338. /package/dist/{chunk-N3ZOP7KC.js.map → chunk-JEIXTYVG.js.map} +0 -0
  339. /package/dist/{chunk-ZO2AZIRT.js.map → chunk-JJPRWTOW.js.map} +0 -0
  340. /package/dist/{chunk-ODW5GDFE.js.map → chunk-JT3EB7ZL.js.map} +0 -0
  341. /package/dist/{chunk-OU4K7IFP.js.map → chunk-K5DSKAVF.js.map} +0 -0
  342. /package/dist/{chunk-VDX2J7OX.js.map → chunk-KQAFEZQX.js.map} +0 -0
  343. /package/dist/{chunk-3K7V3HE6.js.map → chunk-KXRX7YC2.js.map} +0 -0
  344. /package/dist/{chunk-DDB3S53L.js.map → chunk-L5JP37BO.js.map} +0 -0
  345. /package/dist/{chunk-227UFSEQ.js.map → chunk-LEPOP46W.js.map} +0 -0
  346. /package/dist/{chunk-54WHLA65.js.map → chunk-LRICZIGN.js.map} +0 -0
  347. /package/dist/{chunk-TVEONGBU.js.map → chunk-MFJBANPX.js.map} +0 -0
  348. /package/dist/{chunk-OB3XMWX5.js.map → chunk-MKWKYHXJ.js.map} +0 -0
  349. /package/dist/{chunk-HMKPFW7R.js.map → chunk-MPAJFFP3.js.map} +0 -0
  350. /package/dist/{chunk-R7RTXEYG.js.map → chunk-MPYD657E.js.map} +0 -0
  351. /package/dist/{chunk-V4ZBR7CW.js.map → chunk-N2CAORTC.js.map} +0 -0
  352. /package/dist/{chunk-NLDVVWCL.js.map → chunk-NDNTNE3S.js.map} +0 -0
  353. /package/dist/{chunk-JJ4XK25O.js.map → chunk-NEFKNR4V.js.map} +0 -0
  354. /package/dist/{chunk-U6N5IBVY.js.map → chunk-NWWXSJX5.js.map} +0 -0
  355. /package/dist/{chunk-QBC33MPY.js.map → chunk-NZXEK3UF.js.map} +0 -0
  356. /package/dist/{chunk-EOQ6FSQP.js.map → chunk-PHNAB54Q.js.map} +0 -0
  357. /package/dist/{chunk-BD7JTBYP.js.map → chunk-PSPABFN2.js.map} +0 -0
  358. /package/dist/{chunk-RBCQVOVJ.js.map → chunk-PV36INNL.js.map} +0 -0
  359. /package/dist/{chunk-E2P7TZTF.js.map → chunk-ROKKIMON.js.map} +0 -0
  360. /package/dist/{chunk-OEYZXDQI.js.map → chunk-RSVEP77Y.js.map} +0 -0
  361. /package/dist/{chunk-SV4Z2S67.js.map → chunk-S5G2LAL7.js.map} +0 -0
  362. /package/dist/{chunk-AQ7SYDVO.js.map → chunk-S65WXHNK.js.map} +0 -0
  363. /package/dist/{chunk-6XL73HQ4.js.map → chunk-SB6PSOP7.js.map} +0 -0
  364. /package/dist/{chunk-JALOAKSZ.js.map → chunk-TLPZ6MKZ.js.map} +0 -0
  365. /package/dist/{chunk-XTJC7CVX.js.map → chunk-TXMAF7FZ.js.map} +0 -0
  366. /package/dist/{chunk-3NYTZE5G.js.map → chunk-UFDMVGUQ.js.map} +0 -0
  367. /package/dist/{chunk-DFEODULB.js.map → chunk-V2HHAAPI.js.map} +0 -0
  368. /package/dist/{chunk-KEF46KL2.js.map → chunk-V6EGNVUT.js.map} +0 -0
  369. /package/dist/{chunk-ESNFSSO4.js.map → chunk-VGXM5B4H.js.map} +0 -0
  370. /package/dist/{chunk-FHYVNJBN.js.map → chunk-VLLEWQIU.js.map} +0 -0
  371. /package/dist/{chunk-MJUCDM3C.js.map → chunk-VLXBE57O.js.map} +0 -0
  372. /package/dist/{chunk-4TKJGOCJ.js.map → chunk-VP67GZ7T.js.map} +0 -0
  373. /package/dist/{chunk-RX3SC4C5.js.map → chunk-VT4MK674.js.map} +0 -0
  374. /package/dist/{chunk-GHTSNGBZ.js.map → chunk-VZWXFXLX.js.map} +0 -0
  375. /package/dist/{chunk-WJHGDE7X.js.map → chunk-W64HKJJM.js.map} +0 -0
  376. /package/dist/{chunk-Y2MZGBOY.js.map → chunk-W7SECYCQ.js.map} +0 -0
  377. /package/dist/{chunk-2L5FSNPC.js.map → chunk-X2NFFBTO.js.map} +0 -0
  378. /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
  379. /package/dist/{chunk-EGALNSZ4.js.map → chunk-XU6OEECT.js.map} +0 -0
  380. /package/dist/{chunk-MZLV2OJE.js.map → chunk-XWSMJXIG.js.map} +0 -0
  381. /package/dist/{chunk-THQTFTQS.js.map → chunk-Y3BGA7L5.js.map} +0 -0
  382. /package/dist/{chunk-4FIH6MPS.js.map → chunk-YHLWPYHT.js.map} +0 -0
  383. /package/dist/{chunk-PAZY2ZKP.js.map → chunk-YQAXP5AC.js.map} +0 -0
  384. /package/dist/{chunk-JEC4DVM3.js.map → chunk-YUMDFDUA.js.map} +0 -0
  385. /package/dist/{chunk-7HYPN2GC.js.map → chunk-ZG74PWRW.js.map} +0 -0
  386. /package/dist/{chunk-VVX5PZFS.js.map → chunk-ZHXSOMYH.js.map} +0 -0
  387. /package/dist/{chunk-TNSCIPBQ.js.map → chunk-ZNJSBIP4.js.map} +0 -0
  388. /package/dist/{state-store-Z3EN56O5.js.map → config-discovery.js.map} +0 -0
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Shared retrying fetch for connector packages (issue #2792).
3
+ *
4
+ * One copy of the retry loop that six connector clients and the X MCP
5
+ * client duplicated: attempt counting, per-attempt timeout signal,
6
+ * 429/5xx retry with Retry-After (seconds or HTTP-date) plus capped
7
+ * exponential backoff, raw rethrow of caller aborts, and socket
8
+ * release on retryable responses. Vendors keep everything
9
+ * request-specific: headers/body, the error classes their callers
10
+ * match on, and what happens to a successful response body.
11
+ *
12
+ * Import via the `@remnic/core/http-retry` subpath (same pattern as
13
+ * `@remnic/core/abort-error`) — the root index stays untouched.
14
+ */
15
+
16
+ export interface RetryingFetchOptions {
17
+ /** Request init for every attempt. Ignored when `buildInit` is set. */
18
+ init?: RequestInit;
19
+ /**
20
+ * Init builder invoked ONCE, before the retry loop. Request
21
+ * construction (e.g. token acquisition) must stay outside the
22
+ * transport retry boundary: a deterministic provider failure —
23
+ * missing grant, revoked grant, unpersistable token file — runs once
24
+ * and propagates unwrapped, never retried or vendor-wrapped.
25
+ */
26
+ buildInit?: () => RequestInit | Promise<RequestInit>;
27
+ fetchImpl?: typeof fetch;
28
+ sleep?: (ms: number) => Promise<void>;
29
+ signal?: AbortSignal;
30
+ timeoutMs?: number;
31
+ /** Retries after the first attempt. Default 3 (4 attempts total). */
32
+ maxRetries?: number;
33
+ maxRetryDelayMs?: number;
34
+ /** First backoff step; doubles per attempt. Default 1_000. */
35
+ backoffBaseMs?: number;
36
+ /**
37
+ * Vendor Retry-After parsing (e.g. a body field). A `null`/`undefined`
38
+ * result falls back to the shared Retry-After header parse, then to
39
+ * exponential backoff. A number (including 0) is used as-is.
40
+ */
41
+ retryAfterMs?: (response: Response) => number | null | undefined | Promise<number | null | undefined>;
42
+ /** Wraps an exhausted network/timeout failure into the vendor error. */
43
+ networkError: (err: unknown, attempts: number, context: NetworkErrorContext) => Error;
44
+ /** Wraps a retryable (429/5xx) response; thrown when retries are exhausted. */
45
+ retryableError: (response: Response) => Error | Promise<Error>;
46
+ }
47
+
48
+ export interface NetworkErrorContext {
49
+ /** True when the helper's own timeout signal fired (not a caller abort). */
50
+ timedOut: boolean;
51
+ }
52
+
53
+ /**
54
+ * Base class for connector API errors: a message plus optional HTTP
55
+ * status and vendor detail. Vendor subclasses set their own `name`.
56
+ */
57
+ export class ConnectorApiError extends Error {
58
+ constructor(
59
+ message: string,
60
+ readonly status?: number,
61
+ readonly detail?: string,
62
+ ) {
63
+ super(message);
64
+ this.name = "ConnectorApiError";
65
+ }
66
+ }
67
+
68
+ const DEFAULT_TIMEOUT_MS = 30_000;
69
+ const DEFAULT_MAX_RETRIES = 3;
70
+ const DEFAULT_MAX_RETRY_DELAY_MS = 30_000;
71
+ const DEFAULT_BACKOFF_BASE_MS = 1_000;
72
+
73
+ function defaultSleep(ms: number): Promise<void> {
74
+ const { promise, resolve } = Promise.withResolvers<void>();
75
+ setTimeout(resolve, ms);
76
+ return promise;
77
+ }
78
+
79
+ /**
80
+ * Network/timeout failures wrap Node error text that can carry loader
81
+ * paths or stack fragments; sync errors reach MCP clients verbatim, so
82
+ * only the error name + code survive.
83
+ */
84
+ export function describeNetworkError(err: unknown): string {
85
+ if (!(err instanceof Error)) return "unexpected non-Error failure";
86
+ const code = (err as NodeJS.ErrnoException).code;
87
+ return typeof code === "string" && code.length > 0 ? `${err.name} (${code})` : err.name;
88
+ }
89
+
90
+ /** Loop instead of `/\/+$/` — CodeQL js/polynomial-redos on user-set URLs. */
91
+ export function stripTrailingSlashes(value: string): string {
92
+ let end = value.length;
93
+ while (end > 0 && value.charCodeAt(end - 1) === 0x2f) end--;
94
+ return value.slice(0, end);
95
+ }
96
+
97
+ /** Release the socket back to the pool: an unconsumed response body pins the undici connection. */
98
+ export function discardResponseBody(response: Response): void {
99
+ void response.body?.cancel().catch(() => {});
100
+ }
101
+
102
+ /**
103
+ * Parse a `Retry-After` header as delay in ms, capped at `capMs`:
104
+ * delay-seconds first, then HTTP-date. `undefined` when absent or
105
+ * unparseable.
106
+ */
107
+ export function retryAfterHeaderMs(response: Response, capMs: number): number | undefined {
108
+ const header = response.headers.get("retry-after");
109
+ if (header === null || header.length === 0) return undefined;
110
+ const seconds = Number(header);
111
+ if (Number.isFinite(seconds) && seconds >= 0) {
112
+ return Math.min(capMs, Math.ceil(seconds * 1_000));
113
+ }
114
+ const when = Date.parse(header);
115
+ if (Number.isFinite(when)) {
116
+ return Math.min(capMs, Math.max(0, when - Date.now()));
117
+ }
118
+ return undefined;
119
+ }
120
+
121
+ /**
122
+ * Fetch with retries on network failures, 429, and 5xx. Returns the
123
+ * final response (ok or non-retryable status) for the caller to
124
+ * interpret; throws the vendor-wrapped error when retries are exhausted
125
+ * or the transport fails.
126
+ */
127
+ export async function retryingFetch(
128
+ url: string,
129
+ options: RetryingFetchOptions,
130
+ ): Promise<Response> {
131
+ const fetchImpl = options.fetchImpl ?? fetch;
132
+ const sleep = options.sleep ?? defaultSleep;
133
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
134
+ const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
135
+ const maxRetryDelayMs = options.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
136
+ const backoffBaseMs = options.backoffBaseMs ?? DEFAULT_BACKOFF_BASE_MS;
137
+ const backoffMs = (attempt: number): number =>
138
+ Math.min(maxRetryDelayMs, backoffBaseMs * 2 ** attempt);
139
+ const attempts = maxRetries + 1;
140
+
141
+ // Request construction runs once, outside the retry boundary: only
142
+ // fetch/network/HTTP-retryable failures retry, so initializer/token
143
+ // provider errors execute once and propagate unchanged (issue #2792).
144
+ options.signal?.throwIfAborted();
145
+ const init = options.buildInit ? await options.buildInit() : options.init;
146
+
147
+ let lastError: unknown;
148
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
149
+ options.signal?.throwIfAborted();
150
+ const timeoutSignal = AbortSignal.timeout(timeoutMs);
151
+ const combined = options.signal
152
+ ? AbortSignal.any([options.signal, timeoutSignal])
153
+ : timeoutSignal;
154
+ let response: Response;
155
+ try {
156
+ response = await fetchImpl(url, { ...init, signal: combined });
157
+ } catch (err) {
158
+ // The caller's abort always propagates unwrapped and unretried.
159
+ if (options.signal?.aborted) throw err;
160
+ if (attempt < maxRetries) {
161
+ await sleep(backoffMs(attempt));
162
+ continue;
163
+ }
164
+ throw options.networkError(err, attempts, { timedOut: timeoutSignal.aborted });
165
+ }
166
+
167
+ if (response.status === 429 || response.status >= 500) {
168
+ lastError = await options.retryableError(response);
169
+ if (attempt < maxRetries) {
170
+ const override = options.retryAfterMs ? await options.retryAfterMs(response) : undefined;
171
+ const delay = override ?? retryAfterHeaderMs(response, maxRetryDelayMs) ?? backoffMs(attempt);
172
+ discardResponseBody(response);
173
+ await sleep(delay);
174
+ continue;
175
+ }
176
+ discardResponseBody(response);
177
+ throw lastError;
178
+ }
179
+ return response;
180
+ }
181
+ // Unreachable: every terminal loop path throws. Kept for exhaustiveness.
182
+ throw lastError instanceof Error ? lastError : new ConnectorApiError("request failed");
183
+ }
@@ -483,3 +483,48 @@ export async function defaultWriteMemoriesToOrchestrator(
483
483
  await target.ingestBulkImportBatch(turns);
484
484
  return { memoriesIngested: memories.length };
485
485
  }
486
+
487
+ // ---------------------------------------------------------------------------
488
+ // File-importer factory (issue #2794)
489
+ // ---------------------------------------------------------------------------
490
+
491
+ /** Parse args `defineFileImporterAdapter` forwards — the keys file adapters use. */
492
+ export interface FileImporterParseArgs {
493
+ strict?: boolean;
494
+ filePath?: string;
495
+ }
496
+
497
+ /** Per-package config consumed by `defineFileImporterAdapter`. */
498
+ export interface FileImporterDefinition<Parsed> {
499
+ name: string;
500
+ sourceLabel: string;
501
+ /** Decode the raw export file. Receives only `strict` / `filePath`. */
502
+ parse(input: unknown, options: FileImporterParseArgs): Parsed | Promise<Parsed>;
503
+ /** Flatten the parsed export into `ImportedMemory[]` with provenance. */
504
+ transform(
505
+ parsed: Parsed,
506
+ options: ImporterTransformOptions | undefined,
507
+ ): ImportedMemory[] | Promise<ImportedMemory[]>;
508
+ }
509
+
510
+ /**
511
+ * Build the standard file-importer `ImporterAdapter`: parse with the
512
+ * `strict`/`filePath` spread, a package-specific `transform`, and `writeTo`
513
+ * delegating to `defaultWriteMemoriesToOrchestrator` (issue #2794).
514
+ */
515
+ export function defineFileImporterAdapter<Parsed>(
516
+ definition: FileImporterDefinition<Parsed>,
517
+ ): ImporterAdapter<Parsed> {
518
+ return {
519
+ name: definition.name,
520
+ sourceLabel: definition.sourceLabel,
521
+ parse(input, options) {
522
+ return definition.parse(input, {
523
+ ...(options?.strict !== undefined ? { strict: options.strict } : {}),
524
+ ...(options?.filePath !== undefined ? { filePath: options.filePath } : {}),
525
+ });
526
+ },
527
+ transform: (parsed, options) => definition.transform(parsed, options),
528
+ writeTo: defaultWriteMemoriesToOrchestrator,
529
+ };
530
+ }
@@ -0,0 +1,42 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Runtime barrel purity (issue #2794, fix round)
3
+ // ---------------------------------------------------------------------------
4
+ // `makeImporterTestTarget` / `loadImporterFixture` live behind the
5
+ // `@remnic/core/importers/test-utils` subpath ONLY. A static re-export from
6
+ // this barrel would link test-utils.js — and its node:fs/node:path/node:url
7
+ // imports — into every production consumer of `@remnic/core/importers`.
8
+
9
+ import assert from "node:assert/strict";
10
+ import { readFileSync } from "node:fs";
11
+ import { test } from "node:test";
12
+
13
+ import * as barrel from "./index.js";
14
+
15
+ // Namespace record read is deliberate: the harness names must be ABSENT, so
16
+ // they cannot appear on the typed surface of the barrel.
17
+ const surface = barrel as Record<string, unknown>;
18
+
19
+ const barrelSource = readFileSync(
20
+ new URL("./index.ts", import.meta.url),
21
+ "utf-8",
22
+ );
23
+
24
+ test("runtime barrel does not export the test harness (#2794)", () => {
25
+ assert.equal(
26
+ surface.makeImporterTestTarget,
27
+ undefined,
28
+ "test harness must stay behind @remnic/core/importers/test-utils",
29
+ );
30
+ assert.equal(
31
+ surface.loadImporterFixture,
32
+ undefined,
33
+ "test harness must stay behind @remnic/core/importers/test-utils",
34
+ );
35
+ });
36
+
37
+ test("runtime barrel statically links no test-utils module (#2794)", () => {
38
+ assert.ok(
39
+ !barrelSource.includes("test-utils"),
40
+ "src/importers/index.ts must not reference ./test-utils.js — import @remnic/core/importers/test-utils instead",
41
+ );
42
+ });
@@ -19,3 +19,8 @@ export {
19
19
  type RunImporterResult,
20
20
  type RunImportOptions,
21
21
  } from "./base.js";
22
+ export {
23
+ defineFileImporterAdapter,
24
+ type FileImporterDefinition,
25
+ type FileImporterParseArgs,
26
+ } from "./base.js";
@@ -0,0 +1,44 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Shared importer test harness (issue #2794)
3
+ // ---------------------------------------------------------------------------
4
+ // `makeTarget()` / `loadFixture()` were duplicated across the
5
+ // `@remnic/import-*` adapter tests. Test-only — never import from
6
+ // production code paths. Ships behind the `@remnic/core/importers/test-utils`
7
+ // subpath export, NOT the runtime barrel (issue #2794 fix round).
8
+
9
+ import { readFileSync } from "node:fs";
10
+ import path from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+
13
+ import type { ImportTurn } from "../bulk-import/types.js";
14
+ import type { ImporterWriteTarget } from "./base.js";
15
+
16
+ /** In-memory `ImporterWriteTarget` that captures every batch it receives. */
17
+ export function makeImporterTestTarget(): {
18
+ target: ImporterWriteTarget;
19
+ received: ImportTurn[][];
20
+ } {
21
+ const received: ImportTurn[][] = [];
22
+ return {
23
+ target: {
24
+ async ingestBulkImportBatch(turns) {
25
+ received.push(turns.map((t) => ({ ...t })));
26
+ },
27
+ bulkImportWriteNamespace() {
28
+ return "default";
29
+ },
30
+ },
31
+ received,
32
+ };
33
+ }
34
+
35
+ /** Read `<pkg>/fixtures/<name>` relative to the importing test file. */
36
+ export function loadImporterFixture(
37
+ testFileUrl: string,
38
+ name: string,
39
+ ): string {
40
+ return readFileSync(
41
+ path.join(path.dirname(fileURLToPath(testFileUrl)), "../fixtures", name),
42
+ "utf-8",
43
+ );
44
+ }
package/src/index.ts CHANGED
@@ -18,6 +18,8 @@ export { resolvePluginEntry, type PluginEntryResolverOptions } from "./plugin-en
18
18
 
19
19
  export { parseConfig, isOpenaiApiKeyDisabled, resolveEnvVars } from "./config.js";
20
20
  export { resolveRemnicConfigRecord } from "./config-record.js";
21
+ export { readCompatEnv } from "./runtime/env.js";
22
+ export { configPathCandidates, discoverConfigPath, type DiscoveredConfigPath } from "./config-discovery.js";
21
23
  export * from "./external-wiki.js";
22
24
  export * from "./external-wiki-cli.js";
23
25
  export {
@@ -1217,7 +1219,10 @@ export {
1217
1219
  validateImportRateLimit,
1218
1220
  importedMemoryToTurn,
1219
1221
  defaultWriteMemoriesToOrchestrator,
1222
+ defineFileImporterAdapter,
1220
1223
  runImporter,
1224
+ type FileImporterDefinition,
1225
+ type FileImporterParseArgs,
1221
1226
  type ImportedMemory,
1222
1227
  type ImporterAdapter,
1223
1228
  type ImporterParseOptions,
@@ -59,9 +59,7 @@ export interface ReconcileManifest {
59
59
  files: ReconcileManifestFile[];
60
60
  }
61
61
 
62
- export type ReconcileMemoryParser = (
63
- raw: string,
64
- ) => { frontmatter: MemoryFrontmatter; content: string } | null;
62
+ export type ReconcileMemoryParser = (raw: string) => { frontmatter: MemoryFrontmatter; content: string } | null;
65
63
 
66
64
  export interface BuildReconcileManifestOptions {
67
65
  files: Iterable<ReconcileFileState>;
@@ -82,32 +80,26 @@ function isMemoryPath(filePath: string): boolean {
82
80
  return MEMORY_DIRS.has(segments[index] ?? "");
83
81
  }
84
82
 
85
-
86
83
  function parsedMemoryIdentity(
87
84
  filePath: string,
88
85
  raw: Buffer | string,
89
86
  parseMemory: ReconcileMemoryParser,
90
- citationTemplate: string,
87
+ citationTemplate: string
91
88
  ): ReconcileMemoryIdentity | undefined {
92
89
  if (!isMemoryPath(filePath)) return undefined;
93
90
  const parsed = parseMemory(Buffer.isBuffer(raw) ? raw.toString("utf8") : raw);
94
91
  if (!parsed?.frontmatter.id) return undefined;
95
92
 
96
93
  const storedHash =
97
- parsed.frontmatter.contentHash &&
98
- SHA256_PATTERN.test(parsed.frontmatter.contentHash)
94
+ parsed.frontmatter.contentHash && SHA256_PATTERN.test(parsed.frontmatter.contentHash)
99
95
  ? parsed.frontmatter.contentHash.toLowerCase()
100
96
  : undefined;
101
97
  const candidates = storedContentIdentityCandidates(parsed.content, (content) =>
102
98
  stripCitationForTemplate(content, citationTemplate)
103
99
  );
104
100
  const bodyHash = ContentHashIndex.computeHash(candidates[0] ?? "");
105
- const currentMatch = candidates.find(
106
- (content) => ContentHashIndex.computeHash(content) === storedHash
107
- );
108
- const legacyMatch = [...candidates].reverse().find(
109
- (content) => computeLegacyContentHash(content) === storedHash
110
- );
101
+ const currentMatch = candidates.find((content) => ContentHashIndex.computeHash(content) === storedHash);
102
+ const legacyMatch = [...candidates].reverse().find((content) => computeLegacyContentHash(content) === storedHash);
111
103
  let contentHash: string;
112
104
  let contentHashAliases: string[] | undefined;
113
105
  if (currentMatch) {
@@ -126,7 +118,7 @@ function parsedMemoryIdentity(
126
118
  // An EMPTY legacy skeleton identifies nothing (every non-ASCII body maps
127
119
  // to it), so preserving it would collapse unrelated records. Recovering
128
120
  // the current identity here is repair, not replacement.
129
- contentHash = legacyMatch ? ContentHashIndex.computeHash(legacyMatch) : storedHash ?? bodyHash;
121
+ contentHash = legacyMatch ? ContentHashIndex.computeHash(legacyMatch) : (storedHash ?? bodyHash);
130
122
  }
131
123
 
132
124
  return {
@@ -144,7 +136,7 @@ export async function buildReconcileManifestFile(
144
136
  file: ReconcileFileState,
145
137
  readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>,
146
138
  parseMemory: ReconcileMemoryParser,
147
- citationTemplate = DEFAULT_CITATION_FORMAT,
139
+ citationTemplate = DEFAULT_CITATION_FORMAT
148
140
  ): Promise<ReconcileManifestFile> {
149
141
  let raw: Buffer | string | null = null;
150
142
  if (isMemoryPath(file.path)) {
@@ -161,6 +153,15 @@ export async function buildReconcileManifestFile(
161
153
  return { ...file, ...(memory ? { memory } : {}) };
162
154
  }
163
155
 
156
+ /** Read-batch size for manifest builds. Uncached files are independent (a
157
+ * per-file read + sha256 + frontmatter parse); processing them in bounded
158
+ * batches amortizes the per-file promise/async-hook overhead that dominates
159
+ * boot-scale corpus builds (measured: ~66% of CPU in async_hooks._propagate +
160
+ * GC at ~100k files) and overlaps IO waits, while the bound keeps memory flat.
161
+ * Order is preserved: results land in input order regardless of completion
162
+ * order, so the manifest output is byte-identical to the sequential form. */
163
+ const MANIFEST_BUILD_BATCH_SIZE = 50;
164
+
164
165
  export async function buildReconcileManifest(options: BuildReconcileManifestOptions): Promise<ReconcileManifest> {
165
166
  const cachedByPath = new Map<string, ReconcileManifestFile>();
166
167
  for (const cached of options.cachedFiles ?? []) {
@@ -168,24 +169,36 @@ export async function buildReconcileManifest(options: BuildReconcileManifestOpti
168
169
  }
169
170
 
170
171
  const files: ReconcileManifestFile[] = [];
171
- for (const file of options.files) {
172
+ // Cache hits stay on a synchronous fast path (no promise allocation, no
173
+ // Promise.all — a fully-cached rebuild must not regress); only the uncached
174
+ // entries ride the bounded batches. Order is preserved by index.
175
+ const uncached: Array<{ index: number; file: ReconcileFileState }> = [];
176
+ const allFiles = [...options.files];
177
+ for (let i = 0; i < allFiles.length; i += 1) {
178
+ const file = allFiles[i]!;
172
179
  const cached = cachedByPath.get(file.path);
173
180
  if (
174
- cached?.sha256.toLowerCase() === file.sha256.toLowerCase() &&
181
+ cached !== undefined &&
182
+ cached.sha256.toLowerCase() === file.sha256.toLowerCase() &&
175
183
  (cached.memory === undefined ||
176
184
  (cached.memory.normalizerVersion === CONTENT_HASH_NORMALIZER_VERSION &&
177
185
  cached.memory.identityResolutionVersion === IDENTITY_RESOLUTION_VERSION))
178
186
  ) {
179
187
  files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });
180
- continue;
188
+ } else {
189
+ uncached.push({ index: i, file });
190
+ }
191
+ }
192
+ for (let i = 0; i < uncached.length; i += MANIFEST_BUILD_BATCH_SIZE) {
193
+ const batch = uncached.slice(i, i + MANIFEST_BUILD_BATCH_SIZE);
194
+ const results = await Promise.all(
195
+ batch.map(({ file }) =>
196
+ buildReconcileManifestFile(file, options.readFile, options.parseMemory, options.citationTemplate)
197
+ )
198
+ );
199
+ for (let j = 0; j < batch.length; j += 1) {
200
+ files[batch[j]!.index] = results[j]!;
181
201
  }
182
-
183
- files.push(await buildReconcileManifestFile(
184
- file,
185
- options.readFile,
186
- options.parseMemory,
187
- options.citationTemplate,
188
- ));
189
202
  }
190
203
  files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
191
204
  return {
@@ -209,10 +222,7 @@ function memoryIdentityHashes(memory: ReconcileMemoryIdentity): string[] {
209
222
  return [memory.contentHash, ...(memory.contentHashAliases ?? [])];
210
223
  }
211
224
 
212
- function contentHashRows(
213
- files: Iterable<ActiveFactManifestFile>,
214
- contentHash: string,
215
- ): ContentHashPathEntry[] {
225
+ function contentHashRows(files: Iterable<ActiveFactManifestFile>, contentHash: string): ContentHashPathEntry[] {
216
226
  const rows: ContentHashPathEntry[] = [];
217
227
  for (const file of files) {
218
228
  rows.push({ path: file.path, contentHash });
@@ -237,7 +247,7 @@ export function collapseActiveFactDuplicates(
237
247
  plan: ReconcilePlan,
238
248
  localManifests: ReadonlyMap<string, ReconcileManifest>,
239
249
  peerManifests: ReadonlyMap<string, ReconcileManifest>,
240
- priorSemanticAgreements?: ReadonlyMap<string, readonly ReconcileSemanticAgreement[]>,
250
+ priorSemanticAgreements?: ReadonlyMap<string, readonly ReconcileSemanticAgreement[]>
241
251
  ): ReconcilePlan {
242
252
  const entriesByNamespace = new Map<string, ReconcilePlanEntry[]>();
243
253
  for (const entry of plan.entries) {
@@ -256,10 +266,7 @@ export function collapseActiveFactDuplicates(
256
266
  const localFilesByPath = new Map((localManifest?.files ?? []).map((file) => [file.path, file]));
257
267
  const peerFilesByPath = new Map((peerManifest?.files ?? []).map((file) => [file.path, file]));
258
268
  const priorSemanticByPathPair = new Map(
259
- (priorSemanticAgreements?.get(namespace) ?? []).map((agreement) => [
260
- semanticAgreementKey(agreement),
261
- agreement,
262
- ])
269
+ (priorSemanticAgreements?.get(namespace) ?? []).map((agreement) => [semanticAgreementKey(agreement), agreement])
263
270
  );
264
271
  const localByHash = new Map<string, ActiveFactManifestFile[]>();
265
272
  const peerByHash = new Map<string, ActiveFactManifestFile[]>();
@@ -286,17 +293,17 @@ export function collapseActiveFactDuplicates(
286
293
  const localCandidates = (localByHash.get(hash) ?? []).filter((file) => {
287
294
  const opposite = peerFilesByPath.get(file.path);
288
295
  const activeOpposite = peerByPath.get(file.path);
289
- return opposite === undefined || (
290
- activeOpposite !== undefined &&
291
- memoryIdentityHashes(activeOpposite.memory).includes(hash)
296
+ return (
297
+ opposite === undefined ||
298
+ (activeOpposite !== undefined && memoryIdentityHashes(activeOpposite.memory).includes(hash))
292
299
  );
293
300
  });
294
301
  const peerCandidates = (peerByHash.get(hash) ?? []).filter((file) => {
295
302
  const opposite = localFilesByPath.get(file.path);
296
303
  const activeOpposite = localByPath.get(file.path);
297
- return opposite === undefined || (
298
- activeOpposite !== undefined &&
299
- memoryIdentityHashes(activeOpposite.memory).includes(hash)
304
+ return (
305
+ opposite === undefined ||
306
+ (activeOpposite !== undefined && memoryIdentityHashes(activeOpposite.memory).includes(hash))
300
307
  );
301
308
  });
302
309
  const localPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(localCandidates, hash));
@@ -313,19 +320,21 @@ export function collapseActiveFactDuplicates(
313
320
  ...localCandidates.map((file) => file.path),
314
321
  ...peerCandidates.map((file) => file.path),
315
322
  ]);
316
- const authoritativeSamePathEntries = new Set(entries.filter(
317
- (entry) =>
318
- duplicatePaths.has(entry.path)
319
- && localFilesByPath.has(entry.path)
320
- && peerFilesByPath.has(entry.path)
321
- && entry.action !== "identical"
322
- ));
323
+ const authoritativeSamePathEntries = new Set(
324
+ entries.filter(
325
+ (entry) =>
326
+ duplicatePaths.has(entry.path) &&
327
+ localFilesByPath.has(entry.path) &&
328
+ peerFilesByPath.has(entry.path) &&
329
+ entry.action !== "identical"
330
+ )
331
+ );
323
332
  if (authoritativeSamePathEntries.size > 0) {
324
333
  for (const entry of entries) {
325
334
  if (
326
- duplicatePaths.has(entry.path)
327
- && !authoritativeSamePathEntries.has(entry)
328
- && (entry.action === "pull" || entry.action === "push" || entry.action === "identical")
335
+ duplicatePaths.has(entry.path) &&
336
+ !authoritativeSamePathEntries.has(entry) &&
337
+ (entry.action === "pull" || entry.action === "push" || entry.action === "identical")
329
338
  ) {
330
339
  removed.add(entry);
331
340
  changed = true;
@@ -25,6 +25,17 @@ export function readEnvVar(name: string): string | undefined {
25
25
  }
26
26
  return undefined;
27
27
  }
28
+ /**
29
+ * Read an env var by its current name, falling back to a legacy name.
30
+ *
31
+ * Unlike `readEnvVar`, an explicitly-set empty string is returned as-is:
32
+ * callers that must distinguish set-but-invalid from unset (server config
33
+ * readiness, auth-token fallbacks) rely on `??`-only semantics.
34
+ */
35
+ export function readCompatEnv(primary: string, legacy: string): string | undefined {
36
+ const env = getEnvMap();
37
+ return env?.[primary] ?? env?.[legacy];
38
+ }
28
39
 
29
40
  export function resolveHomeDir(): string {
30
41
  return readEnvVar("HOME") || os.homedir();
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/env.ts"],"sourcesContent":["import os from \"node:os\";\n\ntype EnvMap = Record<string, string | undefined>;\n\nfunction getEnvMap(): EnvMap | undefined {\n const runtimeProcess = globalThis.process as { env?: EnvMap } | undefined;\n return runtimeProcess?.[\"env\"];\n}\n\nfunction legacyEnvCandidates(name: string): string[] {\n if (name.startsWith(\"REMNIC_\")) {\n return [name, `ENGRAM_${name.slice(\"REMNIC_\".length)}`];\n }\n if (name.startsWith(\"ENGRAM_\")) {\n return [`REMNIC_${name.slice(\"ENGRAM_\".length)}`, name];\n }\n return [name];\n}\n\nexport function readEnvVar(name: string): string | undefined {\n const env = getEnvMap();\n for (const candidate of legacyEnvCandidates(name)) {\n const value = env?.[candidate];\n if (typeof value === \"string\" && value.length > 0) return value;\n }\n return undefined;\n}\n\nexport function resolveHomeDir(): string {\n return readEnvVar(\"HOME\") || os.homedir();\n}\n\nfunction cloneEnv(): NodeJS.ProcessEnv {\n return { ...(getEnvMap() ?? {}) };\n}\n\nexport function mergeEnv(overrides: Record<string, string | undefined>): NodeJS.ProcessEnv {\n const merged = cloneEnv();\n for (const [key, value] of Object.entries(overrides)) {\n if (typeof value === \"string\") merged[key] = value;\n else delete merged[key];\n }\n return merged;\n}\n"],"mappings":";AAAA,OAAO,QAAQ;AAIf,SAAS,YAAgC;AACvC,QAAM,iBAAiB,WAAW;AAClC,SAAO,iBAAiB,KAAK;AAC/B;AAEA,SAAS,oBAAoB,MAAwB;AACnD,MAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,WAAO,CAAC,MAAM,UAAU,KAAK,MAAM,UAAU,MAAM,CAAC,EAAE;AAAA,EACxD;AACA,MAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,WAAO,CAAC,UAAU,KAAK,MAAM,UAAU,MAAM,CAAC,IAAI,IAAI;AAAA,EACxD;AACA,SAAO,CAAC,IAAI;AACd;AAEO,SAAS,WAAW,MAAkC;AAC3D,QAAM,MAAM,UAAU;AACtB,aAAW,aAAa,oBAAoB,IAAI,GAAG;AACjD,UAAM,QAAQ,MAAM,SAAS;AAC7B,QAAI,OAAO,UAAU,YAAY,MAAM,SAAS,EAAG,QAAO;AAAA,EAC5D;AACA,SAAO;AACT;AAEO,SAAS,iBAAyB;AACvC,SAAO,WAAW,MAAM,KAAK,GAAG,QAAQ;AAC1C;AAEA,SAAS,WAA8B;AACrC,SAAO,EAAE,GAAI,UAAU,KAAK,CAAC,EAAG;AAClC;AAEO,SAAS,SAAS,WAAkE;AACzF,QAAM,SAAS,SAAS;AACxB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,QAAI,OAAO,UAAU,SAAU,QAAO,GAAG,IAAI;AAAA,QACxC,QAAO,OAAO,GAAG;AAAA,EACxB;AACA,SAAO;AACT;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/reconcile/manifest.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { computeLegacyContentHash, normalizeLegacyContent } from \"../content-hash.js\";\nimport { inferMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { ContentHashIndex, type ContentHashPathEntry } from \"../storage/content-hash-index.js\";\nimport { DEFAULT_CITATION_FORMAT, stripCitationForTemplate } from \"../source-attribution.js\";\nimport { storedContentIdentityCandidates } from \"../structured-attributes.js\";\nimport type { MemoryFrontmatter, MemoryStatus } from \"../types.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport {\n type ReconcileFileState,\n type ReconcilePlan,\n type ReconcilePlanEntry,\n type ReconcileSemanticAgreement,\n type ReconcileSemanticChange,\n compareReconcilePlanEntries,\n semanticAgreementKey,\n summarizeReconcilePlan,\n} from \"./plan.js\";\n\nexport const RECONCILE_MANIFEST_FORMAT = \"remnic-reconcile-manifest\";\nexport const RECONCILE_MANIFEST_SCHEMA_VERSION = 1;\nconst CONTENT_HASH_NORMALIZER_VERSION = 4;\n/**\n * Version of the identity-resolution LOGIC (alias recovery, candidate\n * ordering), independent of the content normalizer: a cached manifest entry\n * written before an identity-resolution change carries an older value and is\n * reparsed even when its normalizerVersion still matches (issue #2367\n * review round 2). Bump when parsedMemoryIdentity's output shape or\n * semantics change.\n */\nconst IDENTITY_RESOLUTION_VERSION = 2;\n\nexport interface ReconcileMemoryIdentity {\n id: string;\n category: string;\n contentHash: string;\n /**\n * Recovered current-normalizer identities for a record whose persisted hash\n * is ambiguous under the legacy normalizer (issue #2367). The persisted\n * hash stays primary; these participate in duplicate bucketing so a\n * replica carrying the current form of the same fact still collapses.\n */\n contentHashAliases?: readonly string[];\n /** See IDENTITY_RESOLUTION_VERSION; absent on pre-versioning cache entries. */\n normalizerVersion?: number;\n identityResolutionVersion?: number;\n status: MemoryStatus;\n}\n\nexport interface ReconcileManifestFile extends ReconcileFileState {\n memory?: ReconcileMemoryIdentity;\n}\n\ntype ActiveFactManifestFile = ReconcileManifestFile & { memory: ReconcileMemoryIdentity };\n\nexport interface ReconcileManifest {\n format: typeof RECONCILE_MANIFEST_FORMAT;\n schemaVersion: typeof RECONCILE_MANIFEST_SCHEMA_VERSION;\n files: ReconcileManifestFile[];\n}\n\nexport type ReconcileMemoryParser = (\n raw: string,\n) => { frontmatter: MemoryFrontmatter; content: string } | null;\n\nexport interface BuildReconcileManifestOptions {\n files: Iterable<ReconcileFileState>;\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>;\n parseMemory: ReconcileMemoryParser;\n cachedFiles?: Iterable<ReconcileManifestFile>;\n citationTemplate?: string;\n}\n\nconst SHA256_PATTERN = /^[a-f0-9]{64}$/i;\nconst MEMORY_DIRS = new Set(RECALL_FALLBACK_DIRS);\n\nfunction isMemoryPath(filePath: string): boolean {\n if (!filePath.endsWith(\".md\")) return false;\n const segments = filePath.split(\"/\");\n let index = 0;\n if (segments[index] === \"cold\" || segments[index] === \"archive\") index += 1;\n return MEMORY_DIRS.has(segments[index] ?? \"\");\n}\n\n\nfunction parsedMemoryIdentity(\n filePath: string,\n raw: Buffer | string,\n parseMemory: ReconcileMemoryParser,\n citationTemplate: string,\n): ReconcileMemoryIdentity | undefined {\n if (!isMemoryPath(filePath)) return undefined;\n const parsed = parseMemory(Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : raw);\n if (!parsed?.frontmatter.id) return undefined;\n\n const storedHash =\n parsed.frontmatter.contentHash &&\n SHA256_PATTERN.test(parsed.frontmatter.contentHash)\n ? parsed.frontmatter.contentHash.toLowerCase()\n : undefined;\n const candidates = storedContentIdentityCandidates(parsed.content, (content) =>\n stripCitationForTemplate(content, citationTemplate)\n );\n const bodyHash = ContentHashIndex.computeHash(candidates[0] ?? \"\");\n const currentMatch = candidates.find(\n (content) => ContentHashIndex.computeHash(content) === storedHash\n );\n const legacyMatch = [...candidates].reverse().find(\n (content) => computeLegacyContentHash(content) === storedHash\n );\n let contentHash: string;\n let contentHashAliases: string[] | undefined;\n if (currentMatch) {\n contentHash = ContentHashIndex.computeHash(currentMatch);\n } else if (legacyMatch && normalizeLegacyContent(legacyMatch).length > 0) {\n // A non-empty legacy equality is ambiguous (issue #2367): the persisted\n // hash may be an explicit contentHashSource identity that merely collides\n // with the body's ASCII skeleton under the lossy legacy normalizer, and\n // nothing in the record proves which it is. Keep the persisted hash as\n // the primary identity and expose the recovered current identity as an\n // alias so replicas carrying either form still collapse.\n contentHash = storedHash ?? bodyHash;\n const recovered = ContentHashIndex.computeHash(legacyMatch);\n if (recovered !== contentHash) contentHashAliases = [recovered];\n } else {\n // An EMPTY legacy skeleton identifies nothing (every non-ASCII body maps\n // to it), so preserving it would collapse unrelated records. Recovering\n // the current identity here is repair, not replacement.\n contentHash = legacyMatch ? ContentHashIndex.computeHash(legacyMatch) : storedHash ?? bodyHash;\n }\n\n return {\n id: parsed.frontmatter.id,\n category: parsed.frontmatter.category,\n contentHash,\n ...(contentHashAliases ? { contentHashAliases } : {}),\n normalizerVersion: CONTENT_HASH_NORMALIZER_VERSION,\n identityResolutionVersion: IDENTITY_RESOLUTION_VERSION,\n status: inferMemoryStatus(parsed.frontmatter, filePath),\n };\n}\n\nexport async function buildReconcileManifestFile(\n file: ReconcileFileState,\n readFile: (file: ReconcileFileState) => Promise<Buffer | string | null>,\n parseMemory: ReconcileMemoryParser,\n citationTemplate = DEFAULT_CITATION_FORMAT,\n): Promise<ReconcileManifestFile> {\n let raw: Buffer | string | null = null;\n if (isMemoryPath(file.path)) {\n try {\n raw = await readFile(file);\n } catch {\n raw = null;\n }\n }\n if (raw !== null && createHash(\"sha256\").update(raw).digest(\"hex\") !== file.sha256.toLowerCase()) {\n raw = null;\n }\n const memory = raw === null ? undefined : parsedMemoryIdentity(file.path, raw, parseMemory, citationTemplate);\n return { ...file, ...(memory ? { memory } : {}) };\n}\n\nexport async function buildReconcileManifest(options: BuildReconcileManifestOptions): Promise<ReconcileManifest> {\n const cachedByPath = new Map<string, ReconcileManifestFile>();\n for (const cached of options.cachedFiles ?? []) {\n cachedByPath.set(cached.path, cached);\n }\n\n const files: ReconcileManifestFile[] = [];\n for (const file of options.files) {\n const cached = cachedByPath.get(file.path);\n if (\n cached?.sha256.toLowerCase() === file.sha256.toLowerCase() &&\n (cached.memory === undefined ||\n (cached.memory.normalizerVersion === CONTENT_HASH_NORMALIZER_VERSION &&\n cached.memory.identityResolutionVersion === IDENTITY_RESOLUTION_VERSION))\n ) {\n files.push({ ...file, ...(cached.memory ? { memory: cached.memory } : {}) });\n continue;\n }\n\n files.push(await buildReconcileManifestFile(\n file,\n options.readFile,\n options.parseMemory,\n options.citationTemplate,\n ));\n }\n files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));\n return {\n format: RECONCILE_MANIFEST_FORMAT,\n schemaVersion: RECONCILE_MANIFEST_SCHEMA_VERSION,\n files,\n };\n}\n\nfunction activeFactByPath(manifest: ReconcileManifest | undefined): Map<string, ActiveFactManifestFile> {\n const result = new Map<string, ActiveFactManifestFile>();\n for (const file of manifest?.files ?? []) {\n if (file.memory?.category === \"fact\" && file.memory.status === \"active\") {\n result.set(file.path, file as ActiveFactManifestFile);\n }\n }\n return result;\n}\n\nfunction memoryIdentityHashes(memory: ReconcileMemoryIdentity): string[] {\n return [memory.contentHash, ...(memory.contentHashAliases ?? [])];\n}\n\nfunction contentHashRows(\n files: Iterable<ActiveFactManifestFile>,\n contentHash: string,\n): ContentHashPathEntry[] {\n const rows: ContentHashPathEntry[] = [];\n for (const file of files) {\n rows.push({ path: file.path, contentHash });\n }\n return rows;\n}\n\nfunction classifySemanticChange(\n current: ReconcileSemanticAgreement,\n prior: ReconcileSemanticAgreement | undefined\n): ReconcileSemanticChange {\n if (!prior) return \"unchanged\";\n const localChanged = current.local.sha256 !== prior.local.sha256;\n const peerChanged = current.peer.sha256 !== prior.peer.sha256;\n if (localChanged && peerChanged) return \"both_modified\";\n if (localChanged) return \"local_changed\";\n if (peerChanged) return \"peer_changed\";\n return \"unchanged\";\n}\n\nexport function collapseActiveFactDuplicates(\n plan: ReconcilePlan,\n localManifests: ReadonlyMap<string, ReconcileManifest>,\n peerManifests: ReadonlyMap<string, ReconcileManifest>,\n priorSemanticAgreements?: ReadonlyMap<string, readonly ReconcileSemanticAgreement[]>,\n): ReconcilePlan {\n const entriesByNamespace = new Map<string, ReconcilePlanEntry[]>();\n for (const entry of plan.entries) {\n const entries = entriesByNamespace.get(entry.namespace) ?? [];\n entries.push({ ...entry });\n entriesByNamespace.set(entry.namespace, entries);\n }\n\n let changed = false;\n for (const namespace of new Set([...localManifests.keys(), ...peerManifests.keys()])) {\n const entries = entriesByNamespace.get(namespace) ?? [];\n const localManifest = localManifests.get(namespace);\n const peerManifest = peerManifests.get(namespace);\n const localByPath = activeFactByPath(localManifest);\n const peerByPath = activeFactByPath(peerManifest);\n const localFilesByPath = new Map((localManifest?.files ?? []).map((file) => [file.path, file]));\n const peerFilesByPath = new Map((peerManifest?.files ?? []).map((file) => [file.path, file]));\n const priorSemanticByPathPair = new Map(\n (priorSemanticAgreements?.get(namespace) ?? []).map((agreement) => [\n semanticAgreementKey(agreement),\n agreement,\n ])\n );\n const localByHash = new Map<string, ActiveFactManifestFile[]>();\n const peerByHash = new Map<string, ActiveFactManifestFile[]>();\n\n for (const file of localByPath.values()) {\n for (const hash of memoryIdentityHashes(file.memory)) {\n const bucket = localByHash.get(hash) ?? [];\n bucket.push(file);\n localByHash.set(hash, bucket);\n }\n }\n for (const file of peerByPath.values()) {\n for (const hash of memoryIdentityHashes(file.memory)) {\n const bucket = peerByHash.get(hash) ?? [];\n bucket.push(file);\n peerByHash.set(hash, bucket);\n }\n }\n\n const removed = new Set<ReconcilePlanEntry>();\n const replacements: ReconcilePlanEntry[] = [];\n const processedPathPairs = new Set<string>();\n for (const hash of new Set([...localByHash.keys(), ...peerByHash.keys()])) {\n const localCandidates = (localByHash.get(hash) ?? []).filter((file) => {\n const opposite = peerFilesByPath.get(file.path);\n const activeOpposite = peerByPath.get(file.path);\n return opposite === undefined || (\n activeOpposite !== undefined &&\n memoryIdentityHashes(activeOpposite.memory).includes(hash)\n );\n });\n const peerCandidates = (peerByHash.get(hash) ?? []).filter((file) => {\n const opposite = localFilesByPath.get(file.path);\n const activeOpposite = localByPath.get(file.path);\n return opposite === undefined || (\n activeOpposite !== undefined &&\n memoryIdentityHashes(activeOpposite.memory).includes(hash)\n );\n });\n const localPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(localCandidates, hash));\n const peerPath = ContentHashIndex.resolvePathByHash(hash, contentHashRows(peerCandidates, hash));\n\n if (localPath && peerPath && localPath !== peerPath) {\n const pathPair = `${localPath}\\0${peerPath}`;\n if (processedPathPairs.has(pathPair)) continue;\n processedPathPairs.add(pathPair);\n const localFile = localByPath.get(localPath);\n const peerFile = peerByPath.get(peerPath);\n if (!localFile || !peerFile) continue;\n const duplicatePaths = new Set([\n ...localCandidates.map((file) => file.path),\n ...peerCandidates.map((file) => file.path),\n ]);\n const authoritativeSamePathEntries = new Set(entries.filter(\n (entry) =>\n duplicatePaths.has(entry.path)\n && localFilesByPath.has(entry.path)\n && peerFilesByPath.has(entry.path)\n && entry.action !== \"identical\"\n ));\n if (authoritativeSamePathEntries.size > 0) {\n for (const entry of entries) {\n if (\n duplicatePaths.has(entry.path)\n && !authoritativeSamePathEntries.has(entry)\n && (entry.action === \"pull\" || entry.action === \"push\" || entry.action === \"identical\")\n ) {\n removed.add(entry);\n changed = true;\n }\n }\n continue;\n }\n const unsafeEntry = entries.some(\n (entry) => duplicatePaths.has(entry.path) && (entry.action === \"suppress\" || entry.action === \"conflict\")\n );\n if (unsafeEntry) continue;\n for (const entry of entries) {\n if (\n duplicatePaths.has(entry.path) &&\n (entry.action === \"pull\" || entry.action === \"push\" || entry.action === \"identical\")\n ) {\n removed.add(entry);\n }\n }\n const semanticAgreement: ReconcileSemanticAgreement = {\n local: { path: localPath, sha256: localFile.sha256 },\n peer: { path: peerPath, sha256: peerFile.sha256 },\n };\n replacements.push({\n path: localPath < peerPath ? localPath : peerPath,\n namespace,\n action: \"identical\",\n reason: \"semantic_duplicate\",\n semanticAgreement,\n semanticChange: classifySemanticChange(\n semanticAgreement,\n priorSemanticByPathPair.get(semanticAgreementKey(semanticAgreement))\n ),\n });\n changed = true;\n continue;\n }\n\n const sameSideEntries = entries.filter((entry) => {\n if (localPath && entry.reason === \"local_only\") {\n return localCandidates.some((file) => file.path === entry.path);\n }\n if (peerPath && entry.reason === \"peer_only\") {\n return peerCandidates.some((file) => file.path === entry.path);\n }\n return false;\n });\n const canonicalPath = localPath ?? peerPath;\n const hasSharedCanonical = localPath !== undefined && localPath === peerPath;\n if (!canonicalPath || sameSideEntries.length === 0 || (!hasSharedCanonical && sameSideEntries.length < 2)) {\n continue;\n }\n for (const entry of sameSideEntries) {\n if (entry.path !== canonicalPath) {\n removed.add(entry);\n changed = true;\n }\n }\n }\n\n if (removed.size > 0 || replacements.length > 0) {\n entriesByNamespace.set(\n namespace,\n [...entries.filter((entry) => !removed.has(entry)), ...replacements].sort(compareReconcilePlanEntries)\n );\n }\n }\n\n if (!changed) return plan;\n const entries = [...entriesByNamespace.values()].flat().sort(compareReconcilePlanEntries);\n return {\n entries,\n byNamespace: summarizeReconcilePlan(entries),\n converged: entries.every((entry) => entry.action === \"identical\"),\n };\n}\n"],"mappings":"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","names":["entries"]}