@remnic/core 9.3.712 → 9.3.714

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 (328) 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 +40 -39
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +5 -5
  6. package/dist/access-http.js +24 -23
  7. package/dist/access-mcp.d.ts +18 -5
  8. package/dist/access-mcp.js +21 -20
  9. package/dist/access-operations-batch.js +18 -17
  10. package/dist/access-operations.d.ts +6 -5
  11. package/dist/access-operations.js +20 -19
  12. package/dist/access-schema.d.ts +10 -0
  13. package/dist/access-schema.js +1 -1
  14. package/dist/{access-service-Dx2rSJjH.d.ts → access-service-lddjZoRh.d.ts} +20 -5
  15. package/dist/access-service.d.ts +5 -5
  16. package/dist/access-service.js +16 -15
  17. package/dist/access-surface-catalog.d.ts +5 -5
  18. package/dist/access-surface-catalog.js +6 -1
  19. package/dist/access-surface-catalog.js.map +1 -1
  20. package/dist/action-confidence.d.ts +1 -1
  21. package/dist/active-memory-bridge.d.ts +3 -1
  22. package/dist/active-memory-bridge.js +2 -1
  23. package/dist/active-recall.d.ts +1 -1
  24. package/dist/active-recall.js +4 -3
  25. package/dist/active-recall.js.map +1 -1
  26. package/dist/adapters/index.js +4 -4
  27. package/dist/adapters/registry.js +2 -2
  28. package/dist/behavior-learner.d.ts +1 -1
  29. package/dist/behavior-signals.d.ts +1 -1
  30. package/dist/bootstrap.d.ts +4 -4
  31. package/dist/briefing.d.ts +1 -1
  32. package/dist/briefing.js +8 -7
  33. package/dist/buffer-surprise-report.d.ts +1 -1
  34. package/dist/buffer.d.ts +1 -1
  35. package/dist/calibration.d.ts +1 -1
  36. package/dist/capabilities.d.ts +1 -1
  37. package/dist/{catalog-CadPvH29.d.ts → catalog-CbR0CsUw.d.ts} +1 -1
  38. package/dist/causal-behavior.d.ts +1 -1
  39. package/dist/causal-consolidation.d.ts +1 -1
  40. package/dist/causal-consolidation.js +9 -8
  41. package/dist/causal-consolidation.js.map +1 -1
  42. package/dist/{chunk-OMSTU233.js → chunk-2KAYTPPT.js} +4 -4
  43. package/dist/{chunk-VYZNWH4J.js → chunk-2SXMCQEQ.js} +3 -3
  44. package/dist/{chunk-NXL5CVE7.js → chunk-2Y6LMOQQ.js} +2 -2
  45. package/dist/{chunk-AMXOCZHE.js → chunk-3VUPWDSE.js} +15 -3
  46. package/dist/{chunk-AMXOCZHE.js.map → chunk-3VUPWDSE.js.map} +1 -1
  47. package/dist/{chunk-FVQJYWH7.js → chunk-5GKPFL3S.js} +1 -1
  48. package/dist/{chunk-FVQJYWH7.js.map → chunk-5GKPFL3S.js.map} +1 -1
  49. package/dist/{chunk-LQ4J7ELC.js → chunk-67HG7KFE.js} +2 -2
  50. package/dist/{chunk-ZBG4K36I.js → chunk-6FUJ2VYY.js} +3 -3
  51. package/dist/{chunk-GMRNKPWO.js → chunk-6QUPUTT7.js} +2 -2
  52. package/dist/{chunk-Z56IHRVV.js → chunk-6UU43ZGD.js} +2 -2
  53. package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
  54. package/dist/{chunk-OWOKOFXK.js → chunk-AJOIM6UR.js} +2 -2
  55. package/dist/{chunk-JBPKEARU.js → chunk-AU7Q3LSC.js} +4 -4
  56. package/dist/{chunk-YVWZW37D.js → chunk-BNOAB5HH.js} +62 -12
  57. package/dist/{chunk-YVWZW37D.js.map → chunk-BNOAB5HH.js.map} +1 -1
  58. package/dist/{chunk-A2R5NV6O.js → chunk-CTAHKIG6.js} +205 -29
  59. package/dist/chunk-CTAHKIG6.js.map +1 -0
  60. package/dist/{chunk-K22IJO4R.js → chunk-CTOQEZSN.js} +2 -2
  61. package/dist/{chunk-SINGJCUR.js → chunk-CX77GNMB.js} +14 -3
  62. package/dist/chunk-CX77GNMB.js.map +1 -0
  63. package/dist/{chunk-HSDJCT3V.js → chunk-DXGS5YOQ.js} +3 -3
  64. package/dist/{chunk-HV57RHMD.js → chunk-EH5ED3C6.js} +2 -2
  65. package/dist/{chunk-NUWZFSKC.js → chunk-FVZ2ISIX.js} +9 -1
  66. package/dist/chunk-FVZ2ISIX.js.map +1 -0
  67. package/dist/{chunk-GKPIY7EQ.js → chunk-FXZKXW7C.js} +117 -46
  68. package/dist/chunk-FXZKXW7C.js.map +1 -0
  69. package/dist/{chunk-7NDYFAJS.js → chunk-GM3BMWKR.js} +2 -2
  70. package/dist/{chunk-ZVDRL6SK.js → chunk-HHLWSWWF.js} +2 -2
  71. package/dist/chunk-HHLWSWWF.js.map +1 -0
  72. package/dist/{chunk-5QUS24F7.js → chunk-I56LKMF7.js} +2 -2
  73. package/dist/{chunk-Z3B2YW56.js → chunk-IHMT6XTY.js} +9 -5
  74. package/dist/chunk-IHMT6XTY.js.map +1 -0
  75. package/dist/chunk-JAKIDQB2.js +173 -0
  76. package/dist/chunk-JAKIDQB2.js.map +1 -0
  77. package/dist/{chunk-35YJ6KCV.js → chunk-JEIROMLX.js} +2 -2
  78. package/dist/{chunk-SKQCFAYU.js → chunk-JVEMUX6L.js} +2 -2
  79. package/dist/{chunk-CXMXAC5R.js → chunk-K44MIN6D.js} +3 -3
  80. package/dist/{chunk-5KQCOIPW.js → chunk-MECU6WSH.js} +188 -31
  81. package/dist/chunk-MECU6WSH.js.map +1 -0
  82. package/dist/{chunk-BQCFXAMN.js → chunk-MPHDVHIB.js} +2 -2
  83. package/dist/{chunk-BOGENF7P.js → chunk-MSVSP5VO.js} +1 -1
  84. package/dist/chunk-MSVSP5VO.js.map +1 -0
  85. package/dist/{chunk-QXNFQKWU.js → chunk-MTHNJCOJ.js} +2 -2
  86. package/dist/{chunk-3TCRU4JA.js → chunk-O62P2LFL.js} +2 -2
  87. package/dist/{chunk-JSDZMOT7.js → chunk-OC56UWV5.js} +11 -11
  88. package/dist/{chunk-7IBEWQLG.js → chunk-QOIONSOI.js} +2 -2
  89. package/dist/{chunk-4P5UAL3C.js → chunk-RBHANGVX.js} +6 -6
  90. package/dist/{chunk-SK2CR6MW.js → chunk-RVLB4E6N.js} +2 -2
  91. package/dist/{chunk-I3BT2IDW.js → chunk-SYDHFFAW.js} +1110 -28
  92. package/dist/chunk-SYDHFFAW.js.map +1 -0
  93. package/dist/{chunk-VILEUJXC.js → chunk-UC4YOAC2.js} +74 -2
  94. package/dist/{chunk-VILEUJXC.js.map → chunk-UC4YOAC2.js.map} +1 -1
  95. package/dist/{chunk-CNVIWMQI.js → chunk-UY4JMEAK.js} +2 -2
  96. package/dist/{chunk-S6FQLQGH.js → chunk-V7GDTQ6I.js} +2 -2
  97. package/dist/{chunk-JNOYYWCA.js → chunk-VO4UICII.js} +3 -3
  98. package/dist/{chunk-54TI5GLV.js → chunk-WI4QX7GH.js} +3 -3
  99. package/dist/{chunk-3XHD3XGK.js → chunk-XCTDHF7U.js} +30 -2
  100. package/dist/chunk-XCTDHF7U.js.map +1 -0
  101. package/dist/{chunk-XKU4YE6Z.js → chunk-XZTUMWKQ.js} +2 -2
  102. package/dist/{cli-DTWRoJEI.d.ts → cli-iAiVkbYJ.d.ts} +3 -3
  103. package/dist/cli.d.ts +6 -6
  104. package/dist/cli.js +43 -42
  105. package/dist/compounding/engine.d.ts +1 -1
  106. package/dist/compounding/engine.js +8 -7
  107. package/dist/compounding/preference-consolidator.d.ts +1 -1
  108. package/dist/compression-optimizer.d.ts +1 -1
  109. package/dist/config.d.ts +1 -1
  110. package/dist/config.js +4 -3
  111. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  112. package/dist/connectors/codex-materialize-runner.js +8 -7
  113. package/dist/connectors/codex-materialize.d.ts +1 -1
  114. package/dist/connectors/index.d.ts +1 -1
  115. package/dist/connectors/index.js +9 -8
  116. package/dist/consolidation-provenance-check.d.ts +1 -1
  117. package/dist/consolidation-undo.d.ts +1 -1
  118. package/dist/contradiction/index.d.ts +1 -1
  119. package/dist/conversation-index/backend.d.ts +1 -1
  120. package/dist/conversation-index/chunker.d.ts +1 -1
  121. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  122. package/dist/conversation-index/indexer.d.ts +1 -1
  123. package/dist/conversation-index/search.d.ts +1 -1
  124. package/dist/day-summary.d.ts +1 -1
  125. package/dist/delinearize.d.ts +1 -1
  126. package/dist/direct-answer-wiring.d.ts +1 -1
  127. package/dist/direct-answer.d.ts +1 -1
  128. package/dist/embedding-fallback.d.ts +1 -1
  129. package/dist/enrichment/index.d.ts +1 -1
  130. package/dist/entity-retrieval.d.ts +1 -1
  131. package/dist/entity-retrieval.js +8 -7
  132. package/dist/entity-schema.d.ts +1 -1
  133. package/dist/explicit-capture.d.ts +4 -4
  134. package/dist/explicit-capture.js +3 -2
  135. package/dist/extraction-faithfulness.d.ts +1 -1
  136. package/dist/extraction-judge-telemetry.d.ts +1 -1
  137. package/dist/extraction-judge-training.d.ts +1 -1
  138. package/dist/extraction-judge.d.ts +1 -1
  139. package/dist/extraction.d.ts +1 -1
  140. package/dist/extraction.js +4 -3
  141. package/dist/fallback-llm.d.ts +1 -1
  142. package/dist/identity-continuity.d.ts +1 -1
  143. package/dist/importance.d.ts +1 -1
  144. package/dist/index.d.ts +9 -9
  145. package/dist/index.js +62 -61
  146. package/dist/index.js.map +1 -1
  147. package/dist/intent.d.ts +1 -1
  148. package/dist/lcm/engine.d.ts +1 -1
  149. package/dist/lcm/index.d.ts +1 -1
  150. package/dist/lcm/index.js +3 -3
  151. package/dist/lcm/tools.d.ts +1 -1
  152. package/dist/lifecycle.d.ts +1 -1
  153. package/dist/live-connectors-runner.d.ts +1 -1
  154. package/dist/local-llm.d.ts +1 -1
  155. package/dist/maintenance/memory-governance.d.ts +1 -1
  156. package/dist/maintenance/memory-governance.js +8 -7
  157. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -7
  158. package/dist/maintenance/rebuild-memory-projection.js +9 -8
  159. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  160. package/dist/memory-action-policy.d.ts +1 -1
  161. package/dist/memory-cache.d.ts +1 -1
  162. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  163. package/dist/memory-projection-store.d.ts +1 -1
  164. package/dist/memory-provenance.d.ts +1 -1
  165. package/dist/memory-worth-outcomes.d.ts +1 -1
  166. package/dist/models-json.d.ts +1 -1
  167. package/dist/namespaces/migrate.d.ts +2 -2
  168. package/dist/namespaces/migrate.js +12 -11
  169. package/dist/namespaces/principal.d.ts +1 -1
  170. package/dist/namespaces/search.d.ts +1 -1
  171. package/dist/namespaces/search.js +3 -3
  172. package/dist/namespaces/storage.d.ts +2 -2
  173. package/dist/namespaces/storage.js +8 -7
  174. package/dist/native-knowledge.d.ts +1 -1
  175. package/dist/operator-toolkit.d.ts +1 -1
  176. package/dist/operator-toolkit.js +17 -16
  177. package/dist/orchestration/maintenance.d.ts +2 -2
  178. package/dist/orchestration/maintenance.js +10 -9
  179. package/dist/{orchestrator-B1iVjEyc.d.ts → orchestrator-iVZWi8aW.d.ts} +21 -4
  180. package/dist/orchestrator.d.ts +4 -4
  181. package/dist/orchestrator.js +32 -31
  182. package/dist/patterns-cli.d.ts +1 -1
  183. package/dist/policy-runtime.d.ts +1 -1
  184. package/dist/provenance.d.ts +1 -1
  185. package/dist/provenance.js +3 -2
  186. package/dist/qmd-recall-cache.d.ts +1 -1
  187. package/dist/qmd.d.ts +1 -1
  188. package/dist/recall-disclosure-escalation.d.ts +1 -1
  189. package/dist/recall-explain-renderer.d.ts +1 -1
  190. package/dist/recall-explain-renderer.js +3 -3
  191. package/dist/recall-handles.d.ts +228 -0
  192. package/dist/recall-handles.js +42 -0
  193. package/dist/recall-handles.js.map +1 -0
  194. package/dist/recall-planner-llm.d.ts +1 -1
  195. package/dist/recall-state.d.ts +40 -2
  196. package/dist/recall-state.js +3 -1
  197. package/dist/recall-tag-filter.d.ts +1 -1
  198. package/dist/recall-xray-cli.d.ts +1 -1
  199. package/dist/recall-xray-cli.js +4 -4
  200. package/dist/recall-xray-renderer.d.ts +1 -1
  201. package/dist/recall-xray-renderer.js +3 -3
  202. package/dist/recall-xray.d.ts +1 -1
  203. package/dist/recall-xray.js +2 -2
  204. package/dist/resolve-auth-token.d.ts +1 -1
  205. package/dist/resume-bundles.js +5 -4
  206. package/dist/retrieval-agents.d.ts +1 -1
  207. package/dist/retrieval-tiers.d.ts +1 -1
  208. package/dist/routing/engine.d.ts +1 -1
  209. package/dist/routing/store.d.ts +1 -1
  210. package/dist/sanitize.d.ts +2 -0
  211. package/dist/sanitize.js +6 -2
  212. package/dist/search/embed-helper.d.ts +1 -1
  213. package/dist/search/factory.d.ts +1 -1
  214. package/dist/search/factory.js +2 -2
  215. package/dist/search/index.d.ts +1 -1
  216. package/dist/search/index.js +4 -4
  217. package/dist/search/lancedb-backend.d.ts +1 -1
  218. package/dist/search/meilisearch-backend.d.ts +1 -1
  219. package/dist/search/noop-backend.d.ts +1 -1
  220. package/dist/search/orama-backend.d.ts +1 -1
  221. package/dist/search/port.d.ts +1 -1
  222. package/dist/search/remote-backend.d.ts +1 -1
  223. package/dist/{semantic-consolidation-CY8uVRNJ.d.ts → semantic-consolidation-DSjMDZ1u.d.ts} +1 -1
  224. package/dist/semantic-consolidation.d.ts +2 -2
  225. package/dist/semantic-consolidation.js +9 -8
  226. package/dist/semantic-rule-promotion.js +8 -7
  227. package/dist/semantic-rule-verifier.d.ts +1 -1
  228. package/dist/semantic-rule-verifier.js +8 -7
  229. package/dist/session-observer-bands.d.ts +1 -1
  230. package/dist/session-observer-state.d.ts +1 -1
  231. package/dist/shared-context/manager.d.ts +3 -3
  232. package/dist/signal.d.ts +1 -1
  233. package/dist/storage.d.ts +1 -1
  234. package/dist/storage.js +7 -6
  235. package/dist/summarizer.d.ts +1 -1
  236. package/dist/summary-snapshot.d.ts +1 -1
  237. package/dist/temporal-supersession.d.ts +1 -1
  238. package/dist/temporal-validity.d.ts +1 -1
  239. package/dist/threading.d.ts +1 -1
  240. package/dist/tier-migration.d.ts +1 -1
  241. package/dist/tier-routing.d.ts +1 -1
  242. package/dist/topics.d.ts +1 -1
  243. package/dist/transcript.d.ts +1 -1
  244. package/dist/transfer/import-sqlite.js +2 -2
  245. package/dist/{types-Dr0Cw3L9.d.ts → types-D9dwzU_x.d.ts} +25 -1
  246. package/dist/types.d.ts +1 -1
  247. package/dist/types.js +1 -1
  248. package/dist/utility-runtime.d.ts +1 -1
  249. package/dist/verified-recall.js +8 -7
  250. package/package.json +2 -2
  251. package/src/access-boundary.ts +4 -1
  252. package/src/access-http.ts +78 -20
  253. package/src/access-mcp.test.ts +29 -0
  254. package/src/access-mcp.ts +99 -17
  255. package/src/access-operations-batch.ts +14 -0
  256. package/src/access-operations.ts +5 -0
  257. package/src/access-schema.ts +8 -0
  258. package/src/access-service-observe-idempotency.test.ts +308 -0
  259. package/src/access-service.ts +106 -5
  260. package/src/access-surface-catalog.test.ts +4 -2
  261. package/src/access-surface-catalog.ts +5 -0
  262. package/src/active-memory-bridge.test.ts +72 -0
  263. package/src/active-memory-bridge.ts +21 -2
  264. package/src/chat/chat-cli.test.ts +142 -0
  265. package/src/chat/chat-cli.ts +206 -0
  266. package/src/chat/chat-config.ts +57 -0
  267. package/src/chat/chat-engine.test.ts +272 -0
  268. package/src/chat/chat-engine.ts +518 -0
  269. package/src/chat/chat-executor.ts +133 -0
  270. package/src/chat/chat-factory.ts +161 -0
  271. package/src/chat/chat-http.test.ts +197 -0
  272. package/src/chat/chat-http.ts +222 -0
  273. package/src/chat/chat-llm.ts +229 -0
  274. package/src/chat/chat-mcp.test.ts +135 -0
  275. package/src/chat/chat-security.test.ts +491 -0
  276. package/src/chat/chat-session.ts +296 -0
  277. package/src/chat/chat-system-prompt.ts +76 -0
  278. package/src/chat/chat-tools.ts +255 -0
  279. package/src/chat/chat-types.ts +167 -0
  280. package/src/cli.ts +20 -0
  281. package/src/config.ts +9 -0
  282. package/src/orchestrator.ts +106 -5
  283. package/src/recall-handles-wiring.test.ts +477 -0
  284. package/src/recall-handles.test.ts +283 -0
  285. package/src/recall-handles.ts +414 -0
  286. package/src/recall-state.ts +99 -0
  287. package/src/sanitize.ts +6 -0
  288. package/src/types.ts +29 -0
  289. package/dist/chunk-3XHD3XGK.js.map +0 -1
  290. package/dist/chunk-5KQCOIPW.js.map +0 -1
  291. package/dist/chunk-A2R5NV6O.js.map +0 -1
  292. package/dist/chunk-BOGENF7P.js.map +0 -1
  293. package/dist/chunk-GKPIY7EQ.js.map +0 -1
  294. package/dist/chunk-I3BT2IDW.js.map +0 -1
  295. package/dist/chunk-NUWZFSKC.js.map +0 -1
  296. package/dist/chunk-SINGJCUR.js.map +0 -1
  297. package/dist/chunk-Z3B2YW56.js.map +0 -1
  298. package/dist/chunk-ZVDRL6SK.js.map +0 -1
  299. /package/dist/{chunk-OMSTU233.js.map → chunk-2KAYTPPT.js.map} +0 -0
  300. /package/dist/{chunk-VYZNWH4J.js.map → chunk-2SXMCQEQ.js.map} +0 -0
  301. /package/dist/{chunk-NXL5CVE7.js.map → chunk-2Y6LMOQQ.js.map} +0 -0
  302. /package/dist/{chunk-LQ4J7ELC.js.map → chunk-67HG7KFE.js.map} +0 -0
  303. /package/dist/{chunk-ZBG4K36I.js.map → chunk-6FUJ2VYY.js.map} +0 -0
  304. /package/dist/{chunk-GMRNKPWO.js.map → chunk-6QUPUTT7.js.map} +0 -0
  305. /package/dist/{chunk-Z56IHRVV.js.map → chunk-6UU43ZGD.js.map} +0 -0
  306. /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
  307. /package/dist/{chunk-OWOKOFXK.js.map → chunk-AJOIM6UR.js.map} +0 -0
  308. /package/dist/{chunk-JBPKEARU.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  309. /package/dist/{chunk-K22IJO4R.js.map → chunk-CTOQEZSN.js.map} +0 -0
  310. /package/dist/{chunk-HSDJCT3V.js.map → chunk-DXGS5YOQ.js.map} +0 -0
  311. /package/dist/{chunk-HV57RHMD.js.map → chunk-EH5ED3C6.js.map} +0 -0
  312. /package/dist/{chunk-7NDYFAJS.js.map → chunk-GM3BMWKR.js.map} +0 -0
  313. /package/dist/{chunk-5QUS24F7.js.map → chunk-I56LKMF7.js.map} +0 -0
  314. /package/dist/{chunk-35YJ6KCV.js.map → chunk-JEIROMLX.js.map} +0 -0
  315. /package/dist/{chunk-SKQCFAYU.js.map → chunk-JVEMUX6L.js.map} +0 -0
  316. /package/dist/{chunk-CXMXAC5R.js.map → chunk-K44MIN6D.js.map} +0 -0
  317. /package/dist/{chunk-BQCFXAMN.js.map → chunk-MPHDVHIB.js.map} +0 -0
  318. /package/dist/{chunk-QXNFQKWU.js.map → chunk-MTHNJCOJ.js.map} +0 -0
  319. /package/dist/{chunk-3TCRU4JA.js.map → chunk-O62P2LFL.js.map} +0 -0
  320. /package/dist/{chunk-JSDZMOT7.js.map → chunk-OC56UWV5.js.map} +0 -0
  321. /package/dist/{chunk-7IBEWQLG.js.map → chunk-QOIONSOI.js.map} +0 -0
  322. /package/dist/{chunk-4P5UAL3C.js.map → chunk-RBHANGVX.js.map} +0 -0
  323. /package/dist/{chunk-SK2CR6MW.js.map → chunk-RVLB4E6N.js.map} +0 -0
  324. /package/dist/{chunk-CNVIWMQI.js.map → chunk-UY4JMEAK.js.map} +0 -0
  325. /package/dist/{chunk-S6FQLQGH.js.map → chunk-V7GDTQ6I.js.map} +0 -0
  326. /package/dist/{chunk-JNOYYWCA.js.map → chunk-VO4UICII.js.map} +0 -0
  327. /package/dist/{chunk-54TI5GLV.js.map → chunk-WI4QX7GH.js.map} +0 -0
  328. /package/dist/{chunk-XKU4YE6Z.js.map → chunk-XZTUMWKQ.js.map} +0 -0
@@ -11,19 +11,19 @@ import {
11
11
  } from "./chunk-D24OXEPB.js";
12
12
  import {
13
13
  validateRequest
14
- } from "./chunk-NUWZFSKC.js";
14
+ } from "./chunk-FVZ2ISIX.js";
15
15
  import {
16
16
  getOperation
17
- } from "./chunk-ZVDRL6SK.js";
17
+ } from "./chunk-HHLWSWWF.js";
18
18
  import {
19
19
  EngramAccessInputError
20
- } from "./chunk-YVWZW37D.js";
20
+ } from "./chunk-BNOAB5HH.js";
21
21
  import {
22
22
  projectTagProjectId
23
23
  } from "./chunk-SHRRWOVY.js";
