@remnic/core 9.30.0 → 9.31.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 (495) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +50 -44
  3. package/dist/access-authorization-probe.d.ts +10 -10
  4. package/dist/access-authorization-probe.js +51 -45
  5. package/dist/access-boundary.d.ts +13 -11
  6. package/dist/access-boundary.js +50 -44
  7. package/dist/access-cli.js +168 -123
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +119 -0
  10. package/dist/access-extraction-force-flush.js +166 -0
  11. package/dist/access-health-types.d.ts +1 -1
  12. package/dist/access-http-lcm-compaction.d.ts +47 -13
  13. package/dist/access-http-lcm-compaction.js +7 -3
  14. package/dist/access-http-lifecycle-flush.d.ts +132 -0
  15. package/dist/access-http-lifecycle-flush.js +9 -0
  16. package/dist/access-http-lifecycle-flush.js.map +1 -0
  17. package/dist/access-http.d.ts +11 -10
  18. package/dist/access-http.js +66 -59
  19. package/dist/access-identity-continuity-surface.d.ts +8 -8
  20. package/dist/access-identity-continuity-surface.js +50 -44
  21. package/dist/access-lcm-surface.d.ts +10 -10
  22. package/dist/access-lcm-surface.js +50 -44
  23. package/dist/access-mcp-output-schemas.js +1 -1
  24. package/dist/access-mcp.d.ts +16 -10
  25. package/dist/access-mcp.js +58 -52
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-VfXssvoI.d.ts → access-namespace-preflight-D4vW97H1.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +50 -44
  30. package/dist/access-observe-helpers.d.ts +22 -0
  31. package/dist/access-observe-helpers.js +10 -0
  32. package/dist/access-observe-helpers.js.map +1 -0
  33. package/dist/access-observe-write-surface.d.ts +51 -47
  34. package/dist/access-observe-write-surface.js +50 -44
  35. package/dist/access-operations-batch.js +53 -47
  36. package/dist/access-operations.d.ts +11 -11
  37. package/dist/access-operations.js +55 -49
  38. package/dist/access-recall-concurrency.d.ts +10 -10
  39. package/dist/access-recall-concurrency.js +50 -44
  40. package/dist/access-recall-response.d.ts +10 -10
  41. package/dist/access-recall-response.js +50 -44
  42. package/dist/access-recall-surface.d.ts +10 -10
  43. package/dist/access-recall-surface.js +50 -44
  44. package/dist/access-schema.d.ts +37 -7
  45. package/dist/access-schema.js +5 -3
  46. package/dist/{access-service-B5RwVsTV.d.ts → access-service-B6PZ_xUL.d.ts} +44 -20
  47. package/dist/access-service-helpers.d.ts +113 -0
  48. package/dist/access-service-helpers.js +8 -0
  49. package/dist/access-service-helpers.js.map +1 -0
  50. package/dist/access-service.d.ts +10 -10
  51. package/dist/access-service.js +50 -44
  52. package/dist/access-surface-catalog.d.ts +10 -10
  53. package/dist/access-surface-catalog.js +2 -0
  54. package/dist/access-surface-catalog.js.map +1 -1
  55. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  56. package/dist/action-confidence.d.ts +1 -1
  57. package/dist/active-memory-bridge.d.ts +1 -1
  58. package/dist/active-recall.d.ts +1 -1
  59. package/dist/active-recall.js +1 -1
  60. package/dist/adapters/index.js +7 -7
  61. package/dist/adapters/registry.js +3 -3
  62. package/dist/behavior-learner.d.ts +1 -1
  63. package/dist/behavior-signals.d.ts +1 -1
  64. package/dist/bootstrap.d.ts +8 -8
  65. package/dist/briefing.d.ts +2 -2
  66. package/dist/briefing.js +14 -14
  67. package/dist/buffer-surprise-report.d.ts +1 -1
  68. package/dist/buffer-turn-helpers.d.ts +5 -0
  69. package/dist/buffer-turn-helpers.js +24 -0
  70. package/dist/buffer-turn-helpers.js.map +1 -0
  71. package/dist/buffer.d.ts +17 -4
  72. package/dist/buffer.js +21 -1
  73. package/dist/bulk-import/index.d.ts +3 -3
  74. package/dist/calibration.d.ts +1 -1
  75. package/dist/capabilities.d.ts +1 -1
  76. package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
  77. package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
  78. package/dist/{capsule-merge-5KKJQBWQ.js → capsule-merge-2H2IUTBT.js} +4 -4
  79. package/dist/{catalog-V7inUQdp.d.ts → catalog-CGFYmTT8.d.ts} +1 -1
  80. package/dist/causal-behavior.d.ts +1 -1
  81. package/dist/causal-behavior.js +2 -2
  82. package/dist/causal-chain.js +2 -2
  83. package/dist/causal-consolidation.d.ts +1 -1
  84. package/dist/causal-consolidation.js +19 -19
  85. package/dist/causal-retrieval.js +2 -2
  86. package/dist/causal-trajectory-graph.d.ts +1 -1
  87. package/dist/causal-trajectory.js +1 -1
  88. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  89. package/dist/{chunk-GIBMDSJ2.js → chunk-27P5YVDU.js} +2 -2
  90. package/dist/{chunk-2SA56WMI.js → chunk-2LTDWSR6.js} +4 -4
  91. package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
  92. package/dist/{chunk-YTSNAUXN.js → chunk-3F2LKUMU.js} +22 -8
  93. package/dist/chunk-3F2LKUMU.js.map +1 -0
  94. package/dist/chunk-3QL24R5Y.js +9 -0
  95. package/dist/chunk-3QL24R5Y.js.map +1 -0
  96. package/dist/chunk-4RNZMRAV.js +60 -0
  97. package/dist/chunk-4RNZMRAV.js.map +1 -0
  98. package/dist/{chunk-6U7F52DE.js → chunk-4XHR3I67.js} +60 -60
  99. package/dist/chunk-5IVLTFOV.js +65 -0
  100. package/dist/chunk-5IVLTFOV.js.map +1 -0
  101. package/dist/{chunk-2EUVEDF5.js → chunk-5XA7PQ5I.js} +2 -2
  102. package/dist/{chunk-ALSGMEJR.js → chunk-65ZPVYTA.js} +7 -7
  103. package/dist/{chunk-5VQJBH2G.js → chunk-6TAUHL33.js} +2 -2
  104. package/dist/{chunk-HUHX2OCX.js → chunk-7DRETLP5.js} +1 -1
  105. package/dist/chunk-7DRETLP5.js.map +1 -0
  106. package/dist/{chunk-RGIWINDN.js → chunk-7G5MH4NT.js} +30 -30
  107. package/dist/{chunk-WVO4G37W.js → chunk-7TEZUUGM.js} +3 -3
  108. package/dist/{chunk-MJCGLM25.js → chunk-7VUAG236.js} +5 -5
  109. package/dist/{chunk-M3C2V3PV.js → chunk-AJEMDQNA.js} +12 -12
  110. package/dist/{chunk-RKNJBZ55.js → chunk-AU7Q3LSC.js} +7 -7
  111. package/dist/{chunk-ACXPX4AG.js → chunk-BR2K43MK.js} +2 -2
  112. package/dist/{chunk-IYZ5K7MU.js → chunk-BUE5E2HL.js} +4 -187
  113. package/dist/chunk-BUE5E2HL.js.map +1 -0
  114. package/dist/{chunk-CZRYLSSW.js → chunk-BUGVGH4N.js} +2 -2
  115. package/dist/{chunk-YTQNQ4KB.js → chunk-C4VQMFVM.js} +3 -3
  116. package/dist/{chunk-ZPSVBSOF.js → chunk-CIVDJD6P.js} +3 -3
  117. package/dist/{chunk-K5GB36ME.js → chunk-CZDOT5I2.js} +2 -2
  118. package/dist/{chunk-VI2JQPNQ.js → chunk-E4PWACUN.js} +2 -2
  119. package/dist/{chunk-D2ANTDGO.js → chunk-E6BMSH7U.js} +2 -2
  120. package/dist/{chunk-P5PXWTW7.js → chunk-EJCAV3QZ.js} +3 -3
  121. package/dist/{chunk-CKMO4RDY.js → chunk-EMDLM3LW.js} +4 -4
  122. package/dist/chunk-ER7W6H4T.js +112 -0
  123. package/dist/chunk-ER7W6H4T.js.map +1 -0
  124. package/dist/{chunk-6FUPCJUL.js → chunk-FI4F5X2V.js} +54 -54
  125. package/dist/chunk-FI4F5X2V.js.map +1 -0
  126. package/dist/{chunk-LGHKJABJ.js → chunk-GOUILH55.js} +40 -18
  127. package/dist/chunk-GOUILH55.js.map +1 -0
  128. package/dist/{chunk-G5R3D5UP.js → chunk-GTTAHHD3.js} +2 -2
  129. package/dist/{chunk-H5CPS5JP.js → chunk-H36LJIPD.js} +3 -3
  130. package/dist/{chunk-AITCS2RC.js → chunk-IJ7HK452.js} +4 -4
  131. package/dist/{chunk-D3LMYTBV.js → chunk-J7WZUL2K.js} +9 -9
  132. package/dist/{chunk-5W4ZLBEZ.js → chunk-JCFTIQBR.js} +2 -2
  133. package/dist/{chunk-XOZ4ALGB.js → chunk-KE353EWI.js} +3 -3
  134. package/dist/{chunk-W5EG6LE3.js → chunk-KIT6M7EB.js} +3 -3
  135. package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
  136. package/dist/{chunk-Z54EM5YZ.js → chunk-MAXVH44E.js} +7 -7
  137. package/dist/{chunk-WZFAPHIK.js → chunk-MU7ZHSZE.js} +2 -2
  138. package/dist/chunk-N5Z4EVOR.js +123 -0
  139. package/dist/chunk-N5Z4EVOR.js.map +1 -0
  140. package/dist/{chunk-66772WBP.js → chunk-NFXQJHJD.js} +5 -5
  141. package/dist/{chunk-AZ5BTEKX.js → chunk-NQUF7XKR.js} +2 -2
  142. package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
  143. package/dist/{chunk-NHWB6HG2.js → chunk-NYCGIQRA.js} +2 -2
  144. package/dist/{chunk-4WKA6I65.js → chunk-OGCNZPKX.js} +1119 -309
  145. package/dist/chunk-OGCNZPKX.js.map +1 -0
  146. package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
  147. package/dist/{chunk-FDAMS4PK.js → chunk-PNPOWBGC.js} +2 -2
  148. package/dist/{chunk-IC6CBHCA.js → chunk-QGENAYVS.js} +2 -2
  149. package/dist/{chunk-GBJ4RDFR.js → chunk-QIHIHZYC.js} +66 -91
  150. package/dist/chunk-QIHIHZYC.js.map +1 -0
  151. package/dist/{chunk-PUS63Q3G.js → chunk-RUYJ7TWU.js} +517 -2011
  152. package/dist/chunk-RUYJ7TWU.js.map +1 -0
  153. package/dist/{chunk-4A6YGWQN.js → chunk-TL4TO3EA.js} +115 -120
  154. package/dist/chunk-TL4TO3EA.js.map +1 -0
  155. package/dist/{chunk-SPJXKAVF.js → chunk-U52AKICI.js} +14 -13
  156. package/dist/chunk-U52AKICI.js.map +1 -0
  157. package/dist/chunk-ULARSG5Z.js +203 -0
  158. package/dist/chunk-ULARSG5Z.js.map +1 -0
  159. package/dist/{chunk-62U4J2GN.js → chunk-UR77VKF7.js} +2 -2
  160. package/dist/{chunk-JCBWCYEJ.js → chunk-VANLTS5F.js} +2 -2
  161. package/dist/{chunk-4Z4XNEWZ.js → chunk-VCD4PSK2.js} +56 -12
  162. package/dist/chunk-VCD4PSK2.js.map +1 -0
  163. package/dist/{chunk-RMMVQQA6.js → chunk-WDISJRMG.js} +2 -2
  164. package/dist/{chunk-B6JDYXL7.js → chunk-WWUVONGW.js} +7 -1
  165. package/dist/chunk-WWUVONGW.js.map +1 -0
  166. package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
  167. package/dist/{chunk-TH2LSRMG.js → chunk-XHDIB4T4.js} +2 -2
  168. package/dist/{chunk-CVILPI77.js → chunk-XOQSEF7X.js} +6 -6
  169. package/dist/{chunk-LBOD4U5B.js → chunk-YFOMN2II.js} +6 -6
  170. package/dist/{chunk-RPW2NOU6.js → chunk-YIAA2X3D.js} +41 -1
  171. package/dist/chunk-YIAA2X3D.js.map +1 -0
  172. package/dist/chunk-YPC7W6GA.js +1604 -0
  173. package/dist/chunk-YPC7W6GA.js.map +1 -0
  174. package/dist/{chunk-I5NLEENJ.js → chunk-Z4SWV4VW.js} +3 -3
  175. package/dist/{chunk-PHWUFPCO.js → chunk-ZCPP5OW6.js} +61 -53
  176. package/dist/chunk-ZCPP5OW6.js.map +1 -0
  177. package/dist/{cli-C4GbETPC.d.ts → cli-BptUDTtp.d.ts} +5 -5
  178. package/dist/cli.d.ts +12 -12
  179. package/dist/cli.js +91 -84
  180. package/dist/compounding/engine.d.ts +2 -2
  181. package/dist/compounding/engine.js +14 -14
  182. package/dist/compounding/preference-consolidator.d.ts +1 -1
  183. package/dist/compression-optimizer.d.ts +1 -1
  184. package/dist/config.d.ts +1 -1
  185. package/dist/config.js +1 -1
  186. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  187. package/dist/connectors/codex-materialize-runner.js +14 -14
  188. package/dist/connectors/codex-materialize.d.ts +1 -1
  189. package/dist/connectors/index.d.ts +1 -1
  190. package/dist/connectors/index.js +17 -17
  191. package/dist/consolidation-provenance-check.d.ts +2 -2
  192. package/dist/consolidation-provenance-check.js +5 -5
  193. package/dist/consolidation-undo.d.ts +2 -2
  194. package/dist/consolidation-undo.js +3 -3
  195. package/dist/contradiction/index.d.ts +2 -2
  196. package/dist/contradiction/index.js +4 -4
  197. package/dist/conversation-index/backend.d.ts +1 -1
  198. package/dist/conversation-index/backend.js +2 -2
  199. package/dist/conversation-index/chunker.d.ts +1 -1
  200. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  201. package/dist/conversation-index/indexer.d.ts +1 -1
  202. package/dist/conversation-index/search.d.ts +1 -1
  203. package/dist/corpus-watermark.d.ts +1 -1
  204. package/dist/corpus-watermark.js +26 -26
  205. package/dist/day-summary.d.ts +1 -1
  206. package/dist/delinearize.d.ts +1 -1
  207. package/dist/direct-answer-wiring.d.ts +1 -1
  208. package/dist/direct-answer.d.ts +1 -1
  209. package/dist/embedding-fallback.d.ts +1 -1
  210. package/dist/enrichment/index.d.ts +1 -1
  211. package/dist/entity-retrieval.d.ts +2 -2
  212. package/dist/entity-retrieval.js +14 -14
  213. package/dist/entity-schema.d.ts +1 -1
  214. package/dist/explicit-capture.d.ts +8 -8
  215. package/dist/extraction-error-classification.d.ts +1 -1
  216. package/dist/extraction-faithfulness.d.ts +1 -1
  217. package/dist/extraction-judge-telemetry.d.ts +1 -1
  218. package/dist/extraction-judge-training.d.ts +1 -1
  219. package/dist/extraction-judge.d.ts +1 -1
  220. package/dist/extraction-liveness.d.ts +1 -1
  221. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  222. package/dist/extraction-source-grounding.d.ts +15 -2
  223. package/dist/extraction-source-grounding.js +10 -1
  224. package/dist/extraction.d.ts +2 -15
  225. package/dist/extraction.js +5 -4
  226. package/dist/fallback-llm.d.ts +1 -1
  227. package/dist/graph-dashboard-diff.d.ts +1 -1
  228. package/dist/graph-dashboard-key.d.ts +1 -1
  229. package/dist/graph-dashboard-parser.d.ts +1 -1
  230. package/dist/graph-edge-reinforcement.d.ts +1 -1
  231. package/dist/graph-snapshot.d.ts +1 -1
  232. package/dist/graph.d.ts +1 -1
  233. package/dist/importance.d.ts +1 -1
  234. package/dist/importers/index.d.ts +1 -1
  235. package/dist/in-flight-reads.d.ts +1 -1
  236. package/dist/index.d.ts +19 -19
  237. package/dist/index.js +215 -207
  238. package/dist/intent.d.ts +1 -1
  239. package/dist/lcm/engine.d.ts +1 -1
  240. package/dist/lcm/engine.js +3 -3
  241. package/dist/lcm/index.d.ts +1 -1
  242. package/dist/lcm/index.js +6 -6
  243. package/dist/lcm/tools.d.ts +1 -1
  244. package/dist/lifecycle.d.ts +1 -1
  245. package/dist/live-connectors-runner.d.ts +1 -1
  246. package/dist/local-llm-helpers.d.ts +7 -0
  247. package/dist/local-llm-helpers.js +16 -0
  248. package/dist/local-llm-helpers.js.map +1 -0
  249. package/dist/local-llm.d.ts +3 -6
  250. package/dist/local-llm.js +2 -1
  251. package/dist/local-model-endpoint.d.ts +1 -1
  252. package/dist/maintenance/memory-governance.d.ts +1 -1
  253. package/dist/maintenance/memory-governance.js +14 -14
  254. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  255. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -14
  256. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  257. package/dist/maintenance/rebuild-memory-projection.js +15 -15
  258. package/dist/{maintenance-CL30NWtc.d.ts → maintenance-b6f92bRz.d.ts} +3 -3
  259. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  260. package/dist/memory-action-policy.d.ts +1 -1
  261. package/dist/memory-cache.d.ts +1 -1
  262. package/dist/memory-corpus-version.js +2 -2
  263. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  264. package/dist/memory-projection-store.d.ts +1 -1
  265. package/dist/memory-provenance.d.ts +1 -1
  266. package/dist/memory-worth-outcomes.d.ts +2 -2
  267. package/dist/models-json.d.ts +1 -1
  268. package/dist/namespaces/migrate.d.ts +3 -3
  269. package/dist/namespaces/migrate.js +24 -24
  270. package/dist/namespaces/principal.d.ts +1 -1
  271. package/dist/namespaces/search.d.ts +1 -1
  272. package/dist/namespaces/search.js +9 -9
  273. package/dist/namespaces/storage.d.ts +3 -3
  274. package/dist/namespaces/storage.js +14 -14
  275. package/dist/native-knowledge.d.ts +1 -1
  276. package/dist/offline-sync-impression-drain.d.ts +1 -1
  277. package/dist/offline-sync-impression-drain.js +6 -5
  278. package/dist/operator-doctor-corpus.d.ts +1 -1
  279. package/dist/operator-doctor-corpus.js +29 -29
  280. package/dist/operator-doctor-replica.d.ts +1 -1
  281. package/dist/operator-doctor-replica.js +3 -3
  282. package/dist/operator-toolkit.d.ts +3 -3
  283. package/dist/operator-toolkit.js +38 -37
  284. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  285. package/dist/orchestration/maintenance.d.ts +4 -4
  286. package/dist/orchestration/maintenance.js +22 -21
  287. package/dist/{orchestrator-CKTCRwWV.d.ts → orchestrator-3uGxC1qO.d.ts} +72 -34
  288. package/dist/orchestrator.d.ts +8 -8
  289. package/dist/orchestrator.js +167 -159
  290. package/dist/page-versioning.js +3 -3
  291. package/dist/patterns-cli.d.ts +1 -1
  292. package/dist/{pipeline-B7wj4rRZ.d.ts → pipeline-DepuNr-m.d.ts} +1 -1
  293. package/dist/policy-runtime.d.ts +1 -1
  294. package/dist/proactive-contention.d.ts +1 -1
  295. package/dist/provenance.d.ts +1 -1
  296. package/dist/{qmd-q9tg4dHp.d.ts → qmd-Dalr3Jby.d.ts} +1 -1
  297. package/dist/qmd-preflight.d.ts +2 -2
  298. package/dist/qmd-recall-cache.d.ts +1 -1
  299. package/dist/qmd.d.ts +2 -2
  300. package/dist/qmd.js +4 -4
  301. package/dist/recall-concurrency-config.d.ts +1 -1
  302. package/dist/recall-disclosure-escalation.d.ts +1 -1
  303. package/dist/recall-explain-renderer.d.ts +1 -1
  304. package/dist/recall-explain-renderer.js +3 -3
  305. package/dist/recall-memory-map.d.ts +1 -1
  306. package/dist/recall-planner-llm.d.ts +1 -1
  307. package/dist/recall-state.d.ts +1 -1
  308. package/dist/recall-tag-filter.d.ts +1 -1
  309. package/dist/recall-timings.d.ts +1 -1
  310. package/dist/recall-xray-cli.d.ts +1 -1
  311. package/dist/recall-xray-cli.js +4 -4
  312. package/dist/recall-xray-renderer.d.ts +1 -1
  313. package/dist/recall-xray-renderer.js +3 -3
  314. package/dist/recall-xray.d.ts +1 -1
  315. package/dist/recall-xray.js +2 -2
  316. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  317. package/dist/replay/normalizers/claude.d.ts +1 -1
  318. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  319. package/dist/replay/normalizers/shared.d.ts +1 -1
  320. package/dist/replay/runner.d.ts +1 -1
  321. package/dist/replay/types.d.ts +1 -1
  322. package/dist/replica-divergence.d.ts +1 -1
  323. package/dist/replica-divergence.js +2 -2
  324. package/dist/replica-peers-config.d.ts +1 -1
  325. package/dist/resolve-auth-token.d.ts +1 -1
  326. package/dist/resume-bundles.js +1 -1
  327. package/dist/retrieval-agents.d.ts +2 -2
  328. package/dist/retrieval-tiers.d.ts +1 -1
  329. package/dist/routing/engine.d.ts +1 -1
  330. package/dist/routing/store.d.ts +1 -1
  331. package/dist/salvage-envelope.d.ts +1 -1
  332. package/dist/{scope-profiles-CWDyglPM.d.ts → scope-profiles-BpiM5hTU.d.ts} +1 -1
  333. package/dist/search/embed-helper.d.ts +1 -1
  334. package/dist/search/factory.d.ts +1 -1
  335. package/dist/search/factory.js +8 -8
  336. package/dist/search/index.d.ts +1 -1
  337. package/dist/search/index.js +12 -12
  338. package/dist/search/lancedb-backend.d.ts +1 -1
  339. package/dist/search/meilisearch-backend.d.ts +1 -1
  340. package/dist/search/noop-backend.d.ts +1 -1
  341. package/dist/search/orama-backend.d.ts +1 -1
  342. package/dist/search/port.d.ts +1 -1
  343. package/dist/search/remote-backend.d.ts +1 -1
  344. package/dist/{semantic-consolidation-BUE3deLn.d.ts → semantic-consolidation-CMtVrf9f.d.ts} +1 -1
  345. package/dist/semantic-consolidation.d.ts +2 -2
  346. package/dist/semantic-consolidation.js +16 -16
  347. package/dist/semantic-rule-promotion.js +14 -14
  348. package/dist/semantic-rule-verifier.d.ts +1 -1
  349. package/dist/semantic-rule-verifier.js +14 -14
  350. package/dist/{service-CXgM0bQG.d.ts → service-DuAxwSgg.d.ts} +2 -2
  351. package/dist/session-observer-bands.d.ts +1 -1
  352. package/dist/session-observer-state.d.ts +1 -1
  353. package/dist/shared-context/manager.d.ts +1 -1
  354. package/dist/signal.d.ts +1 -1
  355. package/dist/{storage-DysJq-XH.d.ts → storage-CF0Ih8GP.d.ts} +1 -1
  356. package/dist/storage.d.ts +2 -2
  357. package/dist/storage.js +13 -13
  358. package/dist/summarizer.d.ts +1 -1
  359. package/dist/summarizer.js +3 -2
  360. package/dist/summary-snapshot.d.ts +1 -1
  361. package/dist/temporal-supersession.d.ts +2 -2
  362. package/dist/temporal-timeline-recall.d.ts +1 -1
  363. package/dist/temporal-validity.d.ts +1 -1
  364. package/dist/threading.d.ts +1 -1
  365. package/dist/tier-migration.d.ts +2 -2
  366. package/dist/tier-routing.d.ts +1 -1
  367. package/dist/tokens.js +2 -2
  368. package/dist/topics.d.ts +1 -1
  369. package/dist/transcript.d.ts +1 -1
  370. package/dist/transfer/backup.js +2 -2
  371. package/dist/transfer/capsule-export.js +2 -2
  372. package/dist/transfer/capsule-import.js +5 -5
  373. package/dist/trust-score-stage.d.ts +1 -1
  374. package/dist/trust-score.d.ts +1 -1
  375. package/dist/{types-aPPzhnjT.d.ts → types-BpaYvJ6v.d.ts} +22 -2
  376. package/dist/types.d.ts +1 -1
  377. package/dist/types.js +1 -1
  378. package/dist/utility-runtime.d.ts +1 -1
  379. package/dist/verified-recall.js +14 -14
  380. package/dist/write-envelope.d.ts +1 -1
  381. package/package.json +2 -2
  382. package/src/access-boundary.ts +3 -0
  383. package/src/access-cli.test.ts +93 -0
  384. package/src/access-cli.ts +56 -2
  385. package/src/access-extraction-force-flush.ts +177 -0
  386. package/src/access-http-extraction-force-flush.test.ts +132 -0
  387. package/src/access-http-lcm-compaction.ts +99 -22
  388. package/src/access-http-lifecycle-flush.ts +81 -0
  389. package/src/access-http.test.ts +227 -0
  390. package/src/access-http.ts +33 -40
  391. package/src/access-mcp-output-schemas.ts +6 -0
  392. package/src/access-mcp.test.ts +40 -0
  393. package/src/access-mcp.ts +32 -1
  394. package/src/access-observe-helpers.ts +180 -0
  395. package/src/access-observe-write-surface.ts +78 -19
  396. package/src/access-operations-batch.ts +2 -1
  397. package/src/access-schema-pi.test.ts +17 -0
  398. package/src/access-schema.ts +28 -11
  399. package/src/access-service-helpers.ts +46 -0
  400. package/src/access-service-observe-lcm-parity.test.ts +781 -31
  401. package/src/access-service-observe-scope.test.ts +88 -0
  402. package/src/access-service.ts +46 -128
  403. package/src/access-surface-catalog.test.ts +32 -0
  404. package/src/access-surface-catalog.ts +2 -0
  405. package/src/buffer-session.test.ts +148 -0
  406. package/src/buffer-turn-helpers.ts +152 -0
  407. package/src/buffer.ts +126 -201
  408. package/src/correction/correction-access-wiring.ts +79 -27
  409. package/src/correction/correction-executor.test.ts +542 -1
  410. package/src/correction/correction-executor.ts +309 -89
  411. package/src/correction/correction-planner.test.ts +35 -1
  412. package/src/correction/correction-planner.ts +50 -3
  413. package/src/correction/correction-service.ts +12 -7
  414. package/src/correction/correction-storage-integration.test.ts +172 -1
  415. package/src/correction/passive-capture.test.ts +35 -0
  416. package/src/correction/passive-capture.ts +17 -3
  417. package/src/extraction-source-grounding.ts +55 -1
  418. package/src/extraction-timeout.test.ts +51 -0
  419. package/src/extraction.ts +64 -90
  420. package/src/local-llm-headers-timeout.test.ts +48 -0
  421. package/src/local-llm-helpers.ts +58 -0
  422. package/src/local-llm.ts +62 -58
  423. package/src/orchestration/extraction-run-helpers.ts +309 -0
  424. package/src/orchestration/extraction-run.test.ts +350 -7
  425. package/src/orchestration/extraction-run.ts +327 -250
  426. package/src/orchestration/recall-internal-deps.ts +385 -0
  427. package/src/orchestration/recall-internal.ts +16 -375
  428. package/src/orchestration/session-context.ts +193 -18
  429. package/src/orchestration/turn-ingestion.ts +61 -11
  430. package/src/orchestrator-flush.test.ts +511 -5
  431. package/src/orchestrator.ts +8 -6
  432. package/src/types.ts +2 -2
  433. package/dist/chunk-4A6YGWQN.js.map +0 -1
  434. package/dist/chunk-4WKA6I65.js.map +0 -1
  435. package/dist/chunk-4Z4XNEWZ.js.map +0 -1
  436. package/dist/chunk-6FUPCJUL.js.map +0 -1
  437. package/dist/chunk-B6JDYXL7.js.map +0 -1
  438. package/dist/chunk-GBJ4RDFR.js.map +0 -1
  439. package/dist/chunk-HUHX2OCX.js.map +0 -1
  440. package/dist/chunk-IYZ5K7MU.js.map +0 -1
  441. package/dist/chunk-LGHKJABJ.js.map +0 -1
  442. package/dist/chunk-PHWUFPCO.js.map +0 -1
  443. package/dist/chunk-PUS63Q3G.js.map +0 -1
  444. package/dist/chunk-RPW2NOU6.js.map +0 -1
  445. package/dist/chunk-SPJXKAVF.js.map +0 -1
  446. package/dist/chunk-YTSNAUXN.js.map +0 -1
  447. /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-extraction-force-flush.js.map} +0 -0
  448. /package/dist/{capsule-merge-5KKJQBWQ.js.map → capsule-merge-2H2IUTBT.js.map} +0 -0
  449. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  450. /package/dist/{chunk-GIBMDSJ2.js.map → chunk-27P5YVDU.js.map} +0 -0
  451. /package/dist/{chunk-2SA56WMI.js.map → chunk-2LTDWSR6.js.map} +0 -0
  452. /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
  453. /package/dist/{chunk-6U7F52DE.js.map → chunk-4XHR3I67.js.map} +0 -0
  454. /package/dist/{chunk-2EUVEDF5.js.map → chunk-5XA7PQ5I.js.map} +0 -0
  455. /package/dist/{chunk-ALSGMEJR.js.map → chunk-65ZPVYTA.js.map} +0 -0
  456. /package/dist/{chunk-5VQJBH2G.js.map → chunk-6TAUHL33.js.map} +0 -0
  457. /package/dist/{chunk-RGIWINDN.js.map → chunk-7G5MH4NT.js.map} +0 -0
  458. /package/dist/{chunk-WVO4G37W.js.map → chunk-7TEZUUGM.js.map} +0 -0
  459. /package/dist/{chunk-MJCGLM25.js.map → chunk-7VUAG236.js.map} +0 -0
  460. /package/dist/{chunk-M3C2V3PV.js.map → chunk-AJEMDQNA.js.map} +0 -0
  461. /package/dist/{chunk-RKNJBZ55.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  462. /package/dist/{chunk-ACXPX4AG.js.map → chunk-BR2K43MK.js.map} +0 -0
  463. /package/dist/{chunk-CZRYLSSW.js.map → chunk-BUGVGH4N.js.map} +0 -0
  464. /package/dist/{chunk-YTQNQ4KB.js.map → chunk-C4VQMFVM.js.map} +0 -0
  465. /package/dist/{chunk-ZPSVBSOF.js.map → chunk-CIVDJD6P.js.map} +0 -0
  466. /package/dist/{chunk-K5GB36ME.js.map → chunk-CZDOT5I2.js.map} +0 -0
  467. /package/dist/{chunk-VI2JQPNQ.js.map → chunk-E4PWACUN.js.map} +0 -0
  468. /package/dist/{chunk-D2ANTDGO.js.map → chunk-E6BMSH7U.js.map} +0 -0
  469. /package/dist/{chunk-P5PXWTW7.js.map → chunk-EJCAV3QZ.js.map} +0 -0
  470. /package/dist/{chunk-CKMO4RDY.js.map → chunk-EMDLM3LW.js.map} +0 -0
  471. /package/dist/{chunk-G5R3D5UP.js.map → chunk-GTTAHHD3.js.map} +0 -0
  472. /package/dist/{chunk-H5CPS5JP.js.map → chunk-H36LJIPD.js.map} +0 -0
  473. /package/dist/{chunk-AITCS2RC.js.map → chunk-IJ7HK452.js.map} +0 -0
  474. /package/dist/{chunk-D3LMYTBV.js.map → chunk-J7WZUL2K.js.map} +0 -0
  475. /package/dist/{chunk-5W4ZLBEZ.js.map → chunk-JCFTIQBR.js.map} +0 -0
  476. /package/dist/{chunk-XOZ4ALGB.js.map → chunk-KE353EWI.js.map} +0 -0
  477. /package/dist/{chunk-W5EG6LE3.js.map → chunk-KIT6M7EB.js.map} +0 -0
  478. /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
  479. /package/dist/{chunk-Z54EM5YZ.js.map → chunk-MAXVH44E.js.map} +0 -0
  480. /package/dist/{chunk-WZFAPHIK.js.map → chunk-MU7ZHSZE.js.map} +0 -0
  481. /package/dist/{chunk-66772WBP.js.map → chunk-NFXQJHJD.js.map} +0 -0
  482. /package/dist/{chunk-AZ5BTEKX.js.map → chunk-NQUF7XKR.js.map} +0 -0
  483. /package/dist/{chunk-W4FBGYGK.js.map → chunk-NRV4Y3PM.js.map} +0 -0
  484. /package/dist/{chunk-NHWB6HG2.js.map → chunk-NYCGIQRA.js.map} +0 -0
  485. /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
  486. /package/dist/{chunk-FDAMS4PK.js.map → chunk-PNPOWBGC.js.map} +0 -0
  487. /package/dist/{chunk-IC6CBHCA.js.map → chunk-QGENAYVS.js.map} +0 -0
  488. /package/dist/{chunk-62U4J2GN.js.map → chunk-UR77VKF7.js.map} +0 -0
  489. /package/dist/{chunk-JCBWCYEJ.js.map → chunk-VANLTS5F.js.map} +0 -0
  490. /package/dist/{chunk-RMMVQQA6.js.map → chunk-WDISJRMG.js.map} +0 -0
  491. /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
  492. /package/dist/{chunk-TH2LSRMG.js.map → chunk-XHDIB4T4.js.map} +0 -0
  493. /package/dist/{chunk-CVILPI77.js.map → chunk-XOQSEF7X.js.map} +0 -0
  494. /package/dist/{chunk-LBOD4U5B.js.map → chunk-YFOMN2II.js.map} +0 -0
  495. /package/dist/{chunk-I5NLEENJ.js.map → chunk-Z4SWV4VW.js.map} +0 -0
package/src/local-llm.ts CHANGED
@@ -8,6 +8,13 @@ import { mergeEnv, readEnvVar } from "./runtime/env.js";
8
8
  import { resolveLocalLlmCapabilities } from "./capabilities.js";
9
9
  import { resolvePipelineProcessingCapabilities } from "./capabilities.js";
10
10
  import { ChatTransport } from "./local-llm-transport.js";
11
+ import {
12
+ extractNonRecoverableBackendReason,
13
+ extractNonRecoverableBackendReasonFromErrorText,
14
+ isAbortError,
15
+ normalizeBackendTripReason,
16
+ waitForRetryBackoff,
17
+ } from "./local-llm-helpers.js";
11
18
 
12
19
  /** Trim trailing slash characters without backtracking regex. */
13
20
  function trimTrailingSlashes(s: string): string {
@@ -223,6 +230,7 @@ interface LocalLlmChatCompletionOptions {
223
230
  forceDisableThinking?: boolean;
224
231
  disableThinking?: boolean;
225
232
  priority?: LocalLlmRequestPriority;
233
+ signal?: AbortSignal;
226
234
  }
227
235
 
228
236
  interface LocalLlmQueuedRequest {
@@ -304,15 +312,6 @@ export class LocalLlmClient {
304
312
  return headers;
305
313
  }
306
314
 
307
- private isAbortError(err: unknown): boolean {
308
- if (!err || typeof err !== "object") return false;
309
- const maybe = err as { name?: string; message?: string };
310
- return (
311
- maybe.name === "AbortError" ||
312
- maybe.message === "This operation was aborted" ||
313
- maybe.message === "The operation was aborted"
314
- );
315
- }
316
315
 
317
316
  /**
318
317
  * Set the ModelRegistry for caching detected capabilities
@@ -356,7 +355,7 @@ export class LocalLlmClient {
356
355
  }
357
356
 
358
357
  private markBackendUnavailable(reason: string, durationMs: number): void {
359
- const normalizedReason = this.normalizeBackendTripReason(reason);
358
+ const normalizedReason = normalizeBackendTripReason(reason);
360
359
  if (durationMs > 0) {
361
360
  const untilMs = Date.now() + durationMs;
362
361
  this.getGlobalBackendState().set(this.getBackendKey(), { untilMs, reason: normalizedReason });
@@ -370,29 +369,6 @@ export class LocalLlmClient {
370
369
  );
371
370
  }
372
371
 
373
- private extractNonRecoverableBackendReason(reason: string): string | null {
374
- const match = reason.match(
375
- /Failed to load model|Library not loaded|different Team IDs|code signature|llm_engine_mlx_amphibian/i,
376
- );
377
- return match?.[0] ?? null;
378
- }
379
-
380
- private extractNonRecoverableBackendReasonFromErrorText(errorText: string): string | null {
381
- const directReason = this.extractNonRecoverableBackendReason(errorText);
382
- if (directReason) return directReason;
383
- try {
384
- const parsed = JSON.parse(errorText) as { error?: { message?: string } };
385
- return this.extractNonRecoverableBackendReason(parsed?.error?.message ?? "");
386
- } catch {
387
- return null;
388
- }
389
- }
390
-
391
- private normalizeBackendTripReason(reason: string): string {
392
- const cleaned = reason.replace(/\s+/g, " ").replace(/^[-:–—\s]+/, "").trim();
393
- if (!cleaned) return "unknown local backend failure";
394
- return cleaned.length > 160 ? `${cleaned.slice(0, 157)}...` : cleaned;
395
- }
396
372
 
397
373
  /**
398
374
  * Fetch with timeout for health checks
@@ -401,13 +377,15 @@ export class LocalLlmClient {
401
377
  url: string,
402
378
  timeoutMs: number = 2000,
403
379
  headers?: Record<string, string>,
380
+ signal?: AbortSignal,
404
381
  ): Promise<{ ok: boolean; data: unknown; status: number | null }> {
405
382
  const controller = new AbortController();
383
+ const requestSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
406
384
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
407
385
 
408
386
  try {
409
387
  const response = await fetch(url, {
410
- signal: controller.signal,
388
+ signal: requestSignal,
411
389
  headers: this.buildRequestHeaders({ Accept: "application/json", ...(headers ?? {}) }),
412
390
  });
413
391
  clearTimeout(timeout);
@@ -430,10 +408,13 @@ export class LocalLlmClient {
430
408
 
431
409
  private async probeLmStudioNativeModels(
432
410
  probeBaseUrl: string,
411
+ signal?: AbortSignal,
433
412
  ): Promise<{ matched: boolean; unauthorized: boolean }> {
434
413
  let unauthorized = false;
435
414
  for (const endpoint of ["/api/v1/models", "/api/v0/models"]) {
436
- const probe = await this.fetchWithTimeout(`${probeBaseUrl}${endpoint}`);
415
+ if (signal?.aborted) return { matched: false, unauthorized };
416
+ const probe = await this.fetchWithTimeout(`${probeBaseUrl}${endpoint}`, 2000, undefined, signal);
417
+ if (signal?.aborted) return { matched: false, unauthorized };
437
418
  if (probe.ok && isLmStudioNativeModelsResponse(probe.data)) {
438
419
  return { matched: true, unauthorized };
439
420
  }
@@ -448,7 +429,8 @@ export class LocalLlmClient {
448
429
  * Check if local LLM is available
449
430
  * Uses 127.0.0.1 instead of localhost to avoid DNS issues (consistent with tactician)
450
431
  */
451
- async checkAvailability(): Promise<boolean> {
432
+ async checkAvailability(signal?: AbortSignal): Promise<boolean> {
433
+ if (signal?.aborted) return false;
452
434
  // Cache health check results for 1 minute
453
435
  const now = Date.now();
454
436
  const trippedState = this.getTrippedBackendState(now);
@@ -474,14 +456,17 @@ export class LocalLlmClient {
474
456
  let sawUnauthorizedProbe = false;
475
457
 
476
458
  // Try to detect which server type is running
459
+ if (signal?.aborted) return false;
477
460
  for (const serverConfig of orderedLocalServers(configuredBaseUrl)) {
478
461
  const healthUrl = `${probeBaseUrl}${serverConfig.healthEndpoint}`;
479
462
  log.debug(`checking ${serverConfig.type} at ${healthUrl}`);
480
463
 
481
- const result = await this.fetchWithTimeout(healthUrl);
464
+ const result = await this.fetchWithTimeout(healthUrl, 2000, undefined, signal);
465
+ if (signal?.aborted) return false;
482
466
  if (result.ok && serverConfig.detectFn(result.data)) {
483
467
  if (serverConfig.type === "mlx") {
484
- const lmStudioProbe = await this.probeLmStudioNativeModels(probeBaseUrl);
468
+ const lmStudioProbe = await this.probeLmStudioNativeModels(probeBaseUrl, signal);
469
+ if (signal?.aborted) return false;
485
470
  if (lmStudioProbe.unauthorized) {
486
471
  sawUnauthorizedProbe = true;
487
472
  }
@@ -495,7 +480,8 @@ export class LocalLlmClient {
495
480
  }
496
481
  if (serverConfig.type === "llamacpp") {
497
482
  let sawLlamaCppSignal = false;
498
- const propsProbe = await this.fetchWithTimeout(`${probeBaseUrl}/props`);
483
+ const propsProbe = await this.fetchWithTimeout(`${probeBaseUrl}/props`, 2000, undefined, signal);
484
+ if (signal?.aborted) return false;
499
485
  if (propsProbe.ok && isLlamaCppPropsResponse(propsProbe.data)) {
500
486
  sawLlamaCppSignal = true;
501
487
  }
@@ -504,7 +490,8 @@ export class LocalLlmClient {
504
490
  }
505
491
 
506
492
  const modelsUrl = `${probeBaseUrl}${serverConfig.modelsEndpoint}`;
507
- const modelsProbe = await this.fetchWithTimeout(modelsUrl);
493
+ const modelsProbe = await this.fetchWithTimeout(modelsUrl, 2000, undefined, signal);
494
+ if (signal?.aborted) return false;
508
495
  if (modelsProbe.ok && isLlamaCppModelsResponse(modelsProbe.data)) {
509
496
  sawLlamaCppSignal = true;
510
497
  }
@@ -530,11 +517,13 @@ export class LocalLlmClient {
530
517
  sawUnauthorizedProbe = true;
531
518
  }
532
519
  }
520
+ if (signal?.aborted) return false;
533
521
 
534
522
  // Generic check if specific detection failed
535
523
  try {
536
524
  const modelsUrl = `${probeBaseUrl}/v1/models`;
537
- const result = await this.fetchWithTimeout(modelsUrl);
525
+ const result = await this.fetchWithTimeout(modelsUrl, 2000, undefined, signal);
526
+ if (signal?.aborted) return false;
538
527
  if (result.ok) {
539
528
  this.isAvailable = true;
540
529
  this.detectedType = "generic";
@@ -903,6 +892,10 @@ export class LocalLlmClient {
903
892
 
904
893
  private async runQueuedRequest(next: LocalLlmQueuedRequest): Promise<void> {
905
894
  try {
895
+ if (next.options.signal?.aborted) {
896
+ next.resolve(null);
897
+ return;
898
+ }
906
899
  const remainingCooldownMs = this.remainingCooldownMs();
907
900
  if (remainingCooldownMs > 0) {
908
901
  const additionalDropped = this.failOpenQueuedRequestsForCooldown();
@@ -949,7 +942,8 @@ export class LocalLlmClient {
949
942
  }
950
943
 
951
944
  try {
952
- const isAvailable = await this.checkAvailability();
945
+ if (options.signal?.aborted) return null;
946
+ const isAvailable = await this.checkAvailability(options.signal);
953
947
  if (!isAvailable) {
954
948
  log.debug(
955
949
  `local LLM: checkAvailability returned false for ${this.config.localLlmUrl}`,
@@ -1040,6 +1034,16 @@ export class LocalLlmClient {
1040
1034
  let lastAbortError: Error | null = null;
1041
1035
  for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
1042
1036
  const attemptAbort = new AbortController();
1037
+ const onCallerAbort = (): void => {
1038
+ attemptAbort.abort(options.signal?.reason);
1039
+ };
1040
+ if (options.signal) {
1041
+ if (options.signal.aborted) {
1042
+ onCallerAbort();
1043
+ } else {
1044
+ options.signal.addEventListener("abort", onCallerAbort, { once: true });
1045
+ }
1046
+ }
1043
1047
  const attemptTimeout = setTimeout(() => attemptAbort.abort(), effectiveTimeoutMs);
1044
1048
  try {
1045
1049
  response = await this.chatTransport.post({
@@ -1052,19 +1056,20 @@ export class LocalLlmClient {
1052
1056
  budgetMs: this.config.localLlmTimeoutMs,
1053
1057
  });
1054
1058
  } catch (err) {
1055
- if (!this.isAbortError(err)) throw err;
1059
+ if (!isAbortError(err)) throw err;
1056
1060
  lastAbortError = err instanceof Error ? err : new Error(String(err));
1057
- if (attempt < maxAttempts) {
1058
- const backoffMs = this.config.localLlmRetryBackoffMs * attempt;
1059
- log.warn(
1060
- `local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,
1061
- );
1062
- await new Promise((resolve) => setTimeout(resolve, backoffMs));
1063
- continue;
1061
+ if (options.signal?.aborted || attempt >= maxAttempts) {
1062
+ break;
1064
1063
  }
1065
- break;
1064
+ const backoffMs = this.config.localLlmRetryBackoffMs * attempt;
1065
+ log.warn(
1066
+ `local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,
1067
+ );
1068
+ if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
1069
+ continue;
1066
1070
  } finally {
1067
1071
  clearTimeout(attemptTimeout);
1072
+ options.signal?.removeEventListener("abort", onCallerAbort);
1068
1073
  }
1069
1074
 
1070
1075
  if (response.ok) break;
@@ -1072,7 +1077,7 @@ export class LocalLlmClient {
1072
1077
  try {
1073
1078
  const errorText = await response.clone().text();
1074
1079
  const nonRecoverableReason =
1075
- this.extractNonRecoverableBackendReasonFromErrorText(errorText);
1080
+ extractNonRecoverableBackendReasonFromErrorText(errorText);
1076
1081
  if (nonRecoverableReason) {
1077
1082
  this.markBackendUnavailable(
1078
1083
  nonRecoverableReason,
@@ -1091,12 +1096,11 @@ export class LocalLlmClient {
1091
1096
  log.warn(
1092
1097
  `local LLM request got ${response.status}; retrying (attempt ${attempt + 1}/${maxAttempts}) after ${backoffMs}ms`,
1093
1098
  );
1094
- await new Promise((resolve) => setTimeout(resolve, backoffMs));
1099
+ if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
1095
1100
  }
1096
1101
  log.debug(
1097
1102
  `local LLM: received response, status=${response?.status}, ok=${response?.ok}`,
1098
1103
  );
1099
-
1100
1104
  if (!response) {
1101
1105
  if (lastAbortError) {
1102
1106
  log.warn(
@@ -1131,8 +1135,8 @@ export class LocalLlmClient {
1131
1135
  `(op=${operation}, model=${this.config.localLlmModel}, url=${chatUrl}, promptChars=${promptChars}, maxTokens=${requestBody.max_tokens as number})`,
1132
1136
  );
1133
1137
  const nonRecoverableReason =
1134
- this.extractNonRecoverableBackendReason(reason) ??
1135
- this.extractNonRecoverableBackendReasonFromErrorText(errorText);
1138
+ extractNonRecoverableBackendReason(reason) ??
1139
+ extractNonRecoverableBackendReasonFromErrorText(errorText);
1136
1140
  if (nonRecoverableReason) {
1137
1141
  this.markBackendUnavailable(
1138
1142
  nonRecoverableReason,
@@ -1206,7 +1210,7 @@ export class LocalLlmClient {
1206
1210
  } catch (err) {
1207
1211
  const errMsg = err instanceof Error ? err.message : String(err);
1208
1212
  const durationMs = Date.now() - startedAtMs;
1209
- if (this.isAbortError(err)) {
1213
+ if (isAbortError(err)) {
1210
1214
  log.warn(
1211
1215
  `local LLM request aborted: op=${operation} timeoutMs=${options.timeoutMs ?? this.config.localLlmTimeoutMs} model=${this.config.localLlmModel} durationMs=${durationMs} error=${errMsg}`,
1212
1216
  );
@@ -1214,7 +1218,7 @@ export class LocalLlmClient {
1214
1218
  }
1215
1219
  log.warn(`local LLM request error: op=${operation} error=${errMsg}`);
1216
1220
  this.isAvailable = false; // Mark as unavailable on non-abort errors
1217
- const nonRecoverableReason = this.extractNonRecoverableBackendReason(errMsg);
1221
+ const nonRecoverableReason = extractNonRecoverableBackendReason(errMsg);
1218
1222
  if (nonRecoverableReason) {
1219
1223
  this.markBackendUnavailable(
1220
1224
  nonRecoverableReason,
@@ -0,0 +1,309 @@
1
+ import type { BufferTurn, ExtractionFailureClass, ExtractionResult, MetaState } from "../types.js";
2
+ import type { StorageManager } from "../index.js";
3
+ import { log } from "../logger.js";
4
+
5
+ export function combineExtractionAbortSignals(
6
+ primary: AbortSignal | undefined,
7
+ deadlineController: AbortController | undefined,
8
+ ): AbortSignal | undefined {
9
+ if (!deadlineController) return primary;
10
+ return primary ? AbortSignal.any([primary, deadlineController.signal]) : deadlineController.signal;
11
+ }
12
+
13
+
14
+ function isRecord(value: unknown): value is Record<string, unknown> {
15
+ return typeof value === "object" && value !== null;
16
+ }
17
+
18
+ export function deriveTopicsFromExtraction(result: ExtractionResult): string[] {
19
+ if (!isRecord(result)) return [];
20
+ const topics = new Set<string>();
21
+ const facts = Array.isArray(result.facts) ? result.facts : [];
22
+ for (const rawFact of facts) {
23
+ if (!isRecord(rawFact)) continue;
24
+ const tags = Array.isArray(rawFact.tags) ? rawFact.tags : [];
25
+ for (const tag of tags) {
26
+ if (typeof tag === "string" && tag.length >= 2) topics.add(tag.toLowerCase());
27
+ }
28
+ if (typeof rawFact.entityRef === "string" && rawFact.entityRef.length >= 2) {
29
+ topics.add(rawFact.entityRef.toLowerCase());
30
+ }
31
+ if (typeof rawFact.category === "string" && rawFact.category.length > 0) {
32
+ topics.add(rawFact.category);
33
+ }
34
+ }
35
+ const entities = Array.isArray(result.entities) ? result.entities : [];
36
+ for (const rawEntity of entities) {
37
+ if (!isRecord(rawEntity)) continue;
38
+ if (typeof rawEntity.name === "string" && rawEntity.name.length >= 2) {
39
+ topics.add(rawEntity.name.toLowerCase());
40
+ }
41
+ }
42
+ return [...topics].slice(0, 16);
43
+ }
44
+
45
+ /** Bounded cap on persisted per-fingerprint retry-state entries (per namespace meta). */
46
+ export const EXTRACTION_RETRY_STATE_MAX_ENTRIES = 500;
47
+
48
+ export interface ExtractionRetryStateEntry {
49
+ attempts: number;
50
+ nextEligibleAtMs: number;
51
+ firstFailedAtMs: number;
52
+ lastFailureClass: ExtractionFailureClass;
53
+ }
54
+
55
+ export interface ExtractionResilienceStatus {
56
+ breaker: {
57
+ state: "closed" | "open" | "half_open";
58
+ openUntilMs: number;
59
+ consecutiveFailures: number;
60
+ lastReason: string;
61
+ };
62
+ backoffFingerprintCount: number;
63
+ }
64
+
65
+ /**
66
+ * Pure backoff scheduler. Returns the absolute ms timestamp at which a
67
+ * fingerprint that has failed `attempts` times becomes eligible again:
68
+ * exponential via the configured schedule, clamped to `maxBackoffMs`, with
69
+ * ±`jitterRatio` multiplicative jitter. `rng` is injectable for deterministic
70
+ * tests. Never returns a timestamp before `now`.
71
+ */
72
+ export function computeExtractionRetryNextEligibleMs(
73
+ attempts: number,
74
+ scheduleMs: readonly number[],
75
+ maxBackoffMs: number,
76
+ jitterRatio: number,
77
+ now: number,
78
+ rng: () => number = Math.random,
79
+ ): number {
80
+ if (!Number.isFinite(attempts) || !Number.isInteger(attempts) || attempts < 1) {
81
+ throw new RangeError("attempts must be a finite integer >= 1");
82
+ }
83
+ if (!Number.isFinite(maxBackoffMs) || maxBackoffMs < 0) {
84
+ throw new RangeError("maxBackoffMs must be a finite number >= 0");
85
+ }
86
+ if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) {
87
+ throw new RangeError("jitterRatio must be a finite number in [0, 1]");
88
+ }
89
+ const safeNow = Number.isFinite(now) ? now : 0;
90
+ const cap = maxBackoffMs;
91
+ if (!Array.isArray(scheduleMs) || scheduleMs.length === 0) {
92
+ return safeNow + cap;
93
+ }
94
+ const idx = Math.min(attempts - 1, scheduleMs.length - 1);
95
+ const step = scheduleMs[idx];
96
+ const base = Math.min(typeof step === "number" && Number.isFinite(step) && step > 0 ? step : cap, cap);
97
+ const randomValue = rng();
98
+ if (!Number.isFinite(randomValue) || randomValue < 0 || randomValue > 1) {
99
+ throw new RangeError("rng() must return a finite number in [0, 1]");
100
+ }
101
+ const jitter = 1 + (randomValue * 2 - 1) * jitterRatio;
102
+ return safeNow + Math.max(0, Math.round(base * jitter));
103
+ }
104
+
105
+ /**
106
+ * Cap the persisted retry-state array to the newest `maxEntries` by
107
+ * firstFailedAt. Guards invalid caps so they cannot turn `slice(-maxEntries)`
108
+ * into an unbounded copy (AGENTS.md rule 17).
109
+ */
110
+ export function capExtractionRetryStateEntries<T extends { firstFailedAt: string }>(
111
+ entries: readonly T[],
112
+ maxEntries: number,
113
+ ): T[] {
114
+ if (!Number.isFinite(maxEntries) || !Number.isInteger(maxEntries) || maxEntries <= 0) return [];
115
+ const sorted = [...entries].sort((a, b) => a.firstFailedAt.localeCompare(b.firstFailedAt));
116
+ return sorted.slice(-maxEntries);
117
+ }
118
+
119
+ /**
120
+ * Derive a single `sourceConnector` from a batch of turns.
121
+ * Returns the connector ONLY when ALL turns carry the same connector.
122
+ * Mixed tagged/untagged batches return undefined — extraction facts are
123
+ * persisted at batch level, so attributing them to the single tagged
124
+ * connector would falsely label facts from untagged turns.
125
+ * Conflicting connectors (different values) also return undefined.
126
+ */
127
+ export function deriveSourceConnector(turns: readonly BufferTurn[]): string | undefined {
128
+ if (turns.length === 0) return undefined;
129
+ const connectors = new Set<string>();
130
+ let untaggedCount = 0;
131
+ for (const turn of turns) {
132
+ if (typeof turn.sourceConnector === "string" && turn.sourceConnector.length > 0) {
133
+ connectors.add(turn.sourceConnector);
134
+ } else {
135
+ untaggedCount += 1;
136
+ }
137
+ }
138
+ // All turns must agree on the same connector — no untagged turns mixed in.
139
+ if (untaggedCount > 0) return undefined;
140
+ return connectors.size === 1 ? [...connectors][0] : undefined;
141
+ }
142
+
143
+ export async function runExtractionPostPersistBestEffort(
144
+ runDeadlineAware: (
145
+ operation: () => Promise<unknown>,
146
+ phase: string,
147
+ clearTimerOnError?: boolean,
148
+ options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },
149
+ ) => Promise<unknown>,
150
+ stage: string,
151
+ operation: () => Promise<unknown>,
152
+ options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },
153
+ ): Promise<void> {
154
+ try {
155
+ await runDeadlineAware(operation, stage, false, {
156
+ ignoreAbort: options?.ignoreAbort,
157
+ ignoreDeadline: options?.ignoreDeadline,
158
+ });
159
+ } catch (error) {
160
+ if (options?.propagateErrors) throw error;
161
+ log.warn(`runExtraction: ${stage} failed after persistence (non-fatal)`, error);
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Applies deferred-judge retention only to live, non-shadow extraction runs.
167
+ * Replay/import paths must not synthesize live-buffer entries after persistence.
168
+ */
169
+ export interface ExtractionDeferRetentionOptions {
170
+ clearBufferAfterExtraction: boolean;
171
+ extractionJudgeShadow: boolean;
172
+ getDeferredCount: () => number;
173
+ normalizedTurns: BufferTurn[];
174
+ bufferKey: string;
175
+ retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;
176
+ }
177
+
178
+ export async function runExtractionDeferRetention(
179
+ runPostPersistBestEffort: (
180
+ stage: string,
181
+ operation: () => Promise<unknown>,
182
+ options?: { ignoreAbort?: boolean },
183
+ ) => Promise<void>,
184
+ options: ExtractionDeferRetentionOptions,
185
+ ): Promise<void> {
186
+ await runPostPersistBestEffort("during_defer_retention", async () => {
187
+ if (options.clearBufferAfterExtraction && !options.extractionJudgeShadow) {
188
+ const deferredCount = options.getDeferredCount();
189
+ if (deferredCount > 0 && options.normalizedTurns.length > 0) {
190
+ await options.retainDeferredTurns(options.bufferKey, options.normalizedTurns, 10);
191
+ } else {
192
+ await options.retainDeferredTurns(options.bufferKey, [], 0);
193
+ }
194
+ }
195
+ });
196
+ }
197
+
198
+ export interface ExtractionPostPersistOptions {
199
+ result: ExtractionResult;
200
+ storage: StorageManager;
201
+ meta?: MetaState;
202
+ extractionFingerprint?: string;
203
+ shouldPersistProcessedFingerprint: boolean;
204
+ recordProcessedExtractionFingerprint: (
205
+ storage: StorageManager,
206
+ fingerprint: string,
207
+ meta: MetaState,
208
+ ) => Promise<void>;
209
+ runDeadlineAware: (
210
+ operation: () => Promise<unknown>,
211
+ phase: string,
212
+ clearTimerOnError?: boolean,
213
+ options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },
214
+ ) => Promise<unknown>;
215
+ isDeadlineError: (error: unknown) => boolean;
216
+ createDeadlineError: (stage: string) => Error;
217
+ deadlineMs?: number;
218
+ clearBufferAfterExtraction: boolean;
219
+ runPostPersistBestEffort: (
220
+ stage: string,
221
+ operation: () => Promise<unknown>,
222
+ options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },
223
+ ) => Promise<void>;
224
+ extractionJudgeShadow: boolean;
225
+ getDeferredCount: () => number;
226
+ normalizedTurns: BufferTurn[];
227
+ bufferKey: string;
228
+ retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;
229
+ clearBuffer: (options?: { ignoreAbort?: boolean }) => Promise<void>;
230
+ failOnExtractionFailure: boolean;
231
+ }
232
+
233
+ export interface ExtractionPostPersistResult {
234
+ meta?: MetaState;
235
+ metadataFailed: boolean;
236
+ }
237
+
238
+ export async function runExtractionPostPersist(
239
+ options: ExtractionPostPersistOptions,
240
+ ): Promise<ExtractionPostPersistResult> {
241
+ let metadataFailed = false;
242
+ let deadlineError: Error | undefined;
243
+ const recordFailure = (stage: string, error: unknown): void => {
244
+ metadataFailed = true;
245
+ if (options.isDeadlineError(error) && deadlineError === undefined) {
246
+ deadlineError = error as Error;
247
+ }
248
+ log.warn(`runExtraction: ${stage} failed after durable persistence; continuing with buffer clear`, error);
249
+ };
250
+ let meta = options.meta;
251
+ try {
252
+ meta ??= (await options.runDeadlineAware(
253
+ () => options.storage.loadMeta(),
254
+ "during_post_persist_load_meta",
255
+ false,
256
+ )) as MetaState;
257
+ } catch (error) {
258
+ recordFailure("metadata load", error);
259
+ }
260
+ if (meta && options.extractionFingerprint && options.shouldPersistProcessedFingerprint) {
261
+ try {
262
+ await options.runDeadlineAware(
263
+ () => options.recordProcessedExtractionFingerprint(options.storage, options.extractionFingerprint!, meta!),
264
+ "during_post_persist_fingerprint",
265
+ false,
266
+ );
267
+ } catch (error) {
268
+ recordFailure("processed fingerprint", error);
269
+ }
270
+ }
271
+ if (meta) {
272
+ meta.extractionCount += 1;
273
+ meta.lastExtractionAt = new Date().toISOString();
274
+ meta.totalMemories += Array.isArray(options.result.facts) ? options.result.facts.length : 0;
275
+ meta.totalEntities += Array.isArray(options.result.entities) ? options.result.entities.length : 0;
276
+ try {
277
+ await options.runDeadlineAware(
278
+ () => options.storage.saveMeta(meta!),
279
+ "during_post_persist_meta_save",
280
+ false,
281
+ );
282
+ } catch (error) {
283
+ recordFailure("metadata save", error);
284
+ }
285
+ }
286
+ const runBestEffort = options.runPostPersistBestEffort;
287
+ await runExtractionDeferRetention(runBestEffort, {
288
+ clearBufferAfterExtraction: options.clearBufferAfterExtraction,
289
+ extractionJudgeShadow: options.extractionJudgeShadow,
290
+ getDeferredCount: options.getDeferredCount,
291
+ normalizedTurns: options.normalizedTurns,
292
+ bufferKey: options.bufferKey,
293
+ retainDeferredTurns: options.retainDeferredTurns,
294
+ });
295
+ await runBestEffort(
296
+ "during_buffer_clear",
297
+ () => options.clearBuffer({ ignoreAbort: true }),
298
+ {
299
+ ignoreAbort: true,
300
+ ignoreDeadline: options.failOnExtractionFailure,
301
+ propagateErrors: options.failOnExtractionFailure,
302
+ },
303
+ );
304
+ if (options.failOnExtractionFailure && typeof options.deadlineMs === "number" && Date.now() >= options.deadlineMs) {
305
+ throw options.createDeadlineError("during_buffer_clear");
306
+ }
307
+ if (deadlineError) throw deadlineError;
308
+ return { meta, metadataFailed };
309
+ }