@jack200714/mafw 4.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/.opencode/mafw/.backup-v61/parametric/base-skill-manifest.yaml +2 -0
  2. package/.opencode/mafw/STATUS.md +6 -0
  3. package/.opencode/mafw/ledger.md +20 -0
  4. package/.opencode/mafw/memory/.harmonic_index.json +28 -0
  5. package/.opencode/mafw/memory/.review_queue.json +1 -0
  6. package/.opencode/mafw/memory/tier3/parametric.json +13 -0
  7. package/.opencode/mafw/memory/tier3/test-goal.json +19 -0
  8. package/.opencode/mafw/memory-index.json +6 -0
  9. package/.opencode/mafw/parametric/base-skill-manifest.yaml +2 -0
  10. package/.opencode/mafw/waves.json +4 -0
  11. package/.opencode/opencode.json +3 -0
  12. package/.opencode/plugins/mafw-plugin.ts +8 -0
  13. package/.opencode/skills/banner-design/SKILL.md +196 -0
  14. package/.opencode/skills/banner-design/references/banner-sizes-and-styles.md +118 -0
  15. package/.opencode/skills/brand/SKILL.md +97 -0
  16. package/.opencode/skills/brand/references/approval-checklist.md +169 -0
  17. package/.opencode/skills/brand/references/asset-organization.md +157 -0
  18. package/.opencode/skills/brand/references/brand-guideline-template.md +140 -0
  19. package/.opencode/skills/brand/references/color-palette-management.md +186 -0
  20. package/.opencode/skills/brand/references/consistency-checklist.md +94 -0
  21. package/.opencode/skills/brand/references/logo-usage-rules.md +185 -0
  22. package/.opencode/skills/brand/references/messaging-framework.md +85 -0
  23. package/.opencode/skills/brand/references/typography-specifications.md +214 -0
  24. package/.opencode/skills/brand/references/update.md +118 -0
  25. package/.opencode/skills/brand/references/visual-identity.md +96 -0
  26. package/.opencode/skills/brand/references/voice-framework.md +88 -0
  27. package/.opencode/skills/brand/scripts/extract-colors.cjs +341 -0
  28. package/.opencode/skills/brand/scripts/inject-brand-context.cjs +349 -0
  29. package/.opencode/skills/brand/scripts/sync-brand-to-tokens.cjs +248 -0
  30. package/.opencode/skills/brand/scripts/tests/test_sync_brand_to_tokens.py +52 -0
  31. package/.opencode/skills/brand/scripts/validate-asset.cjs +387 -0
  32. package/.opencode/skills/brand/templates/brand-guidelines-starter.md +275 -0
  33. package/.opencode/skills/design/SKILL.md +313 -0
  34. package/.opencode/skills/design/data/cip/deliverables.csv +51 -0
  35. package/.opencode/skills/design/data/cip/industries.csv +21 -0
  36. package/.opencode/skills/design/data/cip/mockup-contexts.csv +21 -0
  37. package/.opencode/skills/design/data/cip/styles.csv +21 -0
  38. package/.opencode/skills/design/data/icon/styles.csv +16 -0
  39. package/.opencode/skills/design/data/logo/colors.csv +56 -0
  40. package/.opencode/skills/design/data/logo/industries.csv +56 -0
  41. package/.opencode/skills/design/data/logo/styles.csv +56 -0
  42. package/.opencode/skills/design/references/banner-sizes-and-styles.md +118 -0
  43. package/.opencode/skills/design/references/cip-deliverable-guide.md +95 -0
  44. package/.opencode/skills/design/references/cip-design.md +121 -0
  45. package/.opencode/skills/design/references/cip-prompt-engineering.md +84 -0
  46. package/.opencode/skills/design/references/cip-style-guide.md +68 -0
  47. package/.opencode/skills/design/references/design-routing.md +207 -0
  48. package/.opencode/skills/design/references/icon-design.md +122 -0
  49. package/.opencode/skills/design/references/logo-color-psychology.md +101 -0
  50. package/.opencode/skills/design/references/logo-design.md +92 -0
  51. package/.opencode/skills/design/references/logo-prompt-engineering.md +158 -0
  52. package/.opencode/skills/design/references/logo-style-guide.md +109 -0
  53. package/.opencode/skills/design/references/slides-copywriting-formulas.md +84 -0
  54. package/.opencode/skills/design/references/slides-create.md +4 -0
  55. package/.opencode/skills/design/references/slides-html-template.md +295 -0
  56. package/.opencode/skills/design/references/slides-layout-patterns.md +137 -0
  57. package/.opencode/skills/design/references/slides-strategies.md +94 -0
  58. package/.opencode/skills/design/references/slides.md +42 -0
  59. package/.opencode/skills/design/references/social-photos-design.md +329 -0
  60. package/.opencode/skills/design/scripts/cip/core.py +215 -0
  61. package/.opencode/skills/design/scripts/cip/generate.py +484 -0
  62. package/.opencode/skills/design/scripts/cip/render-html.py +424 -0
  63. package/.opencode/skills/design/scripts/cip/search.py +127 -0
  64. package/.opencode/skills/design/scripts/icon/generate.py +487 -0
  65. package/.opencode/skills/design/scripts/logo/core.py +175 -0
  66. package/.opencode/skills/design/scripts/logo/generate.py +362 -0
  67. package/.opencode/skills/design/scripts/logo/search.py +114 -0
  68. package/.opencode/skills/design-system/SKILL.md +244 -0
  69. package/.opencode/skills/design-system/data/slide-backgrounds.csv +11 -0
  70. package/.opencode/skills/design-system/data/slide-charts.csv +26 -0
  71. package/.opencode/skills/design-system/data/slide-color-logic.csv +14 -0
  72. package/.opencode/skills/design-system/data/slide-copy.csv +26 -0
  73. package/.opencode/skills/design-system/data/slide-layout-logic.csv +16 -0
  74. package/.opencode/skills/design-system/data/slide-layouts.csv +26 -0
  75. package/.opencode/skills/design-system/data/slide-strategies.csv +16 -0
  76. package/.opencode/skills/design-system/data/slide-typography.csv +15 -0
  77. package/.opencode/skills/design-system/references/component-specs.md +236 -0
  78. package/.opencode/skills/design-system/references/component-tokens.md +214 -0
  79. package/.opencode/skills/design-system/references/primitive-tokens.md +203 -0
  80. package/.opencode/skills/design-system/references/semantic-tokens.md +215 -0
  81. package/.opencode/skills/design-system/references/states-and-variants.md +241 -0
  82. package/.opencode/skills/design-system/references/tailwind-integration.md +251 -0
  83. package/.opencode/skills/design-system/references/token-architecture.md +224 -0
  84. package/.opencode/skills/design-system/scripts/embed-tokens.cjs +99 -0
  85. package/.opencode/skills/design-system/scripts/fetch-background.py +317 -0
  86. package/.opencode/skills/design-system/scripts/generate-slide.py +770 -0
  87. package/.opencode/skills/design-system/scripts/generate-tokens.cjs +205 -0
  88. package/.opencode/skills/design-system/scripts/html-token-validator.py +327 -0
  89. package/.opencode/skills/design-system/scripts/search-slides.py +218 -0
  90. package/.opencode/skills/design-system/scripts/slide-token-validator.py +35 -0
  91. package/.opencode/skills/design-system/scripts/slide_search_core.py +453 -0
  92. package/.opencode/skills/design-system/scripts/tests/test_validate_tokens.py +48 -0
  93. package/.opencode/skills/design-system/scripts/validate-tokens.cjs +246 -0
  94. package/.opencode/skills/design-system/templates/design-tokens-starter.json +143 -0
  95. package/.opencode/skills/frontend-design/LICENSE.txt +21 -0
  96. package/.opencode/skills/frontend-design/SKILL.md +115 -0
  97. package/.opencode/skills/mafw-automation-interview/SKILL.md +43 -0
  98. package/.opencode/skills/mafw-cli-scanner/SKILL.md +37 -0
  99. package/.opencode/skills/mafw-compression-verifier/SKILL.md +52 -0
  100. package/.opencode/skills/mafw-desktop-inspector/SKILL.md +170 -0
  101. package/.opencode/skills/mafw-execute/SKILL.md +62 -0
  102. package/.opencode/skills/mafw-gateway-restart/SKILL.md +87 -0
  103. package/.opencode/skills/mafw-github-scanner/SKILL.md +38 -0
  104. package/.opencode/skills/mafw-goal/SKILL.md +76 -0
  105. package/.opencode/skills/mafw-interview/SKILL.md +68 -0
  106. package/.opencode/skills/mafw-memory-extractor/SKILL.md +65 -0
  107. package/.opencode/skills/mafw-plan/SKILL.md +58 -0
  108. package/.opencode/skills/mafw-review/SKILL.md +85 -0
  109. package/.opencode/skills/runtime-plugin-authoring/SKILL.md +791 -0
  110. package/.opencode/skills/slides/SKILL.md +40 -0
  111. package/.opencode/skills/slides/references/copywriting-formulas.md +84 -0
  112. package/.opencode/skills/slides/references/create.md +4 -0
  113. package/.opencode/skills/slides/references/html-template.md +295 -0
  114. package/.opencode/skills/slides/references/layout-patterns.md +137 -0
  115. package/.opencode/skills/slides/references/slide-strategies.md +94 -0
  116. package/.opencode/skills/ui-styling/LICENSE.txt +202 -0
  117. package/.opencode/skills/ui-styling/SKILL.md +324 -0
  118. package/.opencode/skills/ui-styling/references/canvas-design-system.md +320 -0
  119. package/.opencode/skills/ui-styling/references/shadcn-accessibility.md +471 -0
  120. package/.opencode/skills/ui-styling/references/shadcn-components.md +424 -0
  121. package/.opencode/skills/ui-styling/references/shadcn-theming.md +373 -0
  122. package/.opencode/skills/ui-styling/references/tailwind-customization.md +483 -0
  123. package/.opencode/skills/ui-styling/references/tailwind-responsive.md +382 -0
  124. package/.opencode/skills/ui-styling/references/tailwind-utilities.md +455 -0
  125. package/.opencode/skills/ui-styling/scripts/requirements.txt +17 -0
  126. package/.opencode/skills/ui-styling/scripts/shadcn_add.py +308 -0
  127. package/.opencode/skills/ui-styling/scripts/tailwind_config_gen.py +473 -0
  128. package/.opencode/skills/ui-styling/scripts/tests/coverage-ui.json +1 -0
  129. package/.opencode/skills/ui-styling/scripts/tests/requirements.txt +3 -0
  130. package/.opencode/skills/ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  131. package/.opencode/skills/ui-styling/scripts/tests/test_tailwind_config_gen.py +394 -0
  132. package/.opencode/skills/ui-ux-pro-max/SKILL.md +388 -0
  133. package/.opencode/skills/ui-ux-pro-max/data/app-interface.csv +31 -0
  134. package/.opencode/skills/ui-ux-pro-max/data/charts.csv +26 -0
  135. package/.opencode/skills/ui-ux-pro-max/data/colors.csv +193 -0
  136. package/.opencode/skills/ui-ux-pro-max/data/google-fonts.csv +1924 -0
  137. package/.opencode/skills/ui-ux-pro-max/data/icons.csv +106 -0
  138. package/.opencode/skills/ui-ux-pro-max/data/landing.csv +35 -0
  139. package/.opencode/skills/ui-ux-pro-max/data/motion.csv +17 -0
  140. package/.opencode/skills/ui-ux-pro-max/data/products.csv +193 -0
  141. package/.opencode/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  142. package/.opencode/skills/ui-ux-pro-max/data/stacks/angular.csv +51 -0
  143. package/.opencode/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  144. package/.opencode/skills/ui-ux-pro-max/data/stacks/avalonia.csv +57 -0
  145. package/.opencode/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  146. package/.opencode/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  147. package/.opencode/skills/ui-ux-pro-max/data/stacks/javafx.csv +76 -0
  148. package/.opencode/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  149. package/.opencode/skills/ui-ux-pro-max/data/stacks/laravel.csv +51 -0
  150. package/.opencode/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  151. package/.opencode/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +71 -0
  152. package/.opencode/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  153. package/.opencode/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  154. package/.opencode/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  155. package/.opencode/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  156. package/.opencode/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  157. package/.opencode/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  158. package/.opencode/skills/ui-ux-pro-max/data/stacks/threejs.csv +54 -0
  159. package/.opencode/skills/ui-ux-pro-max/data/stacks/uno.csv +60 -0
  160. package/.opencode/skills/ui-ux-pro-max/data/stacks/uwp.csv +56 -0
  161. package/.opencode/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  162. package/.opencode/skills/ui-ux-pro-max/data/stacks/winui.csv +60 -0
  163. package/.opencode/skills/ui-ux-pro-max/data/stacks/wpf.csv +57 -0
  164. package/.opencode/skills/ui-ux-pro-max/data/styles.csv +85 -0
  165. package/.opencode/skills/ui-ux-pro-max/data/typography.csv +75 -0
  166. package/.opencode/skills/ui-ux-pro-max/data/ui-reasoning.csv +162 -0
  167. package/.opencode/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  168. package/.opencode/skills/ui-ux-pro-max/scripts/core.py +464 -0
  169. package/.opencode/skills/ui-ux-pro-max/scripts/design_system.py +1479 -0
  170. package/.opencode/skills/ui-ux-pro-max/scripts/search.py +162 -0
  171. package/.opencode/skills/ui-ux-pro-max/scripts/tests/test_core.py +134 -0
  172. package/.opencode/skills/ui-ux-pro-max/scripts/tests/test_design_system_mode.py +159 -0
  173. package/.opencode/skills/ui-ux-pro-max/scripts/validate_data.py +114 -0
  174. package/LICENSE +21 -0
  175. package/README.md +199 -0
  176. package/bin/mafw.js +436 -0
  177. package/dist/hooks/bash-python-guide.d.ts +4 -0
  178. package/dist/hooks/bash-python-guide.d.ts.map +1 -0
  179. package/dist/hooks/bash-python-guide.js +67 -0
  180. package/dist/hooks/bash-python-guide.js.map +1 -0
  181. package/dist/hooks/handoff.d.ts +9 -0
  182. package/dist/hooks/handoff.d.ts.map +1 -0
  183. package/dist/hooks/handoff.js +8 -0
  184. package/dist/hooks/handoff.js.map +1 -0
  185. package/dist/hooks/hook-manager.d.ts +32 -0
  186. package/dist/hooks/hook-manager.d.ts.map +1 -0
  187. package/dist/hooks/hook-manager.js +91 -0
  188. package/dist/hooks/hook-manager.js.map +1 -0
  189. package/dist/hooks/llm-after.d.ts +8 -0
  190. package/dist/hooks/llm-after.d.ts.map +1 -0
  191. package/dist/hooks/llm-after.js +8 -0
  192. package/dist/hooks/llm-after.js.map +1 -0
  193. package/dist/hooks/media-ingest.d.ts +43 -0
  194. package/dist/hooks/media-ingest.d.ts.map +1 -0
  195. package/dist/hooks/media-ingest.js +269 -0
  196. package/dist/hooks/media-ingest.js.map +1 -0
  197. package/dist/hooks/memory-guide.d.ts +3 -0
  198. package/dist/hooks/memory-guide.d.ts.map +1 -0
  199. package/dist/hooks/memory-guide.js +47 -0
  200. package/dist/hooks/memory-guide.js.map +1 -0
  201. package/dist/hooks/observation-capture.d.ts +17 -0
  202. package/dist/hooks/observation-capture.d.ts.map +1 -0
  203. package/dist/hooks/observation-capture.js +20 -0
  204. package/dist/hooks/observation-capture.js.map +1 -0
  205. package/dist/hooks/session-compacting.d.ts +6 -0
  206. package/dist/hooks/session-compacting.d.ts.map +1 -0
  207. package/dist/hooks/session-compacting.js +6 -0
  208. package/dist/hooks/session-compacting.js.map +1 -0
  209. package/dist/hooks/session-ending.d.ts +20 -0
  210. package/dist/hooks/session-ending.d.ts.map +1 -0
  211. package/dist/hooks/session-ending.js +113 -0
  212. package/dist/hooks/session-ending.js.map +1 -0
  213. package/dist/hooks/session-recall.d.ts +2 -0
  214. package/dist/hooks/session-recall.d.ts.map +1 -0
  215. package/dist/hooks/session-recall.js +103 -0
  216. package/dist/hooks/session-recall.js.map +1 -0
  217. package/dist/hooks/session-start.d.ts +9 -0
  218. package/dist/hooks/session-start.d.ts.map +1 -0
  219. package/dist/hooks/session-start.js +42 -0
  220. package/dist/hooks/session-start.js.map +1 -0
  221. package/dist/hooks/tool-before.d.ts +10 -0
  222. package/dist/hooks/tool-before.d.ts.map +1 -0
  223. package/dist/hooks/tool-before.js +6 -0
  224. package/dist/hooks/tool-before.js.map +1 -0
  225. package/dist/hooks/tool-executed.d.ts +19 -0
  226. package/dist/hooks/tool-executed.d.ts.map +1 -0
  227. package/dist/hooks/tool-executed.js +12 -0
  228. package/dist/hooks/tool-executed.js.map +1 -0
  229. package/dist/hooks/user-profile.d.ts +2 -0
  230. package/dist/hooks/user-profile.d.ts.map +1 -0
  231. package/dist/hooks/user-profile.js +30 -0
  232. package/dist/hooks/user-profile.js.map +1 -0
  233. package/dist/hooks/user-prompt.d.ts +9 -0
  234. package/dist/hooks/user-prompt.d.ts.map +1 -0
  235. package/dist/hooks/user-prompt.js +8 -0
  236. package/dist/hooks/user-prompt.js.map +1 -0
  237. package/dist/hooks/voice-guide.d.ts +8 -0
  238. package/dist/hooks/voice-guide.d.ts.map +1 -0
  239. package/dist/hooks/voice-guide.js +101 -0
  240. package/dist/hooks/voice-guide.js.map +1 -0
  241. package/dist/plugin.d.ts +55 -0
  242. package/dist/plugin.d.ts.map +1 -0
  243. package/dist/plugin.js +342 -0
  244. package/dist/plugin.js.map +1 -0
  245. package/dist/tools/add-memory.d.ts +17 -0
  246. package/dist/tools/add-memory.d.ts.map +1 -0
  247. package/dist/tools/add-memory.js +60 -0
  248. package/dist/tools/add-memory.js.map +1 -0
  249. package/dist/tools/media-ask.d.ts +14 -0
  250. package/dist/tools/media-ask.d.ts.map +1 -0
  251. package/dist/tools/media-ask.js +224 -0
  252. package/dist/tools/media-ask.js.map +1 -0
  253. package/dist/tools/media-speak.d.ts +16 -0
  254. package/dist/tools/media-speak.d.ts.map +1 -0
  255. package/dist/tools/media-speak.js +78 -0
  256. package/dist/tools/media-speak.js.map +1 -0
  257. package/dist/tools/media-upload.d.ts +14 -0
  258. package/dist/tools/media-upload.d.ts.map +1 -0
  259. package/dist/tools/media-upload.js +155 -0
  260. package/dist/tools/media-upload.js.map +1 -0
  261. package/dist/tools/python-exec.d.ts +13 -0
  262. package/dist/tools/python-exec.d.ts.map +1 -0
  263. package/dist/tools/python-exec.js +99 -0
  264. package/dist/tools/python-exec.js.map +1 -0
  265. package/dist/tools/python-restart.d.ts +11 -0
  266. package/dist/tools/python-restart.d.ts.map +1 -0
  267. package/dist/tools/python-restart.js +33 -0
  268. package/dist/tools/python-restart.js.map +1 -0
  269. package/dist/utils/circuit-breaker.d.ts +23 -0
  270. package/dist/utils/circuit-breaker.d.ts.map +1 -0
  271. package/dist/utils/circuit-breaker.js +75 -0
  272. package/dist/utils/circuit-breaker.js.map +1 -0
  273. package/dist/utils/config-loader.d.ts +20 -0
  274. package/dist/utils/config-loader.d.ts.map +1 -0
  275. package/dist/utils/config-loader.js +194 -0
  276. package/dist/utils/config-loader.js.map +1 -0
  277. package/dist/utils/fallback.d.ts +7 -0
  278. package/dist/utils/fallback.d.ts.map +1 -0
  279. package/dist/utils/fallback.js +20 -0
  280. package/dist/utils/fallback.js.map +1 -0
  281. package/dist/utils/git.d.ts +24 -0
  282. package/dist/utils/git.d.ts.map +1 -0
  283. package/dist/utils/git.js +71 -0
  284. package/dist/utils/git.js.map +1 -0
  285. package/dist/utils/github.d.ts +37 -0
  286. package/dist/utils/github.d.ts.map +1 -0
  287. package/dist/utils/github.js +53 -0
  288. package/dist/utils/github.js.map +1 -0
  289. package/dist/utils/global-path.d.ts +2 -0
  290. package/dist/utils/global-path.d.ts.map +1 -0
  291. package/dist/utils/global-path.js +32 -0
  292. package/dist/utils/global-path.js.map +1 -0
  293. package/dist/utils/logger.d.ts +6 -0
  294. package/dist/utils/logger.d.ts.map +1 -0
  295. package/dist/utils/logger.js +69 -0
  296. package/dist/utils/logger.js.map +1 -0
  297. package/dist/utils/obs-capture.d.ts +7 -0
  298. package/dist/utils/obs-capture.d.ts.map +1 -0
  299. package/dist/utils/obs-capture.js +49 -0
  300. package/dist/utils/obs-capture.js.map +1 -0
  301. package/dist/utils/retry.d.ts +11 -0
  302. package/dist/utils/retry.d.ts.map +1 -0
  303. package/dist/utils/retry.js +45 -0
  304. package/dist/utils/retry.js.map +1 -0
  305. package/dist/utils/self-wiring.d.ts +13 -0
  306. package/dist/utils/self-wiring.d.ts.map +1 -0
  307. package/dist/utils/self-wiring.js +86 -0
  308. package/dist/utils/self-wiring.js.map +1 -0
  309. package/dist/utils/state.d.ts +106 -0
  310. package/dist/utils/state.d.ts.map +1 -0
  311. package/dist/utils/state.js +166 -0
  312. package/dist/utils/state.js.map +1 -0
  313. package/dist/utils/status.d.ts +47 -0
  314. package/dist/utils/status.d.ts.map +1 -0
  315. package/dist/utils/status.js +147 -0
  316. package/dist/utils/status.js.map +1 -0
  317. package/dist/utils/ttl-map.d.ts +17 -0
  318. package/dist/utils/ttl-map.d.ts.map +1 -0
  319. package/dist/utils/ttl-map.js +67 -0
  320. package/dist/utils/ttl-map.js.map +1 -0
  321. package/gateway/dist/automation-engine.js +729 -0
  322. package/gateway/dist/chat/chat-sessions.js +95 -0
  323. package/gateway/dist/chat/graph-runner.js +76 -0
  324. package/gateway/dist/chat/index.js +7 -0
  325. package/gateway/dist/chat/intent-classifier.js +23 -0
  326. package/gateway/dist/config.js +416 -0
  327. package/gateway/dist/core/auth.js +96 -0
  328. package/gateway/dist/core/budget-guard.js +52 -0
  329. package/gateway/dist/core/compression/bm25-index.js +176 -0
  330. package/gateway/dist/core/compression/compression-pipeline.js +157 -0
  331. package/gateway/dist/core/compression/compression-strategy-selector.js +32 -0
  332. package/gateway/dist/core/compression/compression-verifier.js +79 -0
  333. package/gateway/dist/core/compression/diff-compressor.js +69 -0
  334. package/gateway/dist/core/compression/hybrid-compressor.js +104 -0
  335. package/gateway/dist/core/compression/lesson-compactor.js +114 -0
  336. package/gateway/dist/core/compression/memory-index.js +190 -0
  337. package/gateway/dist/core/compression/observation-classifier.js +41 -0
  338. package/gateway/dist/core/compression/observation-deduplicator.js +43 -0
  339. package/gateway/dist/core/compression/rrf-fusion.js +63 -0
  340. package/gateway/dist/core/compression/session-pruner.js +137 -0
  341. package/gateway/dist/core/compression/token-budget-allocator.js +141 -0
  342. package/gateway/dist/core/compression/vector-index.js +117 -0
  343. package/gateway/dist/core/compression/zero-token-compressor.js +80 -0
  344. package/gateway/dist/core/cost/cognitive-router.js +41 -0
  345. package/gateway/dist/core/cost/cost-estimator.js +63 -0
  346. package/gateway/dist/core/cost/types.js +19 -0
  347. package/gateway/dist/core/engine/degradation.js +159 -0
  348. package/gateway/dist/core/engine/goal-worktree-manager.js +131 -0
  349. package/gateway/dist/core/engine/lesson-manager.js +222 -0
  350. package/gateway/dist/core/engine/optimistic-sync.js +100 -0
  351. package/gateway/dist/core/engine/phase-orchestrator.js +153 -0
  352. package/gateway/dist/core/engine/report-generator.js +131 -0
  353. package/gateway/dist/core/engine/state-lock.js +91 -0
  354. package/gateway/dist/core/engine/task-branch-manager.js +102 -0
  355. package/gateway/dist/core/engine/wave-dependency.js +67 -0
  356. package/gateway/dist/core/engine/wave-executor.js +112 -0
  357. package/gateway/dist/core/goal-budget.js +63 -0
  358. package/gateway/dist/core/graph/entity-extractor.js +53 -0
  359. package/gateway/dist/core/graph/graph-searcher.js +120 -0
  360. package/gateway/dist/core/graph/knowledge-graph-manager.js +138 -0
  361. package/gateway/dist/core/graph/relation-inferencer.js +67 -0
  362. package/gateway/dist/core/graph/types.js +2 -0
  363. package/gateway/dist/core/hooks/handoff.js +7 -0
  364. package/gateway/dist/core/hooks/hook-manager.js +91 -0
  365. package/gateway/dist/core/hooks/llm-after.js +7 -0
  366. package/gateway/dist/core/hooks/observation-capture.js +19 -0
  367. package/gateway/dist/core/hooks/session-compacting.js +5 -0
  368. package/gateway/dist/core/hooks/session-ending.js +123 -0
  369. package/gateway/dist/core/hooks/session-start.js +51 -0
  370. package/gateway/dist/core/hooks/tool-before.js +5 -0
  371. package/gateway/dist/core/hooks/tool-executed.js +11 -0
  372. package/gateway/dist/core/hooks/user-prompt.js +7 -0
  373. package/gateway/dist/core/index.js +119 -0
  374. package/gateway/dist/core/langchain/agent-adapter.js +39 -0
  375. package/gateway/dist/core/langchain/index.js +12 -0
  376. package/gateway/dist/core/langchain/memory.js +35 -0
  377. package/gateway/dist/core/langchain/node-runner.js +115 -0
  378. package/gateway/dist/core/langchain/retriever.js +28 -0
  379. package/gateway/dist/core/langgraph/checkpointer.js +200 -0
  380. package/gateway/dist/core/langgraph/graph.js +57 -0
  381. package/gateway/dist/core/langgraph/index.js +25 -0
  382. package/gateway/dist/core/langgraph/loop-state.js +71 -0
  383. package/gateway/dist/core/langgraph/nodes/archive.node.js +27 -0
  384. package/gateway/dist/core/langgraph/nodes/execute.node.js +5 -0
  385. package/gateway/dist/core/langgraph/nodes/plan.node.js +101 -0
  386. package/gateway/dist/core/langgraph/nodes/review.node.js +89 -0
  387. package/gateway/dist/core/langgraph/nodes/sync.node.js +70 -0
  388. package/gateway/dist/core/langgraph/review-parser.js +35 -0
  389. package/gateway/dist/core/langgraph/signature-detector.js +23 -0
  390. package/gateway/dist/core/manager/goal-snapshot.js +73 -0
  391. package/gateway/dist/core/manager/milestone-push.js +81 -0
  392. package/gateway/dist/core/manager/question-ledger.js +121 -0
  393. package/gateway/dist/core/manager/system-rule-templates.js +76 -0
  394. package/gateway/dist/core/mcp/tools.js +562 -0
  395. package/gateway/dist/core/mcp/validator.js +165 -0
  396. package/gateway/dist/core/mcp-server.js +86 -0
  397. package/gateway/dist/core/memory/abstraction-distiller.js +44 -0
  398. package/gateway/dist/core/memory/cognitive-graph.js +103 -0
  399. package/gateway/dist/core/memory/energy-system.js +69 -0
  400. package/gateway/dist/core/memory/extractor.js +164 -0
  401. package/gateway/dist/core/memory/harmonic-index.js +530 -0
  402. package/gateway/dist/core/memory/harmonic-types.js +6 -0
  403. package/gateway/dist/core/memory/injector.js +111 -0
  404. package/gateway/dist/core/memory/l5-store.js +141 -0
  405. package/gateway/dist/core/memory/matcher.js +66 -0
  406. package/gateway/dist/core/memory/merger.js +95 -0
  407. package/gateway/dist/core/memory/migrate-v6.1.js +133 -0
  408. package/gateway/dist/core/memory/minhash-merger.js +195 -0
  409. package/gateway/dist/core/memory/observation-service.js +87 -0
  410. package/gateway/dist/core/memory/privacy-filter.js +163 -0
  411. package/gateway/dist/core/memory/reranker.js +208 -0
  412. package/gateway/dist/core/memory/review-scheduler.js +100 -0
  413. package/gateway/dist/core/memory/salience-perceptor.js +24 -0
  414. package/gateway/dist/core/memory/store.js +284 -0
  415. package/gateway/dist/core/memory/t1-store.js +183 -0
  416. package/gateway/dist/core/memory/t1-to-t2-compressor.js +119 -0
  417. package/gateway/dist/core/memory/validator.js +66 -0
  418. package/gateway/dist/core/plugin.js +902 -0
  419. package/gateway/dist/core/skills/mafw-execute/entry.js +226 -0
  420. package/gateway/dist/core/skills/mafw-goal/entry.js +203 -0
  421. package/gateway/dist/core/skills/mafw-plan/entry.js +184 -0
  422. package/gateway/dist/core/skills/mafw-review/entry.js +200 -0
  423. package/gateway/dist/core/storage/file-storage.js +120 -0
  424. package/gateway/dist/core/storage/sqlite-storage.js +205 -0
  425. package/gateway/dist/core/storage/types.js +2 -0
  426. package/gateway/dist/core/tools/archive-worktree.js +208 -0
  427. package/gateway/dist/core/tools/remote-cli.js +106 -0
  428. package/gateway/dist/core/tools/run-ask-user.js +79 -0
  429. package/gateway/dist/core/tools/run-execute-wave.js +32 -0
  430. package/gateway/dist/core/tools/run-plan.js +42 -0
  431. package/gateway/dist/core/tools/run-record-feedback.js +55 -0
  432. package/gateway/dist/core/tools/run-review.js +46 -0
  433. package/gateway/dist/core/tools/write-lesson.js +97 -0
  434. package/gateway/dist/core/utils/circuit-breaker.js +74 -0
  435. package/gateway/dist/core/utils/config-loader.js +203 -0
  436. package/gateway/dist/core/utils/fallback.js +19 -0
  437. package/gateway/dist/core/utils/git.js +70 -0
  438. package/gateway/dist/core/utils/github.js +52 -0
  439. package/gateway/dist/core/utils/global-path.js +41 -0
  440. package/gateway/dist/core/utils/logger.js +71 -0
  441. package/gateway/dist/core/utils/retry.js +44 -0
  442. package/gateway/dist/core/utils/state.js +175 -0
  443. package/gateway/dist/core/utils/status.js +156 -0
  444. package/gateway/dist/cost/service.js +17 -0
  445. package/gateway/dist/dashboard/api.js +1156 -0
  446. package/gateway/dist/dashboard/public/assets/index-DOXm39dm.css +1 -0
  447. package/gateway/dist/dashboard/public/index.html +13 -0
  448. package/gateway/dist/dashboard/server.js +140 -0
  449. package/gateway/dist/dashboard/types.js +2 -0
  450. package/gateway/dist/desktop-client.js +124 -0
  451. package/gateway/dist/eval-endpoint.js +219 -0
  452. package/gateway/dist/event-bus.js +7 -0
  453. package/gateway/dist/feedback/anchor-promotion.js +99 -0
  454. package/gateway/dist/feedback/deferred-memory.js +13 -0
  455. package/gateway/dist/feedback/miss-attribution.js +20 -0
  456. package/gateway/dist/graph/anchor-graph-store.js +113 -0
  457. package/gateway/dist/graph/anchor-graph.js +48 -0
  458. package/gateway/dist/health.js +53 -0
  459. package/gateway/dist/heartbeat.js +109 -0
  460. package/gateway/dist/index.js +6377 -0
  461. package/gateway/dist/interceptors/memory-injector.js +79 -0
  462. package/gateway/dist/ledger.js +121 -0
  463. package/gateway/dist/loop-monitor.js +74 -0
  464. package/gateway/dist/mcp/handlers/add-memory.js +113 -0
  465. package/gateway/dist/mcp/handlers/ask-user.js +63 -0
  466. package/gateway/dist/mcp/handlers/commit-heuristic.js +19 -0
  467. package/gateway/dist/mcp/handlers/create-goal.js +83 -0
  468. package/gateway/dist/mcp/handlers/desktop-click.js +18 -0
  469. package/gateway/dist/mcp/handlers/desktop-get-state.js +15 -0
  470. package/gateway/dist/mcp/handlers/desktop-navigate.js +18 -0
  471. package/gateway/dist/mcp/handlers/desktop-screenshot.js +16 -0
  472. package/gateway/dist/mcp/handlers/desktop-scroll.js +19 -0
  473. package/gateway/dist/mcp/handlers/desktop-type.js +19 -0
  474. package/gateway/dist/mcp/handlers/draft-automation-rule.js +45 -0
  475. package/gateway/dist/mcp/handlers/get-automation-history.js +15 -0
  476. package/gateway/dist/mcp/handlers/get-automation-rule.js +26 -0
  477. package/gateway/dist/mcp/handlers/get-axioms.js +14 -0
  478. package/gateway/dist/mcp/handlers/get-deltas.js +77 -0
  479. package/gateway/dist/mcp/handlers/get-memory.js +67 -0
  480. package/gateway/dist/mcp/handlers/get-model-route.js +16 -0
  481. package/gateway/dist/mcp/handlers/get-triage-item.js +17 -0
  482. package/gateway/dist/mcp/handlers/list-automation-rules.js +24 -0
  483. package/gateway/dist/mcp/handlers/list-triage-items.js +14 -0
  484. package/gateway/dist/mcp/handlers/load-state.js +54 -0
  485. package/gateway/dist/mcp/handlers/manager-answer-question.js +67 -0
  486. package/gateway/dist/mcp/handlers/manager-cancel-goal.js +58 -0
  487. package/gateway/dist/mcp/handlers/manager-get-evidence.js +57 -0
  488. package/gateway/dist/mcp/handlers/manager-get-goal-status.js +58 -0
  489. package/gateway/dist/mcp/handlers/manager-list-goals.js +60 -0
  490. package/gateway/dist/mcp/handlers/manager-list-pending-questions.js +67 -0
  491. package/gateway/dist/mcp/handlers/manager-set-goal.js +78 -0
  492. package/gateway/dist/mcp/handlers/merge-memory.js +184 -0
  493. package/gateway/dist/mcp/handlers/pin-memory.js +53 -0
  494. package/gateway/dist/mcp/handlers/propose-triage-decision.js +38 -0
  495. package/gateway/dist/mcp/handlers/record-feedback.js +59 -0
  496. package/gateway/dist/mcp/handlers/resolve-merge.js +92 -0
  497. package/gateway/dist/mcp/handlers/restart-agent.js +22 -0
  498. package/gateway/dist/mcp/handlers/run-automation.js +28 -0
  499. package/gateway/dist/mcp/handlers/search-hybrid.js +181 -0
  500. package/gateway/dist/mcp/handlers/supersede-memory.js +47 -0
  501. package/gateway/dist/mcp/handlers/update-state.js +59 -0
  502. package/gateway/dist/mcp/handlers/validate-rule.js +39 -0
  503. package/gateway/dist/mcp/sse-transport.js +97 -0
  504. package/gateway/dist/mcp/streamable-endpoint.js +98 -0
  505. package/gateway/dist/mcp/tool-registry.js +630 -0
  506. package/gateway/dist/media/media-agent.js +755 -0
  507. package/gateway/dist/media/media-plugin-loader.js +254 -0
  508. package/gateway/dist/media/media-runtime-executor.js +227 -0
  509. package/gateway/dist/media/media-service.js +199 -0
  510. package/gateway/dist/media/pi-adapter.js +159 -0
  511. package/gateway/dist/media/plugin-context.js +14 -0
  512. package/gateway/dist/media/tts-service.js +173 -0
  513. package/gateway/dist/memory/abstraction-matcher.js +28 -0
  514. package/gateway/dist/memory/consolidation-service.js +209 -0
  515. package/gateway/dist/memory/derived-terms.js +50 -0
  516. package/gateway/dist/memory/embedding-provider.js +330 -0
  517. package/gateway/dist/memory/embedding-runtime.js +174 -0
  518. package/gateway/dist/memory/event-log.js +84 -0
  519. package/gateway/dist/memory/gateway-db.js +465 -0
  520. package/gateway/dist/memory/harmonic-file-store.js +338 -0
  521. package/gateway/dist/memory/llamacpp-provider.js +370 -0
  522. package/gateway/dist/memory/okf-index-renderer.js +61 -0
  523. package/gateway/dist/memory/okf-migrator.js +71 -0
  524. package/gateway/dist/memory/okf-parser.js +57 -0
  525. package/gateway/dist/memory/okf-writer.js +107 -0
  526. package/gateway/dist/memory/service.js +81 -0
  527. package/gateway/dist/memory/t1-db.js +139 -0
  528. package/gateway/dist/memory/unmerge-cleanup.js +82 -0
  529. package/gateway/dist/memory/vector-store.js +246 -0
  530. package/gateway/dist/memory/write-queue.js +31 -0
  531. package/gateway/dist/metrics/collector.js +28 -0
  532. package/gateway/dist/mobile/device-store.js +123 -0
  533. package/gateway/dist/mobile/mdns-advertiser.js +55 -0
  534. package/gateway/dist/mobile/media-proxy.js +292 -0
  535. package/gateway/dist/mobile/pairing.js +139 -0
  536. package/gateway/dist/mobile/push-gateway.js +126 -0
  537. package/gateway/dist/mobile/tts-artifact.js +43 -0
  538. package/gateway/dist/opencode-adapter.js +241 -0
  539. package/gateway/dist/orchestration/outcome-recorder.js +218 -0
  540. package/gateway/dist/orchestration/policy.js +57 -0
  541. package/gateway/dist/orchestration/registry.js +47 -0
  542. package/gateway/dist/plugins/hub.js +188 -0
  543. package/gateway/dist/poll.js +110 -0
  544. package/gateway/dist/python/kernel-service.js +762 -0
  545. package/gateway/dist/recall/constraints-migrate.js +108 -0
  546. package/gateway/dist/recall/data-dir-migrate.js +120 -0
  547. package/gateway/dist/recall/gateway-db-migrate.js +134 -0
  548. package/gateway/dist/recall/index-scan.js +437 -0
  549. package/gateway/dist/recall/inject-format.js +222 -0
  550. package/gateway/dist/recall/legacy-t1-archive.js +86 -0
  551. package/gateway/dist/recall/memory-worker.js +128 -0
  552. package/gateway/dist/recall/pipeline-rules.js +76 -0
  553. package/gateway/dist/recall/recall-context.js +297 -0
  554. package/gateway/dist/recall/reflect-cursor.js +50 -0
  555. package/gateway/dist/recall/reflection.js +318 -0
  556. package/gateway/dist/recall/session-worker-pool.js +100 -0
  557. package/gateway/dist/recall/stale-verify.js +72 -0
  558. package/gateway/dist/recall/step-inject.js +173 -0
  559. package/gateway/dist/recall/time-anchor.js +143 -0
  560. package/gateway/dist/recall/ttl-map.js +72 -0
  561. package/gateway/dist/recall/turn-completion.js +44 -0
  562. package/gateway/dist/recall/turn-pipeline.js +150 -0
  563. package/gateway/dist/recovery.js +158 -0
  564. package/gateway/dist/resources/sdk-session.js +202 -0
  565. package/gateway/dist/retrieval/guided-retriever.js +131 -0
  566. package/gateway/dist/retrieval/idf-stats.js +31 -0
  567. package/gateway/dist/routes/embedding-config.js +100 -0
  568. package/gateway/dist/routes/goal-sessions.js +45 -0
  569. package/gateway/dist/routes/manager-rotate.js +55 -0
  570. package/gateway/dist/routes/media-switch.js +78 -0
  571. package/gateway/dist/routes/model-config.js +132 -0
  572. package/gateway/dist/routes/note-board.js +51 -0
  573. package/gateway/dist/routes/permission.js +43 -0
  574. package/gateway/dist/routes/pinned-recall.js +36 -0
  575. package/gateway/dist/routes/plugins.js +77 -0
  576. package/gateway/dist/routes/restart-agent.js +28 -0
  577. package/gateway/dist/routes/runtime-switch.js +80 -0
  578. package/gateway/dist/routes/session-branch.js +63 -0
  579. package/gateway/dist/routes/session-mutations.js +58 -0
  580. package/gateway/dist/routes/session-summarize.js +49 -0
  581. package/gateway/dist/routes/usage-plugins.js +251 -0
  582. package/gateway/dist/runtime/agent-definition.js +2 -0
  583. package/gateway/dist/runtime/auth.js +80 -0
  584. package/gateway/dist/runtime/completion-http.js +97 -0
  585. package/gateway/dist/runtime/contract.js +37 -0
  586. package/gateway/dist/runtime/loader.js +240 -0
  587. package/gateway/dist/runtime/normalize.js +59 -0
  588. package/gateway/dist/runtime/opencode-runtime.js +336 -0
  589. package/gateway/dist/runtime/pi/pi-agent-config.js +294 -0
  590. package/gateway/dist/runtime/pi/pi-approval-bridge.js +44 -0
  591. package/gateway/dist/runtime/pi/pi-approval-extension.js +62 -0
  592. package/gateway/dist/runtime/pi/pi-events.js +122 -0
  593. package/gateway/dist/runtime/pi/pi-messages.js +20 -0
  594. package/gateway/dist/runtime/pi/pi-provider.js +19 -0
  595. package/gateway/dist/runtime/pi/pi-session-storage.js +44 -0
  596. package/gateway/dist/runtime/pi/pi-session.js +328 -0
  597. package/gateway/dist/runtime/plugins/pi-runtime.js +285 -0
  598. package/gateway/dist/runtime/serve-for-runtime.js +22 -0
  599. package/gateway/dist/runtime/serve-sidecar.js +164 -0
  600. package/gateway/dist/runtime/serve-supervisor.js +80 -0
  601. package/gateway/dist/self-update.js +309 -0
  602. package/gateway/dist/skills/manager-agent-config.js +37 -0
  603. package/gateway/dist/skills/manager-identity.js +11 -0
  604. package/gateway/dist/skills/memory-curator-agent.js +55 -0
  605. package/gateway/dist/trajectory/api.js +154 -0
  606. package/gateway/dist/trajectory/backfill-provider.js +41 -0
  607. package/gateway/dist/trajectory/collector.js +337 -0
  608. package/gateway/dist/trajectory/trajectory-store.js +336 -0
  609. package/gateway/dist/trajectory/types.js +17 -0
  610. package/gateway/dist/tray/index.js +131 -0
  611. package/gateway/dist/tray/tray.ps1 +96 -0
  612. package/gateway/dist/types.js +2 -0
  613. package/gateway/dist/usage/builtin-plugins/commandcode.js +71 -0
  614. package/gateway/dist/usage/builtin-plugins/deepseek.js +56 -0
  615. package/gateway/dist/usage/builtin-plugins/gateway.js +127 -0
  616. package/gateway/dist/usage/builtin-plugins/kimi-for-coding.js +93 -0
  617. package/gateway/dist/usage/builtin-plugins/kimi.js +48 -0
  618. package/gateway/dist/usage/builtin-plugins/opencode-go.js +54 -0
  619. package/gateway/dist/usage/builtin-plugins/openrouter.js +48 -0
  620. package/gateway/dist/usage/builtin-plugins/siliconflow-cn.js +49 -0
  621. package/gateway/dist/usage/builtin-plugins/zhipuai-coding-plan.js +44 -0
  622. package/gateway/dist/usage/model-prices.js +39 -0
  623. package/gateway/dist/usage/model-stats.js +21 -0
  624. package/gateway/dist/usage/plugin-context.js +79 -0
  625. package/gateway/dist/usage/plugin-loader.js +280 -0
  626. package/gateway/dist/usage/templates.js +227 -0
  627. package/gateway/dist/usage/types.js +2 -0
  628. package/gateway/dist/usage/usage-poller.js +216 -0
  629. package/gateway/package.json +37 -0
  630. package/package.json +78 -0
  631. package/packages/tui/dist/cli.js +4664 -0
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReflectionPipeline = exports.QUESTIONS_SYSTEM = exports.REFLECT_SYSTEM = exports.ORPHAN_SESSION = void 0;
4
+ exports.parseQuestions = parseQuestions;
5
+ exports.parseInsights = parseInsights;
6
+ exports.unreflectedBySession = unreflectedBySession;
7
+ const harmonic_file_store_1 = require("../memory/harmonic-file-store");
8
+ const minhash_merger_1 = require("../core/memory/minhash-merger");
9
+ const harmonic_types_1 = require("../core/memory/harmonic-types");
10
+ const salience_perceptor_1 = require("../core/memory/salience-perceptor");
11
+ const memory_curator_agent_1 = require("../skills/memory-curator-agent");
12
+ /** Session key for episodic memories with no source_session_id (legacy data). */
13
+ exports.ORPHAN_SESSION = '__orphan__';
14
+ exports.REFLECT_SYSTEM = `You are a reflection system for a coding agent's long-term memory. Review the episodic memories of one conversation and distill durable, reusable insights. Return ONLY valid JSON, no markdown:
15
+ {"insights":[{"category":"failure|correction|insight|preference|convention|tool-quirk","content":"<one sentence>","cue_anchors":["<keyword>"]}]}
16
+ Rules:
17
+ - no redundant insights; each insight must be a durable lesson, preference, failure, convention, or tool quirk
18
+ - every cue_anchors list MUST include the topic entity names (project, module, API, person, feature) so the insight can be found across sessions
19
+ - for category "preference", include a machine-readable anchor like "pref:<dimension>=<value>" (e.g., "pref:output-language=chinese" or "pref:spicy=false")
20
+ - prefer insights that hold across multiple episodes of this conversation
21
+ Division of labor: focus on CROSS-EPISODE high-level patterns — recurring failure root causes, lessons that generalize to future tasks, user behavior patterns. Do NOT re-record single-point facts already present in the episodic memories (the hourly extract pipeline already saved those).
22
+
23
+ ### Cross-Session Entity Linking (CRITICAL):
24
+ - Extract ALL named entities from the episodes: project names, module names, person names, API endpoints, feature names, file paths, commands, error messages, configuration keys
25
+ - For each insight, include entities that would help find this insight in OTHER sessions about the same topic
26
+ - Include entity variants: e.g., both "React" and "react", both "User Auth Module" and "auth module"
27
+ - For technical discussions, include error codes, stack traces, or specific function names as anchors
28
+ - For user preferences, include the dimension AND value: e.g., "pref:ui-language=chinese" AND "chinese" AND "ui-language"
29
+ - Think: "If someone asked about this topic in a different session, what keywords would they search for?"
30
+ ${memory_curator_agent_1.HARD_BOUNDARIES}`;
31
+ exports.QUESTIONS_SYSTEM = `You are a reflection system for a coding agent's long-term memory. Review the episodic memories of one conversation and generate the 2-3 most salient high-level questions about this session — questions whose answers would reveal durable patterns, recurring root causes, or generalizable lessons. Return ONLY valid JSON, no markdown:
32
+ {"questions":["<question>","<question>"]}
33
+ Rules:
34
+ - questions must be answerable from past conversations (not speculation)
35
+ - prefer questions that span multiple episodes
36
+ - questions should be specific enough to retrieve relevant memories (include entity names like project, module, API, feature)
37
+ - for multi-topic sessions, generate questions for each topic separately
38
+ - for user preferences, ask about the preference itself (e.g., "What UI language does the user prefer?") rather than the context where it was mentioned
39
+ ${memory_curator_agent_1.HARD_BOUNDARIES}`;
40
+ function parseQuestions(text) {
41
+ try {
42
+ const parsed = JSON.parse(text.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/, ''));
43
+ const items = parsed?.questions ?? parsed;
44
+ if (!Array.isArray(items))
45
+ return [];
46
+ return items.filter((q) => typeof q === 'string' && q.trim()).slice(0, 3).map(String);
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ }
52
+ const CATEGORY_TO_TYPE = {
53
+ failure: 'semantic',
54
+ correction: 'semantic',
55
+ insight: 'semantic',
56
+ preference: 'semantic',
57
+ convention: 'semantic',
58
+ 'tool-quirk': 'procedural',
59
+ };
60
+ const CATEGORY_ENERGY = {
61
+ failure: 0.9,
62
+ correction: 0.9,
63
+ insight: 0.8,
64
+ preference: 0.85,
65
+ convention: 0.75,
66
+ 'tool-quirk': 0.8,
67
+ };
68
+ function parseInsights(text) {
69
+ try {
70
+ const parsed = JSON.parse(text.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/, ''));
71
+ const items = parsed?.insights ?? parsed;
72
+ if (!Array.isArray(items))
73
+ return [];
74
+ return items
75
+ .filter((i) => i?.content?.trim() &&
76
+ ['failure', 'correction', 'insight', 'preference', 'convention', 'tool-quirk'].includes(i.category))
77
+ .map((i) => ({
78
+ category: i.category,
79
+ content: String(i.content).trim(),
80
+ cue_anchors: Array.isArray(i.cue_anchors) ? i.cue_anchors.slice(0, 8).map(String) : [],
81
+ }));
82
+ }
83
+ catch {
84
+ return [];
85
+ }
86
+ }
87
+ /**
88
+ * Groups index episodic entries by session (source_session_id; legacy entries
89
+ * without one go to the ORPHAN group). Returns only unreflected ids.
90
+ */
91
+ function unreflectedBySession(index, cursor, maxPerSession) {
92
+ const bySession = new Map();
93
+ for (const entry of index.getIndex().entries) {
94
+ if (entry.type !== 'episodic')
95
+ continue;
96
+ const session = entry.source_session_id || exports.ORPHAN_SESSION;
97
+ if (cursor.isReflected(session, entry.id))
98
+ continue;
99
+ let list = bySession.get(session);
100
+ if (!list) {
101
+ list = [];
102
+ bySession.set(session, list);
103
+ }
104
+ if (list.length >= maxPerSession)
105
+ continue;
106
+ list.push({ id: entry.id, text: `${entry.primary_abstraction} ${(entry.cue_anchors ?? []).join(' ')}` });
107
+ }
108
+ return bySession;
109
+ }
110
+ class ReflectionPipeline {
111
+ opts;
112
+ store;
113
+ merger = new minhash_merger_1.MinHashMerger();
114
+ constructor(opts) {
115
+ this.opts = opts;
116
+ this.store = new harmonic_file_store_1.HarmonicUnitFileStore(opts.baseDir, opts.index);
117
+ }
118
+ /**
119
+ * Three-way classification for a new insight against existing memories:
120
+ * - 'duplicate': MinHash > 0.6 → skip (same content)
121
+ * - 'conflict': MinHash 0.4-0.6 + shared cue_anchors → supersede old entry
122
+ * - 'novel': no significant overlap → write normally
123
+ *
124
+ * The conflict band (0.4-0.6) catches "same topic, different value" cases
125
+ * that MinHash dedup misses — e.g., "deploy to us-east-1" vs "deploy to
126
+ * eu-west-1" share structure but differ in the critical detail.
127
+ */
128
+ classifyInsight(content, cueAnchors) {
129
+ const sig = this.merger.generateSignature(content);
130
+ let bestMatch = null;
131
+ for (const entry of this.opts.index.getIndex().entries) {
132
+ if (entry.type !== 'semantic' && entry.type !== 'procedural')
133
+ continue;
134
+ if (entry.superseded_by)
135
+ continue; // skip already-superseded entries
136
+ // Merged blobs concatenate segments with ' | ' — compare per segment
137
+ // so a true duplicate of one segment is not diluted by the rest.
138
+ let sim = 0;
139
+ for (const seg of minhash_merger_1.MinHashMerger.segmentsOf(entry.primary_abstraction)) {
140
+ const other = `${seg} ${(entry.cue_anchors ?? []).join(' ')}`;
141
+ const s = this.merger.similarity(sig, this.merger.generateSignature(other));
142
+ if (s > sim)
143
+ sim = s;
144
+ }
145
+ if (sim > 0.6)
146
+ return { kind: 'duplicate' };
147
+ if (sim > 0.4 && sim > (bestMatch?.sim ?? 0)) {
148
+ bestMatch = { id: entry.id, sim };
149
+ }
150
+ }
151
+ // Conflict requires both MinHash in the 0.4-0.6 band AND at least one shared cue_anchor
152
+ if (bestMatch && bestMatch.sim > 0.4) {
153
+ const targetEntry = this.opts.index.getIndex().entries.find(e => e.id === bestMatch.id);
154
+ const targetAnchors = targetEntry?.cue_anchors ?? [];
155
+ const sharedAnchors = cueAnchors.filter(a => targetAnchors.includes(a));
156
+ if (sharedAnchors.length > 0) {
157
+ return { kind: 'conflict', conflictTarget: bestMatch.id };
158
+ }
159
+ }
160
+ return { kind: 'novel' };
161
+ }
162
+ /**
163
+ * Reflect one session's unreflected episodes. Returns the number of
164
+ * reviewed episodes (0 when nothing pending). Marks ids reflected only
165
+ * after insights were successfully written (failure keeps them pending for
166
+ * the next run).
167
+ */
168
+ async reflectSession(sessionID, episodes) {
169
+ const result = { sessions: 0, reviewed: 0, distilled: 0, deduped: 0, superseded: 0, failed: 0, pendingSessions: 0 };
170
+ if (episodes.length === 0)
171
+ return result;
172
+ result.reviewed = episodes.length;
173
+ const promptLines = [];
174
+ for (let i = 0; i < episodes.length; i++) {
175
+ const ep = episodes[i];
176
+ let text = ep.text;
177
+ try {
178
+ const unit = await this.store.read(ep.id);
179
+ if (unit?.memory_value)
180
+ text = unit.memory_value.slice(0, 2000);
181
+ }
182
+ catch { /* fall back to summary line */ }
183
+ promptLines.push(`${i + 1}. ${text}`);
184
+ }
185
+ const prompt = promptLines.join('\n');
186
+ const worker = this.opts.workerFor(sessionID);
187
+ let insights = [];
188
+ try {
189
+ // Step 1: generate salient questions
190
+ const qText = await worker.prompt(prompt, exports.QUESTIONS_SYSTEM, this.opts.workerModel, 'memory-curator');
191
+ const questions = parseQuestions(qText);
192
+ // Step 2: retrieve evidence per question (bm25, no graph expansion)
193
+ const evidence = [];
194
+ if (questions.length > 0) {
195
+ for (const q of questions) {
196
+ const hits = this.opts.index.searchScored(q, 5, { retriever: 'bm25', graphExpand: false });
197
+ for (const hit of hits) {
198
+ const line = `- [${hit.entry.id}] ${hit.entry.primary_abstraction}`;
199
+ if (!evidence.includes(line))
200
+ evidence.push(line);
201
+ }
202
+ }
203
+ }
204
+ // Step 3: distill insights with evidence context
205
+ const evidenceBlock = evidence.length > 0 ? `\n\n### Related Historical Memories\n${evidence.join('\n')}` : '';
206
+ // Step 3.5: Extract entities from episodes for cross-session linking
207
+ const episodeEntities = new Set();
208
+ for (const ep of episodes) {
209
+ // Extract camelCase/PascalCase identifiers
210
+ const camelPascal = ep.text.match(/\b[A-Z][a-z]+(?:[A-Z][a-z]+)+\b/g);
211
+ if (camelPascal)
212
+ camelPascal.forEach(e => episodeEntities.add(e));
213
+ // Extract ALL_CAPS words
214
+ const allCaps = ep.text.match(/\b[A-Z]{2,}\b/g);
215
+ if (allCaps)
216
+ allCaps.forEach(e => { if (e.length >= 3)
217
+ episodeEntities.add(e); });
218
+ // Extract quoted strings
219
+ const quoted = ep.text.match(/['"]([^'"]+)['"]/g);
220
+ if (quoted)
221
+ quoted.forEach(q => episodeEntities.add(q.slice(1, -1).trim()));
222
+ }
223
+ // Inject entity context into evidence block for cross-session linking
224
+ const entityBlock = episodeEntities.size > 0
225
+ ? `\n\n### Session Entities (for cross-session linking)\n${[...episodeEntities].slice(0, 20).join(', ')}`
226
+ : '';
227
+ const text = await worker.prompt(prompt + evidenceBlock + entityBlock, exports.REFLECT_SYSTEM, this.opts.workerModel, 'memory-curator');
228
+ insights = parseInsights(text);
229
+ }
230
+ catch {
231
+ result.failed++;
232
+ return result; // episodes stay unreflected
233
+ }
234
+ const maxInsights = this.opts.maxInsights ?? 10;
235
+ for (const insight of insights.slice(0, maxInsights)) {
236
+ const classification = this.classifyInsight(insight.content, insight.cue_anchors ?? []);
237
+ if (classification.kind === 'duplicate') {
238
+ result.deduped++;
239
+ continue;
240
+ }
241
+ const now = new Date().toISOString();
242
+ const unit = {
243
+ id: (0, harmonic_types_1.generateHarmonicId)(),
244
+ type: CATEGORY_TO_TYPE[insight.category],
245
+ primary_abstraction: insight.content.slice(0, 200),
246
+ cue_anchors: insight.cue_anchors ?? [],
247
+ memory_value: insight.content,
248
+ energy: CATEGORY_ENERGY[insight.category],
249
+ salience: (0, salience_perceptor_1.calculateSalience)(insight.content),
250
+ abstraction_level: 2,
251
+ created_at: now,
252
+ updated_at: now,
253
+ source_session_id: sessionID === exports.ORPHAN_SESSION ? undefined : sessionID,
254
+ };
255
+ try {
256
+ // If this insight conflicts with an existing memory, supersede the old one
257
+ if (classification.kind === 'conflict' && classification.conflictTarget) {
258
+ this.store.markSuperseded(classification.conflictTarget, unit.id);
259
+ result.superseded++;
260
+ }
261
+ await this.store.write(unit);
262
+ result.distilled++;
263
+ }
264
+ catch {
265
+ result.failed++;
266
+ }
267
+ }
268
+ // Mark the batch reflected once the LLM produced a parseable result —
269
+ // regardless of dedup/partial write failures. The episodes were processed;
270
+ // retrying them would only re-extract the same (deduped) insights. Only a
271
+ // hard LLM failure (no insights at all) keeps them pending.
272
+ if (insights.length > 0) {
273
+ this.opts.cursor.markReflected(sessionID, episodes.map((e) => e.id));
274
+ }
275
+ result.sessions = insights.length > 0 ? 1 : 0;
276
+ return result;
277
+ }
278
+ /**
279
+ * Reflect all sessions with unreflected episodes (daily cron). Each session
280
+ * goes through the exclusive gate so concurrent triggers (restore, manual)
281
+ * can never double-process the same episodes on the same worker.
282
+ */
283
+ async runAll() {
284
+ const total = { sessions: 0, reviewed: 0, distilled: 0, deduped: 0, superseded: 0, failed: 0, pendingSessions: 0 };
285
+ const bySession = unreflectedBySession(this.opts.index, this.opts.cursor, this.opts.maxEpisodicPerSession ?? 100);
286
+ const exclusive = this.opts.exclusive ?? ((_sessionID, fn) => fn());
287
+ for (const [sessionID, episodes] of bySession) {
288
+ const res = await exclusive(sessionID, async () => {
289
+ return this.reflectSession(sessionID, episodes);
290
+ });
291
+ const r = res;
292
+ total.sessions += r.sessions;
293
+ total.reviewed += r.reviewed;
294
+ total.distilled += r.distilled;
295
+ total.deduped += r.deduped;
296
+ total.superseded += r.superseded;
297
+ total.failed += r.failed;
298
+ }
299
+ // Maintenance: drop reflected ids that no longer exist in the index so the
300
+ // bounded per-session list never re-exposes stale episodes.
301
+ this.opts.cursor.prune(new Set(this.opts.index.getIndex().entries.map((e) => e.id)));
302
+ return total;
303
+ }
304
+ /** Reflect a single session (restoreWorkerState / shouldReflect path). */
305
+ async runSession(sessionID) {
306
+ const bySession = unreflectedBySession(this.opts.index, this.opts.cursor, this.opts.maxEpisodicPerSession ?? 100);
307
+ const episodes = bySession.get(sessionID);
308
+ if (!episodes || episodes.length === 0)
309
+ return { sessions: 0, reviewed: 0, distilled: 0, deduped: 0, superseded: 0, failed: 0, pendingSessions: 0 };
310
+ return this.reflectSession(sessionID, episodes);
311
+ }
312
+ /** Number of unreflected episodes for a session (shouldReflect gate). */
313
+ pendingFor(sessionID) {
314
+ const bySession = unreflectedBySession(this.opts.index, this.opts.cursor, this.opts.maxEpisodicPerSession ?? 100);
315
+ return bySession.get(sessionID)?.length ?? 0;
316
+ }
317
+ }
318
+ exports.ReflectionPipeline = ReflectionPipeline;
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionWorkerPool = void 0;
4
+ // Per-session worker pool: every active session gets its own extract and
5
+ // reflect MemoryWorker (background Observer/Reflector pair). Entries are
6
+ // lazily created, TTL-refreshed on access, and disposed on eviction (24h idle
7
+ // or hard-cap overflow). runExclusive serializes pipeline work per
8
+ // (session, kind) so concurrent triggers (cron + restore + manual) can never
9
+ // run the same worker twice at once.
10
+ const ttl_map_1 = require("./ttl-map");
11
+ const memory_worker_1 = require("./memory-worker");
12
+ class SessionWorkerPool {
13
+ opts;
14
+ entries;
15
+ inflight = new Map();
16
+ creationOrder = [];
17
+ constructor(opts) {
18
+ this.opts = opts;
19
+ const ttlMs = opts.ttlMs;
20
+ this.entries = new ttl_map_1.TtlMap(ttlMs, {
21
+ onEvict: (_key, pair) => {
22
+ void pair.extract.dispose();
23
+ void pair.reflect.dispose();
24
+ },
25
+ });
26
+ }
27
+ maxSessions() {
28
+ return this.opts.maxSessions ?? 64;
29
+ }
30
+ /** Get (or lazily create) the worker for a session. Touches the TTL. */
31
+ getWorker(sessionID, kind) {
32
+ this.entries.sweep(); // release idle/expired sessions before serving one
33
+ let pair = this.entries.getAndTouch(sessionID, this.opts.ttlMs);
34
+ if (!pair) {
35
+ // Hard cap: evict the oldest entry that is not mid-flight (never kill a
36
+ // worker whose prompt is in progress — that degrades to fallback/retry).
37
+ while (this.entries.size() >= this.maxSessions()) {
38
+ const idx = this.creationOrder.findIndex((id) => id !== sessionID && !this.isRunning(id, 'extract') && !this.isRunning(id, 'reflect'));
39
+ if (idx === -1)
40
+ break; // everything in flight → accept the overflow
41
+ const oldest = this.creationOrder.splice(idx, 1)[0];
42
+ this.entries.delete(oldest);
43
+ }
44
+ const label = `mem-${sessionID}`;
45
+ pair = {
46
+ extract: new memory_worker_1.MemoryWorker(this.opts.client, {
47
+ directory: this.opts.directory,
48
+ label: `${label}:extract`,
49
+ compactIdleMs: this.opts.compactIdleMs,
50
+ onSessionCreated: this.opts.onSessionCreated
51
+ ? (sid) => this.opts.onSessionCreated(sid, 'extract')
52
+ : undefined,
53
+ }),
54
+ reflect: new memory_worker_1.MemoryWorker(this.opts.client, {
55
+ directory: this.opts.directory,
56
+ label: `${label}:reflect`,
57
+ compactIdleMs: this.opts.compactIdleMs,
58
+ onSessionCreated: this.opts.onSessionCreated
59
+ ? (sid) => this.opts.onSessionCreated(sid, 'reflect')
60
+ : undefined,
61
+ }),
62
+ label,
63
+ };
64
+ this.entries.set(sessionID, pair, this.opts.ttlMs);
65
+ this.creationOrder.push(sessionID);
66
+ }
67
+ return kind === 'extract' ? pair.extract : pair.reflect;
68
+ }
69
+ /**
70
+ * Serialize work per (session, kind): if a run is already in flight for the
71
+ * same key, the new call awaits the existing one instead of starting a
72
+ * second concurrent run (prevents duplicate extraction / cursor races).
73
+ */
74
+ runExclusive(sessionID, kind, fn) {
75
+ const key = `${sessionID}:${kind}`;
76
+ const prev = this.inflight.get(key);
77
+ if (prev)
78
+ return prev;
79
+ const run = fn().finally(() => {
80
+ if (this.inflight.get(key) === run)
81
+ this.inflight.delete(key);
82
+ });
83
+ this.inflight.set(key, run);
84
+ return run;
85
+ }
86
+ isRunning(sessionID, kind) {
87
+ return this.inflight.has(`${sessionID}:${kind}`);
88
+ }
89
+ size() {
90
+ return this.entries.size();
91
+ }
92
+ /** Dispose every worker (gateway stop / restart). */
93
+ disposeAll() {
94
+ this.entries.clear(); // onEvict disposes pairs
95
+ this.inflight.clear();
96
+ this.creationOrder = [];
97
+ return Promise.resolve();
98
+ }
99
+ }
100
+ exports.SessionWorkerPool = SessionWorkerPool;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StaleVerifyPipeline = exports.STALE_VERIFY_SYSTEM = void 0;
4
+ const memory_curator_agent_1 = require("../skills/memory-curator-agent");
5
+ exports.STALE_VERIFY_SYSTEM = `You are the stale-memory reviewer for the harmonic memory system.
6
+ You receive a list of existing long-term memories. Re-verify each one against the CURRENT environment using read/grep/glob/ls (read-only):
7
+ - still true → do nothing.
8
+ - contradicted by the environment → write the corrected version with mafw_add_memory, passing the old memory's id in its supersedes field (or call mafw_supersede_memory on the old id when there is nothing worth replacing it with).
9
+ - not verifiable with read-only tools (preferences, past events, opinions) → skip it.
10
+ Spend at most 3 probes per memory. Probing verifies a memory; it never continues the work the memory describes.
11
+ ${memory_curator_agent_1.HARD_BOUNDARIES}
12
+
13
+ After processing, ALWAYS end your response with exactly one line:
14
+ [STALE-REVIEW: checked=N superseded=M]
15
+ This line MUST be the very last line of your response.`;
16
+ const DAY_MS = 24 * 60 * 60 * 1000;
17
+ class StaleVerifyPipeline {
18
+ opts;
19
+ constructor(opts) {
20
+ this.opts = opts;
21
+ }
22
+ /** High-value, drift-exposed memories: procedural/semantic, live (not
23
+ * superseded), older than minAgeDays, ranked by energy × salience. */
24
+ selectCandidates() {
25
+ const now = this.opts.now ?? Date.now();
26
+ const topK = this.opts.topK ?? 10;
27
+ const minAgeDays = this.opts.minAgeDays ?? 14;
28
+ return this.opts.index
29
+ .getIndex()
30
+ .entries.filter((e) => (e.type === 'procedural' || e.type === 'semantic') && !e.superseded_by)
31
+ .filter((e) => {
32
+ const created = e.created_at ? new Date(e.created_at).getTime() : 0;
33
+ return created > 0 && now - created >= minAgeDays * DAY_MS;
34
+ })
35
+ .sort((a, b) => b.energy * (b.salience ?? 1) - a.energy * (a.salience ?? 1))
36
+ .slice(0, topK);
37
+ }
38
+ async runOnce() {
39
+ const candidates = this.selectCandidates();
40
+ const result = {
41
+ candidates: candidates.length,
42
+ checked: 0,
43
+ superseded: 0,
44
+ failed: false,
45
+ };
46
+ if (candidates.length === 0)
47
+ return result;
48
+ const blocks = [];
49
+ for (const c of candidates) {
50
+ const unit = await this.opts.readMemory(c.id).catch(() => null);
51
+ if (!unit)
52
+ continue;
53
+ blocks.push(`---\nid: ${c.id}\ntype: ${c.type}\ncontent:\n${unit.memory_value}`);
54
+ }
55
+ if (blocks.length === 0)
56
+ return result;
57
+ const prompt = `Re-verify the following ${blocks.length} memories against the current environment:\n\n${blocks.join('\n')}`;
58
+ try {
59
+ const reply = await this.opts.worker.prompt(prompt, exports.STALE_VERIFY_SYSTEM, this.opts.workerModel, 'memory-curator');
60
+ const m = reply.match(/\[STALE-REVIEW:\s*checked=(\d+)\s+superseded=(\d+)\s*\]/);
61
+ if (m) {
62
+ result.checked = parseInt(m[1], 10);
63
+ result.superseded = parseInt(m[2], 10);
64
+ }
65
+ }
66
+ catch {
67
+ result.failed = true;
68
+ }
69
+ return result;
70
+ }
71
+ }
72
+ exports.StaleVerifyPipeline = StaleVerifyPipeline;
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StepInjectState = exports.FINISHED_EXCLUSIONS = void 0;
4
+ exports.defaultStepInjectOptions = defaultStepInjectOptions;
5
+ exports.stepPropsFromPartUpdated = stepPropsFromPartUpdated;
6
+ exports.stepPropsFromMessageUpdated = stepPropsFromMessageUpdated;
7
+ exports.shouldConsiderStep = shouldConsiderStep;
8
+ exports.selectMemories = selectMemories;
9
+ exports.memoryFingerprint = memoryFingerprint;
10
+ // Step-ended memory injection (path 1): on a settled LLM step, search high
11
+ // salience memories and, after the session goes idle, promptAsync them back
12
+ // into the session as a memory block so the agent can act on them.
13
+ //
14
+ // Concurrency model: every method below is synchronous — no await in between
15
+ // state reads/writes, so Node's single thread makes each call atomic. Awaiting
16
+ // happens only in the caller (search, promptAsync) and never while holding
17
+ // state. Mark-before-async (markStepSeen) prevents duplicate evaluation when
18
+ // concurrent step.ended events arrive during an await.
19
+ const ttl_map_1 = require("./ttl-map");
20
+ exports.FINISHED_EXCLUSIONS = ['tool-calls', 'unknown'];
21
+ function defaultStepInjectOptions() {
22
+ return {
23
+ queueCap: 3,
24
+ intervalMs: 15 * 60 * 1000,
25
+ ttlMs: 24 * 60 * 60 * 1000,
26
+ threshold: 0.7,
27
+ maxMemories: 2,
28
+ };
29
+ }
30
+ // opencode ≥1.18 no longer publishes `session.next.step.ended`. Steps settle as
31
+ // `step-finish` parts carried by `message.part.updated`. Messages also emit
32
+ // `message.updated` with `info.role='assistant'` and `info.time.completed` once
33
+ // the final assistant message is settled. These helpers normalize both shapes
34
+ // back into the old StepEndedProps contract.
35
+ function stepPropsFromPartUpdated(props) {
36
+ const part = props?.part;
37
+ if (!part || part.type !== 'step-finish')
38
+ return null;
39
+ return {
40
+ sessionID: part.sessionID,
41
+ assistantMessageID: part.messageID,
42
+ finish: part.reason,
43
+ };
44
+ }
45
+ function stepPropsFromMessageUpdated(props) {
46
+ const info = props?.info;
47
+ if (!info || info.role !== 'assistant' || !info.time?.completed)
48
+ return null;
49
+ return {
50
+ sessionID: info.sessionID,
51
+ assistantMessageID: info.id,
52
+ finish: info.finish,
53
+ };
54
+ }
55
+ function shouldConsiderStep(props) {
56
+ if (!props.sessionID || !props.assistantMessageID)
57
+ return false;
58
+ if (exports.FINISHED_EXCLUSIONS.includes(props.finish || ''))
59
+ return false;
60
+ return true;
61
+ }
62
+ function selectMemories(results, threshold, max) {
63
+ return results
64
+ .filter((r) => r.energy >= threshold)
65
+ .sort((a, b) => b.energy - a.energy)
66
+ .slice(0, max);
67
+ }
68
+ /** Fingerprint of a memory group by sorted IDs — not block text, so dynamic
69
+ * content (timestamps etc.) never defeats dedup. */
70
+ function memoryFingerprint(memIds) {
71
+ return [...memIds].sort().join('|');
72
+ }
73
+ /**
74
+ * All per-session state for step injection. Every method is synchronous; the
75
+ * caller owns all awaiting. Entries expire via TtlMap (idle/ended sessions
76
+ * are released, not leaked).
77
+ */
78
+ class StepInjectState {
79
+ opts;
80
+ queue = new ttl_map_1.TtlMap();
81
+ lastInjectedAt = new ttl_map_1.TtlMap();
82
+ seenSteps = new ttl_map_1.TtlMap();
83
+ seenFingerprints = new ttl_map_1.TtlMap();
84
+ pushedMemories = new ttl_map_1.TtlMap();
85
+ constructor(opts) {
86
+ this.opts = opts;
87
+ }
88
+ /**
89
+ * B1 mark-before-async: returns true only the first time this assistant
90
+ * message ID is evaluated; call it *before* any await so concurrent
91
+ * duplicate step.ended events are dropped.
92
+ */
93
+ markStepSeen(sessionID, assistantMessageID) {
94
+ let set = this.seenSteps.get(sessionID);
95
+ if (!set) {
96
+ set = new Set();
97
+ this.seenSteps.set(sessionID, set);
98
+ }
99
+ if (set.has(assistantMessageID))
100
+ return false;
101
+ set.add(assistantMessageID);
102
+ return true;
103
+ }
104
+ /** True if this memory group was already injected this session (fingerprint dedup). */
105
+ fingerprintSeen(sessionID, fp) {
106
+ const set = this.seenFingerprints.get(sessionID);
107
+ return !!set && set.has(fp);
108
+ }
109
+ rememberFingerprint(sessionID, fp) {
110
+ let set = this.seenFingerprints.get(sessionID);
111
+ if (!set) {
112
+ set = new Set();
113
+ this.seenFingerprints.set(sessionID, set);
114
+ }
115
+ set.add(fp);
116
+ }
117
+ enqueue(sessionID, injection) {
118
+ let list = this.queue.get(sessionID);
119
+ if (!list) {
120
+ list = [];
121
+ this.queue.set(sessionID, list);
122
+ }
123
+ if (list.length >= this.opts.queueCap) {
124
+ list.shift(); // drop oldest, keep the newest high-value group
125
+ }
126
+ list.push(injection);
127
+ }
128
+ /**
129
+ * B2 consumption entry: checks the frequency gate first — if the session
130
+ * injected recently, the whole queue is discarded (single log line) instead
131
+ * of failing each entry.
132
+ */
133
+ consume(sessionID) {
134
+ const list = this.queue.get(sessionID);
135
+ if (!list || list.length === 0)
136
+ return null;
137
+ const last = this.lastInjectedAt.get(sessionID);
138
+ if (last !== undefined && Date.now() - last < this.opts.intervalMs) {
139
+ this.queue.delete(sessionID);
140
+ return null;
141
+ }
142
+ const next = list.shift();
143
+ if (list.length === 0)
144
+ this.queue.delete(sessionID);
145
+ return next ?? null;
146
+ }
147
+ /** B3: register an injected group; the IDs become invisible to /api/recall/context. */
148
+ markInjected(sessionID, memIds, fp) {
149
+ this.lastInjectedAt.set(sessionID, Date.now());
150
+ this.rememberFingerprint(sessionID, fp);
151
+ let set = this.pushedMemories.get(sessionID);
152
+ if (!set) {
153
+ set = new Set();
154
+ this.pushedMemories.set(sessionID, set);
155
+ }
156
+ for (const id of memIds)
157
+ set.add(id);
158
+ }
159
+ /** B3 rollback on promptAsync failure so IDs are never permanently masked. */
160
+ rollbackPushed(sessionID, memIds) {
161
+ const set = this.pushedMemories.get(sessionID);
162
+ if (!set)
163
+ return;
164
+ for (const id of memIds)
165
+ set.delete(id);
166
+ if (set.size === 0)
167
+ this.pushedMemories.delete(sessionID);
168
+ }
169
+ pushedMemoriesFor(sessionID) {
170
+ return this.pushedMemories.get(sessionID) ?? new Set();
171
+ }
172
+ }
173
+ exports.StepInjectState = StepInjectState;