24
24
  import {
25
25
  validateBriefingFormat
26
- } from "./chunk-35YJ6KCV.js";
26
+ } from "./chunk-JEIROMLX.js";
27
27
  import {
28
28
  resolvePrincipal
29
29
  } from "./chunk-UZYLX7M6.js";
@@ -35,8 +35,1012 @@ import {
35
35
  } from "./chunk-JUC24CTX.js";
36
36
 
37
37
  // src/access-mcp.ts
38
- import { readFile } from "fs/promises";
38
+ import { readFile as readFile2 } from "fs/promises";
39
+ import { randomUUID as randomUUID2 } from "crypto";
40
+
41
+ // src/chat/chat-system-prompt.ts
42
+ function buildChatSystemPrompt(opts) {
43
+ const lines = [
44
+ "You are Remnic Chat \u2014 a conversational memory inspector and corrector.",
45
+ "You help the user understand, explore, and fix what Remnic remembers.",
46
+ "",
47
+ "## Core rules",
48
+ "",
49
+ "1. GROUND EVERY ASSERTION. When you state what Remnic remembers, you MUST",
50
+ " cite the memory id or handle, include the source quote, and the date.",
51
+ " If no tool result in this turn supports the claim, say",
52
+ ' "I found nothing" instead of guessing.',
53
+ "",
54
+ "2. NO MUTATION WITHOUT CONFIRMATION. You may propose a correction plan",
55
+ " (correction_plan), but you must NEVER apply it (correction_apply) until",
56
+ " the user explicitly confirms in the conversation.",
57
+ "",
58
+ "3. RENDER PLANS AS DIFFS. When you surface a correction plan, render it",
59
+ " as the diff preview the plan returns \u2014 before/after, affected memory",
60
+ " ids, and the supersession reason.",
61
+ "",
62
+ "4. BE HONEST ABOUT LIMITS. If a tool returns no results, say so. If you",
63
+ " are unsure, say so. Never fabricate memory content.",
64
+ "",
65
+ "5. RESPECT SCOPE. You operate within the caller's namespace and principal.",
66
+ " Do not attempt to access memories outside the caller's scope."
67
+ ];
68
+ if (opts.correctionAvailable) {
69
+ lines.push(
70
+ "",
71
+ "## Mutation protocol",
72
+ "",
73
+ "When the user asks to change or forget memories:",
74
+ "1. Call correction_plan to generate a diff preview.",
75
+ "2. Present the diff to the user and ask them to reply 'apply' to confirm.",
76
+ "3. Only after explicit confirmation, call correction_apply.",
77
+ "",
78
+ "For bulk/destructive requests ('forget everything about X'), always go",
79
+ "through correction_plan first \u2014 there is no direct-delete tool."
80
+ );
81
+ } else {
82
+ lines.push(
83
+ "",
84
+ "## Mutation status",
85
+ "",
86
+ "Correction (mutation) tools are not yet available in this build.",
87
+ "You can inspect and search memories but cannot apply corrections.",
88
+ "When the user asks to change memories, explain that correction tools",
89
+ "require the Correction Contract (#1580) which is pending."
90
+ );
91
+ }
92
+ return lines.join("\n");
93
+ }
94
+
95
+ // src/chat/chat-tools.ts
96
+ var MUTATING_TOOLS = /* @__PURE__ */ new Set([
97
+ "correction_apply",
98
+ "memory_promote"
99
+ ]);
100
+ var MEMORY_SEARCH_SCHEMA = {
101
+ type: "function",
102
+ function: {
103
+ name: "memory_search",
104
+ description: "Semantic search across stored memories. Returns matching memory paths, scores, and snippets. Use this to find what Remnic remembers about a topic.",
105
+ parameters: {
106
+ type: "object",
107
+ properties: {
108
+ query: { type: "string", description: "The search query." },
109
+ maxResults: { type: "number", description: "Maximum results (default 8)." }
110
+ },
111
+ required: ["query"],
112
+ additionalProperties: false
113
+ }
114
+ }
115
+ };
116
+ var MEMORY_GET_SCHEMA = {
117
+ type: "function",
118
+ function: {
119
+ name: "memory_get",
120
+ description: "Fetch a single memory by its id. Returns the full memory content, category, tags, and source attribution.",
121
+ parameters: {
122
+ type: "object",
123
+ properties: {
124
+ memoryId: { type: "string", description: "The memory id to fetch." }
125
+ },
126
+ required: ["memoryId"],
127
+ additionalProperties: false
128
+ }
129
+ }
130
+ };
131
+ var MEMORY_TIMELINE_SCHEMA = {
132
+ type: "function",
133
+ function: {
134
+ name: "memory_timeline",
135
+ description: "Read the lifecycle timeline of a single memory \u2014 creation, updates, consolidations, and tier transitions.",
136
+ parameters: {
137
+ type: "object",
138
+ properties: {
139
+ memoryId: { type: "string", description: "The memory id." },
140
+ limit: { type: "number", description: "Maximum rows (default 200)." }
141
+ },
142
+ required: ["memoryId"],
143
+ additionalProperties: false
144
+ }
145
+ }
146
+ };
147
+ var RECALL_EXPLAIN_SCHEMA = {
148
+ type: "function",
149
+ function: {
150
+ name: "recall_explain",
151
+ description: "Explain why Remnic would recall certain memories for a given query. Returns tier scoring and matching details. Use this to answer 'why did you remember this?'",
152
+ parameters: {
153
+ type: "object",
154
+ properties: {
155
+ query: { type: "string", description: "Optional query to explain recall for. When omitted, explains the most recent recall." }
156
+ },
157
+ required: [],
158
+ additionalProperties: false
159
+ }
160
+ }
161
+ };
162
+ var ENTITY_GET_SCHEMA = {
163
+ type: "function",
164
+ function: {
165
+ name: "entity_get",
166
+ description: "Fetch the compiled entity record for a named entity (person, project, tool, etc.). Returns traits, timeline, and associated memories.",
167
+ parameters: {
168
+ type: "object",
169
+ properties: {
170
+ name: { type: "string", description: "Entity name." }
171
+ },
172
+ required: ["name"],
173
+ additionalProperties: false
174
+ }
175
+ }
176
+ };
177
+ var STATS_SCHEMA = {
178
+ type: "function",
179
+ function: {
180
+ name: "stats",
181
+ description: "Return aggregate memory statistics \u2014 memory count, entity count, profile summary, and open questions. Use this for high-level 'what do you know?' questions.",
182
+ parameters: {
183
+ type: "object",
184
+ properties: {},
185
+ additionalProperties: false
186
+ }
187
+ }
188
+ };
189
+ var CORRECTION_PLAN_SCHEMA = {
190
+ type: "function",
191
+ function: {
192
+ name: "correction_plan",
193
+ description: "Generate a correction plan (diff preview) for a requested memory change. This does NOT apply the change \u2014 it previews what would happen. The user must confirm before correction_apply runs.",
194
+ parameters: {
195
+ type: "object",
196
+ properties: {
197
+ request: {
198
+ type: "string",
199
+ description: "Natural-language description of the correction, e.g. 'we finished the MySQL migration in March' or 'forget the outdated database credentials'."
200
+ }
201
+ },
202
+ required: ["request"],
203
+ additionalProperties: false
204
+ }
205
+ }
206
+ };
207
+ var CORRECTION_APPLY_SCHEMA = {
208
+ type: "function",
209
+ function: {
210
+ name: "correction_apply",
211
+ description: "Apply a previously generated correction plan. The engine intercepts this call and requires explicit user confirmation before it executes.",
212
+ parameters: {
213
+ type: "object",
214
+ properties: {
215
+ planId: { type: "string", description: "The plan id from correction_plan." }
216
+ },
217
+ required: ["planId"],
218
+ additionalProperties: false
219
+ }
220
+ }
221
+ };
222
+ var MEMORY_PROMOTE_SCHEMA = {
223
+ type: "function",
224
+ function: {
225
+ name: "memory_promote",
226
+ description: "Promote a memory's tier (e.g. from cold to hot). The engine requires user confirmation before executing.",
227
+ parameters: {
228
+ type: "object",
229
+ properties: {
230
+ memoryId: { type: "string", description: "The memory id to promote." }
231
+ },
232
+ required: ["memoryId"],
233
+ additionalProperties: false
234
+ }
235
+ }
236
+ };
237
+ var REVIEW_LIST_SCHEMA = {
238
+ type: "function",
239
+ function: {
240
+ name: "review_list",
241
+ description: "List items in the contradiction/quality review queue. Returns pairs of potentially conflicting memories awaiting resolution.",
242
+ parameters: {
243
+ type: "object",
244
+ properties: {
245
+ runId: { type: "string", description: "Optional governance run id." }
246
+ },
247
+ additionalProperties: false
248
+ }
249
+ }
250
+ };
251
+ var SCOPE_INSPECT_SCHEMA = {
252
+ type: "function",
253
+ function: {
254
+ name: "scope_inspect",
255
+ description: "Inspect the current scope/namespace resolution \u2014 which namespace the chat session operates in and how it was resolved.",
256
+ parameters: {
257
+ type: "object",
258
+ properties: {},
259
+ additionalProperties: false
260
+ }
261
+ }
262
+ };
263
+ var READONLY_SCHEMAS = [
264
+ MEMORY_SEARCH_SCHEMA,
265
+ MEMORY_GET_SCHEMA,
266
+ MEMORY_TIMELINE_SCHEMA,
267
+ RECALL_EXPLAIN_SCHEMA,
268
+ ENTITY_GET_SCHEMA,
269
+ STATS_SCHEMA,
270
+ REVIEW_LIST_SCHEMA
271
+ ];
272
+ function buildChatToolSchemas(opts) {
273
+ const tools = [...READONLY_SCHEMAS];
274
+ if (opts.correctionAvailable) {
275
+ tools.push(CORRECTION_PLAN_SCHEMA, CORRECTION_APPLY_SCHEMA, MEMORY_PROMOTE_SCHEMA);
276
+ }
277
+ if (opts.scopeInspectAvailable) {
278
+ tools.push(SCOPE_INSPECT_SCHEMA);
279
+ }
280
+ return tools;
281
+ }
282
+
283
+ // src/chat/chat-engine.ts
284
+ var CONFIRMATION_KEYWORDS = /* @__PURE__ */ new Set(["yes", "y", "apply", "confirm"]);
285
+ function isConfirmationMessage(text) {
286
+ return CONFIRMATION_KEYWORDS.has(text.trim().toLowerCase());
287
+ }
288
+ var ChatEngine = class {
289
+ llm;
290
+ executor;
291
+ maxToolCallsPerTurn;
292
+ model;
293
+ correctionAvailable;
294
+ scopeInspectAvailable;
295
+ systemPrompt;
296
+ toolSchemas;
297
+ allowedToolNames;
298
+ constructor(opts) {
299
+ this.llm = opts.llm;
300
+ this.executor = opts.executor;
301
+ this.maxToolCallsPerTurn = opts.maxToolCallsPerTurn;
302
+ this.model = opts.model;
303
+ this.correctionAvailable = opts.correctionAvailable;
304
+ this.scopeInspectAvailable = opts.scopeInspectAvailable;
305
+ this.systemPrompt = buildChatSystemPrompt({
306
+ correctionAvailable: opts.correctionAvailable
307
+ });
308
+ this.toolSchemas = buildChatToolSchemas({
309
+ correctionAvailable: opts.correctionAvailable,
310
+ scopeInspectAvailable: opts.scopeInspectAvailable
311
+ });
312
+ this.allowedToolNames = new Set(this.toolSchemas.map((t) => t.function.name));
313
+ }
314
+ /**
315
+ * Process a single user message. The session state is mutated in place
316
+ * (confirmedPlanIds, pendingPlanId) — the caller persists the transcript.
317
+ */
318
+ async processMessage(userMessage, session) {
319
+ if (isConfirmationMessage(userMessage) && this.correctionAvailable) {
320
+ if (session.pendingPlanId) {
321
+ const planId = session.pendingPlanId;
322
+ session.confirmedPlanIds.add(planId);
323
+ session.pendingPlanId = void 0;
324
+ try {
325
+ const applyResult = await this.executor.correctionApply(planId);
326
+ session.confirmedPlanIds.delete(planId);
327
+ return {
328
+ reply: `Correction applied.
329
+
330
+ ${applyResult}`,
331
+ chatSessionId: session.id,
332
+ ...session.pendingPromotionId ? {} : {}
333
+ };
334
+ } catch (err) {
335
+ session.confirmedPlanIds.delete(planId);
336
+ session.pendingPlanId = planId;
337
+ const msg = err instanceof Error ? err.message : String(err);
338
+ return {
339
+ reply: "[error] Failed to apply the correction. Please try again or re-request the plan.",
340
+ chatSessionId: session.id,
341
+ error: msg
342
+ };
343
+ }
344
+ }
345
+ if (session.pendingPromotionId) {
346
+ const memoryId = session.pendingPromotionId;
347
+ session.pendingPromotionId = void 0;
348
+ try {
349
+ const promoteResult = await this.executor.memoryPromote(memoryId);
350
+ return {
351
+ reply: `Memory promoted.
352
+
353
+ ${promoteResult}`,
354
+ chatSessionId: session.id
355
+ };
356
+ } catch (err) {
357
+ session.pendingPromotionId = memoryId;
358
+ const msg = err instanceof Error ? err.message : String(err);
359
+ return {
360
+ reply: "[error] Failed to promote the memory. Please try again.",
361
+ chatSessionId: session.id,
362
+ error: msg
363
+ };
364
+ }
365
+ }
366
+ }
367
+ const recentEntries = session.transcript.slice(-21).filter((e) => e.role !== "system" || e.seq !== 0).filter((e) => !(e.role === "system" && /^[a-z_]+:/.test(e.content))).filter((e, _i, arr) => {
368
+ if (e.role === "user" && e.content === userMessage) {
369
+ const lastUser = [...arr].reverse().find((x) => x.role === "user");
370
+ return e !== lastUser;
371
+ }
372
+ return true;
373
+ });
374
+ const conversation = [
375
+ { role: "system", content: this.systemPrompt },
376
+ ...recentEntries.map((e) => ({
377
+ role: e.role,
378
+ content: e.content,
379
+ ...e.toolCallId ? { toolCallId: e.toolCallId } : {}
380
+ })),
381
+ { role: "user", content: userMessage }
382
+ ];
383
+ let toolCallCount = 0;
384
+ const skippedTools = [];
385
+ let pendingPlan;
386
+ for (; ; ) {
387
+ let response;
388
+ try {
389
+ response = await this.llm.complete(conversation, {
390
+ tools: this.toolSchemas,
391
+ ...this.model ? { model: this.model } : {}
392
+ });
393
+ } catch (err) {
394
+ const msg = err instanceof Error ? err.message : String(err);
395
+ return {
396
+ reply: "[error] The model request failed. Check your model configuration and retry.",
397
+ chatSessionId: session.id,
398
+ error: msg
399
+ };
400
+ }
401
+ if (!response) {
402
+ return {
403
+ reply: "[error] No LLM model is available. Configure a local or cloud model to use Remnic Chat.",
404
+ chatSessionId: session.id,
405
+ error: "no_llm_available"
406
+ };
407
+ }
408
+ if (response.toolCalls.length === 0) {
409
+ let reply = response.content;
410
+ if (toolCallCount === 0 && looksLikeMemoryAssertion(reply)) {
411
+ reply += "\n\n\u26A0\uFE0F The above assertion was not grounded in a tool result this turn. Please verify with memory_search or memory_get.";
412
+ }
413
+ return {
414
+ reply,
415
+ chatSessionId: session.id,
416
+ ...pendingPlan ? { pendingPlan } : {},
417
+ ...skippedTools.length > 0 ? { skippedTools } : {}
418
+ };
419
+ }
420
+ conversation.push({ role: "assistant", content: response.content });
421
+ for (const tc of response.toolCalls) {
422
+ if (toolCallCount >= this.maxToolCallsPerTurn) {
423
+ skippedTools.push(tc.name);
424
+ continue;
425
+ }
426
+ toolCallCount++;
427
+ if (!this.allowedToolNames.has(tc.name)) {
428
+ conversation.push({
429
+ role: "tool",
430
+ content: JSON.stringify({ error: `Tool '${tc.name}' is not available in this configuration.` }),
431
+ toolCallId: tc.id
432
+ });
433
+ continue;
434
+ }
435
+ if (MUTATING_TOOLS.has(tc.name)) {
436
+ if (tc.name === "correction_apply") {
437
+ const planId = typeof tc.arguments.planId === "string" ? tc.arguments.planId : "";
438
+ if (!session.confirmedPlanIds.has(planId)) {
439
+ try {
440
+ const plan = await this.executor.correctionPlan(
441
+ `retrieve plan ${planId}`
442
+ );
443
+ pendingPlan = { planId, preview: plan.preview };
444
+ session.pendingPlanId = planId;
445
+ conversation.push({
446
+ role: "tool",
447
+ content: JSON.stringify({
448
+ intercepted: true,
449
+ message: "This mutation requires confirmation. The plan preview has been shown to the user."
450
+ }),
451
+ toolCallId: tc.id
452
+ });
453
+ return {
454
+ reply: formatPlanPreview(plan.preview),
455
+ chatSessionId: session.id,
456
+ pendingPlan
457
+ };
458
+ } catch {
459
+ conversation.push({
460
+ role: "tool",
461
+ content: JSON.stringify({ error: "Plan not found or expired." }),
462
+ toolCallId: tc.id
463
+ });
464
+ continue;
465
+ }
466
+ }
467
+ session.confirmedPlanIds.delete(planId);
468
+ }
469
+ }
470
+ if (tc.name === "memory_promote" && this.correctionAvailable) {
471
+ const memoryId = typeof tc.arguments.memoryId === "string" ? tc.arguments.memoryId : "";
472
+ session.pendingPromotionId = memoryId;
473
+ conversation.push({
474
+ role: "tool",
475
+ content: JSON.stringify({
476
+ intercepted: true,
477
+ message: `Memory promotion requires confirmation. Reply 'apply' to promote memory '${memoryId}'.`
478
+ }),
479
+ toolCallId: tc.id
480
+ });
481
+ return {
482
+ reply: `I want to promote memory \`${memoryId}\`. Reply **apply** to confirm this promotion, or **cancel** to discard it.`,
483
+ chatSessionId: session.id
484
+ };
485
+ }
486
+ let result;
487
+ try {
488
+ result = await this.executeTool(tc.name, tc.arguments, session);
489
+ } catch (err) {
490
+ const msg = err instanceof Error ? err.message : String(err);
491
+ result = { content: JSON.stringify({ error: msg }) };
492
+ }
493
+ conversation.push({
494
+ role: "tool",
495
+ content: result.content,
496
+ toolCallId: tc.id
497
+ });
498
+ if (tc.name === "correction_plan" && this.correctionAvailable) {
499
+ try {
500
+ const parsed = JSON.parse(result.content);
501
+ if (parsed.planId && parsed.preview) {
502
+ pendingPlan = { planId: parsed.planId, preview: parsed.preview };
503
+ session.pendingPlanId = parsed.planId;
504
+ }
505
+ } catch {
506
+ }
507
+ }
508
+ }
509
+ if (skippedTools.length > 0) {
510
+ conversation.push({
511
+ role: "user",
512
+ content: `[system] Tool budget exhausted (${this.maxToolCallsPerTurn} calls). ${skippedTools.length} tool(s) were skipped: ${skippedTools.join(", ")}. Please summarize what you found.`
513
+ });
514
+ let summaryResponse;
515
+ try {
516
+ summaryResponse = await this.llm.complete(conversation, {
517
+ tools: [],
518
+ // No more tools — force a text reply.
519
+ ...this.model ? { model: this.model } : {}
520
+ });
521
+ } catch {
522
+ summaryResponse = null;
523
+ }
524
+ const summaryText = summaryResponse?.content ?? "I reached my tool-call budget. Here is what I found so far, but some queries were skipped.";
525
+ return {
526
+ reply: summaryText,
527
+ chatSessionId: session.id,
528
+ ...pendingPlan ? { pendingPlan } : {},
529
+ skippedTools
530
+ };
531
+ }
532
+ }
533
+ }
534
+ /**
535
+ * Execute a single tool by name, delegating to the executor.
536
+ */
537
+ async executeTool(name, args, _session) {
538
+ switch (name) {
539
+ case "memory_search": {
540
+ const query = typeof args.query === "string" ? args.query : "";
541
+ const maxResults = typeof args.maxResults === "number" ? args.maxResults : void 0;
542
+ return { content: await this.executor.memorySearch(query, maxResults) };
543
+ }
544
+ case "memory_get": {
545
+ const memoryId = typeof args.memoryId === "string" ? args.memoryId : "";
546
+ return { content: await this.executor.memoryGet(memoryId) };
547
+ }
548
+ case "memory_timeline": {
549
+ const memoryId = typeof args.memoryId === "string" ? args.memoryId : "";
550
+ const limit = typeof args.limit === "number" ? args.limit : void 0;
551
+ return { content: await this.executor.memoryTimeline(memoryId, limit) };
552
+ }
553
+ case "recall_explain": {
554
+ const query = typeof args.query === "string" ? args.query : "";
555
+ return { content: await this.executor.recallExplain(query) };
556
+ }
557
+ case "entity_get": {
558
+ const entityName = typeof args.name === "string" ? args.name : "";
559
+ return { content: await this.executor.entityGet(entityName) };
560
+ }
561
+ case "stats": {
562
+ return { content: await this.executor.stats() };
563
+ }
564
+ case "correction_plan": {
565
+ const request = typeof args.request === "string" ? args.request : "";
566
+ const plan = await this.executor.correctionPlan(request);
567
+ return { content: JSON.stringify(plan) };
568
+ }
569
+ case "correction_apply": {
570
+ const planId = typeof args.planId === "string" ? args.planId : "";
571
+ return { content: await this.executor.correctionApply(planId) };
572
+ }
573
+ case "memory_promote": {
574
+ const memoryId = typeof args.memoryId === "string" ? args.memoryId : "";
575
+ return { content: await this.executor.memoryPromote(memoryId) };
576
+ }
577
+ case "review_list": {
578
+ const runId = typeof args.runId === "string" ? args.runId : void 0;
579
+ return { content: await this.executor.reviewList(runId) };
580
+ }
581
+ case "scope_inspect": {
582
+ return { content: await this.executor.scopeInspect() };
583
+ }
584
+ default:
585
+ return { content: JSON.stringify({ error: `Unknown tool: ${name}` }) };
586
+ }
587
+ }
588
+ };
589
+ function looksLikeMemoryAssertion(text) {
590
+ const lower = text.toLowerCase();
591
+ const assertionPhrases = [
592
+ "you remember",
593
+ "i remember",
594
+ "according to my memory",
595
+ "your memory",
596
+ "stored memory",
597
+ "remnic remembers",
598
+ "remnic knows"
599
+ ];
600
+ const hasAssertion = assertionPhrases.some((p) => lower.includes(p));
601
+ const hasCitation = lower.includes("[id:") || lower.includes("memory id") || lower.includes("source:");
602
+ return hasAssertion && !hasCitation;
603
+ }
604
+ function formatPlanPreview(preview) {
605
+ return [
606
+ "Here is the correction plan I generated:",
607
+ "",
608
+ "```diff",
609
+ preview,
610
+ "```",
611
+ "",
612
+ "Reply **apply** to confirm and apply this correction.",
613
+ "Reply **cancel** to discard it."
614
+ ].join("\n");
615
+ }
616
+
617
+ // src/chat/chat-llm.ts
618
+ function createProductionChatLlmAdapter(client) {
619
+ return {
620
+ async complete(messages, options) {
621
+ const toolInstruction = formatToolInstruction(options.tools);
622
+ const mapped = messages.map((m) => {
623
+ if (m.role === "system") {
624
+ return { role: m.role, content: m.content + "\n\n" + toolInstruction };
625
+ }
626
+ if (m.role === "tool") {
627
+ const tag = m.toolCallId ? `[tool:${m.toolCallId}]` : "[tool]";
628
+ return { role: "user", content: `${tag} ${m.content}` };
629
+ }
630
+ return { role: m.role, content: m.content };
631
+ });
632
+ const result = await client.chatCompletion(mapped, {
633
+ ...options.model ? { model: options.model } : {},
634
+ ...options.signal ? { signal: options.signal } : {}
635
+ });
636
+ if (!result) return null;
637
+ const toolCalls = parseToolCalls(result.content);
638
+ return {
639
+ content: stripToolCallJson(result.content, toolCalls),
640
+ toolCalls
641
+ };
642
+ }
643
+ };
644
+ }
645
+ function formatToolInstruction(tools) {
646
+ if (tools.length === 0) return "";
647
+ const lines = [
648
+ "## Available tools",
649
+ "",
650
+ "You may call the following tools by emitting a JSON block on its own line:",
651
+ "```json",
652
+ '{"tool": "<name>", "arguments": { ... }}',
653
+ "```",
654
+ "",
655
+ "Call one tool at a time. After receiving the tool result, continue your",
656
+ "reasoning or emit another tool call. When you have a final answer, reply",
657
+ "with text only (no tool-call JSON).",
658
+ "",
659
+ "Tools:"
660
+ ];
661
+ for (const t of tools) {
662
+ const params = JSON.stringify(t.function.parameters);
663
+ lines.push(`- ${t.function.name}: ${t.function.description}`);
664
+ lines.push(` Parameters: ${params}`);
665
+ }
666
+ return lines.join("\n");
667
+ }
668
+ function parseToolCalls(content) {
669
+ const calls = [];
670
+ const patterns = [
671
+ /```json\s*\n([\s\S]*?)\n```/g,
672
+ /```\s*\n([\s\S]*?)\n```/g
673
+ ];
674
+ const candidates = [];
675
+ for (const pattern of patterns) {
676
+ let match;
677
+ while ((match = pattern.exec(content)) !== null) {
678
+ candidates.push(match[1]);
679
+ }
680
+ }
681
+ for (const line of content.split("\n")) {
682
+ const trimmed = line.trim();
683
+ if (trimmed.startsWith("{") && trimmed.includes('"tool"')) {
684
+ candidates.push(trimmed);
685
+ }
686
+ }
687
+ const seen = /* @__PURE__ */ new Set();
688
+ for (const candidate of candidates) {
689
+ try {
690
+ const parsed = JSON.parse(candidate);
691
+ if (typeof parsed.tool === "string" && parsed.tool.length > 0) {
692
+ const args = parsed.arguments ?? {};
693
+ const key = parsed.tool + ":" + JSON.stringify(args);
694
+ if (seen.has(key)) continue;
695
+ seen.add(key);
696
+ calls.push({
697
+ id: `call_${calls.length + 1}`,
698
+ name: parsed.tool,
699
+ arguments: args
700
+ });
701
+ }
702
+ } catch {
703
+ }
704
+ }
705
+ return calls;
706
+ }
707
+ function stripToolCallJson(content, toolCalls) {
708
+ if (toolCalls.length === 0) return content;
709
+ let result = content;
710
+ result = result.replace(/```json\s*\n[\s\S]*?\n```/g, "");
711
+ result = result.replace(/```\s*\n[\s\S]*?\n```/g, "");
712
+ result = result.split("\n").filter((line) => {
713
+ const trimmed = line.trim();
714
+ return !(trimmed.startsWith("{") && trimmed.includes('"tool"'));
715
+ }).join("\n");
716
+ return result.trim();
717
+ }
718
+
719
+ // src/chat/chat-executor.ts
720
+ function createChatExecutor(bindings) {
721
+ const { service, principal, namespace, sessionKey } = bindings;
722
+ return {
723
+ async memorySearch(query, maxResults) {
724
+ const result = await service.memorySearch({
725
+ query,
726
+ ...namespace ? { namespace } : {},
727
+ ...maxResults !== void 0 ? { maxResults } : {},
728
+ ...principal ? { principal } : {}
729
+ });
730
+ return JSON.stringify(result);
731
+ },
732
+ async memoryGet(memoryId) {
733
+ const result = await service.memoryGet(memoryId, namespace, principal, sessionKey);
734
+ return JSON.stringify(result);
735
+ },
736
+ async memoryTimeline(memoryId, limit) {
737
+ const result = await service.memoryTimeline(memoryId, namespace, limit ?? 200, principal);
738
+ return JSON.stringify(result);
739
+ },
740
+ async recallExplain(query) {
741
+ const result = await service.recallExplain({
742
+ ...sessionKey ? { sessionKey } : {},
743
+ ...namespace ? { namespace } : {},
744
+ ...principal ? { authenticatedPrincipal: principal } : {},
745
+ ...query ? { query } : {}
746
+ });
747
+ return JSON.stringify(result);
748
+ },
749
+ async entityGet(name) {
750
+ const result = await service.entityGet(name, namespace);
751
+ return JSON.stringify(result);
752
+ },
753
+ async stats() {
754
+ const [profile, entities, questions] = await Promise.all([
755
+ service.memoryProfile(namespace, principal),
756
+ service.memoryEntitiesList(namespace, principal),
757
+ service.memoryQuestions(namespace, principal)
758
+ ]);
759
+ return JSON.stringify({ profile, entities, questions });
760
+ },
761
+ async reviewList(runId) {
762
+ const result = await service.reviewQueue(runId, namespace, principal);
763
+ return JSON.stringify(result);
764
+ },
765
+ async scopeInspect() {
766
+ return JSON.stringify({
767
+ namespace: namespace ?? "default",
768
+ principal: principal ?? "default",
769
+ sessionKey: sessionKey ?? void 0
770
+ });
771
+ },
772
+ // ── Correction tools — stubbed until #1580 merges ──────────────────
773
+ // When the Correction Contract lands, replace these stubs with calls to
774
+ // the correction module's plan/apply interface. The engine, CLI, and
775
+ // MCP tool all consume this interface, so the stub-to-real swap is a
776
+ // single-file change here.
777
+ async correctionPlan(request) {
778
+ return {
779
+ planId: `stub-${Date.now()}`,
780
+ preview: `[Correction Contract (#1580) not yet available]
781
+
782
+ Requested correction: "${request}"
783
+
784
+ The plan/apply pipeline is pending. Inspection tools are fully functional.`
785
+ };
786
+ },
787
+ async correctionApply(planId) {
788
+ return JSON.stringify({
789
+ applied: false,
790
+ planId,
791
+ reason: "Correction Contract (#1580) not yet available. No mutation was applied."
792
+ });
793
+ },
794
+ async memoryPromote(memoryId) {
795
+ try {
796
+ const serviceWithPromote = service;
797
+ if (typeof serviceWithPromote.memoryPromote === "function") {
798
+ const result = await serviceWithPromote.memoryPromote(memoryId, namespace, principal);
799
+ return JSON.stringify(result);
800
+ }
801
+ } catch {
802
+ }
803
+ return JSON.stringify({
804
+ promoted: false,
805
+ memoryId,
806
+ reason: "Memory promotion is not available in this build."
807
+ });
808
+ }
809
+ };
810
+ }
811
+
812
+ // src/chat/chat-session.ts
813
+ import { mkdir, readFile, appendFile, readdir, stat, unlink } from "fs/promises";
814
+ import { join } from "path";
39
815
  import { randomUUID } from "crypto";
