@snoai/memory 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (478) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +7 -2
  3. package/config/b-profile-section-registry.json +118 -0
  4. package/config/llm/compiled/2026-05-19T230932Z/manifest.json +25 -0
  5. package/config/llm/compiled/2026-05-19T230932Z/registry-root.json +67 -0
  6. package/config/llm/compiled/2026-05-19T230932Z/resolved/mem_claw/openai_gpt_5_nano.json +5 -0
  7. package/config/llm/compiled/2026-05-19T230932Z/resolved/mem_claw/openrouter_auto.json +5 -0
  8. package/config/llm/compiled/2026-05-19T230932Z/resolved/mem_claw/sno_ai_extract.json +5 -0
  9. package/config/llm/compiled/2026-05-19T230932Z/source/mem_claw/openai_gpt_5_nano.mda +24 -0
  10. package/config/llm/compiled/2026-05-19T230932Z/source/mem_claw/openrouter_auto.mda +24 -0
  11. package/config/llm/compiled/2026-05-19T230932Z/source/mem_claw/sno_ai_extract.mda +24 -0
  12. package/config/llm/compiled/2026-07-21T001311Z/manifest.json +43 -0
  13. package/config/llm/compiled/2026-07-21T001311Z/registry-root.json +97 -0
  14. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/openai_gpt_5_nano.json +5 -0
  15. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/openrouter_auto.json +5 -0
  16. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/sno_ai_extract.json +5 -0
  17. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/sno_conflict_verdict.json +10 -0
  18. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/sno_extract_chat.json +10 -0
  19. package/config/llm/compiled/2026-07-21T001311Z/resolved/mem_claw/sno_extract_profile.json +10 -0
  20. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/openai_gpt_5_nano.mda +24 -0
  21. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/openrouter_auto.mda +24 -0
  22. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/sno_ai_extract.mda +24 -0
  23. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/sno_conflict_verdict.mda +27 -0
  24. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/sno_extract_chat.mda +27 -0
  25. package/config/llm/compiled/2026-07-21T001311Z/source/mem_claw/sno_extract_profile.mda +27 -0
  26. package/config/llm/compiled/2026-08-29T060335Z/manifest.json +43 -0
  27. package/config/llm/compiled/2026-08-29T060335Z/registry-root.json +97 -0
  28. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/openai_gpt_5_nano.json +5 -0
  29. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/openrouter_auto.json +5 -0
  30. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/sno_ai_extract.json +5 -0
  31. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/sno_conflict_verdict.json +10 -0
  32. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/sno_extract_chat.json +10 -0
  33. package/config/llm/compiled/2026-08-29T060335Z/resolved/mem_claw/sno_extract_profile.json +10 -0
  34. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/openai_gpt_5_nano.mda +24 -0
  35. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/openrouter_auto.mda +24 -0
  36. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/sno_ai_extract.mda +24 -0
  37. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/sno_conflict_verdict.mda +27 -0
  38. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/sno_extract_chat.mda +27 -0
  39. package/config/llm/compiled/2026-08-29T060335Z/source/mem_claw/sno_extract_profile.mda +27 -0
  40. package/config/llm/compiled/2026-09-04T004828Z/manifest.json +43 -0
  41. package/config/llm/compiled/2026-09-04T004828Z/registry-root.json +97 -0
  42. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/openai_gpt_5_nano.json +5 -0
  43. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/openrouter_auto.json +5 -0
  44. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/sno_ai_extract.json +5 -0
  45. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/sno_conflict_verdict.json +10 -0
  46. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/sno_extract_chat.json +10 -0
  47. package/config/llm/compiled/2026-09-04T004828Z/resolved/mem_claw/sno_extract_profile.json +10 -0
  48. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/openai_gpt_5_nano.mda +24 -0
  49. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/openrouter_auto.mda +24 -0
  50. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/sno_ai_extract.mda +24 -0
  51. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/sno_conflict_verdict.mda +27 -0
  52. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/sno_extract_chat.mda +27 -0
  53. package/config/llm/compiled/2026-09-04T004828Z/source/mem_claw/sno_extract_profile.mda +27 -0
  54. package/config/llm/current.json +4 -0
  55. package/config/llm/source/mem_claw/openai_gpt_5_nano.mda +24 -0
  56. package/config/llm/source/mem_claw/openrouter_auto.mda +24 -0
  57. package/config/llm/source/mem_claw/sno_ai_extract.mda +24 -0
  58. package/config/llm/source/mem_claw/sno_conflict_verdict.mda +27 -0
  59. package/config/llm/source/mem_claw/sno_extract_chat.mda +27 -0
  60. package/config/llm/source/mem_claw/sno_extract_profile.mda +27 -0
  61. package/config/llm.trust.json +37 -0
  62. package/dist/_types-CUKHSRkS.d.ts +103 -0
  63. package/dist/access-tracker-CSc21GtV.d.ts +110 -0
  64. package/dist/adapter-DMEmCTKo.d.ts +69 -0
  65. package/dist/adapter-XaRHZWZ2.js +333 -0
  66. package/dist/agent-llm-port-5oXgBpzJ.d.ts +53 -0
  67. package/dist/all-resources-BQK2ugjB.js +6379 -0
  68. package/dist/all-resources-Dij6l5h0.d.ts +18 -0
  69. package/dist/ambient-learning-text-normalizer-CxjATmMp.js +170 -0
  70. package/dist/ambient-learning-text-normalizer-_fH3LeuK.d.ts +10 -0
  71. package/dist/atomic-extraction-reply-BJ9XV_9s.js +863 -0
  72. package/dist/atomic-extraction-skill-CcXmuCqL.js +56 -0
  73. package/dist/atomic-memory-extraction-BpOUWPJM.d.ts +327 -0
  74. package/dist/atomic-memory-extraction-sdNf1-B1.js +3605 -0
  75. package/dist/b-profile-section-dictionary-provider-BHkoNqgk.js +1812 -0
  76. package/dist/b-profile-section-dictionary-provider-BxbksLj3.d.ts +62 -0
  77. package/dist/best-effort-BPZSzKk0.d.ts +9 -0
  78. package/dist/calendar-instruction-CzqZbAPG.js +194 -0
  79. package/dist/capture-policy-detector-CHz5GOPA.d.ts +53 -0
  80. package/dist/capture-policy-detector-DaMfy9CZ.js +357 -0
  81. package/dist/classifier-C96uH9OF.d.ts +272 -0
  82. package/dist/client.d.ts +34 -0
  83. package/dist/client.js +305 -0
  84. package/dist/coding-skin.d.ts +51 -0
  85. package/dist/coding-skin.js +55 -0
  86. package/dist/config-tSrvLXgV.js +2577 -0
  87. package/dist/connection-DAbzki8K.d.ts +391 -0
  88. package/dist/connection-DliCOBB2.js +297 -0
  89. package/dist/daily-log-generator-CH_KuWHs.js +469 -0
  90. package/dist/daily-log-generator-CsQPHl4A.d.ts +73 -0
  91. package/dist/daily-spend-estimator-DiwzBlo1.d.ts +8 -0
  92. package/dist/data-bootstrap-CYniFp8b.js +172 -0
  93. package/dist/data-bootstrap-CcJUwkqf.d.ts +30 -0
  94. package/dist/data-paths-C7sNdqvP.d.ts +22 -0
  95. package/dist/derived-suppression-cache-C7bGARc0.d.ts +36 -0
  96. package/dist/diagnostic-encoder.d.ts +6 -0
  97. package/dist/diagnostic-encoder.js +29 -0
  98. package/dist/embedding-provider-client-Q_hJonK9.js +294 -0
  99. package/dist/embedding-provider-client-vynZMuit.d.ts +94 -0
  100. package/dist/entry-metadata-parser-BIVSMCIk.js +20 -0
  101. package/dist/error-D-wb-rZw.js +23 -0
  102. package/dist/error-signals-D8_3vYu4.d.ts +28 -0
  103. package/dist/error-signals-lMH2uAdV.js +134 -0
  104. package/dist/errors-CeVRxf9V.d.ts +49 -0
  105. package/dist/extraction-text-sanitizer-B_AhIecT.d.ts +32 -0
  106. package/dist/i18n-text-DbD6Qify.d.ts +13 -0
  107. package/dist/index-BsMap4It.d.ts +650 -0
  108. package/dist/index-DL8AVj0Z.d.ts +571 -0
  109. package/dist/index-DQ7VL6d3.d.ts +350 -0
  110. package/dist/index.d.ts +65 -0
  111. package/dist/index.js +1201 -0
  112. package/dist/intent-analyzer-B5XVrWwe.d.ts +28 -0
  113. package/dist/internal/config/index.d.ts +2 -0
  114. package/dist/internal/config/index.js +581 -0
  115. package/dist/internal/config/plugin-config-schema.d.ts +2 -0
  116. package/dist/internal/config/plugin-config-schema.js +2 -0
  117. package/dist/internal/config/product-mode.d.ts +2 -0
  118. package/dist/internal/config/product-mode.js +36 -0
  119. package/dist/internal/config/settings.d.ts +2 -0
  120. package/dist/internal/config/settings.js +265 -0
  121. package/dist/internal/config/skill-categories.d.ts +4 -0
  122. package/dist/internal/config/skill-categories.js +68 -0
  123. package/dist/internal/config/skin-defaults.d.ts +6 -0
  124. package/dist/internal/config/skin-defaults.js +6 -0
  125. package/dist/internal/contract/discovery.d.ts +10 -0
  126. package/dist/internal/contract/discovery.js +53 -0
  127. package/dist/internal/contract/profile.d.ts +2 -0
  128. package/dist/internal/contract/profile.js +44 -0
  129. package/dist/internal/contract/routes.d.ts +2 -0
  130. package/dist/internal/contract/routes.js +61 -0
  131. package/dist/internal/engine/bindings/memory-cli-shared.d.ts +47 -0
  132. package/dist/internal/engine/bindings/memory-cli-shared.js +84 -0
  133. package/dist/internal/engine/bindings/memory-forget-tool.d.ts +5 -0
  134. package/dist/internal/engine/bindings/memory-forget-tool.js +66 -0
  135. package/dist/internal/engine/bindings/memory-list-tool.d.ts +5 -0
  136. package/dist/internal/engine/bindings/memory-list-tool.js +57 -0
  137. package/dist/internal/engine/bindings/memory-recall-tool.d.ts +10 -0
  138. package/dist/internal/engine/bindings/memory-recall-tool.js +283 -0
  139. package/dist/internal/engine/bindings/memory-reflection-resolve-tool.d.ts +5 -0
  140. package/dist/internal/engine/bindings/memory-reflection-resolve-tool.js +150 -0
  141. package/dist/internal/engine/bindings/memory-stats-tool.d.ts +5 -0
  142. package/dist/internal/engine/bindings/memory-stats-tool.js +43 -0
  143. package/dist/internal/engine/bindings/memory-store-tool.d.ts +5 -0
  144. package/dist/internal/engine/bindings/memory-store-tool.js +165 -0
  145. package/dist/internal/engine/bindings/memory-tool-access.d.ts +16 -0
  146. package/dist/internal/engine/bindings/memory-tool-access.js +46 -0
  147. package/dist/internal/engine/bindings/memory-tool-formatting.d.ts +62 -0
  148. package/dist/internal/engine/bindings/memory-tool-formatting.js +106 -0
  149. package/dist/internal/engine/bindings/memory-tool-results.d.ts +8 -0
  150. package/dist/internal/engine/bindings/memory-tool-results.js +41 -0
  151. package/dist/internal/engine/bindings/memory-tool-schemas.d.ts +109 -0
  152. package/dist/internal/engine/bindings/memory-tool-schemas.js +75 -0
  153. package/dist/internal/engine/bindings/memory-update-tool.d.ts +5 -0
  154. package/dist/internal/engine/bindings/memory-update-tool.js +127 -0
  155. package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.d.ts +14 -0
  156. package/dist/internal/engine/bindings/sno-station-mem-ambient-learning-hook.js +248 -0
  157. package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.d.ts +12 -0
  158. package/dist/internal/engine/bindings/sno-station-mem-auto-recall-hook.js +324 -0
  159. package/dist/internal/engine/bindings/sno-station-mem-hook-types.d.ts +56 -0
  160. package/dist/internal/engine/bindings/sno-station-mem-hook-types.js +1 -0
  161. package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.d.ts +14 -0
  162. package/dist/internal/engine/bindings/sno-station-mem-insight-distill-factory.js +119 -0
  163. package/dist/internal/engine/bindings/sno-station-mem-message-transcript.d.ts +52 -0
  164. package/dist/internal/engine/bindings/sno-station-mem-message-transcript.js +145 -0
  165. package/dist/internal/engine/bindings/sno-station-mem-reset-hook.d.ts +10 -0
  166. package/dist/internal/engine/bindings/sno-station-mem-reset-hook.js +9 -0
  167. package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.d.ts +37 -0
  168. package/dist/internal/engine/bindings/sno-station-mem-runtime-mode.js +105 -0
  169. package/dist/internal/engine/bindings/sno-station-mem-session-state.d.ts +10 -0
  170. package/dist/internal/engine/bindings/sno-station-mem-session-state.js +27 -0
  171. package/dist/internal/engine/eval/trace.d.ts +2 -0
  172. package/dist/internal/engine/eval/trace.js +151 -0
  173. package/dist/internal/engine/extraction/ambient-learning-text-normalizer.d.ts +2 -0
  174. package/dist/internal/engine/extraction/ambient-learning-text-normalizer.js +2 -0
  175. package/dist/internal/engine/extraction/atomic-memory-extraction.d.ts +2 -0
  176. package/dist/internal/engine/extraction/atomic-memory-extraction.js +2 -0
  177. package/dist/internal/engine/extraction/b-profile-section-dictionary-provider.d.ts +2 -0
  178. package/dist/internal/engine/extraction/b-profile-section-dictionary-provider.js +2 -0
  179. package/dist/internal/engine/extraction/b-profile-section-rekey.d.ts +49 -0
  180. package/dist/internal/engine/extraction/b-profile-section-rekey.js +730 -0
  181. package/dist/internal/engine/extraction/capture-policy-detector.d.ts +2 -0
  182. package/dist/internal/engine/extraction/capture-policy-detector.js +2 -0
  183. package/dist/internal/engine/extraction/embedding-provider-client.d.ts +2 -0
  184. package/dist/internal/engine/extraction/embedding-provider-client.js +2 -0
  185. package/dist/internal/engine/extraction/extraction-text-sanitizer.d.ts +2 -0
  186. package/dist/internal/engine/extraction/extraction-text-sanitizer.js +114 -0
  187. package/dist/internal/engine/extraction/memory-metadata-codec.d.ts +3 -0
  188. package/dist/internal/engine/extraction/memory-metadata-codec.js +2 -0
  189. package/dist/internal/engine/extraction/memory-temporality-classifier.d.ts +2 -0
  190. package/dist/internal/engine/extraction/memory-temporality-classifier.js +2 -0
  191. package/dist/internal/engine/i18n/all-resources.d.ts +2 -0
  192. package/dist/internal/engine/i18n/all-resources.js +2 -0
  193. package/dist/internal/engine/i18n/locales.d.ts +2 -0
  194. package/dist/internal/engine/i18n/locales.js +19 -0
  195. package/dist/internal/engine/i18n/res/_types.d.ts +2 -0
  196. package/dist/internal/engine/i18n/res/_types.js +11 -0
  197. package/dist/internal/engine/observability/adapter.d.ts +2 -0
  198. package/dist/internal/engine/observability/adapter.js +2 -0
  199. package/dist/internal/engine/observability/best-effort.d.ts +2 -0
  200. package/dist/internal/engine/observability/best-effort.js +41 -0
  201. package/dist/internal/engine/observability/early-diagnostics.js +2 -0
  202. package/dist/internal/engine/observability/memory-snapshot.d.ts +2 -0
  203. package/dist/internal/engine/observability/memory-snapshot.js +44 -0
  204. package/dist/internal/engine/observability/observable-embedder.d.ts +2 -0
  205. package/dist/internal/engine/observability/observable-embedder.js +43 -0
  206. package/dist/internal/engine/observability/observable-llm-client.d.ts +2 -0
  207. package/dist/internal/engine/observability/observable-llm-client.js +98 -0
  208. package/dist/internal/engine/observability/observable-memory-store.d.ts +2 -0
  209. package/dist/internal/engine/observability/observable-memory-store.js +701 -0
  210. package/dist/internal/engine/observability/observable-retriever.d.ts +2 -0
  211. package/dist/internal/engine/observability/observable-retriever.js +95 -0
  212. package/dist/internal/engine/observability/runtime-diagnostics.d.ts +13 -0
  213. package/dist/internal/engine/observability/runtime-diagnostics.js +96 -0
  214. package/dist/internal/engine/observability/session-registry.d.ts +2 -0
  215. package/dist/internal/engine/observability/session-registry.js +58 -0
  216. package/dist/internal/engine/observability/version-metadata.d.ts +7 -0
  217. package/dist/internal/engine/observability/version-metadata.js +59 -0
  218. package/dist/internal/engine/operations/daily-spend-estimator.d.ts +2 -0
  219. package/dist/internal/engine/operations/daily-spend-estimator.js +97 -0
  220. package/dist/internal/engine/operations/learning-file-maintenance.d.ts +2 -0
  221. package/dist/internal/engine/operations/learning-file-maintenance.js +255 -0
  222. package/dist/internal/engine/operations/memory-tier-promoter.d.ts +2 -0
  223. package/dist/internal/engine/operations/memory-tier-promoter.js +95 -0
  224. package/dist/internal/engine/operations/runtime-audit-log.d.ts +3 -0
  225. package/dist/internal/engine/operations/runtime-audit-log.js +3 -0
  226. package/dist/internal/engine/provider/canonical-memory-corpus.d.ts +38 -0
  227. package/dist/internal/engine/provider/canonical-memory-corpus.js +253 -0
  228. package/dist/internal/engine/provider/provider-registration.d.ts +39 -0
  229. package/dist/internal/engine/provider/provider-registration.js +2 -0
  230. package/dist/internal/engine/provider/provider-row-renderer.d.ts +7 -0
  231. package/dist/internal/engine/provider/provider-row-renderer.js +53 -0
  232. package/dist/internal/engine/provider/provider-types.d.ts +2 -0
  233. package/dist/internal/engine/provider/provider-types.js +1 -0
  234. package/dist/internal/engine/reflection/daily-log-generator.d.ts +2 -0
  235. package/dist/internal/engine/reflection/daily-log-generator.js +2 -0
  236. package/dist/internal/engine/reflection/reflection-command-hooks.d.ts +2 -0
  237. package/dist/internal/engine/reflection/reflection-command-hooks.js +2 -0
  238. package/dist/internal/engine/reflection/reflection-deps.d.ts +2 -0
  239. package/dist/internal/engine/reflection/reflection-deps.js +1 -0
  240. package/dist/internal/engine/reflection/reflection-embedded-generator.d.ts +2 -0
  241. package/dist/internal/engine/reflection/reflection-embedded-generator.js +2 -0
  242. package/dist/internal/engine/reflection/reflection-injection-hooks.d.ts +2 -0
  243. package/dist/internal/engine/reflection/reflection-injection-hooks.js +219 -0
  244. package/dist/internal/engine/reflection/reflection-lifecycle-hooks.d.ts +2 -0
  245. package/dist/internal/engine/reflection/reflection-lifecycle-hooks.js +63 -0
  246. package/dist/internal/engine/reflection/strategy-hook-runner.d.ts +4 -0
  247. package/dist/internal/engine/reflection/strategy-hook-runner.js +3 -0
  248. package/dist/internal/engine/rem/classifier.d.ts +2 -0
  249. package/dist/internal/engine/rem/classifier.js +180 -0
  250. package/dist/internal/engine/rem/index.d.ts +4 -0
  251. package/dist/internal/engine/rem/index.js +2551 -0
  252. package/dist/internal/engine/rem/types.d.ts +2 -0
  253. package/dist/internal/engine/rem/types.js +40 -0
  254. package/dist/internal/engine/retrieval/access-tracker.d.ts +2 -0
  255. package/dist/internal/engine/retrieval/access-tracker.js +314 -0
  256. package/dist/internal/engine/retrieval/intent-analyzer.d.ts +2 -0
  257. package/dist/internal/engine/retrieval/intent-analyzer.js +27 -0
  258. package/dist/internal/engine/retrieval/retrieval-gate.d.ts +2 -0
  259. package/dist/internal/engine/retrieval/retrieval-gate.js +47 -0
  260. package/dist/internal/engine/retrieval/retriever.d.ts +2 -0
  261. package/dist/internal/engine/retrieval/retriever.js +2 -0
  262. package/dist/internal/engine/security/memory-scope-policy.d.ts +2 -0
  263. package/dist/internal/engine/security/memory-scope-policy.js +2 -0
  264. package/dist/internal/engine/security/redact.d.ts +2 -0
  265. package/dist/internal/engine/security/redact.js +34 -0
  266. package/dist/internal/engine/security/scopes.d.ts +3 -0
  267. package/dist/internal/engine/security/scopes.js +3 -0
  268. package/dist/internal/engine/shared/errors.d.ts +2 -0
  269. package/dist/internal/engine/shared/errors.js +66 -0
  270. package/dist/internal/engine/shared/i18n-text.d.ts +2 -0
  271. package/dist/internal/engine/shared/i18n-text.js +58 -0
  272. package/dist/internal/engine/shared/iso-date-time.d.ts +16 -0
  273. package/dist/internal/engine/shared/iso-date-time.js +40 -0
  274. package/dist/internal/engine/shared/lru.d.ts +2 -0
  275. package/dist/internal/engine/shared/lru.js +30 -0
  276. package/dist/internal/engine/shared/memory-kind-policy.d.ts +2 -0
  277. package/dist/internal/engine/shared/memory-kind-policy.js +64 -0
  278. package/dist/internal/engine/shared/paths.d.ts +3 -0
  279. package/dist/internal/engine/shared/paths.js +2 -0
  280. package/dist/internal/engine/shared/types.d.ts +3 -0
  281. package/dist/internal/engine/shared/types.js +25 -0
  282. package/dist/internal/engine/shared/utils.d.ts +2 -0
  283. package/dist/internal/engine/shared/utils.js +175 -0
  284. package/dist/internal/engine/telemetry/memory-telemetry-api.d.ts +134 -0
  285. package/dist/internal/engine/telemetry/memory-telemetry-api.js +730 -0
  286. package/dist/internal/engine/telemetry/memory-telemetry-observability.d.ts +24 -0
  287. package/dist/internal/engine/telemetry/memory-telemetry-observability.js +133 -0
  288. package/dist/internal/engine/telemetry/memory-telemetry-outbox.d.ts +2 -0
  289. package/dist/internal/engine/telemetry/memory-telemetry-outbox.js +443 -0
  290. package/dist/internal/engine/telemetry/memory-telemetry-types.d.ts +2 -0
  291. package/dist/internal/engine/telemetry/memory-telemetry-types.js +21 -0
  292. package/dist/internal/engine/telemetry/observe-ledger.d.ts +30 -0
  293. package/dist/internal/engine/telemetry/observe-ledger.js +111 -0
  294. package/dist/internal/model/agent-llm-port.d.ts +2 -0
  295. package/dist/internal/model/agent-llm-port.js +1 -0
  296. package/dist/internal/model/llm-client.d.ts +3 -0
  297. package/dist/internal/model/llm-client.js +3 -0
  298. package/dist/internal/model/llm-failure.d.ts +26 -0
  299. package/dist/internal/model/llm-failure.js +63 -0
  300. package/dist/internal/model/llm-mode-routing.d.ts +22 -0
  301. package/dist/internal/model/llm-mode-routing.js +37 -0
  302. package/dist/internal/store/atomic-memory-cutover-sql.d.ts +13 -0
  303. package/dist/internal/store/atomic-memory-cutover-sql.js +237 -0
  304. package/dist/internal/store/connection.d.ts +2 -0
  305. package/dist/internal/store/connection.js +2 -0
  306. package/dist/internal/store/data-bootstrap.d.ts +2 -0
  307. package/dist/internal/store/data-bootstrap.js +2 -0
  308. package/dist/internal/store/data-paths.d.ts +2 -0
  309. package/dist/internal/store/data-paths.js +65 -0
  310. package/dist/internal/store/maintenance.d.ts +75 -0
  311. package/dist/internal/store/maintenance.js +1401 -0
  312. package/dist/internal/store/memory-kinds-cutover-migrator.d.ts +28 -0
  313. package/dist/internal/store/memory-kinds-cutover-migrator.js +415 -0
  314. package/dist/internal/store/migrations.d.ts +27 -0
  315. package/dist/internal/store/migrations.js +201 -0
  316. package/dist/internal/store/sqlite-runtime.d.ts +2 -0
  317. package/dist/internal/store/sqlite-runtime.js +109 -0
  318. package/dist/internal/store/store.d.ts +3 -0
  319. package/dist/internal/store/store.js +2 -0
  320. package/dist/learning-file-maintenance-9b-Ut6Kv.d.ts +30 -0
  321. package/dist/llm-client-B7Xoxqou.js +1378 -0
  322. package/dist/llm-client-DOTSGzhe.d.ts +51 -0
  323. package/dist/locales-JxGmkG6t.d.ts +7 -0
  324. package/dist/log-site-catalog.generated-B9WYdnAM.js +2321 -0
  325. package/dist/log-site-catalog.json +1 -0
  326. package/dist/lru-DyoaTyIs.d.ts +14 -0
  327. package/dist/memdump.d.ts +52 -0
  328. package/dist/memdump.js +163 -0
  329. package/dist/memory-entry-projector-DHo8jH10.js +1015 -0
  330. package/dist/memory-kind-policy-LKt0u3gy.d.ts +23 -0
  331. package/dist/memory-metadata-codec-C3oQd47V.d.ts +68 -0
  332. package/dist/memory-metadata-codec-DL1sbJiN.js +577 -0
  333. package/dist/memory-runtime-BZtREuwW.js +19459 -0
  334. package/dist/memory-scope-policy-1gg5QlWZ.d.ts +67 -0
  335. package/dist/memory-scope-policy-DICSCURA.js +283 -0
  336. package/dist/memory-snapshot-3e44ND2i.d.ts +16 -0
  337. package/dist/memory-source-order-BtrIxaIt.js +134 -0
  338. package/dist/memory-store-base-XRA4S9Xl.d.ts +1095 -0
  339. package/dist/memory-store-shared-DeIDkhLj.js +158 -0
  340. package/dist/memory-store-write-validation-B_hDG2zf.js +243 -0
  341. package/dist/memory-telemetry-incidents-BWA9kcZx.js +8 -0
  342. package/dist/memory-telemetry-metadata-CA7W8tK6.js +77 -0
  343. package/dist/memory-telemetry-outbox-ddTdImt7.d.ts +74 -0
  344. package/dist/memory-telemetry-receipts-MAJecvXQ.d.ts +34 -0
  345. package/dist/memory-telemetry-receipts-YsxbwOAf.js +91 -0
  346. package/dist/memory-telemetry-types-CufVmrCs.d.ts +14 -0
  347. package/dist/memory-temporality-classifier-CEdRTN5J.d.ts +43 -0
  348. package/dist/memory-temporality-classifier-CKiTAHXe.js +184 -0
  349. package/dist/memory-tier-promoter-DbTpahkP.d.ts +43 -0
  350. package/dist/memory-tool-dependencies-CLODycUw.js +19 -0
  351. package/dist/memory-tool-dependencies-N69chrQc.d.ts +14 -0
  352. package/dist/model-call-table-CspopkBg.js +563 -0
  353. package/dist/model-reply-text-CKopStP2.js +334 -0
  354. package/dist/observable-embedder-DQnNgf9O.d.ts +17 -0
  355. package/dist/observable-llm-client-uwqPADpN.d.ts +21 -0
  356. package/dist/observable-memory-store-BaZKbhgq.d.ts +73 -0
  357. package/dist/observable-retriever-Dt_NUxAA.d.ts +23 -0
  358. package/dist/operation-cancellation-CTKWwNHk.js +81 -0
  359. package/dist/paths-qVF-5uBq.d.ts +1 -0
  360. package/dist/plugin-config-schema-C0UUbOmG.d.ts +413 -0
  361. package/dist/plugin-config-schema-YJLyIIcJ.js +361 -0
  362. package/dist/profile-TWPJ_myr.d.ts +13 -0
  363. package/dist/profile-section-writer-hIphqpUY.js +2149 -0
  364. package/dist/provider-registration-CF1tg8Xy.js +721 -0
  365. package/dist/provider-runtime-types-DFhtdA6d.d.ts +134 -0
  366. package/dist/provider-types-CZGm6v88.d.ts +23 -0
  367. package/dist/redact-BTIZcHQL.d.ts +5 -0
  368. package/dist/reflection-command-hooks-BeQiJI9-.js +644 -0
  369. package/dist/reflection-command-hooks-C1Vxgb-O.d.ts +32 -0
  370. package/dist/reflection-deps-RpLPFrSc.d.ts +19 -0
  371. package/dist/reflection-embedded-generator-CDUhgV96.js +130 -0
  372. package/dist/reflection-embedded-generator-CxOex5xK.d.ts +14 -0
  373. package/dist/reflection-injection-hooks-DfUgqu8f.d.ts +43 -0
  374. package/dist/reflection-lifecycle-hooks-Ct5HBdSG.d.ts +27 -0
  375. package/dist/relation-dictionary-Cev1kyLe.js +4248 -0
  376. package/dist/release-download.d.ts +8 -0
  377. package/dist/release-download.js +32 -0
  378. package/dist/relevant-memories-context-m8nuFZcM.js +23 -0
  379. package/dist/rem-batch-executor-Cbm5gfSe.js +31644 -0
  380. package/dist/rem-batch-executor-bc0IFlp2.js +2 -0
  381. package/dist/rem-consumer-retrieval-CRpvG8KS.js +246 -0
  382. package/dist/rem-trigger-BTxkcjgT.js +729 -0
  383. package/dist/resolver-Dy-hnjCR.js +103 -0
  384. package/dist/results-C3ZLroMb.js +140 -0
  385. package/dist/retrieval-gate-Bx2Zg7jD.d.ts +31 -0
  386. package/dist/retriever-CygHBazG.js +1757 -0
  387. package/dist/retriever-Ruk3zp7_.d.ts +469 -0
  388. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  389. package/dist/routes-Ce7SQKec.js +59 -0
  390. package/dist/runtime-audit-log-BCeujlEp.js +430 -0
  391. package/dist/runtime-audit-log-zpQiR9HT.d.ts +149 -0
  392. package/dist/scopes-CSOn6zdd.js +71 -0
  393. package/dist/scopes-CtrY-YQ3.d.ts +23 -0
  394. package/dist/server-BPAY4NTG.js +1410 -0
  395. package/dist/session-registry-DBoE7AvZ.d.ts +14 -0
  396. package/dist/sidecar/main.d.ts +1 -0
  397. package/dist/sidecar/main.js +56 -0
  398. package/dist/signed-registry-constants-Bv0fgZ8Q.d.ts +12 -0
  399. package/dist/signed-registry-constants-yq3DlG3B.js +82 -0
  400. package/dist/sno-station-mem-runtime-dependencies-Bu-MiqPX.d.ts +31 -0
  401. package/dist/sno-station-mem-runtime-dependencies-DjLOhB45.js +30 -0
  402. package/dist/sqlite-runtime-L_ywirTm.d.ts +58 -0
  403. package/dist/store-2pM0-dZg.d.ts +27 -0
  404. package/dist/store-DzpZBMEm.js +5830 -0
  405. package/dist/strategy-hook-runner-gBtU47tX.d.ts +16 -0
  406. package/dist/strategy-hook-runner-zmdIYOmQ.js +110 -0
  407. package/dist/token-counter-BD1f48Km.js +73 -0
  408. package/dist/trace-1t1n_wUm.d.ts +86 -0
  409. package/dist/types-DxKqU60b.d.ts +477 -0
  410. package/dist/types-pVomjzqR.d.ts +132 -0
  411. package/dist/unplaced-candidate-migration-CbQHzcEM.js +940 -0
  412. package/dist/utils-Ctb9aevJ.d.ts +34 -0
  413. package/drizzle/0000_initial.sql +10 -0
  414. package/drizzle/0001_virtual_tables.sql +34 -0
  415. package/drizzle/0002_add_indexes.sql +11 -0
  416. package/drizzle/0003_content_hash_lookup_index.sql +2 -0
  417. package/drizzle/0004_chunk_swap.sql +60 -0
  418. package/drizzle/0005_drop_legacy_vec_fts.sql +10 -0
  419. package/drizzle/0006_fts_simple.sql +45 -0
  420. package/drizzle/0007_restore_simple_fts.sql +40 -0
  421. package/drizzle/0008_widen_memory_hash_unique_index.sql +4 -0
  422. package/drizzle/0009_memory_telemetry.sql +109 -0
  423. package/drizzle/0010_provider_mappings.sql +27 -0
  424. package/drizzle/0011_db_optimization.sql +82 -0
  425. package/drizzle/0012_b_profile_lanes.sql +9 -0
  426. package/drizzle/0013_extraction_timestamps.sql +6 -0
  427. package/drizzle/0014_extraction_timestamp_source.sql +3 -0
  428. package/drizzle/0015_task_lifecycle_state.sql +101 -0
  429. package/drizzle/0016_task_lifecycle_legacy_migration.sql +144 -0
  430. package/drizzle/0017_unplaced_candidates.sql +15 -0
  431. package/drizzle/0018_rem_batch_chassis.sql +71 -0
  432. package/drizzle/0019_profile_recovery_entries.sql +17 -0
  433. package/drizzle/0020_rem_scan_retry_progress.down.sql +14 -0
  434. package/drizzle/0020_rem_scan_retry_progress.sql +24 -0
  435. package/drizzle/0021_rem_two_facet_storage.down.sql +14 -0
  436. package/drizzle/0021_rem_two_facet_storage.sql +42 -0
  437. package/drizzle/0022_rem_facet_chunk_versions.down.sql +4 -0
  438. package/drizzle/0022_rem_facet_chunk_versions.sql +4 -0
  439. package/drizzle/0023_rem_defect_ledger.sql +40 -0
  440. package/drizzle/0024_rem_unbuilt_foundations.down.sql +13 -0
  441. package/drizzle/0024_rem_unbuilt_foundations.sql +65 -0
  442. package/drizzle/0025_rem_journal_operation_constraint.sql +28 -0
  443. package/drizzle/0026_rem_journal_detail.sql +1 -0
  444. package/drizzle/0027_legacy_nodix_namespace.sql +3 -0
  445. package/drizzle/0028_memory_timezone.sql +23 -0
  446. package/drizzle/0029_rem_write_hash_symmetry.sql +17 -0
  447. package/drizzle/0030_atomic_memory_additive.sql +105 -0
  448. package/drizzle/0031_atomic_extraction_ledger.sql +23 -0
  449. package/drizzle/0032_atomic_memory_entities.sql +12 -0
  450. package/drizzle/0033_todo_own_store.sql +99 -0
  451. package/drizzle/meta/0000_snapshot.json +87 -0
  452. package/drizzle/meta/_journal.json +244 -0
  453. package/generated/rem-operations.json +1 -0
  454. package/package.json +126 -4
  455. package/scripts/download-simple-tokenizer.mjs +254 -0
  456. package/settings.default.json +243 -0
  457. package/skills/extract-atomic-memory/SKILL.md +298 -0
  458. package/skills/extract-atomic-memory/references/account-for-turns.md +9 -0
  459. package/skills/extract-atomic-memory/references/calendar-meaning.md +64 -0
  460. package/skills/extract-atomic-memory/references/capture.md +120 -0
  461. package/skills/extract-atomic-memory/references/enrichment.md +92 -0
  462. package/skills/extract-atomic-memory/references/missing-durable-half.md +6 -0
  463. package/skills/extract-atomic-memory/references/progress-classification.md +21 -0
  464. package/skills/extract-atomic-memory/references/resolve-subject.md +19 -0
  465. package/skills/extract-atomic-memory/references/surrounding-context.md +10 -0
  466. package/skills/extract-atomic-memory/references/user-subject-guard.md +29 -0
  467. package/skills/judge-group-closure/SKILL.md +25 -0
  468. package/skills/judge-rem-memory-updates/SKILL.md +56 -0
  469. package/skills/judge-rem-memory-updates/agents/openai.yaml +4 -0
  470. package/skills/judge-retired-position/SKILL.md +25 -0
  471. package/skills/judge-task-lifecycle/SKILL.md +45 -0
  472. package/skills/key-state-attribute/SKILL.md +16 -0
  473. package/skills/resolve-entity-identity/SKILL.md +24 -0
  474. package/skills/resolve-relative-time/SKILL.md +22 -0
  475. package/sqlite-extensions/LICENSE-simple-tokenizer +28 -0
  476. package/sqlite-extensions/LICENSE-sqlite-vec +21 -0
  477. package/sqlite-extensions/linux-arm64/vec0.so +0 -0
  478. package/sqlite-extensions/linux-x64/vec0.so +0 -0
