@claude-flow/cli 3.32.2 → 3.32.3

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 (655) hide show
  1. package/.claude/helpers/helpers.manifest.json +3 -3
  2. package/.claude/helpers/statusline.cjs +38 -38
  3. package/catalog-manifest.json +2 -2
  4. package/package.json +2 -2
  5. package/plugins/ruflo-metaharness/scripts/smoke.sh +11 -11
  6. package/dist/src/agenticow/speculative-exploration.d.ts +0 -148
  7. package/dist/src/agenticow/speculative-exploration.js +0 -218
  8. package/dist/src/appliance/gguf-engine.d.ts +0 -91
  9. package/dist/src/appliance/gguf-engine.js +0 -425
  10. package/dist/src/appliance/ruvllm-bridge.d.ts +0 -102
  11. package/dist/src/appliance/ruvllm-bridge.js +0 -292
  12. package/dist/src/appliance/rvfa-builder.d.ts +0 -44
  13. package/dist/src/appliance/rvfa-builder.js +0 -329
  14. package/dist/src/appliance/rvfa-distribution.d.ts +0 -97
  15. package/dist/src/appliance/rvfa-distribution.js +0 -370
  16. package/dist/src/appliance/rvfa-format.d.ts +0 -111
  17. package/dist/src/appliance/rvfa-format.js +0 -393
  18. package/dist/src/appliance/rvfa-runner.d.ts +0 -69
  19. package/dist/src/appliance/rvfa-runner.js +0 -237
  20. package/dist/src/appliance/rvfa-signing.d.ts +0 -123
  21. package/dist/src/appliance/rvfa-signing.js +0 -347
  22. package/dist/src/autopilot-state.d.ts +0 -77
  23. package/dist/src/autopilot-state.js +0 -271
  24. package/dist/src/benchmarks/gaia-agent-planning.smoke.d.ts +0 -18
  25. package/dist/src/benchmarks/gaia-agent-planning.smoke.js +0 -253
  26. package/dist/src/benchmarks/gaia-agent.d.ts +0 -198
  27. package/dist/src/benchmarks/gaia-agent.js +0 -651
  28. package/dist/src/benchmarks/gaia-causal-memory.d.ts +0 -133
  29. package/dist/src/benchmarks/gaia-causal-memory.js +0 -281
  30. package/dist/src/benchmarks/gaia-causal-memory.smoke.d.ts +0 -22
  31. package/dist/src/benchmarks/gaia-causal-memory.smoke.js +0 -300
  32. package/dist/src/benchmarks/gaia-convergence.d.ts +0 -138
  33. package/dist/src/benchmarks/gaia-convergence.js +0 -260
  34. package/dist/src/benchmarks/gaia-convergence.smoke.d.ts +0 -19
  35. package/dist/src/benchmarks/gaia-convergence.smoke.js +0 -246
  36. package/dist/src/benchmarks/gaia-critic.d.ts +0 -123
  37. package/dist/src/benchmarks/gaia-critic.js +0 -312
  38. package/dist/src/benchmarks/gaia-critic.smoke.d.ts +0 -21
  39. package/dist/src/benchmarks/gaia-critic.smoke.js +0 -327
  40. package/dist/src/benchmarks/gaia-decomposer.d.ts +0 -125
  41. package/dist/src/benchmarks/gaia-decomposer.js +0 -350
  42. package/dist/src/benchmarks/gaia-decomposer.smoke.d.ts +0 -21
  43. package/dist/src/benchmarks/gaia-decomposer.smoke.js +0 -228
  44. package/dist/src/benchmarks/gaia-e2e-smoke.d.ts +0 -27
  45. package/dist/src/benchmarks/gaia-e2e-smoke.js +0 -136
  46. package/dist/src/benchmarks/gaia-extract.smoke.d.ts +0 -45
  47. package/dist/src/benchmarks/gaia-extract.smoke.js +0 -242
  48. package/dist/src/benchmarks/gaia-hardness/features.d.ts +0 -46
  49. package/dist/src/benchmarks/gaia-hardness/features.js +0 -170
  50. package/dist/src/benchmarks/gaia-hardness/predictor.d.ts +0 -105
  51. package/dist/src/benchmarks/gaia-hardness/predictor.js +0 -260
  52. package/dist/src/benchmarks/gaia-hardness/predictor.smoke.d.ts +0 -20
  53. package/dist/src/benchmarks/gaia-hardness/predictor.smoke.js +0 -235
  54. package/dist/src/benchmarks/gaia-hardness/train-data-loader.d.ts +0 -51
  55. package/dist/src/benchmarks/gaia-hardness/train-data-loader.js +0 -179
  56. package/dist/src/benchmarks/gaia-judge.d.ts +0 -88
  57. package/dist/src/benchmarks/gaia-judge.js +0 -437
  58. package/dist/src/benchmarks/gaia-loader.d.ts +0 -87
  59. package/dist/src/benchmarks/gaia-loader.js +0 -326
  60. package/dist/src/benchmarks/gaia-tools/file_read.d.ts +0 -35
  61. package/dist/src/benchmarks/gaia-tools/file_read.js +0 -403
  62. package/dist/src/benchmarks/gaia-tools/grounded_query.d.ts +0 -126
  63. package/dist/src/benchmarks/gaia-tools/grounded_query.js +0 -225
  64. package/dist/src/benchmarks/gaia-tools/index.d.ts +0 -32
  65. package/dist/src/benchmarks/gaia-tools/index.js +0 -36
  66. package/dist/src/benchmarks/gaia-tools/types.d.ts +0 -62
  67. package/dist/src/benchmarks/gaia-tools/types.js +0 -12
  68. package/dist/src/benchmarks/gaia-tools/web_search.d.ts +0 -30
  69. package/dist/src/benchmarks/gaia-tools/web_search.js +0 -210
  70. package/dist/src/benchmarks/gaia-voting.d.ts +0 -88
  71. package/dist/src/benchmarks/gaia-voting.js +0 -297
  72. package/dist/src/benchmarks/gaia-voting.smoke.d.ts +0 -20
  73. package/dist/src/benchmarks/gaia-voting.smoke.js +0 -332
  74. package/dist/src/benchmarks/pretrain/index.d.ts +0 -58
  75. package/dist/src/benchmarks/pretrain/index.js +0 -404
  76. package/dist/src/business-pods/bbs-budget-tracker.d.ts +0 -139
  77. package/dist/src/business-pods/bbs-budget-tracker.js +0 -358
  78. package/dist/src/business-pods/domain-affinity-policy.d.ts +0 -47
  79. package/dist/src/business-pods/domain-affinity-policy.js +0 -65
  80. package/dist/src/business-pods/pod-schema.d.ts +0 -96
  81. package/dist/src/business-pods/pod-schema.js +0 -225
  82. package/dist/src/commands/advisor.d.ts +0 -15
  83. package/dist/src/commands/advisor.js +0 -94
  84. package/dist/src/commands/agent-wasm.d.ts +0 -14
  85. package/dist/src/commands/agent-wasm.js +0 -333
  86. package/dist/src/commands/agent.d.ts +0 -8
  87. package/dist/src/commands/agent.js +0 -927
  88. package/dist/src/commands/analyze.d.ts +0 -19
  89. package/dist/src/commands/analyze.js +0 -2047
  90. package/dist/src/commands/announcements.d.ts +0 -17
  91. package/dist/src/commands/announcements.js +0 -0
  92. package/dist/src/commands/appliance-advanced.d.ts +0 -9
  93. package/dist/src/commands/appliance-advanced.js +0 -215
  94. package/dist/src/commands/appliance.d.ts +0 -8
  95. package/dist/src/commands/appliance.js +0 -404
  96. package/dist/src/commands/autopilot.d.ts +0 -15
  97. package/dist/src/commands/autopilot.js +0 -407
  98. package/dist/src/commands/benchmark.d.ts +0 -10
  99. package/dist/src/commands/benchmark.js +0 -460
  100. package/dist/src/commands/claims.d.ts +0 -10
  101. package/dist/src/commands/claims.js +0 -620
  102. package/dist/src/commands/cleanup.d.ts +0 -13
  103. package/dist/src/commands/cleanup.js +0 -250
  104. package/dist/src/commands/completions.d.ts +0 -10
  105. package/dist/src/commands/completions.js +0 -539
  106. package/dist/src/commands/config.d.ts +0 -8
  107. package/dist/src/commands/config.js +0 -428
  108. package/dist/src/commands/daemon.d.ts +0 -59
  109. package/dist/src/commands/daemon.js +0 -1733
  110. package/dist/src/commands/deployment.d.ts +0 -10
  111. package/dist/src/commands/deployment.js +0 -672
  112. package/dist/src/commands/doctor.d.ts +0 -10
  113. package/dist/src/commands/doctor.js +0 -1695
  114. package/dist/src/commands/eject.d.ts +0 -33
  115. package/dist/src/commands/eject.js +0 -195
  116. package/dist/src/commands/embeddings.d.ts +0 -18
  117. package/dist/src/commands/embeddings.js +0 -1623
  118. package/dist/src/commands/funnel.d.ts +0 -18
  119. package/dist/src/commands/funnel.js +0 -302
  120. package/dist/src/commands/gaia-bench.d.ts +0 -40
  121. package/dist/src/commands/gaia-bench.js +0 -597
  122. package/dist/src/commands/guidance.d.ts +0 -8
  123. package/dist/src/commands/guidance.js +0 -556
  124. package/dist/src/commands/hive-mind.d.ts +0 -11
  125. package/dist/src/commands/hive-mind.js +0 -1319
  126. package/dist/src/commands/hooks.d.ts +0 -8
  127. package/dist/src/commands/hooks.js +0 -4606
  128. package/dist/src/commands/index.d.ts +0 -118
  129. package/dist/src/commands/index.js +0 -364
  130. package/dist/src/commands/init.d.ts +0 -13
  131. package/dist/src/commands/init.js +0 -1297
  132. package/dist/src/commands/issues.d.ts +0 -21
  133. package/dist/src/commands/issues.js +0 -567
  134. package/dist/src/commands/mcp.d.ts +0 -11
  135. package/dist/src/commands/mcp.js +0 -732
  136. package/dist/src/commands/memory-backup.d.ts +0 -11
  137. package/dist/src/commands/memory-backup.js +0 -46
  138. package/dist/src/commands/memory-distill.d.ts +0 -27
  139. package/dist/src/commands/memory-distill.js +0 -374
  140. package/dist/src/commands/memory.d.ts +0 -8
  141. package/dist/src/commands/memory.js +0 -1596
  142. package/dist/src/commands/metaharness.d.ts +0 -39
  143. package/dist/src/commands/metaharness.js +0 -215
  144. package/dist/src/commands/migrate.d.ts +0 -8
  145. package/dist/src/commands/migrate.js +0 -742
  146. package/dist/src/commands/neural.d.ts +0 -10
  147. package/dist/src/commands/neural.js +0 -4331
  148. package/dist/src/commands/performance.d.ts +0 -10
  149. package/dist/src/commands/performance.js +0 -583
  150. package/dist/src/commands/plugins.d.ts +0 -11
  151. package/dist/src/commands/plugins.js +0 -826
  152. package/dist/src/commands/process.d.ts +0 -10
  153. package/dist/src/commands/process.js +0 -694
  154. package/dist/src/commands/progress.d.ts +0 -11
  155. package/dist/src/commands/progress.js +0 -259
  156. package/dist/src/commands/providers.d.ts +0 -10
  157. package/dist/src/commands/providers.js +0 -502
  158. package/dist/src/commands/proxy.d.ts +0 -21
  159. package/dist/src/commands/proxy.js +0 -310
  160. package/dist/src/commands/route.d.ts +0 -16
  161. package/dist/src/commands/route.js +0 -822
  162. package/dist/src/commands/ruvector/backup.d.ts +0 -11
  163. package/dist/src/commands/ruvector/backup.js +0 -747
  164. package/dist/src/commands/ruvector/benchmark.d.ts +0 -11
  165. package/dist/src/commands/ruvector/benchmark.js +0 -490
  166. package/dist/src/commands/ruvector/import.d.ts +0 -18
  167. package/dist/src/commands/ruvector/import.js +0 -373
  168. package/dist/src/commands/ruvector/index.d.ts +0 -29
  169. package/dist/src/commands/ruvector/index.js +0 -129
  170. package/dist/src/commands/ruvector/init.d.ts +0 -11
  171. package/dist/src/commands/ruvector/init.js +0 -467
  172. package/dist/src/commands/ruvector/migrate.d.ts +0 -11
  173. package/dist/src/commands/ruvector/migrate.js +0 -498
  174. package/dist/src/commands/ruvector/optimize.d.ts +0 -11
  175. package/dist/src/commands/ruvector/optimize.js +0 -505
  176. package/dist/src/commands/ruvector/pg-utils.d.ts +0 -14
  177. package/dist/src/commands/ruvector/pg-utils.js +0 -41
  178. package/dist/src/commands/ruvector/setup.d.ts +0 -18
  179. package/dist/src/commands/ruvector/setup.js +0 -765
  180. package/dist/src/commands/ruvector/status.d.ts +0 -11
  181. package/dist/src/commands/ruvector/status.js +0 -479
  182. package/dist/src/commands/security.d.ts +0 -10
  183. package/dist/src/commands/security.js +0 -1012
  184. package/dist/src/commands/session.d.ts +0 -8
  185. package/dist/src/commands/session.js +0 -757
  186. package/dist/src/commands/settings.d.ts +0 -19
  187. package/dist/src/commands/settings.js +0 -180
  188. package/dist/src/commands/spinner.d.ts +0 -16
  189. package/dist/src/commands/spinner.js +0 -329
  190. package/dist/src/commands/start.d.ts +0 -8
  191. package/dist/src/commands/start.js +0 -418
  192. package/dist/src/commands/status.d.ts +0 -8
  193. package/dist/src/commands/status.js +0 -608
  194. package/dist/src/commands/swarm.d.ts +0 -8
  195. package/dist/src/commands/swarm.js +0 -891
  196. package/dist/src/commands/task.d.ts +0 -8
  197. package/dist/src/commands/task.js +0 -675
  198. package/dist/src/commands/transfer-store.d.ts +0 -13
  199. package/dist/src/commands/transfer-store.js +0 -428
  200. package/dist/src/commands/update.d.ts +0 -8
  201. package/dist/src/commands/update.js +0 -276
  202. package/dist/src/commands/verify.d.ts +0 -19
  203. package/dist/src/commands/verify.js +0 -261
  204. package/dist/src/commands/version.d.ts +0 -42
  205. package/dist/src/commands/version.js +0 -106
  206. package/dist/src/commands/workflow.d.ts +0 -8
  207. package/dist/src/commands/workflow.js +0 -617
  208. package/dist/src/config/harness-feedback-applier.d.ts +0 -50
  209. package/dist/src/config/harness-feedback-applier.js +0 -122
  210. package/dist/src/config/proven-config-refresh.d.ts +0 -39
  211. package/dist/src/config/proven-config-refresh.js +0 -154
  212. package/dist/src/config/proven-config-rvfa.d.ts +0 -23
  213. package/dist/src/config/proven-config-rvfa.js +0 -73
  214. package/dist/src/config/proven-config.d.ts +0 -86
  215. package/dist/src/config/proven-config.js +0 -176
  216. package/dist/src/config-adapter.d.ts +0 -15
  217. package/dist/src/config-adapter.js +0 -186
  218. package/dist/src/encryption/vault.d.ts +0 -94
  219. package/dist/src/encryption/vault.js +0 -172
  220. package/dist/src/fs-secure.d.ts +0 -86
  221. package/dist/src/fs-secure.js +0 -133
  222. package/dist/src/funnel/advisor-tip.d.ts +0 -58
  223. package/dist/src/funnel/advisor-tip.js +0 -92
  224. package/dist/src/funnel/attribution.d.ts +0 -37
  225. package/dist/src/funnel/attribution.js +0 -101
  226. package/dist/src/funnel/consent.d.ts +0 -22
  227. package/dist/src/funnel/consent.js +0 -58
  228. package/dist/src/funnel/credit-errors.d.ts +0 -31
  229. package/dist/src/funnel/credit-errors.js +0 -88
  230. package/dist/src/funnel/credit-notifier.d.ts +0 -44
  231. package/dist/src/funnel/credit-notifier.js +0 -74
  232. package/dist/src/funnel/disclosure.d.ts +0 -47
  233. package/dist/src/funnel/disclosure.js +0 -109
  234. package/dist/src/funnel/enrollment.d.ts +0 -36
  235. package/dist/src/funnel/enrollment.js +0 -64
  236. package/dist/src/funnel/environment.d.ts +0 -17
  237. package/dist/src/funnel/environment.js +0 -39
  238. package/dist/src/funnel/event-transport.d.ts +0 -51
  239. package/dist/src/funnel/event-transport.js +0 -199
  240. package/dist/src/funnel/events.d.ts +0 -42
  241. package/dist/src/funnel/events.js +0 -150
  242. package/dist/src/funnel/index.d.ts +0 -21
  243. package/dist/src/funnel/index.js +0 -21
  244. package/dist/src/funnel/insights.d.ts +0 -50
  245. package/dist/src/funnel/insights.js +0 -120
  246. package/dist/src/funnel/local-signals.d.ts +0 -20
  247. package/dist/src/funnel/local-signals.js +0 -77
  248. package/dist/src/funnel/message-transport.d.ts +0 -51
  249. package/dist/src/funnel/message-transport.js +0 -149
  250. package/dist/src/funnel/messages.d.ts +0 -55
  251. package/dist/src/funnel/messages.js +0 -160
  252. package/dist/src/funnel/payout.d.ts +0 -40
  253. package/dist/src/funnel/payout.js +0 -60
  254. package/dist/src/funnel/power-saver-notifier.d.ts +0 -44
  255. package/dist/src/funnel/power-saver-notifier.js +0 -92
  256. package/dist/src/funnel/precedence.d.ts +0 -16
  257. package/dist/src/funnel/precedence.js +0 -85
  258. package/dist/src/funnel/promo.d.ts +0 -41
  259. package/dist/src/funnel/promo.js +0 -144
  260. package/dist/src/funnel/rate-limit-notifier.d.ts +0 -55
  261. package/dist/src/funnel/rate-limit-notifier.js +0 -102
  262. package/dist/src/funnel/rotation.d.ts +0 -19
  263. package/dist/src/funnel/rotation.js +0 -70
  264. package/dist/src/funnel/state.d.ts +0 -13
  265. package/dist/src/funnel/state.js +0 -52
  266. package/dist/src/funnel/toggle-cooldown.d.ts +0 -17
  267. package/dist/src/funnel/toggle-cooldown.js +0 -32
  268. package/dist/src/funnel/types.d.ts +0 -98
  269. package/dist/src/funnel/types.js +0 -26
  270. package/dist/src/index.d.ts +0 -81
  271. package/dist/src/index.js +0 -609
  272. package/dist/src/infrastructure/in-memory-repositories.d.ts +0 -68
  273. package/dist/src/infrastructure/in-memory-repositories.js +0 -264
  274. package/dist/src/init/claudemd-generator.d.ts +0 -16
  275. package/dist/src/init/claudemd-generator.js +0 -368
  276. package/dist/src/init/executor.d.ts +0 -41
  277. package/dist/src/init/executor.js +0 -2142
  278. package/dist/src/init/helper-refresh.d.ts +0 -79
  279. package/dist/src/init/helper-refresh.js +0 -347
  280. package/dist/src/init/helper-signing.d.ts +0 -37
  281. package/dist/src/init/helper-signing.js +0 -67
  282. package/dist/src/init/helpers-generator.d.ts +0 -87
  283. package/dist/src/init/helpers-generator.js +0 -1456
  284. package/dist/src/init/index.d.ts +0 -13
  285. package/dist/src/init/index.js +0 -15
  286. package/dist/src/init/mcp-generator.d.ts +0 -26
  287. package/dist/src/init/mcp-generator.js +0 -126
  288. package/dist/src/init/memory-package-resolver.d.ts +0 -53
  289. package/dist/src/init/memory-package-resolver.js +0 -118
  290. package/dist/src/init/settings-generator.d.ts +0 -14
  291. package/dist/src/init/settings-generator.js +0 -462
  292. package/dist/src/init/statusline-generator.d.ts +0 -28
  293. package/dist/src/init/statusline-generator.js +0 -177
  294. package/dist/src/init/types.d.ts +0 -331
  295. package/dist/src/init/types.js +0 -276
  296. package/dist/src/log-filters.d.ts +0 -46
  297. package/dist/src/log-filters.js +0 -107
  298. package/dist/src/mcp-client.d.ts +0 -92
  299. package/dist/src/mcp-client.js +0 -397
  300. package/dist/src/mcp-server.d.ts +0 -163
  301. package/dist/src/mcp-server.js +0 -751
  302. package/dist/src/mcp-tools/agent-execute-core.d.ts +0 -115
  303. package/dist/src/mcp-tools/agent-execute-core.js +0 -587
  304. package/dist/src/mcp-tools/agent-tools.d.ts +0 -9
  305. package/dist/src/mcp-tools/agent-tools.js +0 -837
  306. package/dist/src/mcp-tools/agentbbs-tools.d.ts +0 -28
  307. package/dist/src/mcp-tools/agentbbs-tools.js +0 -394
  308. package/dist/src/mcp-tools/agentdb-tools.d.ts +0 -35
  309. package/dist/src/mcp-tools/agentdb-tools.js +0 -1473
  310. package/dist/src/mcp-tools/agenticow-loader.d.ts +0 -59
  311. package/dist/src/mcp-tools/agenticow-loader.js +0 -105
  312. package/dist/src/mcp-tools/agenticow-speculate-tools.d.ts +0 -24
  313. package/dist/src/mcp-tools/agenticow-speculate-tools.js +0 -209
  314. package/dist/src/mcp-tools/agenticow-tools.d.ts +0 -36
  315. package/dist/src/mcp-tools/agenticow-tools.js +0 -360
  316. package/dist/src/mcp-tools/analyze-tools.d.ts +0 -38
  317. package/dist/src/mcp-tools/analyze-tools.js +0 -346
  318. package/dist/src/mcp-tools/auto-install.d.ts +0 -83
  319. package/dist/src/mcp-tools/auto-install.js +0 -131
  320. package/dist/src/mcp-tools/autopilot-tools.d.ts +0 -12
  321. package/dist/src/mcp-tools/autopilot-tools.js +0 -231
  322. package/dist/src/mcp-tools/browser-intent-tools.d.ts +0 -162
  323. package/dist/src/mcp-tools/browser-intent-tools.js +0 -548
  324. package/dist/src/mcp-tools/browser-session-tools.d.ts +0 -27
  325. package/dist/src/mcp-tools/browser-session-tools.js +0 -398
  326. package/dist/src/mcp-tools/browser-tools.d.ts +0 -21
  327. package/dist/src/mcp-tools/browser-tools.js +0 -760
  328. package/dist/src/mcp-tools/business-pod-tools.d.ts +0 -20
  329. package/dist/src/mcp-tools/business-pod-tools.js +0 -169
  330. package/dist/src/mcp-tools/claims-tools.d.ts +0 -12
  331. package/dist/src/mcp-tools/claims-tools.js +0 -863
  332. package/dist/src/mcp-tools/config-tools.d.ts +0 -8
  333. package/dist/src/mcp-tools/config-tools.js +0 -411
  334. package/dist/src/mcp-tools/coordination-tools.d.ts +0 -13
  335. package/dist/src/mcp-tools/coordination-tools.js +0 -729
  336. package/dist/src/mcp-tools/daa-tools.d.ts +0 -13
  337. package/dist/src/mcp-tools/daa-tools.js +0 -534
  338. package/dist/src/mcp-tools/embeddings-tools.d.ts +0 -9
  339. package/dist/src/mcp-tools/embeddings-tools.js +0 -904
  340. package/dist/src/mcp-tools/github-tools.d.ts +0 -9
  341. package/dist/src/mcp-tools/github-tools.js +0 -659
  342. package/dist/src/mcp-tools/guidance-tools.d.ts +0 -15
  343. package/dist/src/mcp-tools/guidance-tools.js +0 -639
  344. package/dist/src/mcp-tools/hive-mind-tools.d.ts +0 -8
  345. package/dist/src/mcp-tools/hive-mind-tools.js +0 -953
  346. package/dist/src/mcp-tools/hooks-tools.d.ts +0 -65
  347. package/dist/src/mcp-tools/hooks-tools.js +0 -4836
  348. package/dist/src/mcp-tools/http-fetch-tools.d.ts +0 -55
  349. package/dist/src/mcp-tools/http-fetch-tools.js +0 -329
  350. package/dist/src/mcp-tools/index.d.ts +0 -34
  351. package/dist/src/mcp-tools/index.js +0 -40
  352. package/dist/src/mcp-tools/managed-agent-tools.d.ts +0 -22
  353. package/dist/src/mcp-tools/managed-agent-tools.js +0 -357
  354. package/dist/src/mcp-tools/memory-tools.d.ts +0 -14
  355. package/dist/src/mcp-tools/memory-tools.js +0 -1330
  356. package/dist/src/mcp-tools/metaharness-tools.d.ts +0 -51
  357. package/dist/src/mcp-tools/metaharness-tools.js +0 -684
  358. package/dist/src/mcp-tools/neural-tools.d.ts +0 -54
  359. package/dist/src/mcp-tools/neural-tools.js +0 -1168
  360. package/dist/src/mcp-tools/performance-tools.d.ts +0 -16
  361. package/dist/src/mcp-tools/performance-tools.js +0 -675
  362. package/dist/src/mcp-tools/progress-tools.d.ts +0 -14
  363. package/dist/src/mcp-tools/progress-tools.js +0 -348
  364. package/dist/src/mcp-tools/request-tracker.d.ts +0 -17
  365. package/dist/src/mcp-tools/request-tracker.js +0 -27
  366. package/dist/src/mcp-tools/ruvllm-tools.d.ts +0 -9
  367. package/dist/src/mcp-tools/ruvllm-tools.js +0 -355
  368. package/dist/src/mcp-tools/security-tools.d.ts +0 -18
  369. package/dist/src/mcp-tools/security-tools.js +0 -556
  370. package/dist/src/mcp-tools/session-tools.d.ts +0 -8
  371. package/dist/src/mcp-tools/session-tools.js +0 -517
  372. package/dist/src/mcp-tools/swarm-tools.d.ts +0 -37
  373. package/dist/src/mcp-tools/swarm-tools.js +0 -390
  374. package/dist/src/mcp-tools/system-tools.d.ts +0 -13
  375. package/dist/src/mcp-tools/system-tools.js +0 -688
  376. package/dist/src/mcp-tools/task-tools.d.ts +0 -8
  377. package/dist/src/mcp-tools/task-tools.js +0 -487
  378. package/dist/src/mcp-tools/terminal-tools.d.ts +0 -8
  379. package/dist/src/mcp-tools/terminal-tools.js +0 -306
  380. package/dist/src/mcp-tools/testgen-tools.d.ts +0 -26
  381. package/dist/src/mcp-tools/testgen-tools.js +0 -168
  382. package/dist/src/mcp-tools/tool-loop-guardrail.d.ts +0 -31
  383. package/dist/src/mcp-tools/tool-loop-guardrail.js +0 -71
  384. package/dist/src/mcp-tools/transfer-tools.d.ts +0 -14
  385. package/dist/src/mcp-tools/transfer-tools.js +0 -447
  386. package/dist/src/mcp-tools/types.d.ts +0 -8
  387. package/dist/src/mcp-tools/types.js +0 -8
  388. package/dist/src/mcp-tools/validate-input.d.ts +0 -9
  389. package/dist/src/mcp-tools/validate-input.js +0 -9
  390. package/dist/src/mcp-tools/wasm-agent-tools.d.ts +0 -13
  391. package/dist/src/mcp-tools/wasm-agent-tools.js +0 -840
  392. package/dist/src/mcp-tools/workflow-tools.d.ts +0 -8
  393. package/dist/src/mcp-tools/workflow-tools.js +0 -884
  394. package/dist/src/memory/bge-embedder.d.ts +0 -25
  395. package/dist/src/memory/bge-embedder.js +0 -121
  396. package/dist/src/memory/cross-encoder-rerank.d.ts +0 -33
  397. package/dist/src/memory/cross-encoder-rerank.js +0 -123
  398. package/dist/src/memory/embedding-policy.d.ts +0 -21
  399. package/dist/src/memory/embedding-policy.js +0 -30
  400. package/dist/src/memory/embedding-quantization.d.ts +0 -62
  401. package/dist/src/memory/embedding-quantization.js +0 -156
  402. package/dist/src/memory/ewc-consolidation.d.ts +0 -305
  403. package/dist/src/memory/ewc-consolidation.js +0 -611
  404. package/dist/src/memory/graph-edge-writer.d.ts +0 -95
  405. package/dist/src/memory/graph-edge-writer.js +0 -217
  406. package/dist/src/memory/hybrid-retrieval.d.ts +0 -77
  407. package/dist/src/memory/hybrid-retrieval.js +0 -192
  408. package/dist/src/memory/intelligence.d.ts +0 -405
  409. package/dist/src/memory/intelligence.js +0 -1316
  410. package/dist/src/memory/lucene-bm25.d.ts +0 -19
  411. package/dist/src/memory/lucene-bm25.js +0 -308
  412. package/dist/src/memory/memory-bridge.d.ts +0 -537
  413. package/dist/src/memory/memory-bridge.js +0 -2460
  414. package/dist/src/memory/memory-initializer.d.ts +0 -556
  415. package/dist/src/memory/memory-initializer.js +0 -3021
  416. package/dist/src/memory/neural-package-bridge.d.ts +0 -48
  417. package/dist/src/memory/neural-package-bridge.js +0 -87
  418. package/dist/src/memory/rabitq-index.d.ts +0 -60
  419. package/dist/src/memory/rabitq-index.js +0 -242
  420. package/dist/src/memory/sona-optimizer.d.ts +0 -267
  421. package/dist/src/memory/sona-optimizer.js +0 -779
  422. package/dist/src/memory/structured-distill.d.ts +0 -48
  423. package/dist/src/memory/structured-distill.js +0 -125
  424. package/dist/src/output.d.ts +0 -9
  425. package/dist/src/output.js +0 -9
  426. package/dist/src/parser.d.ts +0 -89
  427. package/dist/src/parser.js +0 -516
  428. package/dist/src/plugins/manager.d.ts +0 -133
  429. package/dist/src/plugins/manager.js +0 -415
  430. package/dist/src/plugins/store/discovery.d.ts +0 -99
  431. package/dist/src/plugins/store/discovery.js +0 -1224
  432. package/dist/src/plugins/store/index.d.ts +0 -76
  433. package/dist/src/plugins/store/index.js +0 -141
  434. package/dist/src/plugins/store/search.d.ts +0 -46
  435. package/dist/src/plugins/store/search.js +0 -230
  436. package/dist/src/plugins/store/types.d.ts +0 -279
  437. package/dist/src/plugins/store/types.js +0 -7
  438. package/dist/src/plugins/tests/demo-plugin-store.d.ts +0 -7
  439. package/dist/src/plugins/tests/demo-plugin-store.js +0 -126
  440. package/dist/src/plugins/tests/standalone-test.d.ts +0 -12
  441. package/dist/src/plugins/tests/standalone-test.js +0 -188
  442. package/dist/src/plugins/tests/test-plugin-store.d.ts +0 -7
  443. package/dist/src/plugins/tests/test-plugin-store.js +0 -206
  444. package/dist/src/production/circuit-breaker.d.ts +0 -101
  445. package/dist/src/production/circuit-breaker.js +0 -241
  446. package/dist/src/production/error-handler.d.ts +0 -92
  447. package/dist/src/production/error-handler.js +0 -299
  448. package/dist/src/production/index.d.ts +0 -23
  449. package/dist/src/production/index.js +0 -18
  450. package/dist/src/production/monitoring.d.ts +0 -161
  451. package/dist/src/production/monitoring.js +0 -356
  452. package/dist/src/production/rate-limiter.d.ts +0 -80
  453. package/dist/src/production/rate-limiter.js +0 -201
  454. package/dist/src/production/retry.d.ts +0 -48
  455. package/dist/src/production/retry.js +0 -179
  456. package/dist/src/prompt.d.ts +0 -44
  457. package/dist/src/prompt.js +0 -501
  458. package/dist/src/runtime/headless.d.ts +0 -60
  459. package/dist/src/runtime/headless.js +0 -284
  460. package/dist/src/runtime/parent-death-watchdog.d.ts +0 -42
  461. package/dist/src/runtime/parent-death-watchdog.js +0 -70
  462. package/dist/src/ruvector/agent-wasm.d.ts +0 -228
  463. package/dist/src/ruvector/agent-wasm.js +0 -463
  464. package/dist/src/ruvector/ast-analyzer.d.ts +0 -67
  465. package/dist/src/ruvector/ast-analyzer.js +0 -277
  466. package/dist/src/ruvector/codemods/engine.d.ts +0 -45
  467. package/dist/src/ruvector/codemods/engine.js +0 -291
  468. package/dist/src/ruvector/codemods/scope-analysis.d.ts +0 -29
  469. package/dist/src/ruvector/codemods/scope-analysis.js +0 -162
  470. package/dist/src/ruvector/coverage-router.d.ts +0 -160
  471. package/dist/src/ruvector/coverage-router.js +0 -531
  472. package/dist/src/ruvector/coverage-tools.d.ts +0 -33
  473. package/dist/src/ruvector/coverage-tools.js +0 -157
  474. package/dist/src/ruvector/diff-classifier.d.ts +0 -175
  475. package/dist/src/ruvector/diff-classifier.js +0 -699
  476. package/dist/src/ruvector/diskann-backend.d.ts +0 -78
  477. package/dist/src/ruvector/diskann-backend.js +0 -310
  478. package/dist/src/ruvector/enhanced-model-router.d.ts +0 -172
  479. package/dist/src/ruvector/enhanced-model-router.js +0 -577
  480. package/dist/src/ruvector/graph-analyzer.d.ts +0 -187
  481. package/dist/src/ruvector/graph-analyzer.js +0 -929
  482. package/dist/src/ruvector/graph-backend.d.ts +0 -79
  483. package/dist/src/ruvector/graph-backend.js +0 -220
  484. package/dist/src/ruvector/index.d.ts +0 -38
  485. package/dist/src/ruvector/index.js +0 -86
  486. package/dist/src/ruvector/lora-adapter.d.ts +0 -292
  487. package/dist/src/ruvector/lora-adapter.js +0 -710
  488. package/dist/src/ruvector/model-prices.d.ts +0 -50
  489. package/dist/src/ruvector/model-prices.js +0 -72
  490. package/dist/src/ruvector/model-router.d.ts +0 -408
  491. package/dist/src/ruvector/model-router.js +0 -1162
  492. package/dist/src/ruvector/neural-router.d.ts +0 -182
  493. package/dist/src/ruvector/neural-router.js +0 -825
  494. package/dist/src/ruvector/output-verifier.d.ts +0 -83
  495. package/dist/src/ruvector/output-verifier.js +0 -277
  496. package/dist/src/ruvector/q-learning-router.d.ts +0 -227
  497. package/dist/src/ruvector/q-learning-router.js +0 -721
  498. package/dist/src/ruvector/router-calibrator.d.ts +0 -65
  499. package/dist/src/ruvector/router-calibrator.js +0 -120
  500. package/dist/src/ruvector/router-parallel-recorder.d.ts +0 -127
  501. package/dist/src/ruvector/router-parallel-recorder.js +0 -183
  502. package/dist/src/ruvector/router-trajectory.d.ts +0 -194
  503. package/dist/src/ruvector/router-trajectory.js +0 -281
  504. package/dist/src/ruvector/run-transcript-recorder.d.ts +0 -154
  505. package/dist/src/ruvector/run-transcript-recorder.js +0 -209
  506. package/dist/src/ruvector/ruvllm-wasm.d.ts +0 -179
  507. package/dist/src/ruvector/ruvllm-wasm.js +0 -379
  508. package/dist/src/ruvector/semantic-router.d.ts +0 -77
  509. package/dist/src/ruvector/semantic-router.js +0 -178
  510. package/dist/src/ruvector/task-embedder.d.ts +0 -56
  511. package/dist/src/ruvector/task-embedder.js +0 -237
  512. package/dist/src/ruvector/trajectory-tree.d.ts +0 -113
  513. package/dist/src/ruvector/trajectory-tree.js +0 -237
  514. package/dist/src/ruvector/vector-db.d.ts +0 -73
  515. package/dist/src/ruvector/vector-db.js +0 -301
  516. package/dist/src/ruvector/wasm-embedder.d.ts +0 -13
  517. package/dist/src/ruvector/wasm-embedder.js +0 -143
  518. package/dist/src/security/builtin-aidefence.d.ts +0 -34
  519. package/dist/src/security/builtin-aidefence.js +0 -86
  520. package/dist/src/services/agentic-flow-bridge.d.ts +0 -50
  521. package/dist/src/services/agentic-flow-bridge.js +0 -95
  522. package/dist/src/services/ai-job-dedup.d.ts +0 -61
  523. package/dist/src/services/ai-job-dedup.js +0 -136
  524. package/dist/src/services/checkpoint-gate.d.ts +0 -140
  525. package/dist/src/services/checkpoint-gate.js +0 -223
  526. package/dist/src/services/claim-service.d.ts +0 -204
  527. package/dist/src/services/claim-service.js +0 -818
  528. package/dist/src/services/config-file-manager.d.ts +0 -37
  529. package/dist/src/services/config-file-manager.js +0 -224
  530. package/dist/src/services/container-worker-pool.d.ts +0 -204
  531. package/dist/src/services/container-worker-pool.js +0 -589
  532. package/dist/src/services/daemon-autostart.d.ts +0 -17
  533. package/dist/src/services/daemon-autostart.js +0 -102
  534. package/dist/src/services/distill-oracle.d.ts +0 -190
  535. package/dist/src/services/distill-oracle.js +0 -349
  536. package/dist/src/services/distill-tuning.d.ts +0 -111
  537. package/dist/src/services/distill-tuning.js +0 -510
  538. package/dist/src/services/evolve-proof.d.ts +0 -253
  539. package/dist/src/services/evolve-proof.js +0 -343
  540. package/dist/src/services/fable-harness.d.ts +0 -208
  541. package/dist/src/services/fable-harness.js +0 -388
  542. package/dist/src/services/git-workspace-identity.d.ts +0 -42
  543. package/dist/src/services/git-workspace-identity.js +0 -99
  544. package/dist/src/services/global-ai-budget.d.ts +0 -135
  545. package/dist/src/services/global-ai-budget.js +0 -415
  546. package/dist/src/services/harness-benchmark.d.ts +0 -68
  547. package/dist/src/services/harness-benchmark.js +0 -94
  548. package/dist/src/services/harness-canary.d.ts +0 -60
  549. package/dist/src/services/harness-canary.js +0 -69
  550. package/dist/src/services/harness-corpus-harvester.d.ts +0 -51
  551. package/dist/src/services/harness-corpus-harvester.js +0 -74
  552. package/dist/src/services/harness-flywheel-generations.d.ts +0 -115
  553. package/dist/src/services/harness-flywheel-generations.js +0 -360
  554. package/dist/src/services/harness-flywheel-runtime.d.ts +0 -25
  555. package/dist/src/services/harness-flywheel-runtime.js +0 -92
  556. package/dist/src/services/harness-flywheel.d.ts +0 -48
  557. package/dist/src/services/harness-flywheel.js +0 -207
  558. package/dist/src/services/harness-frozen-eval.d.ts +0 -22
  559. package/dist/src/services/harness-frozen-eval.js +0 -66
  560. package/dist/src/services/harness-hosts.d.ts +0 -40
  561. package/dist/src/services/harness-hosts.js +0 -88
  562. package/dist/src/services/harness-improvement-ledger.d.ts +0 -63
  563. package/dist/src/services/harness-improvement-ledger.js +0 -101
  564. package/dist/src/services/harness-loop.d.ts +0 -53
  565. package/dist/src/services/harness-loop.js +0 -85
  566. package/dist/src/services/harness-qualification.d.ts +0 -66
  567. package/dist/src/services/harness-qualification.js +0 -143
  568. package/dist/src/services/harness-replay.d.ts +0 -37
  569. package/dist/src/services/harness-replay.js +0 -92
  570. package/dist/src/services/harness-verify.d.ts +0 -33
  571. package/dist/src/services/harness-verify.js +0 -26
  572. package/dist/src/services/harness-worker.d.ts +0 -23
  573. package/dist/src/services/harness-worker.js +0 -66
  574. package/dist/src/services/headless-worker-executor.d.ts +0 -358
  575. package/dist/src/services/headless-worker-executor.js +0 -1269
  576. package/dist/src/services/index.d.ts +0 -13
  577. package/dist/src/services/index.js +0 -11
  578. package/dist/src/services/memory-backup.d.ts +0 -53
  579. package/dist/src/services/memory-backup.js +0 -198
  580. package/dist/src/services/memory-distillation.d.ts +0 -41
  581. package/dist/src/services/memory-distillation.js +0 -277
  582. package/dist/src/services/native-training.d.ts +0 -68
  583. package/dist/src/services/native-training.js +0 -141
  584. package/dist/src/services/registry-api.d.ts +0 -58
  585. package/dist/src/services/registry-api.js +0 -146
  586. package/dist/src/services/repo-supervisor.d.ts +0 -70
  587. package/dist/src/services/repo-supervisor.js +0 -228
  588. package/dist/src/services/ruvector-training.d.ts +0 -222
  589. package/dist/src/services/ruvector-training.js +0 -693
  590. package/dist/src/services/swarm-memory-branches.d.ts +0 -135
  591. package/dist/src/services/swarm-memory-branches.js +0 -213
  592. package/dist/src/services/weight-eft.d.ts +0 -305
  593. package/dist/src/services/weight-eft.js +0 -296
  594. package/dist/src/services/worker-daemon.d.ts +0 -439
  595. package/dist/src/services/worker-daemon.js +0 -1865
  596. package/dist/src/services/worker-queue.d.ts +0 -194
  597. package/dist/src/services/worker-queue.js +0 -513
  598. package/dist/src/services/workspace-lease.d.ts +0 -55
  599. package/dist/src/services/workspace-lease.js +0 -191
  600. package/dist/src/suggest.d.ts +0 -53
  601. package/dist/src/suggest.js +0 -200
  602. package/dist/src/transfer/anonymization/index.d.ts +0 -25
  603. package/dist/src/transfer/anonymization/index.js +0 -175
  604. package/dist/src/transfer/deploy-seraphine.d.ts +0 -13
  605. package/dist/src/transfer/deploy-seraphine.js +0 -205
  606. package/dist/src/transfer/export.d.ts +0 -25
  607. package/dist/src/transfer/export.js +0 -113
  608. package/dist/src/transfer/index.d.ts +0 -12
  609. package/dist/src/transfer/index.js +0 -31
  610. package/dist/src/transfer/ipfs/client.d.ts +0 -109
  611. package/dist/src/transfer/ipfs/client.js +0 -307
  612. package/dist/src/transfer/ipfs/upload.d.ts +0 -95
  613. package/dist/src/transfer/ipfs/upload.js +0 -413
  614. package/dist/src/transfer/models/seraphine.d.ts +0 -72
  615. package/dist/src/transfer/models/seraphine.js +0 -373
  616. package/dist/src/transfer/serialization/cfp.d.ts +0 -49
  617. package/dist/src/transfer/serialization/cfp.js +0 -183
  618. package/dist/src/transfer/storage/gcs.d.ts +0 -82
  619. package/dist/src/transfer/storage/gcs.js +0 -272
  620. package/dist/src/transfer/storage/index.d.ts +0 -6
  621. package/dist/src/transfer/storage/index.js +0 -6
  622. package/dist/src/transfer/store/discovery.d.ts +0 -84
  623. package/dist/src/transfer/store/discovery.js +0 -382
  624. package/dist/src/transfer/store/download.d.ts +0 -70
  625. package/dist/src/transfer/store/download.js +0 -334
  626. package/dist/src/transfer/store/index.d.ts +0 -84
  627. package/dist/src/transfer/store/index.js +0 -153
  628. package/dist/src/transfer/store/publish.d.ts +0 -76
  629. package/dist/src/transfer/store/publish.js +0 -294
  630. package/dist/src/transfer/store/registry.d.ts +0 -58
  631. package/dist/src/transfer/store/registry.js +0 -285
  632. package/dist/src/transfer/store/search.d.ts +0 -54
  633. package/dist/src/transfer/store/search.js +0 -232
  634. package/dist/src/transfer/store/tests/standalone-test.d.ts +0 -12
  635. package/dist/src/transfer/store/tests/standalone-test.js +0 -190
  636. package/dist/src/transfer/store/types.d.ts +0 -193
  637. package/dist/src/transfer/store/types.js +0 -6
  638. package/dist/src/transfer/test-seraphine.d.ts +0 -6
  639. package/dist/src/transfer/test-seraphine.js +0 -105
  640. package/dist/src/transfer/tests/test-store.d.ts +0 -7
  641. package/dist/src/transfer/tests/test-store.js +0 -214
  642. package/dist/src/transfer/types.d.ts +0 -245
  643. package/dist/src/transfer/types.js +0 -6
  644. package/dist/src/types.d.ts +0 -13
  645. package/dist/src/types.js +0 -13
  646. package/dist/src/update/checker.d.ts +0 -34
  647. package/dist/src/update/checker.js +0 -191
  648. package/dist/src/update/executor.d.ts +0 -33
  649. package/dist/src/update/executor.js +0 -217
  650. package/dist/src/update/index.d.ts +0 -33
  651. package/dist/src/update/index.js +0 -64
  652. package/dist/src/update/rate-limiter.d.ts +0 -20
  653. package/dist/src/update/rate-limiter.js +0 -96
  654. package/dist/src/update/validator.d.ts +0 -17
  655. package/dist/src/update/validator.js +0 -123