816
+ var CHAT_DIR_NAME = "state/chat";
817
+ function chatSessionDir(memoryDir) {
818
+ return join(memoryDir, CHAT_DIR_NAME);
819
+ }
820
+ function isSafeChatSessionId(chatSessionId) {
821
+ return /^[A-Za-z0-9]{8,128}$/.test(chatSessionId.replace(/-/g, ""));
822
+ }
823
+ function chatSessionFile(memoryDir, chatSessionId) {
824
+ if (!isSafeChatSessionId(chatSessionId)) {
825
+ throw new Error("Invalid chat session id");
826
+ }
827
+ return join(chatSessionDir(memoryDir), `${chatSessionId}.jsonl`);
828
+ }
829
+ async function createChatSession(memoryDir, opts) {
830
+ const id = randomUUID();
831
+ const now = (/* @__PURE__ */ new Date()).toISOString();
832
+ const state = {
833
+ id,
834
+ principal: opts.principal,
835
+ sessionKey: opts.sessionKey,
836
+ namespace: opts.namespace,
837
+ transcript: [],
838
+ confirmedPlanIds: /* @__PURE__ */ new Set(),
839
+ createdAt: now
840
+ };
841
+ await mkdir(chatSessionDir(memoryDir), { recursive: true });
842
+ await appendFile(
843
+ chatSessionFile(memoryDir, id),
844
+ JSON.stringify({
845
+ seq: 0,
846
+ ts: now,
847
+ role: "system",
848
+ content: `Chat session created. Principal: ${opts.principal ?? "default"}. Namespace: ${opts.namespace ?? "default"}. work_task: Excluded from memory extraction`,
849
+ // Structured binding fields so loadChatSession doesn't need to regex-parse
850
+ // prose (robust against dotted principals like alice@example.com).
851
+ ...opts.principal ? { principal: opts.principal } : {},
852
+ ...opts.namespace ? { namespace: opts.namespace } : {},
853
+ ...opts.sessionKey ? { sessionKey: opts.sessionKey } : {}
854
+ }) + "\n",
855
+ "utf8"
856
+ );
857
+ return state;
858
+ }
859
+ async function loadChatSession(memoryDir, chatSessionId) {
860
+ let raw;
861
+ try {
862
+ raw = await readFile(chatSessionFile(memoryDir, chatSessionId), "utf8");
863
+ } catch {
864
+ return null;
865
+ }
866
+ const lines = raw.split("\n").filter((l) => l.trim().length > 0);
867
+ const transcript = [];
868
+ let principal;
869
+ let sessionKey;
870
+ let namespace;
871
+ let createdAt = "";
872
+ let pendingPlanId;
873
+ let pendingPromotionId;
874
+ for (const line of lines) {
875
+ try {
876
+ const entry = JSON.parse(line);
877
+ transcript.push(entry);
878
+ if (entry.role === "system" && entry.seq === 0) {
879
+ const metaPrincipal = typeof entry.principal === "string" ? entry.principal : void 0;
880
+ const metaNamespace = typeof entry.namespace === "string" ? entry.namespace : void 0;
881
+ const metaSessionKey = typeof entry.sessionKey === "string" ? entry.sessionKey : void 0;
882
+ if (metaPrincipal) principal = metaPrincipal;
883
+ else {
884
+ const pMatch = entry.content.match(/Principal: (.+?)\.\s/);
885
+ if (pMatch) principal = pMatch[1]?.trim() === "default" ? void 0 : pMatch[1]?.trim();
886
+ }
887
+ if (metaNamespace) namespace = metaNamespace;
888
+ else {
889
+ const nsMatch = entry.content.match(/Namespace: (.+?)\.\s/);
890
+ if (nsMatch) namespace = nsMatch[1]?.trim() === "default" ? void 0 : nsMatch[1]?.trim();
891
+ }
892
+ if (metaSessionKey) sessionKey = metaSessionKey;
893
+ createdAt = entry.ts;
894
+ }
895
+ if (entry.role === "system") {
896
+ const pm = entry.content.match(/^pending_plan:(.+)$/);
897
+ if (pm) pendingPlanId = pm[1];
898
+ const pp = entry.content.match(/^pending_promotion:(.+)$/);
899
+ if (pp) pendingPromotionId = pp[1];
900
+ const resolved = entry.content.match(/^(plan_applied|plan_cancelled|promotion_applied|promotion_cancelled):/);
901
+ if (resolved) {
902
+ if (entry.content.startsWith("plan_")) {
903
+ pendingPlanId = void 0;
904
+ }
905
+ if (entry.content.startsWith("promotion_")) {
906
+ pendingPromotionId = void 0;
907
+ }
908
+ }
909
+ }
910
+ } catch {
911
+ }
912
+ }
913
+ return {
914
+ id: chatSessionId,
915
+ principal,
916
+ sessionKey,
917
+ namespace,
918
+ transcript,
919
+ confirmedPlanIds: /* @__PURE__ */ new Set(),
920
+ ...pendingPlanId ? { pendingPlanId } : {},
921
+ ...pendingPromotionId ? { pendingPromotionId } : {},
922
+ createdAt
923
+ };
924
+ }
925
+ async function appendTranscriptEntry(memoryDir, chatSessionId, entry) {
926
+ const full = {
927
+ ...entry,
928
+ seq: Date.now(),
929
+ ts: (/* @__PURE__ */ new Date()).toISOString()
930
+ };
931
+ await appendFile(
932
+ chatSessionFile(memoryDir, chatSessionId),
933
+ JSON.stringify(full) + "\n",
934
+ "utf8"
935
+ );
936
+ return full;
937
+ }
938
+ async function markPendingPlan(memoryDir, chatSessionId, planId) {
939
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
940
+ role: "system",
941
+ content: `pending_plan:${planId}`
942
+ });
943
+ }
944
+ async function markPendingPromotion(memoryDir, chatSessionId, memoryId) {
945
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
946
+ role: "system",
947
+ content: `pending_promotion:${memoryId}`
948
+ });
949
+ }
950
+ async function markPlanResolved(memoryDir, chatSessionId, planId) {
951
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
952
+ role: "system",
953
+ content: `plan_applied:${planId}`
954
+ });
955
+ }
956
+ async function markPromotionResolved(memoryDir, chatSessionId, memoryId) {
957
+ await appendTranscriptEntry(memoryDir, chatSessionId, {
958
+ role: "system",
959
+ content: `promotion_applied:${memoryId}`
960
+ });
961
+ }
962
+ function sessionBelongsToPrincipal(session, principal) {
963
+ if (!session.principal) return true;
964
+ return session.principal === principal;
965
+ }
966
+
967
+ // src/chat/chat-factory.ts
968
+ function createChatEngine(opts) {
969
+ const llmClient = opts.fallbackLlm ?? opts.localLlm;
970
+ if (!llmClient) return null;
971
+ const adapter = createProductionChatLlmAdapter(llmClient);
972
+ const executor = createChatExecutor({
973
+ service: opts.service,
974
+ principal: opts.principal,
975
+ namespace: opts.namespace,
976
+ sessionKey: opts.sessionKey
977
+ });
978
+ return new ChatEngine({
979
+ llm: adapter,
980
+ executor,
981
+ maxToolCallsPerTurn: opts.config.maxToolCallsPerTurn,
982
+ ...opts.config.model ? { model: opts.config.model } : {},
983
+ correctionAvailable: false,
984
+ scopeInspectAvailable: false
985
+ });
986
+ }
987
+ async function processChatMessage(opts) {
988
+ if (!opts.config?.enabled) {
989
+ throw new Error("chat_disabled");
990
+ }
991
+ if (!opts.service.fallbackLlmRef && !opts.service.localLlmRef) {
992
+ throw new Error("no_llm_available");
993
+ }
994
+ let session;
995
+ if (opts.chatSessionId) {
996
+ session = await loadChatSession(opts.memoryDir, opts.chatSessionId);
997
+ if (!session) throw new Error("chat_session_not_found");
998
+ if (!sessionBelongsToPrincipal(session, opts.principal)) {
999
+ throw new Error("access_denied");
1000
+ }
1001
+ } else {
1002
+ session = await createChatSession(opts.memoryDir, {
1003
+ principal: opts.principal,
1004
+ ...opts.namespace ? { namespace: opts.namespace } : {},
1005
+ ...opts.sessionKey ? { sessionKey: opts.sessionKey } : {}
1006
+ });
1007
+ }
1008
+ const engine = createChatEngine({
1009
+ service: opts.service,
1010
+ config: opts.config,
1011
+ fallbackLlm: opts.service.fallbackLlmRef,
1012
+ localLlm: opts.service.localLlmRef,
1013
+ principal: opts.principal,
1014
+ ...session.namespace ? { namespace: session.namespace } : {},
1015
+ ...session.sessionKey ? { sessionKey: session.sessionKey } : {}
1016
+ });
1017
+ if (!engine) {
1018
+ throw new Error("engine_unavailable");
1019
+ }
1020
+ await appendTranscriptEntry(opts.memoryDir, session.id, {
1021
+ role: "user",
1022
+ content: opts.message
1023
+ });
1024
+ const priorPendingPlanId = session.pendingPlanId;
1025
+ const priorPendingPromotionId = session.pendingPromotionId;
1026
+ const result = await engine.processMessage(opts.message, session);
1027
+ await appendTranscriptEntry(opts.memoryDir, session.id, {
1028
+ role: "assistant",
1029
+ content: result.reply
1030
+ });
1031
+ if (result.pendingPlan?.planId) {
1032
+ await markPendingPlan(opts.memoryDir, session.id, result.pendingPlan.planId);
1033
+ } else if (session.pendingPromotionId && !priorPendingPromotionId) {
1034
+ await markPendingPromotion(opts.memoryDir, session.id, session.pendingPromotionId);
1035
+ } else if (priorPendingPlanId && !session.pendingPlanId) {
1036
+ await markPlanResolved(opts.memoryDir, session.id, priorPendingPlanId);
1037
+ } else if (priorPendingPromotionId && !session.pendingPromotionId) {
1038
+ await markPromotionResolved(opts.memoryDir, session.id, priorPendingPromotionId);
1039
+ }
1040
+ return result;
1041
+ }
1042
+
1043
+ // src/access-mcp.ts
40
1044
  var MCP_PROTOCOL_VERSION = "2024-11-05";
