@remnic/core 9.3.713 → 9.3.715

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 (325) hide show
  1. package/dist/access-boundary.d.ts +6 -6
  2. package/dist/access-boundary.js +17 -16
  3. package/dist/access-cli.js +39 -38
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +5 -5
  6. package/dist/access-http.js +23 -22
  7. package/dist/access-mcp.d.ts +12 -5
  8. package/dist/access-mcp.js +20 -19
  9. package/dist/access-operations-batch.js +18 -17
  10. package/dist/access-operations.d.ts +6 -5
  11. package/dist/access-operations.js +19 -18
  12. package/dist/{access-service-DwVmvgBg.d.ts → access-service-GgnA--CE.d.ts} +12 -4
  13. package/dist/access-service.d.ts +5 -5
  14. package/dist/access-service.js +16 -15
  15. package/dist/access-surface-catalog.d.ts +5 -5
  16. package/dist/access-surface-catalog.js +6 -1
  17. package/dist/access-surface-catalog.js.map +1 -1
  18. package/dist/action-confidence.d.ts +1 -1
  19. package/dist/active-memory-bridge.d.ts +3 -1
  20. package/dist/active-memory-bridge.js +2 -1
  21. package/dist/active-recall.d.ts +1 -1
  22. package/dist/active-recall.js +4 -3
  23. package/dist/active-recall.js.map +1 -1
  24. package/dist/adapters/index.js +4 -4
  25. package/dist/adapters/registry.js +2 -2
  26. package/dist/behavior-learner.d.ts +1 -1
  27. package/dist/behavior-signals.d.ts +1 -1
  28. package/dist/bootstrap.d.ts +4 -4
  29. package/dist/briefing.d.ts +1 -1
  30. package/dist/briefing.js +8 -7
  31. package/dist/buffer-surprise-report.d.ts +1 -1
  32. package/dist/buffer.d.ts +1 -1
  33. package/dist/calibration.d.ts +1 -1
  34. package/dist/capabilities.d.ts +1 -1
  35. package/dist/{catalog-CadPvH29.d.ts → catalog-CbR0CsUw.d.ts} +1 -1
  36. package/dist/causal-behavior.d.ts +1 -1
  37. package/dist/causal-consolidation.d.ts +1 -1
  38. package/dist/causal-consolidation.js +9 -8
  39. package/dist/causal-consolidation.js.map +1 -1
  40. package/dist/{chunk-OMSTU233.js → chunk-2KAYTPPT.js} +4 -4
  41. package/dist/{chunk-VYZNWH4J.js → chunk-2SXMCQEQ.js} +3 -3
  42. package/dist/{chunk-NXL5CVE7.js → chunk-2Y6LMOQQ.js} +2 -2
  43. package/dist/{chunk-ZDUF7K5V.js → chunk-3VUPWDSE.js} +15 -3
  44. package/dist/{chunk-ZDUF7K5V.js.map → chunk-3VUPWDSE.js.map} +1 -1
  45. package/dist/{chunk-FVQJYWH7.js → chunk-5GKPFL3S.js} +1 -1
  46. package/dist/{chunk-FVQJYWH7.js.map → chunk-5GKPFL3S.js.map} +1 -1
  47. package/dist/{chunk-LQ4J7ELC.js → chunk-67HG7KFE.js} +2 -2
  48. package/dist/{chunk-ZBG4K36I.js → chunk-6FUJ2VYY.js} +3 -3
  49. package/dist/{chunk-GMRNKPWO.js → chunk-6QUPUTT7.js} +2 -2
  50. package/dist/{chunk-Z56IHRVV.js → chunk-6UU43ZGD.js} +2 -2
  51. package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
  52. package/dist/{chunk-OWOKOFXK.js → chunk-AJOIM6UR.js} +2 -2
  53. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  54. package/dist/{chunk-UHN2TNSB.js → chunk-BNOAB5HH.js} +38 -11
  55. package/dist/chunk-BNOAB5HH.js.map +1 -0
  56. package/dist/{chunk-VW24K2Q4.js → chunk-CTAHKIG6.js} +169 -8
  57. package/dist/chunk-CTAHKIG6.js.map +1 -0
  58. package/dist/{chunk-K22IJO4R.js → chunk-CTOQEZSN.js} +2 -2
  59. package/dist/{chunk-SINGJCUR.js → chunk-CX77GNMB.js} +14 -3
  60. package/dist/chunk-CX77GNMB.js.map +1 -0
  61. package/dist/{chunk-HSDJCT3V.js → chunk-DXGS5YOQ.js} +3 -3
  62. package/dist/{chunk-HV57RHMD.js → chunk-EH5ED3C6.js} +2 -2
  63. package/dist/{chunk-7NDYFAJS.js → chunk-GM3BMWKR.js} +2 -2
  64. package/dist/{chunk-RMT7PAVW.js → chunk-HHLWSWWF.js} +2 -2
  65. package/dist/chunk-HHLWSWWF.js.map +1 -0
  66. package/dist/{chunk-5QUS24F7.js → chunk-I56LKMF7.js} +2 -2
  67. package/dist/{chunk-VUNI6Y3D.js → chunk-IHMT6XTY.js} +8 -4
  68. package/dist/chunk-IHMT6XTY.js.map +1 -0
  69. package/dist/chunk-JAKIDQB2.js +173 -0
  70. package/dist/chunk-JAKIDQB2.js.map +1 -0
  71. package/dist/{chunk-35YJ6KCV.js → chunk-JEIROMLX.js} +2 -2
  72. package/dist/{chunk-SKQCFAYU.js → chunk-JVEMUX6L.js} +2 -2
  73. package/dist/{chunk-CXMXAC5R.js → chunk-K44MIN6D.js} +3 -3
  74. package/dist/{chunk-JC3MIKR4.js → chunk-MECU6WSH.js} +188 -31
  75. package/dist/chunk-MECU6WSH.js.map +1 -0
  76. package/dist/{chunk-BQCFXAMN.js → chunk-MPHDVHIB.js} +2 -2
  77. package/dist/{chunk-BOGENF7P.js → chunk-MSVSP5VO.js} +1 -1
  78. package/dist/chunk-MSVSP5VO.js.map +1 -0
  79. package/dist/{chunk-QXNFQKWU.js → chunk-MTHNJCOJ.js} +2 -2
  80. package/dist/{chunk-3TCRU4JA.js → chunk-O62P2LFL.js} +2 -2
  81. package/dist/{chunk-JSDZMOT7.js → chunk-OC56UWV5.js} +11 -11
  82. package/dist/{chunk-7IBEWQLG.js → chunk-QOIONSOI.js} +2 -2
  83. package/dist/{chunk-4P5UAL3C.js → chunk-RBHANGVX.js} +6 -6
  84. package/dist/{chunk-SK2CR6MW.js → chunk-RVLB4E6N.js} +2 -2
  85. package/dist/{chunk-DJNKN3XY.js → chunk-SYDHFFAW.js} +1084 -12
  86. package/dist/chunk-SYDHFFAW.js.map +1 -0
  87. package/dist/{chunk-VILEUJXC.js → chunk-UC4YOAC2.js} +74 -2
  88. package/dist/{chunk-VILEUJXC.js.map → chunk-UC4YOAC2.js.map} +1 -1
  89. package/dist/{chunk-CNVIWMQI.js → chunk-UY4JMEAK.js} +2 -2
  90. package/dist/{chunk-S6FQLQGH.js → chunk-V7GDTQ6I.js} +2 -2
  91. package/dist/{chunk-JNOYYWCA.js → chunk-VO4UICII.js} +3 -3
  92. package/dist/{chunk-54TI5GLV.js → chunk-WI4QX7GH.js} +3 -3
  93. package/dist/{chunk-3XHD3XGK.js → chunk-XCTDHF7U.js} +30 -2
  94. package/dist/chunk-XCTDHF7U.js.map +1 -0
  95. package/dist/{chunk-XKU4YE6Z.js → chunk-XZTUMWKQ.js} +2 -2
  96. package/dist/{chunk-GKPIY7EQ.js → chunk-YUJL27ET.js} +160 -61
  97. package/dist/chunk-YUJL27ET.js.map +1 -0
  98. package/dist/{cli-DfDMJqPP.d.ts → cli-Do1YtfnH.d.ts} +3 -3
  99. package/dist/cli.d.ts +6 -6
  100. package/dist/cli.js +42 -41
  101. package/dist/compounding/engine.d.ts +1 -1
  102. package/dist/compounding/engine.js +8 -7
  103. package/dist/compounding/preference-consolidator.d.ts +1 -1
  104. package/dist/compression-optimizer.d.ts +1 -1
  105. package/dist/config.d.ts +1 -1
  106. package/dist/config.js +4 -3
  107. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  108. package/dist/connectors/codex-materialize-runner.js +8 -7
  109. package/dist/connectors/codex-materialize.d.ts +1 -1
  110. package/dist/connectors/index.d.ts +1 -1
  111. package/dist/connectors/index.js +9 -8
  112. package/dist/consolidation-provenance-check.d.ts +1 -1
  113. package/dist/consolidation-undo.d.ts +1 -1
  114. package/dist/contradiction/index.d.ts +1 -1
  115. package/dist/conversation-index/backend.d.ts +1 -1
  116. package/dist/conversation-index/chunker.d.ts +1 -1
  117. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  118. package/dist/conversation-index/indexer.d.ts +1 -1
  119. package/dist/conversation-index/search.d.ts +1 -1
  120. package/dist/day-summary.d.ts +1 -1
  121. package/dist/delinearize.d.ts +1 -1
  122. package/dist/direct-answer-wiring.d.ts +1 -1
  123. package/dist/direct-answer.d.ts +1 -1
  124. package/dist/embedding-fallback.d.ts +1 -1
  125. package/dist/enrichment/index.d.ts +1 -1
  126. package/dist/entity-retrieval.d.ts +1 -1
  127. package/dist/entity-retrieval.js +8 -7
  128. package/dist/entity-schema.d.ts +1 -1
  129. package/dist/explicit-capture.d.ts +4 -4
  130. package/dist/explicit-capture.js +3 -2
  131. package/dist/extraction-faithfulness.d.ts +1 -1
  132. package/dist/extraction-judge-telemetry.d.ts +1 -1
  133. package/dist/extraction-judge-training.d.ts +1 -1
  134. package/dist/extraction-judge.d.ts +1 -1
  135. package/dist/extraction.d.ts +1 -1
  136. package/dist/extraction.js +4 -3
  137. package/dist/fallback-llm.d.ts +1 -1
  138. package/dist/identity-continuity.d.ts +1 -1
  139. package/dist/importance.d.ts +1 -1
  140. package/dist/index.d.ts +9 -9
  141. package/dist/index.js +61 -60
  142. package/dist/index.js.map +1 -1
  143. package/dist/intent.d.ts +1 -1
  144. package/dist/lcm/engine.d.ts +1 -1
  145. package/dist/lcm/index.d.ts +1 -1
  146. package/dist/lcm/index.js +3 -3
  147. package/dist/lcm/tools.d.ts +1 -1
  148. package/dist/lifecycle.d.ts +1 -1
  149. package/dist/live-connectors-runner.d.ts +1 -1
  150. package/dist/local-llm.d.ts +1 -1
  151. package/dist/maintenance/memory-governance.d.ts +1 -1
  152. package/dist/maintenance/memory-governance.js +8 -7
  153. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -7
  154. package/dist/maintenance/rebuild-memory-projection.js +9 -8
  155. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  156. package/dist/memory-action-policy.d.ts +1 -1
  157. package/dist/memory-cache.d.ts +1 -1
  158. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  159. package/dist/memory-projection-store.d.ts +1 -1
  160. package/dist/memory-provenance.d.ts +1 -1
  161. package/dist/memory-worth-outcomes.d.ts +1 -1
  162. package/dist/models-json.d.ts +1 -1
  163. package/dist/namespaces/migrate.d.ts +2 -2
  164. package/dist/namespaces/migrate.js +12 -11
  165. package/dist/namespaces/principal.d.ts +1 -1
  166. package/dist/namespaces/search.d.ts +1 -1
  167. package/dist/namespaces/search.js +3 -3
  168. package/dist/namespaces/storage.d.ts +2 -2
  169. package/dist/namespaces/storage.js +8 -7
  170. package/dist/native-knowledge.d.ts +1 -1
  171. package/dist/operator-toolkit.d.ts +1 -1
  172. package/dist/operator-toolkit.js +17 -16
  173. package/dist/orchestration/maintenance.d.ts +2 -2
  174. package/dist/orchestration/maintenance.js +10 -9
  175. package/dist/{orchestrator-B1iVjEyc.d.ts → orchestrator-BOaVstFG.d.ts} +32 -4
  176. package/dist/orchestrator.d.ts +4 -4
  177. package/dist/orchestrator.js +32 -31
  178. package/dist/patterns-cli.d.ts +1 -1
  179. package/dist/policy-runtime.d.ts +1 -1
  180. package/dist/provenance.d.ts +1 -1
  181. package/dist/provenance.js +3 -2
  182. package/dist/qmd-recall-cache.d.ts +1 -1
  183. package/dist/qmd.d.ts +1 -1
  184. package/dist/recall-disclosure-escalation.d.ts +1 -1
  185. package/dist/recall-explain-renderer.d.ts +1 -1
  186. package/dist/recall-explain-renderer.js +3 -3
  187. package/dist/recall-handles.d.ts +228 -0
  188. package/dist/recall-handles.js +42 -0
  189. package/dist/recall-handles.js.map +1 -0
  190. package/dist/recall-planner-llm.d.ts +1 -1
  191. package/dist/recall-state.d.ts +40 -2
  192. package/dist/recall-state.js +3 -1
  193. package/dist/recall-tag-filter.d.ts +1 -1
  194. package/dist/recall-xray-cli.d.ts +1 -1
  195. package/dist/recall-xray-cli.js +4 -4
  196. package/dist/recall-xray-renderer.d.ts +1 -1
  197. package/dist/recall-xray-renderer.js +3 -3
  198. package/dist/recall-xray.d.ts +1 -1
  199. package/dist/recall-xray.js +2 -2
  200. package/dist/resolve-auth-token.d.ts +1 -1
  201. package/dist/resume-bundles.js +5 -4
  202. package/dist/retrieval-agents.d.ts +1 -1
  203. package/dist/retrieval-tiers.d.ts +1 -1
  204. package/dist/routing/engine.d.ts +1 -1
  205. package/dist/routing/store.d.ts +1 -1
  206. package/dist/sanitize.d.ts +2 -0
  207. package/dist/sanitize.js +6 -2
  208. package/dist/schemas.d.ts +22 -22
  209. package/dist/search/embed-helper.d.ts +1 -1
  210. package/dist/search/factory.d.ts +1 -1
  211. package/dist/search/factory.js +2 -2
  212. package/dist/search/index.d.ts +1 -1
  213. package/dist/search/index.js +4 -4
  214. package/dist/search/lancedb-backend.d.ts +1 -1
  215. package/dist/search/meilisearch-backend.d.ts +1 -1
  216. package/dist/search/noop-backend.d.ts +1 -1
  217. package/dist/search/orama-backend.d.ts +1 -1
  218. package/dist/search/port.d.ts +1 -1
  219. package/dist/search/remote-backend.d.ts +1 -1
  220. package/dist/{semantic-consolidation-CY8uVRNJ.d.ts → semantic-consolidation-DSjMDZ1u.d.ts} +1 -1
  221. package/dist/semantic-consolidation.d.ts +2 -2
  222. package/dist/semantic-consolidation.js +9 -8
  223. package/dist/semantic-rule-promotion.js +8 -7
  224. package/dist/semantic-rule-verifier.d.ts +1 -1
  225. package/dist/semantic-rule-verifier.js +8 -7
  226. package/dist/session-observer-bands.d.ts +1 -1
  227. package/dist/session-observer-state.d.ts +1 -1
  228. package/dist/shared-context/manager.d.ts +3 -3
  229. package/dist/signal.d.ts +1 -1
  230. package/dist/storage.d.ts +1 -1
  231. package/dist/storage.js +7 -6
  232. package/dist/summarizer.d.ts +1 -1
  233. package/dist/summary-snapshot.d.ts +1 -1
  234. package/dist/temporal-supersession.d.ts +1 -1
  235. package/dist/temporal-validity.d.ts +1 -1
  236. package/dist/threading.d.ts +1 -1
  237. package/dist/tier-migration.d.ts +1 -1
  238. package/dist/tier-routing.d.ts +1 -1
  239. package/dist/topics.d.ts +1 -1
  240. package/dist/transcript.d.ts +1 -1
  241. package/dist/transfer/import-sqlite.js +2 -2
  242. package/dist/transfer/types.d.ts +12 -12
  243. package/dist/{types-Dr0Cw3L9.d.ts → types-D9dwzU_x.d.ts} +25 -1
  244. package/dist/types.d.ts +1 -1
  245. package/dist/types.js +1 -1
  246. package/dist/utility-runtime.d.ts +1 -1
  247. package/dist/verified-recall.js +8 -7
  248. package/package.json +2 -2
  249. package/src/access-boundary.ts +4 -1
  250. package/src/access-http.ts +33 -1
  251. package/src/access-mcp.test.ts +28 -0
  252. package/src/access-mcp.ts +67 -2
  253. package/src/access-operations-batch.ts +14 -0
  254. package/src/access-operations.ts +5 -0
  255. package/src/access-service.ts +43 -2
  256. package/src/access-surface-catalog.test.ts +4 -2
  257. package/src/access-surface-catalog.ts +5 -0
  258. package/src/active-memory-bridge.test.ts +72 -0
  259. package/src/active-memory-bridge.ts +21 -2
  260. package/src/chat/chat-cli.test.ts +142 -0
  261. package/src/chat/chat-cli.ts +206 -0
  262. package/src/chat/chat-config.ts +57 -0
  263. package/src/chat/chat-engine.test.ts +272 -0
  264. package/src/chat/chat-engine.ts +518 -0
  265. package/src/chat/chat-executor.ts +133 -0
  266. package/src/chat/chat-factory.ts +161 -0
  267. package/src/chat/chat-http.test.ts +197 -0
  268. package/src/chat/chat-http.ts +222 -0
  269. package/src/chat/chat-llm.ts +229 -0
  270. package/src/chat/chat-mcp.test.ts +135 -0
  271. package/src/chat/chat-security.test.ts +491 -0
  272. package/src/chat/chat-session.ts +296 -0
  273. package/src/chat/chat-system-prompt.ts +76 -0
  274. package/src/chat/chat-tools.ts +255 -0
  275. package/src/chat/chat-types.ts +167 -0
  276. package/src/cli.ts +20 -0
  277. package/src/config.ts +9 -0
  278. package/src/faithfulness-graph-guard.test.ts +214 -8
  279. package/src/orchestrator.ts +167 -22
  280. package/src/recall-handles-wiring.test.ts +477 -0
  281. package/src/recall-handles.test.ts +283 -0
  282. package/src/recall-handles.ts +414 -0
  283. package/src/recall-state.ts +99 -0
  284. package/src/sanitize.ts +6 -0
  285. package/src/types.ts +29 -0
  286. package/dist/chunk-3XHD3XGK.js.map +0 -1
  287. package/dist/chunk-BOGENF7P.js.map +0 -1
  288. package/dist/chunk-DJNKN3XY.js.map +0 -1
  289. package/dist/chunk-GKPIY7EQ.js.map +0 -1
  290. package/dist/chunk-JC3MIKR4.js.map +0 -1
  291. package/dist/chunk-RMT7PAVW.js.map +0 -1
  292. package/dist/chunk-SINGJCUR.js.map +0 -1
  293. package/dist/chunk-UHN2TNSB.js.map +0 -1
  294. package/dist/chunk-VUNI6Y3D.js.map +0 -1
  295. package/dist/chunk-VW24K2Q4.js.map +0 -1
  296. /package/dist/{chunk-OMSTU233.js.map → chunk-2KAYTPPT.js.map} +0 -0
  297. /package/dist/{chunk-VYZNWH4J.js.map → chunk-2SXMCQEQ.js.map} +0 -0
  298. /package/dist/{chunk-NXL5CVE7.js.map → chunk-2Y6LMOQQ.js.map} +0 -0
  299. /package/dist/{chunk-LQ4J7ELC.js.map → chunk-67HG7KFE.js.map} +0 -0
  300. /package/dist/{chunk-ZBG4K36I.js.map → chunk-6FUJ2VYY.js.map} +0 -0
  301. /package/dist/{chunk-GMRNKPWO.js.map → chunk-6QUPUTT7.js.map} +0 -0
  302. /package/dist/{chunk-Z56IHRVV.js.map → chunk-6UU43ZGD.js.map} +0 -0
  303. /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
  304. /package/dist/{chunk-OWOKOFXK.js.map → chunk-AJOIM6UR.js.map} +0 -0
  305. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  306. /package/dist/{chunk-K22IJO4R.js.map → chunk-CTOQEZSN.js.map} +0 -0
  307. /package/dist/{chunk-HSDJCT3V.js.map → chunk-DXGS5YOQ.js.map} +0 -0
  308. /package/dist/{chunk-HV57RHMD.js.map → chunk-EH5ED3C6.js.map} +0 -0
  309. /package/dist/{chunk-7NDYFAJS.js.map → chunk-GM3BMWKR.js.map} +0 -0
  310. /package/dist/{chunk-5QUS24F7.js.map → chunk-I56LKMF7.js.map} +0 -0
  311. /package/dist/{chunk-35YJ6KCV.js.map → chunk-JEIROMLX.js.map} +0 -0
  312. /package/dist/{chunk-SKQCFAYU.js.map → chunk-JVEMUX6L.js.map} +0 -0
  313. /package/dist/{chunk-CXMXAC5R.js.map → chunk-K44MIN6D.js.map} +0 -0
  314. /package/dist/{chunk-BQCFXAMN.js.map → chunk-MPHDVHIB.js.map} +0 -0
  315. /package/dist/{chunk-QXNFQKWU.js.map → chunk-MTHNJCOJ.js.map} +0 -0
  316. /package/dist/{chunk-3TCRU4JA.js.map → chunk-O62P2LFL.js.map} +0 -0
  317. /package/dist/{chunk-JSDZMOT7.js.map → chunk-OC56UWV5.js.map} +0 -0
  318. /package/dist/{chunk-7IBEWQLG.js.map → chunk-QOIONSOI.js.map} +0 -0
  319. /package/dist/{chunk-4P5UAL3C.js.map → chunk-RBHANGVX.js.map} +0 -0
  320. /package/dist/{chunk-SK2CR6MW.js.map → chunk-RVLB4E6N.js.map} +0 -0
  321. /package/dist/{chunk-CNVIWMQI.js.map → chunk-UY4JMEAK.js.map} +0 -0
  322. /package/dist/{chunk-S6FQLQGH.js.map → chunk-V7GDTQ6I.js.map} +0 -0
  323. /package/dist/{chunk-JNOYYWCA.js.map → chunk-VO4UICII.js.map} +0 -0
  324. /package/dist/{chunk-54TI5GLV.js.map → chunk-WI4QX7GH.js.map} +0 -0
  325. /package/dist/{chunk-XKU4YE6Z.js.map → chunk-XZTUMWKQ.js.map} +0 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Shared types for the conversational memory chat engine (issue #1583).
3
+ *
4
+ * The chat engine is a deliberately bounded tool-loop agent — NOT a general
5
+ * assistant. It exposes a fixed set of read-only and (confirmation-gated)
6
+ * mutating tools, each a thin adapter over an existing access-service method.
7
+ */
8
+
9
+ // ---------------------------------------------------------------------------
10
+ // LLM adapter — production signature (rule 33), stubbable for tests
11
+ // ---------------------------------------------------------------------------
12
+
13
+ /**
14
+ * A single chat message in the LLM conversation.
15
+ */
16
+ export interface ChatLlmMessage {
17
+ role: "system" | "user" | "assistant" | "tool";
18
+ content: string;
19
+ /** Tool-call id when role === "tool" (correlates the result back). */
20
+ toolCallId?: string;
21
+ }
22
+
23
+ /**
24
+ * A tool-call request emitted by the LLM. The engine parses these from the
25
+ * LLM response and dispatches them through the tool registry.
26
+ */
27
+ export interface ChatLlmToolCall {
28
+ id: string;
29
+ name: string;
30
+ arguments: Record<string, unknown>;
31
+ }
32
+
33
+ /**
34
+ * Structured LLM response — either a text reply or a set of tool calls.
35
+ * The adapter (stub or production) is responsible for parsing the raw model
36
+ * output into this shape.
37
+ */
38
+ export interface ChatLlmResponse {
39
+ /** Assistant text reply (empty when only tool calls are present). */
40
+ content: string;
41
+ /** Tool calls to execute (empty for a final text reply). */
42
+ toolCalls: ChatLlmToolCall[];
43
+ }
44
+
45
+ /**
46
+ * Production-grade LLM adapter interface. The stub implementation used in
47
+ * tests drives scripted sequences; the production implementation wraps the
48
+ * existing FallbackLlmClient routing chain so local Ollama/vLLM models are
49
+ * fully supported (gotcha 1).
50
+ */
51
+ export interface ChatLlmAdapter {
52
+ /**
53
+ * Send the conversation so far to the LLM and receive the next response.
54
+ * Returns `null` when no model is available or the request fails (rule 13).
55
+ */
56
+ complete(
57
+ messages: ChatLlmMessage[],
58
+ options: {
59
+ tools: ChatToolSchema[];
60
+ model?: string;
61
+ signal?: AbortSignal;
62
+ },
63
+ ): Promise<ChatLlmResponse | null>;
64
+ }
65
+
66
+ // ---------------------------------------------------------------------------
67
+ // Tool schema + execution
68
+ // ---------------------------------------------------------------------------
69
+
70
+ /**
71
+ * JSON-Schema description of a chat tool, sent to the LLM so it knows what
72
+ * tools are available and how to call them.
73
+ */
74
+ export interface ChatToolSchema {
75
+ type: "function";
76
+ function: {
77
+ name: string;
78
+ description: string;
79
+ parameters: Record<string, unknown>;
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Result of executing a chat tool. Read-only tools return data; mutating
85
+ * tools go through the confirmation protocol before they reach the executor.
86
+ */
87
+ export interface ChatToolResult {
88
+ /** Structured payload returned to the LLM as a tool message. */
89
+ content: string;
90
+ /** Whether the tool call was intercepted by the confirmation protocol. */
91
+ pendingConfirmation?: boolean;
92
+ /** Plan preview when pendingConfirmation is true. */
93
+ planPreview?: string;
94
+ }
95
+
96
+ // ---------------------------------------------------------------------------
97
+ // Chat session — transcript + pending-plan state
98
+ // ---------------------------------------------------------------------------
99
+
100
+ /**
101
+ * A single line in the persisted chat transcript (JSONL).
102
+ */
103
+ export interface ChatTranscriptEntry {
104
+ /** Monotonic sequence number within the session. */
105
+ seq: number;
106
+ /** ISO 8601 timestamp. */
107
+ ts: string;
108
+ role: "user" | "assistant" | "tool" | "system";
109
+ content: string;
110
+ /** Tool-call id for tool messages. */
111
+ toolCallId?: string;
112
+ /** Tool name for tool messages. */
113
+ toolName?: string;
114
+ }
115
+
116
+ /**
117
+ * In-memory session state, backed by the JSONL transcript on disk.
118
+ */
119
+ export interface ChatSessionState {
120
+ id: string;
121
+ /** Caller principal bound at creation (rule 42). */
122
+ principal?: string;
123
+ /** Session key for namespace resolution. */
124
+ sessionKey?: string;
125
+ /** Namespace override. */
126
+ namespace?: string;
127
+ /** Transcript entries loaded from disk. */
128
+ transcript: ChatTranscriptEntry[];
129
+ /** Plan ids confirmed by the user for exactly one apply. */
130
+ confirmedPlanIds: Set<string>;
131
+ /** The pending plan awaiting confirmation (if any). */
132
+ pendingPlanId?: string;
133
+ /** The pending memory-promotion memory id awaiting confirmation (if any). */
134
+ pendingPromotionId?: string;
135
+ /** Creation timestamp. */
136
+ createdAt: string;
137
+ }
138
+
139
+ // ---------------------------------------------------------------------------
140
+ // Engine turn result
141
+ // ---------------------------------------------------------------------------
142
+
143
+ /**
144
+ * What the engine returns for a single user message.
145
+ */
146
+ export interface ChatTurnResult {
147
+ /** The assistant's text reply (may be partial on budget exhaustion). */
148
+ reply: string;
149
+ /** The chat session id (existing or newly created). */
150
+ chatSessionId: string;
151
+ /** A pending plan awaiting user confirmation, if surfaced. */
152
+ pendingPlan?: {
153
+ planId: string;
154
+ preview: string;
155
+ };
156
+ /** Tool calls that were skipped due to budget exhaustion. */
157
+ skippedTools?: string[];
158
+ /** Whether the reply is a tagged error (rule 13). */
159
+ error?: string;
160
+ }
161
+
162
+ // ---------------------------------------------------------------------------
163
+ // Chat config — re-exported from types.ts (canonical definition).
164
+ // DEFAULT_CHAT_CONFIG lives in chat-config.ts.
165
+ // ---------------------------------------------------------------------------
166
+
167
+ export type { ChatConfig } from "../types.js";
package/src/cli.ts CHANGED
@@ -95,6 +95,7 @@ import { WebDavServer } from "./network/webdav.js";
95
95
  import { GraphDashboardServer, type DashboardStatus } from "./dashboard-runtime.js";
96
96
  import { EngramAccessService } from "./access-service.js";
97
97
  import { EngramAccessHttpServer } from "./access-http.js";
98
+ import { runChatCli } from "./chat/chat-cli.js";
98
99
  import {
99
100
  buildActionConfidenceInputFromOptions,
100
101
  evaluateActionConfidence,
@@ -2807,6 +2808,7 @@ export async function runAccessMcpServeCliCommand(
2807
2808
  architectureCardVisible: service.architectureCardSurfaceVisible,
2808
2809
  codegraphVisible: service.codegraphSurfaceVisible,
2809
2810
  sessionDeltaVisible: service.sessionDeltaSurfaceVisible,
2811
+ chatVisible: service.configRef?.chat?.enabled === true,
2810
2812
  correctionVisible: service.correctionSurfaceVisible,
2811
2813
  });
2812
2814
  await server.runStdio(options.stdin ?? process.stdin, options.stdout ?? process.stdout);
@@ -9336,6 +9338,24 @@ export function registerCli(
9336
9338
  }
9337
9339
  }
9338
9340
  });