@@ -1,2460 +0,0 @@
1
- /**
2
- * Memory Bridge — Routes CLI memory operations through ControllerRegistry + AgentDB v3
3
- *
4
- * Per ADR-053 Phases 1-6: Full controller activation pipeline.
5
- * CLI → ControllerRegistry → AgentDB v3 controllers.
6
- *
7
- * Phase 1: Core CRUD + embeddings + HNSW + controller access (complete)
8
- * Phase 2: BM25 hybrid search, TieredCache read/write, MutationGuard validation
9
- * Phase 3: ReasoningBank pattern store, recordFeedback, CausalMemoryGraph edges
10
- * Phase 4: SkillLibrary promotion, ExplainableRecall provenance, AttestationLog
11
- * Phase 5: ReflexionMemory session lifecycle, WitnessChain attestation
12
- * Phase 6: AgentDB MCP tools (separate file), COW branching
13
- *
14
- * Uses better-sqlite3 API (synchronous .all()/.get()/.run()) since that's
15
- * what AgentDB v3 uses internally.
16
- *
17
- * @module v3/cli/memory-bridge
18
- */
19
- import * as path from 'path';
20
- import * as crypto from 'crypto';
21
- import { createRequire } from 'node:module';
22
- // ===== Lazy singleton =====
23
- let registryPromise = null;
24
- let registryInstance = null;
25
- let bridgeAvailable = null;
26
- /**
27
- * Resolve database path with path traversal protection.
28
- * Only allows paths within or below the project's working directory,
29
- * or the special ':memory:' path.
30
- *
31
- * #1945: the previous hard-coded `<cwd>/.swarm/memory.db` default ignored
32
- * `CLAUDE_FLOW_MEMORY_PATH` / `claude-flow.config.json#memory.persistPath`
33
- * — so users with non-default memory paths had `memory init` write to e.g.
34
- * `data/memory/memory.db` while `bridgeStoreEntry()` wrote to
35
- * `.swarm/memory.db`. CLI store reported success against the wrong file and
36
- * a fresh process reading the configured path saw nothing.
37
- *
38
- * Use `getMemoryRoot()` (from memory-initializer) so the bridge and the
39
- * initializer agree on the same file. Imported via require() to avoid a
40
- * circular ESM dep between memory-initializer.ts and memory-bridge.ts.
41
- */
42
- function getDbPath(customPath) {
43
- let defaultDir = path.resolve(process.cwd(), '.swarm');
44
- try {
45
- // `getMemoryRoot()` honors $CLAUDE_FLOW_MEMORY_PATH, then the
46
- // claude-flow.config.json `memory.persistPath`, then defaults to `.swarm`.
47
- const cjsRequire = createRequire(import.meta.url);
48
- const mod = cjsRequire('./memory-initializer.js');
49
- if (typeof mod.getMemoryRoot === 'function') {
50
- defaultDir = mod.getMemoryRoot();
51
- }
52
- }
53
- catch {
54
- /* memory-initializer not resolvable in this build — keep `.swarm/` default */
55
- }
56
- if (!customPath)
57
- return path.join(defaultDir, 'memory.db');
58
- if (customPath === ':memory:')
59
- return ':memory:';
60
- const resolved = path.resolve(customPath);
61
- // Ensure the path doesn't escape the working directory.
62
- const cwd = process.cwd();
63
- if (!resolved.startsWith(cwd)) {
64
- return path.join(defaultDir, 'memory.db'); // fallback to safe default
65
- }
66
- return resolved;
67
- }
68
- /**
69
- * Generate a secure random ID for memory entries.
70
- */
71
- function generateId(prefix) {
72
- return `${prefix}_${Date.now()}_${crypto.randomBytes(8).toString('hex')}`;
73
- }
74
- /**
75
- * Lazily initialize the ControllerRegistry singleton.
76
- * Returns null if @claude-flow/memory is not available.
77
- */
78
- async function getRegistry(dbPath) {
79
- if (bridgeAvailable === false)
80
- return null;
81
- if (registryInstance)
82
- return registryInstance;
83
- if (!registryPromise) {
84
- registryPromise = (async () => {
85
- try {
86
- const { ControllerRegistry } = await import('@claude-flow/memory');
87
- const registry = new ControllerRegistry();
88
- // Suppress noisy console.log during init
89
- const origLog = console.log;
90
- console.log = (...args) => {
91
- const msg = String(args[0] ?? '');
92
- if (msg.includes('Transformers.js') ||
93
- msg.includes('better-sqlite3') ||
94
- msg.includes('[AgentDB]') ||
95
- msg.includes('[HNSWLibBackend]') ||
96
- msg.includes('RuVector graph'))
97
- return;
98
- origLog.apply(console, args);
99
- };
100
- try {
101
- await registry.initialize({
102
- dbPath: dbPath || getDbPath(),
103
- embeddingModel: 'Xenova/all-MiniLM-L6-v2',
104
- dimension: 384,
105
- vectorBackend: 'auto',
106
- controllers: {
107
- reasoningBank: true,
108
- learningBridge: false,
109
- tieredCache: true,
110
- hierarchicalMemory: true,
111
- memoryConsolidation: true,
112
- memoryGraph: true,
113
- vectorBackend: true,
114
- },
115
- });
116
- }
117
- finally {
118
- console.log = origLog;
119
- }
120
- // Wire intelligence module as the learning backend.
121
- // AgentDB's ReasoningBank/LearningSystem need a better-sqlite3 db
122
- // handle which ControllerRegistry doesn't expose. Instead, use the
123
- // local intelligence module (SONA + LocalReasoningBank + file
124
- // persistence) for learning.
125
- //
126
- // PERF: parallelize the two independent post-init paths
127
- // (intelligence module load + agentdb import). Previously these
128
- // ran serially, adding ~50-150ms to cold start. Both can resolve
129
- // concurrently because they touch disjoint controller slots.
130
- try {
131
- const reg = registry;
132
- const intelligencePromise = (async () => {
133
- try {
134
- const intelligence = await import('./intelligence.js');
135
- const initResult = await intelligence.initializeIntelligence();
136
- if (initResult.reasoningBankEnabled) {
137
- const rb = intelligence.getReasoningBank();
138
- if (rb && !reg.get('reasoningBank')) {
139
- if (typeof reg.set === 'function')
140
- reg.set('reasoningBank', rb);
141
- else
142
- reg._controllers = { ...(reg._controllers || {}), reasoningBank: rb };
143
- }
144
- }
145
- if (initResult.sonaEnabled) {
146
- const sona = intelligence.getSonaCoordinator();
147
- if (sona && !reg.get('learningSystem')) {
148
- if (typeof reg.set === 'function')
149
- reg.set('learningSystem', sona);
150
- else
151
- reg._controllers = { ...(reg._controllers || {}), learningSystem: sona };
152
- }
153
- }
154
- }
155
- catch { /* intelligence module not available — learning stays unwired */ }
156
- })();
157
- const agentdbPromise = (async () => {
158
- // Single import shared across SkillLibrary + SemanticRouter probe.
159
- let agentdb = null;
160
- try {
161
- agentdb = (await import('agentdb'));
162
- }
163
- catch {
164
- return; /* AgentDB not available */
165
- }
166
- // SkillLibrary (no db required)
167
- try {
168
- const SkillCtor = agentdb.SkillLibrary;
169
- if (SkillCtor && !reg.get('skills')) {
170
- const sk = new SkillCtor();
171
- if (typeof reg.set === 'function')
172
- reg.set('skills', sk);
173
- else
174
- reg._controllers = { ...(reg._controllers || {}), skills: sk };
175
- }
176
- }
177
- catch { /* SkillLibrary optional */ }
178
- // ADR-093 F9: probe multiple router class names across agentdb
179
- // alpha versions (alpha.10 had SemanticRouter; alpha.11+ removed
180
- // it in favor of @ruvector/router; future versions may
181
- // reintroduce). Wire only if .route() is callable.
182
- try {
183
- const candidates = ['SemanticRouter', 'IntentRouter', 'TaskRouter'];
184
- let routerInstance = null;
185
- for (const name of candidates) {
186
- const Ctor = agentdb[name];
187
- if (typeof Ctor === 'function') {
188
- try {
189
- const inst = (() => {
190
- try {
191
- return new Ctor({ dimension: 384 });
192
- }
193
- catch {
194
- return new Ctor();
195
- }
196
- })();
197
- if (inst && typeof inst.route === 'function') {
198
- routerInstance = inst;
199
- break;
200
- }
201
- }
202
- catch { /* try next candidate */ }
203
- }
204
- }
205
- if (routerInstance && !reg.get('semanticRouter')) {
206
- if (typeof reg.set === 'function')
207
- reg.set('semanticRouter', routerInstance);
208
- else
209
- reg._controllers = { ...(reg._controllers || {}), semanticRouter: routerInstance };
210
- }
211
- }
212
- catch { /* router optional */ }
213
- // ADR-095 G7: load disabled-by-default controllers via direct
214
- // file:// URLs from the bundled agentdb. agentdb's exports
215
- // field doesn't expose these subpaths and we can't reliably
216
- // patch it across pnpm-hoisted multi-version trees, so we
217
- // sidestep the exports field entirely and import the file
218
- // by absolute URL. Only loads controllers whose constructor
219
- // is safe with no special prerequisites — others remain off
220
- // pending per-controller activation ADRs.
221
- try {
222
- const { createRequire } = await import('node:module');
223
- const { pathToFileURL } = await import('node:url');
224
- const path = await import('node:path');
225
- const fs = await import('node:fs');
226
- const cjsRequire = createRequire(import.meta.url);
227
- let adbPkgJsonPath = null;
228
- try {
229
- adbPkgJsonPath = cjsRequire.resolve('agentdb/package.json');
230
- }
231
- catch {
232
- adbPkgJsonPath = null;
233
- }
234
- if (adbPkgJsonPath) {
235
- const adbDir = path.dirname(adbPkgJsonPath);
236
- const candidates = [
237
- // GNNService and RVFOptimizer can construct with no args
238
- // in current agentdb — safe to activate as-is.
239
- { name: 'gnnService', relPath: 'dist/src/services/GNNService.js', configurable: false },
240
- { name: 'rvfOptimizer', relPath: 'dist/src/optimizations/RVFOptimizer.js', configurable: false },
241
- // ADR-095 G7 follow-up: MutationGuard constructs cleanly
242
- // with no args and exposes WASM-backed proof generation.
243
- // No external deps; safe-default activation.
244
- { name: 'mutationGuard', relPath: 'dist/src/security/MutationGuard.js', configurable: false },
245
- // AttestationLog needs a sqlite db handle — wired below
246
- // separately because we have to construct a db too.
247
- // GuardedVectorBackend needs key material — leave for
248
- // follow-up ADR.
249
- ];
250
- for (const cand of candidates) {
251
- if (reg.get(cand.name))
252
- continue;
253
- const abs = path.join(adbDir, cand.relPath);
254
- if (!fs.existsSync(abs))
255
- continue;
256
- try {
257
- const url = pathToFileURL(abs).href;
258
- const mod = await import(url);
259
- // Look for a default export, named export matching the
260
- // file basename, or any class-typed export.
261
- const baseName = path.basename(cand.relPath, '.js');
262
- const Ctor = (mod[baseName] || mod.default ||
263
- Object.values(mod).find(v => typeof v === 'function'));
264
- if (typeof Ctor !== 'function')
265
- continue;
266
- const inst = new Ctor();
267
- if (typeof reg.set === 'function')
268
- reg.set(cand.name, inst);
269
- else
270
- reg._controllers = { ...(reg._controllers || {}), [cand.name]: inst };
271
- }
272
- catch { /* skip controllers that fail to construct */ }
273
- }
274
- // AttestationLog activation — needs a better-sqlite3
275
- // database. We open a dedicated file at .swarm/attestation.db
276
- // (separate from the main memory.db so the audit trail
277
- // is isolated). Best-effort: if better-sqlite3 isn't
278
- // resolvable in this env, skip cleanly.
279
- let attestationInst = null;
280
- if (!reg.get('attestationLog')) {
281
- try {
282
- const attestationFile = path.join(adbDir, 'dist/src/security/AttestationLog.js');
283
- if (fs.existsSync(attestationFile)) {
284
- const Database = cjsRequire('better-sqlite3');
285
- const swarmDir = path.resolve(process.cwd(), '.swarm');
286
- if (!fs.existsSync(swarmDir))
287
- fs.mkdirSync(swarmDir, { recursive: true });
288
- const dbPath = path.join(swarmDir, 'attestation.db');
289
- const db = new Database(dbPath);
290
- const url = pathToFileURL(attestationFile).href;
291
- const mod = await import(url);
292
- const Ctor = mod.AttestationLog;
293
- if (typeof Ctor === 'function') {
294
- const inst = new Ctor({ db });
295
- attestationInst = inst;
296
- if (typeof reg.set === 'function')
297
- reg.set('attestationLog', inst);
298
- else
299
- reg._controllers = { ...(reg._controllers || {}), attestationLog: inst };
300
- }
301
- }
302
- }
303
- catch { /* better-sqlite3 missing or schema init failed — skip silently */ }
304
- }
305
- // ADR-095 G7 follow-up: GuardedVectorBackend wraps the
306
- // existing vectorBackend with mutationGuard + attestationLog
307
- // for proof-gated state mutations (ADR-060). All three
308
- // dependencies are reachable here — vectorBackend is in
309
- // the baseline init, mutationGuard was just activated, and
310
- // attestationLog is constructed above. Skip if any piece
311
- // is missing rather than constructing with undefined.
312
- if (!reg.get('guardedVectorBackend')) {
313
- try {
314
- const gvbFile = path.join(adbDir, 'dist/src/backends/ruvector/GuardedVectorBackend.js');
315
- if (fs.existsSync(gvbFile)) {
316
- const inner = reg.get('vectorBackend');
317
- const guard = reg.get('mutationGuard');
318
- const log = attestationInst ?? reg.get('attestationLog');
319
- if (inner && guard) {
320
- const url = pathToFileURL(gvbFile).href;
321
- const mod = await import(url);
322
- const Ctor = mod.GuardedVectorBackend;
323
- if (typeof Ctor === 'function') {
324
- const inst = new Ctor(inner, guard, log);
325
- if (typeof reg.set === 'function')
326
- reg.set('guardedVectorBackend', inst);
327
- else
328
- reg._controllers = { ...(reg._controllers || {}), guardedVectorBackend: inst };
329
- }
330
- }
331
- }
332
- }
333
- catch { /* GuardedVectorBackend optional */ }
334
- }
335
- }
336
- }
337
- catch { /* G7 wiring optional */ }
338
- })();
339
- // Run both in parallel; settle either way so a single failing
340
- // path doesn't tear down the rest of the post-init wiring.
341
- await Promise.allSettled([intelligencePromise, agentdbPromise]);
342
- // Remaining disabled controllers tracked in ADR-095 G7 for
343
- // per-controller activation ADRs:
344
- // - graphAdapter (graph DB adapter — needs graph DB connection)
345
- }
346
- catch {
347
- // Top-level catch — registry stays usable even if post-init wiring fails wholesale.
348
- }
349
- registryInstance = registry;
350
- bridgeAvailable = true;
351
- return registry;
352
- }
353
- catch {
354
- bridgeAvailable = false;
355
- registryPromise = null;
356
- return null;
357
- }
358
- })();
359
- }
360
- return registryPromise;
361
- }
362
- // ===== Phase 2: BM25 hybrid scoring =====
363
- /**
364
- * BM25 scoring for keyword-based search.
365
- * Replaces naive String.includes() with proper information retrieval scoring.
366
- * Parameters tuned for short memory entries (k1=1.2, b=0.75).
367
- */
368
- function bm25Score(queryTerms, docWords, docLength, avgDocLength, docCount, termDocFreqs) {
369
- const k1 = 1.2;
370
- const b = 0.75;
371
- let score = 0;
372
- for (const term of queryTerms) {
373
- const tf = docWords.filter(w => w === term || w.includes(term)).length;
374
- if (tf === 0)
375
- continue;
376
- const df = termDocFreqs.get(term) || 1;
377
- const idf = Math.log((docCount - df + 0.5) / (df + 0.5) + 1);
378
- const tfNorm = (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * (docLength / Math.max(1, avgDocLength))));
379
- score += idf * tfNorm;
380
- }
381
- return score;
382
- }
383
- function tokenizeCorpus(rows) {
384
- return rows.map(row => {
385
- const contentLower = (row.content || '').toLowerCase();
386
- return { contentLower, words: contentLower.split(/\s+/) };
387
- });
388
- }
389
- /**
390
- * Compute BM25 term document frequencies over an already-tokenized corpus.
391
- */
392
- function computeTermDocFreqs(queryTerms, docs) {
393
- const termDocFreqs = new Map();
394
- let totalLength = 0;
395
- for (const doc of docs) {
396
- totalLength += doc.words.length;
397
- for (const term of queryTerms) {
398
- if (doc.contentLower.includes(term)) {
399
- termDocFreqs.set(term, (termDocFreqs.get(term) || 0) + 1);
400
- }
401
- }
402
- }
403
- return { termDocFreqs, avgDocLength: docs.length > 0 ? totalLength / docs.length : 1 };
404
- }
405
- // ===== Phase 2: TieredCache helpers =====
406
- /**
407
- * Try to read from TieredCache before hitting DB.
408
- * Returns cached value or null if cache miss.
409
- */
410
- async function cacheGet(registry, cacheKey) {
411
- try {
412
- const cache = registry.get('tieredCache');
413
- if (!cache || typeof cache.get !== 'function')
414
- return null;
415
- return cache.get(cacheKey) ?? null;
416
- }
417
- catch {
418
- return null;
419
- }
420
- }
421
- /**
422
- * Write to TieredCache after DB write.
423
- */
424
- async function cacheSet(registry, cacheKey, value) {
425
- try {
426
- const cache = registry.get('tieredCache');
427
- if (cache && typeof cache.set === 'function') {
428
- cache.set(cacheKey, value);
429
- }
430
- }
431
- catch {
432
- // Non-fatal
433
- }
434
- }
435
- /**
436
- * Invalidate a cache key after mutation.
437
- */
438
- async function cacheInvalidate(registry, cacheKey) {
439
- try {
440
- const cache = registry.get('tieredCache');
441
- if (cache && typeof cache.delete === 'function') {
442
- cache.delete(cacheKey);
443
- }
444
- }
445
- catch {
446
- // Non-fatal
447
- }
448
- }
449
- // ===== Phase 2: MutationGuard helpers =====
450
- /**
451
- * Validate a mutation through MutationGuard before executing.
452
- * Returns true if the mutation is allowed, false if rejected.
453
- * When guard is unavailable (not installed), mutations are allowed.
454
- * When guard is present but throws, mutations are DENIED (fail-closed).
455
- */
456
- async function guardValidate(registry, operation, params) {
457
- try {
458
- const guard = registry.get('mutationGuard');
459
- if (!guard || typeof guard.validate !== 'function') {
460
- return { allowed: true }; // No guard installed = allow (degraded mode)
461
- }
462
- const result = guard.validate({ operation, params, timestamp: Date.now() });
463
- return { allowed: result?.allowed === true, reason: result?.reason };
464
- }
465
- catch {
466
- return { allowed: false, reason: 'MutationGuard validation error' }; // Fail-closed
467
- }
468
- }
469
- // ===== Phase 3: AttestationLog helpers =====
470
- /**
471
- * Log a write operation to AttestationLog/WitnessChain.
472
- */
473
- async function logAttestation(registry, operation, entryId, metadata) {
474
- try {
475
- const attestation = registry.get('attestationLog');
476
- if (!attestation)
477
- return;
478
- if (typeof attestation.record === 'function') {
479
- attestation.record({ operation, entryId, timestamp: Date.now(), ...metadata });
480
- }
481
- else if (typeof attestation.log === 'function') {
482
- attestation.log(operation, entryId, metadata);
483
- }
484
- }
485
- catch {
486
- // Non-fatal — attestation is observability, not correctness
487
- }
488
- }
489
- // Tracks db handles whose schema DDL has already been ensured, so getDb()
490
- // runs the CREATE…IF NOT EXISTS block at most once per handle instead of on
491
- // every bridge call. WeakSet so handles GC without leaking.
492
- const _schemaEnsuredDbs = new WeakSet();
493
- /**
494
- * Get the AgentDB database handle and ensure memory_entries table exists.
495
- * Returns null if not available.
496
- */
497
- function getDb(registry) {
498
- const agentdb = registry.getAgentDB();
499
- if (!agentdb?.database)
500
- return null;
501
- const db = agentdb.database;
502
- // Ensure memory_entries table exists (idempotent). The DDL is run at most
503
- // once per db handle — re-parsing 4× CREATE…IF NOT EXISTS on every bridge
504
- // call (store/search/get) was pure per-op overhead. Keyed by handle via a
505
- // WeakSet so a new db instance re-ensures without a stale global flag.
506
- if (!_schemaEnsuredDbs.has(db)) {
507
- try {
508
- db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
509
- id TEXT PRIMARY KEY,
510
- key TEXT NOT NULL,
511
- namespace TEXT DEFAULT 'default',
512
- content TEXT NOT NULL,
513
- type TEXT DEFAULT 'semantic',
514
- embedding TEXT,
515
- embedding_model TEXT DEFAULT 'local',
516
- embedding_dimensions INTEGER,
517
- tags TEXT,
518
- metadata TEXT,
519
- owner_id TEXT,
520
- created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
521
- updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),
522
- expires_at INTEGER,
523
- last_accessed_at INTEGER,
524
- access_count INTEGER DEFAULT 0,
525
- status TEXT DEFAULT 'active',
526
- UNIQUE(namespace, key)
527
- )`);
528
- // Ensure indexes
529
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_ns ON memory_entries(namespace)`);
530
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_key ON memory_entries(key)`);
531
- db.exec(`CREATE INDEX IF NOT EXISTS idx_bridge_status ON memory_entries(status)`);
532
- _schemaEnsuredDbs.add(db);
533
- }
534
- catch {
535
- // Table already exists or db is read-only — that's fine. Don't mark
536
- // ensured on failure so a later writable call can retry.
537
- }
538
- }
539
- // ─── #2256-followup: rescue agentdb.embedder when its transformers.js
540
- // path fell through to mock embeddings.
541
- //
542
- // What was happening: agentdb's `EmbeddingService.initialize()` always
543
- // tries `@xenova/transformers` first, which transitively requires `sharp`
544
- // → `libvips`. On macOS arm64 systems without `brew install vips`, sharp
545
- // fails to load and agentdb silently falls back to MOCK EMBEDDINGS
546
- // (random vectors). The bridge then calls `agentdb.embedder.embed(...)`
547
- // and gets garbage; semantic search returns no useful matches.
548
- //
549
- // In our process, `memory-initializer.ts::loadEmbeddingModel()` already
550
- // tried this same chain and ALSO has a working ruvector-ONNX fallback
551
- // that the user typically reaches before the bridge initialises. The
552
- // ruvector ONNX model has been loaded; the agentdb instance just doesn't
553
- // know about it. We monkey-patch `embed`/`embedBatch` to delegate to our
554
- // `generateEmbedding()` so the bridge gets real vectors.
555
- //
556
- // Detection signal: `embedder.pipeline === null` after init means
557
- // transformers failed and agentdb would otherwise use mockEmbedding().
558
- // Patch is idempotent (`__ruvectorRescued` sentinel) and a no-op if
559
- // ruvector is also unavailable.
560
- rescueAgentdbEmbedder(agentdb).catch(() => { });
561
- return { db, agentdb };
562
- }
563
- // One-shot guard so we only patch once per process — the embedder is shared
564
- // by ReflexionMemory/SkillLibrary/CausalRecall and they all see the same
565
- // object reference.
566
- let _embedderPatched = false;
567
- async function rescueAgentdbEmbedder(agentdb) {
568
- if (_embedderPatched)
569
- return;
570
- const emb = agentdb?.embedder;
571
- if (!emb || emb.__ruvectorRescued)
572
- return;
573
- // Only rescue when transformers.js initialisation failed: that's
574
- // signalled by a null pipeline. If transformers IS working, agentdb's
575
- // own embed() does the right thing and we should not interpose.
576
- if (emb.pipeline)
577
- return;
578
- let localEmbed = null;
579
- try {
580
- const mod = (await import('./memory-initializer.js'));
581
- localEmbed = mod.generateLocalEmbedding ?? null;
582
- }
583
- catch {
584
- return; // can't import the rescuer — leave the mock fallback alone
585
- }
586
- if (!localEmbed)
587
- return;
588
- const embed = localEmbed;
589
- // Probe once to confirm the rescuer actually returns REAL ONNX vectors
590
- // (#2312: the old probe only checked non-zero, which the deterministic
591
- // hash fallback also satisfies — so it "rescued" agentdb's mock with our
592
- // own mock and reported it as real). Require backend === 'onnx'.
593
- try {
594
- const probe = await embed('rescue-probe');
595
- const arr = probe?.embedding ? Array.from(probe.embedding) : [];
596
- const hasSignal = arr.length > 0 && arr.some((v) => Math.abs(v) > 1e-9);
597
- if (!hasSignal || probe.backend !== 'onnx') {
598
- // Local chain is also degraded — leave agentdb's embedder alone, but
599
- // tag it so bridgeGenerateEmbedding's AUDIT-#3 isMock check reports
600
- // backend='mock' truthfully instead of labeling mock vectors 'onnx'.
601
- try {
602
- emb.backend = 'mock';
603
- }
604
- catch { /* frozen */ }
605
- return;
606
- }
607
- }
608
- catch {
609
- return;
610
- }
611
- const newEmbed = async (text) => {
612
- const out = await embed(text);
613
- return out.embedding instanceof Float32Array
614
- ? out.embedding
615
- : new Float32Array(out.embedding ?? []);
616
- };
617
- emb.embed = newEmbed;
618
- emb.embedBatch = async (texts) => Promise.all(texts.map(t => newEmbed(t)));
619
- emb.__ruvectorRescued = true;
620
- _embedderPatched = true;
621
- }
622
- // ===== Bridge functions — match memory-initializer.ts signatures =====
623
- /**
624
- * Store an entry via AgentDB v3.
625
- * Phase 2-5: Routes through MutationGuard → TieredCache → DB → AttestationLog.
626
- * Returns null to signal fallback to sql.js.
627
- */
628
- export async function bridgeStoreEntry(options) {
629
- const registry = await getRegistry(options.dbPath);
630
- if (!registry)
631
- return null;
632
- const ctx = getDb(registry);
633
- if (!ctx)
634
- return null;
635
- try {
636
- const { key, value, namespace = 'default', tags = [], ttl } = options;
637
- const id = generateId('entry');
638
- const now = Date.now();
639
- // #2245 — record the activity so signalsProcessed stops being a dead
640
- // zero. Fire-and-forget; never blocks the write path.
641
- try {
642
- const intel = await import('./intelligence.js');
643
- intel.recordSignalProcessed();
644
- }
645
- catch { /* intelligence module not yet initialised */ }
646
- // Phase 5: MutationGuard validation before write
647
- const guardResult = await guardValidate(registry, 'store', { key, namespace, size: value.length });
648
- if (!guardResult.allowed) {
649
- return { success: false, id, error: `MutationGuard rejected: ${guardResult.reason}` };
650
- }
651
- // Generate embedding via AgentDB's embedder
652
- let embeddingJson = null;
653
- let embeddingArr = null;
654
- let dimensions = 0;
655
- let model = 'local';
656
- if (options.generateEmbeddingFlag !== false && value.length > 0) {
657
- try {
658
- const embedder = ctx.agentdb.embedder;
659
- if (embedder) {
660
- const emb = await embedder.embed(value);
661
- if (emb) {
662
- embeddingArr = Array.from(emb);
663
- embeddingJson = JSON.stringify(embeddingArr);
664
- dimensions = emb.length;
665
- model = 'Xenova/all-MiniLM-L6-v2';
666
- }
667
- }
668
- }
669
- catch {
670
- // Embedding failed — store without
671
- }
672
- }
673
- // better-sqlite3 uses synchronous .run() with positional params
674
- const insertSql = options.upsert
675
- ? `INSERT OR REPLACE INTO memory_entries (
676
- id, key, namespace, content, type,
677
- embedding, embedding_dimensions, embedding_model,
678
- tags, metadata, created_at, updated_at, expires_at, status
679
- ) VALUES (?, ?, ?, ?, 'semantic', ?, ?, ?, ?, ?, ?, ?, ?, 'active')`
680
- : `INSERT INTO memory_entries (
681
- id, key, namespace, content, type,
682
- embedding, embedding_dimensions, embedding_model,
683
- tags, metadata, created_at, updated_at, expires_at, status
684
- ) VALUES (?, ?, ?, ?, 'semantic', ?, ?, ?, ?, ?, ?, ?, ?, 'active')`;
685
- // #1941: provision a `vector_indexes` row for this namespace before the
686
- // entry insert. AgentDB's HNSW/router keys lookups by namespace via this
687
- // table — if it has no row for e.g. `claude-memories`, `memory_search`
688
- // returns 0 results even when memory_entries holds hundreds of rows for
689
- // that namespace. INSERT OR IGNORE so existing index rows are preserved.
690
- try {
691
- ctx.db
692
- .prepare(`INSERT OR IGNORE INTO vector_indexes (id, name, dimensions) VALUES (?, ?, ?)`)
693
- .run(namespace, namespace, dimensions || 384);
694
- }
695
- catch { /* vector_indexes may not exist on legacy DBs — fall through */ }
696
- const stmt = ctx.db.prepare(insertSql);
697
- stmt.run(id, key, namespace, value, embeddingJson, dimensions || null, model, tags.length > 0 ? JSON.stringify(tags) : null, '{}', now, now, ttl ? now + (ttl * 1000) : null);
698
- // #2558: keep `vector_indexes.total_vectors` accurate so status/tooling
699
- // stop reporting "HNSW index: 0 vectors" while embedded entries exist.
700
- try {
701
- ctx.db
702
- .prepare(`UPDATE vector_indexes SET
703
- total_vectors = (SELECT COUNT(*) FROM memory_entries
704
- WHERE namespace = ? AND embedding IS NOT NULL),
705
- updated_at = ?
706
- WHERE name = ?`)
707
- .run(namespace, now, namespace);
708
- }
709
- catch { /* vector_indexes may not exist on legacy DBs — non-fatal */ }
710
- // #2558: better-sqlite3 opens the DB in WAL mode and, for the small write
711
- // volumes typical of CLI usage, may never reach the auto-checkpoint
712
- // threshold — leaving committed rows only in the -wal file. WAL-blind
713
- // readers (the sql.js fallback search path; the statusline's read-only
714
- // `sqlite3` vector count) then see a stale/empty main DB file and report
715
- // "0 vectors" / empty search. A PASSIVE checkpoint flushes committed pages
716
- // into the main file without blocking writers. Best-effort, never fatal.
717
- try {
718
- if (typeof ctx.db.pragma === 'function') {
719
- ctx.db.pragma('wal_checkpoint(PASSIVE)');
720
- }
721
- }
722
- catch { /* non-WAL, busy, or unsupported — non-fatal */ }
723
- // Phase 2: Write-through to TieredCache
724
- const safeNs = String(namespace).replace(/:/g, '_');
725
- const safeKey = String(key).replace(/:/g, '_');
726
- const cacheKey = `entry:${safeNs}:${safeKey}`;
727
- await cacheSet(registry, cacheKey, { id, key, namespace, content: value, embedding: embeddingJson });
728
- // Phase 4: AttestationLog write audit
729
- await logAttestation(registry, 'store', id, { key, namespace, hasEmbedding: !!embeddingJson });
730
- return {
731
- success: true,
732
- id,
733
- embedding: embeddingJson ? { dimensions, model } : undefined,
734
- rawEmbedding: embeddingArr ?? undefined,
735
- guarded: true,
736
- cached: true,
737
- attested: true,
738
- };
739
- }
740
- catch {
741
- return null;
742
- }
743
- }
744
- /**
745
- * Search entries via AgentDB v3.
746
- * Phase 2: BM25 hybrid scoring replaces naive String.includes() keyword fallback.
747
- * Combines cosine similarity (semantic) with BM25 (lexical) via reciprocal rank fusion.
748
- */
749
- export async function bridgeSearchEntries(options) {
750
- const registry = await getRegistry(options.dbPath);
751
- if (!registry)
752
- return null;
753
- const ctx = getDb(registry);
754
- if (!ctx)
755
- return null;
756
- try {
757
- const { query: queryStr, namespace, limit = 10, threshold = 0.3 } = options;
758
- const effectiveNamespace = namespace || 'all';
759
- const startTime = Date.now();
760
- // Generate query embedding
761
- let queryEmbedding = null;
762
- try {
763
- const embedder = ctx.agentdb.embedder;
764
- if (embedder) {
765
- const emb = await embedder.embed(queryStr);
766
- queryEmbedding = Array.from(emb);
767
- }
768
- }
769
- catch {
770
- // Fall back to keyword search
771
- }
772
- // better-sqlite3: .prepare().all() returns array of objects
773
- const nsFilter = effectiveNamespace !== 'all'
774
- ? `AND namespace = ?`
775
- : '';
776
- let rows;
777
- try {
778
- const stmt = ctx.db.prepare(`
779
- SELECT id, key, namespace, content, embedding
780
- FROM memory_entries
781
- WHERE status = 'active' ${nsFilter}
782
- LIMIT 1000
783
- `);
784
- rows = effectiveNamespace !== 'all' ? stmt.all(effectiveNamespace) : stmt.all();
785
- }
786
- catch {
787
- return null;
788
- }
789
- // Phase 2: Compute BM25 term stats for the corpus. Tokenize the corpus a
790
- // single time and reuse the per-doc `{contentLower, words}` for term-freq,
791
- // BM25 scoring, and the coverage floor below.
792
- const queryTerms = queryStr.toLowerCase().split(/\s+/).filter(t => t.length > 1);
793
- const docs = tokenizeCorpus(rows);
794
- const { termDocFreqs, avgDocLength } = computeTermDocFreqs(queryTerms, docs);
795
- const docCount = rows.length;
796
- const results = [];
797
- for (let i = 0; i < rows.length; i++) {
798
- const row = rows[i];
799
- const doc = docs[i];
800
- let semanticScore = 0;
801
- let bm25ScoreVal = 0;
802
- // Semantic scoring via cosine similarity
803
- if (queryEmbedding && row.embedding) {
804
- try {
805
- const embedding = JSON.parse(row.embedding);
806
- semanticScore = cosineSim(queryEmbedding, embedding);
807
- }
808
- catch {
809
- // Invalid embedding
810
- }
811
- }
812
- // Phase 2: BM25 keyword scoring (replaces String.includes fallback)
813
- if (queryTerms.length > 0 && row.content) {
814
- bm25ScoreVal = bm25Score(queryTerms, doc.words, doc.words.length, avgDocLength, docCount, termDocFreqs);
815
- // Normalize BM25 to 0-1 range (cap at 10 for normalization)
816
- bm25ScoreVal = Math.min(bm25ScoreVal / 10, 1.0);
817
- }
818
- // #2558: keyword-coverage floor for the lexical signal.
819
- // BM25's IDF collapses toward zero when a term appears in most/all
820
- // documents (routine on small memory corpora), and the /10 normalization
821
- // crushed exact-keyword hits well below the default 0.3 threshold — so
822
- // `memory search` recalled NOTHING even when the content literally
823
- // contained the query term (issue #2558: "keyword recall random"). The
824
- // pre-BM25 fallback guaranteed keyword recall via matchCount/words*0.5;
825
- // this restores that guarantee. `coverage` is the fraction of query
826
- // terms present in the document — a full-coverage hit must always be
827
- // recallable regardless of IDF.
828
- const contentLower = doc.contentLower;
829
- const matchedTerms = queryTerms.filter(t => contentLower.includes(t)).length;
830
- const coverage = queryTerms.length > 0 ? matchedTerms / queryTerms.length : 0;
831
- const lexicalScore = Math.max(bm25ScoreVal, coverage);
832
- // Recall-friendly fusion: a strong semantic OR lexical signal alone must
833
- // clear the threshold. `blended` (0.6 semantic + 0.4 lexical) drives
834
- // ranking; taking max() with the raw semantic score means (a) a genuinely
835
- // similar entry is never dropped just because it lacks the query's exact
836
- // words, and (b) a full-coverage keyword hit (lexical=1 → blended≥0.4) is
837
- // never dropped just because its embedding cosine is low or negative.
838
- const blended = 0.6 * Math.max(0, semanticScore) + 0.4 * lexicalScore;
839
- const score = Math.max(blended, semanticScore);
840
- if (score >= threshold) {
841
- // Phase 4: ExplainableRecall provenance
842
- const provenance = queryEmbedding
843
- ? `semantic:${semanticScore.toFixed(3)}+lexical:${lexicalScore.toFixed(3)}`
844
- : `lexical:${lexicalScore.toFixed(3)}`;
845
- results.push({
846
- id: String(row.id).substring(0, 12),
847
- key: row.key || String(row.id).substring(0, 15),
848
- content: (row.content || '').substring(0, 60) + ((row.content || '').length > 60 ? '...' : ''),
849
- score,
850
- namespace: row.namespace || 'default',
851
- provenance,
852
- });
853
- }
854
- }
855
- results.sort((a, b) => b.score - a.score);
856
- return {
857
- success: true,
858
- results: results.slice(0, limit),
859
- searchTime: Date.now() - startTime,
860
- searchMethod: queryEmbedding ? 'hybrid-bm25-semantic' : 'bm25-only',
861
- };
862
- }
863
- catch {
864
- return null;
865
- }
866
- }
867
- /**
868
- * List entries via AgentDB v3.
869
- */
870
- export async function bridgeListEntries(options) {
871
- const registry = await getRegistry(options.dbPath);
872
- if (!registry)
873
- return null;
874
- const ctx = getDb(registry);
875
- if (!ctx)
876
- return null;
877
- try {
878
- const { namespace, limit = 20, offset = 0 } = options;
879
- const nsFilter = namespace ? `AND namespace = ?` : '';
880
- const nsParams = namespace ? [namespace] : [];
881
- // #2120 — `status IS NULL` accepted alongside `'active'`. Old
882
- // databases imported by the auto-memory bridge (before the status
883
- // column existed) end up with NULL status after schema migration if
884
- // the migration ran on an existing DB without a backfill. Reporter
885
- // @alexandrelealbess on WSL2 had 251 entries with NULL status, so
886
- // the `status = 'active'` filter matched zero. Treat NULL as
887
- // "legacy-active" — the safe default for any entry that predates the
888
- // status column.
889
- const statusFilter = `(status = 'active' OR status IS NULL)`;
890
- // Count
891
- let total = 0;
892
- try {
893
- const countStmt = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE ${statusFilter} ${nsFilter}`);
894
- const countRow = countStmt.get(...nsParams);
895
- total = countRow?.cnt ?? 0;
896
- }
897
- catch {
898
- return null;
899
- }
900
- // List
901
- const entries = [];
902
- try {
903
- const stmt = ctx.db.prepare(`
904
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at
905
- FROM memory_entries
906
- WHERE ${statusFilter} ${nsFilter}
907
- ORDER BY updated_at DESC
908
- LIMIT ? OFFSET ?
909
- `);
910
- const rows = stmt.all(...nsParams, limit, offset);
911
- for (const row of rows) {
912
- const entry = {
913
- // #2073: don't truncate id when content is requested — callers
914
- // (notably memory_export) need the full id to round-trip via import.
915
- id: options.includeContent ? String(row.id) : String(row.id).substring(0, 20),
916
- key: row.key || String(row.id).substring(0, 15),
917
- namespace: row.namespace || 'default',
918
- size: (row.content || '').length,
919
- accessCount: row.access_count ?? 0,
920
- createdAt: row.created_at || new Date().toISOString(),
921
- updatedAt: row.updated_at || new Date().toISOString(),
922
- hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
923
- };
924
- if (options.includeContent) {
925
- entry.content = row.content || '';
926
- }
927
- entries.push(entry);
928
- }
929
- }
930
- catch {
931
- return null;
932
- }
933
- return { success: true, entries, total };
934
- }
935
- catch {
936
- return null;
937
- }
938
- }
939
- /**
940
- * Get a specific entry via AgentDB v3.
941
- * Phase 2: TieredCache consulted before DB hit.
942
- */
943
- export async function bridgeGetEntry(options) {
944
- const registry = await getRegistry(options.dbPath);
945
- if (!registry)
946
- return null;
947
- const ctx = getDb(registry);
948
- if (!ctx)
949
- return null;
950
- try {
951
- const { key, namespace = 'default' } = options;
952
- // Phase 2: Check TieredCache first
953
- const safeNs = String(namespace).replace(/:/g, '_');
954
- const safeKey = String(key).replace(/:/g, '_');
955
- const cacheKey = `entry:${safeNs}:${safeKey}`;
956
- const cached = await cacheGet(registry, cacheKey);
957
- if (cached && cached.content) {
958
- return {
959
- success: true,
960
- found: true,
961
- cacheHit: true,
962
- entry: {
963
- id: String(cached.id || ''),
964
- key: cached.key || key,
965
- namespace: cached.namespace || namespace,
966
- content: cached.content || '',
967
- accessCount: cached.accessCount ?? 0,
968
- createdAt: cached.createdAt || new Date().toISOString(),
969
- updatedAt: cached.updatedAt || new Date().toISOString(),
970
- hasEmbedding: !!cached.embedding,
971
- tags: cached.tags || [],
972
- },
973
- };
974
- }
975
- let row;
976
- try {
977
- const stmt = ctx.db.prepare(`
978
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
979
- FROM memory_entries
980
- WHERE status = 'active' AND key = ? AND namespace = ?
981
- LIMIT 1
982
- `);
983
- row = stmt.get(key, namespace);
984
- }
985
- catch {
986
- return null;
987
- }
988
- if (!row) {
989
- return { success: true, found: false };
990
- }
991
- // Update access count
992
- try {
993
- ctx.db.prepare(`UPDATE memory_entries SET access_count = access_count + 1, last_accessed_at = ? WHERE id = ?`).run(Date.now(), row.id);
994
- }
995
- catch {
996
- // Non-fatal
997
- }
998
- let tags = [];
999
- if (row.tags) {
1000
- try {
1001
- tags = JSON.parse(row.tags);
1002
- }
1003
- catch { /* invalid */ }
1004
- }
1005
- const entry = {
1006
- id: String(row.id),
1007
- key: row.key || String(row.id),
1008
- namespace: row.namespace || 'default',
1009
- content: row.content || '',
1010
- accessCount: (row.access_count ?? 0) + 1,
1011
- createdAt: row.created_at || new Date().toISOString(),
1012
- updatedAt: row.updated_at || new Date().toISOString(),
1013
- hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
1014
- tags,
1015
- };
1016
- // Phase 2: Populate cache for next read
1017
- await cacheSet(registry, cacheKey, entry);
1018
- return { success: true, found: true, cacheHit: false, entry };
1019
- }
1020
- catch {
1021
- return null;
1022
- }
1023
- }
1024
- /**
1025
- * Delete an entry via AgentDB v3.
1026
- * Phase 5: MutationGuard validation, cache invalidation, attestation logging.
1027
- */
1028
- export async function bridgeDeleteEntry(options) {
1029
- const registry = await getRegistry(options.dbPath);
1030
- if (!registry)
1031
- return null;
1032
- const ctx = getDb(registry);
1033
- if (!ctx)
1034
- return null;
1035
- try {
1036
- const { key, namespace = 'default' } = options;
1037
- // Phase 5: MutationGuard validation before delete
1038
- const guardResult = await guardValidate(registry, 'delete', { key, namespace });
1039
- if (!guardResult.allowed) {
1040
- return { success: false, deleted: false, key, namespace, remainingEntries: 0, error: `MutationGuard rejected: ${guardResult.reason}` };
1041
- }
1042
- // Soft delete using parameterized query
1043
- let changes = 0;
1044
- try {
1045
- const result = ctx.db.prepare(`
1046
- UPDATE memory_entries
1047
- SET status = 'deleted', updated_at = ?
1048
- WHERE key = ? AND namespace = ? AND status = 'active'
1049
- `).run(Date.now(), key, namespace);
1050
- changes = result?.changes ?? 0;
1051
- }
1052
- catch {
1053
- return null;
1054
- }
1055
- // Phase 2: Invalidate cache
1056
- const safeNs = String(namespace).replace(/:/g, '_');
1057
- const safeKey = String(key).replace(/:/g, '_');
1058
- await cacheInvalidate(registry, `entry:${safeNs}:${safeKey}`);
1059
- // Phase 4: AttestationLog delete audit
1060
- if (changes > 0) {
1061
- await logAttestation(registry, 'delete', key, { namespace });
1062
- }
1063
- let remaining = 0;
1064
- try {
1065
- const row = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`).get();
1066
- remaining = row?.cnt ?? 0;
1067
- }
1068
- catch {
1069
- // Non-fatal
1070
- }
1071
- return {
1072
- success: true,
1073
- deleted: changes > 0,
1074
- key,
1075
- namespace,
1076
- remainingEntries: remaining,
1077
- guarded: true,
1078
- };
1079
- }
1080
- catch {
1081
- return null;
1082
- }
1083
- }
1084
- // #2666 — Hard, namespace-scoped purge. bridgeDeleteEntry above only ever
1085
- // soft-deletes a single (namespace, key); this is a real
1086
- // `DELETE FROM memory_entries WHERE namespace = ?` against the live
1087
- // better-sqlite3-style handle, for callers (e.g. a plugin's index-reconcile
1088
- // step) that need a namespace to be genuinely empty rather than tombstoned.
1089
- // Irreversible — callers must gate this behind an explicit confirmation.
1090
- export async function bridgePurgeNamespace(options) {
1091
- const registry = await getRegistry(options.dbPath);
1092
- if (!registry)
1093
- return null;
1094
- const ctx = getDb(registry);
1095
- if (!ctx)
1096
- return null;
1097
- try {
1098
- const { namespace } = options;
1099
- const guardResult = await guardValidate(registry, 'purge', { namespace });
1100
- if (!guardResult.allowed) {
1101
- return { success: false, deletedCount: 0, remainingEntries: 0, error: `MutationGuard rejected: ${guardResult.reason}` };
1102
- }
1103
- let deletedCount = 0;
1104
- try {
1105
- const result = ctx.db.prepare(`DELETE FROM memory_entries WHERE namespace = ?`).run(namespace);
1106
- deletedCount = result?.changes ?? 0;
1107
- }
1108
- catch (e) {
1109
- return { success: false, deletedCount: 0, remainingEntries: 0, error: e instanceof Error ? e.message : String(e) };
1110
- }
1111
- const safeNs = String(namespace).replace(/:/g, '_');
1112
- await cacheInvalidate(registry, `namespace:${safeNs}`);
1113
- if (deletedCount > 0) {
1114
- await logAttestation(registry, 'purge', namespace, { namespace, deletedCount });
1115
- }
1116
- let remaining = 0;
1117
- try {
1118
- const row = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`).get();
1119
- remaining = row?.cnt ?? 0;
1120
- }
1121
- catch {
1122
- // Non-fatal
1123
- }
1124
- return {
1125
- success: true,
1126
- deletedCount,
1127
- remainingEntries: remaining,
1128
- guarded: true,
1129
- };
1130
- }
1131
- catch {
1132
- return null;
1133
- }
1134
- }
1135
- // ===== Phase 2: Embedding bridge =====
1136
- /**
1137
- * Generate embedding via AgentDB v3's embedder.
1138
- * Returns null if bridge unavailable — caller falls back to own ONNX/hash.
1139
- */
1140
- export async function bridgeGenerateEmbedding(text, dbPath) {
1141
- const registry = await getRegistry(dbPath);
1142
- if (!registry)
1143
- return null;
1144
- try {
1145
- const agentdb = registry.getAgentDB();
1146
- const embedder = agentdb?.embedder;
1147
- if (!embedder)
1148
- return null;
1149
- const emb = await embedder.embed(text);
1150
- if (!emb)
1151
- return null;
1152
- // AUDIT #3: surface backend truthfully. AgentDB's embedder is a real ONNX
1153
- // model when present; if it ever exposes a mock/stub signal, honor it.
1154
- const isMock = embedder.isMock === true
1155
- || embedder.backend === 'mock';
1156
- // #2395 — AgentDB's vectorBackend controller may initialize as
1157
- // `enabled: false` (e.g., ruvector isn't wired into its neural substrate
1158
- // yet) and silently fall back to a 128-dim hash stub. The embedder doesn't
1159
- // expose isMock=true in that path, so the wrapper above was reporting
1160
- // backend='onnx' on what's actually 128-dim hash garbage. The model name
1161
- // we hardcode ('Xenova/all-MiniLM-L6-v2') always produces 384-dim, so a
1162
- // dimensions mismatch is a definitive stub signal: return null and let
1163
- // the caller fall through to generateLocalEmbedding which routes to
1164
- // transformers.js / ruvector ONNX directly.
1165
- if (emb.length !== 384) {
1166
- return null;
1167
- }
1168
- return {
1169
- embedding: Array.from(emb),
1170
- dimensions: emb.length,
1171
- model: 'Xenova/all-MiniLM-L6-v2',
1172
- backend: isMock ? 'mock' : 'onnx',
1173
- };
1174
- }
1175
- catch {
1176
- return null;
1177
- }
1178
- }
1179
- /**
1180
- * Load embedding model via AgentDB v3 (it loads on init).
1181
- * Returns null if unavailable.
1182
- */
1183
- export async function bridgeLoadEmbeddingModel(dbPath) {
1184
- const startTime = Date.now();
1185
- const registry = await getRegistry(dbPath);
1186
- if (!registry)
1187
- return null;
1188
- try {
1189
- const agentdb = registry.getAgentDB();
1190
- const embedder = agentdb?.embedder;
1191
- if (!embedder)
1192
- return null;
1193
- // Verify embedder works by generating a test embedding
1194
- const test = await embedder.embed('test');
1195
- if (!test)
1196
- return null;
1197
- return {
1198
- success: true,
1199
- dimensions: test.length,
1200
- modelName: 'Xenova/all-MiniLM-L6-v2',
1201
- loadTime: Date.now() - startTime,
1202
- };
1203
- }
1204
- catch {
1205
- return null;
1206
- }
1207
- }
1208
- // ===== Phase 3: HNSW bridge =====
1209
- /**
1210
- * Get HNSW status from AgentDB v3's vector backend or HNSW index.
1211
- * Returns null if unavailable.
1212
- */
1213
- export async function bridgeGetHNSWStatus(dbPath) {
1214
- const registry = await getRegistry(dbPath);
1215
- if (!registry)
1216
- return null;
1217
- try {
1218
- const ctx = getDb(registry);
1219
- if (!ctx)
1220
- return null;
1221
- // Count entries with embeddings
1222
- let entryCount = 0;
1223
- try {
1224
- const row = ctx.db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND embedding IS NOT NULL`).get();
1225
- entryCount = row?.cnt ?? 0;
1226
- }
1227
- catch {
1228
- // Table might not exist
1229
- }
1230
- return {
1231
- available: true,
1232
- initialized: true,
1233
- entryCount,
1234
- dimensions: 384,
1235
- };
1236
- }
1237
- catch {
1238
- return null;
1239
- }
1240
- }
1241
- /**
1242
- * Search using AgentDB v3's embedder + SQLite entries.
1243
- * This is the HNSW-equivalent search through the bridge.
1244
- * Returns null if unavailable.
1245
- */
1246
- export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
1247
- const registry = await getRegistry(dbPath);
1248
- if (!registry)
1249
- return null;
1250
- const ctx = getDb(registry);
1251
- if (!ctx)
1252
- return null;
1253
- try {
1254
- const k = options?.k ?? 10;
1255
- const threshold = options?.threshold ?? 0.3;
1256
- const nsFilter = options?.namespace && options.namespace !== 'all'
1257
- ? `AND namespace = ?`
1258
- : '';
1259
- let rows;
1260
- try {
1261
- const stmt = ctx.db.prepare(`
1262
- SELECT id, key, namespace, content, embedding
1263
- FROM memory_entries
1264
- WHERE status = 'active' AND embedding IS NOT NULL ${nsFilter}
1265
- LIMIT 10000
1266
- `);
1267
- rows = nsFilter
1268
- ? stmt.all(options.namespace)
1269
- : stmt.all();
1270
- }
1271
- catch {
1272
- return null;
1273
- }
1274
- const results = [];
1275
- for (const row of rows) {
1276
- if (!row.embedding)
1277
- continue;
1278
- try {
1279
- const emb = JSON.parse(row.embedding);
1280
- const score = cosineSim(queryEmbedding, emb);
1281
- if (score >= threshold) {
1282
- results.push({
1283
- id: String(row.id).substring(0, 12),
1284
- key: row.key || String(row.id).substring(0, 15),
1285
- content: (row.content || '').substring(0, 60) +
1286
- ((row.content || '').length > 60 ? '...' : ''),
1287
- score,
1288
- namespace: row.namespace || 'default',
1289
- });
1290
- }
1291
- }
1292
- catch {
1293
- // Skip invalid embeddings
1294
- }
1295
- }
1296
- results.sort((a, b) => b.score - a.score);
1297
- return results.slice(0, k);
1298
- }
1299
- catch {
1300
- return null;
1301
- }
1302
- }
1303
- /**
1304
- * Add entry to the bridge's database with embedding.
1305
- * Returns null if unavailable.
1306
- */
1307
- export async function bridgeAddToHNSW(id, embedding, entry, dbPath) {
1308
- const registry = await getRegistry(dbPath);
1309
- if (!registry)
1310
- return null;
1311
- const ctx = getDb(registry);
1312
- if (!ctx)
1313
- return null;
1314
- try {
1315
- const now = Date.now();
1316
- const embeddingJson = JSON.stringify(embedding);
1317
- ctx.db.prepare(`
1318
- INSERT OR REPLACE INTO memory_entries (
1319
- id, key, namespace, content, type,
1320
- embedding, embedding_dimensions, embedding_model,
1321
- created_at, updated_at, status
1322
- ) VALUES (?, ?, ?, ?, 'semantic', ?, ?, 'Xenova/all-MiniLM-L6-v2', ?, ?, 'active')
1323
- `).run(id, entry.key, entry.namespace, entry.content, embeddingJson, embedding.length, now, now);
1324
- return true;
1325
- }
1326
- catch {
1327
- return null;
1328
- }
1329
- }
1330
- // ===== Phase 4: Controller access =====
1331
- /**
1332
- * Get a named controller from AgentDB v3 via ControllerRegistry.
1333
- * Returns null if unavailable.
1334
- */
1335
- export async function bridgeGetController(name, dbPath) {
1336
- const registry = await getRegistry(dbPath);
1337
- if (!registry)
1338
- return null;
1339
- try {
1340
- return registry.get(name) ?? null;
1341
- }
1342
- catch {
1343
- return null;
1344
- }
1345
- }
1346
- /**
1347
- * Check if a controller is available.
1348
- */
1349
- export async function bridgeHasController(name, dbPath) {
1350
- const registry = await getRegistry(dbPath);
1351
- if (!registry)
1352
- return false;
1353
- try {
1354
- const controller = registry.get(name);
1355
- return controller !== null && controller !== undefined;
1356
- }
1357
- catch {
1358
- return false;
1359
- }
1360
- }
1361
- /**
1362
- * List all controllers and their status.
1363
- */
1364
- export async function bridgeListControllers(dbPath) {
1365
- const registry = await getRegistry(dbPath);
1366
- if (!registry)
1367
- return null;
1368
- try {
1369
- return registry.listControllers();
1370
- }
1371
- catch {
1372
- return null;
1373
- }
1374
- }
1375
- /**
1376
- * Check if the AgentDB v3 bridge is available.
1377
- */
1378
- export async function isBridgeAvailable(dbPath) {
1379
- if (bridgeAvailable !== null)
1380
- return bridgeAvailable;
1381
- const registry = await getRegistry(dbPath);
1382
- return registry !== null;
1383
- }
1384
- /**
1385
- * Get the ControllerRegistry instance (for advanced consumers).
1386
- */
1387
- export async function getControllerRegistry(dbPath) {
1388
- return getRegistry(dbPath);
1389
- }
1390
- /**
1391
- * Shutdown the bridge and release resources.
1392
- */
1393
- export async function shutdownBridge() {
1394
- if (registryInstance) {
1395
- try {
1396
- await registryInstance.shutdown();
1397
- }
1398
- catch {
1399
- // Best-effort
1400
- }
1401
- registryInstance = null;
1402
- registryPromise = null;
1403
- bridgeAvailable = null;
1404
- }
1405
- }
1406
- // ===== Phase 3: ReasoningBank pattern operations =====
1407
- /**
1408
- * Store a pattern via ReasoningBank controller.
1409
- * Falls back to raw SQL if ReasoningBank unavailable.
1410
- */
1411
- export async function bridgeStorePattern(options) {
1412
- const registry = await getRegistry(options.dbPath);
1413
- if (!registry)
1414
- return null;
1415
- try {
1416
- const reasoningBank = registry.get('reasoningBank');
1417
- const patternId = generateId('pattern');
1418
- if (reasoningBank && typeof reasoningBank.store === 'function') {
1419
- await reasoningBank.store({
1420
- id: patternId,
1421
- content: options.pattern,
1422
- type: options.type,
1423
- confidence: options.confidence,
1424
- metadata: options.metadata,
1425
- timestamp: Date.now(),
1426
- });
1427
- return { success: true, patternId, controller: 'reasoningBank' };
1428
- }
1429
- // Fallback: store via bridge SQL
1430
- const patternValue = JSON.stringify({ pattern: options.pattern, type: options.type, confidence: options.confidence, metadata: options.metadata });
1431
- const result = await bridgeStoreEntry({
1432
- key: patternId,
1433
- value: patternValue,
1434
- namespace: 'pattern',
1435
- generateEmbeddingFlag: true,
1436
- tags: [options.type, 'reasoning-pattern'],
1437
- dbPath: options.dbPath,
1438
- });
1439
- if (!result)
1440
- return null;
1441
- // Add to HNSW index for fast semantic search (bridgeStoreEntry stores SQL only)
1442
- if (result.rawEmbedding) {
1443
- try {
1444
- const { addToHNSWIndex } = await import('./memory-initializer.js');
1445
- await addToHNSWIndex(result.id, result.rawEmbedding, {
1446
- id: result.id,
1447
- key: patternId,
1448
- namespace: 'pattern',
1449
- content: patternValue,
1450
- });
1451
- }
1452
- catch { /* HNSW is best-effort */ }
1453
- }
1454
- return { success: true, patternId: result.id, controller: 'bridge-fallback' };
1455
- }
1456
- catch {
1457
- return null;
1458
- }
1459
- }
1460
- /**
1461
- * Search patterns via ReasoningBank controller.
1462
- */
1463
- export async function bridgeSearchPatterns(options) {
1464
- const registry = await getRegistry(options.dbPath);
1465
- if (!registry)
1466
- return null;
1467
- try {
1468
- const reasoningBank = registry.get('reasoningBank');
1469
- // ReasoningBank may expose .searchPatterns() (agentdb) or .search() (legacy) (#1492 Bug 2)
1470
- if (reasoningBank && typeof (reasoningBank.searchPatterns ?? reasoningBank.search) === 'function') {
1471
- let results;
1472
- if (typeof reasoningBank.searchPatterns === 'function') {
1473
- results = await reasoningBank.searchPatterns({ task: options.query, k: options.topK || 5, threshold: options.minConfidence || 0.3 });
1474
- }
1475
- else {
1476
- results = await reasoningBank.search(options.query, { topK: options.topK || 5, minScore: options.minConfidence || 0.3 });
1477
- }
1478
- return {
1479
- results: Array.isArray(results) ? results.map((r) => ({
1480
- id: r.id || r.patternId || '',
1481
- content: r.content || r.pattern || '',
1482
- score: r.score ?? r.confidence ?? 0,
1483
- })) : [],
1484
- controller: 'reasoningBank',
1485
- };
1486
- }
1487
- // #2226 — the wired-in LocalReasoningBank implements store() + findSimilar()/getAll()
1488
- // but NOT searchPatterns()/search(). bridgeStorePattern commits patterns to its
1489
- // store(), so search MUST read the SAME backend or stored patterns are never found
1490
- // (previously search fell through to the disjoint sql.js 'pattern' namespace, which
1491
- // the store never wrote to → always-empty results). Adapt findSimilar (semantic) with
1492
- // a getAll() substring fallback so freshly-stored patterns are visible. This mirrors
1493
- // what hooks_intelligence_pattern-search already does against the same backend.
1494
- if (reasoningBank && typeof reasoningBank.findSimilar === 'function') {
1495
- const k = options.topK || 5;
1496
- const threshold = options.minConfidence ?? 0.3;
1497
- let mapped = [];
1498
- try {
1499
- const { generateEmbedding } = await import('./memory-initializer.js');
1500
- const qEmb = await generateEmbedding(options.query);
1501
- if (qEmb && Array.isArray(qEmb.embedding) && qEmb.embedding.length > 0) {
1502
- const hits = reasoningBank.findSimilar(qEmb.embedding, { k, threshold });
1503
- mapped = (Array.isArray(hits) ? hits : []).map((r) => ({
1504
- id: r.id ?? '',
1505
- content: r.content ?? '',
1506
- score: r.confidence ?? r.score ?? 0,
1507
- }));
1508
- }
1509
- }
1510
- catch { /* embedding unavailable — fall through to substring scan */ }
1511
- // Deterministic substring fallback over the same in-memory store.
1512
- if (mapped.length === 0 && typeof reasoningBank.getAll === 'function') {
1513
- const q = options.query.toLowerCase();
1514
- mapped = reasoningBank.getAll()
1515
- .filter((p) => typeof p.content === 'string' && p.content.toLowerCase().includes(q))
1516
- .slice(0, k)
1517
- .map((p) => ({ id: p.id ?? '', content: p.content ?? '', score: p.confidence ?? 0 }));
1518
- }
1519
- return { results: mapped, controller: 'reasoningBank' };
1520
- }
1521
- // Fallback: search via bridge
1522
- const result = await bridgeSearchEntries({
1523
- query: options.query,
1524
- namespace: 'pattern',
1525
- limit: options.topK || 5,
1526
- threshold: options.minConfidence || 0.3,
1527
- dbPath: options.dbPath,
1528
- });
1529
- return result ? {
1530
- results: result.results.map(r => ({ id: r.id, content: r.content, score: r.score })),
1531
- controller: 'bridge-fallback',
1532
- } : null;
1533
- }
1534
- catch {
1535
- return null;
1536
- }
1537
- }
1538
- // ===== Phase 3: Feedback recording =====
1539
- /**
1540
- * Record task feedback for learning via ReasoningBank or LearningSystem.
1541
- * Wired into hooks_post-task handler.
1542
- */
1543
- export async function bridgeRecordFeedback(options) {
1544
- const registry = await getRegistry(options.dbPath);
1545
- if (!registry)
1546
- return null;
1547
- try {
1548
- let controller = 'none';
1549
- let updated = 0;
1550
- // Try LearningSystem first (Phase 4)
1551
- const learningSystem = registry.get('learningSystem');
1552
- if (learningSystem) {
1553
- try {
1554
- if (typeof learningSystem.recordFeedback === 'function') {
1555
- await learningSystem.recordFeedback({
1556
- taskId: options.taskId, success: options.success, quality: options.quality,
1557
- agent: options.agent, duration: options.duration, timestamp: Date.now(),
1558
- // ADR-147 P2: forward spawn-tree lineage if present
1559
- parentAgentId: options.parentAgentId, depth: options.depth,
1560
- });
1561
- controller = 'learningSystem';
1562
- updated++;
1563
- }
1564
- else if (typeof learningSystem.record === 'function') {
1565
- await learningSystem.record(options.taskId, options.quality, options.success ? 'success' : 'failure');
1566
- controller = 'learningSystem';
1567
- updated++;
1568
- }
1569
- }
1570
- catch { /* API mismatch — skip */ }
1571
- }
1572
- // Also record in ReasoningBank for pattern reinforcement
1573
- const reasoningBank = registry.get('reasoningBank');
1574
- if (reasoningBank) {
1575
- try {
1576
- if (typeof reasoningBank.recordOutcome === 'function') {
1577
- await reasoningBank.recordOutcome({
1578
- taskId: options.taskId, verdict: options.success ? 'success' : 'failure',
1579
- score: options.quality, timestamp: Date.now(),
1580
- });
1581
- controller = controller === 'none' ? 'reasoningBank' : `${controller}+reasoningBank`;
1582
- updated++;
1583
- }
1584
- else if (typeof reasoningBank.record === 'function') {
1585
- await reasoningBank.record(options.taskId, options.quality);
1586
- controller = controller === 'none' ? 'reasoningBank' : `${controller}+reasoningBank`;
1587
- updated++;
1588
- }
1589
- }
1590
- catch { /* API mismatch — skip */ }
1591
- }
1592
- // Phase 4: SkillLibrary promotion for high-quality patterns
1593
- if (options.success && options.quality >= 0.9 && options.patterns?.length) {
1594
- const skills = registry.get('skills');
1595
- if (skills && typeof skills.promote === 'function') {
1596
- for (const pattern of options.patterns) {
1597
- try {
1598
- await skills.promote(pattern, options.quality);
1599
- updated++;
1600
- }
1601
- catch { /* skip */ }
1602
- }
1603
- controller += '+skills';
1604
- }
1605
- }
1606
- // Always store feedback as a memory entry for retrieval (ensures it persists)
1607
- const storeResult = await bridgeStoreEntry({
1608
- key: `feedback-${options.taskId}`,
1609
- value: JSON.stringify(options),
1610
- namespace: 'feedback',
1611
- tags: [options.success ? 'success' : 'failure', options.agent || 'unknown'],
1612
- dbPath: options.dbPath,
1613
- });
1614
- if (storeResult?.success) {
1615
- controller = controller === 'none' ? 'bridge-store' : `${controller}+bridge-store`;
1616
- updated++;
1617
- }
1618
- return { success: true, controller, updated };
1619
- }
1620
- catch {
1621
- return null;
1622
- }
1623
- }
1624
- // ===== Phase 3: CausalMemoryGraph =====
1625
- /**
1626
- * Record a causal edge between two entries (e.g., task → result).
1627
- */
1628
- export async function bridgeRecordCausalEdge(options) {
1629
- const registry = await getRegistry(options.dbPath);
1630
- if (!registry)
1631
- return null;
1632
- try {
1633
- const causalGraph = registry.get('causalGraph');
1634
- if (causalGraph && typeof causalGraph.addEdge === 'function') {
1635
- causalGraph.addEdge(options.sourceId, options.targetId, {
1636
- relation: options.relation,
1637
- weight: options.weight ?? 1.0,
1638
- timestamp: Date.now(),
1639
- });
1640
- return { success: true, controller: 'causalGraph' };
1641
- }
1642
- // Fallback: store edge as metadata
1643
- const ctx = getDb(registry);
1644
- if (ctx) {
1645
- try {
1646
- ctx.db.prepare(`
1647
- INSERT OR REPLACE INTO memory_entries (id, key, namespace, content, type, created_at, updated_at, status)
1648
- VALUES (?, ?, 'causal-edges', ?, 'procedural', ?, ?, 'active')
1649
- `).run(generateId('edge'), `${options.sourceId}→${options.targetId}`, JSON.stringify(options), Date.now(), Date.now());
1650
- return { success: true, controller: 'bridge-fallback' };
1651
- }
1652
- catch { /* skip */ }
1653
- }
1654
- return null;
1655
- }
1656
- catch {
1657
- return null;
1658
- }
1659
- }
1660
- // ===== #1784: Delete tools for hierarchical + causal-graph =====
1661
- /**
1662
- * Delete a hierarchical-memory entry by key (#1784).
1663
- *
1664
- * Reality check: agentdb's HierarchicalMemory class doesn't expose a public
1665
- * delete API today, so the real-backend path falls back to direct SQL on
1666
- * the underlying SQLite tables (status flip to 'deleted' + AttestationLog
1667
- * audit). The bridge-fallback path that bridgeHierarchicalStore uses when
1668
- * HierarchicalMemory isn't loaded writes plain memory_entries rows that
1669
- * `bridgeDeleteEntry` already handles.
1670
- *
1671
- * Returns { controller: 'native-unsupported' } when the real HM is loaded
1672
- * and the SQL fallback can't reach its private tables — surfacing the
1673
- * limitation honestly instead of silently returning success.
1674
- */
1675
- export async function bridgeDeleteHierarchical(options) {
1676
- const registry = await getRegistry(options.dbPath);
1677
- if (!registry)
1678
- return null;
1679
- try {
1680
- const { key, tier } = options;
1681
- // MutationGuard validation
1682
- const guardResult = await guardValidate(registry, 'delete', { key, namespace: 'hierarchical' });
1683
- if (!guardResult.allowed) {
1684
- return { success: false, deleted: false, key, tier, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
1685
- }
1686
- const hm = registry.get('hierarchicalMemory');
1687
- // 1. agentdb@3.0.0-alpha.13+: ReflexionMemory.deleteEpisode propagates through
1688
- // graph adapter / generic graph backend / vector backend AND purges SQL
1689
- // episodes + episode_embeddings rows. Single call, durably consistent.
1690
- // See agentic-flow#150/#151 (closes ruvnet/RuVector#427 the cli-visible way).
1691
- const reflexion = registry.get('reflexionMemory');
1692
- if (reflexion && typeof reflexion.deleteEpisode === 'function') {
1693
- try {
1694
- const removed = await reflexion.deleteEpisode(key);
1695
- if (removed) {
1696
- await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
1697
- return { success: true, deleted: true, key, tier, controller: 'reflexionMemory', guarded: true };
1698
- }
1699
- }
1700
- catch { /* fall through */ }
1701
- }
1702
- // 2. Try HierarchicalMemory's own delete API if it ever ships one.
1703
- if (hm && typeof hm.delete === 'function') {
1704
- try {
1705
- await hm.delete(key);
1706
- await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
1707
- return { success: true, deleted: true, key, tier, controller: 'hierarchicalMemory', guarded: true };
1708
- }
1709
- catch (err) {
1710
- // Fall through to SQL fallback
1711
- }
1712
- }
1713
- // 3. Stub HierarchicalMemory may expose `remove` or `forget`
1714
- if (hm && typeof hm.remove === 'function') {
1715
- try {
1716
- await hm.remove(key);
1717
- await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
1718
- return { success: true, deleted: true, key, tier, controller: 'hierarchicalMemory-stub', guarded: true };
1719
- }
1720
- catch { /* fall through */ }
1721
- }
1722
- // 3. Bridge-fallback: HM stored to memory_entries with namespace prefix
1723
- // (used when the real controller isn't loaded). Soft-delete via SQL.
1724
- const ctx = getDb(registry);
1725
- if (ctx) {
1726
- try {
1727
- const result = ctx.db.prepare(`
1728
- UPDATE memory_entries
1729
- SET status = 'deleted', updated_at = ?
1730
- WHERE key = ? AND namespace LIKE 'hierarchical%' AND status = 'active'
1731
- `).run(Date.now(), key);
1732
- const changes = result?.changes ?? 0;
1733
- if (changes > 0) {
1734
- await logAttestation(registry, 'delete', key, { namespace: 'hierarchical', tier });
1735
- return { success: true, deleted: true, key, tier, controller: 'bridge-fallback', guarded: true };
1736
- }
1737
- // Nothing to delete in SQL fallback — and no real-HM delete API.
1738
- // Surface the situation honestly.
1739
- return {
1740
- success: false, deleted: false, key, tier,
1741
- controller: hm ? 'native-unsupported' : 'not-found',
1742
- error: hm
1743
- ? 'HierarchicalMemory has no public delete API; entry remains in native storage'
1744
- : 'No hierarchical entry found with this key',
1745
- };
1746
- }
1747
- catch (err) {
1748
- return { success: false, deleted: false, key, tier, controller: 'sql-error', error: err.message };
1749
- }
1750
- }
1751
- return null;
1752
- }
1753
- catch {
1754
- return null;
1755
- }
1756
- }
1757
- /**
1758
- * Delete a causal edge between two memory entries (#1784).
1759
- *
1760
- * The bridge stores fallback edges in namespace='causal-edges' with key
1761
- * '{sourceId}→{targetId}'. Those CAN be soft-deleted. The native graph-node
1762
- * backend has no delete API (createNode/createEdge/createHyperedge only),
1763
- * so an edge that landed in graph-node native storage stays there. We
1764
- * surface that explicitly via controller: 'native-unsupported'.
1765
- */
1766
- export async function bridgeDeleteCausalEdge(options) {
1767
- const registry = await getRegistry(options.dbPath);
1768
- if (!registry)
1769
- return null;
1770
- try {
1771
- const { sourceId, targetId, relation } = options;
1772
- const edgeKey = `${sourceId}→${targetId}`;
1773
- const guardResult = await guardValidate(registry, 'delete', { key: edgeKey, namespace: 'causal-edges' });
1774
- if (!guardResult.allowed) {
1775
- return { success: false, deleted: false, sourceId, targetId, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
1776
- }
1777
- const causalGraph = registry.get('causalGraph');
1778
- // 1. agentdb@3.0.0-alpha.13+: GraphDatabaseAdapter.deleteEdgesByEndpoints
1779
- // handles the (sourceId, targetId, relation?) tuple case directly via
1780
- // Cypher MATCH … DETACH DELETE. Cypher-injection-safe (label validated
1781
- // against /^[A-Za-z_][A-Za-z0-9_]*$/ upstream).
1782
- if (causalGraph && typeof causalGraph.deleteEdgesByEndpoints === 'function') {
1783
- try {
1784
- const r = await causalGraph.deleteEdgesByEndpoints(sourceId, targetId, relation);
1785
- const deletedCount = typeof r === 'object' && r ? (r.deleted ?? 0) : (r ? 1 : 0);
1786
- if (deletedCount > 0) {
1787
- await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation, count: deletedCount });
1788
- return { success: true, deleted: true, sourceId, targetId, controller: 'causalGraph-cypher', guarded: true };
1789
- }
1790
- }
1791
- catch { /* fall through */ }
1792
- }
1793
- // 2. Pre-alpha.13 / different controller: try removeEdge() if exposed.
1794
- if (causalGraph && typeof causalGraph.removeEdge === 'function') {
1795
- try {
1796
- await causalGraph.removeEdge(sourceId, targetId, relation);
1797
- await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation });
1798
- return { success: true, deleted: true, sourceId, targetId, controller: 'causalGraph', guarded: true };
1799
- }
1800
- catch { /* fall through */ }
1801
- }
1802
- // 2. Bridge-fallback: soft-delete the memory_entries row.
1803
- const ctx = getDb(registry);
1804
- if (ctx) {
1805
- try {
1806
- const result = ctx.db.prepare(`
1807
- UPDATE memory_entries
1808
- SET status = 'deleted', updated_at = ?
1809
- WHERE key = ? AND namespace = 'causal-edges' AND status = 'active'
1810
- `).run(Date.now(), edgeKey);
1811
- const changes = result?.changes ?? 0;
1812
- if (changes > 0) {
1813
- await logAttestation(registry, 'delete', edgeKey, { namespace: 'causal-edges', relation });
1814
- return { success: true, deleted: true, sourceId, targetId, controller: 'bridge-fallback', guarded: true };
1815
- }
1816
- return {
1817
- success: false, deleted: false, sourceId, targetId,
1818
- controller: 'native-unsupported',
1819
- error: 'graph-node native backend has no delete API; edge cannot be removed from native storage. SQL fallback found no matching row.',
1820
- };
1821
- }
1822
- catch (err) {
1823
- return { success: false, deleted: false, sourceId, targetId, controller: 'sql-error', error: err.message };
1824
- }
1825
- }
1826
- return null;
1827
- }
1828
- catch {
1829
- return null;
1830
- }
1831
- }
1832
- /**
1833
- * Cascade-delete a causal node and all its incident edges (#1784).
1834
- *
1835
- * Same constraint as bridgeDeleteCausalEdge — native graph-node lacks a
1836
- * delete API. SQL fallback path soft-deletes the node (if stored as a
1837
- * memory_entries row) and every edge whose key contains the nodeId.
1838
- */
1839
- export async function bridgeDeleteCausalNode(options) {
1840
- const registry = await getRegistry(options.dbPath);
1841
- if (!registry)
1842
- return null;
1843
- try {
1844
- const { nodeId } = options;
1845
- const guardResult = await guardValidate(registry, 'delete', { key: nodeId, namespace: 'causal-nodes' });
1846
- if (!guardResult.allowed) {
1847
- return { success: false, deletedNode: false, deletedEdges: 0, nodeId, controller: 'guard', error: `MutationGuard rejected: ${guardResult.reason}` };
1848
- }
1849
- // 1. agentdb@3.0.0-alpha.13+: GraphDatabaseAdapter.deleteNode(id, {cascade})
1850
- // counts incident edges before delete so we get accurate audit numbers
1851
- // regardless of binding stats. Cypher MATCH (n {id}) DETACH DELETE n.
1852
- const causalGraph = registry.get('causalGraph');
1853
- if (causalGraph && typeof causalGraph.deleteNode === 'function') {
1854
- try {
1855
- const r = await causalGraph.deleteNode(nodeId, { cascade: true });
1856
- if (r && typeof r === 'object') {
1857
- const deletedNodeNative = !!r.deletedNode;
1858
- const deletedEdgesNative = typeof r.deletedEdges === 'number' ? r.deletedEdges : 0;
1859
- await logAttestation(registry, 'delete', nodeId, { namespace: 'causal-nodes', deletedEdges: deletedEdgesNative });
1860
- return {
1861
- success: true,
1862
- deletedNode: deletedNodeNative,
1863
- deletedEdges: deletedEdgesNative,
1864
- nodeId,
1865
- controller: 'causalGraph-cypher',
1866
- guarded: true,
1867
- };
1868
- }
1869
- }
1870
- catch { /* fall through to SQL */ }
1871
- }
1872
- // 2. SQL fallback: soft-delete the node row + every causal-edges row whose
1873
- // key contains nodeId on either side. Used when agentdb pre-alpha.13 OR
1874
- // when the entry was stored via the bridge's SQL fallback path.
1875
- const ctx = getDb(registry);
1876
- if (!ctx)
1877
- return null;
1878
- let deletedEdges = 0;
1879
- let deletedNode = false;
1880
- try {
1881
- const edgeResult = ctx.db.prepare(`
1882
- UPDATE memory_entries
1883
- SET status = 'deleted', updated_at = ?
1884
- WHERE namespace = 'causal-edges'
1885
- AND status = 'active'
1886
- AND (key LIKE ? OR key LIKE ?)
1887
- `).run(Date.now(), `${nodeId}→%`, `%→${nodeId}`);
1888
- deletedEdges = edgeResult?.changes ?? 0;
1889
- const nodeResult = ctx.db.prepare(`
1890
- UPDATE memory_entries
1891
- SET status = 'deleted', updated_at = ?
1892
- WHERE key = ? AND status = 'active'
1893
- `).run(Date.now(), nodeId);
1894
- deletedNode = (nodeResult?.changes ?? 0) > 0;
1895
- await logAttestation(registry, 'delete', nodeId, { namespace: 'causal-nodes', deletedEdges });
1896
- }
1897
- catch (err) {
1898
- return { success: false, deletedNode: false, deletedEdges: 0, nodeId, controller: 'sql-error', error: err.message };
1899
- }
1900
- return {
1901
- success: true,
1902
- deletedNode,
1903
- deletedEdges,
1904
- nodeId,
1905
- controller: 'bridge-fallback',
1906
- guarded: true,
1907
- };
1908
- }
1909
- catch {
1910
- return null;
1911
- }
1912
- }
1913
- // ===== Phase 5: ReflexionMemory session lifecycle =====
1914
- /**
1915
- * Start a session with ReflexionMemory episodic replay.
1916
- * Loads relevant past session patterns for the new session.
1917
- */
1918
- export async function bridgeSessionStart(options) {
1919
- const registry = await getRegistry(options.dbPath);
1920
- if (!registry)
1921
- return null;
1922
- try {
1923
- let restoredPatterns = 0;
1924
- let controller = 'none';
1925
- // Try ReflexionMemory for episodic session replay
1926
- const reflexion = registry.get('reflexion');
1927
- if (reflexion && typeof reflexion.startEpisode === 'function') {
1928
- await reflexion.startEpisode(options.sessionId, { context: options.context });
1929
- controller = 'reflexion';
1930
- }
1931
- // Load recent patterns from past sessions
1932
- const searchResult = await bridgeSearchEntries({
1933
- query: options.context || 'session patterns',
1934
- namespace: 'session',
1935
- limit: 10,
1936
- threshold: 0.2,
1937
- dbPath: options.dbPath,
1938
- });
1939
- if (searchResult?.results) {
1940
- restoredPatterns = searchResult.results.length;
1941
- }
1942
- return {
1943
- success: true,
1944
- controller: controller === 'none' ? 'bridge-search' : controller,
1945
- restoredPatterns,
1946
- sessionId: options.sessionId,
1947
- };
1948
- }
1949
- catch {
1950
- return null;
1951
- }
1952
- }
1953
- /**
1954
- * End a session and persist episodic summary to ReflexionMemory.
1955
- */
1956
- export async function bridgeSessionEnd(options) {
1957
- const registry = await getRegistry(options.dbPath);
1958
- if (!registry)
1959
- return null;
1960
- try {
1961
- let controller = 'none';
1962
- let persisted = false;
1963
- // End episode in ReflexionMemory
1964
- const reflexion = registry.get('reflexion');
1965
- if (reflexion && typeof reflexion.endEpisode === 'function') {
1966
- await reflexion.endEpisode(options.sessionId, {
1967
- summary: options.summary,
1968
- tasksCompleted: options.tasksCompleted,
1969
- patternsLearned: options.patternsLearned,
1970
- });
1971
- controller = 'reflexion';
1972
- persisted = true;
1973
- }
1974
- // Persist session summary as memory entry
1975
- await bridgeStoreEntry({
1976
- key: `session-${options.sessionId}`,
1977
- value: JSON.stringify({
1978
- sessionId: options.sessionId,
1979
- summary: options.summary || 'Session ended',
1980
- tasksCompleted: options.tasksCompleted ?? 0,
1981
- patternsLearned: options.patternsLearned ?? 0,
1982
- endedAt: new Date().toISOString(),
1983
- }),
1984
- namespace: 'session',
1985
- tags: ['session-end'],
1986
- upsert: true,
1987
- dbPath: options.dbPath,
1988
- });
1989
- if (controller === 'none')
1990
- controller = 'bridge-store';
1991
- persisted = true;
1992
- // Phase 3: Trigger NightlyLearner consolidation if available
1993
- const nightlyLearner = registry.get('nightlyLearner');
1994
- if (nightlyLearner && typeof nightlyLearner.consolidate === 'function') {
1995
- try {
1996
- await nightlyLearner.consolidate({ sessionId: options.sessionId });
1997
- controller += '+nightlyLearner';
1998
- }
1999
- catch { /* non-fatal */ }
2000
- }
2001
- return { success: true, controller, persisted };
2002
- }
2003
- catch {
2004
- return null;
2005
- }
2006
- }
2007
- // ===== Phase 5: SemanticRouter bridge =====
2008
- /**
2009
- * Route a task via AgentDB's SemanticRouter.
2010
- * Returns null to fall back to local ruvector router.
2011
- */
2012
- export async function bridgeRouteTask(options) {
2013
- const registry = await getRegistry(options.dbPath);
2014
- if (!registry)
2015
- return null;
2016
- try {
2017
- // Try AgentDB's SemanticRouter
2018
- const semanticRouter = registry.get('semanticRouter');
2019
- if (semanticRouter && typeof semanticRouter.route === 'function') {
2020
- const result = await semanticRouter.route(options.task, { context: options.context });
2021
- if (result) {
2022
- return {
2023
- route: result.route || result.category || 'general',
2024
- confidence: result.confidence ?? result.score ?? 0.5,
2025
- agents: result.agents || result.suggestedAgents || [],
2026
- controller: 'semanticRouter',
2027
- };
2028
- }
2029
- }
2030
- // Try LearningSystem recommendAlgorithm (Phase 4)
2031
- const learningSystem = registry.get('learningSystem');
2032
- if (learningSystem && typeof learningSystem.recommendAlgorithm === 'function') {
2033
- const rec = await learningSystem.recommendAlgorithm(options.task);
2034
- if (rec) {
2035
- return {
2036
- route: rec.algorithm || rec.route || 'general',
2037
- confidence: rec.confidence ?? 0.5,
2038
- agents: rec.agents || [],
2039
- controller: 'learningSystem',
2040
- };
2041
- }
2042
- }
2043
- return null; // Fall back to local router
2044
- }
2045
- catch {
2046
- return null;
2047
- }
2048
- }
2049
- // ===== Phase 4: Health check with attestation =====
2050
- /**
2051
- * Get comprehensive bridge health including all controller statuses.
2052
- */
2053
- export async function bridgeHealthCheck(dbPath) {
2054
- const registry = await getRegistry(dbPath);
2055
- if (!registry)
2056
- return null;
2057
- try {
2058
- const controllers = registry.listControllers();
2059
- // Phase 4: AttestationLog stats
2060
- let attestationCount = 0;
2061
- const attestation = registry.get('attestationLog');
2062
- if (attestation && typeof attestation.count === 'function') {
2063
- attestationCount = attestation.count();
2064
- }
2065
- // Phase 2: TieredCache stats
2066
- let cacheStats = { size: 0, hits: 0, misses: 0 };
2067
- const cache = registry.get('tieredCache');
2068
- if (cache && typeof cache.stats === 'function') {
2069
- const s = cache.stats();
2070
- cacheStats = { size: s.size ?? 0, hits: s.hits ?? 0, misses: s.misses ?? 0 };
2071
- }
2072
- return { available: true, controllers, attestationCount, cacheStats };
2073
- }
2074
- catch {
2075
- return null;
2076
- }
2077
- }
2078
- // ===== Phase 7: Hierarchical memory, consolidation, batch, context, semantic route =====
2079
- /**
2080
- * Store to hierarchical memory with tier.
2081
- * Valid tiers: working, episodic, semantic
2082
- *
2083
- * Real HierarchicalMemory API (agentdb alpha.10+):
2084
- * store(content, importance?, tier?, options?) → Promise<string>
2085
- * Fallback API (@claude-flow/memory TieredMemoryStore):
2086
- * store(key, value, tier, temporalOptions?) — synchronous, returns
2087
- * { id, key, tier, superseded? }
2088
- *
2089
- * Temporal validity (Zep/Graphiti-style, impl/memory-sota):
2090
- * - validFrom / validUntil (ISO) travel with the entry.
2091
- * - supersedes=<entryId|key> INVALIDATES the old entry (validUntil=now +
2092
- * supersededBy=newId) instead of deleting it. Natively supported by the
2093
- * TieredMemoryStore fallback; on the real agentdb HierarchicalMemory the
2094
- * temporal fields are stored in metadata, and supersede is reported as
2095
- * unsupported (no public update API) rather than silently dropped.
2096
- */
2097
- export async function bridgeHierarchicalStore(params) {
2098
- const registry = await getRegistry();
2099
- if (!registry)
2100
- return null;
2101
- try {
2102
- const hm = registry.get('hierarchicalMemory');
2103
- if (!hm)
2104
- return { success: false, error: 'HierarchicalMemory not available' };
2105
- const tier = params.tier || 'working';
2106
- // Detect real HierarchicalMemory (has async store returning id) vs stub
2107
- if (typeof hm.getStats === 'function' && typeof hm.promote === 'function') {
2108
- // Real agentdb HierarchicalMemory — temporal fields ride in metadata
2109
- // so bridgeHierarchicalRecall can filter on them.
2110
- const metadata = { key: params.key };
2111
- if (params.validFrom)
2112
- metadata.validFrom = params.validFrom;
2113
- if (params.validUntil)
2114
- metadata.validUntil = params.validUntil;
2115
- const id = await hm.store(params.value, params.importance || 0.5, tier, {
2116
- metadata,
2117
- tags: [params.key],
2118
- });
2119
- const result = { success: true, id, key: params.key, tier };
2120
- if (params.supersedes) {
2121
- // No public update/invalidate API on agentdb HierarchicalMemory —
2122
- // surface the limitation honestly instead of silently dropping it.
2123
- result.superseded = null;
2124
- result.warning = 'supersedes is not supported by the native agentdb HierarchicalMemory backend (no update API); the referenced entry was left untouched';
2125
- }
2126
- return result;
2127
- }
2128
- // TieredMemoryStore fallback (temporal-aware) / legacy stub
2129
- const storeResult = hm.store(params.key, params.value, tier, {
2130
- validFrom: params.validFrom,
2131
- validUntil: params.validUntil,
2132
- supersedes: params.supersedes,
2133
- });
2134
- if (storeResult && typeof storeResult === 'object') {
2135
- return { success: true, ...storeResult };
2136
- }
2137
- // Legacy stub (returns void) — temporal options were ignored
2138
- return { success: true, key: params.key, tier };
2139
- }
2140
- catch (e) {
2141
- return { success: false, error: e.message };
2142
- }
2143
- }
2144
- /**
2145
- * Recall from hierarchical memory.
2146
- *
2147
- * Real HierarchicalMemory API (agentdb alpha.10+):
2148
- * recall(query: MemoryQuery) → Promise<MemoryItem[]>
2149
- * where MemoryQuery = { query, tier?, k?, threshold?, context?, includeDecayed? }
2150
- * Stub API (fallback):
2151
- * recall(query: string, topK: number) → synchronous array
2152
- */
2153
- export async function bridgeHierarchicalRecall(params) {
2154
- const registry = await getRegistry();
2155
- if (!registry)
2156
- return null;
2157
- try {
2158
- const hm = registry.get('hierarchicalMemory');
2159
- if (!hm)
2160
- return { results: [], error: 'HierarchicalMemory not available' };
2161
- // Detect real HierarchicalMemory vs stub
2162
- if (typeof hm.getStats === 'function' && typeof hm.promote === 'function') {
2163
- // Real agentdb HierarchicalMemory — recall takes MemoryQuery object
2164
- const memoryQuery = {
2165
- query: params.query,
2166
- k: params.topK || 5,
2167
- };
2168
- if (params.tier) {
2169
- memoryQuery.tier = params.tier;
2170
- }
2171
- const results = await hm.recall(memoryQuery);
2172
- // Temporal filter over metadata (validFrom/validUntil stamped by
2173
- // bridgeHierarchicalStore). Entries without the fields are always
2174
- // valid — legacy behavior unchanged.
2175
- const filtered = params.includeExpired
2176
- ? (results || [])
2177
- : (results || []).filter((r) => {
2178
- const meta = r?.metadata || {};
2179
- const now = Date.now();
2180
- if (meta.validFrom) {
2181
- const from = Date.parse(String(meta.validFrom));
2182
- if (!Number.isNaN(from) && from > now)
2183
- return false;
2184
- }
2185
- if (meta.validUntil) {
2186
- const until = Date.parse(String(meta.validUntil));
2187
- if (!Number.isNaN(until) && until <= now)
2188
- return false;
2189
- }
2190
- return true;
2191
- });
2192
- return { results: filtered, controller: 'hierarchicalMemory' };
2193
- }
2194
- // TieredMemoryStore fallback — recall(string, number, options?).
2195
- // Temporal filtering happens inside the store; the legacy stub simply
2196
- // ignores the extra argument.
2197
- const results = hm.recall(params.query, params.topK || 5, {
2198
- includeExpired: params.includeExpired === true,
2199
- });
2200
- const filtered = params.tier
2201
- ? results.filter((r) => r.tier === params.tier)
2202
- : results;
2203
- return { results: filtered, controller: 'hierarchicalMemory' };
2204
- }
2205
- catch (e) {
2206
- return { results: [], error: e.message };
2207
- }
2208
- }
2209
- /**
2210
- * Run memory consolidation.
2211
- *
2212
- * Real MemoryConsolidation API (agentdb alpha.10+):
2213
- * consolidate() → Promise<ConsolidationReport>
2214
- * ConsolidationReport = { episodicProcessed, semanticCreated, memoriesForgotten, ... }
2215
- * Stub API (fallback):
2216
- * consolidate() → { promoted, pruned, timestamp }
2217
- */
2218
- export async function bridgeConsolidate(params) {
2219
- const registry = await getRegistry();
2220
- if (!registry)
2221
- return null;
2222
- try {
2223
- const mc = registry.get('memoryConsolidation');
2224
- if (!mc)
2225
- return { success: false, error: 'MemoryConsolidation not available' };
2226
- const result = await mc.consolidate();
2227
- return { success: true, consolidated: result };
2228
- }
2229
- catch (e) {
2230
- return { success: false, error: e.message };
2231
- }
2232
- }
2233
- /**
2234
- * Batch operations (insert, update, delete).
2235
- * - insert: calls insertEpisodes(entries) where entries are {content, metadata?}
2236
- * - delete: calls bulkDelete(table, conditions) on episodes table
2237
- * - update: calls bulkUpdate(table, updates, conditions) on episodes table
2238
- */
2239
- export async function bridgeBatchOperation(params) {
2240
- const registry = await getRegistry();
2241
- if (!registry)
2242
- return null;
2243
- try {
2244
- const batch = registry.get('batchOperations');
2245
- if (!batch)
2246
- return { success: false, error: 'BatchOperations not available' };
2247
- let result;
2248
- switch (params.operation) {
2249
- case 'insert': {
2250
- if (typeof batch.insertEpisodes !== 'function') {
2251
- return { success: false, error: 'BatchOperations.insertEpisodes not available — embedder may not be initialized. Use memory_store instead.' };
2252
- }
2253
- const episodes = params.entries.map((e) => ({
2254
- content: e.value || e.content || JSON.stringify(e),
2255
- metadata: e.metadata || { key: e.key },
2256
- }));
2257
- try {
2258
- result = await batch.insertEpisodes(episodes);
2259
- }
2260
- catch (insertErr) {
2261
- if (insertErr?.message?.includes('null') || insertErr?.message?.includes('embedBatch')) {
2262
- return { success: false, error: 'Embedder not initialized for batch insert. Use memory_store for individual entries or run embeddings_init first.' };
2263
- }
2264
- throw insertErr;
2265
- }
2266
- break;
2267
- }
2268
- case 'delete': {
2269
- // bulkDelete(table, conditions) — conditions is a WHERE clause object
2270
- const keys = params.entries.map((e) => e.key).filter(Boolean);
2271
- for (const key of keys) {
2272
- await batch.bulkDelete('episodes', { key });
2273
- }
2274
- result = { deleted: keys.length };
2275
- break;
2276
- }
2277
- case 'update': {
2278
- // bulkUpdate(table, updates, conditions)
2279
- for (const entry of params.entries) {
2280
- await batch.bulkUpdate('episodes', { content: entry.value || entry.content }, { key: entry.key });
2281
- }
2282
- result = { updated: params.entries.length };
2283
- break;
2284
- }
2285
- default: return { success: false, error: `Unknown operation: ${params.operation}` };
2286
- }
2287
- return { success: true, operation: params.operation, count: params.entries.length, result };
2288
- }
2289
- catch (e) {
2290
- return { success: false, error: e.message };
2291
- }
2292
- }
2293
- /**
2294
- * Synthesize context from memories.
2295
- * ContextSynthesizer.synthesize is a static method that takes MemoryPattern[] (not a string).
2296
- */
2297
- export async function bridgeContextSynthesize(params) {
2298
- const registry = await getRegistry();
2299
- if (!registry)
2300
- return null;
2301
- try {
2302
- const CS = registry.get('contextSynthesizer');
2303
- if (!CS || typeof CS.synthesize !== 'function') {
2304
- return { success: false, error: 'ContextSynthesizer not available' };
2305
- }
2306
- // Gather memory patterns from hierarchical memory as input
2307
- const hm = registry.get('hierarchicalMemory');
2308
- let memories = [];
2309
- if (hm && typeof hm.recall === 'function') {
2310
- // Detect real HierarchicalMemory (MemoryQuery object) vs stub (string, number)
2311
- let recalled;
2312
- if (typeof hm.promote === 'function') {
2313
- // Real agentdb HierarchicalMemory
2314
- recalled = await hm.recall({ query: params.query, k: params.maxEntries || 10 });
2315
- }
2316
- else {
2317
- // Stub
2318
- recalled = hm.recall(params.query, params.maxEntries || 10);
2319
- }
2320
- memories = (recalled || []).map((r) => ({
2321
- content: r.value || r.content || '',
2322
- key: r.key || r.id || '',
2323
- reward: 1,
2324
- verdict: 'success',
2325
- }));
2326
- }
2327
- const result = CS.synthesize(memories, { includeRecommendations: true });
2328
- return { success: true, synthesis: result };
2329
- }
2330
- catch (e) {
2331
- return { success: false, error: e.message };
2332
- }
2333
- }
2334
- /**
2335
- * Route via SemanticRouter.
2336
- * Available since agentdb 3.0.0-alpha.10 — uses @ruvector/router for
2337
- * semantic matching with keyword fallback.
2338
- */
2339
- export async function bridgeSemanticRoute(params) {
2340
- const registry = await getRegistry();
2341
- if (!registry)
2342
- return null;
2343
- try {
2344
- const router = registry.get('semanticRouter');
2345
- if (!router) {
2346
- // ADR-093 F9: surface an actionable error pointing callers at the
2347
- // alternative routing surfaces that DO work, instead of just
2348
- // saying "not available".
2349
- return {
2350
- route: null,
2351
- error: 'SemanticRouter not available in current agentdb build',
2352
- recommendation: 'Use bridgeRouteTask (registers as `agentdb_route` MCP tool) for keyword+pattern routing, or hooks_model-route for ADR-026 model selection.',
2353
- controller: 'none',
2354
- };
2355
- }
2356
- const result = await router.route(params.input);
2357
- return { route: result, controller: 'semanticRouter' };
2358
- }
2359
- catch (e) {
2360
- return { route: null, error: e.message, controller: 'error' };
2361
- }
2362
- }
2363
- // ===== RaBitQ data export =====
2364
- /**
2365
- * Export all embeddings from the bridge's better-sqlite3 connection.
2366
- * Used by RaBitQ to build its index from the same data that memory_store writes.
2367
- * Returns null if bridge is unavailable (caller falls back to sql.js).
2368
- */
2369
- export async function bridgeGetAllEmbeddings(options) {
2370
- const registry = await getRegistry(options?.dbPath);
2371
- if (!registry)
2372
- return null;
2373
- const ctx = getDb(registry);
2374
- if (!ctx)
2375
- return null;
2376
- try {
2377
- const dims = options?.dimensions ?? 384;
2378
- const maxRows = options?.limit ?? 50000;
2379
- const rows = ctx.db.prepare(`
2380
- SELECT id, key, namespace, embedding
2381
- FROM memory_entries
2382
- WHERE status = 'active' AND embedding IS NOT NULL
2383
- LIMIT ?
2384
- `).all(maxRows);
2385
- const results = [];
2386
- for (const row of rows) {
2387
- if (!row.embedding)
2388
- continue;
2389
- try {
2390
- const emb = JSON.parse(row.embedding);
2391
- if (emb.length !== dims)
2392
- continue;
2393
- results.push({
2394
- id: String(row.id),
2395
- key: row.key || String(row.id),
2396
- namespace: row.namespace || 'default',
2397
- embedding: emb,
2398
- });
2399
- }
2400
- catch { /* skip invalid */ }
2401
- }
2402
- return results;
2403
- }
2404
- catch {
2405
- return null;
2406
- }
2407
- }
2408
- // ===== Utility =====
2409
- function cosineSim(a, b) {
2410
- if (!a || !b || a.length === 0 || b.length === 0)
2411
- return 0;
2412
- const len = Math.min(a.length, b.length);
2413
- let dot = 0, normA = 0, normB = 0;
2414
- for (let i = 0; i < len; i++) {
2415
- const ai = a[i], bi = b[i];
2416
- dot += ai * bi;
2417
- normA += ai * ai;
2418
- normB += bi * bi;
2419
- }
2420
- const mag = Math.sqrt(normA * normB);
2421
- return mag === 0 ? 0 : dot / mag;
2422
- }
2423
- /**
2424
- * Public helper for the unified learning-stats aggregator: counts of entries
2425
- * per namespace + the top-level total. Best-effort — if the bridge isn't
2426
- * available it returns zeros so the aggregator can still report the other
2427
- * stores honestly. (#2245 follow-up.)
2428
- */
2429
- export async function getMemoryBridgeStats(options = {}) {
2430
- const namespaces = options.namespaces ?? [
2431
- 'default', 'patterns', 'claude-memories', 'auto-memory',
2432
- 'tasks', 'feedback', 'pretrain', 'trajectories',
2433
- ];
2434
- try {
2435
- const all = await bridgeListEntries({ dbPath: options.dbPath, limit: 1 });
2436
- if (!all) {
2437
- return { totalEntries: 0, perNamespace: {}, source: 'memory-bridge (unreachable)', reachable: false };
2438
- }
2439
- const perNamespace = {};
2440
- for (const ns of namespaces) {
2441
- try {
2442
- const r = await bridgeListEntries({ namespace: ns, dbPath: options.dbPath, limit: 1 });
2443
- const n = r?.total ?? 0;
2444
- if (n > 0)
2445
- perNamespace[ns] = n;
2446
- }
2447
- catch { /* skip per-namespace failure */ }
2448
- }
2449
- return {
2450
- totalEntries: all.total,
2451
- perNamespace,
2452
- source: 'memory-bridge AgentDB (bridgeListEntries)',
2453
- reachable: true,
2454
- };
2455
- }
2456
- catch {
2457
- return { totalEntries: 0, perNamespace: {}, source: 'memory-bridge (error)', reachable: false };
2458
- }
2459
- }
2460
- //# sourceMappingURL=memory-bridge.js.map