41
1045
  var LEGACY_MCP_PREFIX = "engram.";
42
1046
  var CANONICAL_MCP_PREFIX = "remnic.";
@@ -81,7 +1085,7 @@ var MCP_MIGRATED_OPERATIONS = {
81
1085
  function resolveChatGptInspectorRecallSessionKey(explicitSessionKey, authenticatedPrincipal) {
82
1086
  if (explicitSessionKey) return explicitSessionKey;
83
1087
  if (!authenticatedPrincipal) return void 0;
84
- return `remnic:chatgpt-memory-inspector:${randomUUID()}`;
1088
+ return `remnic:chatgpt-memory-inspector:${randomUUID2()}`;
85
1089
  }
86
1090
  var STRICT_MCP_SCHEMA_KEYS = {
87
1091
  daySummary: [
@@ -202,7 +1206,7 @@ async function getMcpServerVersion() {
202
1206
  if (envVersion) return envVersion;
203
1207
  try {
204
1208
  const pkgPath = new URL("../package.json", import.meta.url);
205
- const raw = await readFile(pkgPath, "utf-8");
1209
+ const raw = await readFile2(pkgPath, "utf-8");
206
1210
  const parsed = JSON.parse(raw);
207
1211
  return parsed.version?.trim() || "unknown";
208
1212
  } catch {
@@ -220,6 +1224,7 @@ var EngramMcpServer = class {
220
1224
  this.codegraphVisible = options.codegraphVisible === true;
221
1225
  this.sessionDeltaVisible = options.sessionDeltaVisible === true;
222
1226
  this.correctionVisible = options.correctionVisible !== false;
1227
+ this.chatVisible = options.chatVisible === true;
223
1228
  this.authenticatedPrincipal = options.principal?.trim() || readEnvVar("OPENCLAW_ENGRAM_ACCESS_PRINCIPAL")?.trim() || void 0;
224
1229
  this.resources = [
225
1230
  {
@@ -806,7 +1811,12 @@ var EngramMcpServer = class {
806
1811
  type: "object",
807
1812
  properties: {
808
1813
  memoryId: { type: "string" },
809
- namespace: { type: "string" }
1814
+ namespace: { type: "string" },
1815
+ // Issue #1582 — when memoryId is a `[m:xxxx]` handle, sessionKey
1816
+ // scopes resolution to this session's recent recall history.
1817
+ // Advertising it here lets the transport inject its session key
1818
+ // (toolAcceptsArgument) so MCP callers can cite handles (codex review).
1819
+ sessionKey: { type: "string" }
810
1820
  },
811
1821
  required: ["memoryId"],
812
1822
  additionalProperties: false
@@ -960,6 +1970,10 @@ var EngramMcpServer = class {
960
1970
  },
961
1971
  description: "Conversation messages to observe"
962
1972
  },
1973
+ idempotencyKey: {
1974
+ type: "string",
1975
+ description: "Optional idempotency key (issue #1649). Deduplicates a retried observe POST server-side so the batch is ingested once even when the HTTP response is lost. Reusing the key with a different payload is rejected."
1976
+ },
963
1977
  namespace: { type: "string" },
964
1978
  skipExtraction: { type: "boolean" },
965
1979
  cwd: { type: "string", description: "Working directory for auto git-context resolution." },
@@ -1988,6 +3002,25 @@ var EngramMcpServer = class {
1988
3002
  );
1989
3003
  this.tools = [...this.tools, ...planTool, ...applyTool];
1990
3004
  }
3005
+ if (this.chatVisible) {
3006
+ const chatTools = withToolAliases(
3007
+ {
3008
+ name: "engram.memory_chat",
3009
+ description: "Conversational memory inspection and correction (issue #1583). Send a message to chat about what Remnic remembers, inspect memories, or request corrections. Returns {reply, chatSessionId, pendingPlan?}.",
3010
+ inputSchema: {
3011
+ type: "object",
3012
+ properties: {
3013
+ message: { type: "string", description: "The user's message \u2014 a question about memories, a correction request, or a confirmation (yes/apply) to proceed with a pending plan." },
3014
+ chatSessionId: { type: "string", description: "Optional existing chat session id to resume. Omit to start a new session." }
3015
+ },
3016
+ required: ["message"],
3017
+ additionalProperties: false
3018
+ }
3019
+ },
3020
+ this.emitLegacyTools
3021
+ );
3022
+ this.tools = [...this.tools, ...chatTools];
3023
+ }
1991
3024
  }
1992
3025
  service;
1993
3026
  buffer = Buffer.alloc(0);
@@ -2049,6 +3082,12 @@ var EngramMcpServer = class {
2049
3082
  * byte-identical to pre-feature.
2050
3083
  */
2051
3084
  correctionVisible;
3085
+ /**
3086
+ * Whether the `memory_chat` tool should appear in `tools/list` (issue
3087
+ * #1583). Gated on `chat.enabled`. When false the tools array is
3088
+ * byte-identical to pre-feature (rule 39).
3089
+ */
3090
+ chatVisible;
2052
3091
  /** Get clientInfo for a specific MCP session. Returns undefined for non-MCP requests. */
2053
3092
  getClientInfo(sessionId) {
2054
3093
  if (sessionId) {
@@ -2072,7 +3111,7 @@ var EngramMcpServer = class {
2072
3111
  if (method === "initialize") {
2073
3112
  const params = request.params ?? {};
2074
3113
  const rawClientInfo = params.clientInfo;
2075
- const newSessionId = randomUUID();
3114
+ const newSessionId = randomUUID2();
2076
3115
  if (rawClientInfo && typeof rawClientInfo.name === "string") {
2077
3116
  const info = { name: rawClientInfo.name, version: rawClientInfo.version };
2078
3117
  this.clientInfoBySession.set(newSessionId, info);
@@ -2186,7 +3225,11 @@ var EngramMcpServer = class {
2186
3225
  argumentsObject = { ...argumentsObject, sessionKey: options.sessionKeyOverride };
2187
3226
  }
2188
3227
  const effectivePrincipal = options?.principalOverride ?? this.authenticatedPrincipal;
2189
- const result = await this.callTool(name, argumentsObject, effectivePrincipal, options?.sessionId);
3228
+ const mcpScope = {
3229
+ ...options?.namespaceOverride ? { namespace: options.namespaceOverride } : {},
3230
+ ...options?.sessionKeyOverride ? { sessionKey: options.sessionKeyOverride } : {}
3231
+ };
3232
+ const result = await this.callTool(name, argumentsObject, effectivePrincipal, options?.sessionId, mcpScope, options?.enforceWriteQuota);
2190
3233
  return {
2191
3234
  jsonrpc: "2.0",
2192
3235
  id,
@@ -2351,7 +3394,7 @@ ${body}`;
2351
3394
  noteDefault: r.preview?.slice(0, 60) || r.id
2352
3395
  }));
2353
3396
  }
2354
- async callTool(name, args, effectivePrincipal, mcpSessionId) {
3397
+ async callTool(name, args, effectivePrincipal, mcpSessionId, scope, enforceWriteQuota) {
2355
3398
  const migrated = MCP_MIGRATED_OPERATIONS[toLegacyToolName(name)];
2356
3399
  if (migrated) {
2357
3400
  const op = getOperation(migrated);
@@ -2596,7 +3639,7 @@ ${body}`;
2596
3639
  }
2597
3640
  let currentContextScopes;
2598
3641
  if (args.currentContextScopes !== void 0 && args.currentContextScopes !== null) {
2599
- if (!Array.isArray(args.currentContextScopes) || !args.currentContextScopes.every((scope) => typeof scope === "string")) {
3642
+ if (!Array.isArray(args.currentContextScopes) || !args.currentContextScopes.every((scope2) => typeof scope2 === "string")) {
2600
3643
  throw new EngramAccessInputError(
2601
3644
  "currentContextScopes must be an array of strings"
2602
3645
  );
@@ -2773,21 +3816,27 @@ ${body}`;
2773
3816
  );
2774
3817
  case "engram.observe": {
2775
3818
  const body = parseMcpRequest("observe", args);
2776
- return this.service.observe({
2777
- sessionKey: body.sessionKey,
2778
- messages: body.messages.map((message) => ({
2779
- role: message.role,
2780
- content: message.content,
2781
- parts: message.parts ?? void 0,
2782
- rawContent: message.rawContent ?? void 0,
2783
- sourceFormat: message.sourceFormat ?? void 0
2784
- })),
2785
- namespace: body.namespace,
2786
- authenticatedPrincipal: effectivePrincipal,
2787
- skipExtraction: body.skipExtraction === true,
2788
- cwd: body.cwd,
2789
- projectTag: body.projectTag
2790
- });
3819
+ return this.service.observe(
3820
+ {
3821
+ sessionKey: body.sessionKey,
3822
+ messages: body.messages.map((message) => ({
3823
+ role: message.role,
3824
+ content: message.content,
3825
+ parts: message.parts ?? void 0,
3826
+ rawContent: message.rawContent ?? void 0,
3827
+ sourceFormat: message.sourceFormat ?? void 0
3828
+ })),
3829
+ skipExtraction: body.skipExtraction === true,
3830
+ idempotencyKey: body.idempotencyKey,
3831
+ namespace: body.namespace,
3832
+ authenticatedPrincipal: effectivePrincipal,
3833
+ cwd: body.cwd,
3834
+ projectTag: body.projectTag
3835
+ },
3836
+ // Forward the transport's write-quota enforcer into observe's
3837
+ // idempotency lock so a replay is never 429'd (issue #1649).
3838
+ enforceWriteQuota ? { enforceWriteQuota } : void 0
3839
+ );
2791
3840
  }
2792
3841
  case "engram.lcm_search":
2793
3842
  return this.service.lcmSearch({
@@ -3350,6 +4399,28 @@ ${body}`;
3350
4399
  authenticatedPrincipal: effectivePrincipal
3351
4400
  });
3352
4401
  }
4402
+ case "engram.memory_chat": {
4403
+ const message = typeof args.message === "string" ? args.message : "";
4404
+ if (!message) {
4405
+ throw new EngramAccessInputError("message is required");
4406
+ }
4407
+ const chatSessionId = typeof args.chatSessionId === "string" ? args.chatSessionId : void 0;
4408
+ const chatResult = await processChatMessage({
4409
+ service: this.service,
4410
+ config: this.service.configRef?.chat,
4411
+ memoryDir: this.service.memoryDir,
4412
+ message,
4413
+ ...chatSessionId ? { chatSessionId } : {},
4414
+ ...effectivePrincipal ? { principal: effectivePrincipal } : {},
4415
+ ...scope?.namespace ? { namespace: scope.namespace } : {},
4416
+ ...scope?.sessionKey ? { sessionKey: scope.sessionKey } : {}
4417
+ });
4418
+ if (chatResult && typeof chatResult === "object" && "error" in chatResult) {
4419
+ const { error: _stripped, ...wireResult } = chatResult;
4420
+ return wireResult;
4421
+ }
4422
+ return chatResult;
4423
+ }
3353
4424
  default:
3354
4425
  throw new Error(`unknown tool: ${name}`);
3355
4426
  }
@@ -3357,6 +4428,17 @@ ${body}`;
3357
4428
  };
3358
4429
 
3359
4430
  export {
4431
+ ChatEngine,
4432
+ createProductionChatLlmAdapter,
4433
+ createChatExecutor,
4434
+ createChatSession,
4435
+ loadChatSession,
4436
+ appendTranscriptEntry,
4437
+ markPendingPlan,
4438
+ markPendingPromotion,
4439
+ markPlanResolved,
4440
+ markPromotionResolved,
4441
+ sessionBelongsToPrincipal,
3360
4442
  EngramMcpServer
3361
4443
  };
3362
- //# sourceMappingURL=chunk-I3BT2IDW.js.map
4444
+ //# sourceMappingURL=chunk-SYDHFFAW.js.map