@remnic/core 1.1.0 → 1.1.1

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 (287) hide show
  1. package/dist/access-audit.d.ts +56 -0
  2. package/dist/access-audit.js +9 -0
  3. package/dist/access-cli.js +62 -45
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +16 -9
  6. package/dist/access-http.js +25 -17
  7. package/dist/access-mcp.d.ts +16 -9
  8. package/dist/access-mcp.js +29 -7
  9. package/dist/access-schema.d.ts +124 -33
  10. package/dist/access-schema.js +5 -1
  11. package/dist/{access-service-HmO1Trrx.d.ts → access-service-Br8ZydTK.d.ts} +158 -63
  12. package/dist/access-service.d.ts +13 -6
  13. package/dist/access-service.js +22 -14
  14. package/dist/bootstrap.d.ts +6 -3
  15. package/dist/briefing.d.ts +1 -0
  16. package/dist/briefing.js +7 -6
  17. package/dist/buffer-surprise-report.d.ts +70 -0
  18. package/dist/buffer-surprise-report.js +7 -0
  19. package/dist/buffer-surprise-report.js.map +1 -0
  20. package/dist/buffer-surprise.d.ts +98 -0
  21. package/dist/buffer-surprise.js +11 -0
  22. package/dist/buffer-surprise.js.map +1 -0
  23. package/dist/buffer.d.ts +100 -2
  24. package/dist/buffer.js +1 -1
  25. package/dist/calibration.js +5 -5
  26. package/dist/causal-behavior.js +4 -4
  27. package/dist/causal-chain.js +2 -2
  28. package/dist/causal-consolidation.js +17 -16
  29. package/dist/causal-consolidation.js.map +1 -1
  30. package/dist/causal-retrieval.js +4 -4
  31. package/dist/causal-trajectory.js +1 -1
  32. package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
  33. package/dist/chunk-2LGMW3DJ.js.map +1 -0
  34. package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
  35. package/dist/chunk-3FPTCC3Z.js.map +1 -0
  36. package/dist/chunk-3GPTTA4J.js +57 -0
  37. package/dist/chunk-3GPTTA4J.js.map +1 -0
  38. package/dist/{chunk-44ICJRF3.js → chunk-3GXCSUXR.js} +4 -4
  39. package/dist/{chunk-ITRLGI2T.js → chunk-3OGMS3PE.js} +2 -2
  40. package/dist/chunk-54V4BZWP.js +139 -0
  41. package/dist/chunk-54V4BZWP.js.map +1 -0
  42. package/dist/chunk-5JRF2PZA.js +67 -0
  43. package/dist/chunk-5JRF2PZA.js.map +1 -0
  44. package/dist/chunk-64NJRYU2.js +332 -0
  45. package/dist/chunk-64NJRYU2.js.map +1 -0
  46. package/dist/{chunk-OIT5QGG4.js → chunk-6AUUAZEX.js} +72 -2
  47. package/dist/chunk-6AUUAZEX.js.map +1 -0
  48. package/dist/{chunk-ZVBB3T7V.js → chunk-7I7FKFZH.js} +24 -22
  49. package/dist/chunk-7I7FKFZH.js.map +1 -0
  50. package/dist/chunk-AJU4PJGY.js +126 -0
  51. package/dist/chunk-AJU4PJGY.js.map +1 -0
  52. package/dist/chunk-ASAITVLA.js +64 -0
  53. package/dist/chunk-ASAITVLA.js.map +1 -0
  54. package/dist/{chunk-3QHL5ABG.js → chunk-B5WXLVDY.js} +187 -6
  55. package/dist/chunk-B5WXLVDY.js.map +1 -0
  56. package/dist/{chunk-SYUK3VLY.js → chunk-BGJGXLZ7.js} +111 -2
  57. package/dist/{chunk-SYUK3VLY.js.map → chunk-BGJGXLZ7.js.map} +1 -1
  58. package/dist/{chunk-MBJHSA7F.js → chunk-BK2EFTE2.js} +258 -13
  59. package/dist/chunk-BK2EFTE2.js.map +1 -0
  60. package/dist/chunk-C4SQJZAF.js +486 -0
  61. package/dist/chunk-C4SQJZAF.js.map +1 -0
  62. package/dist/{chunk-6UJ47TVX.js → chunk-CUPFXL3J.js} +2 -2
  63. package/dist/chunk-DF3RVK3X.js +119 -0
  64. package/dist/chunk-DF3RVK3X.js.map +1 -0
  65. package/dist/{chunk-37UIFYWO.js → chunk-DFTTJYSO.js} +108 -9
  66. package/dist/chunk-DFTTJYSO.js.map +1 -0
  67. package/dist/chunk-DGVM5SFL.js +69 -0
  68. package/dist/chunk-DGVM5SFL.js.map +1 -0
  69. package/dist/chunk-EIR5VLIH.js +90 -0
  70. package/dist/chunk-EIR5VLIH.js.map +1 -0
  71. package/dist/{chunk-PAORGQRI.js → chunk-EPQJM2GC.js} +37 -23
  72. package/dist/chunk-EPQJM2GC.js.map +1 -0
  73. package/dist/{chunk-GV6NLQ4X.js → chunk-F5VP6YCB.js} +374 -16
  74. package/dist/chunk-F5VP6YCB.js.map +1 -0
  75. package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
  76. package/dist/chunk-FAAFWE4G.js.map +1 -0
  77. package/dist/{chunk-7WQ6SLIE.js → chunk-FVA6TGI3.js} +2 -2
  78. package/dist/chunk-GDFS42HT.js +206 -0
  79. package/dist/chunk-GDFS42HT.js.map +1 -0
  80. package/dist/{chunk-MVTHXUBX.js → chunk-GKFXUTJ2.js} +479 -20
  81. package/dist/chunk-GKFXUTJ2.js.map +1 -0
  82. package/dist/{chunk-NQEVYWX6.js → chunk-HK3FGIEW.js} +209 -5
  83. package/dist/chunk-HK3FGIEW.js.map +1 -0
  84. package/dist/chunk-IISBCCWR.js +52 -0
  85. package/dist/chunk-IISBCCWR.js.map +1 -0
  86. package/dist/{chunk-WBSAYXVI.js → chunk-INXV5JBT.js} +198 -42
  87. package/dist/chunk-INXV5JBT.js.map +1 -0
  88. package/dist/chunk-JBMSGZEQ.js +441 -0
  89. package/dist/chunk-JBMSGZEQ.js.map +1 -0
  90. package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
  91. package/dist/chunk-JXS5PDQ7.js.map +1 -0
  92. package/dist/{chunk-6LX5ORAS.js → chunk-KUB6JU6H.js} +4 -4
  93. package/dist/chunk-KVBLZUKV.js +173 -0
  94. package/dist/chunk-KVBLZUKV.js.map +1 -0
  95. package/dist/chunk-LBLXEFWK.js +51 -0
  96. package/dist/chunk-LBLXEFWK.js.map +1 -0
  97. package/dist/{chunk-3WHVNEN7.js → chunk-LTCGGW2D.js} +1 -1
  98. package/dist/chunk-LTCGGW2D.js.map +1 -0
  99. package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
  100. package/dist/chunk-NZLQTHS5.js.map +1 -0
  101. package/dist/chunk-PVPWZSSI.js +37 -0
  102. package/dist/chunk-PVPWZSSI.js.map +1 -0
  103. package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
  104. package/dist/chunk-RFYAYKTD.js +146 -0
  105. package/dist/chunk-RFYAYKTD.js.map +1 -0
  106. package/dist/{chunk-DHHP2Z4X.js → chunk-RGLL5SPU.js} +2 -2
  107. package/dist/{chunk-3SV6CQHO.js → chunk-S3EEFKNY.js} +101 -65
  108. package/dist/chunk-S3EEFKNY.js.map +1 -0
  109. package/dist/chunk-SOBJ6NEY.js +18 -0
  110. package/dist/chunk-SOBJ6NEY.js.map +1 -0
  111. package/dist/{chunk-JIU55F3X.js → chunk-SPI27QT6.js} +2 -2
  112. package/dist/chunk-TVVEYCNW.js +65 -0
  113. package/dist/chunk-TVVEYCNW.js.map +1 -0
  114. package/dist/chunk-ULYOGL6R.js +322 -0
  115. package/dist/chunk-ULYOGL6R.js.map +1 -0
  116. package/dist/{chunk-47UU5PU2.js → chunk-VBVG2M5G.js} +18 -3
  117. package/dist/chunk-VBVG2M5G.js.map +1 -0
  118. package/dist/{chunk-7ECD5ATE.js → chunk-VDX363PS.js} +2 -2
  119. package/dist/{chunk-DEPL3635.js → chunk-VYM3VWOF.js} +1432 -188
  120. package/dist/chunk-VYM3VWOF.js.map +1 -0
  121. package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
  122. package/dist/chunk-WCLICCGB.js.map +1 -0
  123. package/dist/{chunk-4LACOVZX.js → chunk-WVVA7F5A.js} +2 -2
  124. package/dist/chunk-X6GF3FX2.js +26 -0
  125. package/dist/chunk-X6GF3FX2.js.map +1 -0
  126. package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
  127. package/dist/{chunk-BLKTA7MM.js → chunk-YNQKWQT4.js} +50 -17
  128. package/dist/chunk-YNQKWQT4.js.map +1 -0
  129. package/dist/chunk-ZAIM4TUE.js +488 -0
  130. package/dist/chunk-ZAIM4TUE.js.map +1 -0
  131. package/dist/{chunk-N42IWANG.js → chunk-ZEM3OK2K.js} +2 -2
  132. package/dist/chunk-ZZTOURJI.js +91 -0
  133. package/dist/chunk-ZZTOURJI.js.map +1 -0
  134. package/dist/{cli-BneVIEvh.d.ts → cli-BkeRaYfk.d.ts} +2 -2
  135. package/dist/cli.d.ts +13 -6
  136. package/dist/cli.js +40 -29
  137. package/dist/config.js +1 -1
  138. package/dist/consolidation-operator.d.ts +41 -0
  139. package/dist/consolidation-operator.js +11 -0
  140. package/dist/consolidation-operator.js.map +1 -0
  141. package/dist/consolidation-provenance-check.d.ts +68 -0
  142. package/dist/consolidation-provenance-check.js +9 -0
  143. package/dist/consolidation-provenance-check.js.map +1 -0
  144. package/dist/consolidation-undo.d.ts +123 -0
  145. package/dist/consolidation-undo.js +426 -0
  146. package/dist/consolidation-undo.js.map +1 -0
  147. package/dist/{contradiction-scan-GR33PONM.js → contradiction-scan-E3GJTI4F.js} +43 -7
  148. package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
  149. package/dist/cross-namespace-budget.d.ts +133 -0
  150. package/dist/cross-namespace-budget.js +9 -0
  151. package/dist/cross-namespace-budget.js.map +1 -0
  152. package/dist/direct-answer-wiring.js +5 -70
  153. package/dist/direct-answer-wiring.js.map +1 -1
  154. package/dist/{engine-5TIQBYZR.js → engine-F3GOXGE5.js} +8 -7
  155. package/dist/engine-F3GOXGE5.js.map +1 -0
  156. package/dist/entity-retrieval.d.ts +1 -0
  157. package/dist/entity-retrieval.js +7 -6
  158. package/dist/explicit-capture.d.ts +6 -3
  159. package/dist/explicit-capture.js +2 -2
  160. package/dist/extraction-judge-telemetry.d.ts +113 -0
  161. package/dist/extraction-judge-telemetry.js +14 -0
  162. package/dist/extraction-judge-telemetry.js.map +1 -0
  163. package/dist/extraction-judge-training.d.ts +85 -0
  164. package/dist/extraction-judge-training.js +16 -0
  165. package/dist/extraction-judge-training.js.map +1 -0
  166. package/dist/extraction-judge.d.ts +124 -2
  167. package/dist/extraction-judge.js +11 -1
  168. package/dist/extraction.js +6 -5
  169. package/dist/fallback-llm.js +2 -2
  170. package/dist/graph-recall.d.ts +100 -0
  171. package/dist/graph-recall.js +8 -0
  172. package/dist/graph-recall.js.map +1 -0
  173. package/dist/graph-retrieval.d.ts +271 -0
  174. package/dist/graph-retrieval.js +21 -0
  175. package/dist/graph-retrieval.js.map +1 -0
  176. package/dist/importance.js +1 -1
  177. package/dist/index.d.ts +585 -20
  178. package/dist/index.js +503 -312
  179. package/dist/index.js.map +1 -1
  180. package/dist/memory-worth-bench.d.ts +51 -0
  181. package/dist/memory-worth-bench.js +131 -0
  182. package/dist/memory-worth-bench.js.map +1 -0
  183. package/dist/memory-worth-filter.d.ts +128 -0
  184. package/dist/memory-worth-filter.js +10 -0
  185. package/dist/memory-worth-filter.js.map +1 -0
  186. package/dist/memory-worth-outcomes.d.ts +118 -0
  187. package/dist/memory-worth-outcomes.js +9 -0
  188. package/dist/memory-worth-outcomes.js.map +1 -0
  189. package/dist/memory-worth.d.ts +102 -0
  190. package/dist/memory-worth.js +7 -0
  191. package/dist/memory-worth.js.map +1 -0
  192. package/dist/operator-toolkit.d.ts +40 -1
  193. package/dist/operator-toolkit.js +23 -14
  194. package/dist/{orchestrator-DRYA6_lW.d.ts → orchestrator-CmJ-NTdJ.d.ts} +233 -8
  195. package/dist/orchestrator.d.ts +6 -3
  196. package/dist/orchestrator.js +49 -39
  197. package/dist/page-versioning.d.ts +12 -1
  198. package/dist/page-versioning.js +5 -3
  199. package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
  200. package/dist/qmd-recall-cache.d.ts +1 -1
  201. package/dist/qmd.d.ts +5 -3
  202. package/dist/qmd.js +1 -1
  203. package/dist/reasoning-trace-recall.d.ts +90 -0
  204. package/dist/reasoning-trace-recall.js +13 -0
  205. package/dist/reasoning-trace-recall.js.map +1 -0
  206. package/dist/reasoning-trace-types.d.ts +54 -0
  207. package/dist/reasoning-trace-types.js +17 -0
  208. package/dist/reasoning-trace-types.js.map +1 -0
  209. package/dist/recall-audit-anomaly.d.ts +112 -0
  210. package/dist/recall-audit-anomaly.js +11 -0
  211. package/dist/recall-audit-anomaly.js.map +1 -0
  212. package/dist/recall-audit.js +5 -44
  213. package/dist/recall-audit.js.map +1 -1
  214. package/dist/recall-explain-renderer.d.ts +49 -0
  215. package/dist/recall-explain-renderer.js +18 -0
  216. package/dist/recall-explain-renderer.js.map +1 -0
  217. package/dist/recall-state.d.ts +12 -1
  218. package/dist/recall-state.js +1 -1
  219. package/dist/recall-xray-cli.d.ts +40 -0
  220. package/dist/recall-xray-cli.js +11 -0
  221. package/dist/recall-xray-cli.js.map +1 -0
  222. package/dist/recall-xray-renderer.d.ts +44 -0
  223. package/dist/recall-xray-renderer.js +18 -0
  224. package/dist/recall-xray-renderer.js.map +1 -0
  225. package/dist/recall-xray.d.ts +179 -0
  226. package/dist/recall-xray.js +13 -0
  227. package/dist/recall-xray.js.map +1 -0
  228. package/dist/resume-bundles.js +5 -5
  229. package/dist/retrieval-agents.d.ts +1 -1
  230. package/dist/retrieval-tiers.d.ts +17 -0
  231. package/dist/retrieval-tiers.js +9 -0
  232. package/dist/retrieval-tiers.js.map +1 -0
  233. package/dist/schemas.d.ts +287 -31
  234. package/dist/schemas.js +1 -1
  235. package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
  236. package/dist/semantic-consolidation.d.ts +2 -1
  237. package/dist/semantic-consolidation.js +21 -7
  238. package/dist/semantic-rule-promotion.js +7 -6
  239. package/dist/semantic-rule-verifier.js +7 -6
  240. package/dist/storage.d.ts +82 -1
  241. package/dist/storage.js +6 -5
  242. package/dist/summarizer.js +3 -3
  243. package/dist/temporal-supersession.d.ts +1 -0
  244. package/dist/tier-migration.d.ts +2 -1
  245. package/dist/types.d.ts +276 -2
  246. package/dist/types.js +1 -1
  247. package/dist/verified-recall.js +7 -6
  248. package/package.json +1 -1
  249. package/dist/chunk-37UIFYWO.js.map +0 -1
  250. package/dist/chunk-3QHL5ABG.js.map +0 -1
  251. package/dist/chunk-3SV6CQHO.js.map +0 -1
  252. package/dist/chunk-3WHVNEN7.js.map +0 -1
  253. package/dist/chunk-47UU5PU2.js.map +0 -1
  254. package/dist/chunk-6ZH4TU6I.js.map +0 -1
  255. package/dist/chunk-BLKTA7MM.js.map +0 -1
  256. package/dist/chunk-DEPL3635.js.map +0 -1
  257. package/dist/chunk-GV6NLQ4X.js.map +0 -1
  258. package/dist/chunk-J4IYOZZ5.js.map +0 -1
  259. package/dist/chunk-LAYN4LDC.js +0 -267
  260. package/dist/chunk-LAYN4LDC.js.map +0 -1
  261. package/dist/chunk-MBJHSA7F.js.map +0 -1
  262. package/dist/chunk-MTLYEMJB.js.map +0 -1
  263. package/dist/chunk-MVTHXUBX.js.map +0 -1
  264. package/dist/chunk-NQEVYWX6.js.map +0 -1
  265. package/dist/chunk-OIT5QGG4.js.map +0 -1
  266. package/dist/chunk-PAORGQRI.js.map +0 -1
  267. package/dist/chunk-QDYXG4CS.js.map +0 -1
  268. package/dist/chunk-QNJMBKFK.js.map +0 -1
  269. package/dist/chunk-UEYA6UC7.js.map +0 -1
  270. package/dist/chunk-UVJFDP7P.js +0 -202
  271. package/dist/chunk-UVJFDP7P.js.map +0 -1
  272. package/dist/chunk-WBSAYXVI.js.map +0 -1
  273. package/dist/chunk-ZVBB3T7V.js.map +0 -1
  274. package/dist/contradiction-scan-GR33PONM.js.map +0 -1
  275. /package/dist/{engine-5TIQBYZR.js.map → access-audit.js.map} +0 -0
  276. /package/dist/{chunk-44ICJRF3.js.map → chunk-3GXCSUXR.js.map} +0 -0
  277. /package/dist/{chunk-ITRLGI2T.js.map → chunk-3OGMS3PE.js.map} +0 -0
  278. /package/dist/{chunk-6UJ47TVX.js.map → chunk-CUPFXL3J.js.map} +0 -0
  279. /package/dist/{chunk-7WQ6SLIE.js.map → chunk-FVA6TGI3.js.map} +0 -0
  280. /package/dist/{chunk-6LX5ORAS.js.map → chunk-KUB6JU6H.js.map} +0 -0
  281. /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
  282. /package/dist/{chunk-DHHP2Z4X.js.map → chunk-RGLL5SPU.js.map} +0 -0
  283. /package/dist/{chunk-JIU55F3X.js.map → chunk-SPI27QT6.js.map} +0 -0
  284. /package/dist/{chunk-7ECD5ATE.js.map → chunk-VDX363PS.js.map} +0 -0
  285. /package/dist/{chunk-4LACOVZX.js.map → chunk-WVVA7F5A.js.map} +0 -0
  286. /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
  287. /package/dist/{chunk-N42IWANG.js.map → chunk-ZEM3OK2K.js.map} +0 -0