9341
+ // ── Chat — conversational memory inspection + correction (#1583) ────
9342
+ cmd
9343
+ .command("chat")
9344
+ .description("Conversational memory inspection and correction (issue #1583)")
9345
+ .option("--session <id>", "Resume an existing chat session")
9346
+ .option("--once", "Process a single message from stdin and exit (non-TTY/scripting)")
9347
+ .option("--principal <principal>", "Trusted principal (defaults to config/env)")
9348
+ .action(async (...args: unknown[]) => {
9349
+ const options = (args[0] ?? {}) as Record<string, unknown>;
9350
+ await runChatCli({
9351
+ service: new EngramAccessService(orchestrator),
9352
+ config: orchestrator.config?.chat,
9353
+ memoryDir: orchestrator.config.memoryDir,
9354
+ principal: resolveAccessPrincipalOverride(options.principal, orchestrator.config.agentAccessHttp.principal),
9355
+ ...(typeof options.session === "string" ? { sessionId: options.session } : {}),
9356
+ ...(options.once === true ? { once: true } : {}),
9357
+ });
9358
+ });
9339
9359
  },
9340
9360
  { commands: ["engram"] },
9341
9361
  );
package/src/config.ts CHANGED
@@ -47,6 +47,7 @@ import {
47
47
  import { parseWearablesConfig } from "./wearables/config.js";
48
48
  import { parseProvenanceConfig } from "./provenance.js";
49
49
  import { parseCodingKnowledgeConfig } from "./coding/coding-knowledge-config.js";
50
+ import { parseChatConfig } from "./chat/chat-config.js";
50
51
  const DEFAULT_MEMORY_DIR = path.join(
51
52
  resolveHomeDir(),
52
53
  ".openclaw",
@@ -2507,6 +2508,7 @@ export function parseConfig(
2507
2508
  slotBehavior,
2508
2509
  codexCompat,
2509
2510
  codingKnowledge: parseCodingKnowledgeConfig(cfg.codingKnowledge),
2511
+ chat: parseChatConfig(cfg.chat),
2510
2512
  // Hourly summaries
2511
2513
  hourlySummariesEnabled: cfg.hourlySummariesEnabled !== false, // default: true
2512
2514
  daySummaryEnabled: cfg.daySummaryEnabled !== false, // default: true
@@ -3246,6 +3248,13 @@ export function parseConfig(
3246
3248
  // Issue #564 PR 3: off by default; enable explicitly after bench validation.
3247
3249
  recallReasoningTraceBoostEnabled:
3248
3250
  coerceBool(cfg.recallReasoningTraceBoostEnabled) ?? false,
3251
+ // Issue #1582: off by default — handles are byte-additive at injection time.
3252
+ recallMemoryHandles: coerceBool(cfg.recallMemoryHandles) ?? false,
3253
+ recallHandleSnapshotDepth:
3254
+ typeof cfg.recallHandleSnapshotDepth === "number" &&
3255
+ Number.isFinite(cfg.recallHandleSnapshotDepth)
3256
+ ? Math.max(1, Math.min(50, Math.floor(cfg.recallHandleSnapshotDepth)))
3257
+ : 5,
3249
3258
  qmdRecallCacheTtlMs:
3250
3259
  typeof cfg.qmdRecallCacheTtlMs === "number" ? Math.max(0, Math.floor(cfg.qmdRecallCacheTtlMs)) : 60_000,
3251
3260
  qmdRecallCacheStaleTtlMs:
@@ -25,6 +25,7 @@ import { Orchestrator } from "./orchestrator.js";
25
25
  import { readEdges } from "./graph.js";
26
26
  import type { ExtractionResult, PluginConfig } from "./types.js";
27
27
  import type { LocalLlmClient } from "./local-llm.js";
28
+ import type { BufferTurn, ConversationThread } from "./types.js";
28
29
 
29
30
  /**
30
31
  * Stub local LLM whose `chatCompletion` only answers faithfulness-gate calls
@@ -42,15 +43,20 @@ function faithfulnessStubLocalLlm(
42
43
  ) => {
43
44
  if (options.operation !== "extraction-faithfulness") return null;
44
45
  const userMsg = messages.find((m) => m.role === "user");
45
- // The prompt emits `FACT: "<text>"` fact text never contains a raw
46
- // double-quote, so capture up to the closing quote.
47
- const match = userMsg?.content.match(/FACT: "([^"]*)"/);
48
- const factContent = match ? (match[1] ?? "") : "";
49
- const verdict = verdictForFactContent(factContent);
46
+ // The batch prompt emits one `FACT: "<text>"` line per fact, each
47
+ // followed by `Respond with the JSON array entry for index <i>`. The
48
+ // gate maps verdicts back to facts by that index, so return one entry
49
+ // per fact in prompt order. (Single-fact callers still get one entry.)
50
+ const factMatches = [...(userMsg?.content ?? "").matchAll(/FACT: "([^"]*)"/g)];
51
+ const entries = factMatches.map((m, i) => ({
52
+ index: i,
53
+ verdict: verdictForFactContent(m[1] ?? ""),
54
+ rationale: "stub verdict",
55
+ }));
50
56
  return {
51
- content: JSON.stringify([
52
- { index: 0, verdict, rationale: "stub verdict" },
53
- ]),
57
+ content: JSON.stringify(
58
+ entries.length > 0 ? entries : [{ index: 0, verdict: "entailed" as const, rationale: "stub" }],
59
+ ),
54
60
  };
55
61
  },
56
62
  } as unknown as LocalLlmClient;
@@ -250,3 +256,203 @@ test("pending_review fact gets no graph edge; an active fact with the same entit
250
256
  await rm(memoryDir, { recursive: true, force: true });
251
257
  }
252
258
  });
259
+
260
+
261
+ /**
262
+ * Thread-enabled harness for issue #1635: time + causal graph ON (so
263
+ * thread-predecessor edges are built), faithfulness gate in enforce mode.
264
+ * Entity graph is left OFF to isolate the thread-episode predecessor
265
+ * mechanism (entity-sibling edges are a separate, out-of-scope path).
266
+ */
267
+ async function makeThreadHarness(): Promise<OrchHarness> {
268
+ const memoryDir = await mkdtemp(
269
+ path.join(os.tmpdir(), "remnic-faithfulness-thread-"),
270
+ );
271
+ const config: PluginConfig = parseConfig({
272
+ openaiApiKey: "sk-test",
273
+ memoryDir,
274
+ workspaceDir: path.join(memoryDir, "workspace"),
275
+ multiGraphMemoryEnabled: true,
276
+ entityGraphEnabled: false,
277
+ timeGraphEnabled: true,
278
+ causalGraphEnabled: true,
279
+ extractionFaithfulnessGate: "enforce",
280
+ extractionFaithfulnessContextChars: 400,
281
+ extractionFaithfulnessTimeoutMs: 2000,
282
+ extractionJudgeEnabled: false,
283
+ temporalSupersessionEnabled: false,
284
+ contradictionDetectionEnabled: false,
285
+ chunkingEnabled: false,
286
+ embeddingFallbackEnabled: false,
287
+ qmdEnabled: false,
288
+ extractionMinChars: 0,
289
+ extractionMinImportanceLevel: "trivial",
290
+ inlineSourceAttributionEnabled: false,
291
+ });
292
+ const orchestrator = new Orchestrator(config);
293
+ return { orchestrator, memoryDir };
294
+ }
295
+
296
+ /** ExtractionResult with two facts (order preserved by the persist loop). */
297
+ function twoFactResult(
298
+ contentA: string,
299
+ entityRefA: string,
300
+ contentB: string,
301
+ entityRefB: string,
302
+ ): ExtractionResult {
303
+ return {
304
+ facts: [
305
+ { content: contentA, category: "fact", tags: [], confidence: 0.9, entityRef: entityRefA },
306
+ { content: contentB, category: "fact", tags: [], confidence: 0.9, entityRef: entityRefB },
307
+ ],
308
+ entities: [],
309
+ relationships: [],
310
+ questions: [],
311
+ profileUpdates: [],
312
+ } as unknown as ExtractionResult;
313
+ }
314
+
315
+ interface StorageLike {
316
+ ensureDirectories: () => Promise<void>;
317
+ dir: string;
318
+ readAllMemories: () => Promise<
319
+ Array<{ path: string; frontmatter: { id: string; status?: string } }>
320
+ >;
321
+ }
322
+
323
+ interface PersistExtractionSig {
324
+ (
325
+ r: ExtractionResult,
326
+ s: unknown,
327
+ t: string | null,
328
+ ctx: unknown,
329
+ bn: unknown,
330
+ plan: unknown,
331
+ src: string,
332
+ ): Promise<string[]>;
333
+ }
334
+
335
+ test("pending_review id must NOT enter persisted thread episodes across a cross-flush (#1635)", async () => {
336
+ const { orchestrator, memoryDir } = await makeThreadHarness();
337
+ try {
338
+ // fact content containing "closed permanently" → unsupported → pending_review.
339
+ (orchestrator as unknown as { localLlm: LocalLlmClient }).localLlm =
340
+ faithfulnessStubLocalLlm((c) =>
341
+ c.includes("closed permanently") ? "unsupported" : "entailed",
342
+ );
343
+
344
+ const getStorage = orchestrator as unknown as {
345
+ getStorage: (ns: string) => Promise<StorageLike>;
346
+ };
347
+ const storage = await getStorage.getStorage("default");
348
+ await storage.ensureDirectories();
349
+
350
+ // Establish a real thread (mirrors runExtraction's processTurn step) so
351
+ // appendEpisodeIds has a thread file to write episode ids into.
352
+ const threading = orchestrator as unknown as {
353
+ threading: {
354
+ processTurn: (turn: BufferTurn, ids: string[]) => Promise<string>;
355
+ loadThread: (id: string) => Promise<ConversationThread | null>;
356
+ };
357
+ };
358
+ const seedTurn: BufferTurn = {
359
+ role: "user",
360
+ content: "Tell me about the widget factory.",
361
+ timestamp: "2026-07-06T10:00:00.000Z",
362
+ sessionKey: "agent:test:main",
363
+ };
364
+ const threadId = await threading.threading.processTurn(seedTurn, []);
365
+ assert.ok(threadId, "thread established via processTurn");
366
+
367
+ const persist = orchestrator as unknown as {
368
+ persistExtraction: PersistExtractionSig;
369
+ appendPersistedThreadEpisodes: (
370
+ threadId: string,
371
+ persistedIds: string[],
372
+ ) => Promise<void>;
373
+ };
374
+
375
+ const sourceText =
376
+ "The widget factory reopened this quarter after being closed permanently last year.";
377
+
378
+ // --- Flush 1: an active fact + a pending_review fact, same thread ---
379
+ const flush1 = await persist.persistExtraction(
380
+ twoFactResult(
381
+ "The widget factory reopened this quarter.", "wf-active",
382
+ "The widget factory closed permanently last year.", "wf-pending",
383
+ ),
384
+ storage,
385
+ threadId,
386
+ { sessionKey: "agent:test:main", principal: "test" },
387
+ undefined,
388
+ null,
389
+ sourceText,
390
+ );
391
+ const [activeId1, pendingId] = flush1;
392
+ assert.ok(activeId1, "flush1 active fact persisted");
393
+ assert.ok(pendingId, "flush1 pending_review fact persisted");
394
+
395
+ // runExtraction's append step (the real helper; filters pending_review).
396
+ await persist.appendPersistedThreadEpisodes(threadId, flush1);
397
+
398
+ // PART (a): the thread FILE must hold the active id but NOT the pending id.
399
+ const threadAfter1 = await threading.threading.loadThread(threadId);
400
+ assert.ok(threadAfter1, "thread file readable after flush 1");
401
+ assert.ok(
402
+ threadAfter1!.episodeIds.includes(activeId1),
403
+ "active fact id is in persisted thread episodes",
404
+ );
405
+ assert.ok(
406
+ !threadAfter1!.episodeIds.includes(pendingId),
407
+ "pending_review id must NOT enter persisted thread episodes (#1635)",
408
+ );
409
+
410
+ // The pending fact IS durable (with status pending_review) — proves the
411
+ // gate routed it correctly; the guard is about its absence from the thread.
412
+ const memsAfter1 = await storage.readAllMemories();
413
+ const pendingMem = memsAfter1.find((m) => m.frontmatter.id === pendingId);
414
+ assert.ok(pendingMem, "pending_review fact is durable");
415
+ assert.equal(
416
+ pendingMem!.frontmatter.status,
417
+ "pending_review",
418
+ "unsupported fact is pending_review under enforce",
419
+ );
420
+
421
+ // --- Flush 2: an active fact in the SAME thread ---
422
+ const flush2 = await persist.persistExtraction(
423
+ factResult("The widget factory hired ten new engineers.", "wf-active"),
424
+ storage,
425
+ threadId,
426
+ { sessionKey: "agent:test:main", principal: "test" },
427
+ undefined,
428
+ null,
429
+ sourceText,
430
+ );
431
+ const activeId2 = flush2[0];
432
+ assert.ok(activeId2, "flush2 active fact persisted");
433
+ await persist.appendPersistedThreadEpisodes(threadId, flush2);
434
+
435
+ // PART (a)+(b): no predecessor edge may reference the pending fact. Under
436
+ // the bug, flush 1 would have appended pendingId to the thread file, flush
437
+ // 2's loadThread would re-seed it into threadEpisodeIdsForGraph, and the
438
+ // active fact2 would build a time/causal predecessor edge to it.
439
+ const pendingPath = path.relative(memoryDir, pendingMem!.path);
440
+ for (const gtype of ["time", "causal"] as const) {
441
+ const edges = await readEdges(memoryDir, gtype);
442
+ assert.ok(
443
+ !edges.some((e) => e.from === pendingPath || e.to === pendingPath),
444
+ `no ${gtype} edge references the pending_review fact path (${pendingPath}); got ${edges.length} edges`,
445
+ );
446
+ }
447
+
448
+ // Control: the graph + threading are wired — the active fact2 builds a
449
+ // time predecessor edge to the active fact1 (which IS in the thread file).
450
+ const timeEdges = await readEdges(memoryDir, "time");
451
+ assert.ok(
452
+ timeEdges.length > 0,
453
+ "active fact2 builds a time predecessor edge (control: graph+threading wired)",
454
+ );
455
+ } finally {
456
+ await rm(memoryDir, { recursive: true, force: true });
457
+ }
458
+ });