@@ -0,0 +1,2577 @@
1
+ import { createLogger } from "@snoai/utils/logger";
2
+ import path, { dirname, join, resolve } from "node:path";
3
+ import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, utimesSync, writeFileSync } from "node:fs";
4
+ import { homedir, totalmem, userInfo } from "node:os";
5
+ import { fileURLToPath } from "node:url";
6
+ import { LRUCache } from "lru-cache";
7
+ import { isLowercaseCanonicalUUIDv7 } from "@snoai/common-core";
8
+ import { z } from "zod";
9
+ import { CHUNKING_VERSION, DEFAULT_AGGREGATION_CONFIG, DEFAULT_CHUNK_CONFIG, HEAD_EXTRACT_MIN_CONTENT_TOKENS, HEAD_EXTRACT_OVERLAP_DROP_RATIO, HEAD_EXTRACT_TOKEN_BUDGET } from "@snoai/chunking";
10
+ //#region ../embedder/dist/index.mjs
11
+ /**
12
+ * Shared embedding constants — single source of truth for all apps.
13
+ * 1024-d is the ONLY supported dimension.
14
+ */
15
+ const CONSTANTS_DIR = dirname(fileURLToPath(import.meta.url));
16
+ /** Local ONNX model identifier (Hugging Face hub) */
17
+ const LOCAL_EMBEDDING_MODEL = "tss-deposium/pplx-embed-v1-0.6b-onnx-int8-standard";
18
+ /**
19
+ * Pinned HuggingFace revision (commit SHA) for supply-chain integrity.
20
+ * Update this when intentionally upgrading to a newer model version.
21
+ */
22
+ const LOCAL_EMBEDDING_MODEL_REVISION = "a18fdffe7480e6ea5643acb7757142b33838817a";
23
+ /** Default ONNX Runtime profile for constrained local agents. */
24
+ const LOCAL_EMBEDDING_SESSION_OPTIONS_DEFAULT = {
25
+ graphOptimizationLevel: "extended",
26
+ enableMemPattern: false,
27
+ enableCpuMemArena: false
28
+ };
29
+ /**
30
+ * Default local embedding model cache directory.
31
+ * Absolute path anchored to the embedder package's own `.cache/models/` so it
32
+ * resolves identically regardless of process CWD. Apps can override via
33
+ * constructor config.
34
+ */
35
+ const LOCAL_EMBEDDING_CACHE_DIR_DEFAULT = join(CONSTANTS_DIR, "..", ".cache", "models");
36
+ /**
37
+ * Local ONNX embedding provider — PPLX embed v1 0.6B INT8, 1024-d vectors.
38
+ *
39
+ * Self-contained: all params via constructor; no app-level config dependency.
40
+ */
41
+ const log$1 = createLogger("embedder:local");
42
+ let sharedExtractor;
43
+ let sharedLoading;
44
+ let sharedRefCount = 0;
45
+ let sharedPipelineKey;
46
+ function buildSessionOptions(options) {
47
+ const sessionOptions = {
48
+ graphOptimizationLevel: options.graphOptimizationLevel ?? LOCAL_EMBEDDING_SESSION_OPTIONS_DEFAULT.graphOptimizationLevel,
49
+ enableMemPattern: options.enableMemPattern ?? LOCAL_EMBEDDING_SESSION_OPTIONS_DEFAULT.enableMemPattern,
50
+ enableCpuMemArena: options.enableCpuMemArena ?? LOCAL_EMBEDDING_SESSION_OPTIONS_DEFAULT.enableCpuMemArena,
51
+ freeDimensionOverrides: { batch_size: 1 }
52
+ };
53
+ if (options.executionMode !== void 0) sessionOptions.executionMode = options.executionMode;
54
+ if (options.interOpNumThreads !== void 0) sessionOptions.interOpNumThreads = options.interOpNumThreads;
55
+ if (options.intraOpNumThreads !== void 0) sessionOptions.intraOpNumThreads = options.intraOpNumThreads;
56
+ return sessionOptions;
57
+ }
58
+ function buildPipelineKey(identity) {
59
+ return JSON.stringify({
60
+ cacheDir: identity.cacheDir,
61
+ modelId: identity.modelId,
62
+ revision: identity.revision,
63
+ dtype: identity.dtype,
64
+ sessionOptions: buildSessionOptions(identity.sessionOptions)
65
+ });
66
+ }
67
+ function isNumericTensorData(value) {
68
+ if (typeof value !== "object" || value === null) return false;
69
+ return "length" in value && typeof value.length === "number";
70
+ }
71
+ function tensorDataToArray(data, length) {
72
+ if (!isNumericTensorData(data)) throw new Error("Local embedding returned non-array tensor data");
73
+ return typeof data.subarray === "function" ? Array.from(data.subarray(0, length)) : Array.from(data).slice(0, length);
74
+ }
75
+ var ModelNotFoundError = class extends Error {
76
+ constructor(modelId) {
77
+ super(`Local embedding model "${modelId}" not found in cacheDir. Download it via Hugging Face CLI or 'npm run model:pull'.`);
78
+ this.name = "ModelNotFoundError";
79
+ }
80
+ };
81
+ /** Thrown by `countTokens()` before the model (and its tokenizer) has loaded. */
82
+ var ModelNotLoadedError = class extends Error {
83
+ constructor(modelId) {
84
+ super(`Local embedding model "${modelId}" is not loaded yet; await embed() or the embedder warmup before counting tokens.`);
85
+ this.name = "ModelNotLoadedError";
86
+ }
87
+ };
88
+ var LocalEmbedProvider = class LocalEmbedProvider {
89
+ _disposed = false;
90
+ cacheDir;
91
+ dtype;
92
+ modelId;
93
+ revision;
94
+ nativeDim;
95
+ outputDim;
96
+ pooling;
97
+ sessionOptions;
98
+ pipelineKey;
99
+ offline;
100
+ mirror;
101
+ /**
102
+ * Guard: transformers `env` is process-global — only one cacheDir is allowed per process.
103
+ * Intentionally never reset during normal operation; use `resetStaticState()` only in tests.
104
+ */
105
+ static configuredCacheDir;
106
+ /** Reset static state — FOR TESTS ONLY. Not safe in production. */
107
+ static resetStaticState() {
108
+ LocalEmbedProvider.configuredCacheDir = void 0;
109
+ sharedExtractor = void 0;
110
+ sharedLoading = void 0;
111
+ sharedRefCount = 0;
112
+ sharedPipelineKey = void 0;
113
+ }
114
+ /** Output dimension exposed to consumers (after Matryoshka truncation, if any). */
115
+ get dimension() {
116
+ return this.outputDim;
117
+ }
118
+ constructor(config) {
119
+ this.cacheDir = resolve(config?.cacheDir ?? LOCAL_EMBEDDING_CACHE_DIR_DEFAULT);
120
+ this.dtype = config?.dtype ?? "q8";
121
+ this.modelId = config?.model ?? "tss-deposium/pplx-embed-v1-0.6b-onnx-int8-standard";
122
+ this.revision = config?.revision ?? (config?.model === void 0 ? "a18fdffe7480e6ea5643acb7757142b33838817a" : void 0);
123
+ this.nativeDim = config?.nativeDim ?? 1024;
124
+ this.outputDim = config?.outputDim ?? this.nativeDim;
125
+ if (this.outputDim > this.nativeDim) throw new Error(`outputDim (${this.outputDim}) cannot exceed nativeDim (${this.nativeDim}) — Matryoshka truncation only shrinks dimensions.`);
126
+ this.pooling = config?.pooling ?? "mean";
127
+ this.sessionOptions = config?.sessionOptions ?? {};
128
+ this.offline = config?.offline ?? false;
129
+ this.mirror = config?.mirror;
130
+ this.pipelineKey = buildPipelineKey({
131
+ cacheDir: this.cacheDir,
132
+ modelId: this.modelId,
133
+ revision: this.revision,
134
+ dtype: this.dtype,
135
+ sessionOptions: this.sessionOptions
136
+ });
137
+ sharedRefCount++;
138
+ }
139
+ async getExtractor() {
140
+ if (this._disposed) throw new Error("LocalEmbedProvider has been disposed");
141
+ this.assertCompatibleSharedPipeline();
142
+ if (sharedExtractor) return sharedExtractor;
143
+ if (sharedLoading) {
144
+ const extractor = await sharedLoading;
145
+ if (this._disposed) throw new Error("LocalEmbedProvider has been disposed");
146
+ if (!sharedExtractor) sharedExtractor = extractor;
147
+ return extractor;
148
+ }
149
+ sharedPipelineKey = this.pipelineKey;
150
+ sharedLoading = this.initPipeline();
151
+ try {
152
+ const extractor = await sharedLoading;
153
+ sharedExtractor = extractor;
154
+ if (this._disposed) throw new Error("LocalEmbedProvider has been disposed");
155
+ return extractor;
156
+ } finally {
157
+ sharedLoading = void 0;
158
+ if (!sharedExtractor && sharedRefCount === 0) sharedPipelineKey = void 0;
159
+ }
160
+ }
161
+ assertCompatibleSharedPipeline() {
162
+ if (sharedPipelineKey === void 0 || sharedPipelineKey === this.pipelineKey) return;
163
+ throw new Error("LocalEmbedProvider shared ONNX pipeline is already loaded with a different model, revision, dtype, cacheDir, or sessionOptions. Dispose all live providers before changing pipeline configuration.");
164
+ }
165
+ async initPipeline() {
166
+ if (LocalEmbedProvider.configuredCacheDir !== void 0 && LocalEmbedProvider.configuredCacheDir !== this.cacheDir) throw new Error(`transformers env is global; LocalEmbedProvider cacheDir must be consistent (existing: ${LocalEmbedProvider.configuredCacheDir}, requested: ${this.cacheDir})`);
167
+ LocalEmbedProvider.configuredCacheDir = this.cacheDir;
168
+ const { env, pipeline } = await import("@huggingface/transformers");
169
+ env.cacheDir = this.cacheDir;
170
+ env.allowRemoteModels = !this.offline;
171
+ env.localModelPath = this.cacheDir;
172
+ env.remotePathTemplate = `{model}/resolve/${this.revision ?? "main"}/`;
173
+ const hfEndpoint = this.mirror?.trim();
174
+ if (hfEndpoint) env.remoteHost = hfEndpoint.endsWith("/") ? hfEndpoint : `${hfEndpoint}/`;
175
+ log$1.info("loading ONNX model", {
176
+ model: this.modelId,
177
+ cacheDir: this.cacheDir,
178
+ dtype: this.dtype,
179
+ nativeDim: this.nativeDim,
180
+ outputDim: this.outputDim,
181
+ sessionOptions: buildSessionOptions(this.sessionOptions)
182
+ }, {
183
+ event_name: "embedder.local.provider.initpipeline",
184
+ file: "packages/embedder/src/local-provider.ts",
185
+ function: "initPipeline",
186
+ site_id: "embedder.local.provider.initpipeline.1"
187
+ });
188
+ const t0 = performance.now();
189
+ try {
190
+ const sessionOptions = buildSessionOptions(this.sessionOptions);
191
+ const extractor = await pipeline("feature-extraction", this.modelId, {
192
+ dtype: this.dtype,
193
+ device: "cpu",
194
+ session_options: sessionOptions
195
+ });
196
+ const durationMs = Math.round(performance.now() - t0);
197
+ log$1.info("ONNX model loaded", {
198
+ durationMs,
199
+ model: this.modelId
200
+ }, {
201
+ event_name: "embedder.local.provider.initpipeline",
202
+ file: "packages/embedder/src/local-provider.ts",
203
+ function: "initPipeline",
204
+ site_id: "embedder.local.provider.initpipeline.2"
205
+ });
206
+ return extractor;
207
+ } catch (error) {
208
+ const msg = error instanceof Error ? error.message : String(error);
209
+ if (msg.includes("no such file") || msg.includes("ENOENT") || msg.includes("not found") || msg.includes("Could not locate file")) {
210
+ log$1.error("ONNX model not found", {
211
+ cacheDir: this.cacheDir,
212
+ model: this.modelId
213
+ }, {
214
+ event_name: "embedder.local.provider.initpipeline",
215
+ file: "packages/embedder/src/local-provider.ts",
216
+ function: "initPipeline",
217
+ site_id: "embedder.local.provider.initpipeline.3"
218
+ });
219
+ throw new ModelNotFoundError(this.modelId);
220
+ }
221
+ log$1.error("ONNX model init failed", { error }, {
222
+ event_name: "embedder.local.provider.initpipeline",
223
+ file: "packages/embedder/src/local-provider.ts",
224
+ function: "initPipeline",
225
+ site_id: "embedder.local.provider.initpipeline.4"
226
+ });
227
+ throw error;
228
+ }
229
+ }
230
+ countTokens(text) {
231
+ if (this._disposed) throw new Error("LocalEmbedProvider has been disposed");
232
+ this.assertCompatibleSharedPipeline();
233
+ if (!sharedExtractor) throw new ModelNotLoadedError(this.modelId);
234
+ return sharedExtractor.tokenizer.encode(text, { add_special_tokens: false }).length;
235
+ }
236
+ async embed(text) {
237
+ const output = await (await this.getExtractor())(text, {
238
+ pooling: this.pooling,
239
+ normalize: true
240
+ });
241
+ const lastDimIndex = output.dims.length - 1;
242
+ if (lastDimIndex < 0) throw new Error("Local embedding returned empty tensor dims");
243
+ const dim = output.dims[lastDimIndex];
244
+ if (dim === void 0) throw new Error("Local embedding returned undefined dimension");
245
+ if (dim !== this.nativeDim) throw new Error(`Model "${this.modelId}" produced ${dim}-d native vectors, but provider was configured with nativeDim=${this.nativeDim}.`);
246
+ const native = tensorDataToArray(output.data, dim);
247
+ if (native.length !== this.nativeDim) throw new Error(`Expected ${this.nativeDim}-d native embedding, got ${native.length}-d`);
248
+ if (this.outputDim === this.nativeDim) return native;
249
+ return truncateAndRenormalize(native, this.outputDim);
250
+ }
251
+ async embedDocuments(texts) {
252
+ if (texts.length === 0) return [];
253
+ log$1.debug("batch local embedding", { count: texts.length }, {
254
+ event_name: "embedder.local.provider.embeddocuments",
255
+ file: "packages/embedder/src/local-provider.ts",
256
+ function: "embedDocuments",
257
+ site_id: "embedder.local.provider.embeddocuments.5"
258
+ });
259
+ const results = new Array(texts.length);
260
+ for (let i = 0; i < texts.length; i++) {
261
+ const text = texts[i];
262
+ if (text === void 0) throw new Error(`Missing text at batch index ${i}`);
263
+ results[i] = await this.embed(text);
264
+ }
265
+ return results;
266
+ }
267
+ async dispose() {
268
+ if (this._disposed) return;
269
+ log$1.debug("disposing local embedding provider", {}, {
270
+ event_name: "embedder.local.provider.dispose",
271
+ file: "packages/embedder/src/local-provider.ts",
272
+ function: "dispose",
273
+ site_id: "embedder.local.provider.dispose.6"
274
+ });
275
+ this._disposed = true;
276
+ sharedRefCount = Math.max(0, sharedRefCount - 1);
277
+ if (sharedRefCount > 0) return;
278
+ const pending = sharedLoading;
279
+ if (pending) {
280
+ const extractor = await pending.catch(() => void 0);
281
+ if (sharedRefCount > 0) {
282
+ if (extractor && !sharedExtractor) sharedExtractor = extractor;
283
+ return;
284
+ }
285
+ if (extractor && extractor !== sharedExtractor) await extractor.dispose();
286
+ }
287
+ if (sharedRefCount > 0) return;
288
+ if (sharedExtractor) {
289
+ await sharedExtractor.dispose();
290
+ sharedExtractor = void 0;
291
+ }
292
+ if (sharedLoading === void 0) sharedPipelineKey = void 0;
293
+ }
294
+ async warmup() {
295
+ await this.embed("warmup");
296
+ }
297
+ };
298
+ /**
299
+ * Slice the leading `outputDim` floats and re-L2-normalize.
300
+ *
301
+ * Qwen3 embedding models are trained with Matryoshka representation learning,
302
+ * so the head of a unit-length native vector remains a meaningful (but no
303
+ * longer unit-length) embedding. Re-normalizing keeps cosine similarity
304
+ * comparable across stored vectors of the same truncated dim.
305
+ */
306
+ function truncateAndRenormalize(native, outputDim) {
307
+ if (outputDim <= 0 || outputDim > native.length) throw new Error(`truncateAndRenormalize: outputDim=${outputDim} out of range for native length ${native.length}`);
308
+ const head = native.slice(0, outputDim);
309
+ let normSq = 0;
310
+ for (let i = 0; i < outputDim; i++) {
311
+ const v = head[i] ?? 0;
312
+ normSq += v * v;
313
+ }
314
+ const norm = Math.sqrt(normSq);
315
+ if (norm === 0) return head;
316
+ for (let i = 0; i < outputDim; i++) head[i] = (head[i] ?? 0) / norm;
317
+ return head;
318
+ }
319
+ /**
320
+ * LRU-cached embedding provider wrapper.
321
+ *
322
+ * Wraps any EmbeddingProvider with an LRU cache (TTL + max-size eviction).
323
+ * Extracted from mem-claw's Embedder cache pattern,
324
+ * upgraded to use the `lru-cache` package instead of a hand-rolled Map.
325
+ */
326
+ /** Shared key prefix for single-text and document-batch cache entries. */
327
+ const PASSAGE_PREFIX = "p:";
328
+ var CachedEmbeddingProvider = class {
329
+ inner;
330
+ cache;
331
+ inflight = /* @__PURE__ */ new Map();
332
+ get dimension() {
333
+ return this.inner.dimension;
334
+ }
335
+ countTokens(text) {
336
+ return this.inner.countTokens(text);
337
+ }
338
+ constructor(provider, config) {
339
+ this.inner = provider;
340
+ this.cache = new LRUCache({
341
+ max: config?.maxSize ?? 256,
342
+ ttl: config?.ttlMs ?? 18e5
343
+ });
344
+ }
345
+ async getOrLoad(key, load) {
346
+ const cached = this.cache.get(key);
347
+ if (cached) return [...cached];
348
+ const pending = this.inflight.get(key);
349
+ if (pending) return [...await pending];
350
+ const created = (async () => {
351
+ const cloned = [...await load()];
352
+ this.cache.set(key, cloned);
353
+ return cloned;
354
+ })();
355
+ this.inflight.set(key, created);
356
+ try {
357
+ return [...await created];
358
+ } catch (error) {
359
+ if (this.inflight.get(key) === created) this.inflight.delete(key);
360
+ throw error;
361
+ } finally {
362
+ if (this.inflight.get(key) === created) this.inflight.delete(key);
363
+ }
364
+ }
365
+ async embed(text) {
366
+ const key = `${PASSAGE_PREFIX}${text}`;
367
+ return this.getOrLoad(key, async () => this.inner.embed(text));
368
+ }
369
+ async embedDocuments(texts) {
370
+ if (texts.length === 0) return [];
371
+ const results = new Array(texts.length);
372
+ const batchKeys = [];
373
+ const batchTexts = [];
374
+ const batchIndicesByKey = /* @__PURE__ */ new Map();
375
+ for (let i = 0; i < texts.length; i++) {
376
+ const text = texts[i];
377
+ if (text === void 0) continue;
378
+ const key = `${PASSAGE_PREFIX}${text}`;
379
+ const cached = this.cache.get(key);
380
+ if (cached) {
381
+ results[i] = Promise.resolve([...cached]);
382
+ continue;
383
+ }
384
+ const pending = this.inflight.get(key);
385
+ if (pending) {
386
+ results[i] = pending.then((embedding) => [...embedding]);
387
+ continue;
388
+ }
389
+ const existingBatch = batchIndicesByKey.get(key);
390
+ if (existingBatch) {
391
+ existingBatch.push(i);
392
+ continue;
393
+ }
394
+ batchKeys.push(key);
395
+ batchTexts.push(text);
396
+ batchIndicesByKey.set(key, [i]);
397
+ }
398
+ if (batchTexts.length > 0) {
399
+ const batchPromises = /* @__PURE__ */ new Map();
400
+ const freshEmbeddingsPromise = this.inner.embedDocuments(batchTexts).then((freshEmbeddings) => {
401
+ if (freshEmbeddings.length !== batchTexts.length) throw new Error(`inner.embedDocuments returned ${freshEmbeddings.length} results for ${batchTexts.length} inputs`);
402
+ return freshEmbeddings.map((embedding) => [...embedding]);
403
+ });
404
+ for (let j = 0; j < batchKeys.length; j++) {
405
+ const key = batchKeys[j];
406
+ if (key === void 0) continue;
407
+ const indices = batchIndicesByKey.get(key);
408
+ if (indices === void 0) continue;
409
+ const keyPromise = freshEmbeddingsPromise.then((freshEmbeddings) => {
410
+ const embedding = freshEmbeddings[j];
411
+ if (embedding === void 0) throw new Error(`Missing fresh embedding at batch index ${j}`);
412
+ this.cache.set(key, embedding);
413
+ return embedding;
414
+ });
415
+ batchPromises.set(key, keyPromise);
416
+ this.inflight.set(key, keyPromise);
417
+ for (const idx of indices) results[idx] = keyPromise.then((embedding) => [...embedding]);
418
+ }
419
+ const clearInflight = () => {
420
+ for (const [key, keyPromise] of batchPromises) if (this.inflight.get(key) === keyPromise) this.inflight.delete(key);
421
+ };
422
+ freshEmbeddingsPromise.then(clearInflight, clearInflight);
423
+ }
424
+ return Promise.all(results.map((result, index) => {
425
+ if (result === void 0) throw new Error(`Missing embedding at index ${index}`);
426
+ return result;
427
+ }));
428
+ }
429
+ async dispose() {
430
+ this.cache.clear();
431
+ this.inflight.clear();
432
+ if ("dispose" in this.inner && typeof this.inner.dispose === "function") await this.inner.dispose();
433
+ }
434
+ /** Clear the cache without disposing the inner provider */
435
+ clear() {
436
+ this.cache.clear();
437
+ this.inflight.clear();
438
+ }
439
+ /** Current cache size */
440
+ get size() {
441
+ return this.cache.size;
442
+ }
443
+ };
444
+ /**
445
+ * model-download.ts — Shared ONNX model download utility.
446
+ *
447
+ * Idempotent: skips download when a .download-complete marker and .onnx files
448
+ * exist in cacheDir. Interrupted downloads (no marker) trigger re-download.
449
+ * User-facing progress goes to stderr (not stdout) so it doesn't interfere
450
+ * with structured log output or piped commands.
451
+ */
452
+ const log$2 = createLogger("embedder:model-download");
453
+ /** Marker file written after a successful download to distinguish complete vs partial cache. */
454
+ const DOWNLOAD_COMPLETE_MARKER = ".download-complete";
455
+ /** Lock file for cross-process download serialization (O_EXCL based). */
456
+ const DOWNLOAD_LOCK_FILE = ".download-lock";
457
+ /** Max time (ms) to wait for another process's download before giving up. */
458
+ const LOCK_WAIT_TIMEOUT_MS = 6e5;
459
+ /** Poll interval (ms) when waiting for a competing download to finish. */
460
+ const LOCK_POLL_INTERVAL_MS = 2e3;
461
+ /** Stale lock threshold (ms) — locks older than this are assumed abandoned. */
462
+ const LOCK_STALE_MS = 9e5;
463
+ /** Lock heartbeat interval (ms) while owning the download lock. */
464
+ const LOCK_HEARTBEAT_INTERVAL_MS = 5e3;
465
+ function parseDownloadMarker(raw) {
466
+ try {
467
+ const parsed = JSON.parse(raw);
468
+ const model = parsed.model;
469
+ const revision = parsed.revision;
470
+ const dtype = parsed.dtype;
471
+ const completedAt = parsed.completedAt;
472
+ if (typeof model !== "string" || typeof revision !== "string" || typeof dtype !== "string" || typeof completedAt !== "string") return null;
473
+ return {
474
+ model,
475
+ revision,
476
+ dtype,
477
+ completedAt
478
+ };
479
+ } catch {
480
+ return null;
481
+ }
482
+ }
483
+ const DTYPE_SIZES = {
484
+ q4: "~400MB",
485
+ q8: "~639MB",
486
+ fp16: "~1.2GB",
487
+ fp32: "~2.4GB"
488
+ };
489
+ function getSystemRamGB() {
490
+ return Math.round(totalmem() / 1073741824);
491
+ }
492
+ /**
493
+ * Check if a valid model download exists in cacheDir.
494
+ *
495
+ * When `expectedRevision` and/or `expectedDtype` are provided, the marker
496
+ * metadata is validated against them — a mismatch (e.g. after model upgrade)
497
+ * returns false so the caller re-downloads. Without these params the check
498
+ * is structural only (marker + .onnx files), which is appropriate for
499
+ * lock-wait polling where dtype/revision aren't available.
500
+ */
501
+ function isModelCached(cacheDir, expectedRevision, expectedDtype) {
502
+ try {
503
+ if (!existsSync(cacheDir)) return false;
504
+ const markerPath = join(cacheDir, DOWNLOAD_COMPLETE_MARKER);
505
+ if (!existsSync(markerPath)) return false;
506
+ const onnxDir = join(cacheDir, LOCAL_EMBEDDING_MODEL, "onnx");
507
+ if (!existsSync(onnxDir) || !readdirSync(onnxDir).some((e) => e.endsWith(".onnx"))) return false;
508
+ if (expectedRevision !== void 0 || expectedDtype !== void 0) {
509
+ const marker = parseDownloadMarker(readFileSync(markerPath, "utf8"));
510
+ if (!marker) {
511
+ log$2.warn("download marker is corrupt, re-download needed", { cacheDir }, {
512
+ event_name: "embedder.model.download.ismodelcached",
513
+ file: "packages/embedder/src/model-download.ts",
514
+ function: "isModelCached",
515
+ site_id: "embedder.model.download.ismodelcached.1"
516
+ });
517
+ return false;
518
+ }
519
+ if (expectedRevision !== void 0 && marker.revision !== expectedRevision) {
520
+ log$2.info("cached model revision mismatch, re-download needed", {
521
+ cached: String(marker.revision),
522
+ expected: expectedRevision
523
+ }, {
524
+ event_name: "embedder.model.download.ismodelcached",
525
+ file: "packages/embedder/src/model-download.ts",
526
+ function: "isModelCached",
527
+ site_id: "embedder.model.download.ismodelcached.2"
528
+ });
529
+ return false;
530
+ }
531
+ if (expectedDtype !== void 0 && marker.dtype !== expectedDtype) {
532
+ log$2.info("cached model dtype mismatch, re-download needed", {
533
+ cached: String(marker.dtype),
534
+ expected: expectedDtype
535
+ }, {
536
+ event_name: "embedder.model.download.ismodelcached",
537
+ file: "packages/embedder/src/model-download.ts",
538
+ function: "isModelCached",
539
+ site_id: "embedder.model.download.ismodelcached.3"
540
+ });
541
+ return false;
542
+ }
543
+ }
544
+ return true;
545
+ } catch (error) {
546
+ log$2.warn("failed to inspect model cache directory", {
547
+ cacheDir,
548
+ error
549
+ }, {
550
+ event_name: "embedder.model.download.ismodelcached",
551
+ file: "packages/embedder/src/model-download.ts",
552
+ function: "isModelCached",
553
+ site_id: "embedder.model.download.ismodelcached.4"
554
+ });
555
+ return false;
556
+ }
557
+ }
558
+ function getDirSizeMB(dirPath) {
559
+ let total = 0;
560
+ try {
561
+ const entries = readdirSync(dirPath, { recursive: true });
562
+ for (const entry of entries) {
563
+ if (typeof entry !== "string") continue;
564
+ const fullPath = join(dirPath, entry);
565
+ try {
566
+ const stat = statSync(fullPath);
567
+ if (stat.isFile()) total += stat.size;
568
+ } catch {}
569
+ }
570
+ } catch (error) {
571
+ log$2.warn("failed to read directory for size calculation", {
572
+ dirPath,
573
+ error
574
+ }, {
575
+ event_name: "embedder.model.download.getdirsizemb",
576
+ file: "packages/embedder/src/model-download.ts",
577
+ function: "getDirSizeMB",
578
+ site_id: "embedder.model.download.getdirsizemb.5"
579
+ });
580
+ }
581
+ return Math.round(total / 1048576);
582
+ }
583
+ function getDtypeDisplaySize(dtype) {
584
+ return DTYPE_SIZES[dtype] ?? "unknown size";
585
+ }
586
+ /**
587
+ * Acquire an exclusive download lock using O_EXCL (atomic create-if-not-exists).
588
+ * Returns true if lock acquired, false if another process holds it.
589
+ */
590
+ function tryAcquireLock(cacheDir) {
591
+ const lockPath = join(cacheDir, DOWNLOAD_LOCK_FILE);
592
+ try {
593
+ mkdirSync(cacheDir, { recursive: true });
594
+ const fd = openSync(lockPath, "wx");
595
+ writeFileSync(fd, `${process.pid}\n${Date.now()}\n`);
596
+ closeSync(fd);
597
+ return true;
598
+ } catch (error) {
599
+ if (error instanceof Error && "code" in error && error.code === "EEXIST") return false;
600
+ throw error;
601
+ }
602
+ }
603
+ function releaseLock(cacheDir) {
604
+ try {
605
+ unlinkSync(join(cacheDir, DOWNLOAD_LOCK_FILE));
606
+ } catch {}
607
+ }
608
+ function heartbeatLock(cacheDir) {
609
+ const lockPath = join(cacheDir, DOWNLOAD_LOCK_FILE);
610
+ try {
611
+ const now = /* @__PURE__ */ new Date();
612
+ utimesSync(lockPath, now, now);
613
+ } catch {}
614
+ }
615
+ function isLockStale(cacheDir) {
616
+ const lockPath = join(cacheDir, DOWNLOAD_LOCK_FILE);
617
+ try {
618
+ const stat = statSync(lockPath);
619
+ if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) return true;
620
+ const pid = Number.parseInt(readFileSync(lockPath, "utf8").split("\n")[0] ?? "", 10);
621
+ if (!Number.isInteger(pid) || pid <= 0) return false;
622
+ try {
623
+ process.kill(pid, 0);
624
+ return false;
625
+ } catch (error) {
626
+ return error instanceof Error && "code" in error && error.code === "ESRCH";
627
+ }
628
+ } catch {
629
+ return true;
630
+ }
631
+ }
632
+ function sleep(ms) {
633
+ return new Promise((resolve) => setTimeout(resolve, ms));
634
+ }
635
+ /**
636
+ * Wait for an existing download lock to be released (another process finishing).
637
+ * If the lock is stale (abandoned), break it and return so the caller can retry.
638
+ *
639
+ * `expectedRevision` / `expectedDtype` are forwarded to `isModelCached` so a
640
+ * concurrent revision/dtype upgrade is not satisfied by a stale matching-shape
641
+ * cache from the previous version. Without them, two processes upgrading the
642
+ * same cacheDir can both return "finished" on the old artifacts.
643
+ */
644
+ async function waitForLock(cacheDir, expectedRevision, expectedDtype) {
645
+ const lockPath = join(cacheDir, DOWNLOAD_LOCK_FILE);
646
+ const deadline = Date.now() + LOCK_WAIT_TIMEOUT_MS;
647
+ log$2.info("another process is downloading the model, waiting...", { cacheDir }, {
648
+ event_name: "embedder.model.download.waitforlock",
649
+ file: "packages/embedder/src/model-download.ts",
650
+ function: "waitForLock",
651
+ site_id: "embedder.model.download.waitforlock.6"
652
+ });
653
+ process.stderr.write(" Waiting for another download to finish...\n");
654
+ while (Date.now() < deadline) {
655
+ if (!existsSync(lockPath)) return;
656
+ if (isModelCached(cacheDir, expectedRevision, expectedDtype)) return;
657
+ if (isLockStale(cacheDir)) {
658
+ log$2.warn("breaking stale download lock", { cacheDir }, {
659
+ event_name: "embedder.model.download.waitforlock",
660
+ file: "packages/embedder/src/model-download.ts",
661
+ function: "waitForLock",
662
+ site_id: "embedder.model.download.waitforlock.7"
663
+ });
664
+ releaseLock(cacheDir);
665
+ return;
666
+ }
667
+ await sleep(LOCK_POLL_INTERVAL_MS);
668
+ }
669
+ throw new Error(`Timed out (${LOCK_WAIT_TIMEOUT_MS / 1e3}s) waiting for model download lock. Another process may still be downloading. Check ${join(cacheDir, DOWNLOAD_LOCK_FILE)}`);
670
+ }
671
+ /**
672
+ * Ensure the local ONNX embedding model is downloaded. Idempotent.
673
+ *
674
+ * - If .download-complete marker + .onnx files exist in cacheDir, logs "already cached" and returns.
675
+ * - Otherwise, downloads with progress output to stderr.
676
+ * - Resets `env.allowRemoteModels = false` after download to prevent
677
+ * surprise network calls during inference.
678
+ */
679
+ async function ensureModelDownloaded(opts) {
680
+ const cacheDir = opts?.cacheDir ?? LOCAL_EMBEDDING_CACHE_DIR_DEFAULT;
681
+ const ramGB = getSystemRamGB();
682
+ const dtype = opts?.dtype ?? "q8";
683
+ if (isModelCached(cacheDir, "a18fdffe7480e6ea5643acb7757142b33838817a", dtype)) {
684
+ const sizeMB = getDirSizeMB(cacheDir);
685
+ log$2.info("local embedding model already cached", {
686
+ sizeMB,
687
+ cacheDir
688
+ }, {
689
+ event_name: "embedder.model.download.ensuremodeldownloaded",
690
+ file: "packages/embedder/src/model-download.ts",
691
+ function: "ensureModelDownloaded",
692
+ site_id: "embedder.model.download.ensuremodeldownloaded.8"
693
+ });
694
+ return;
695
+ }
696
+ if (opts?.offline) return;
697
+ const lockWasPresent = existsSync(join(cacheDir, DOWNLOAD_LOCK_FILE));
698
+ if (!tryAcquireLock(cacheDir)) {
699
+ await waitForLock(cacheDir, LOCAL_EMBEDDING_MODEL_REVISION, dtype);
700
+ if (isModelCached(cacheDir, "a18fdffe7480e6ea5643acb7757142b33838817a", dtype)) {
701
+ const sizeMB = getDirSizeMB(cacheDir);
702
+ log$2.info("local embedding model already cached (downloaded by another process)", {
703
+ sizeMB,
704
+ cacheDir
705
+ }, {
706
+ event_name: "embedder.model.download.ensuremodeldownloaded",
707
+ file: "packages/embedder/src/model-download.ts",
708
+ function: "ensureModelDownloaded",
709
+ site_id: "embedder.model.download.ensuremodeldownloaded.9"
710
+ });
711
+ return;
712
+ }
713
+ if (!tryAcquireLock(cacheDir)) throw new Error(`Failed to acquire model download lock after waiting. Another process may still be downloading. Check ${join(cacheDir, DOWNLOAD_LOCK_FILE)}`);
714
+ }
715
+ const modelDir = join(cacheDir, LOCAL_EMBEDDING_MODEL);
716
+ let completed = false;
717
+ let startedEmpty = false;
718
+ const lockHeartbeat = setInterval(() => heartbeatLock(cacheDir), LOCK_HEARTBEAT_INTERVAL_MS);
719
+ try {
720
+ heartbeatLock(cacheDir);
721
+ if (lockWasPresent) {
722
+ rmSync(join(cacheDir, DOWNLOAD_COMPLETE_MARKER), { force: true });
723
+ rmSync(modelDir, {
724
+ recursive: true,
725
+ force: true
726
+ });
727
+ } else if (!existsSync(join(cacheDir, DOWNLOAD_COMPLETE_MARKER)) && existsSync(modelDir) && existsSync(join(modelDir, "onnx")) && readdirSync(join(modelDir, "onnx")).some((e) => e.endsWith(".onnx"))) {
728
+ writeFileSync(join(cacheDir, DOWNLOAD_COMPLETE_MARKER), JSON.stringify({
729
+ model: LOCAL_EMBEDDING_MODEL,
730
+ revision: LOCAL_EMBEDDING_MODEL_REVISION,
731
+ dtype,
732
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
733
+ }));
734
+ completed = true;
735
+ return;
736
+ }
737
+ startedEmpty = !existsSync(modelDir);
738
+ const banner = [
739
+ "",
740
+ "Downloading local embedding model (first run only)",
741
+ `${"─".repeat(52)}`,
742
+ ` Model: ${LOCAL_EMBEDDING_MODEL}`,
743
+ ` Revision: ${LOCAL_EMBEDDING_MODEL_REVISION.slice(0, 12)}`,
744
+ ` Dtype: ${dtype} (${getDtypeDisplaySize(dtype)})`,
745
+ ` RAM: ${ramGB}GB`,
746
+ ` Cache dir: ${cacheDir}`,
747
+ "",
748
+ " This may take a few minutes on the first run...",
749
+ ""
750
+ ];
751
+ process.stderr.write(`${banner.join("\n")}\n`);
752
+ log$2.info("starting model download", {
753
+ model: LOCAL_EMBEDDING_MODEL,
754
+ revision: LOCAL_EMBEDDING_MODEL_REVISION,
755
+ dtype,
756
+ cacheDir
757
+ }, {
758
+ event_name: "embedder.model.download.ensuremodeldownloaded",
759
+ file: "packages/embedder/src/model-download.ts",
760
+ function: "ensureModelDownloaded",
761
+ site_id: "embedder.model.download.ensuremodeldownloaded.10"
762
+ });
763
+ const { env, pipeline } = await import("@huggingface/transformers");
764
+ const prevCacheDir = env.cacheDir;
765
+ const prevAllowRemote = env.allowRemoteModels;
766
+ const prevLocalModelPath = env.localModelPath;
767
+ const prevRemoteHost = env.remoteHost;
768
+ const prevRemotePathTemplate = env.remotePathTemplate;
769
+ env.cacheDir = cacheDir;
770
+ env.allowRemoteModels = true;
771
+ env.localModelPath = cacheDir;
772
+ env.remotePathTemplate = `{model}/resolve/${LOCAL_EMBEDDING_MODEL_REVISION}/`;
773
+ if (opts?.mirror) env.remoteHost = opts.mirror.endsWith("/") ? opts.mirror : `${opts.mirror}/`;
774
+ let lastProgress = 0;
775
+ const startTime = performance.now();
776
+ try {
777
+ await pipeline("feature-extraction", LOCAL_EMBEDDING_MODEL, {
778
+ dtype,
779
+ device: "cpu",
780
+ progress_callback: (progress) => {
781
+ if (progress.status === "progress" && typeof progress.progress === "number") {
782
+ const pct = Math.round(progress.progress);
783
+ if (pct >= lastProgress + 10) {
784
+ lastProgress = pct;
785
+ process.stderr.write(` ${pct}% — ${progress.file ?? ""}\n`);
786
+ }
787
+ } else if (progress.status === "done" && progress.file) process.stderr.write(` done ${progress.file}\n`);
788
+ }
789
+ });
790
+ } finally {
791
+ env.cacheDir = prevCacheDir;
792
+ env.allowRemoteModels = prevAllowRemote;
793
+ env.localModelPath = prevLocalModelPath;
794
+ env.remoteHost = prevRemoteHost;
795
+ env.remotePathTemplate = prevRemotePathTemplate;
796
+ }
797
+ writeFileSync(join(cacheDir, DOWNLOAD_COMPLETE_MARKER), JSON.stringify({
798
+ model: LOCAL_EMBEDDING_MODEL,
799
+ revision: LOCAL_EMBEDDING_MODEL_REVISION,
800
+ dtype,
801
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
802
+ }));
803
+ completed = true;
804
+ const elapsedSec = Math.round((performance.now() - startTime) / 1e3);
805
+ const finalSizeMB = getDirSizeMB(cacheDir);
806
+ const summary = [
807
+ "",
808
+ " Download complete!",
809
+ ` Size: ${finalSizeMB}MB | Time: ${elapsedSec}s`,
810
+ ` Location: ${cacheDir}`,
811
+ ""
812
+ ];
813
+ process.stderr.write(`${summary.join("\n")}\n`);
814
+ log$2.info("model download complete", {
815
+ model: LOCAL_EMBEDDING_MODEL,
816
+ revision: LOCAL_EMBEDDING_MODEL_REVISION,
817
+ dtype,
818
+ sizeMB: finalSizeMB,
819
+ elapsedSec,
820
+ cacheDir
821
+ }, {
822
+ event_name: "embedder.model.download.ensuremodeldownloaded",
823
+ file: "packages/embedder/src/model-download.ts",
824
+ function: "ensureModelDownloaded",
825
+ site_id: "embedder.model.download.ensuremodeldownloaded.11"
826
+ });
827
+ } finally {
828
+ clearInterval(lockHeartbeat);
829
+ if (!completed && startedEmpty) rmSync(modelDir, {
830
+ recursive: true,
831
+ force: true
832
+ });
833
+ releaseLock(cacheDir);
834
+ }
835
+ }
836
+ //#endregion
837
+ //#region config/index.ts
838
+ /**
839
+ * Sno Station Memory centralized configuration.
840
+ * Shared tunable constants for every memory skin.
841
+ * Organized by domain: Scoring → Retrieval → Storage → Backup → Cache → Session → Capture → Reflection
842
+ */
843
+ /** Maximum wait for sidecar requests and resource cleanup during shutdown. */
844
+ const MEMORY_SHUTDOWN_TIMEOUT_MS = 5e3;
845
+ /** Default importance score for new memories (0.0–1.0) */
846
+ const DEFAULT_IMPORTANCE = .7;
847
+ /** Default scope for memories without explicit scope */
848
+ const DEFAULT_SCOPE = "global";
849
+ /** Default embedding vector dimension (Voyage AI 1024-d) */
850
+ const VECTOR_DIMENSION_DEFAULT = 1024;
851
+ /** Production sno.ai host origin used by @snoai/observability. */
852
+ const SNO_OBSERVE_DEFAULT_BASE_URL = "https://www.sno.ai";
853
+ /** Default observability agent id for OpenClaw plugin emits. */
854
+ const SNO_OBSERVE_DEFAULT_AGENT_ID = "openclaw";
855
+ /** Bounded lifecycle observe flush — enough headroom for the SDK to complete one HTTP POST batch. */
856
+ const SNO_OBSERVE_FLUSH_TIMEOUT_MS = 8e3;
857
+ /** Default and minimum character-estimated token budgets for one recall result. */
858
+ const DEFAULT_RECALL_TOKEN_BUDGET = 7e3;
859
+ const MIN_RECALL_TOKEN_BUDGET = 5e3;
860
+ /** Weight for vector (semantic) branch in hybrid score fusion */
861
+ const DEFAULT_VECTOR_WEIGHT = .7;
862
+ /** Weight for BM25 (keyword) branch in hybrid score fusion */
863
+ const DEFAULT_BM25_WEIGHT = .3;
864
+ /**
865
+ * Hard ceiling for candidate pool expansion. Also the retrieval limit `memory_recall` asks for,
866
+ * so it bounds how much of a live store one answer can see. Raised 100 → 512 on 2026-09-06 (owner
867
+ * order): atomic rows are small and many, and at 100 a 159-row live store served 76 rows per
868
+ * question, cutting live to-dos the question asked for; at 512 the whole store came back for
869
+ * 3,476 tokens, half the recall token budget. Raised again 512 -> 2048 on 2026-09-15: the pool is
870
+ * `max(candidatePoolSize, limit * 2)` clamped here, so at 512 a caller asking for more than 256
871
+ * memories silently got fewer, and the ceiling — not the ranking — decided what the model saw.
872
+ */
873
+ const MAX_CANDIDATE_POOL_SIZE = 2048;
874
+ /**
875
+ * Measurement-only overrides for the block 210 retrieval-breadth experiment.
876
+ *
877
+ * Both are OFF unless the named environment variable is set, and neither is
878
+ * reachable from the plugin configuration schema, so a deployed plugin cannot
879
+ * turn them on: the experiment harness sets them on the process it starts and
880
+ * nothing else does. They exist because the runtime and the schema both stop
881
+ * the candidate pool at `MAX_CANDIDATE_POOL_SIZE`, which makes the pool-200
882
+ * cell impossible to run at all without one enabling edit (PRD 210 DEC-1).
883
+ *
884
+ * Read at call time, not at import time, so a harness that sets the variable
885
+ * after this module loads still gets the value it asked for.
886
+ */
887
+ function experimentCandidatePoolOverride() {
888
+ const raw = process.env.MEM_CLAW_EXPERIMENT_CANDIDATE_POOL_SIZE?.trim();
889
+ if (!raw) return void 0;
890
+ const parsed = Number(raw);
891
+ if (!Number.isSafeInteger(parsed) || parsed < 1) return void 0;
892
+ return parsed;
893
+ }
894
+ /** True only while the block 210 experiment harness has asked for MMR off. */
895
+ function experimentMmrDisabled() {
896
+ return process.env.MEM_CLAW_EXPERIMENT_DISABLE_MMR?.trim() === "1";
897
+ }
898
+ /**
899
+ * Token budget for the aggregation payload ONE consumer receives.
900
+ *
901
+ * Derived, and every number is a measurement. The answering engine's context is 64K tokens (owner,
902
+ * 2026-08-14, raised from 32K with the Qwen 3.8 rollout); half is reserved for the question, the
903
+ * surrounding prompt and the answer, leaving 32K for recalled evidence. Measured with
904
+ * `dev-scripts/census-aggregation-payload.mts` against the largest real store
905
+ * (`academic_researcher_weekly`, 138 active profile/episodic rows): the ENTIRE population renders in
906
+ * 43,699 characters ~= 10,925 tokens, a sixth of the context. A complete aggregation is therefore
907
+ * the ordinary case on real data, not an aspiration.
908
+ *
909
+ * The HALF is the load-bearing part, not the literal number. When the context moved to 64K this
910
+ * constant did not move with it for one commit, and a budget that stays put while its derivation
911
+ * doubles silently becomes a quarter of the context — a tightening nobody decided and nobody would
912
+ * find. That is the same shape as defect 2 below. If the context changes again, this changes.
913
+ *
914
+ * Known trade, stated rather than discovered later: widening this window is what raised aggregation
915
+ * from 0.045 to 0.744 on 2026-08-13, and it is also what dropped FAA 0.647 -> 0.600 in the same
916
+ * run, because retired rows the old ceiling had hidden came back into view. The answer to that is
917
+ * REM removing them (PRD 30/40), never a smaller recall window — shrinking this to protect FAA
918
+ * re-severs the counting path, which is the defect this constant exists to record.
919
+ *
920
+ * This replaces three ceilings that stacked on one path and severed it. Measured on the full
921
+ * benchmark run of 2026-08-13: 30 counting questions scored 0.045 mean with 28 of them exactly
922
+ * 0.000, while the same personas' other 60 questions scored 0.748. The model was not wrong — asked
923
+ * for a week of steps it answered "14,392 steps (recorded on June 7). No other step data is logged
924
+ * for the rest of the week", because 8 rows of 138 reached it. A model cannot total rows it was
925
+ * never shown. The three were:
926
+ *
927
+ * 1. `MAX_AGGREGATION_OUTPUT_ROWS = 8` — no derivation anywhere; 5.8% of a population handed to a
928
+ * question whose entire job is to total that population.
929
+ * 2. `MAX_AGGREGATION_TOOL_RESULT_CHARS = 16_384` — a unit error. 16,384 was the OLD 16K context
930
+ * in TOKENS, applied as a CHARACTER count, binding 3-4x tighter than it read.
931
+ * 3. Charging each consumer for the other's copy: the budget measured `JSON.stringify(result)`,
932
+ * which carries every row twice — once rendered, once in `memories` — while the OpenClaw host
933
+ * reads only the rendered text and the eval reads only `memories`.
934
+ *
935
+ * So this budget is counted in tokens, against the larger of the two consumer views, never a sum.
936
+ */
937
+ const MAX_AGGREGATION_RESULT_TOKENS = 32768;
938
+ /** Additive recency boost magnitude */
939
+ const RECENCY_WEIGHT = .1;
940
+ /** Maximum allowed recency weight */
941
+ const RECENCY_WEIGHT_MAX = .5;
942
+ /** Base multiplier for importance weighting (score * (base + importance * base)) */
943
+ const IMPORTANCE_WEIGHT_BASE = .7;
944
+ /** Minimum time decay multiplier (floor for very old entries) */
945
+ const TIME_DECAY_FLOOR = .6;
946
+ /**
947
+ * Relevance vs diversity tradeoff for MMR (0.7 = 70% relevance, 30% diversity).
948
+ * `applyMmrDiversity` normalizes the relevance term to [0,1] (batch-max) before
949
+ * applying this weight — without that normalization, the shrinker chain above
950
+ * compresses relevance so far below the [0,1] cosine-similarity diversity term
951
+ * that this ratio was moot (diversity always won). Fixed 2026-07-05.
952
+ */
953
+ const MMR_LAMBDA = .7;
954
+ /** Weight for fusion score in rerank blend */
955
+ const RERANK_BLEND_VECTOR = .3;
956
+ /** Weight for cross-encoder score in rerank blend */
957
+ const RERANK_BLEND_CROSS = .7;
958
+ /** Fusion-score weight in local cosine-blend rerank */
959
+ const LIGHTWEIGHT_FUSION_WEIGHT = .7;
960
+ /** Cosine-similarity weight in local cosine-blend rerank */
961
+ const LIGHTWEIGHT_COSINE_WEIGHT = .3;
962
+ /** Default rerank model identifier */
963
+ const DEFAULT_RERANK_MODEL = "rerank-2";
964
+ /** Default timeout for rerank API calls in milliseconds */
965
+ const DEFAULT_RERANK_TIMEOUT_MS = 15e3;
966
+ /**
967
+ * Maximum allowed list query page size; also caps each search branch
968
+ * (`memory-store-search-api.ts` clamps both the semantic and the keyword branch to it), so it
969
+ * stays >= the pool ceiling. Derived, not written: left at a literal 512 when the pool ceiling
970
+ * went 512 -> 2048 on 2026-09-15, every branch silently returned at most 512 candidates while
971
+ * retrieval asked for up to 2048, and the ceiling decided what ranking never saw.
972
+ */
973
+ const MAX_LIST_LIMIT = MAX_CANDIDATE_POOL_SIZE;
974
+ const MAX_RECALLED_TODO_TOKENS = 1e3;
975
+ /**
976
+ * Ceiling for chunk-level fetch budgets (semantic/keyword chunk search).
977
+ * Deliberately independent of MAX_LIST_LIMIT: memory-level wrappers overfetch
978
+ * chunks (limit * 8) so one high-recall parent cannot collapse parent diversity.
979
+ */
980
+ const MAX_CHUNK_FETCH_LIMIT = 4096;
981
+ /** Minimum score threshold for forget-query matches */
982
+ const FORGET_QUERY_MIN_SCORE = .8;
983
+ /**
984
+ * Minimum age of the newest backup before another is taken (1 day). A backup is a full copy of
985
+ * the store, so an hourly cadence cost a 1.7 GB store 40 GB of disk a day.
986
+ */
987
+ const BACKUP_INTERVAL_MS = 864e5;
988
+ /**
989
+ * Share of the backup volume that must stay free. Before a backup is written the oldest backups are
990
+ * deleted until the copy fits above this floor, and again afterwards if the volume is still under
991
+ * it; the newest backup is always kept, and when even that is not enough the backup is skipped.
992
+ */
993
+ const BACKUP_MIN_FREE_DISK_RATIO = .1;
994
+ /** How often the maintenance timer wakes to see which jobs are due (1 hour). */
995
+ const MAINTENANCE_TICK_MS = 36e5;
996
+ /** Full-page integrity sweep (1 hour). */
997
+ const INTEGRITY_CHECK_INTERVAL_MS = 36e5;
998
+ /** Usage-telemetry outbox drain and quarantine cleanup (1 hour). */
999
+ const USAGE_OUTBOX_INTERVAL_MS = 36e5;
1000
+ /** Pruning of expired recall/inject usage events (1 hour). */
1001
+ const USAGE_EVENT_RETENTION_INTERVAL_MS = 36e5;
1002
+ /** Full-text index segment merge (1 hour). */
1003
+ const FTS_MERGE_INTERVAL_MS = 36e5;
1004
+ /** Query-planner statistics refresh (1 hour). */
1005
+ const PLANNER_STATISTICS_INTERVAL_MS = 36e5;
1006
+ /**
1007
+ * How often the automatic REM trigger is evaluated (1 hour). Evaluating is only a check: REM
1008
+ * itself runs on its own daily schedule and volume rule in src/sidecar/rem-trigger.ts.
1009
+ */
1010
+ const REM_TRIGGER_CHECK_INTERVAL_MS = 36e5;
1011
+ /** Embedder LRU cache TTL in milliseconds (30 minutes) */
1012
+ const CACHE_TTL_MS = 18e5;
1013
+ /** Transcript budget shared by an atomic window and its preceding context. */
1014
+ const ATOMIC_EXTRACTION_MAX_INPUT_TOKENS = 4096;
1015
+ const ATOMIC_ENRICHMENT_OUTPUT_TOKEN_BUDGET = 1400;
1016
+ /**
1017
+ * Output cap of one capture call. The capture reply lists every claim and then every fact with
1018
+ * its quote, roughly 70 tokens per fact; at 4,096 a 35-turn session replayed as one turn hit the
1019
+ * cap and lost the whole window (43 of 272 LoCoMo sessions, measured 2026-09-13). A window is
1020
+ * split by turns when a reply truncates, so a single long turn (a pasted document, a replayed
1021
+ * session) has only this cap between it and total loss. Sized from the budget, not the failure:
1022
+ * the prompt (skill, calendar reference, response schema, dictionaries) is about 10K tokens, the
1023
+ * transcript at most ATOMIC_EXTRACTION_MAX_INPUT_TOKENS, and the model serves a 64K context, so
1024
+ * 16,384 keeps the whole call near 30K; the longest LoCoMo session (40 messages, ~100 facts)
1025
+ * needs about 10K, which 8,192 only just covered.
1026
+ */
1027
+ const ATOMIC_CAPTURE_OUTPUT_TOKEN_BUDGET = 16384;
1028
+ /**
1029
+ * Wall time one capture call is given. The generic client timeout is what an installation sets
1030
+ * for short judgments (30s by default, 60s on the LoCoMo VM) and does not know this call's output
1031
+ * budget, so raising the budget silently made the call unfinishable: measured 2026-09-20, four
1032
+ * sessions produced `LlmClientTerminalError category=timeout` at 60s after 105-130s of work and
1033
+ * stored nothing. Sized from the budget at the extraction model's measured ~60 output tokens per
1034
+ * second, with the same headroom the budget carries.
1035
+ */
1036
+ const ATOMIC_CAPTURE_TIMEOUT_MS = 3e5;
1037
+ /** Maximum character length of auto-recall query before truncation */
1038
+ const DEFAULT_AUTO_RECALL_MAX_QUERY_LENGTH = 2e3;
1039
+ /** Maximum input characters for reflection prompt */
1040
+ const DEFAULT_REFLECTION_MAX_INPUT_CHARS = 24e3;
1041
+ /** Timeout for individual reflection LLM calls in milliseconds */
1042
+ const DEFAULT_REFLECTION_TIMEOUT_MS = 2e4;
1043
+ /** Session TTL in reflection tracking map (30 minutes) */
1044
+ const DEFAULT_REFLECTION_SESSION_TTL_MS = 18e5;
1045
+ /** Maximum chars scanned for error signals in conversation */
1046
+ const DEFAULT_REFLECTION_ERROR_SCAN_MAX_CHARS = 8e3;
1047
+ /** Cache TTL for loaded reflection slices in milliseconds */
1048
+ const REFLECTION_SLICE_CACHE_TTL_MS = 15e3;
1049
+ const RETRIEVAL_STORAGE_CHUNK_PROFILE = {
1050
+ minTokens: 256,
1051
+ targetTokens: 384,
1052
+ maxTokens: 448,
1053
+ overlapTokens: 32
1054
+ };
1055
+ /** Minimum tokens per chunk before merge (mirrors RETRIEVAL_STORAGE_CHUNK_PROFILE). */
1056
+ const CHUNK_MIN_TOKENS = RETRIEVAL_STORAGE_CHUNK_PROFILE.minTokens;
1057
+ /** Target tokens per chunk (mirrors RETRIEVAL_STORAGE_CHUNK_PROFILE). */
1058
+ const CHUNK_TARGET_TOKENS = RETRIEVAL_STORAGE_CHUNK_PROFILE.targetTokens;
1059
+ /** Max tokens per chunk before split (mirrors RETRIEVAL_STORAGE_CHUNK_PROFILE). */
1060
+ const CHUNK_MAX_TOKENS = RETRIEVAL_STORAGE_CHUNK_PROFILE.maxTokens;
1061
+ /** Overlap tokens between adjacent chunks (mirrors RETRIEVAL_STORAGE_CHUNK_PROFILE). */
1062
+ const CHUNK_OVERLAP_TOKENS = RETRIEVAL_STORAGE_CHUNK_PROFILE.overlapTokens;
1063
+ /** Tokenizer mode used by the chunker (mirrors DEFAULT_CHUNK_CONFIG.tokenizerMode). */
1064
+ const CHUNK_TOKENIZER_MODE = DEFAULT_CHUNK_CONFIG.tokenizerMode;
1065
+ /**
1066
+ * Diagnostic threshold for intra-memory chunk cosine similarity (PRD §8.1).
1067
+ * Pairs above this score are flagged as redundant during eval / introspection.
1068
+ */
1069
+ const INTRA_MEMORY_COSINE_THRESHOLD = .92;
1070
+ /** Alias for VECTOR_DIMENSION_DEFAULT — the embedder output dimension. */
1071
+ const EMBEDDER_DIM = VECTOR_DIMENSION_DEFAULT;
1072
+ /** Default embedder provider id stamped into chunk provenance. */
1073
+ const EMBEDDER_PROVIDER_DEFAULT = "local-onnx";
1074
+ /**
1075
+ * Default embedder model id stamped into chunk provenance.
1076
+ *
1077
+ * Codex 2026-04-30 (batch-C C1): the previous hard-coded
1078
+ * `qwen3-embedding-4b@1024` did not match the actual local default
1079
+ * (`LOCAL_EMBEDDING_MODEL`, the bundled local embedding model), which would
1080
+ * mislabel every default-provider chunk in eval traces. Tracking the
1081
+ * embedder package's constant keeps provenance honest by construction.
1082
+ */
1083
+ const EMBEDDER_MODEL_DEFAULT = LOCAL_EMBEDDING_MODEL;
1084
+ /** Per-hit bonus for repeated chunk hits inside one parent. */
1085
+ const MULTI_HIT_BONUS_PER_HIT = DEFAULT_AGGREGATION_CONFIG.multiHitBonusPerHit;
1086
+ /** Cap on the cumulative multi-hit bonus per parent. */
1087
+ const MULTI_HIT_BONUS_CAP = DEFAULT_AGGREGATION_CONFIG.multiHitBonusCap;
1088
+ /** Per-pair bonus for adjacent chunk hits within one parent. */
1089
+ const ADJACENCY_BONUS_PER_PAIR = DEFAULT_AGGREGATION_CONFIG.adjacencyBonusPerPair;
1090
+ /** Cap on the cumulative adjacency bonus per parent. */
1091
+ const ADJACENCY_BONUS_CAP = DEFAULT_AGGREGATION_CONFIG.adjacencyBonusCap;
1092
+ /** Invariant: bonusTotalInvariant >= MULTI_HIT_BONUS_CAP + ADJACENCY_BONUS_CAP. */
1093
+ const BONUS_TOTAL_INVARIANT = DEFAULT_AGGREGATION_CONFIG.bonusTotalInvariant;
1094
+ /** Filename for per-QA retrieval traces emitted during eval runs. */
1095
+ const EVAL_QA_TRACES_FILENAME = "qa_traces.jsonl";
1096
+ /** Multiplicative penalty applied to unreturned candidates after rerank. */
1097
+ const LIGHTWEIGHT_RERANK_PENALTY = .8;
1098
+ /**
1099
+ * Zod schema for the `recallLifecycle` config block. The whole block defaults
1100
+ * to `{}` so existing configs without it continue to parse and behave
1101
+ * bit-for-bit identically to the pre-Phase-0 baseline.
1102
+ *
1103
+ * Spec: openspec/changes/mem-lifecycle/specs/config/spec.md.
1104
+ */
1105
+ const recallLifecycleSchema = z.object({
1106
+ retentionScorer: z.boolean().default(true),
1107
+ tierPromoter: z.boolean().default(true),
1108
+ autoRecallAccessTracking: z.boolean().default(true),
1109
+ traceEnabled: z.boolean().default(true),
1110
+ tierFloorMode: z.enum(["bare", "withFloor"]).default("bare"),
1111
+ tierPromotionTopK: z.number().int().positive().default(3),
1112
+ accessRateLimitMs: z.number().int().nonnegative().default(36e5),
1113
+ accessCountCeiling: z.number().int().positive().default(20)
1114
+ }).prefault({});
1115
+ /**
1116
+ * Resolved default `recallLifecycle` config. Use in code paths that need a
1117
+ * literal default object instead of re-parsing the schema each time.
1118
+ */
1119
+ const DEFAULT_RECALL_LIFECYCLE = recallLifecycleSchema.parse(void 0);
1120
+ //#endregion
1121
+ //#region src/engine/i18n/locales.ts
1122
+ const SUPPORTED_LOCALES = [
1123
+ "en",
1124
+ "de",
1125
+ "es",
1126
+ "fr",
1127
+ "zh",
1128
+ "zh-Hant",
1129
+ "ja",
1130
+ "ko",
1131
+ "ru"
1132
+ ];
1133
+ const SUPPORTED_SET = new Set(SUPPORTED_LOCALES);
1134
+ function isSupportedLocale(value) {
1135
+ return SUPPORTED_SET.has(value);
1136
+ }
1137
+ //#endregion
1138
+ //#region config/plugin-config-mode-schema.ts
1139
+ /**
1140
+ * Product LLM modes, tier-ordered: Local First (selected calls on host) → Agent
1141
+ * Native (every call borrows the host agent's model) → REM Enhanced (top
1142
+ * tier: SNO-REM-MEM serves the LoRA-covered calls, the host model covers
1143
+ * the rest).
1144
+ */
1145
+ const PRODUCT_MODES = [
1146
+ "local-first",
1147
+ "agent-native",
1148
+ "rem-enhanced"
1149
+ ];
1150
+ const DEFAULT_MODEL_MODE = "agent-native";
1151
+ const remEnhancedConfigSchema = z.object({ trigger: z.object({ tick: z.boolean().default(true) }).strict().prefault({}) }).strict().prefault({});
1152
+ const llmRoutingConfigSchema = z.object({
1153
+ mode: z.enum(PRODUCT_MODES),
1154
+ language: z.enum(SUPPORTED_LOCALES).default("en"),
1155
+ modelCalls: z.record(z.string(), z.record(z.enum(PRODUCT_MODES), z.enum([
1156
+ "off",
1157
+ "host",
1158
+ "sno-gpu"
1159
+ ]))).optional()
1160
+ }).strict();
1161
+ //#endregion
1162
+ //#region config/plugin-config-embedding-schema.ts
1163
+ const localEmbedSessionOptionsSchema = z.object({
1164
+ graphOptimizationLevel: z.enum([
1165
+ "disabled",
1166
+ "basic",
1167
+ "extended",
1168
+ "all"
1169
+ ]).default("extended"),
1170
+ enableMemPattern: z.boolean().default(false),
1171
+ enableCpuMemArena: z.boolean().default(false),
1172
+ executionMode: z.enum(["sequential", "parallel"]).optional(),
1173
+ interOpNumThreads: z.number().int().positive().optional(),
1174
+ intraOpNumThreads: z.number().int().positive().optional()
1175
+ }).strict().prefault({});
1176
+ const embeddingConfigSchema = z.object({
1177
+ provider: z.enum(["local-onnx"]).default("local-onnx"),
1178
+ /** Hugging Face model id. Defaults to the bundled PPLX INT8 model. */
1179
+ model: z.string().optional(),
1180
+ /** Output dimension after optional truncation and re-normalization. */
1181
+ dimensions: z.number().int().positive().default(VECTOR_DIMENSION_DEFAULT),
1182
+ /** Native dimension produced by the local model. */
1183
+ nativeDim: z.number().int().positive().optional(),
1184
+ /** Pinned HuggingFace revision (commit SHA) for local-onnx supply-chain integrity. */
1185
+ revision: z.string().optional(),
1186
+ /**
1187
+ * Pooling strategy for local-onnx. Read from the model's
1188
+ * `1_Pooling/config.json`. Omit to use the provider default; the bundled
1189
+ * PPLX model uses `mean`.
1190
+ */
1191
+ pooling: z.enum([
1192
+ "last_token",
1193
+ "mean",
1194
+ "cls"
1195
+ ]).optional(),
1196
+ normalized: z.boolean().optional(),
1197
+ /** Local ONNX model cache directory */
1198
+ cacheDir: z.string().optional(),
1199
+ offline: z.boolean().optional(),
1200
+ mirror: z.string().optional(),
1201
+ /** Quantization dtype: q4 | q8 | fp16 | fp32 */
1202
+ dtype: z.enum([
1203
+ "q4",
1204
+ "q8",
1205
+ "fp16",
1206
+ "fp32"
1207
+ ]).default("q8"),
1208
+ /** ONNX Runtime session options for local low-memory operation. */
1209
+ sessionOptions: localEmbedSessionOptionsSchema,
1210
+ /** Enable text chunking for long passages (default: true) */
1211
+ chunking: z.boolean().default(true)
1212
+ }).prefault({});
1213
+ //#endregion
1214
+ //#region src/model/signed-registry-constants.ts
1215
+ /** Fixed signed, persisted, and host protocol values. Change only with their external authority. */
1216
+ const FIXED_EXTERNAL_VALUE_49 = "database contains both mem_claw_memories and nodix_memories";
1217
+ const FIXED_EXTERNAL_VALUE_51 = "PRAGMA table_info(mem_claw_memories)";
1218
+ const FIXED_EXTERNAL_VALUE_52 = "cannot read vec_mem_claw_chunks dimension";
1219
+ const FIXED_EXTERNAL_VALUE_53 = "vec_mem_claw_chunks does not match the current schema (configured dim ";
1220
+ const FIXED_EXTERNAL_VALUE_54 = "DROP TABLE mem_claw_chunks_fts";
1221
+ const FIXED_EXTERNAL_VALUE_55 = "database contains both vec_mem_claw_chunks and nodix_memory_chunk_vectors";
1222
+ const FIXED_EXTERNAL_VALUE_56 = "INSERT INTO nodix_memory_chunk_vectors(id, project_id, embedding) SELECT id, project_id, embedding FROM vec_mem_claw_chunks";
1223
+ const FIXED_EXTERNAL_VALUE_57 = "INSERT INTO nodix_memory_chunk_vectors(id, project_id, embedding)\n SELECT vectors.id, memories.project_id, vectors.embedding\n FROM vec_mem_claw_chunks AS vectors\n JOIN nodix_memory_chunks AS chunks ON chunks.chunk_id = vectors.id\n JOIN nodix_memories AS memories ON memories.id = chunks.memory_id";
1224
+ const FIXED_EXTERNAL_VALUE_58 = ";\n DROP TABLE vec_mem_claw_chunks;\n ";
1225
+ const FIXED_EXTERNAL_VALUE_62 = "mem_claw.unplaced-candidate-migration.relocated.non.active.memory.rows.into.the.unplaced.candidate.table";
1226
+ const FIXED_EXTERNAL_VALUE_8 = "https://www.sno.ai/.well-known/sno-mem-openclaw-release.json";
1227
+ const FIXED_EXTERNAL_VALUE_9 = "did:web:www.sno.ai#sno-mem-openclaw-release";
1228
+ const FIXED_IDX_MEMORY = "idx_mem_claw";
1229
+ const FIXED_IDX_MEMORY_ACTIVE_TASK_CURRENT_REVISION = "idx_mem_claw_active_task_current_revision";
1230
+ const FIXED_IDX_MEMORY_ACTIVE_TASK_EVIDENCE_INSTANCE = "idx_mem_claw_active_task_evidence_instance";
1231
+ const FIXED_IDX_MEMORY_ACTIVE_TASK_INSTANCES_PROJECTION = "idx_mem_claw_active_task_instances_projection";
1232
+ const FIXED_IDX_MEMORY_MEMORIES_CATEGORY = "idx_mem_claw_memories_category";
1233
+ const FIXED_IDX_MEMORY_MEMORIES_CONTENT_HASH = "idx_mem_claw_memories_content_hash";
1234
+ const FIXED_IDX_MEMORY_MEMORIES_FACT_ID = "idx_mem_claw_memories_fact_id";
1235
+ const FIXED_IDX_MEMORY_MEMORIES_LANE_PROJECT = "idx_mem_claw_memories_lane_project";
1236
+ const FIXED_IDX_MEMORY_MEMORIES_PROJECT = "idx_mem_claw_memories_project";
1237
+ const FIXED_IDX_MEMORY_MEMORIES_PROJECT_CONTENT_HASH = "idx_mem_claw_memories_project_content_hash";
1238
+ const FIXED_IDX_MEMORY_MEMORIES_PROJECT_FACT_KEY_ACTIVE = "idx_mem_claw_memories_project_fact_key_active";
1239
+ const FIXED_IDX_MEMORY_MEMORIES_PROJECT_TIMESTAMP = "idx_mem_claw_memories_project_timestamp";
1240
+ const FIXED_MEMORY = "mem_claw";
1241
+ const FIXED_MEMORY_ACTIVE_TASK_EVIDENCE = "mem_claw_active_task_evidence";
1242
+ const FIXED_MEMORY_ACTIVE_TASK_INSTANCES = "mem_claw_active_task_instances";
1243
+ const FIXED_MEMORY_ACTIVE_TASK_MIGRATION_EVIDENCE = "mem_claw_active_task_migration_evidence";
1244
+ const FIXED_MEMORY_ACTIVE_TASK_MIGRATION_MANIFESTS = "mem_claw_active_task_migration_manifests";
1245
+ const FIXED_MEMORY_ACTIVE_TASK_REVISIONS = "mem_claw_active_task_revisions";
1246
+ const FIXED_MEMORY_ACTIVE_TASK_TRANSITIONS = "mem_claw_active_task_transitions";
1247
+ const FIXED_MEMORY_CHUNKS = "mem_claw_chunks";
1248
+ const FIXED_MEMORY_CHUNKS_AD = "mem_claw_chunks_ad";
1249
+ const FIXED_MEMORY_CHUNKS_AI = "mem_claw_chunks_ai";
1250
+ const FIXED_MEMORY_CHUNKS_AU = "mem_claw_chunks_au";
1251
+ const FIXED_MEMORY_CHUNKS_FTS = "mem_claw_chunks_fts";
1252
+ const FIXED_MEMORY_CHUNKS_MEM_FACET_IDX = "mem_claw_chunks_mem_facet_idx";
1253
+ const FIXED_MEMORY_CHUNKS_MEM_IDX = "mem_claw_chunks_mem_idx";
1254
+ const FIXED_MEMORY_CHUNKS_MEMORY_ID_IDX = "mem_claw_chunks_memory_id_idx";
1255
+ const FIXED_MEMORY_EXTRACTION_TIMESTAMPS = "mem_claw_extraction_timestamps";
1256
+ const FIXED_MEMORY_MEMORIES = "mem_claw_memories";
1257
+ const FIXED_MEMORY_MEMORIES_FACT_ID_INSERT_GUARD = "mem_claw_memories_fact_id_insert_guard";
1258
+ const FIXED_MEMORY_MEMORIES_FACT_ID_UPDATE_GUARD = "mem_claw_memories_fact_id_update_guard";
1259
+ const FIXED_MEMORY_MIGRATION_MARKERS = "mem_claw_migration_markers";
1260
+ const FIXED_MEMORY_PROFILE_RECOVERY_ENTRIES = "mem_claw_profile_recovery_entries";
1261
+ const FIXED_MEMORY_PROVIDER_AGENT_MAPPINGS = "mem_claw_provider_agent_mappings";
1262
+ const FIXED_MEMORY_PROVIDER_PROJECT_AGENTS = "mem_claw_provider_project_agents";
1263
+ const FIXED_MEMORY_PROVIDER_PROJECT_MAPPINGS = "mem_claw_provider_project_mappings";
1264
+ const FIXED_MEMORY_ROW_PATH_PATTERN = /^mem-claw\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.md$/;
1265
+ const FIXED_MEMORY_SNO_AI_EXTRACT = "mem_claw/sno_ai_extract";
1266
+ const FIXED_MEMORY_SNO_CONFLICT_VERDICT = "mem_claw/sno_conflict_verdict";
1267
+ const FIXED_MEMORY_SNO_EXTRACT_CHAT = "mem_claw/sno_extract_chat";
1268
+ const FIXED_MEMORY_SNO_EXTRACT_PROFILE = "mem_claw/sno_extract_profile";
1269
+ const FIXED_MEMORY_TASK_LIFECYCLE_COMMANDS = "mem_claw_task_lifecycle_commands";
1270
+ const FIXED_MEMORY_UNPLACED_CANDIDATES = "mem_claw_unplaced_candidates";
1271
+ const FIXED_PROTOCOL_VALUE_63 = "mem-claw-internal-llm";
1272
+ const FIXED_PROTOCOL_VALUE_64 = ".openclaw";
1273
+ const FIXED_PROTOCOL_VALUE_65 = "SELECT project_id FROM nodix_provider_project_mappings WHERE user_id = ? AND external_system = 'openclaw' AND external_project_key = ? LIMIT 1";
1274
+ const FIXED_PROTOCOL_VALUE_66 = "SELECT agent_id FROM nodix_provider_agent_mappings WHERE user_id = ? AND external_system = 'openclaw' AND external_agent_key = ? LIMIT 1";
1275
+ const FIXED_PROTOCOL_VALUE_67 = "INSERT OR IGNORE INTO nodix_provider_project_mappings(user_id, external_system, external_project_key, project_id, created_at_ms) VALUES (?, 'openclaw', ?, ?, ?)";
1276
+ const FIXED_PROTOCOL_VALUE_68 = "INSERT OR IGNORE INTO nodix_provider_agent_mappings(user_id, external_system, external_agent_key, agent_id, created_at_ms) VALUES (?, 'openclaw', ?, ?, ?)";
1277
+ const FIXED_PROTOCOL_VALUE_69 = "http://localhost:8070/codex/v1";
1278
+ const FIXED_PROTOCOL_VALUE_70 = "hermes";
1279
+ const FIXED_PROTOCOL_VALUE_71 = "claude-code";
1280
+ const FIXED_PROTOCOL_VALUE_72 = "codex";
1281
+ const FIXED_PROTOCOL_VALUE_73 = "mem-claw:atomic-card:v1";
1282
+ const FIXED_PROTOCOL_VALUE_74 = "sno-mem-claw";
1283
+ const FIXED_PROTOCOL_VALUE_75 = "mem-claw/self_improvement_log";
1284
+ const FIXED_PROTOCOL_VALUE_76 = "Provider authority externalSystem must be openclaw";
1285
+ const FIXED_PROTOCOL_VALUE_77 = "mem-claw/";
1286
+ const FIXED_PROTOCOL_VALUE_78 = "mem-claw/reflection/";
1287
+ const FIXED_PROTOCOL_VALUE_79 = "Stable rules inherited from mem-claw reflections. Treat as long-term behavioral constraints unless user overrides.";
1288
+ const FIXED_VEC_MEMORY = "vec_mem_claw";
1289
+ const FIXED_VEC_MEMORY_CHUNKS = "vec_mem_claw_chunks";
1290
+ const PERSISTED_CANDIDATE_HASH_V1 = "mem-claw:unplaced-candidate:legacy:v1";
1291
+ const PERSISTED_CONTENT_HASH_V1 = "mem-claw:hash:v1";
1292
+ const PERSISTED_CONTENT_HASH_V3 = "mem-claw:hash:v3";
1293
+ const PERSISTED_PROVIDER_SYSTEM = "openclaw";
1294
+ //#endregion
1295
+ //#region src/model/llm-client-types.ts
1296
+ const LLM_PRESETS = [
1297
+ FIXED_MEMORY_SNO_AI_EXTRACT,
1298
+ FIXED_MEMORY_SNO_EXTRACT_CHAT,
1299
+ FIXED_MEMORY_SNO_EXTRACT_PROFILE,
1300
+ FIXED_MEMORY_SNO_CONFLICT_VERDICT
1301
+ ];
1302
+ //#endregion
1303
+ //#region config/plugin-config-feature-schema.ts
1304
+ const sessionMemoryConfigSchema = z.object({
1305
+ enabled: z.boolean().default(true),
1306
+ messageCount: z.number().int().min(1).max(100).default(15)
1307
+ }).prefault({});
1308
+ const selfImprovementConfigSchema = z.object({
1309
+ enabled: z.boolean().default(true),
1310
+ beforeResetNote: z.boolean().default(true),
1311
+ skipSubagentBootstrap: z.boolean().default(true),
1312
+ ensureLearningFiles: z.boolean().default(true)
1313
+ }).prefault({});
1314
+ const extractionConfigSchema = z.object({ llm: z.object({
1315
+ preset: z.enum(LLM_PRESETS).default(FIXED_MEMORY_SNO_AI_EXTRACT),
1316
+ /** Overrides provider default / env baseURL if set. */
1317
+ baseURL: z.string().optional(),
1318
+ /** Overrides provider-native env if set. */
1319
+ apiKey: z.string().optional(),
1320
+ timeoutMs: z.number().int().min(1e3).max(3e5).default(3e4)
1321
+ }).strict().prefault({}) }).strict().prefault({});
1322
+ const memoryReflectionConfigSchema = z.object({
1323
+ messageCount: z.number().int().min(1).max(500).default(120),
1324
+ maxInputChars: z.number().int().min(1e3).max(2e5).default(DEFAULT_REFLECTION_MAX_INPUT_CHARS),
1325
+ timeoutMs: z.number().int().min(5e3).max(3e5).default(DEFAULT_REFLECTION_TIMEOUT_MS),
1326
+ errorReminderMaxEntries: z.number().int().min(0).max(50).default(3),
1327
+ dedupeErrorSignals: z.boolean().default(true),
1328
+ injectMode: z.enum([
1329
+ "inheritance+derived",
1330
+ "inheritance-only",
1331
+ "none"
1332
+ ]).default("inheritance+derived"),
1333
+ storeToDb: z.boolean().default(true),
1334
+ /**
1335
+ * Inject reflection invariants/derived slices into agent prompts at recall
1336
+ * time. Default `false` until the LoCoMo paired-arm gate validates eval-
1337
+ * neutrality (PRD §4.4.1, §5 eval gate). Permanent kill switch even after
1338
+ * the default flips.
1339
+ */
1340
+ injectIntoPrompt: z.boolean().default(false),
1341
+ agentId: z.string().optional()
1342
+ }).prefault({});
1343
+ //#endregion
1344
+ //#region config/plugin-config-observe-schema.ts
1345
+ const AGENT_IDS = [
1346
+ PERSISTED_PROVIDER_SYSTEM,
1347
+ FIXED_PROTOCOL_VALUE_70,
1348
+ FIXED_PROTOCOL_VALUE_71,
1349
+ FIXED_PROTOCOL_VALUE_72
1350
+ ];
1351
+ const observeAgentIdSchema = z.enum(AGENT_IDS, { error: () => `observe.agentId must be one of ${AGENT_IDS.join(", ")}` });
1352
+ /** The observe agent id a skin reports under; a skin id outside the SDK's set is a hard error. */
1353
+ function observeAgentId(skinId) {
1354
+ return observeAgentIdSchema.parse(skinId);
1355
+ }
1356
+ function isObserveAgentId(skinId) {
1357
+ return observeAgentIdSchema.safeParse(skinId).success;
1358
+ }
1359
+ function isLoopbackUrl(url) {
1360
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1" || url.hostname === "[::1]";
1361
+ }
1362
+ function validateObserveBaseUrl(value, ctx) {
1363
+ let parsed;
1364
+ try {
1365
+ parsed = new URL(value);
1366
+ } catch {
1367
+ ctx.addIssue({
1368
+ code: z.ZodIssueCode.custom,
1369
+ path: ["baseUrl"],
1370
+ message: `Invalid observe.baseUrl: "${value}"`
1371
+ });
1372
+ return;
1373
+ }
1374
+ const normalized = parsed.origin;
1375
+ if (process.env.SNO_STATION_MEM_NODE_ENV === "test" && isLoopbackUrl(parsed)) {
1376
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") ctx.addIssue({
1377
+ code: z.ZodIssueCode.custom,
1378
+ path: ["baseUrl"],
1379
+ message: "observe.baseUrl test fixture must use http or https"
1380
+ });
1381
+ return;
1382
+ }
1383
+ if (normalized !== "https://www.sno.ai") ctx.addIssue({
1384
+ code: z.ZodIssueCode.custom,
1385
+ path: ["baseUrl"],
1386
+ message: `observe.baseUrl must be ${SNO_OBSERVE_DEFAULT_BASE_URL} outside loopback tests`
1387
+ });
1388
+ }
1389
+ const observeConfigSchema = z.object({
1390
+ enabled: z.boolean().default(true),
1391
+ baseUrl: z.string().default(SNO_OBSERVE_DEFAULT_BASE_URL),
1392
+ agentId: observeAgentIdSchema.default(SNO_OBSERVE_DEFAULT_AGENT_ID)
1393
+ }).prefault({}).superRefine((value, ctx) => {
1394
+ if (value.enabled) validateObserveBaseUrl(value.baseUrl, ctx);
1395
+ });
1396
+ //#endregion
1397
+ //#region config/plugin-config-retrieval-schema.ts
1398
+ const log = createLogger("sno-station-mem:config:retrieval");
1399
+ const retrievalConfigSchema = z.object({
1400
+ mode: z.enum(["precision-recall", "vector"]).default("precision-recall"),
1401
+ /**
1402
+ * Top-K memories injected per turn during auto-recall. Source of truth
1403
+ * for the runtime retriever `limit`; AC5 drift test pins this default
1404
+ * to AUTO_RECALL_INJECTION_TOP_K (currently 20). Lower (15) trades
1405
+ * ~5pp accuracy for ~25% fewer prompt tokens.
1406
+ */
1407
+ recallTopK: z.number().int().min(0).max(2e3).default(20),
1408
+ vectorWeight: z.number().min(0).max(1).default(DEFAULT_VECTOR_WEIGHT),
1409
+ bm25Weight: z.number().min(0).max(1).default(DEFAULT_BM25_WEIGHT),
1410
+ minScore: z.number().min(0).max(1).default(0),
1411
+ rerank: z.enum([
1412
+ "cross-encoder",
1413
+ "lightweight",
1414
+ "none"
1415
+ ]).default("lightweight"),
1416
+ candidatePoolSize: z.number().int().min(10).max(2e3).default(64),
1417
+ rerankApiKey: z.string().optional(),
1418
+ rerankModel: z.string().default(DEFAULT_RERANK_MODEL),
1419
+ rerankTimeoutMs: z.number().int().min(1e3).max(12e4).default(DEFAULT_RERANK_TIMEOUT_MS),
1420
+ recencyHalfLifeDays: z.number().min(0).max(365).default(14),
1421
+ recencyWeight: z.number().min(0).max(RECENCY_WEIGHT_MAX).default(RECENCY_WEIGHT),
1422
+ /** Drop memories past their valid_until timestamp (default OFF — needs A/B eval) */
1423
+ temporalWeighting: z.boolean().default(false),
1424
+ mmrWindowOnly: z.boolean().default(false),
1425
+ temporalExpiry: z.boolean().default(false),
1426
+ /** Dynamic memories decay 3× faster in time-decay scoring (default ON — low risk) */
1427
+ temporalDecay: z.boolean().default(true),
1428
+ lengthNormAnchor: z.number().int().min(0).max(5e3).default(0),
1429
+ hardMinScore: z.number().min(0).max(1).default(0),
1430
+ timeDecayHalfLifeDays: z.number().min(0).max(365).default(60),
1431
+ /** Weight for fusion score in rerank blend */
1432
+ rerankBlendVector: z.number().min(0).max(1).optional(),
1433
+ /** Weight for cross-encoder score in rerank blend */
1434
+ rerankBlendCross: z.number().min(0).max(1).optional(),
1435
+ /** Fusion-score weight when rerank="lightweight" (local cosine blend) */
1436
+ lightweightFusionWeight: z.number().min(0).max(1).optional(),
1437
+ /** Cosine-score weight when rerank="lightweight" (local cosine blend) */
1438
+ lightweightCosineWeight: z.number().min(0).max(1).optional(),
1439
+ /** Base multiplier for importance weighting */
1440
+ importanceWeightBase: z.number().min(0).max(1).optional(),
1441
+ /** Minimum multiplier for old entries */
1442
+ timeDecayFloor: z.number().min(0).max(1).optional(),
1443
+ /** Relevance vs diversity tradeoff (default: 0.7) */
1444
+ mmrLambda: z.number().min(0).max(1).optional(),
1445
+ /** Custom rerank API endpoint URL. */
1446
+ rerankEndpoint: z.string().optional(),
1447
+ /** Rerank provider name */
1448
+ rerankProvider: z.enum([
1449
+ "jina",
1450
+ "siliconflow",
1451
+ "pinecone",
1452
+ "voyage",
1453
+ "dashscope",
1454
+ "tei",
1455
+ "custom"
1456
+ ]).optional(),
1457
+ /** Hard cap on candidates sent per rerank API request (some deployments reject over-limit batches) */
1458
+ rerankMaxCandidates: z.number().int().min(1).max(2e3).optional(),
1459
+ /** Scaling factor for access-based reinforcement (0 = disabled, default: 0.5) */
1460
+ reinforcementFactor: z.number().min(0).max(5).default(.5),
1461
+ /** Hard cap: effective half-life <= baseHalfLife * maxHalfLifeMultiplier (default: 3) */
1462
+ maxHalfLifeMultiplier: z.number().min(1).max(10).default(3)
1463
+ }).prefault({}).transform((ret, ctx) => {
1464
+ if (ret.rerank === "none") return ret;
1465
+ if ((ret.rerank === "cross-encoder" || ret.rerankEndpoint !== void 0) && ret.rerankProvider === void 0) ctx.addIssue({
1466
+ code: z.ZodIssueCode.custom,
1467
+ path: ["rerankProvider"],
1468
+ message: "retrieval.rerankProvider is required when retrieval.rerank is \"cross-encoder\" or retrieval.rerankEndpoint is set: the provider decides the request shape and the per-request batch limit"
1469
+ });
1470
+ if (ret.rerankEndpoint !== void 0) try {
1471
+ new URL(ret.rerankEndpoint);
1472
+ } catch {
1473
+ ctx.addIssue({
1474
+ code: z.ZodIssueCode.custom,
1475
+ path: ["rerankEndpoint"],
1476
+ message: `Invalid rerankEndpoint URL: "${ret.rerankEndpoint}"`
1477
+ });
1478
+ }
1479
+ const rerankApiKey = ret.rerankApiKey;
1480
+ if (ret.rerank === "cross-encoder" && !rerankApiKey?.trim()) {
1481
+ log.error("memory.rerank.key.missing", { cause: "missing-rerank-key" }, {
1482
+ event_name: "memory.rerank.key.missing",
1483
+ file: "packages/memory/config/plugin-config-retrieval-schema.ts",
1484
+ function: "retrievalConfigSchema",
1485
+ site_id: "memory.rerank.key.missing"
1486
+ });
1487
+ ctx.addIssue({
1488
+ code: z.ZodIssueCode.custom,
1489
+ path: ["rerankApiKey"],
1490
+ message: "retrieval.rerankApiKey is required for cross-encoder reranking"
1491
+ });
1492
+ }
1493
+ return ret;
1494
+ });
1495
+ //#endregion
1496
+ //#region config/session-strategy.ts
1497
+ /** @file session-strategy.ts
1498
+ * @purpose Defines session-memory strategy constants without importing plugin config schemas.
1499
+ * @boundary Shared literal values only; no schema or runtime registration dependencies.
1500
+ */
1501
+ const SESSION_STRATEGIES = [
1502
+ "memoryReflection",
1503
+ "systemSessionMemory",
1504
+ "none"
1505
+ ];
1506
+ //#endregion
1507
+ //#region config/plugin-config-schema.ts
1508
+ const scopesConfigSchema = z.object({
1509
+ default: z.string().default(DEFAULT_SCOPE),
1510
+ definitions: z.record(z.string(), z.object({
1511
+ description: z.string().optional(),
1512
+ metadata: z.record(z.string(), z.unknown()).optional()
1513
+ })).prefault({ global: { description: "Shared knowledge across all agents" } }),
1514
+ agentAccess: z.record(z.string(), z.array(z.string())).default({})
1515
+ }).prefault({});
1516
+ const providerConfigSchema = z.object({ userId: z.string().trim().optional() }).strict().prefault({});
1517
+ const ONBOARDING_PROFILES = [
1518
+ "local-active",
1519
+ "capture-only",
1520
+ "manual-only",
1521
+ "custom"
1522
+ ];
1523
+ const REM_OPERATIONS = ["rem-replace", "rem-update"];
1524
+ const pluginConfigSchema = z.object({
1525
+ embedding: embeddingConfigSchema,
1526
+ observe: observeConfigSchema,
1527
+ dbPath: z.string().optional(),
1528
+ provider: providerConfigSchema,
1529
+ ambientLearning: z.boolean().default(true),
1530
+ autoRecall: z.boolean().default(false),
1531
+ /** Minimum query length for auto-recall to fire (default: 15) */
1532
+ autoRecallMinLength: z.number().int().min(0).max(200).default(2),
1533
+ /** Skip re-injecting a memory if it was shown within the last N turns (0 = no dedup) */
1534
+ autoRecallMinRepeated: z.number().int().min(0).max(100).default(0),
1535
+ /** Maximum character length of auto-recall query before truncation */
1536
+ autoRecallMaxQueryLength: z.number().int().min(100).max(1e4).default(DEFAULT_AUTO_RECALL_MAX_QUERY_LENGTH),
1537
+ /** Timeout in ms for the entire auto-recall pipeline (embed + search + rerank) */
1538
+ autoRecallTimeoutMs: z.number().int().min(500).max(6e4).default(5e3),
1539
+ /**
1540
+ * Whitelist: if non-empty, ONLY these agentIds receive auto-recall injection.
1541
+ * Takes precedence over autoRecallExcludeAgents when both are set. Entries
1542
+ * are trimmed; empty strings are dropped.
1543
+ */
1544
+ autoRecallIncludeAgents: z.array(z.string().transform((s) => s.trim())).transform((arr) => arr.filter((s) => s.length > 0)).default([]),
1545
+ /**
1546
+ * Blocklist: agentIds excluded from auto-recall injection. The implicit
1547
+ * "main" fallback used when hook context lacks a parseable agent identity
1548
+ * is evaluated against this blocklist too.
1549
+ */
1550
+ autoRecallExcludeAgents: z.array(z.string().transform((s) => s.trim())).transform((arr) => arr.filter((s) => s.length > 0)).default([]),
1551
+ captureAssistant: z.boolean().default(false),
1552
+ retrieval: retrievalConfigSchema,
1553
+ scopes: scopesConfigSchema,
1554
+ enableManagementTools: z.boolean().default(false),
1555
+ /**
1556
+ * Optional user-facing language for tool descriptions and other static
1557
+ * locale-bound surface that cannot be derived from query text.
1558
+ */
1559
+ language: z.enum(SUPPORTED_LOCALES).optional(),
1560
+ sessionStrategy: z.enum(SESSION_STRATEGIES).default("systemSessionMemory"),
1561
+ sessionMemory: sessionMemoryConfigSchema,
1562
+ compression: z.object({ enabled: z.boolean().default(false) }).optional(),
1563
+ selfImprovement: selfImprovementConfigSchema,
1564
+ extraction: extractionConfigSchema,
1565
+ memoryReflection: memoryReflectionConfigSchema,
1566
+ /**
1567
+ * Phase 0 lifecycle stub channel. All flags default false; enabling any
1568
+ * lights up its dedicated wire site without altering the others.
1569
+ */
1570
+ recallLifecycle: recallLifecycleSchema,
1571
+ memoryTelemetry: z.object({
1572
+ enabled: z.boolean().default(true),
1573
+ currentKeyVersion: z.number().int().positive().default(1),
1574
+ key: z.string().default(""),
1575
+ historicKeys: z.array(z.string()).default([])
1576
+ }).prefault({}),
1577
+ debugContent: z.boolean().default(false),
1578
+ /**
1579
+ * Product LLM mode, tier-ordered: local-first → agent-native →
1580
+ * rem-enhanced. A true bare config defaults to agent-native; model route
1581
+ * config requires an explicit product mode.
1582
+ */
1583
+ mode: z.enum(PRODUCT_MODES).default(DEFAULT_MODEL_MODE),
1584
+ modelCalls: z.record(z.string(), z.record(z.enum(PRODUCT_MODES), z.enum([
1585
+ "off",
1586
+ "host",
1587
+ "sno-gpu"
1588
+ ]))).optional(),
1589
+ remOperations: z.array(z.enum(REM_OPERATIONS)).min(1).max(2).default([...REM_OPERATIONS]),
1590
+ remEnhanced: remEnhancedConfigSchema,
1591
+ /**
1592
+ * Installer completion marker (bin/_onboarding-core.js writes it into
1593
+ * this same config block). The runtime never reads it, but the strict
1594
+ * schema must accept it or every installer-onboarded config fails to
1595
+ * load.
1596
+ */
1597
+ onboarding: z.object({
1598
+ version: z.number().int().positive(),
1599
+ completedAt: z.string(),
1600
+ profile: z.enum(ONBOARDING_PROFILES)
1601
+ }).strict().optional()
1602
+ }).strict();
1603
+ //#endregion
1604
+ //#region src/model/model-call-table.ts
1605
+ const extract = {
1606
+ "local-first": "off",
1607
+ "agent-native": "host",
1608
+ "rem-enhanced": "sno-gpu"
1609
+ };
1610
+ const host = {
1611
+ "local-first": "off",
1612
+ "agent-native": "host",
1613
+ "rem-enhanced": "host"
1614
+ };
1615
+ const profile = {
1616
+ "local-first": "host",
1617
+ "agent-native": "host",
1618
+ "rem-enhanced": "host"
1619
+ };
1620
+ const rem = {
1621
+ "local-first": "host",
1622
+ "agent-native": "host",
1623
+ "rem-enhanced": "sno-gpu"
1624
+ };
1625
+ const remHost = {
1626
+ "local-first": "host",
1627
+ "agent-native": "host",
1628
+ "rem-enhanced": "host"
1629
+ };
1630
+ const chat = FIXED_MEMORY_SNO_EXTRACT_CHAT;
1631
+ const verdict = FIXED_MEMORY_SNO_CONFLICT_VERDICT;
1632
+ const MODEL_CALLS = {
1633
+ E1: {
1634
+ description: "conversation extraction",
1635
+ occasion: "memoryExtract",
1636
+ destinations: extract,
1637
+ snoPreset: chat,
1638
+ transport: {
1639
+ host: "agent-host-seam",
1640
+ snoGpu: "chat-completions"
1641
+ },
1642
+ promptVariant: {
1643
+ host: "standard",
1644
+ snoGpu: "standard"
1645
+ },
1646
+ replyParser: {
1647
+ host: "json",
1648
+ snoGpu: "json"
1649
+ }
1650
+ },
1651
+ E2: {
1652
+ description: "fact enrichment",
1653
+ occasion: "memoryExtract",
1654
+ destinations: extract,
1655
+ snoPreset: chat,
1656
+ transport: {
1657
+ host: "agent-host-seam",
1658
+ snoGpu: "chat-completions"
1659
+ },
1660
+ promptVariant: {
1661
+ host: "standard",
1662
+ snoGpu: "standard"
1663
+ },
1664
+ replyParser: {
1665
+ host: "json",
1666
+ snoGpu: "json"
1667
+ }
1668
+ },
1669
+ E3: {
1670
+ description: "missed figure recovery",
1671
+ occasion: "memoryExtract",
1672
+ destinations: extract,
1673
+ snoPreset: chat,
1674
+ transport: {
1675
+ host: "agent-host-seam",
1676
+ snoGpu: "chat-completions"
1677
+ },
1678
+ promptVariant: {
1679
+ host: "standard",
1680
+ snoGpu: "standard"
1681
+ },
1682
+ replyParser: {
1683
+ host: "json",
1684
+ snoGpu: "json"
1685
+ }
1686
+ },
1687
+ E4: {
1688
+ description: "compound record split",
1689
+ occasion: "memoryExtract",
1690
+ destinations: extract,
1691
+ snoPreset: chat,
1692
+ transport: {
1693
+ host: "agent-host-seam",
1694
+ snoGpu: "chat-completions"
1695
+ },
1696
+ promptVariant: {
1697
+ host: "standard",
1698
+ snoGpu: "standard"
1699
+ },
1700
+ replyParser: {
1701
+ host: "json",
1702
+ snoGpu: "json"
1703
+ }
1704
+ },
1705
+ E5: {
1706
+ description: "missing half recovery",
1707
+ occasion: "memoryExtract",
1708
+ destinations: extract,
1709
+ snoPreset: chat,
1710
+ transport: {
1711
+ host: "agent-host-seam",
1712
+ snoGpu: "chat-completions"
1713
+ },
1714
+ promptVariant: {
1715
+ host: "standard",
1716
+ snoGpu: "standard"
1717
+ },
1718
+ replyParser: {
1719
+ host: "json",
1720
+ snoGpu: "json"
1721
+ }
1722
+ },
1723
+ E6: {
1724
+ description: "subject check",
1725
+ occasion: "memoryExtract",
1726
+ destinations: extract,
1727
+ snoPreset: chat,
1728
+ transport: {
1729
+ host: "agent-host-seam",
1730
+ snoGpu: "chat-completions"
1731
+ },
1732
+ promptVariant: {
1733
+ host: "standard",
1734
+ snoGpu: "standard"
1735
+ },
1736
+ replyParser: {
1737
+ host: "json",
1738
+ snoGpu: "json"
1739
+ }
1740
+ },
1741
+ E7: {
1742
+ description: "unresolved subject recovery",
1743
+ occasion: "memoryExtract",
1744
+ destinations: extract,
1745
+ snoPreset: chat,
1746
+ transport: {
1747
+ host: "agent-host-seam",
1748
+ snoGpu: "chat-completions"
1749
+ },
1750
+ promptVariant: {
1751
+ host: "standard",
1752
+ snoGpu: "standard"
1753
+ },
1754
+ replyParser: {
1755
+ host: "json",
1756
+ snoGpu: "json"
1757
+ }
1758
+ },
1759
+ E8: {
1760
+ description: "same entity judgment",
1761
+ occasion: "memoryExtract",
1762
+ destinations: extract,
1763
+ snoPreset: chat,
1764
+ transport: {
1765
+ host: "agent-host-seam",
1766
+ snoGpu: "chat-completions"
1767
+ },
1768
+ promptVariant: {
1769
+ host: "standard",
1770
+ snoGpu: "standard"
1771
+ },
1772
+ replyParser: {
1773
+ host: "json",
1774
+ snoGpu: "json"
1775
+ }
1776
+ },
1777
+ E9: {
1778
+ description: "profile keying",
1779
+ occasion: "memoryExtract",
1780
+ destinations: extract,
1781
+ snoPreset: FIXED_MEMORY_SNO_EXTRACT_PROFILE,
1782
+ transport: {
1783
+ host: "agent-host-seam",
1784
+ snoGpu: "raw-completions"
1785
+ },
1786
+ promptVariant: {
1787
+ host: "standard",
1788
+ snoGpu: "standard"
1789
+ },
1790
+ replyParser: {
1791
+ host: "json",
1792
+ snoGpu: "json"
1793
+ }
1794
+ },
1795
+ E10: {
1796
+ description: "arrival retirement judgment",
1797
+ occasion: "conflictAdjudication",
1798
+ destinations: extract,
1799
+ snoPreset: verdict,
1800
+ transport: {
1801
+ host: "agent-host-seam",
1802
+ snoGpu: "raw-completions"
1803
+ },
1804
+ promptVariant: {
1805
+ host: "adapter-a-chat",
1806
+ snoGpu: "adapter-a-raw"
1807
+ },
1808
+ replyParser: {
1809
+ host: "json-or-single-token-verdict",
1810
+ snoGpu: "single-token-verdict"
1811
+ }
1812
+ },
1813
+ E11: {
1814
+ description: "date resolution",
1815
+ occasion: "dateResolution",
1816
+ destinations: host,
1817
+ snoPreset: chat,
1818
+ transport: {
1819
+ host: "agent-host-seam",
1820
+ snoGpu: "chat-completions"
1821
+ },
1822
+ promptVariant: {
1823
+ host: "standard",
1824
+ snoGpu: "standard"
1825
+ },
1826
+ replyParser: {
1827
+ host: "text",
1828
+ snoGpu: "text"
1829
+ }
1830
+ },
1831
+ E12: {
1832
+ description: "background state keying",
1833
+ occasion: "memoryExtract",
1834
+ destinations: extract,
1835
+ snoPreset: chat,
1836
+ transport: {
1837
+ host: "agent-host-seam",
1838
+ snoGpu: "chat-completions"
1839
+ },
1840
+ promptVariant: {
1841
+ host: "standard",
1842
+ snoGpu: "standard"
1843
+ },
1844
+ replyParser: {
1845
+ host: "json",
1846
+ snoGpu: "json"
1847
+ }
1848
+ },
1849
+ P1: {
1850
+ description: "profile conflict judgment",
1851
+ occasion: "conflictAdjudication",
1852
+ destinations: extract,
1853
+ snoPreset: verdict,
1854
+ transport: {
1855
+ host: "agent-host-seam",
1856
+ snoGpu: "raw-completions"
1857
+ },
1858
+ promptVariant: {
1859
+ host: "adapter-a-chat",
1860
+ snoGpu: "adapter-a-raw"
1861
+ },
1862
+ replyParser: {
1863
+ host: "json-or-single-token-verdict",
1864
+ snoGpu: "single-token-verdict"
1865
+ }
1866
+ },
1867
+ P2: {
1868
+ description: "profile lifecycle retirement",
1869
+ occasion: "profileSectionMerge",
1870
+ destinations: profile,
1871
+ snoPreset: chat,
1872
+ transport: {
1873
+ host: "agent-host-seam",
1874
+ snoGpu: "chat-completions"
1875
+ },
1876
+ promptVariant: {
1877
+ host: "standard",
1878
+ snoGpu: "standard"
1879
+ },
1880
+ replyParser: {
1881
+ host: "json",
1882
+ snoGpu: "json"
1883
+ }
1884
+ },
1885
+ P3: {
1886
+ description: "profile retirement recheck",
1887
+ occasion: "profileSectionMerge",
1888
+ destinations: profile,
1889
+ snoPreset: chat,
1890
+ transport: {
1891
+ host: "agent-host-seam",
1892
+ snoGpu: "chat-completions"
1893
+ },
1894
+ promptVariant: {
1895
+ host: "standard",
1896
+ snoGpu: "standard"
1897
+ },
1898
+ replyParser: {
1899
+ host: "json",
1900
+ snoGpu: "json"
1901
+ }
1902
+ },
1903
+ P4: {
1904
+ description: "profile section judgment",
1905
+ occasion: "profileSectionMerge",
1906
+ destinations: profile,
1907
+ snoPreset: chat,
1908
+ transport: {
1909
+ host: "agent-host-seam",
1910
+ snoGpu: "chat-completions"
1911
+ },
1912
+ promptVariant: {
1913
+ host: "standard",
1914
+ snoGpu: "standard"
1915
+ },
1916
+ replyParser: {
1917
+ host: "json",
1918
+ snoGpu: "json"
1919
+ }
1920
+ },
1921
+ P5: {
1922
+ description: "profile section text",
1923
+ occasion: "profileSectionMerge",
1924
+ destinations: profile,
1925
+ snoPreset: chat,
1926
+ transport: {
1927
+ host: "agent-host-seam",
1928
+ snoGpu: "chat-completions"
1929
+ },
1930
+ promptVariant: {
1931
+ host: "standard",
1932
+ snoGpu: "standard"
1933
+ },
1934
+ replyParser: {
1935
+ host: "json",
1936
+ snoGpu: "json"
1937
+ }
1938
+ },
1939
+ P6: {
1940
+ description: "retire by name",
1941
+ occasion: "profileSectionMerge",
1942
+ destinations: profile,
1943
+ snoPreset: chat,
1944
+ transport: {
1945
+ host: "agent-host-seam",
1946
+ snoGpu: "chat-completions"
1947
+ },
1948
+ promptVariant: {
1949
+ host: "standard",
1950
+ snoGpu: "standard"
1951
+ },
1952
+ replyParser: {
1953
+ host: "json",
1954
+ snoGpu: "json"
1955
+ }
1956
+ },
1957
+ T1: {
1958
+ description: "active task classification and match",
1959
+ occasion: "profileActiveTaskClassify",
1960
+ destinations: host,
1961
+ snoPreset: chat,
1962
+ transport: {
1963
+ host: "agent-host-seam",
1964
+ snoGpu: "chat-completions"
1965
+ },
1966
+ promptVariant: {
1967
+ host: "standard",
1968
+ snoGpu: "standard"
1969
+ },
1970
+ replyParser: {
1971
+ host: "json",
1972
+ snoGpu: "json"
1973
+ }
1974
+ },
1975
+ R1: {
1976
+ description: "session reflection",
1977
+ occasion: "summaryBuild",
1978
+ destinations: host,
1979
+ snoPreset: chat,
1980
+ transport: {
1981
+ host: "agent-host-seam",
1982
+ snoGpu: "chat-completions"
1983
+ },
1984
+ promptVariant: {
1985
+ host: "standard",
1986
+ snoGpu: "standard"
1987
+ },
1988
+ replyParser: {
1989
+ host: "text",
1990
+ snoGpu: "text"
1991
+ }
1992
+ },
1993
+ R2: {
1994
+ description: "label local sessions before the nightly cloud upload",
1995
+ calledBy: "RSI skill",
1996
+ destinations: host
1997
+ },
1998
+ R3: {
1999
+ description: "upload sessions nightly for cloud experience and skill review",
2000
+ calledBy: "RSI skill",
2001
+ destinations: {
2002
+ "local-first": "off",
2003
+ "agent-native": "sno-gpu",
2004
+ "rem-enhanced": "sno-gpu"
2005
+ }
2006
+ },
2007
+ R4: {
2008
+ description: "recall one relevant cloud experience on a session's first prompt",
2009
+ calledBy: "RSI skill",
2010
+ destinations: {
2011
+ "local-first": "off",
2012
+ "agent-native": "sno-gpu",
2013
+ "rem-enhanced": "sno-gpu"
2014
+ }
2015
+ },
2016
+ REM1: {
2017
+ description: "replace conflict pair",
2018
+ occasion: "conflictAdjudication",
2019
+ destinations: rem,
2020
+ snoPreset: verdict,
2021
+ transport: {
2022
+ host: "agent-host-seam",
2023
+ snoGpu: "raw-completions"
2024
+ },
2025
+ promptVariant: {
2026
+ host: "adapter-a-chat",
2027
+ snoGpu: "adapter-a-raw"
2028
+ },
2029
+ replyParser: {
2030
+ host: "json-or-single-token-verdict",
2031
+ snoGpu: "single-token-verdict"
2032
+ }
2033
+ },
2034
+ REM2: {
2035
+ description: "replace clauses",
2036
+ occasion: "memoryExtract",
2037
+ destinations: remHost,
2038
+ snoPreset: chat,
2039
+ transport: {
2040
+ host: "agent-host-seam",
2041
+ snoGpu: "chat-completions"
2042
+ },
2043
+ promptVariant: {
2044
+ host: "standard",
2045
+ snoGpu: "standard"
2046
+ },
2047
+ replyParser: {
2048
+ host: "json",
2049
+ snoGpu: "json"
2050
+ }
2051
+ },
2052
+ REM3: {
2053
+ description: "replace coverage",
2054
+ occasion: "memoryExtract",
2055
+ destinations: rem,
2056
+ snoPreset: chat,
2057
+ transport: {
2058
+ host: "agent-host-seam",
2059
+ snoGpu: "chat-completions"
2060
+ },
2061
+ promptVariant: {
2062
+ host: "standard",
2063
+ snoGpu: "standard"
2064
+ },
2065
+ replyParser: {
2066
+ host: "json",
2067
+ snoGpu: "json"
2068
+ }
2069
+ },
2070
+ REM4: {
2071
+ description: "replace clause carry",
2072
+ occasion: "memoryExtract",
2073
+ destinations: rem,
2074
+ snoPreset: chat,
2075
+ transport: {
2076
+ host: "agent-host-seam",
2077
+ snoGpu: "chat-completions"
2078
+ },
2079
+ promptVariant: {
2080
+ host: "standard",
2081
+ snoGpu: "standard"
2082
+ },
2083
+ replyParser: {
2084
+ host: "json",
2085
+ snoGpu: "json"
2086
+ }
2087
+ },
2088
+ REM5: {
2089
+ description: "update judgment",
2090
+ occasion: "memoryExtract",
2091
+ destinations: rem,
2092
+ snoPreset: chat,
2093
+ transport: {
2094
+ host: "agent-host-seam",
2095
+ snoGpu: "chat-completions"
2096
+ },
2097
+ promptVariant: {
2098
+ host: "standard",
2099
+ snoGpu: "standard"
2100
+ },
2101
+ replyParser: {
2102
+ host: "json",
2103
+ snoGpu: "json"
2104
+ }
2105
+ },
2106
+ REM6: {
2107
+ description: "update verification",
2108
+ occasion: "memoryExtract",
2109
+ destinations: remHost,
2110
+ snoPreset: chat,
2111
+ transport: {
2112
+ host: "agent-host-seam",
2113
+ snoGpu: "chat-completions"
2114
+ },
2115
+ promptVariant: {
2116
+ host: "standard",
2117
+ snoGpu: "standard"
2118
+ },
2119
+ replyParser: {
2120
+ host: "json",
2121
+ snoGpu: "json"
2122
+ }
2123
+ },
2124
+ REM7: {
2125
+ description: "update relation",
2126
+ occasion: "memoryExtract",
2127
+ destinations: remHost,
2128
+ snoPreset: chat,
2129
+ transport: {
2130
+ host: "agent-host-seam",
2131
+ snoGpu: "chat-completions"
2132
+ },
2133
+ promptVariant: {
2134
+ host: "standard",
2135
+ snoGpu: "standard"
2136
+ },
2137
+ replyParser: {
2138
+ host: "json",
2139
+ snoGpu: "json"
2140
+ }
2141
+ },
2142
+ REM8: {
2143
+ description: "update retirement target",
2144
+ occasion: "memoryExtract",
2145
+ destinations: remHost,
2146
+ snoPreset: chat,
2147
+ transport: {
2148
+ host: "agent-host-seam",
2149
+ snoGpu: "chat-completions"
2150
+ },
2151
+ promptVariant: {
2152
+ host: "standard",
2153
+ snoGpu: "standard"
2154
+ },
2155
+ replyParser: {
2156
+ host: "json",
2157
+ snoGpu: "json"
2158
+ }
2159
+ }
2160
+ };
2161
+ function modelCallDestination(callId, mode, modelCalls) {
2162
+ return modelCalls[callId][mode];
2163
+ }
2164
+ //#endregion
2165
+ //#region config/settings.ts
2166
+ const destination = z.enum([
2167
+ "off",
2168
+ "host",
2169
+ "sno-gpu"
2170
+ ]);
2171
+ const destinations = z.strictObject({
2172
+ "local-first": destination,
2173
+ "agent-native": destination,
2174
+ "rem-enhanced": destination
2175
+ });
2176
+ const modelCalls = z.strictObject(Object.fromEntries(Object.keys(MODEL_CALLS).map((id) => [id, destinations])));
2177
+ const settingsSchema = z.strictObject({
2178
+ mode: z.enum(PRODUCT_MODES),
2179
+ modelCalls,
2180
+ user: z.strictObject({
2181
+ id: z.string().refine((id) => id === "" || isLowercaseCanonicalUUIDv7(id)),
2182
+ language: z.enum(SUPPORTED_LOCALES)
2183
+ }),
2184
+ snoGpu: z.strictObject({
2185
+ baseUrl: z.string(),
2186
+ apiKey: z.string()
2187
+ }),
2188
+ rerank: z.strictObject({
2189
+ mode: z.enum([
2190
+ "lightweight",
2191
+ "cross-encoder",
2192
+ "none"
2193
+ ]),
2194
+ provider: z.enum([
2195
+ "jina",
2196
+ "siliconflow",
2197
+ "pinecone",
2198
+ "voyage",
2199
+ "dashscope",
2200
+ "tei",
2201
+ "custom"
2202
+ ]),
2203
+ endpoint: z.string(),
2204
+ model: z.string(),
2205
+ apiKey: z.string(),
2206
+ timeoutMs: z.number().int().min(1e3).max(12e4),
2207
+ maxCandidates: z.number().int().min(1).max(2e3)
2208
+ }),
2209
+ store: z.strictObject({
2210
+ path: z.string(),
2211
+ encryptionKey: z.string().min(1).regex(/^[0-9a-f]{64}$/u)
2212
+ }),
2213
+ embedding: z.strictObject({
2214
+ model: z.string(),
2215
+ revision: z.string(),
2216
+ dtype: z.enum([
2217
+ "q4",
2218
+ "q8",
2219
+ "fp16",
2220
+ "fp32"
2221
+ ]),
2222
+ threads: z.number().int().nonnegative(),
2223
+ cacheDir: z.string(),
2224
+ offline: z.boolean(),
2225
+ mirror: z.string()
2226
+ }),
2227
+ recall: z.strictObject({
2228
+ auto: z.boolean(),
2229
+ sessionStart: z.strictObject({
2230
+ limit: z.number().int().nonnegative(),
2231
+ maxChars: z.number().int().nonnegative(),
2232
+ timeoutMs: z.number().int().nonnegative()
2233
+ }),
2234
+ prompt: z.strictObject({
2235
+ limit: z.number().int().min(0).max(2e3),
2236
+ maxChars: z.number().int().nonnegative(),
2237
+ timeoutMs: z.number().int().min(500).max(6e4),
2238
+ minChars: z.number().int().min(0).max(200),
2239
+ minScore: z.number().min(0).max(1)
2240
+ }),
2241
+ explicitLimit: z.number().int().nonnegative()
2242
+ }),
2243
+ capture: z.strictObject({
2244
+ assistant: z.boolean(),
2245
+ ambient: z.boolean(),
2246
+ sessionMemory: z.strictObject({
2247
+ enabled: z.boolean(),
2248
+ messageCount: z.number().int().min(1).max(100)
2249
+ }),
2250
+ sessionStrategy: z.enum(SESSION_STRATEGIES)
2251
+ }),
2252
+ rem: z.strictObject({
2253
+ tick: z.boolean(),
2254
+ operations: z.array(z.enum(["rem-replace", "rem-update"])).min(1).max(2)
2255
+ }),
2256
+ telemetry: z.strictObject({
2257
+ memoryUsage: z.strictObject({
2258
+ enabled: z.boolean(),
2259
+ key: z.string(),
2260
+ historicKeys: z.array(z.string())
2261
+ }),
2262
+ observe: z.strictObject({
2263
+ enabled: z.boolean(),
2264
+ baseUrl: z.string()
2265
+ }),
2266
+ redactionRules: z.array(z.string())
2267
+ }),
2268
+ logging: z.strictObject({
2269
+ level: z.enum([
2270
+ "debug",
2271
+ "info",
2272
+ "warn",
2273
+ "error"
2274
+ ]),
2275
+ file: z.string(),
2276
+ debugContent: z.boolean()
2277
+ }),
2278
+ memoryPackage: z.strictObject({
2279
+ path: z.string(),
2280
+ node: z.string()
2281
+ })
2282
+ });
2283
+ function defaultSettings() {
2284
+ const engine = pluginConfigSchema.parse({});
2285
+ return {
2286
+ mode: engine.mode,
2287
+ modelCalls: Object.fromEntries(Object.entries(MODEL_CALLS).map(([id, call]) => [id, call.destinations])),
2288
+ user: {
2289
+ id: "",
2290
+ language: "en"
2291
+ },
2292
+ snoGpu: {
2293
+ baseUrl: "https://rt3-llm.sno.ai",
2294
+ apiKey: ""
2295
+ },
2296
+ rerank: {
2297
+ mode: "lightweight",
2298
+ provider: "voyage",
2299
+ endpoint: "",
2300
+ model: engine.retrieval.rerankModel,
2301
+ apiKey: "",
2302
+ timeoutMs: engine.retrieval.rerankTimeoutMs,
2303
+ maxCandidates: 64
2304
+ },
2305
+ store: {
2306
+ path: "",
2307
+ encryptionKey: ""
2308
+ },
2309
+ embedding: {
2310
+ model: EMBEDDER_MODEL_DEFAULT,
2311
+ revision: LOCAL_EMBEDDING_MODEL_REVISION,
2312
+ dtype: engine.embedding.dtype,
2313
+ threads: 0,
2314
+ cacheDir: "",
2315
+ offline: false,
2316
+ mirror: ""
2317
+ },
2318
+ recall: {
2319
+ auto: true,
2320
+ sessionStart: {
2321
+ limit: 5,
2322
+ maxChars: 3500,
2323
+ timeoutMs: 8e3
2324
+ },
2325
+ prompt: {
2326
+ limit: 3,
2327
+ maxChars: 1500,
2328
+ timeoutMs: 4e3,
2329
+ minChars: 12,
2330
+ minScore: 0
2331
+ },
2332
+ explicitLimit: 5
2333
+ },
2334
+ capture: {
2335
+ assistant: true,
2336
+ ambient: true,
2337
+ sessionMemory: {
2338
+ enabled: true,
2339
+ messageCount: 15
2340
+ },
2341
+ sessionStrategy: "systemSessionMemory"
2342
+ },
2343
+ rem: {
2344
+ tick: engine.remEnhanced?.trigger.tick ?? true,
2345
+ operations: engine.remOperations
2346
+ },
2347
+ telemetry: {
2348
+ memoryUsage: {
2349
+ enabled: false,
2350
+ key: "",
2351
+ historicKeys: []
2352
+ },
2353
+ observe: {
2354
+ enabled: true,
2355
+ baseUrl: "https://www.sno.ai"
2356
+ },
2357
+ redactionRules: []
2358
+ },
2359
+ logging: {
2360
+ level: "info",
2361
+ file: "",
2362
+ debugContent: false
2363
+ },
2364
+ memoryPackage: {
2365
+ path: "",
2366
+ node: ""
2367
+ }
2368
+ };
2369
+ }
2370
+ function settingsToPluginConfig(settings) {
2371
+ return pluginConfigSchema.parse({
2372
+ mode: settings.mode,
2373
+ modelCalls: settings.modelCalls,
2374
+ provider: { userId: settings.user.id || void 0 },
2375
+ language: settings.user.language,
2376
+ dbPath: settings.store.path,
2377
+ embedding: {
2378
+ model: settings.embedding.model,
2379
+ revision: settings.embedding.revision || void 0,
2380
+ dtype: settings.embedding.dtype,
2381
+ cacheDir: settings.embedding.cacheDir || void 0,
2382
+ offline: settings.embedding.offline,
2383
+ mirror: settings.embedding.mirror,
2384
+ sessionOptions: { intraOpNumThreads: settings.embedding.threads || void 0 }
2385
+ },
2386
+ retrieval: {
2387
+ rerank: settings.rerank.mode,
2388
+ rerankProvider: settings.rerank.provider,
2389
+ recallTopK: settings.recall.prompt.limit,
2390
+ minScore: settings.recall.prompt.minScore,
2391
+ rerankEndpoint: settings.rerank.endpoint || void 0,
2392
+ rerankModel: settings.rerank.model,
2393
+ rerankApiKey: settings.rerank.apiKey,
2394
+ rerankTimeoutMs: settings.rerank.timeoutMs,
2395
+ rerankMaxCandidates: settings.rerank.maxCandidates
2396
+ },
2397
+ autoRecall: settings.recall.auto,
2398
+ autoRecallTimeoutMs: settings.recall.prompt.timeoutMs,
2399
+ autoRecallMinLength: settings.recall.prompt.minChars,
2400
+ captureAssistant: settings.capture.assistant,
2401
+ ambientLearning: settings.capture.ambient,
2402
+ debugContent: settings.logging.debugContent,
2403
+ sessionMemory: settings.capture.sessionMemory,
2404
+ sessionStrategy: settings.capture.sessionStrategy,
2405
+ remEnhanced: { trigger: { tick: settings.rem.tick } },
2406
+ remOperations: settings.rem.operations,
2407
+ memoryTelemetry: {
2408
+ enabled: settings.telemetry.memoryUsage.enabled,
2409
+ currentKeyVersion: settings.telemetry.memoryUsage.historicKeys.length + 1,
2410
+ key: settings.telemetry.memoryUsage.key,
2411
+ historicKeys: settings.telemetry.memoryUsage.historicKeys
2412
+ },
2413
+ observe: settings.telemetry.observe,
2414
+ extraction: { llm: {
2415
+ baseURL: settings.snoGpu.baseUrl,
2416
+ apiKey: settings.snoGpu.apiKey
2417
+ } }
2418
+ });
2419
+ }
2420
+ //#endregion
2421
+ //#region src/contract/profile.ts
2422
+ function getStateDir(defaultStateDir) {
2423
+ return path.resolve(process.env.SNO_PROFILE_DIR ?? defaultStateDir ?? path.join(homedir(), ".sno"));
2424
+ }
2425
+ function getSettingsPath() {
2426
+ return path.join(getStateDir(), "settings.json");
2427
+ }
2428
+ var SettingsUnavailableError = class extends Error {};
2429
+ function readSettings() {
2430
+ const settingsPath = getSettingsPath();
2431
+ let raw;
2432
+ try {
2433
+ raw = JSON.parse(readFileSync(settingsPath, "utf8"));
2434
+ } catch (error) {
2435
+ throw new SettingsUnavailableError(`settings unavailable: ${settingsPath}: ${error instanceof Error && "code" in error && error.code === "ENOENT" ? "file" : error instanceof SyntaxError ? `JSON: ${error.message}` : "file"}; see https://github.com/sno-ai/sno-station/blob/main/docs/memory-setup.md`);
2436
+ }
2437
+ const parsed = settingsSchema.safeParse(raw);
2438
+ if (!parsed.success) {
2439
+ const issue = parsed.error.issues[0];
2440
+ throw new SettingsUnavailableError(`settings unavailable: ${settingsPath}: ${issue?.code === "unrecognized_keys" ? [...issue.path, issue.keys[0]].join(".") : issue?.path.join(".") || "settings"}; see https://github.com/sno-ai/sno-station/blob/main/docs/memory-setup.md`);
2441
+ }
2442
+ return parsed.data;
2443
+ }
2444
+ function getSnoStationMemStateDir() {
2445
+ return path.join(getStateDir(), "sno-station-mem");
2446
+ }
2447
+ function getPrincipal() {
2448
+ return userInfo().username;
2449
+ }
2450
+ function getDiscoveryPath() {
2451
+ return path.join(getStateDir(), "station", "sidecar.json");
2452
+ }
2453
+ function getSidecarSocketPath() {
2454
+ return path.join(getStateDir(), "station", "sidecar.sock");
2455
+ }
2456
+ //#endregion
2457
+ //#region src/sidecar/config.ts
2458
+ /** @file config.ts
2459
+ * @purpose Centralizes the standalone REM sidecar's paths, protocol constants, and boot settings.
2460
+ * @boundary Environment and filesystem configuration for CLI discovery and local REM state.
2461
+ */
2462
+ const REM_SIDECAR_HOST = "127.0.0.1";
2463
+ const REM_SIDECAR_ORIGIN = "http://127.0.0.1";
2464
+ const REM_SIDECAR_TOKEN_HEADER = "x-sidecar-token";
2465
+ const REM_CORRELATION_ID_HEADER = "x-rem-correlation-id";
2466
+ const REM_RUN_PATH = "/rem/run";
2467
+ const REM_JOBS_PATH_PREFIX = "/rem/jobs/";
2468
+ const HEALTH_PATH = "/healthz";
2469
+ const REM_SOURCE = "sidecar";
2470
+ const REM_MODEL_OUTPUT_TOKEN_CAP = 4096;
2471
+ const MEMORY_USAGE_FLUSH_INTERVAL_MS = 3e5;
2472
+ const SNO_REM_TEST_HOLD_MS_ENV = "SNO_STATION_MEM_REM_TEST_HOLD_MS";
2473
+ const SNO_REM_TRACE_ENV = "SNO_STATION_MEM_REM_TRACE";
2474
+ const REM_JOB_JOURNAL_NAME = "rem-wave-jobs.jsonl";
2475
+ const REM_TRACE_LOG_NAME = "rem-trace.jsonl";
2476
+ const REM_CHASSIS_JOURNAL_NAME = "rem-chassis-journal.jsonl";
2477
+ function getRemDiscoveryPath() {
2478
+ return getDiscoveryPath();
2479
+ }
2480
+ function getRemJobJournalPath() {
2481
+ return path.join(getSnoStationMemStateDir(), REM_JOB_JOURNAL_NAME);
2482
+ }
2483
+ function getRemChassisJournalPath() {
2484
+ return path.join(getSnoStationMemStateDir(), REM_CHASSIS_JOURNAL_NAME);
2485
+ }
2486
+ function getRemTraceLogPath(stateRoot = getStateDir()) {
2487
+ return path.join(stateRoot, "sno-station-mem", REM_TRACE_LOG_NAME);
2488
+ }
2489
+ function isRemTraceEnabled() {
2490
+ return ![
2491
+ "0",
2492
+ "false",
2493
+ "off"
2494
+ ].includes((process.env[SNO_REM_TRACE_ENV] ?? "1").toLowerCase());
2495
+ }
2496
+ function readRemTestHoldMs() {
2497
+ const raw = process.env[SNO_REM_TEST_HOLD_MS_ENV];
2498
+ if (raw === void 0) return 0;
2499
+ const value = Number(raw);
2500
+ if (!Number.isSafeInteger(value) || value < 0) {
2501
+ reportConfigFailure(/* @__PURE__ */ new Error(`${SNO_REM_TEST_HOLD_MS_ENV} must be a non-negative integer`));
2502
+ return 0;
2503
+ }
2504
+ return value;
2505
+ }
2506
+ const DEFAULT_REM_CONFIGURATION = {
2507
+ profileId: "default",
2508
+ operations: {
2509
+ "rem-replace": true,
2510
+ "rem-update": true,
2511
+ "rem-distill": true,
2512
+ "rem-retire": true
2513
+ },
2514
+ budgets: { maxPairs: 200 },
2515
+ retrieval: {
2516
+ neighborLimit: 10,
2517
+ similarityThreshold: .8
2518
+ },
2519
+ coverage: { accuracyFloor: null },
2520
+ retries: { liveContentionRetries: 1 },
2521
+ facetPolicy: {
2522
+ aggregationGrammar: "current-first-v1",
2523
+ historyGrammar: "history-evidence-v1"
2524
+ },
2525
+ calibration: {
2526
+ minimumPublishableScoreEffect: null,
2527
+ minimumTargetCount: null,
2528
+ minimumTargetPercent: null
2529
+ },
2530
+ enableGateDigests: {
2531
+ "p5-production-config": "0".repeat(64),
2532
+ "p6-monthly-non-regression": "0".repeat(64),
2533
+ "p7-detector-gate-verdict": "0".repeat(64),
2534
+ "population-routing": "0".repeat(64),
2535
+ "rem-update": "0".repeat(64),
2536
+ "rem-replace": "0".repeat(64)
2537
+ }
2538
+ };
2539
+ function reportConfigFailure(error) {
2540
+ createLogger("sno-station-mem:config").error("sidecar.config.failed", { error }, {
2541
+ event_name: "sidecar.config.failed",
2542
+ file: "packages/memory/src/sidecar/config.ts",
2543
+ function: "reportConfigFailure",
2544
+ site_id: "sidecar.config.failed"
2545
+ });
2546
+ }
2547
+ function readRemOperationalConfig() {
2548
+ return DEFAULT_REM_CONFIGURATION;
2549
+ }
2550
+ const MAINTENANCE_INTERVAL_ENV = "SNO_STATION_MEM_MAINTENANCE_INTERVAL_MS";
2551
+ const REM_CLOCK_OVERRIDE_ENV = "SNO_STATION_MEM_REM_CLOCK_OVERRIDE";
2552
+ const REM_VOLUME_THRESHOLD_ENV = "SNO_STATION_MEM_REM_VOLUME_THRESHOLD";
2553
+ function readMaintenanceOverrides() {
2554
+ const positive = (name) => {
2555
+ const raw = process.env[name];
2556
+ if (raw === void 0) return void 0;
2557
+ const value = Number(raw);
2558
+ if (!Number.isSafeInteger(value) || value < 1) {
2559
+ reportConfigFailure(/* @__PURE__ */ new Error(`${name} must be a positive integer`));
2560
+ return;
2561
+ }
2562
+ return value;
2563
+ };
2564
+ const rawClock = process.env[REM_CLOCK_OVERRIDE_ENV];
2565
+ const now = rawClock === void 0 ? void 0 : new Date(rawClock);
2566
+ if (now && Number.isNaN(now.getTime())) {
2567
+ reportConfigFailure(/* @__PURE__ */ new Error(`${REM_CLOCK_OVERRIDE_ENV} must be an ISO timestamp`));
2568
+ return {};
2569
+ }
2570
+ return {
2571
+ intervalMs: positive(MAINTENANCE_INTERVAL_ENV),
2572
+ now,
2573
+ volumeThreshold: positive(REM_VOLUME_THRESHOLD_ENV)
2574
+ };
2575
+ }
2576
+ //#endregion
2577
+ export { FIXED_IDX_MEMORY_ACTIVE_TASK_CURRENT_REVISION as $, MAX_CANDIDATE_POOL_SIZE as $n, FIXED_PROTOCOL_VALUE_79 as $t, modelCallDestination as A, DEFAULT_REFLECTION_ERROR_SCAN_MAX_CHARS as An, FIXED_MEMORY_PROFILE_RECOVERY_ENTRIES as At, FIXED_EXTERNAL_VALUE_49 as B, FORGET_QUERY_MIN_SCORE as Bn, FIXED_PROTOCOL_VALUE_63 as Bt, getSidecarSocketPath as C, CHUNK_OVERLAP_TOKENS as Cn, CachedEmbeddingProvider as Cr, FIXED_MEMORY_CHUNKS_MEM_FACET_IDX as Ct, defaultSettings as D, DEFAULT_IMPORTANCE as Dn, LocalEmbedProvider as Dr, FIXED_MEMORY_MEMORIES_FACT_ID_INSERT_GUARD as Dt, readSettings as E, DEFAULT_BM25_WEIGHT as En, LOCAL_EMBEDDING_MODEL_REVISION as Er, FIXED_MEMORY_MEMORIES as Et, observeConfigSchema as F, DEFAULT_VECTOR_WEIGHT as Fn, FIXED_MEMORY_SNO_AI_EXTRACT as Ft, FIXED_EXTERNAL_VALUE_55 as G, IMPORTANCE_WEIGHT_BASE as Gn, FIXED_PROTOCOL_VALUE_68 as Gt, FIXED_EXTERNAL_VALUE_52 as H, HEAD_EXTRACT_MIN_CONTENT_TOKENS as Hn, FIXED_PROTOCOL_VALUE_65 as Ht, extractionConfigSchema as I, EMBEDDER_DIM as In, FIXED_MEMORY_SNO_EXTRACT_CHAT as It, FIXED_EXTERNAL_VALUE_58 as J, LIGHTWEIGHT_COSINE_WEIGHT as Jn, FIXED_PROTOCOL_VALUE_74 as Jt, FIXED_EXTERNAL_VALUE_56 as K, INTEGRITY_CHECK_INTERVAL_MS as Kn, FIXED_PROTOCOL_VALUE_69 as Kt, memoryReflectionConfigSchema as L, EMBEDDER_MODEL_DEFAULT as Ln, FIXED_MEMORY_SNO_EXTRACT_PROFILE as Lt, retrievalConfigSchema as M, DEFAULT_RERANK_MODEL as Mn, FIXED_MEMORY_PROVIDER_PROJECT_AGENTS as Mt, isObserveAgentId as N, DEFAULT_RERANK_TIMEOUT_MS as Nn, FIXED_MEMORY_PROVIDER_PROJECT_MAPPINGS as Nt, settingsToPluginConfig as O, DEFAULT_RECALL_LIFECYCLE as On, ensureModelDownloaded as Or, FIXED_MEMORY_MEMORIES_FACT_ID_UPDATE_GUARD as Ot, observeAgentId as P, DEFAULT_SCOPE as Pn, FIXED_MEMORY_ROW_PATH_PATTERN as Pt, FIXED_IDX_MEMORY as Q, MAX_AGGREGATION_RESULT_TOKENS as Qn, FIXED_PROTOCOL_VALUE_78 as Qt, selfImprovementConfigSchema as R, EMBEDDER_PROVIDER_DEFAULT as Rn, FIXED_MEMORY_TASK_LIFECYCLE_COMMANDS as Rt, getSettingsPath as S, CHUNK_MIN_TOKENS as Sn, recallLifecycleSchema as Sr, FIXED_MEMORY_CHUNKS_MEMORY_ID_IDX as St, getStateDir as T, CHUNK_TOKENIZER_MODE as Tn, LOCAL_EMBEDDING_MODEL as Tr, FIXED_MEMORY_EXTRACTION_TIMESTAMPS as Tt, FIXED_EXTERNAL_VALUE_53 as U, HEAD_EXTRACT_OVERLAP_DROP_RATIO as Un, FIXED_PROTOCOL_VALUE_66 as Ut, FIXED_EXTERNAL_VALUE_51 as V, FTS_MERGE_INTERVAL_MS as Vn, FIXED_PROTOCOL_VALUE_64 as Vt, FIXED_EXTERNAL_VALUE_54 as W, HEAD_EXTRACT_TOKEN_BUDGET as Wn, FIXED_PROTOCOL_VALUE_67 as Wt, FIXED_EXTERNAL_VALUE_8 as X, LIGHTWEIGHT_RERANK_PENALTY as Xn, FIXED_PROTOCOL_VALUE_76 as Xt, FIXED_EXTERNAL_VALUE_62 as Y, LIGHTWEIGHT_FUSION_WEIGHT as Yn, FIXED_PROTOCOL_VALUE_75 as Yt, FIXED_EXTERNAL_VALUE_9 as Z, MAINTENANCE_TICK_MS as Zn, FIXED_PROTOCOL_VALUE_77 as Zt, readRemOperationalConfig as _, BACKUP_MIN_FREE_DISK_RATIO as _n, USAGE_EVENT_RETENTION_INTERVAL_MS as _r, FIXED_MEMORY_CHUNKS as _t, REM_MODEL_OUTPUT_TOKEN_CAP as a, PERSISTED_PROVIDER_SYSTEM as an, MMR_LAMBDA as ar, FIXED_IDX_MEMORY_MEMORIES_LANE_PROJECT as at, getDiscoveryPath as b, CHUNKING_VERSION as bn, experimentCandidatePoolOverride as br, FIXED_MEMORY_CHUNKS_AU as bt, REM_SIDECAR_ORIGIN as c, SUPPORTED_LOCALES as cn, PLANNER_STATISTICS_INTERVAL_MS as cr, FIXED_IDX_MEMORY_MEMORIES_PROJECT_FACT_KEY_ACTIVE as ct, getRemChassisJournalPath as d, ADJACENCY_BONUS_PER_PAIR as dn, REM_TRIGGER_CHECK_INTERVAL_MS as dr, FIXED_MEMORY_ACTIVE_TASK_EVIDENCE as dt, FIXED_VEC_MEMORY as en, MAX_CHUNK_FETCH_LIMIT as er, FIXED_IDX_MEMORY_ACTIVE_TASK_EVIDENCE_INSTANCE as et, getRemDiscoveryPath as f, ATOMIC_CAPTURE_OUTPUT_TOKEN_BUDGET as fn, RERANK_BLEND_CROSS as fr, FIXED_MEMORY_ACTIVE_TASK_INSTANCES as ft, readMaintenanceOverrides as g, BACKUP_INTERVAL_MS as gn, TIME_DECAY_FLOOR as gr, FIXED_MEMORY_ACTIVE_TASK_TRANSITIONS as gt, isRemTraceEnabled as h, ATOMIC_EXTRACTION_MAX_INPUT_TOKENS as hn, SNO_OBSERVE_FLUSH_TIMEOUT_MS as hr, FIXED_MEMORY_ACTIVE_TASK_REVISIONS as ht, REM_JOBS_PATH_PREFIX as i, PERSISTED_CONTENT_HASH_V3 as in, MIN_RECALL_TOKEN_BUDGET as ir, FIXED_IDX_MEMORY_MEMORIES_FACT_ID as it, SESSION_STRATEGIES as j, DEFAULT_REFLECTION_SESSION_TTL_MS as jn, FIXED_MEMORY_PROVIDER_AGENT_MAPPINGS as jt, MODEL_CALLS as k, DEFAULT_RECALL_TOKEN_BUDGET as kn, FIXED_MEMORY_MIGRATION_MARKERS as kt, REM_SIDECAR_TOKEN_HEADER as l, isSupportedLocale as ln, RECENCY_WEIGHT as lr, FIXED_IDX_MEMORY_MEMORIES_PROJECT_TIMESTAMP as lt, getRemTraceLogPath as m, ATOMIC_ENRICHMENT_OUTPUT_TOKEN_BUDGET as mn, RETRIEVAL_STORAGE_CHUNK_PROFILE as mr, FIXED_MEMORY_ACTIVE_TASK_MIGRATION_MANIFESTS as mt, MEMORY_USAGE_FLUSH_INTERVAL_MS as n, PERSISTED_CANDIDATE_HASH_V1 as nn, MAX_RECALLED_TODO_TOKENS as nr, FIXED_IDX_MEMORY_MEMORIES_CATEGORY as nt, REM_RUN_PATH as o, embeddingConfigSchema as on, MULTI_HIT_BONUS_CAP as or, FIXED_IDX_MEMORY_MEMORIES_PROJECT as ot, getRemJobJournalPath as p, ATOMIC_CAPTURE_TIMEOUT_MS as pn, RERANK_BLEND_VECTOR as pr, FIXED_MEMORY_ACTIVE_TASK_MIGRATION_EVIDENCE as pt, FIXED_EXTERNAL_VALUE_57 as q, INTRA_MEMORY_COSINE_THRESHOLD as qn, FIXED_PROTOCOL_VALUE_73 as qt, REM_CORRELATION_ID_HEADER as r, PERSISTED_CONTENT_HASH_V1 as rn, MEMORY_SHUTDOWN_TIMEOUT_MS as rr, FIXED_IDX_MEMORY_MEMORIES_CONTENT_HASH as rt, REM_SIDECAR_HOST as s, llmRoutingConfigSchema as sn, MULTI_HIT_BONUS_PER_HIT as sr, FIXED_IDX_MEMORY_MEMORIES_PROJECT_CONTENT_HASH as st, HEALTH_PATH as t, FIXED_VEC_MEMORY_CHUNKS as tn, MAX_LIST_LIMIT as tr, FIXED_IDX_MEMORY_ACTIVE_TASK_INSTANCES_PROJECTION as tt, REM_SOURCE as u, ADJACENCY_BONUS_CAP as un, REFLECTION_SLICE_CACHE_TTL_MS as ur, FIXED_MEMORY as ut, readRemTestHoldMs as v, BONUS_TOTAL_INVARIANT as vn, USAGE_OUTBOX_INTERVAL_MS as vr, FIXED_MEMORY_CHUNKS_AD as vt, getSnoStationMemStateDir as w, CHUNK_TARGET_TOKENS as wn, LOCAL_EMBEDDING_CACHE_DIR_DEFAULT as wr, FIXED_MEMORY_CHUNKS_MEM_IDX as wt, getPrincipal as x, CHUNK_MAX_TOKENS as xn, experimentMmrDisabled as xr, FIXED_MEMORY_CHUNKS_FTS as xt, SettingsUnavailableError as y, CACHE_TTL_MS as yn, VECTOR_DIMENSION_DEFAULT as yr, FIXED_MEMORY_CHUNKS_AI as yt, sessionMemoryConfigSchema as z, EVAL_QA_TRACES_FILENAME as zn, FIXED_MEMORY_UNPLACED_CANDIDATES as zt };