@@ -15,18 +15,29 @@ var sessionKeySchema = z.string().trim().min(1).max(512).optional();
15
15
  var idempotencyKeySchema = z.string().trim().min(1).max(256).optional();
16
16
  var dryRunSchema = z.boolean().optional();
17
17
  var schemaVersionSchema = z.number().int().optional();
18
+ var codingContextSchema = z.object({
19
+ projectId: z.string().trim().min(1, "codingContext.projectId is required").max(128),
20
+ branch: z.string().trim().max(256).nullable(),
21
+ rootPath: z.string().trim().min(1, "codingContext.rootPath is required").max(1024),
22
+ defaultBranch: z.string().trim().max(256).nullable()
23
+ }).nullable();
18
24
  var recallRequestSchema = z.object({
19
25
  query: z.string().min(1, "query is required"),
20
26
  sessionKey: sessionKeySchema,
21
27
  namespace: namespaceSchema,
22
28
  topK: z.number().int().min(0).max(200).optional(),
23
29
  mode: z.enum(["auto", "no_recall", "minimal", "full", "graph_mode"]).optional(),
24
- includeDebug: z.boolean().optional()
30
+ includeDebug: z.boolean().optional(),
31
+ codingContext: codingContextSchema.optional()
25
32
  });
26
33
  var recallExplainRequestSchema = z.object({
27
34
  sessionKey: sessionKeySchema,
28
35
  namespace: namespaceSchema
29
36
  });
37
+ var setCodingContextRequestSchema = z.object({
38
+ sessionKey: z.string().trim().min(1, "sessionKey is required").max(512),
39
+ codingContext: codingContextSchema
40
+ });
30
41
  var messageSchema = z.object({
31
42
  role: z.enum(["user", "assistant"]),
32
43
  content: z.string().min(1, "message content must be non-empty")
@@ -50,7 +61,8 @@ var categorySchema = z.enum([
50
61
  "moment",
51
62
  "skill",
52
63
  "rule",
53
- "procedure"
64
+ "procedure",
65
+ "reasoning_trace"
54
66
  ]).optional();
55
67
  var confidenceSchema = z.number().min(0).max(1).optional();
56
68
  var tagsSchema = z.array(z.string().max(256)).max(50).optional();
@@ -116,6 +128,7 @@ var daySummaryRequestSchema = z.object({
116
128
  var schemas = {
117
129
  recall: recallRequestSchema,
118
130
  recallExplain: recallExplainRequestSchema,
131
+ setCodingContext: setCodingContextRequestSchema,
119
132
  observe: observeRequestSchema,
120
133
  memoryStore: memoryStoreRequestSchema,
121
134
  suggestionSubmit: suggestionSubmitRequestSchema,
@@ -146,8 +159,10 @@ function validateRequest(schemaName, body) {
146
159
 
147
160
  export {
148
161
  formatZodError,
162
+ codingContextSchema,
149
163
  recallRequestSchema,
150
164
  recallExplainRequestSchema,
165
+ setCodingContextRequestSchema,
151
166
  observeRequestSchema,
152
167
  memoryStoreRequestSchema,
153
168
  suggestionSubmitRequestSchema,
@@ -158,4 +173,4 @@ export {
158
173
  daySummaryRequestSchema,
159
174
  validateRequest
160
175
  };
161
- //# sourceMappingURL=chunk-MTLYEMJB.js.map
176
+ //# sourceMappingURL=chunk-WCLICCGB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/access-schema.ts"],"sourcesContent":["// Request/response schema validation for the Remnic HTTP API.\n// Uses zod for runtime validation — returns structured 400 errors with\n// field-level detail so consumers get clear feedback on malformed requests.\n\nimport { z } from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Error formatting\n// ---------------------------------------------------------------------------\n\nexport interface SchemaValidationError {\n error: string;\n code: \"validation_error\";\n details: Array<{ field: string; message: string }>;\n}\n\nexport function formatZodError(error: z.ZodError): SchemaValidationError {\n return {\n error: \"request validation failed\",\n code: \"validation_error\",\n details: error.issues.map((issue) => ({\n field: issue.path.join(\".\") || \"(root)\",\n message: issue.message,\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Shared fields\n// ---------------------------------------------------------------------------\n\nconst namespaceSchema = z.string().trim().max(256).optional();\nconst sessionKeySchema = z.string().trim().min(1).max(512).optional();\nconst idempotencyKeySchema = z.string().trim().min(1).max(256).optional();\nconst dryRunSchema = z.boolean().optional();\nconst schemaVersionSchema = z.number().int().optional();\n\n// ---------------------------------------------------------------------------\n// Recall\n// ---------------------------------------------------------------------------\n\n/**\n * Coding-agent context (issue #569). Optional payload that connectors may\n * ship with a recall request so the project/branch namespace overlay\n * applies to that recall. All fields are validated per CLAUDE.md #51 —\n * empty-string projectId / rootPath is rejected, not silently accepted.\n */\nexport const codingContextSchema = z\n .object({\n projectId: z.string().trim().min(1, \"codingContext.projectId is required\").max(128),\n branch: z.string().trim().max(256).nullable(),\n rootPath: z.string().trim().min(1, \"codingContext.rootPath is required\").max(1024),\n defaultBranch: z.string().trim().max(256).nullable(),\n })\n .nullable();\n\nexport const recallRequestSchema = z.object({\n query: z.string().min(1, \"query is required\"),\n sessionKey: sessionKeySchema,\n namespace: namespaceSchema,\n topK: z.number().int().min(0).max(200).optional(),\n mode: z.enum([\"auto\", \"no_recall\", \"minimal\", \"full\", \"graph_mode\"]).optional(),\n includeDebug: z.boolean().optional(),\n codingContext: codingContextSchema.optional(),\n});\n\nexport const recallExplainRequestSchema = z.object({\n sessionKey: sessionKeySchema,\n namespace: namespaceSchema,\n});\n\n/**\n * Standalone \"set coding context\" request. Used by the HTTP endpoint\n * `POST /engram/v1/coding-context` and the MCP `remnic.set_coding_context`\n * tool (PR 7). `codingContext: null` clears the attached context.\n */\nexport const setCodingContextRequestSchema = z.object({\n sessionKey: z.string().trim().min(1, \"sessionKey is required\").max(512),\n codingContext: codingContextSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Observe\n// ---------------------------------------------------------------------------\n\nconst messageSchema = z.object({\n role: z.enum([\"user\", \"assistant\"]),\n content: z.string().min(1, \"message content must be non-empty\"),\n});\n\nexport const observeRequestSchema = z.object({\n sessionKey: z.string().trim().min(1, \"sessionKey is required\").max(512),\n messages: z.array(messageSchema).min(1, \"messages must be a non-empty array\"),\n namespace: namespaceSchema,\n skipExtraction: z.boolean().optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Memory store / suggestion submit\n// ---------------------------------------------------------------------------\n\nconst writeContentSchema = z.string().min(1, \"content is required\").max(50000);\nconst categorySchema = z\n .enum([\n \"fact\", \"preference\", \"correction\", \"entity\", \"decision\",\n \"relationship\", \"principle\", \"commitment\", \"moment\", \"skill\", \"rule\", \"procedure\",\n \"reasoning_trace\",\n ])\n .optional();\nconst confidenceSchema = z.number().min(0).max(1).optional();\nconst tagsSchema = z.array(z.string().max(256)).max(50).optional();\nconst entityRefSchema = z.string().trim().max(512).optional();\nconst ttlSchema = z.string().trim().max(128).optional();\nconst sourceReasonSchema = z.string().trim().max(2000).optional();\n\nexport const memoryStoreRequestSchema = z.object({\n schemaVersion: schemaVersionSchema,\n idempotencyKey: idempotencyKeySchema,\n dryRun: dryRunSchema,\n sessionKey: sessionKeySchema,\n content: writeContentSchema,\n category: categorySchema,\n confidence: confidenceSchema,\n namespace: namespaceSchema,\n tags: tagsSchema,\n entityRef: entityRefSchema,\n ttl: ttlSchema,\n sourceReason: sourceReasonSchema,\n});\n\nexport const suggestionSubmitRequestSchema = memoryStoreRequestSchema;\n\n// ---------------------------------------------------------------------------\n// Review disposition\n// ---------------------------------------------------------------------------\n\nexport const reviewDispositionRequestSchema = z.object({\n memoryId: z.string().trim().min(1, \"memoryId is required\"),\n status: z.enum([\n \"active\", \"pending_review\", \"quarantined\", \"rejected\", \"superseded\", \"archived\",\n ]),\n reasonCode: z.string().trim().min(1, \"reasonCode is required\"),\n namespace: namespaceSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Trust-zone promote\n// ---------------------------------------------------------------------------\n\nexport const trustZonePromoteRequestSchema = z.object({\n recordId: z.string().trim().min(1, \"recordId is required\"),\n targetZone: z.enum([\"working\", \"trusted\"], {\n errorMap: () => ({ message: \"targetZone must be 'working' or 'trusted'\" }),\n }),\n promotionReason: z.string().trim().min(1, \"promotionReason is required\"),\n recordedAt: z.string().trim().optional(),\n summary: z.string().trim().max(5000).optional(),\n dryRun: dryRunSchema,\n namespace: namespaceSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Trust-zone demo-seed\n// ---------------------------------------------------------------------------\n\nexport const trustZoneDemoSeedRequestSchema = z.object({\n scenario: z.string().trim().max(256).optional(),\n recordedAt: z.string().trim().optional(),\n dryRun: dryRunSchema,\n namespace: namespaceSchema,\n});\n\n// ---------------------------------------------------------------------------\n// LCM search\n// ---------------------------------------------------------------------------\n\nexport const lcmSearchRequestSchema = z.object({\n query: z.string().min(1, \"query is required\"),\n sessionKey: sessionKeySchema,\n namespace: namespaceSchema,\n limit: z.number().int().min(1).max(100).optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Day summary\n// ---------------------------------------------------------------------------\n\nexport const daySummaryRequestSchema = z.object({\n memories: z.string().max(100000).optional(),\n sessionKey: sessionKeySchema,\n namespace: namespaceSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Inferred types\n// ---------------------------------------------------------------------------\n\nexport type RecallRequest = z.infer<typeof recallRequestSchema>;\nexport type RecallExplainRequest = z.infer<typeof recallExplainRequestSchema>;\nexport type SetCodingContextRequest = z.infer<typeof setCodingContextRequestSchema>;\nexport type ObserveRequest = z.infer<typeof observeRequestSchema>;\nexport type MemoryStoreRequest = z.infer<typeof memoryStoreRequestSchema>;\nexport type SuggestionSubmitRequest = z.infer<typeof suggestionSubmitRequestSchema>;\nexport type ReviewDispositionRequest = z.infer<typeof reviewDispositionRequestSchema>;\nexport type TrustZonePromoteRequest = z.infer<typeof trustZonePromoteRequestSchema>;\nexport type TrustZoneDemoSeedRequest = z.infer<typeof trustZoneDemoSeedRequestSchema>;\nexport type LcmSearchRequest = z.infer<typeof lcmSearchRequestSchema>;\nexport type DaySummaryRequest = z.infer<typeof daySummaryRequestSchema>;\n\n// ---------------------------------------------------------------------------\n// Validation helper\n// ---------------------------------------------------------------------------\n\nexport type SchemaName =\n | \"recall\"\n | \"recallExplain\"\n | \"setCodingContext\"\n | \"observe\"\n | \"memoryStore\"\n | \"suggestionSubmit\"\n | \"reviewDisposition\"\n | \"trustZonePromote\"\n | \"trustZoneDemoSeed\"\n | \"lcmSearch\"\n | \"daySummary\";\n\nexport type SchemaTypeFor<N extends SchemaName> =\n N extends \"recall\" ? RecallRequest\n : N extends \"recallExplain\" ? RecallExplainRequest\n : N extends \"setCodingContext\" ? SetCodingContextRequest\n : N extends \"observe\" ? ObserveRequest\n : N extends \"memoryStore\" ? MemoryStoreRequest\n : N extends \"suggestionSubmit\" ? SuggestionSubmitRequest\n : N extends \"reviewDisposition\" ? ReviewDispositionRequest\n : N extends \"trustZonePromote\" ? TrustZonePromoteRequest\n : N extends \"trustZoneDemoSeed\" ? TrustZoneDemoSeedRequest\n : N extends \"lcmSearch\" ? LcmSearchRequest\n : N extends \"daySummary\" ? DaySummaryRequest\n : never;\n\nconst schemas: Record<SchemaName, z.ZodTypeAny> = {\n recall: recallRequestSchema,\n recallExplain: recallExplainRequestSchema,\n setCodingContext: setCodingContextRequestSchema,\n observe: observeRequestSchema,\n memoryStore: memoryStoreRequestSchema,\n suggestionSubmit: suggestionSubmitRequestSchema,\n reviewDisposition: reviewDispositionRequestSchema,\n trustZonePromote: trustZonePromoteRequestSchema,\n trustZoneDemoSeed: trustZoneDemoSeedRequestSchema,\n lcmSearch: lcmSearchRequestSchema,\n daySummary: daySummaryRequestSchema,\n};\n\n/**\n * Validate a request body against the named schema.\n * Returns `{ success: true, data }` on pass or\n * `{ success: false, error }` on failure with field-level detail.\n */\nexport function validateRequest<T = unknown>(\n schemaName: SchemaName,\n body: unknown,\n): { success: true; data: T } | { success: false; error: SchemaValidationError } {\n const schema = schemas[schemaName];\n if (!schema) {\n return {\n success: false,\n error: {\n error: `unknown schema: ${schemaName}`,\n code: \"validation_error\",\n details: [],\n },\n };\n }\n const result = schema.safeParse(body);\n if (result.success) {\n return { success: true, data: result.data as T };\n }\n return { success: false, error: formatZodError(result.error) };\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StorageManager
3
- } from "./chunk-GV6NLQ4X.js";
3
+ } from "./chunk-F5VP6YCB.js";
4
4
  import {
5
5
  log
6
6
  } from "./chunk-2ODBA7MQ.js";
@@ -810,4 +810,4 @@ export {
810
810
  resolveBriefingSaveDir,
811
811
  briefingFilename
812
812
  };
813
- //# sourceMappingURL=chunk-4LACOVZX.js.map
813
+ //# sourceMappingURL=chunk-WVVA7F5A.js.map
@@ -0,0 +1,26 @@
1
+ // src/consolidation-operator.ts
2
+ var CONSOLIDATION_OPERATORS = [
3
+ "split",
4
+ "merge",
5
+ "update"
6
+ ];
7
+ var DERIVED_FROM_ENTRY_RE = /^(.+):(\d+)$/;
8
+ function isValidDerivedFromEntry(entry) {
9
+ if (typeof entry !== "string") return false;
10
+ const match = entry.match(DERIVED_FROM_ENTRY_RE);
11
+ if (!match) return false;
12
+ const pathPart = match[1];
13
+ if (pathPart.length === 0 || pathPart.trim().length === 0) return false;
14
+ const versionNum = Number(match[2]);
15
+ return Number.isInteger(versionNum) && versionNum >= 0;
16
+ }
17
+ function isConsolidationOperator(value) {
18
+ return typeof value === "string" && CONSOLIDATION_OPERATORS.includes(value);
19
+ }
20
+
21
+ export {
22
+ CONSOLIDATION_OPERATORS,
23
+ isValidDerivedFromEntry,
24
+ isConsolidationOperator
25
+ };
26
+ //# sourceMappingURL=chunk-X6GF3FX2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/consolidation-operator.ts"],"sourcesContent":["/**\n * consolidation-operator.ts — Standalone operator vocabulary + validators\n * for the consolidation subsystem (issue #561, All-Mem paper\n * arxiv:2603.19595).\n *\n * This module is intentionally dependency-free so storage, the `remnic\n * doctor` check (PR 4), and the undo CLI (PR 5) can import the validators\n * without dragging in the full consolidation engine — which in turn pulls\n * in the Codex materialize runner and creates a `storage → consolidation\n * → codex-materialize-runner → storage` import cycle.\n *\n * The `semantic-consolidation.ts` module re-exports these symbols so\n * existing import paths continue to work.\n */\n\n/**\n * Operator algebra for non-destructive consolidation.\n *\n * - `split` — one source memory is rewritten as multiple smaller memories.\n * - `merge` — multiple source memories are collapsed into one canonical\n * memory.\n * - `update` — a newer value supersedes an older value within the same\n * logical fact.\n */\nexport type ConsolidationOperator = \"split\" | \"merge\" | \"update\";\n\n/**\n * Allowed values for the `derived_via` frontmatter field. Used by storage\n * validation to reject unknown operator values on write.\n */\nexport const CONSOLIDATION_OPERATORS: readonly ConsolidationOperator[] = [\n \"split\",\n \"merge\",\n \"update\",\n] as const;\n\n/**\n * Regular expression for validating a single `derived_from` entry.\n *\n * Format: `<non-empty memory path>:<integer version >= 0>`. Matches the\n * `path:versionNumber` convention used by `page-versioning.ts` snapshots\n * (e.g. `\"facts/preferences.md:3\"`). The path portion is greedy-last so\n * paths that themselves contain a colon remain parseable — only the final\n * `:<digits>` is consumed as the version.\n */\nconst DERIVED_FROM_ENTRY_RE = /^(.+):(\\d+)$/;\n\n/**\n * Validate a `derived_from` entry string. Returns `true` if the entry\n * parses as `<non-empty path>:<integer >= 0>`. Kept pure so storage and\n * future CLI/doctor paths can share the same validator.\n */\nexport function isValidDerivedFromEntry(entry: unknown): entry is string {\n if (typeof entry !== \"string\") return false;\n const match = entry.match(DERIVED_FROM_ENTRY_RE);\n if (!match) return false;\n const pathPart = match[1];\n if (pathPart.length === 0 || pathPart.trim().length === 0) return false;\n const versionNum = Number(match[2]);\n return Number.isInteger(versionNum) && versionNum >= 0;\n}\n\n/**\n * Type guard for `ConsolidationOperator`.\n */\nexport function isConsolidationOperator(value: unknown): value is ConsolidationOperator {\n return (\n typeof value === \"string\" &&\n (CONSOLIDATION_OPERATORS as readonly string[]).includes(value)\n );\n}\n"],"mappings":";AA8BO,IAAM,0BAA4D;AAAA,EACvE;AAAA,EACA;AAAA,EACA;AACF;AAWA,IAAM,wBAAwB;AAOvB,SAAS,wBAAwB,OAAiC;AACvE,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,QAAQ,MAAM,MAAM,qBAAqB;AAC/C,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,WAAW,MAAM,CAAC;AACxB,MAAI,SAAS,WAAW,KAAK,SAAS,KAAK,EAAE,WAAW,EAAG,QAAO;AAClE,QAAM,aAAa,OAAO,MAAM,CAAC,CAAC;AAClC,SAAO,OAAO,UAAU,UAAU,KAAK,cAAc;AACvD;AAKO,SAAS,wBAAwB,OAAgD;AACtF,SACE,OAAO,UAAU,YAChB,wBAA8C,SAAS,KAAK;AAEjE;","names":[]}
@@ -5,6 +5,9 @@ import {
5
5
  countRecallTokenOverlap,
6
6
  normalizeRecallTokens
7
7
  } from "./chunk-DT5TVLJE.js";
8
+ import {
9
+ log
10
+ } from "./chunk-2ODBA7MQ.js";
8
11
  import {
9
12
  assertIsoRecordedAt,
10
13
  assertString,
@@ -15,9 +18,6 @@ import {
15
18
  listJsonFiles,
16
19
  readJsonFile
17
20
  } from "./chunk-LPSF4OQH.js";
18
- import {
19
- log
20
- } from "./chunk-2ODBA7MQ.js";
21
21
 
22
22
  // src/causal-chain.ts
23
23
  import path from "path";
@@ -280,4 +280,4 @@ export {
280
280
  scoreStitchCandidate,
281
281
  stitchCausalChain
282
282
  };
283
- //# sourceMappingURL=chunk-3QFQGRHO.js.map
283
+ //# sourceMappingURL=chunk-XMHBH5H6.js.map
@@ -589,20 +589,32 @@ function parseQmdSearchStdout(stdout, transport = "subprocess") {
589
589
  })
590
590
  );
591
591
  }
592
- var _sharedDaemonSession = null;
593
- var _sharedDaemonSessionPath = null;
594
- function getSharedDaemonSession(qmdPath) {
592
+ var SHARED_DAEMON_SESSIONS = /* @__PURE__ */ new Map();
593
+ function retainSharedDaemonSession(qmdPath) {
595
594
  const normalizedPath = qmdPath.trim() || "qmd";
596
- if (_sharedDaemonSession && _sharedDaemonSessionPath !== normalizedPath) {
597
- _sharedDaemonSession.invalidate();
598
- _sharedDaemonSession = null;
599
- _sharedDaemonSessionPath = null;
595
+ const existing = SHARED_DAEMON_SESSIONS.get(normalizedPath);
596
+ if (existing) {
597
+ existing.refs += 1;
598
+ return existing.session;
600
599
  }
601
- if (!_sharedDaemonSession) {
602
- _sharedDaemonSession = new QmdDaemonSession(normalizedPath);
603
- _sharedDaemonSessionPath = normalizedPath;
600
+ const session = new QmdDaemonSession(normalizedPath);
601
+ SHARED_DAEMON_SESSIONS.set(normalizedPath, {
602
+ refs: 1,
603
+ session
604
+ });
605
+ return session;
606
+ }
607
+ function releaseSharedDaemonSession(session) {
608
+ if (!session) return;
609
+ for (const [qmdPath, entry] of SHARED_DAEMON_SESSIONS.entries()) {
610
+ if (entry.session !== session) continue;
611
+ entry.refs = Math.max(0, entry.refs - 1);
612
+ if (entry.refs === 0) {
613
+ entry.session.invalidate();
614
+ SHARED_DAEMON_SESSIONS.delete(qmdPath);
615
+ }
616
+ return;
604
617
  }
605
- return _sharedDaemonSession;
606
618
  }
607
619
  var QmdClient = class _QmdClient {
608
620
  constructor(collection, maxResults, opts) {
@@ -648,6 +660,7 @@ var QmdClient = class _QmdClient {
648
660
  // Daemon mode fields
649
661
  daemonSession = null;
650
662
  daemonAvailable = false;
663
+ daemonSessionPath = null;
651
664
  lastDaemonCheckAtMs = 0;
652
665
  daemonEnabled;
653
666
  daemonRecheckIntervalMs;
@@ -664,7 +677,12 @@ var QmdClient = class _QmdClient {
664
677
  }
665
678
  async probeDaemon() {
666
679
  this.lastDaemonCheckAtMs = Date.now();
667
- this.daemonSession = getSharedDaemonSession(this.qmdPath);
680
+ const normalizedPath = this.qmdPath.trim() || "qmd";
681
+ if (!this.daemonSession || this.daemonSessionPath !== normalizedPath) {
682
+ releaseSharedDaemonSession(this.daemonSession);
683
+ this.daemonSession = retainSharedDaemonSession(normalizedPath);
684
+ this.daemonSessionPath = normalizedPath;
685
+ }
668
686
  try {
669
687
  const PROBE_QUICK_TIMEOUT_MS = 3e3;
670
688
  const ok = await Promise.race([
@@ -782,6 +800,13 @@ ${stderr}`.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
782
800
  isDaemonMode() {
783
801
  return this.daemonAvailable;
784
802
  }
803
+ dispose() {
804
+ releaseSharedDaemonSession(this.daemonSession);
805
+ this.daemonSession = null;
806
+ this.daemonSessionPath = null;
807
+ this.daemonAvailable = false;
808
+ this.daemonTransientFailures = 0;
809
+ }
785
810
  /**
786
811
  * Record a daemon search success — resets the transient failure counter.
787
812
  */
@@ -1254,11 +1279,19 @@ ${stderr}`.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
1254
1279
  return [];
1255
1280
  }
1256
1281
  }
1257
- async update(signal) {
1258
- await this.runUpdateForCollection(this.collection, { perCollectionThrottle: false }, signal);
1282
+ async update(execution) {
1283
+ await this.runUpdateForCollection(
1284
+ this.collection,
1285
+ { perCollectionThrottle: false },
1286
+ execution?.signal
1287
+ );
1259
1288
  }
1260
- async updateCollection(collection) {
1261
- await this.runUpdateForCollection(collection, { perCollectionThrottle: true });
1289
+ async updateCollection(collection, execution) {
1290
+ await this.runUpdateForCollection(
1291
+ collection,
1292
+ { perCollectionThrottle: true },
1293
+ execution?.signal
1294
+ );
1262
1295
  }
1263
1296
  async runUpdateForCollection(collection, options, signal) {
1264
1297
  if (this.available === false) return;
@@ -1462,4 +1495,4 @@ export {
1462
1495
  parseQmdExplain,
1463
1496
  QmdClient
1464
1497
  };
1465
- //# sourceMappingURL=chunk-BLKTA7MM.js.map
1498
+ //# sourceMappingURL=chunk-YNQKWQT4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/qmd.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { log } from \"./logger.js\";\nimport { getCachedQmdSearch, setCachedQmdSearch } from \"./memory-cache.js\";\nimport {\n abortError,\n isAbortError,\n throwIfAborted,\n} from \"./abort-error.js\";\nimport type { QmdSearchExplain, QmdSearchResult } from \"./types.js\";\nimport type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from \"./search/port.js\";\nimport { launchProcess, type CommandChildProcess } from \"./runtime/child-process.js\";\nimport { mergeEnv } from \"./runtime/env.js\";\n\nexport interface QmdClientOptions {\n slowLog?: { enabled: boolean; thresholdMs: number };\n updateTimeoutMs?: number;\n updateMinIntervalMs?: number;\n qmdPath?: string;\n daemonUrl?: string;\n daemonRecheckIntervalMs?: number;\n}\n\nconst QMD_TIMEOUT_MS = 30_000;\n// Daemon timeout for individual search calls. Keep well under RECALL_TIMEOUT_MS (75s) so a\n// slow/loading daemon fails fast and the caller can return early rather than hanging.\n// After the daemon has loaded its index (~90s for 75K files), actual searches complete in <3s.\n// During the loading window, searches will timeout/return [] quickly — this is preferable to\n// blocking the full 75s on every recall request.\n// Note: keep this ≥ 5s to allow normal searches (post-load) to complete reliably.\nconst QMD_DAEMON_TIMEOUT_MS = 8_000;\nconst QMD_PROBE_TIMEOUT_MS = 8_000;\nconst QMD_UPDATE_BACKOFF_MS = 15 * 60 * 1000; // 15m\nconst QMD_EMBED_BACKOFF_MS = 60 * 60 * 1000; // 60m\nconst QMD_CLI_WARN_THROTTLE_MS = 15 * 60 * 1000; // 15m\nconst QMD_FALLBACK_PATHS = [\n path.join(os.homedir(), \".bun\", \"bin\", \"qmd\"),\n \"/usr/local/bin/qmd\",\n \"/opt/homebrew/bin/qmd\",\n];\nconst QMD_GLOBAL_STATE_KEY = \"__openclawEngramQmdGlobalState\";\n\ntype QmdGlobalState = {\n warnedGlobalUpdateBehavior: boolean;\n lastGlobalUpdateRunAtMs: number | null;\n lastGlobalUpdateFailAtMs: number | null;\n lastGlobalEmbedRunAtMs: number | null;\n lastGlobalEmbedFailAtMs: number | null;\n lastCliWarnAtMs: number | null;\n lastUpdateByCollectionMs: Record<string, number>;\n lastUpdateFailByCollectionMs: Record<string, number>;\n lastEmbedByCollectionMs: Record<string, number>;\n lastEmbedFailByCollectionMs: Record<string, number>;\n};\n\nfunction getGlobalQmdState(): QmdGlobalState {\n const g = globalThis as any;\n if (!g[QMD_GLOBAL_STATE_KEY]) {\n g[QMD_GLOBAL_STATE_KEY] = {\n warnedGlobalUpdateBehavior: false,\n lastGlobalUpdateRunAtMs: null,\n lastGlobalUpdateFailAtMs: null,\n lastGlobalEmbedRunAtMs: null,\n lastGlobalEmbedFailAtMs: null,\n lastCliWarnAtMs: null,\n lastUpdateByCollectionMs: {},\n lastUpdateFailByCollectionMs: {},\n lastEmbedByCollectionMs: {},\n lastEmbedFailByCollectionMs: {},\n } satisfies QmdGlobalState;\n }\n return g[QMD_GLOBAL_STATE_KEY] as QmdGlobalState;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction errorMessage(err: unknown): string {\n if (typeof err === \"string\") return err;\n if (err instanceof Error) return err.message;\n if (err && typeof err === \"object\" && \"message\" in err && typeof (err as { message?: unknown }).message === \"string\") {\n return (err as { message: string }).message;\n }\n return String(err);\n}\n\nfunction isCallerCancellation(err: unknown, signal?: AbortSignal): boolean {\n if (signal?.aborted) return true;\n if (isAbortError(err)) return true;\n if (err && typeof err === \"object\") {\n const code = \"code\" in err ? (err as { code?: unknown }).code : undefined;\n if (code === \"ABORT_ERR\" || code === \"ERR_CANCELED\") return true;\n }\n return false;\n}\n\nfunction isDaemonTimeoutError(err: unknown): boolean {\n return /timed out/i.test(errorMessage(err));\n}\n\nfunction sleepWithSignal(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal);\n const timer = setTimeout(() => {\n cleanup();\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n cleanup();\n reject(abortError(\"operation aborted while waiting\"));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction isSqliteBusyError(msg: string): boolean {\n const lower = msg.toLowerCase();\n return (\n lower.includes(\"database is locked\") ||\n lower.includes(\"sqlite_busy\") ||\n lower.includes(\"sqlite_busy_recovery\") ||\n lower.includes(\"sqliterror: database is locked\")\n );\n}\n\nfunction stripControlChars(s: string): string {\n // Remove ANSI escapes and other control characters that explode logs.\n return s.replace(/\\x1b\\[[0-9;]*[A-Za-z]/g, \"\").replace(/[\\u0000-\\u001f\\u007f]/g, \"\");\n}\n\nfunction truncateForLog(s: string, max = 2000): string {\n const cleaned = stripControlChars(s);\n return cleaned.length > max ? cleaned.slice(0, max) + \"…(truncated)\" : cleaned;\n}\n\nfunction isVectorDimensionMismatchError(err: unknown): boolean {\n const msg = err instanceof Error ? err.message : String(err);\n return (\n /dimension mismatch/i.test(msg) ||\n (/vectors?_vec/i.test(msg) && /float\\[\\d+\\]/i.test(msg)) ||\n (/embedding/i.test(msg) && /dimensions?/i.test(msg))\n );\n}\n\nfunction parseQmdVersion(version: string | null): [number, number, number] | null {\n if (!version) return null;\n const match = version.match(/v?(\\d{1,10})\\.(\\d{1,10})\\.(\\d{1,10})/i);\n if (!match) return null;\n return [\n Number.parseInt(match[1] ?? \"0\", 10),\n Number.parseInt(match[2] ?? \"0\", 10),\n Number.parseInt(match[3] ?? \"0\", 10),\n ];\n}\n\nfunction versionAtLeast(\n current: [number, number, number] | null,\n target: [number, number, number],\n): boolean {\n if (!current) return false;\n for (let i = 0; i < 3; i += 1) {\n if ((current[i] ?? 0) > target[i]) return true;\n if ((current[i] ?? 0) < target[i]) return false;\n }\n return true;\n}\n\nfunction normalizeSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n if (!options) return undefined;\n const intent = typeof options.intent === \"string\" ? options.intent.trim() : \"\";\n const normalized: SearchQueryOptions = {};\n if (intent.length > 0) {\n normalized.intent = intent;\n }\n if (options.explain === true) {\n normalized.explain = true;\n }\n return Object.keys(normalized).length > 0 ? normalized : undefined;\n}\n\nfunction parseExplainScores(value: unknown): number[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const scores = value.filter((entry): entry is number => typeof entry === \"number\");\n return scores.length > 0 ? scores : undefined;\n}\n\nexport function parseQmdExplain(value: unknown): QmdSearchExplain | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const candidate = value as Record<string, unknown>;\n const parsed: QmdSearchExplain = {\n ftsScores: parseExplainScores(candidate.ftsScores),\n vectorScores: parseExplainScores(candidate.vectorScores),\n rrf: typeof candidate.rrf === \"number\" ? candidate.rrf : undefined,\n rerankScore: typeof candidate.rerankScore === \"number\" ? candidate.rerankScore : undefined,\n blendedScore: typeof candidate.blendedScore === \"number\" ? candidate.blendedScore : undefined,\n };\n return Object.values(parsed).some((entry) => entry !== undefined) ? parsed : undefined;\n}\n\nclass AsyncMutex {\n private locked = false;\n private queue: Array<{\n resolve: (release: () => void) => void;\n reject: (reason: Error) => void;\n signal?: AbortSignal;\n onAbort: () => void;\n }> = [];\n\n async runExclusive<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n const release = await this.acquire(signal);\n try {\n throwIfAborted(signal);\n return await fn();\n } finally {\n release();\n }\n }\n\n private acquire(signal?: AbortSignal): Promise<() => void> {\n throwIfAborted(signal);\n if (!this.locked) {\n this.locked = true;\n return Promise.resolve(() => this.release());\n }\n\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve: (release: () => void) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n resolve(release);\n },\n reject: (reason: Error) => {\n signal?.removeEventListener(\"abort\", waiter.onAbort);\n reject(reason);\n },\n signal,\n onAbort: () => {\n this.queue = this.queue.filter((entry) => entry !== waiter);\n reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n },\n };\n signal?.addEventListener(\"abort\", waiter.onAbort, { once: true });\n this.queue.push(waiter);\n });\n }\n\n private release(): void {\n while (this.queue.length > 0) {\n const next = this.queue.shift();\n if (!next) break;\n if (next.signal?.aborted) {\n next.reject(abortError(\"operation aborted while waiting for qmd mutex\"));\n continue;\n }\n this.locked = true;\n next.resolve(() => this.release());\n return;\n }\n this.locked = false;\n }\n}\n\nconst QMD_MUTEX = new AsyncMutex();\n\nfunction runQmd(\n args: string[],\n timeoutMs: number = QMD_TIMEOUT_MS,\n qmdPath: string = \"qmd\",\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n // Serialize all qmd calls. This avoids SQLite lock contention when multiple\n // channels/agents trigger QMD operations at nearly the same time.\n return QMD_MUTEX.runExclusive(async () => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before start`);\n const maxAttempts = isLikelyWriteCommand(args) ? 3 : 1;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await runQmdOnce(args, timeoutMs, qmdPath, signal);\n } catch (err) {\n if (isAbortError(err)) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n if (attempt < maxAttempts && isSqliteBusyError(msg)) {\n // Another qmd call (or an external qmd process) currently holds the DB.\n // Back off briefly and retry.\n await sleepWithSignal(1500 * attempt, signal);\n continue;\n }\n throw err;\n }\n }\n // unreachable\n throw new Error(\"qmd command failed\");\n }, signal);\n}\n\nfunction isLikelyWriteCommand(args: string[]): boolean {\n const cmd = args[0] ?? \"\";\n return cmd === \"update\" || cmd === \"embed\" || cmd === \"cleanup\" || cmd === \"collection\";\n}\n\nfunction runQmdOnce(\n args: string[],\n timeoutMs: number,\n qmdPath: string,\n signal?: AbortSignal,\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `qmd ${args.join(\" \")} aborted before spawn`);\n const child = launchProcess(qmdPath, args, {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n if (!child.stdout || !child.stderr) {\n reject(new Error(`qmd ${args.join(\" \")} failed to open stdio pipes`));\n return;\n }\n\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n\n const timer = setTimeout(() => {\n settled = true;\n cleanup();\n child.kill(\"SIGKILL\");\n reject(new Error(`qmd ${args.join(\" \")} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n child.kill(\"SIGKILL\");\n reject(abortError(`qmd ${args.join(\" \")} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n child.stdout.on(\"data\", (data: Buffer) => {\n stdout += data.toString();\n });\n child.stderr.on(\"data\", (data: Buffer) => {\n stderr += data.toString();\n });\n child.on(\"error\", (err) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n reject(err);\n });\n child.on(\"close\", (code) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n cleanup();\n // QMD returns exit code 1 for --version (shows usage), but that's ok\n const isVersionCheck = args.length === 1 && args[0] === \"--version\";\n if (code === 0 || (isVersionCheck && code === 1)) {\n resolve({ stdout, stderr });\n } else {\n reject(\n new Error(\n `qmd ${args.join(\" \")} failed (code ${code}): ${truncateForLog(stderr || stdout)}`,\n ),\n );\n }\n });\n });\n}\n\n// ---------------------------------------------------------------------------\n// QMD Stdio Daemon Session (MCP over stdio child process)\n// ---------------------------------------------------------------------------\n\nlet nextJsonRpcId = 1;\n\nclass QmdDaemonSession {\n private child: CommandChildProcess | null = null;\n private initialized = false;\n private buffer = \"\";\n private startPromise: Promise<boolean> | null = null;\n private pendingRequests = new Map<\n number,\n {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n cleanup: () => void;\n }\n >();\n private readonly qmdPath: string;\n\n constructor(qmdPath: string) {\n this.qmdPath = qmdPath;\n }\n\n /** Spawn the qmd mcp child process and perform MCP handshake. */\n async start(): Promise<boolean> {\n if (this.child && !this.child.killed && this.initialized) {\n return true;\n }\n if (this.startPromise) {\n return this.startPromise;\n }\n this.startPromise = (async () => {\n // If the process is already running but not yet initialized (e.g. it is still\n // loading its index after a previous handshake timeout), reuse it instead of\n // killing and re-spawning. This prevents accumulating zombie qmd-mcp processes\n // when the daemon takes >15s to load a large collection.\n const processAlreadyRunning = this.child != null && !this.child.killed;\n if (!processAlreadyRunning) {\n if (this.child) {\n this.cleanup({ killChild: true });\n }\n try {\n const child = launchProcess(this.qmdPath, [\"mcp\"], {\n env: mergeEnv({ NO_COLOR: \"1\" }),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n this.child = child;\n this.buffer = \"\";\n\n child.stdout?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n this.handleStdoutData(data);\n });\n child.stderr?.on(\"data\", (data: Buffer) => {\n if (this.child !== child) return;\n const msg = data.toString().trim();\n if (msg) log.debug(`QMD mcp stderr: ${stripControlChars(msg)}`);\n });\n child.stdin?.on(\"error\", (err) => {\n // Swallow EPIPE/ERR_STREAM_DESTROYED — these happen when the child\n // process is killed (e.g. due to recall timeout) and a write arrives\n // after the pipe is broken. Without this handler Node.js would throw\n // an uncaught exception and crash the process.\n log.debug(`QMD mcp stdin error (suppressed): ${err.message}`);\n });\n child.on(\"error\", (err) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process error: ${err.message}`);\n this.cleanup({ child });\n });\n child.on(\"close\", (code) => {\n if (this.child !== child) return;\n log.debug(`QMD mcp process exited (code ${code})`);\n this.cleanup({ child });\n });\n } catch (err) {\n log.debug(`QMD mcp: failed to spawn process: ${err}`);\n this.cleanup({ killChild: true });\n return false;\n }\n } else {\n log.debug(\"QMD mcp: process already running, retrying handshake\");\n }\n\n try {\n // Use a generous timeout — large collections (75K+ files) can take 60-90s\n // to load their vector index. We keep the process alive across retries so\n // only one mcp instance is running at a time.\n const result = await this.sendRequest(\n \"initialize\",\n {\n protocolVersion: \"2024-11-05\",\n capabilities: {},\n clientInfo: { name: \"openclaw-remnic\", version: \"1.0.0\" },\n },\n 60_000,\n );\n if (!result) {\n // Null result (non-timeout failure) — kill and let the next probe respawn.\n this.cleanup({ killChild: true });\n return false;\n }\n this.sendNotification(\"notifications/initialized\");\n this.initialized = true;\n log.info(\"QMD mcp: stdio session initialized\");\n return true;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n if (/timed out/i.test(msg)) {\n // Handshake timeout — process is still loading. Keep it alive for the\n // next retry (daemonRecheckIntervalMs). Do NOT kill and respawn.\n log.debug(`QMD mcp: handshake timed out — process still loading, will retry later`);\n // Reset initialized flag but leave child running.\n this.initialized = false;\n } else {\n log.debug(`QMD mcp: failed to start stdio session: ${err}`);\n this.cleanup({ killChild: true });\n }\n return false;\n } finally {\n this.startPromise = null;\n }\n })();\n return this.startPromise;\n }\n\n /** Call an MCP tool and return the parsed result. */\n async callTool(\n name: string,\n args: Record<string, unknown>,\n timeoutMs: number = 30_000,\n signal?: AbortSignal,\n ): Promise<unknown> {\n if (!this.child || this.child.killed || !this.initialized) {\n throw new Error(\"QMD mcp process not running\");\n }\n return this.sendRequest(\"tools/call\", { name, arguments: args }, timeoutMs, signal);\n }\n\n /** Kill stdio process and clear state so the next probe can restart. */\n invalidate(): void {\n this.cleanup({ killChild: true });\n }\n\n isActive(): boolean {\n return this.child !== null && !this.child.killed && this.initialized;\n }\n\n /** True while the process is spawned but the MCP handshake has not yet completed. */\n isLoading(): boolean {\n return this.child !== null && !this.child.killed && !this.initialized;\n }\n\n private sendRequest(\n method: string,\n params: Record<string, unknown>,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n throwIfAborted(signal, `QMD mcp ${method} aborted before request`);\n if (!this.child || !this.child.stdin || this.child.killed) {\n reject(new Error(\"QMD mcp process not available\"));\n return;\n }\n\n const id = nextJsonRpcId++;\n const timer = setTimeout(() => {\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`QMD mcp ${method} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n const onAbort = () => {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(abortError(`QMD mcp ${method} aborted`));\n };\n const cleanup = () => {\n signal?.removeEventListener(\"abort\", onAbort);\n };\n\n this.pendingRequests.set(id, { resolve, reject, timer, cleanup });\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n const message = JSON.stringify({ jsonrpc: \"2.0\", id, method, params }) + \"\\n\";\n this.child.stdin.write(message, (err) => {\n if (err) {\n clearTimeout(timer);\n this.pendingRequests.delete(id);\n cleanup();\n reject(new Error(`Failed to write to QMD mcp stdin: ${err.message}`));\n }\n });\n });\n }\n\n private sendNotification(method: string, params?: Record<string, unknown>): void {\n if (!this.child || !this.child.stdin || this.child.killed) return;\n if (this.child.stdin.destroyed) return;\n const msg: Record<string, unknown> = { jsonrpc: \"2.0\", method };\n if (params) msg.params = params;\n try {\n this.child.stdin.write(JSON.stringify(msg) + \"\\n\");\n } catch {\n // Ignore EPIPE / write-after-close\n }\n }\n\n private handleStdoutData(data: Buffer): void {\n this.buffer += data.toString();\n let newlineIdx: number;\n while ((newlineIdx = this.buffer.indexOf(\"\\n\")) !== -1) {\n const line = this.buffer.slice(0, newlineIdx).trim();\n this.buffer = this.buffer.slice(newlineIdx + 1);\n if (!line) continue;\n try {\n const msg = JSON.parse(line);\n this.handleMessage(msg);\n } catch {\n log.debug(`QMD mcp: unparseable stdout: ${truncateForLog(line, 200)}`);\n }\n }\n }\n\n private handleMessage(msg: Record<string, unknown>): void {\n if (msg.id !== undefined && msg.id !== null) {\n const pending = this.pendingRequests.get(msg.id as number);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingRequests.delete(msg.id as number);\n pending.cleanup();\n if (msg.error) {\n pending.reject(new Error(JSON.stringify(msg.error)));\n } else {\n pending.resolve(msg.result);\n }\n }\n return;\n }\n if (msg.method) {\n log.debug(`QMD mcp notification: ${msg.method}`);\n }\n }\n\n private cleanup(opts?: { killChild?: boolean; child?: CommandChildProcess | null }): void {\n const target = opts?.child ?? this.child;\n if (!target) return;\n if (opts?.child && this.child !== opts.child) {\n return;\n }\n if (opts?.killChild && !target.killed) {\n target.kill(\"SIGTERM\");\n }\n this.initialized = false;\n for (const [, pending] of this.pendingRequests) {\n clearTimeout(pending.timer);\n pending.cleanup();\n pending.reject(new Error(\"QMD mcp process terminated\"));\n }\n this.pendingRequests.clear();\n this.startPromise = null;\n this.child = null;\n this.buffer = \"\";\n }\n}\n\n/** Matches `#<hex-docid> <score>% <rest-of-line>` — rest is split in a second pass. */\nconst QMD_RESULT_LINE_RE = /^#([0-9a-fA-F]+)\\s+(\\d+)%\\s+(.+)/;\n\n/**\n * Splits `collection/path.ext - Title text` into path and title.\n * Non-greedy `.+?` finds the FIRST dot-extension (2+ alphabetic chars)\n * followed by ` - `, accepting any indexed file type while skipping\n * version-like segments (e.g. `v1.2` where `.2` is a single digit).\n */\nconst QMD_PATH_TITLE_RE = /^(.+?\\.[a-zA-Z]{2,10})\\s+-\\s+(.*)$/;\n\nfunction parseQmdMarkdownResultText(\n text: string,\n transport: QmdSearchResult[\"transport\"],\n): QmdSearchResult[] {\n const results: QmdSearchResult[] = [];\n for (const line of text.split(\"\\n\")) {\n const m = QMD_RESULT_LINE_RE.exec(line.trim());\n if (!m) continue;\n const rest = m[3]; // \"collection/path.md - Title with - dashes\"\n // Find the path by looking for known file extensions followed by \" - \"\n const pathTitleSplit = QMD_PATH_TITLE_RE.exec(rest);\n if (!pathTitleSplit) continue;\n results.push({\n docid: m[1],\n path: pathTitleSplit[1] ?? \"unknown\",\n snippet: \"\",\n score: parseInt(m[2], 10) / 100,\n transport,\n });\n }\n return results;\n}\n\nfunction parseMcpSearchResult(\n result: unknown,\n transport: QmdSearchResult[\"transport\"] = \"daemon\",\n): QmdSearchResult[] {\n const resultObj = result as Record<string, unknown> | null;\n if (!resultObj) return [];\n const results: QmdSearchResult[] = [];\n const pushDocs = (docs: unknown[]) => {\n for (const doc of docs) {\n const d = doc as Record<string, unknown>;\n results.push({\n docid: typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"\",\n path: typeof d.file === \"string\"\n ? d.file\n : typeof d.path === \"string\"\n ? d.path\n : (typeof d.docid === \"string\" ? d.docid.replace(/^#/, \"\") : \"unknown\"),\n snippet: typeof d.snippet === \"string\" ? d.snippet : \"\",\n score: typeof d.score === \"number\" ? d.score : 0,\n explain: parseQmdExplain(d.explain),\n transport,\n });\n }\n };\n const topStructured = resultObj.structuredContent as Record<string, unknown> | undefined;\n const topDocs = topStructured?.results ?? topStructured?.documents;\n if (Array.isArray(topDocs)) pushDocs(topDocs);\n const content = resultObj.content;\n if (Array.isArray(content)) {\n for (const item of content) {\n const structured = item?.structuredContent;\n const docResults = structured?.results ?? structured?.documents;\n if (Array.isArray(docResults)) pushDocs(docResults);\n if (typeof item?.text === \"string\") {\n try {\n const parsed = JSON.parse(item.text);\n const textResults = parsed?.results ?? parsed?.documents;\n if (Array.isArray(textResults)) pushDocs(textResults);\n } catch {\n const existingKeys = new Set(results.map((r) => `${r.docid.toLowerCase()}|${r.path}`));\n const parsed = parseQmdMarkdownResultText(item.text, transport);\n for (const p of parsed) {\n const key = `${p.docid.toLowerCase()}|${p.path}`;\n if (!existingKeys.has(key)) {\n results.push(p);\n existingKeys.add(key);\n }\n }\n }\n }\n }\n }\n return results;\n}\n\nfunction parseQmdSearchStdout(\n stdout: string,\n transport: QmdSearchResult[\"transport\"] = \"subprocess\",\n): QmdSearchResult[] {\n const trimmedOut = stdout.trim();\n if (!trimmedOut || trimmedOut === \"No results found.\") return [];\n const parsed = JSON.parse(trimmedOut);\n if (!Array.isArray(parsed)) return [];\n return parsed.map(\n (entry: Record<string, unknown>): QmdSearchResult => ({\n docid: (entry.docid as string) ?? \"\",\n path:\n (entry.file as string) ??\n (entry.path as string) ??\n (entry.docid as string) ??\n \"unknown\",\n snippet: (entry.snippet as string) ?? \"\",\n score: typeof entry.score === \"number\" ? entry.score : 0,\n explain: parseQmdExplain(entry.explain),\n transport,\n }),\n );\n}\n\ntype SharedDaemonSessionEntry = {\n refs: number;\n session: QmdDaemonSession;\n};\n\nconst SHARED_DAEMON_SESSIONS = new Map<string, SharedDaemonSessionEntry>();\n\nfunction retainSharedDaemonSession(qmdPath: string): QmdDaemonSession {\n const normalizedPath = qmdPath.trim() || \"qmd\";\n const existing = SHARED_DAEMON_SESSIONS.get(normalizedPath);\n if (existing) {\n existing.refs += 1;\n return existing.session;\n }\n\n const session = new QmdDaemonSession(normalizedPath);\n SHARED_DAEMON_SESSIONS.set(normalizedPath, {\n refs: 1,\n session,\n });\n return session;\n}\n\nfunction releaseSharedDaemonSession(session: QmdDaemonSession | null): void {\n if (!session) return;\n\n for (const [qmdPath, entry] of SHARED_DAEMON_SESSIONS.entries()) {\n if (entry.session !== session) continue;\n entry.refs = Math.max(0, entry.refs - 1);\n if (entry.refs === 0) {\n entry.session.invalidate();\n SHARED_DAEMON_SESSIONS.delete(qmdPath);\n }\n return;\n }\n}\n\n// ---------------------------------------------------------------------------\n// QmdClient\n// ---------------------------------------------------------------------------\n\nexport class QmdClient implements SearchBackend {\n private available: boolean | null = null;\n private _lastUpdateFailAtMs: number | null = null;\n private lastEmbedFailAtMs: number | null = null;\n private lastUpdateRunAtMs: number | null = null;\n\n get lastUpdateFailedAtMs(): number | null {\n return this._lastUpdateFailAtMs;\n }\n\n get lastUpdateRanAtMs(): number | null {\n return this.lastUpdateRunAtMs;\n }\n\n resetUpdateThrottles(): void {\n this._lastUpdateFailAtMs = null;\n this.lastUpdateRunAtMs = null;\n const gs = getGlobalQmdState();\n gs.lastGlobalUpdateRunAtMs = null;\n gs.lastGlobalUpdateFailAtMs = null;\n }\n\n private readonly updateTimeoutMs: number;\n private readonly updateMinIntervalMs: number;\n private readonly slowLog?: { enabled: boolean; thresholdMs: number };\n private readonly configuredQmdPath?: string;\n private qmdPathSource: \"auto-path\" | \"auto-fallback\" | \"configured\" = \"auto-path\";\n private cliVersion: string | null = null;\n private lastCliProbeError: string | null = null;\n\n // Daemon mode fields\n private daemonSession: QmdDaemonSession | null = null;\n private daemonAvailable = false;\n private daemonSessionPath: string | null = null;\n private lastDaemonCheckAtMs = 0;\n private readonly daemonEnabled: boolean;\n private readonly daemonRecheckIntervalMs: number;\n /** Consecutive transient daemon failures before invalidating the session. */\n private daemonTransientFailures = 0;\n private static readonly DAEMON_MAX_TRANSIENT_FAILURES = 3;\n\n constructor(\n private readonly collection: string,\n private readonly maxResults: number,\n opts?: QmdClientOptions,\n ) {\n this.slowLog = opts?.slowLog;\n this.updateTimeoutMs = opts?.updateTimeoutMs ?? 120_000;\n this.updateMinIntervalMs = Math.max(0, opts?.updateMinIntervalMs ?? 15 * 60_000);\n this.configuredQmdPath = opts?.qmdPath?.trim() ? opts.qmdPath.trim() : undefined;\n if (this.configuredQmdPath) {\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n }\n this.daemonEnabled = Boolean(opts?.daemonUrl);\n this.daemonRecheckIntervalMs = opts?.daemonRecheckIntervalMs ?? 15_000;\n }\n\n private qmdPath: string = \"qmd\";\n\n async probe(): Promise<boolean> {\n const cliOk = await this.probeCli();\n if (this.daemonEnabled) {\n await this.probeDaemon();\n }\n return cliOk || this.daemonAvailable;\n }\n\n private async probeDaemon(): Promise<boolean> {\n this.lastDaemonCheckAtMs = Date.now();\n const normalizedPath = this.qmdPath.trim() || \"qmd\";\n if (!this.daemonSession || this.daemonSessionPath !== normalizedPath) {\n releaseSharedDaemonSession(this.daemonSession);\n this.daemonSession = retainSharedDaemonSession(normalizedPath);\n this.daemonSessionPath = normalizedPath;\n }\n try {\n // Race start() against a short window: if the session is already initialized\n // this returns instantly; if the process is still loading its index we fail\n // fast and let the caller fall back gracefully. The underlying start() promise\n // continues running in the background so the process is NOT killed. On the\n // next recheck cycle (daemonRecheckIntervalMs=15s) start() returns true\n // immediately once the handshake has completed.\n const PROBE_QUICK_TIMEOUT_MS = 3_000;\n const ok = await Promise.race([\n this.daemonSession.start(),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), PROBE_QUICK_TIMEOUT_MS)),\n ]);\n if (!ok) {\n const loading = this.daemonSession.isLoading();\n log.debug(`QMD daemon: stdio session not ready within ${PROBE_QUICK_TIMEOUT_MS}ms probe window${loading ? \" (still loading)\" : \"\"}`);\n this.daemonAvailable = false;\n return false;\n }\n log.info(`QMD daemon: stdio session active (collection=${this.collection})`);\n this.daemonAvailable = true;\n this.daemonTransientFailures = 0;\n return true;\n } catch (err) {\n log.debug(`QMD daemon: probe failed: ${err}`);\n this.daemonAvailable = false;\n return false;\n }\n }\n\n private async probeCli(): Promise<boolean> {\n const parseVersion = (stdout: string, stderr: string): string | null => {\n const lines = `${stdout}\\n${stderr}`\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n if (lines.length === 0) return null;\n const semanticLines = lines.filter((line) => parseQmdVersion(line) !== null);\n if (semanticLines.length === 0) return lines[0] ?? null;\n return semanticLines.find((line) => /\\bqmd\\b/i.test(line)) ?? semanticLines[0] ?? null;\n };\n const markProbeFailure = (err: unknown): void => {\n this.lastCliProbeError = err instanceof Error ? err.message : String(err);\n };\n\n if (this.configuredQmdPath) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, this.configuredQmdPath);\n this.available = true;\n this.qmdPath = this.configuredQmdPath;\n this.qmdPathSource = \"configured\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Do not hard-fail here: fall through to PATH/fallback probing.\n // This keeps recall healthy even when configured path is stale.\n this.logCliProbeWarning(\n `QMD: configured qmdPath failed (${this.configuredQmdPath}): ${this.lastCliProbeError}`,\n );\n }\n }\n\n // Try PATH first\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, \"qmd\");\n this.available = true;\n this.qmdPath = \"qmd\";\n this.qmdPathSource = \"auto-path\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n return true;\n } catch (err) {\n markProbeFailure(err);\n // Try fallback paths\n for (const fallbackPath of QMD_FALLBACK_PATHS) {\n try {\n const result = await runQmd([\"--version\"], QMD_PROBE_TIMEOUT_MS, fallbackPath);\n this.available = true;\n this.qmdPath = fallbackPath;\n this.qmdPathSource = \"auto-fallback\";\n this.cliVersion = parseVersion(result.stdout, result.stderr);\n this.lastCliProbeError = null;\n log.info(`QMD: found at ${fallbackPath}`);\n return true;\n } catch (fallbackErr) {\n markProbeFailure(fallbackErr);\n // Continue to next fallback\n }\n }\n this.available = false;\n return false;\n }\n }\n\n private logCliProbeWarning(message: string): void {\n const state = getGlobalQmdState();\n const now = Date.now();\n const canWarn =\n state.lastCliWarnAtMs === null || now - state.lastCliWarnAtMs >= QMD_CLI_WARN_THROTTLE_MS;\n if (!canWarn) {\n log.debug(message);\n return;\n }\n state.lastCliWarnAtMs = now;\n if (this.daemonAvailable) {\n // Daemon mode is healthy; keep this as debug noise rather than warning.\n log.debug(message);\n return;\n }\n log.warn(message);\n }\n\n /** Re-probe daemon if it was down and recheck interval has elapsed. */\n private async maybeProbeDaemon(): Promise<void> {\n if (!this.daemonEnabled) return;\n // If daemon is marked healthy and session is active, nothing to do.\n if (this.daemonAvailable && this.daemonSession?.isActive()) return;\n // If recently checked and failed, respect the recheck interval.\n if (this.daemonAvailable === false) {\n const elapsed = Date.now() - this.lastDaemonCheckAtMs;\n if (elapsed < this.daemonRecheckIntervalMs) return;\n }\n this.daemonAvailable = false;\n await this.probeDaemon();\n }\n\n isAvailable(): boolean {\n return this.available === true || this.daemonAvailable;\n }\n\n /** Debug string for troubleshooting availability issues. */\n debugStatus(): string {\n const cliPath = this.available ? this.qmdPath : (this.configuredQmdPath ?? \"unavailable\");\n const cliVersion = this.cliVersion ?? \"unknown\";\n const probeError = this.lastCliProbeError ? ` cliProbeError=${this.lastCliProbeError}` : \"\";\n return `cli=${this.available} daemon=${this.daemonAvailable} session=${!!this.daemonSession} cliPath=${cliPath} cliPathSource=${this.qmdPathSource} cliVersion=${cliVersion}${probeError}`;\n }\n\n isDaemonMode(): boolean {\n return this.daemonAvailable;\n }\n\n dispose(): void {\n releaseSharedDaemonSession(this.daemonSession);\n this.daemonSession = null;\n this.daemonSessionPath = null;\n this.daemonAvailable = false;\n this.daemonTransientFailures = 0;\n }\n\n /**\n * Record a daemon search success — resets the transient failure counter.\n */\n private recordDaemonSuccess(): void {\n this.daemonTransientFailures = 0;\n }\n\n /**\n * Handle a non-timeout, non-cancellation daemon error.\n * Tolerates up to DAEMON_MAX_TRANSIENT_FAILURES consecutive failures\n * before invalidating the session. This prevents a single transient\n * error from pushing all concurrent searches through the subprocess\n * mutex for the full recheck interval.\n */\n private handleDaemonTransientError(label: string, err: unknown, durationMs: number): void {\n // If daemon was already marked unavailable by a concurrent call, don't\n // increment further — the counter will reset on the next successful probe.\n if (!this.daemonAvailable) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (daemon already unavailable, ignoring): ${err}`);\n return;\n }\n this.daemonTransientFailures += 1;\n if (this.daemonTransientFailures >= QmdClient.DAEMON_MAX_TRANSIENT_FAILURES) {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (${this.daemonTransientFailures} consecutive failures, invalidating): ${err}`);\n this.daemonSession?.invalidate();\n this.daemonAvailable = false;\n this.daemonTransientFailures = 0;\n } else {\n log.debug(`QMD daemon ${label} failed after ${durationMs}ms (transient ${this.daemonTransientFailures}/${QmdClient.DAEMON_MAX_TRANSIENT_FAILURES}): ${err}`);\n }\n }\n\n private async runQmdCommand(\n args: string[],\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<{ stdout: string; stderr: string }> {\n return runQmd(args, timeoutMs, this.qmdPath, signal);\n }\n\n private supportsIntentHints(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 5]);\n }\n\n private supportsExplainTraces(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [1, 1, 2]);\n }\n\n /**\n * QMD v2 (>= 2.0.0) uses a new MCP tool API:\n * - `search` and `vsearch` tools removed; only `query` tool exists\n * - `query` accepts `{ searches: [{ type, query }], collections?: string[] }`\n * instead of `{ query: string, collection?: string }`\n * - `collection` (singular) → `collections` (plural array)\n */\n private isQmdV2(): boolean {\n return versionAtLeast(parseQmdVersion(this.cliVersion), [2, 0, 0]);\n }\n\n private resolveSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n const normalized = normalizeSearchOptions(options);\n if (!normalized) return undefined;\n const resolved: SearchQueryOptions = {};\n if (normalized.intent && this.supportsIntentHints()) {\n resolved.intent = normalized.intent;\n }\n if (normalized.explain === true && this.supportsExplainTraces()) {\n resolved.explain = true;\n }\n return Object.keys(resolved).length > 0 ? resolved : undefined;\n }\n\n resolveSupportedSearchOptions(options?: SearchQueryOptions): SearchQueryOptions | undefined {\n return this.resolveSearchOptions(options);\n }\n\n async search(\n query: string,\n collection?: string,\n maxResults?: number,\n options?: SearchQueryOptions,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n const searchOptions = this.resolveSearchOptions(options);\n\n // Short-lived search result cache — avoids redundant daemon calls for\n // repeated queries within the same recall cycle (e.g., primary + hybrid\n // top-up, or conversation recall using the same collection).\n const optionsFingerprint = searchOptions ? JSON.stringify(searchOptions) : \"\";\n const cacheKey = createHash(\"sha256\").update(`${col}:${n}:${optionsFingerprint}:${trimmed}`).digest(\"hex\");\n const cached = getCachedQmdSearch(cacheKey);\n if (cached) {\n log.debug(`QMD search cache hit (${cached.length} results)`);\n return cached as QmdSearchResult[];\n }\n\n // Try daemon first (bypasses QMD_MUTEX — daemon handles its own concurrency)\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, col, n, searchOptions, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n throw err;\n }\n // When the daemon is available, trust its outcome and skip the subprocess.\n // The subprocess runs `qmd query` (BM25 + LLM expansion) which hangs at\n // 99% CPU on large collections (75K+ files) making it strictly worse than\n // the daemon for this workload. Specifically:\n // results !== null → daemon succeeded (even with 0 hits) → return as-is\n // results === null → daemon timed-out or errored → still skip subprocess\n // because subprocess will also hang or timeout\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon search returned 0 results; skipping subprocess\");\n }\n setCachedQmdSearch(cacheKey, results);\n return results;\n }\n // Daemon timed out or had a transient error — skip subprocess for large\n // collections. Return empty rather than hanging the caller.\n log.debug(\"QMD daemon search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon process is spawned but still loading (handshake not yet complete),\n // skip subprocess — it would add load and block under QMD_MUTEX without helping.\n // Return empty and let the next recheck cycle pick up the daemon once ready.\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD search: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n const subprocessResults = await this.searchViaSubprocess(trimmed, col, n, searchOptions, execution?.signal);\n setCachedQmdSearch(cacheKey, subprocessResults);\n return subprocessResults;\n }\n\n async searchGlobal(\n query: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const n = maxResults ?? 6;\n\n // Try daemon first\n await this.maybeProbeDaemon();\n if (this.daemonAvailable) {\n // Global search: no collection filter\n let results: QmdSearchResult[] | null;\n try {\n results = await this.searchViaDaemon(trimmed, undefined, n, undefined, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon global search aborted\");\n }\n throw err;\n }\n // Same rationale as search() — trust daemon outcome, skip subprocess.\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon global search returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon global search timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n\n // If the daemon is spawned but still loading, skip subprocess — same as search().\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD searchGlobal: daemon loading, skipping subprocess\");\n return [];\n }\n\n // Subprocess fallback (only reached when daemon is unavailable and not loading)\n return this.searchGlobalViaSubprocess(trimmed, n, execution?.signal);\n }\n\n /**\n * BM25 keyword search (fast, ~0.3s). Uses `qmd search`.\n */\n async bm25Search(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — BM25 via daemon is much faster than subprocess.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.bm25SearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon bm25 returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon bm25 timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD bm25: daemon loading, skipping subprocess\");\n return [];\n }\n return this.bm25SearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Vector similarity search (~3-4s). Uses `qmd vsearch`.\n */\n async vectorSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n if (!this.isAvailable()) return [];\n const trimmed = query.trim();\n if (!trimmed) return [];\n const col = collection ?? this.collection;\n const n = maxResults ?? this.maxResults;\n\n // Try daemon first — keeps models warm, avoids cold subprocess loads.\n await this.maybeProbeDaemon();\n if (this.daemonAvailable && this.daemonSession) {\n let results: QmdSearchResult[] | null;\n try {\n results = await this.vsearchViaDaemon(trimmed, col, n, execution?.signal);\n } catch (err) {\n if (isCallerCancellation(err, execution?.signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n throw err;\n }\n // When daemon is available, trust its outcome and skip subprocess (same\n // rationale as search() — subprocess hangs at 99% CPU on 75K+ files).\n if (results !== null) {\n if (results.length === 0) {\n log.debug(\"QMD daemon vsearch returned 0 results; skipping subprocess\");\n }\n return results;\n }\n log.debug(\"QMD daemon vsearch timed out/failed; skipping subprocess (daemon-only mode)\");\n return [];\n }\n if (this.daemonSession?.isLoading()) {\n log.debug(\"QMD vsearch: daemon loading, skipping subprocess\");\n return [];\n }\n return this.vsearchViaSubprocess(trimmed, col, n, execution?.signal);\n }\n\n /**\n * Hybrid search: runs BM25 + vector in parallel, merges/dedupes by path\n * keeping the best score and first non-empty snippet.\n */\n async hybridSearch(\n query: string,\n collection?: string,\n maxResults?: number,\n execution?: SearchExecutionOptions,\n ): Promise<QmdSearchResult[]> {\n const n = maxResults ?? this.maxResults;\n const trimmed = query.trim();\n if (!trimmed) return [];\n\n const [bm25Results, vectorResults] = await Promise.all([\n this.bm25Search(trimmed, collection, n, execution),\n this.vectorSearch(trimmed, collection, n, execution),\n ]);\n\n // Merge by path, keeping best score\n const merged = new Map<string, QmdSearchResult>();\n for (const r of [...bm25Results, ...vectorResults]) {\n const key = r.path || r.docid;\n const existing = merged.get(key);\n if (!existing || r.score > existing.score) {\n merged.set(key, {\n ...r,\n snippet: r.snippet || existing?.snippet || \"\",\n });\n }\n }\n\n // Sort by score descending, take top N\n return [...merged.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, n);\n }\n\n private async searchViaDaemon(\n query: string,\n collection: string | undefined,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let args: Record<string, unknown>;\n if (v2) {\n // QMD v2: query tool expects { searches: [...], collections?: [...] }\n // A plain query without type prefix uses LLM auto-expansion on the daemon side\n const searches: Array<{ type: string; query: string }> = [{ type: \"lex\", query }];\n // Add a vec sub-query for hybrid recall (mirrors v1 behavior)\n searches.push({ type: \"vec\", query });\n args = { searches, limit: maxResults };\n if (collection) {\n args.collections = [collection];\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n } else {\n // QMD v1: query tool accepts { query, collection?, limit }\n args = { query, limit: maxResults };\n if (collection) {\n args.collection = collection;\n }\n if (options?.intent) {\n args.intent = options.intent;\n }\n if (options?.explain === true) {\n args.explain = true;\n }\n }\n\n const result = await this.daemonSession.callTool(\"query\", args, QMD_DAEMON_TIMEOUT_MS, signal);\n const durationMs = Date.now() - startedAtMs;\n\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD daemon query: durationMs=${durationMs} collection=${collection ?? \"global\"} maxResults=${maxResults} queryChars=${query.length} v2=${v2}`,\n );\n }\n\n const results = parseMcpSearchResult(result, \"daemon\");\n\n log.debug(`QMD daemon search: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon search aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon search aborted\");\n }\n // Timeout: don't invalidate session — daemon is still running, just slow.\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon search timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n // Transient error: tolerate a few before invalidating.\n this.handleDaemonTransientError(\"search\", err, durationMs);\n return null;\n }\n }\n\n private async bm25SearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `search` tool — use `query` with lex-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"lex\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `search` tool for BM25\n result = await this.daemonSession.callTool(\n \"search\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon bm25: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon bm25 aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon bm25 aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon bm25 timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"bm25\", err, durationMs);\n return null;\n }\n }\n\n private async vsearchViaDaemon(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[] | null> {\n if (!this.daemonSession || !this.daemonAvailable) return null;\n\n const startedAtMs = Date.now();\n const v2 = this.isQmdV2();\n try {\n let result: unknown;\n if (v2) {\n // QMD v2: no `vsearch` tool — use `query` with vec-only sub-query\n result = await this.daemonSession.callTool(\n \"query\",\n {\n searches: [{ type: \"vec\", query }],\n collections: [collection],\n limit: maxResults,\n },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n } else {\n // QMD v1: dedicated `vsearch` tool for vector search\n result = await this.daemonSession.callTool(\n \"vsearch\",\n { query, limit: maxResults, collection },\n QMD_DAEMON_TIMEOUT_MS,\n signal,\n );\n }\n const durationMs = Date.now() - startedAtMs;\n const results = parseMcpSearchResult(result);\n log.debug(`QMD daemon vsearch: ${results.length} results in ${durationMs}ms (v2=${v2})`);\n this.recordDaemonSuccess();\n return results;\n } catch (err) {\n const durationMs = Date.now() - startedAtMs;\n if (isCallerCancellation(err, signal)) {\n log.debug(`QMD daemon vsearch aborted/cancelled after ${durationMs}ms`);\n throw isAbortError(err) ? err : abortError(\"QMD daemon vsearch aborted\");\n }\n if (isDaemonTimeoutError(err)) {\n log.debug(`QMD daemon vsearch timed out after ${durationMs}ms, falling back to subprocess`);\n return null;\n }\n this.handleDaemonTransientError(\"vsearch\", err, durationMs);\n return null;\n }\n }\n\n private async searchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n options?: SearchQueryOptions,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const args = [\"query\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)];\n if (options?.intent) {\n args.push(\"--intent\", options.intent);\n }\n if (options?.explain === true) {\n args.push(\"--explain\");\n }\n const { stdout } = await runQmd(\n args,\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD query: durationMs=${durationMs} collection=${collection} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout, \"subprocess\");\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess search aborted\");\n }\n log.debug(`QMD search failed: ${err}`);\n return [];\n }\n }\n\n private async bm25SearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"search\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD bm25: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess bm25 aborted\");\n }\n log.debug(`QMD bm25 search failed: ${err}`);\n return [];\n }\n }\n\n private async vsearchViaSubprocess(\n query: string,\n collection: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"vsearch\", query, \"-c\", collection, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n log.debug(`QMD vsearch: ${Date.now() - startedAtMs}ms`);\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess vsearch aborted\");\n }\n log.debug(`QMD vsearch failed: ${err}`);\n return [];\n }\n }\n\n private async searchGlobalViaSubprocess(\n query: string,\n maxResults: number,\n signal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n if (this.available === false) return [];\n\n const startedAtMs = Date.now();\n try {\n const { stdout } = await runQmd(\n [\"query\", query, \"--json\", \"-n\", String(maxResults)],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n signal,\n );\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(\n `SLOW QMD global query: durationMs=${durationMs} maxResults=${maxResults} queryChars=${query.length}`,\n );\n }\n\n return parseQmdSearchStdout(stdout);\n } catch (err) {\n if (isCallerCancellation(err, signal)) {\n throw isAbortError(err) ? err : abortError(\"QMD subprocess global search aborted\");\n }\n log.debug(`QMD global search failed: ${err}`);\n return [];\n }\n }\n\n async update(execution?: SearchExecutionOptions): Promise<void> {\n await this.runUpdateForCollection(\n this.collection,\n { perCollectionThrottle: false },\n execution?.signal,\n );\n }\n\n async updateCollection(\n collection: string,\n execution?: SearchExecutionOptions,\n ): Promise<void> {\n await this.runUpdateForCollection(\n collection,\n { perCollectionThrottle: true },\n execution?.signal,\n );\n }\n\n private async runUpdateForCollection(\n collection: string,\n options: { perCollectionThrottle: boolean },\n signal?: AbortSignal,\n ): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (options.perCollectionThrottle) {\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n const lastCollectionRun = globalState.lastUpdateByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD update: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastUpdateFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(`QMD update: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n } else {\n if (\n this.lastUpdateRunAtMs &&\n now - this.lastUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed due to min-interval gate\");\n return;\n }\n if (\n this._lastUpdateFailAtMs &&\n now - this._lastUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalUpdateRunAtMs &&\n now - globalState.lastGlobalUpdateRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD update: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalUpdateFailAtMs &&\n now - globalState.lastGlobalUpdateFailAtMs < QMD_UPDATE_BACKOFF_MS\n ) {\n log.debug(\"QMD update: suppressed by global failure backoff\");\n return;\n }\n }\n try {\n if (!globalState.warnedGlobalUpdateBehavior) {\n globalState.warnedGlobalUpdateBehavior = true;\n log.warn(\n \"QMD update runs globally across collections in current CLI versions; Engram now rate-limits update calls to reduce gateway load.\",\n );\n }\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"update\", \"-c\", name], this.updateTimeoutMs, signal);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD update: durationMs=${durationMs}`);\n }\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateByCollectionMs[name] = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n } else {\n this.lastUpdateRunAtMs = at;\n globalState.lastGlobalUpdateRunAtMs = at;\n }\n log.debug(`QMD update completed for collection=${name}`);\n } catch (err) {\n const at = Date.now();\n if (options.perCollectionThrottle) {\n globalState.lastUpdateFailByCollectionMs[name] = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n } else {\n this._lastUpdateFailAtMs = at;\n globalState.lastGlobalUpdateFailAtMs = at;\n }\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD update failed for collection ${name}: ${msg}`);\n }\n }\n\n async embed(): Promise<void> {\n if (this.available === false) return;\n const globalState = getGlobalQmdState();\n if (\n this.lastEmbedFailAtMs &&\n Date.now() - this.lastEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed due to recent failures (backoff)\");\n return;\n }\n if (\n globalState.lastGlobalEmbedRunAtMs &&\n Date.now() - globalState.lastGlobalEmbedRunAtMs < this.updateMinIntervalMs\n ) {\n log.debug(\"QMD embed: suppressed by global min-interval gate\");\n return;\n }\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n Date.now() - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(\"QMD embed: suppressed by global failure backoff\");\n return;\n }\n try {\n const startedAtMs = Date.now();\n await this.runQmdCommand([\"embed\", \"-c\", this.collection], 300_000);\n const durationMs = Date.now() - startedAtMs;\n if (this.slowLog?.enabled && durationMs >= this.slowLog.thresholdMs) {\n log.warn(`SLOW QMD embed: durationMs=${durationMs}`);\n }\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n log.debug(\"QMD embed completed\");\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(\"QMD embed hit a vector dimension mismatch; retrying with force re-embed\");\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", this.collection], 300_000);\n globalState.lastGlobalEmbedRunAtMs = Date.now();\n this.lastEmbedFailAtMs = null;\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(\"QMD embed recovered by forcing a full vector rebuild\");\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed after dimension mismatch: ${retryMsg}`);\n }\n }\n const now = Date.now();\n this.lastEmbedFailAtMs = now;\n globalState.lastGlobalEmbedFailAtMs = now;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed: ${msg}`);\n }\n }\n\n async embedCollection(collection: string): Promise<void> {\n if (this.available === false) return;\n const name = collection.trim();\n if (!name) return;\n const globalState = getGlobalQmdState();\n const now = Date.now();\n if (\n globalState.lastGlobalEmbedFailAtMs &&\n now - globalState.lastGlobalEmbedFailAtMs < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by global failure backoff (${name})`);\n return;\n }\n const lastCollectionRun = globalState.lastEmbedByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionRun) &&\n now - lastCollectionRun < this.updateMinIntervalMs\n ) {\n log.debug(`QMD embed: suppressed by per-collection min-interval gate (${name})`);\n return;\n }\n const lastCollectionFail = globalState.lastEmbedFailByCollectionMs[name];\n if (\n Number.isFinite(lastCollectionFail) &&\n now - lastCollectionFail < QMD_EMBED_BACKOFF_MS\n ) {\n log.debug(`QMD embed: suppressed by per-collection failure backoff (${name})`);\n return;\n }\n try {\n await this.runQmdCommand([\"embed\", \"-c\", name], 300_000);\n const at = Date.now();\n globalState.lastEmbedByCollectionMs[name] = at;\n globalState.lastGlobalEmbedRunAtMs = at;\n } catch (err) {\n if (isVectorDimensionMismatchError(err)) {\n try {\n log.warn(`QMD embed for collection ${name} hit a vector dimension mismatch; retrying with force re-embed`);\n await this.runQmdCommand([\"embed\", \"-f\", \"-c\", name], 300_000);\n const recoveredAt = Date.now();\n globalState.lastEmbedByCollectionMs[name] = recoveredAt;\n globalState.lastGlobalEmbedRunAtMs = recoveredAt;\n delete globalState.lastEmbedFailByCollectionMs[name];\n globalState.lastGlobalEmbedFailAtMs = null;\n log.warn(`QMD embed for collection ${name} recovered by forcing a full vector rebuild`);\n return;\n } catch (retryErr) {\n const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);\n log.warn(`QMD force re-embed failed for collection ${name}: ${retryMsg}`);\n }\n }\n const at = Date.now();\n globalState.lastEmbedFailByCollectionMs[name] = at;\n globalState.lastGlobalEmbedFailAtMs = at;\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`QMD embed failed for collection ${name}: ${msg}`);\n }\n }\n\n async ensureCollection(memoryDir: string): Promise<\"present\" | \"missing\" | \"unknown\" | \"skipped\"> {\n if (this.available === false && !this.daemonAvailable) return \"unknown\";\n // If only daemon is available (no CLI), skip collection check\n if (this.available === false) return \"skipped\";\n try {\n const { stdout } = await runQmd(\n [\"collection\", \"list\"],\n QMD_TIMEOUT_MS,\n this.qmdPath,\n );\n // Parse text output: \"openclaw-engram (qmd://openclaw-engram/)\"\n const collectionRegex = new RegExp(\n `^${this.collection}\\\\s+\\\\(qmd://`,\n \"m\",\n );\n if (collectionRegex.test(stdout)) {\n return \"present\";\n }\n } catch (err) {\n // Treat command/probe failures as unknown so callers do not disable features\n // permanently after a transient CLI or daemon hiccup.\n log.debug(\n `QMD collection check unavailable for \"${this.collection}\" (will not disable features): ${err instanceof Error ? err.message : String(err)}`,\n );\n return \"unknown\";\n }\n\n log.info(\n `QMD collection \"${this.collection}\" not found. ` +\n `Add it to ~/.config/qmd/index.yml pointing at ${memoryDir}`,\n );\n return \"missing\";\n }\n}\n"],"mappings":"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","names":[]}