@xopcai/xopc 0.0.119 → 0.0.121

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 (286) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/dashscope/src/image-generation-provider.d.ts +6 -5
  3. package/dist/extensions/dashscope/src/image-generation-provider.js +40 -64
  4. package/dist/extensions/dashscope/src/image-generation-provider.js.map +1 -1
  5. package/dist/extensions/dashscope/src/index.d.ts +1 -1
  6. package/dist/extensions/dashscope/src/index.js +2 -2
  7. package/dist/extensions/dashscope/xopc.extension.json +3 -2
  8. package/dist/extensions/minimax/src/image-generation-provider.d.ts +7 -5
  9. package/dist/extensions/minimax/src/image-generation-provider.js +43 -37
  10. package/dist/extensions/minimax/src/image-generation-provider.js.map +1 -1
  11. package/dist/extensions/minimax/src/index.d.ts +1 -1
  12. package/dist/extensions/minimax/src/index.js +2 -2
  13. package/dist/extensions/minimax/xopc.extension.json +1 -1
  14. package/dist/extensions/telegram/xopc.extension.json +1 -1
  15. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +41 -0
  16. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CU8J6zou.js → agent-avatar-dicebear-4AW4JgSU.js} +1 -1
  17. package/dist/gateway/static/root/assets/agents-2SVUUPlp.js +2 -0
  18. package/dist/gateway/static/root/assets/{app-management-settings-panel-B9vfYoEr.js → app-management-settings-panel-CE6GkGU2.js} +1 -1
  19. package/dist/gateway/static/root/assets/{appearance-settings-ClOzIO24.js → appearance-settings-BmaUjghw.js} +1 -1
  20. package/dist/gateway/static/root/assets/{apps-page-DU0dz9Zo.js → apps-page-BWeQ1I49.js} +1 -1
  21. package/dist/gateway/static/root/assets/{archive-plugin-BkVIgZzA.js → archive-plugin-CX4_KWut.js} +1 -1
  22. package/dist/gateway/static/root/assets/{attachment-load-CaCMWh1D.js → attachment-load-jf-PIIUU.js} +1 -1
  23. package/dist/gateway/static/root/assets/{automation-suggestion-card-DhGDpKP3.js → automation-suggestion-card-BHk5rtJz.js} +1 -1
  24. package/dist/gateway/static/root/assets/automations-page-QHotl53D.js +1 -0
  25. package/dist/gateway/static/root/assets/{binary-plugins-B4TO_bsn.js → binary-plugins-DG9XQikd.js} +1 -1
  26. package/dist/gateway/static/root/assets/{block-editor-DJRWwWNI.js → block-editor-Up_VIxLJ.js} +6 -6
  27. package/dist/gateway/static/root/assets/browser-settings-page-Cmwi6IIQ.js +8 -0
  28. package/dist/gateway/static/root/assets/{capability-presets-api-Befi89CL.js → capability-presets-api-CGM4OyMw.js} +1 -1
  29. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-_G8eb2vJ.js → capability-presets-settings-panel-CzWt0LBb.js} +1 -1
  30. package/dist/gateway/static/root/assets/{channel-recipient-api-BNSuJb5f.js → channel-recipient-api-BEByL4_o.js} +1 -1
  31. package/dist/gateway/static/root/assets/channels-settings-BOMCUe2J.js +1 -0
  32. package/dist/gateway/static/root/assets/connectors-page-C-Dexk_F.js +2 -0
  33. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +1 -0
  34. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +1 -0
  35. package/dist/gateway/static/root/assets/dreaming-settings-WPEj8pir.js +1 -0
  36. package/dist/gateway/static/root/assets/{extension-debug-page-DYh402XV.js → extension-debug-page-DZxa_j7-.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-Cr_TizrN.js → extension-page-CseziW53.js} +1 -1
  38. package/dist/gateway/static/root/assets/extension-settings-page-B_9J-xyo.js +1 -0
  39. package/dist/gateway/static/root/assets/{fetch-Y7AEX4H3.js → fetch-Cs4ck8zA.js} +1 -1
  40. package/dist/gateway/static/root/assets/{gateway-config-api-RbMmAOpX.js → gateway-config-api-Dl223a7r.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-DdzbtW9R.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-DiD_Tx4N.js → gateway-startup-retry-IvePwjFE.js} +1 -1
  43. package/dist/gateway/static/root/assets/goal-detail-page-Dxldogms.js +1 -0
  44. package/dist/gateway/static/root/assets/{goals-config-api-DqxVi0p5.js → goals-config-api-CUCP6yCl.js} +1 -1
  45. package/dist/gateway/static/root/assets/goals-page-DU5Nd6Xp.js +2 -0
  46. package/dist/gateway/static/root/assets/goals-settings-Dj87qPxv.js +1 -0
  47. package/dist/gateway/static/root/assets/heartbeat-settings-Cgm5JmwH.js +1 -0
  48. package/dist/gateway/static/root/assets/index-BU1pvxmS.js +191 -0
  49. package/dist/gateway/static/root/assets/index-l54WfSqe.css +1 -0
  50. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Dvg53qnd.js → keyboard-shortcuts-settings-DJgYw0nB.js} +1 -1
  51. package/dist/gateway/static/root/assets/{locale-store-DjbfSsfA.js → locale-store-Ba72bFmP.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-C10aS4XO.js +2 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-CpHxbtWJ.js → markdown-split-gnQ_EiGo.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-SFPQRSxq.js → media-plugins-CQV-mgJn.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-C6Kc4Jhf.js +3 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-B35CAfg6.js +2 -0
  57. package/dist/gateway/static/root/assets/note-detail-page-Brlwse8x.js +2 -0
  58. package/dist/gateway/static/root/assets/{note-image-lightbox-BUYURRgn.js → note-image-lightbox-BthwKjLA.js} +1 -1
  59. package/dist/gateway/static/root/assets/{notes-page-BsIBSFyZ.js → notes-page-CoAwRc7L.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-BHz9iWYA.js → preview-open-alternatives-BPMXC-2u.js} +1 -1
  61. package/dist/gateway/static/root/assets/remote-access-hub-B36RQ05h.js +1 -0
  62. package/dist/gateway/static/root/assets/{save-bar-controls-CefkOlRg.js → save-bar-controls-BEHqwZjz.js} +1 -1
  63. package/dist/gateway/static/root/assets/schedule-field-CMY25m97.js +1 -0
  64. package/dist/gateway/static/root/assets/schema-form-CxjxsFfg.js +1 -0
  65. package/dist/gateway/static/root/assets/sessions-page-73THChnj.js +1 -0
  66. package/dist/gateway/static/root/assets/settings-advanced-gate-CR9VsY-R.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-collapsible-section-BouO6JTi.js → settings-collapsible-section-s-kiLAxP.js} +1 -1
  68. package/dist/gateway/static/root/assets/settings-form-section-CIxIEYxU.js +1 -0
  69. package/dist/gateway/static/root/assets/settings-page-BJ1AhfKI.js +1 -0
  70. package/dist/gateway/static/root/assets/{settings-page-layout-BJ4Gsef5.js → settings-page-layout--6qT7ZJa.js} +1 -1
  71. package/dist/gateway/static/root/assets/{setup-status-panel-CrUjHPQo.js → setup-status-panel-C1TtS1vJ.js} +1 -1
  72. package/dist/gateway/static/root/assets/{share-preview-page-BDy2btRN.js → share-preview-page-BZADSbS1.js} +1 -1
  73. package/dist/gateway/static/root/assets/shares-settings-gqC8Rmhy.js +1 -0
  74. package/dist/gateway/static/root/assets/skill-reload-api-C9P-WYvS.js +1 -0
  75. package/dist/gateway/static/root/assets/skills-page-CEpSvOhF.js +2 -0
  76. package/dist/gateway/static/root/assets/{system-settings-panel-CRngrlnZ.js → system-settings-panel-Czjf0kLJ.js} +1 -1
  77. package/dist/gateway/static/root/assets/{theme-store-CD2wtgZV.js → theme-store-Bt6vAkSB.js} +1 -1
  78. package/dist/gateway/static/root/assets/{typed-models-lib-BltBc0b-.js → typed-models-lib-Cmt8SYdI.js} +1 -1
  79. package/dist/gateway/static/root/assets/{use-channel-catalog-CjN-51e6.js → use-channel-catalog-DyM-ckEQ.js} +1 -1
  80. package/dist/gateway/static/root/assets/user-profile-settings-panel-BygLv8vm.js +1 -0
  81. package/dist/gateway/static/root/assets/{utils-B5M5-YvK.js → utils-CloW8coB.js} +1 -1
  82. package/dist/gateway/static/root/assets/voice-api-key-field-BsoqJba6.js +1 -0
  83. package/dist/gateway/static/root/assets/{voice-player-store-B7ykUlHM.js → voice-player-store-DduWlJYV.js} +1 -1
  84. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CcQeX6l5.js +3 -0
  85. package/dist/gateway/static/root/assets/workflows-page-CeA8A9Ef.js +18 -0
  86. package/dist/gateway/static/root/index.html +9 -10
  87. package/dist/package.js +1 -1
  88. package/dist/src/agent/context/workspace-templates/AGENTS.md +3 -2
  89. package/dist/src/agent/embedded/xopc-auth-storage.d.ts +1 -5
  90. package/dist/src/agent/embedded/xopc-auth-storage.js +2 -8
  91. package/dist/src/agent/embedded/xopc-auth-storage.js.map +1 -1
  92. package/dist/src/agent/embedded/xopc-tools-bridge.js +23 -0
  93. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  94. package/dist/src/agent/goals/checklist-judge.js +1 -1
  95. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  96. package/dist/src/agent/goals/judge.js +1 -1
  97. package/dist/src/agent/goals/judge.js.map +1 -1
  98. package/dist/src/agent/image/tool-model-config.d.ts +2 -0
  99. package/dist/src/agent/image/tool-model-config.js +2 -2
  100. package/dist/src/agent/image/tool-model-config.js.map +1 -1
  101. package/dist/src/agent/image/understanding/pi-ai-provider.js +1 -1
  102. package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
  103. package/dist/src/agent/memory/builtin-memory-store.d.ts +1 -1
  104. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  105. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  106. package/dist/src/agent/memory/builtin-provider.d.ts +2 -2
  107. package/dist/src/agent/memory/builtin-provider.js +2 -2
  108. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  109. package/dist/src/agent/memory/compaction.d.ts +1 -1
  110. package/dist/src/agent/memory/compaction.js +1 -1
  111. package/dist/src/agent/memory/compaction.js.map +1 -1
  112. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +0 -7
  113. package/dist/src/agent/memory/dreaming/light-sweep.js +16 -277
  114. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  115. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  116. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  117. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  118. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +3 -3
  119. package/dist/src/agent/memory/dreaming/short-term-store.js +5 -5
  120. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  121. package/dist/src/agent/memory/dreaming/utils.d.ts +2 -2
  122. package/dist/src/agent/memory/dreaming/utils.js +2 -2
  123. package/dist/src/agent/memory/dreaming/utils.js.map +1 -1
  124. package/dist/src/agent/memory/index.d.ts +0 -2
  125. package/dist/src/agent/memory/index.js +1 -2
  126. package/dist/src/agent/middleware/self-verify.d.ts +3 -0
  127. package/dist/src/agent/middleware/self-verify.js +18 -0
  128. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  129. package/dist/src/agent/orchestration/agent-event-handler.js +28 -3
  130. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  131. package/dist/src/agent/prompt/sections/memory-skills.js +11 -10
  132. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  133. package/dist/src/agent/prompt/sections/tooling.js +23 -7
  134. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  135. package/dist/src/agent/prompt/service-prompt-builder.js +1 -0
  136. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  137. package/dist/src/agent/prompt/system-prompt.d.ts +1 -0
  138. package/dist/src/agent/prompt/system-prompt.js +13 -1
  139. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  140. package/dist/src/agent/reply/startup-context.js +6 -105
  141. package/dist/src/agent/reply/startup-context.js.map +1 -1
  142. package/dist/src/agent/sandbox/path-policy.js +30 -6
  143. package/dist/src/agent/sandbox/path-policy.js.map +1 -1
  144. package/dist/src/agent/service/btw-query.js +1 -1
  145. package/dist/src/agent/service/btw-query.js.map +1 -1
  146. package/dist/src/agent/service.d.ts +0 -3
  147. package/dist/src/agent/service.js +0 -41
  148. package/dist/src/agent/service.js.map +1 -1
  149. package/dist/src/agent/starter-agents.js +16 -16
  150. package/dist/src/agent/starter-agents.js.map +1 -1
  151. package/dist/src/agent/tools/image-generate-tool.js +12 -1
  152. package/dist/src/agent/tools/image-generate-tool.js.map +1 -1
  153. package/dist/src/agent/tools/memory-tool.js +2 -2
  154. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  155. package/dist/src/agent/tools/session-search-tool.js +1 -1
  156. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  157. package/dist/src/agent/tools/web-extract.js +1 -1
  158. package/dist/src/agent/tools/web-extract.js.map +1 -1
  159. package/dist/src/agent-manifest/index.js +2 -2
  160. package/dist/src/agent-manifest/schema.d.ts +66 -0
  161. package/dist/src/agent-manifest/schema.js +28 -2
  162. package/dist/src/agent-manifest/schema.js.map +1 -1
  163. package/dist/src/automations/draft/automation-draft-service.js +1 -1
  164. package/dist/src/automations/draft/automation-draft-service.js.map +1 -1
  165. package/dist/src/cli/commands/agent.js +2 -2
  166. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  167. package/dist/src/cli/commands/init.js +1 -1
  168. package/dist/src/cli/commands/init.js.map +1 -1
  169. package/dist/src/cli/commands/models.js +1 -1
  170. package/dist/src/cli/commands/onboard/model.js +161 -11
  171. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  172. package/dist/src/cli/commands/onboard.js +1 -1
  173. package/dist/src/cli/commands/profile.js +1 -1
  174. package/dist/src/cli/commands/tunnel.js +1 -1
  175. package/dist/src/cli/commands/update.js +1 -1
  176. package/dist/src/cli/extension-cli-register.js +1 -1
  177. package/dist/src/cli/templates.js +3 -2
  178. package/dist/src/cli/templates.js.map +1 -1
  179. package/dist/src/config/agent-profile.js +1 -1
  180. package/dist/src/config/default-model.d.ts +11 -0
  181. package/dist/src/config/default-model.js +19 -0
  182. package/dist/src/config/default-model.js.map +1 -0
  183. package/dist/src/config/index.js +3 -3
  184. package/dist/src/config/schema.d.ts +73 -13
  185. package/dist/src/config/schema.js +59 -24
  186. package/dist/src/config/schema.js.map +1 -1
  187. package/dist/src/connectors/registries/smithery.js +10 -9
  188. package/dist/src/connectors/registries/smithery.js.map +1 -1
  189. package/dist/src/daemon/install-plan.js +2 -1
  190. package/dist/src/daemon/install-plan.js.map +1 -1
  191. package/dist/src/gateway/agents-admin.js +1 -1
  192. package/dist/src/gateway/global-defaults-admin.js +6 -16
  193. package/dist/src/gateway/global-defaults-admin.js.map +1 -1
  194. package/dist/src/gateway/hono/lib/config-payload.d.ts +24 -0
  195. package/dist/src/gateway/hono/routes/agents.js +1 -79
  196. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  197. package/dist/src/gateway/hono/routes/config-patch/misc.js +4 -1
  198. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  199. package/dist/src/gateway/hono/routes/models.js +132 -14
  200. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  201. package/dist/src/gateway/hono/routes/voice.js +1 -1
  202. package/dist/src/gateway/hono/routes/voice.js.map +1 -1
  203. package/dist/src/gateway/image-capabilities.d.ts +11 -1
  204. package/dist/src/gateway/image-capabilities.js +32 -43
  205. package/dist/src/gateway/image-capabilities.js.map +1 -1
  206. package/dist/src/gateway/run-loop.js +1 -1
  207. package/dist/src/gateway/workspace-editor-path.js +9 -1
  208. package/dist/src/gateway/workspace-editor-path.js.map +1 -1
  209. package/dist/src/generated/bundled-image-generation-providers.d.ts +4 -2
  210. package/dist/src/generated/bundled-image-generation-providers.js +6 -4
  211. package/dist/src/generated/bundled-image-generation-providers.js.map +1 -1
  212. package/dist/src/infra/update-restart.js +1 -1
  213. package/dist/src/mcp/channel-bridge.js +1 -1
  214. package/dist/src/media/paths.js +3 -4
  215. package/dist/src/media/paths.js.map +1 -1
  216. package/dist/src/notes/service.js +1 -1
  217. package/dist/src/notes/service.js.map +1 -1
  218. package/dist/src/providers/domestic-presets.d.ts +615 -0
  219. package/dist/src/providers/domestic-presets.js +834 -0
  220. package/dist/src/providers/domestic-presets.js.map +1 -0
  221. package/dist/src/providers/env-keys.js +29 -5
  222. package/dist/src/providers/env-keys.js.map +1 -1
  223. package/dist/src/providers/extension-stream-bridge.js +1 -1
  224. package/dist/src/providers/extension-stream-bridge.js.map +1 -1
  225. package/dist/src/providers/index.d.ts +5 -5
  226. package/dist/src/providers/index.js +101 -21
  227. package/dist/src/providers/index.js.map +1 -1
  228. package/dist/src/providers/model-discovery.d.ts +17 -0
  229. package/dist/src/providers/model-discovery.js +61 -0
  230. package/dist/src/providers/model-discovery.js.map +1 -0
  231. package/dist/src/providers/model-registry.d.ts +1 -1
  232. package/dist/src/providers/model-registry.js +1 -1
  233. package/dist/src/providers/model-registry.js.map +1 -1
  234. package/dist/src/providers/presentation.js +185 -14
  235. package/dist/src/providers/presentation.js.map +1 -1
  236. package/dist/src/session/session-title.js +1 -1
  237. package/dist/src/session/session-title.js.map +1 -1
  238. package/dist/src/storage/sqlite/row-mappers.js +3 -1
  239. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  240. package/dist/src/tui/backends/embedded-backend.js +1 -2
  241. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  242. package/dist/src/tui/xopc-tui-keybindings.d.ts +1 -1
  243. package/dist/src/voice/tts/summarize.js +1 -1
  244. package/dist/src/voice/tts/summarize.js.map +1 -1
  245. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  246. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  247. package/package.json +6 -6
  248. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +0 -41
  249. package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +0 -2
  250. package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +0 -1
  251. package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +0 -8
  252. package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +0 -1
  253. package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +0 -2
  254. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +0 -1
  255. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +0 -1
  256. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +0 -1
  257. package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +0 -1
  258. package/dist/gateway/static/root/assets/extension-settings-page-BU1KoKRj.js +0 -1
  259. package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +0 -1
  260. package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +0 -1
  261. package/dist/gateway/static/root/assets/goals-page-CS0R-Af2.js +0 -2
  262. package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +0 -1
  263. package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +0 -1
  264. package/dist/gateway/static/root/assets/index-BoKafJIZ.js +0 -191
  265. package/dist/gateway/static/root/assets/index-CArhCcYn.css +0 -1
  266. package/dist/gateway/static/root/assets/logs-page-DLXPcksQ.js +0 -2
  267. package/dist/gateway/static/root/assets/messages-CrDHEbss.js +0 -3
  268. package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +0 -2
  269. package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +0 -2
  270. package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +0 -1
  271. package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +0 -1
  272. package/dist/gateway/static/root/assets/schema-form-FMKv1vGu.js +0 -1
  273. package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +0 -1
  274. package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +0 -1
  275. package/dist/gateway/static/root/assets/settings-form-section-D-4lBl6X.js +0 -1
  276. package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +0 -1
  277. package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +0 -1
  278. package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +0 -1
  279. package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +0 -2
  280. package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +0 -1
  281. package/dist/gateway/static/root/assets/voice-api-key-field-CeEevm7z.js +0 -1
  282. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +0 -3
  283. package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +0 -18
  284. package/dist/src/agent/memory/memory-flush.d.ts +0 -27
  285. package/dist/src/agent/memory/memory-flush.js +0 -124
  286. package/dist/src/agent/memory/memory-flush.js.map +0 -1
@@ -1,38 +1,8 @@
1
- import { createLogger } from "../../../utils/logger/index.js";
2
- import { init_logger } from "../../../utils/logger.js";
3
1
  import { DREAMING_DIR_RELATIVE } from "./constants.js";
4
- import { buildEntryKey, isoDay, normalizeMemoryPath, normalizeSnippetForHash, snippetHash } from "./utils.js";
5
- import { bumpEntryPhaseSignal, loadDreamingStore, saveDreamingStore } from "./short-term-store.js";
6
2
  import "./last-run.js";
7
3
  import path from "node:path";
8
4
  import fs from "node:fs/promises";
9
5
  //#region src/agent/memory/dreaming/light-sweep.ts
10
- init_logger();
11
- const log = createLogger("Dreaming:Light");
12
- function isDailyMemoryFile(filename) {
13
- return /^\d{4}-\d{2}-\d{2}\.md$/i.test(filename);
14
- }
15
- /**
16
- * Cosine-ish similarity via character n-gram overlap.
17
- * Fast and deterministic — no embeddings required.
18
- */
19
- function trigramSimilarity(textA, textB) {
20
- const normalizedA = normalizeSnippetForHash(textA);
21
- const normalizedB = normalizeSnippetForHash(textB);
22
- if (!normalizedA || !normalizedB) return 0;
23
- if (normalizedA === normalizedB) return 1;
24
- const gramsA = buildTrigramSet(normalizedA);
25
- const gramsB = buildTrigramSet(normalizedB);
26
- if (gramsA.size === 0 || gramsB.size === 0) return 0;
27
- let intersection = 0;
28
- for (const gram of gramsA) if (gramsB.has(gram)) intersection += 1;
29
- return intersection / Math.sqrt(gramsA.size * gramsB.size);
30
- }
31
- function buildTrigramSet(text) {
32
- const grams = /* @__PURE__ */ new Set();
33
- for (let i = 0; i <= text.length - 3; i++) grams.add(text.slice(i, i + 3));
34
- return grams;
35
- }
36
6
  function resolveConfig(overrides) {
37
7
  return {
38
8
  enabled: overrides?.enabled === true,
@@ -42,262 +12,31 @@ function resolveConfig(overrides) {
42
12
  dedupeSimilarity: Math.max(0, Math.min(1, Number(overrides?.dedupeSimilarity) || .9))
43
13
  };
44
14
  }
45
- /**
46
- * Scan recent daily memory files (memory/YYYY-MM-DD.md) and collect signal
47
- * entries into the short-term store. Deduplicates near-identical snippets
48
- * using trigram similarity.
49
- *
50
- * This is the "light sleep" phase: fast, frequent, cheap.
51
- */
52
15
  async function runLightSweep(params) {
53
16
  const cfg = resolveConfig(params.config);
54
- const now = params.now ?? /* @__PURE__ */ new Date();
55
- const startedAt = now.toISOString();
17
+ const startedAt = (params.now ?? /* @__PURE__ */ new Date()).toISOString();
56
18
  const runId = `light:${startedAt}:${process.pid}`;
57
19
  const startMs = Date.now();
58
- if (!cfg.enabled) {
59
- await writeLastRun(params.workspaceDir, {
60
- runId,
61
- startedAt,
62
- cfg,
63
- ok: true,
64
- reason: "light sweep disabled",
65
- startMs,
66
- light: {
67
- scannedEntries: 0,
68
- newSignals: 0,
69
- deduped: 0
70
- }
71
- });
72
- return {
73
- ok: true,
74
- reason: "light sweep disabled",
20
+ const reason = cfg.enabled ? "light sweep disabled: no implicit file source" : "light sweep disabled";
21
+ await writeLastRun(params.workspaceDir, {
22
+ runId,
23
+ startedAt,
24
+ cfg,
25
+ ok: true,
26
+ reason,
27
+ startMs,
28
+ light: {
75
29
  scannedEntries: 0,
76
30
  newSignals: 0,
77
31
  deduped: 0
78
- };
79
- }
80
- try {
81
- const recentFiles = await listRecentDailyFiles(path.join(params.workspaceDir, "memory"), cfg.lookbackDays, now);
82
- if (recentFiles.length === 0) {
83
- await writeLastRun(params.workspaceDir, {
84
- runId,
85
- startedAt,
86
- cfg,
87
- ok: true,
88
- reason: "no recent daily files",
89
- startMs,
90
- light: {
91
- scannedEntries: 0,
92
- newSignals: 0,
93
- deduped: 0
94
- }
95
- });
96
- return {
97
- ok: true,
98
- reason: "no recent daily files",
99
- scannedEntries: 0,
100
- newSignals: 0,
101
- deduped: 0
102
- };
103
- }
104
- const allChunks = [];
105
- for (const filePath of recentFiles) {
106
- const chunks = await parseFileChunks(filePath, params.workspaceDir);
107
- allChunks.push(...chunks);
108
32
  }
109
- if (allChunks.length === 0) {
110
- await writeLastRun(params.workspaceDir, {
111
- runId,
112
- startedAt,
113
- cfg,
114
- ok: true,
115
- reason: "no chunks found in daily files",
116
- startMs,
117
- light: {
118
- scannedEntries: 0,
119
- newSignals: 0,
120
- deduped: 0
121
- }
122
- });
123
- return {
124
- ok: true,
125
- reason: "no chunks found in daily files",
126
- scannedEntries: 0,
127
- newSignals: 0,
128
- deduped: 0
129
- };
130
- }
131
- const { unique, deduped } = deduplicateChunks(allChunks, cfg.dedupeSimilarity);
132
- const capped = unique.slice(0, cfg.limit);
133
- const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });
134
- let newSignals = 0;
135
- const dayBucket = isoDay(now);
136
- const nowIso = now.toISOString();
137
- for (const chunk of capped) {
138
- const key = buildEntryKey({
139
- path: chunk.path,
140
- startLine: chunk.startLine,
141
- endLine: chunk.endLine
142
- });
143
- const existing = store.entries[key];
144
- if (existing) {
145
- bumpEntryPhaseSignal(existing, "lightHits");
146
- bumpEntryPhaseSignal(existing, "dailyCount");
147
- existing.snippet = chunk.text.slice(0, 360);
148
- existing.lastRecalledAt = nowIso;
149
- } else {
150
- store.entries[key] = {
151
- key,
152
- path: chunk.path,
153
- startLine: chunk.startLine,
154
- endLine: chunk.endLine,
155
- snippet: chunk.text.slice(0, 360),
156
- recallCount: 0,
157
- dailyCount: 1,
158
- groundedCount: 0,
159
- lightHits: 1,
160
- remHits: 0,
161
- phaseHitCount: 1,
162
- totalSignalCount: 1,
163
- totalScore: 0,
164
- maxScore: 0,
165
- queryHashes: [],
166
- recallDays: [dayBucket],
167
- firstRecalledAt: nowIso,
168
- lastRecalledAt: nowIso
169
- };
170
- newSignals += 1;
171
- }
172
- }
173
- store.updatedAt = nowIso;
174
- await saveDreamingStore({
175
- workspaceDir: params.workspaceDir,
176
- store
177
- });
178
- log.info({
179
- workspaceDir: params.workspaceDir,
180
- scanned: allChunks.length,
181
- newSignals,
182
- deduped
183
- }, "Light sweep complete");
184
- await writeLastRun(params.workspaceDir, {
185
- runId,
186
- startedAt,
187
- cfg,
188
- ok: true,
189
- reason: "light sweep complete",
190
- startMs,
191
- light: {
192
- scannedEntries: allChunks.length,
193
- newSignals,
194
- deduped
195
- }
196
- });
197
- return {
198
- ok: true,
199
- reason: "light sweep complete",
200
- scannedEntries: allChunks.length,
201
- newSignals,
202
- deduped
203
- };
204
- } catch (err) {
205
- const errorMessage = err instanceof Error ? err.message : String(err);
206
- log.error({
207
- err,
208
- errorMessage,
209
- workspaceDir: params.workspaceDir
210
- }, `Light sweep failed: ${errorMessage}`);
211
- await writeLastRun(params.workspaceDir, {
212
- runId,
213
- startedAt,
214
- cfg,
215
- ok: false,
216
- reason: `light sweep error: ${errorMessage}`,
217
- startMs,
218
- light: {
219
- scannedEntries: 0,
220
- newSignals: 0,
221
- deduped: 0
222
- },
223
- errorMessage
224
- }).catch(() => void 0);
225
- return {
226
- ok: false,
227
- reason: errorMessage,
228
- scannedEntries: 0,
229
- newSignals: 0,
230
- deduped: 0
231
- };
232
- }
233
- }
234
- async function listRecentDailyFiles(memoryDir, lookbackDays, now) {
235
- let entries;
236
- try {
237
- entries = await fs.readdir(memoryDir);
238
- } catch (err) {
239
- if (err?.code === "ENOENT") return [];
240
- throw err;
241
- }
242
- const cutoff = new Date(now);
243
- cutoff.setDate(cutoff.getDate() - lookbackDays);
244
- const cutoffDay = isoDay(cutoff);
245
- return entries.filter((name) => isDailyMemoryFile(name)).filter((name) => {
246
- return name.replace(/\.md$/i, "") >= cutoffDay;
247
- }).sort().map((name) => path.join(memoryDir, name));
248
- }
249
- async function parseFileChunks(filePath, workspaceDir) {
250
- let raw;
251
- try {
252
- raw = await fs.readFile(filePath, "utf-8");
253
- } catch {
254
- return [];
255
- }
256
- const relativePath = normalizeMemoryPath(path.relative(workspaceDir, filePath));
257
- const lines = raw.split(/\r?\n/);
258
- const chunks = [];
259
- let chunkStartLine = 1;
260
- let currentLines = [];
261
- for (let i = 0; i < lines.length; i++) {
262
- const trimmed = lines[i].trim();
263
- if (trimmed.length === 0) {
264
- if (currentLines.length > 0) {
265
- const text = currentLines.join(" ").replace(/\s+/g, " ").trim();
266
- if (text.length >= 20) chunks.push({
267
- path: relativePath,
268
- startLine: chunkStartLine,
269
- endLine: chunkStartLine + currentLines.length - 1,
270
- text: text.slice(0, 360),
271
- hash: snippetHash(text)
272
- });
273
- currentLines = [];
274
- }
275
- chunkStartLine = i + 2;
276
- } else {
277
- if (currentLines.length === 0) chunkStartLine = i + 1;
278
- currentLines.push(trimmed);
279
- }
280
- }
281
- if (currentLines.length > 0) {
282
- const text = currentLines.join(" ").replace(/\s+/g, " ").trim();
283
- if (text.length >= 20) chunks.push({
284
- path: relativePath,
285
- startLine: chunkStartLine,
286
- endLine: chunkStartLine + currentLines.length - 1,
287
- text: text.slice(0, 360),
288
- hash: snippetHash(text)
289
- });
290
- }
291
- return chunks;
292
- }
293
- function deduplicateChunks(chunks, threshold) {
294
- const unique = [];
295
- let deduped = 0;
296
- for (const chunk of chunks) if (unique.some((existing) => existing.hash === chunk.hash || trigramSimilarity(existing.text, chunk.text) >= threshold)) deduped += 1;
297
- else unique.push(chunk);
33
+ });
298
34
  return {
299
- unique,
300
- deduped
35
+ ok: true,
36
+ reason,
37
+ scannedEntries: 0,
38
+ newSignals: 0,
39
+ deduped: 0
301
40
  };
302
41
  }
303
42
  async function writeLastRun(workspaceDir, params) {
@@ -1 +1 @@
1
- {"version":3,"file":"light-sweep.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/light-sweep.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { DREAMING_DIR_RELATIVE } from './constants.js';\nimport type { DreamingLightConfig } from './config.js';\nimport {\n bumpEntryPhaseSignal,\n loadDreamingStore,\n saveDreamingStore,\n} from './short-term-store.js';\nimport {\n buildEntryKey,\n isoDay,\n normalizeMemoryPath,\n normalizeSnippetForHash,\n snippetHash,\n} from './utils.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n type DreamingLightLastRun,\n} from './last-run.js';\n\nconst log = createLogger('Dreaming:Light');\n\n// ── Helpers ────────────────────────────────────────────────────────────\n\nfunction isDailyMemoryFile(filename: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}\\.md$/i.test(filename);\n}\n\n/**\n * Cosine-ish similarity via character n-gram overlap.\n * Fast and deterministic — no embeddings required.\n */\nfunction trigramSimilarity(textA: string, textB: string): number {\n const normalizedA = normalizeSnippetForHash(textA);\n const normalizedB = normalizeSnippetForHash(textB);\n if (!normalizedA || !normalizedB) return 0;\n if (normalizedA === normalizedB) return 1;\n\n const gramsA = buildTrigramSet(normalizedA);\n const gramsB = buildTrigramSet(normalizedB);\n if (gramsA.size === 0 || gramsB.size === 0) return 0;\n\n let intersection = 0;\n for (const gram of gramsA) {\n if (gramsB.has(gram)) intersection += 1;\n }\n return intersection / Math.sqrt(gramsA.size * gramsB.size);\n}\n\nfunction buildTrigramSet(text: string): Set<string> {\n const grams = new Set<string>();\n for (let i = 0; i <= text.length - 3; i++) {\n grams.add(text.slice(i, i + 3));\n }\n return grams;\n}\n\n// ── Light sweep config defaults ────────────────────────────────────────\n\nfunction resolveConfig(overrides?: Partial<DreamingLightConfig>): DreamingLightConfig {\n return {\n enabled: overrides?.enabled === true,\n cron: typeof overrides?.cron === 'string' ? overrides.cron : '0 */6 * * *',\n lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 2)),\n limit: Math.max(0, Math.floor(Number(overrides?.limit) || 100)),\n dedupeSimilarity: Math.max(0, Math.min(1, Number(overrides?.dedupeSimilarity) || 0.9)),\n };\n}\n\n// ── Core light sweep ───────────────────────────────────────────────────\n\ntype LightSweepChunk = {\n path: string;\n startLine: number;\n endLine: number;\n text: string;\n hash: string;\n};\n\n/**\n * Scan recent daily memory files (memory/YYYY-MM-DD.md) and collect signal\n * entries into the short-term store. Deduplicates near-identical snippets\n * using trigram similarity.\n *\n * This is the \"light sleep\" phase: fast, frequent, cheap.\n */\nexport async function runLightSweep(params: {\n workspaceDir: string;\n config?: Partial<DreamingLightConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n scannedEntries: number;\n newSignals: number;\n deduped: number;\n}> {\n const cfg = resolveConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `light:${startedAt}:${process.pid}`;\n const startMs = Date.now();\n\n if (!cfg.enabled) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'light sweep disabled', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'light sweep disabled', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n try {\n const memoryDir = path.join(params.workspaceDir, 'memory');\n const recentFiles = await listRecentDailyFiles(memoryDir, cfg.lookbackDays, now);\n\n if (recentFiles.length === 0) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'no recent daily files', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'no recent daily files', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n // Parse chunks from daily files.\n const allChunks: LightSweepChunk[] = [];\n for (const filePath of recentFiles) {\n const chunks = await parseFileChunks(filePath, params.workspaceDir);\n allChunks.push(...chunks);\n }\n\n if (allChunks.length === 0) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'no chunks found in daily files', startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason: 'no chunks found in daily files', scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n\n // Deduplicate chunks by trigram similarity.\n const { unique, deduped } = deduplicateChunks(allChunks, cfg.dedupeSimilarity);\n const capped = unique.slice(0, cfg.limit);\n\n // Merge into the short-term store, bumping lightHits + dailyCount.\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n let newSignals = 0;\n const dayBucket = isoDay(now);\n const nowIso = now.toISOString();\n\n for (const chunk of capped) {\n const key = buildEntryKey({ path: chunk.path, startLine: chunk.startLine, endLine: chunk.endLine });\n const existing = store.entries[key];\n\n if (existing) {\n bumpEntryPhaseSignal(existing, 'lightHits');\n bumpEntryPhaseSignal(existing, 'dailyCount');\n existing.snippet = chunk.text.slice(0, 360);\n existing.lastRecalledAt = nowIso;\n } else {\n store.entries[key] = {\n key,\n path: chunk.path,\n startLine: chunk.startLine,\n endLine: chunk.endLine,\n snippet: chunk.text.slice(0, 360),\n recallCount: 0,\n dailyCount: 1,\n groundedCount: 0,\n lightHits: 1,\n remHits: 0,\n phaseHitCount: 1,\n totalSignalCount: 1,\n totalScore: 0,\n maxScore: 0,\n queryHashes: [],\n recallDays: [dayBucket],\n firstRecalledAt: nowIso,\n lastRecalledAt: nowIso,\n };\n newSignals += 1;\n }\n }\n\n store.updatedAt = nowIso;\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n log.info(\n { workspaceDir: params.workspaceDir, scanned: allChunks.length, newSignals, deduped },\n 'Light sweep complete',\n );\n\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'light sweep complete', startMs,\n light: { scannedEntries: allChunks.length, newSignals, deduped },\n });\n\n return { ok: true, reason: 'light sweep complete', scannedEntries: allChunks.length, newSignals, deduped };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage, workspaceDir: params.workspaceDir }, `Light sweep failed: ${errorMessage}`);\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: false, reason: `light sweep error: ${errorMessage}`, startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 }, errorMessage,\n }).catch(() => undefined);\n return { ok: false, reason: errorMessage, scannedEntries: 0, newSignals: 0, deduped: 0 };\n }\n}\n\n// ── File scanning ──────────────────────────────────────────────────────\n\nasync function listRecentDailyFiles(memoryDir: string, lookbackDays: number, now: Date): Promise<string[]> {\n let entries: string[];\n try {\n entries = await fs.readdir(memoryDir);\n } catch (err) {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return [];\n throw err;\n }\n\n const cutoff = new Date(now);\n cutoff.setDate(cutoff.getDate() - lookbackDays);\n const cutoffDay = isoDay(cutoff);\n\n return entries\n .filter((name) => isDailyMemoryFile(name))\n .filter((name) => {\n const day = name.replace(/\\.md$/i, '');\n return day >= cutoffDay;\n })\n .sort()\n .map((name) => path.join(memoryDir, name));\n}\n\nasync function parseFileChunks(filePath: string, workspaceDir: string): Promise<LightSweepChunk[]> {\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const relativePath = normalizeMemoryPath(path.relative(workspaceDir, filePath));\n const lines = raw.split(/\\r?\\n/);\n const chunks: LightSweepChunk[] = [];\n\n // Split into paragraph-level chunks (separated by blank lines).\n let chunkStartLine = 1;\n let currentLines: string[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed.length === 0) {\n if (currentLines.length > 0) {\n const text = currentLines.join(' ').replace(/\\s+/g, ' ').trim();\n if (text.length >= 20) {\n chunks.push({\n path: relativePath,\n startLine: chunkStartLine,\n endLine: chunkStartLine + currentLines.length - 1,\n text: text.slice(0, 360),\n hash: snippetHash(text),\n });\n }\n currentLines = [];\n }\n chunkStartLine = i + 2; // next non-blank line (1-indexed)\n } else {\n if (currentLines.length === 0) chunkStartLine = i + 1;\n currentLines.push(trimmed);\n }\n }\n\n // Flush remaining.\n if (currentLines.length > 0) {\n const text = currentLines.join(' ').replace(/\\s+/g, ' ').trim();\n if (text.length >= 20) {\n chunks.push({\n path: relativePath,\n startLine: chunkStartLine,\n endLine: chunkStartLine + currentLines.length - 1,\n text: text.slice(0, 360),\n hash: snippetHash(text),\n });\n }\n }\n\n return chunks;\n}\n\n// ── Deduplication ──────────────────────────────────────────────────────\n\nfunction deduplicateChunks(\n chunks: LightSweepChunk[],\n threshold: number,\n): { unique: LightSweepChunk[]; deduped: number } {\n const unique: LightSweepChunk[] = [];\n let deduped = 0;\n\n for (const chunk of chunks) {\n const isDuplicate = unique.some(\n (existing) => existing.hash === chunk.hash || trigramSimilarity(existing.text, chunk.text) >= threshold,\n );\n if (isDuplicate) {\n deduped += 1;\n } else {\n unique.push(chunk);\n }\n }\n\n return { unique, deduped };\n}\n\n// ── Last-run writer ────────────────────────────────────────────────────\n\nasync function writeLastRun(\n workspaceDir: string,\n params: {\n runId: string;\n startedAt: string;\n cfg: DreamingLightConfig;\n ok: boolean;\n reason: string;\n startMs: number;\n light: DreamingLightLastRun['light'];\n errorMessage?: string;\n },\n): Promise<void> {\n const finishedAt = new Date().toISOString();\n const durationMs = Math.max(0, Date.now() - params.startMs);\n\n const lastRun: DreamingLightLastRun = {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'light',\n runId: params.runId,\n startedAt: params.startedAt,\n finishedAt,\n durationMs,\n ok: params.ok,\n reason: params.reason,\n config: params.cfg,\n light: params.light,\n ...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),\n };\n\n const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, 'last-run-light.json');\n await fs.mkdir(path.dirname(lastRunPath), { recursive: true });\n const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, lastRunPath);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"light-sweep.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/light-sweep.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { DREAMING_DIR_RELATIVE } from './constants.js';\nimport type { DreamingLightConfig } from './config.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n type DreamingLightLastRun,\n} from './last-run.js';\n\nfunction resolveConfig(overrides?: Partial<DreamingLightConfig>): DreamingLightConfig {\n return {\n enabled: overrides?.enabled === true,\n cron: typeof overrides?.cron === 'string' ? overrides.cron : '0 */6 * * *',\n lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 2)),\n limit: Math.max(0, Math.floor(Number(overrides?.limit) || 100)),\n dedupeSimilarity: Math.max(0, Math.min(1, Number(overrides?.dedupeSimilarity) || 0.9)),\n };\n}\n\nexport async function runLightSweep(params: {\n workspaceDir: string;\n config?: Partial<DreamingLightConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n scannedEntries: number;\n newSignals: number;\n deduped: number;\n}> {\n const cfg = resolveConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `light:${startedAt}:${process.pid}`;\n const startMs = Date.now();\n const reason = cfg.enabled\n ? 'light sweep disabled: no implicit file source'\n : 'light sweep disabled';\n\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason, startMs,\n light: { scannedEntries: 0, newSignals: 0, deduped: 0 },\n });\n return { ok: true, reason, scannedEntries: 0, newSignals: 0, deduped: 0 };\n}\n\n// ── Last-run writer ────────────────────────────────────────────────────\n\nasync function writeLastRun(\n workspaceDir: string,\n params: {\n runId: string;\n startedAt: string;\n cfg: DreamingLightConfig;\n ok: boolean;\n reason: string;\n startMs: number;\n light: DreamingLightLastRun['light'];\n errorMessage?: string;\n },\n): Promise<void> {\n const finishedAt = new Date().toISOString();\n const durationMs = Math.max(0, Date.now() - params.startMs);\n\n const lastRun: DreamingLightLastRun = {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'light',\n runId: params.runId,\n startedAt: params.startedAt,\n finishedAt,\n durationMs,\n ok: params.ok,\n reason: params.reason,\n config: params.cfg,\n light: params.light,\n ...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),\n };\n\n const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, 'last-run-light.json');\n await fs.mkdir(path.dirname(lastRunPath), { recursive: true });\n const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, lastRunPath);\n}\n"],"mappings":";;;;;AAUA,SAAS,cAAc,WAA+D;AACpF,QAAO;EACL,SAAS,WAAW,YAAY;EAChC,MAAM,OAAO,WAAW,SAAS,WAAW,UAAU,OAAO;EAC7D,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,WAAW,aAAa,IAAI,EAAE,CAAC;EAC3E,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,WAAW,MAAM,IAAI,IAAI,CAAC;EAC/D,kBAAkB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,WAAW,iBAAiB,IAAI,GAAI,CAAC;EACvF;;AAGH,eAAsB,cAAc,QAUjC;CACD,MAAM,MAAM,cAAc,OAAO,OAAO;CAExC,MAAM,aADM,OAAO,uBAAO,IAAI,MAAM,EACd,aAAa;CACnC,MAAM,QAAQ,SAAS,UAAU,GAAG,QAAQ;CAC5C,MAAM,UAAU,KAAK,KAAK;CAC1B,MAAM,SAAS,IAAI,UACf,kDACA;AAEJ,OAAM,aAAa,OAAO,cAAc;EACtC;EAAO;EAAW;EAAK,IAAI;EAAM;EAAQ;EACzC,OAAO;GAAE,gBAAgB;GAAG,YAAY;GAAG,SAAS;GAAG;EACxD,CAAC;AACF,QAAO;EAAE,IAAI;EAAM;EAAQ,gBAAgB;EAAG,YAAY;EAAG,SAAS;EAAG;;AAK3E,eAAe,aACb,cACA,QAUe;CACf,MAAM,8BAAa,IAAI,MAAM,EAAC,aAAa;CAC3C,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,KAAK,GAAG,OAAO,QAAQ;CAE3D,MAAM,UAAgC;EACpC,SAAA;EACA,OAAO;EACP,OAAO,OAAO;EACd,WAAW,OAAO;EAClB;EACA;EACA,IAAI,OAAO;EACX,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,OAAO,OAAO;EACd,GAAI,OAAO,eAAe,EAAE,cAAc,OAAO,cAAc,GAAG,EAAE;EACrE;CAED,MAAM,cAAc,KAAK,KAAK,cAAc,uBAAuB,sBAAsB;AACzF,OAAM,GAAG,MAAM,KAAK,QAAQ,YAAY,EAAE,EAAE,WAAW,MAAM,CAAC;CAC9D,MAAM,MAAM,GAAG,YAAY,GAAG,QAAQ,IAAI,GAAG,KAAK,KAAK,CAAC;AACxD,OAAM,GAAG,UAAU,KAAK,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC,KAAK,QAAQ;AACzE,OAAM,GAAG,OAAO,KAAK,YAAY"}
@@ -3,7 +3,7 @@ import type { DreamingRemConfig } from './config.js';
3
3
  * REM phase: cross-session pattern discovery.
4
4
  *
5
5
  * Scans the short-term store for entries that share query hashes or
6
- * appear across multiple daily files, then clusters them to identify
6
+ * appear across multiple indexed memory sources, then clusters them to identify
7
7
  * recurring themes/patterns. Bumps `remHits` on touched entries and
8
8
  * optionally writes a pattern summary to DREAMS.md.
9
9
  *
@@ -22,7 +22,7 @@ function resolveConfig(overrides) {
22
22
  * REM phase: cross-session pattern discovery.
23
23
  *
24
24
  * Scans the short-term store for entries that share query hashes or
25
- * appear across multiple daily files, then clusters them to identify
25
+ * appear across multiple indexed memory sources, then clusters them to identify
26
26
  * recurring themes/patterns. Bumps `remHits` on touched entries and
27
27
  * optionally writes a pattern summary to DREAMS.md.
28
28
  *
@@ -1 +1 @@
1
- {"version":3,"file":"rem-patterns.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/rem-patterns.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { DREAMING_DIR_RELATIVE, DREAMS_MD_FILENAME, MS_PER_DAY } from './constants.js';\nimport type { DreamingRemConfig } from './config.js';\nimport {\n bumpEntryPhaseSignal,\n loadDreamingStore,\n saveDreamingStore,\n type DreamingStoreEntry,\n} from './short-term-store.js';\nimport { isoDay } from './utils.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n type DreamingRemLastRun,\n} from './last-run.js';\n\nconst log = createLogger('Dreaming:REM');\n\n// ── Pattern types ──────────────────────────────────────────────────────\n\ntype PatternCluster = {\n representative: DreamingStoreEntry;\n members: DreamingStoreEntry[];\n strength: number;\n /** Shared query hashes across members. */\n sharedQueries: string[];\n /** Distinct source files involved. */\n distinctPaths: string[];\n};\n\n// ── Config defaults ────────────────────────────────────────────────────\n\nfunction resolveConfig(overrides?: Partial<DreamingRemConfig>): DreamingRemConfig {\n return {\n enabled: overrides?.enabled === true,\n cron: typeof overrides?.cron === 'string' ? overrides.cron : '0 5 * * 0',\n lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 7)),\n limit: Math.max(0, Math.floor(Number(overrides?.limit) || 10)),\n minPatternStrength: Math.max(0, Math.min(1, Number(overrides?.minPatternStrength) || 0.75)),\n };\n}\n\n// ── Core REM pattern discovery ─────────────────────────────────────────\n\n/**\n * REM phase: cross-session pattern discovery.\n *\n * Scans the short-term store for entries that share query hashes or\n * appear across multiple daily files, then clusters them to identify\n * recurring themes/patterns. Bumps `remHits` on touched entries and\n * optionally writes a pattern summary to DREAMS.md.\n *\n * Runs weekly; expensive but insightful.\n */\nexport async function runRemPatterns(params: {\n workspaceDir: string;\n config?: Partial<DreamingRemConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n patternsDiscovered: number;\n entriesAnalyzed: number;\n}> {\n const cfg = resolveConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `rem:${startedAt}:${process.pid}`;\n const startMs = Date.now();\n const nowMs = now.getTime();\n\n if (!cfg.enabled) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'REM patterns disabled', startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: 0 },\n });\n return { ok: true, reason: 'REM patterns disabled', patternsDiscovered: 0, entriesAnalyzed: 0 };\n }\n\n try {\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n\n // Filter entries within the lookback window.\n const cutoffMs = nowMs - cfg.lookbackDays * MS_PER_DAY;\n const recentEntries = Object.values(store.entries ?? {}).filter(\n (entry): entry is DreamingStoreEntry => {\n if (!entry || typeof entry !== 'object') return false;\n if (!entry.lastRecalledAt) return false;\n const lastMs = Date.parse(entry.lastRecalledAt);\n return Number.isFinite(lastMs) && lastMs >= cutoffMs;\n },\n );\n\n if (recentEntries.length < 2) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'not enough recent entries for pattern analysis', startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: recentEntries.length },\n });\n return {\n ok: true,\n reason: 'not enough recent entries for pattern analysis',\n patternsDiscovered: 0,\n entriesAnalyzed: recentEntries.length,\n };\n }\n\n // Discover patterns by clustering entries that share query hashes.\n const clusters = discoverPatternClusters(recentEntries, cfg.minPatternStrength);\n const topClusters = clusters.slice(0, cfg.limit);\n\n // Bump remHits on all entries that belong to a discovered pattern.\n const touchedKeys = new Set<string>();\n for (const cluster of topClusters) {\n for (const member of cluster.members) {\n if (!touchedKeys.has(member.key)) {\n touchedKeys.add(member.key);\n const storeEntry = store.entries[member.key];\n if (storeEntry) {\n bumpEntryPhaseSignal(storeEntry, 'remHits');\n }\n }\n }\n }\n\n store.updatedAt = now.toISOString();\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n // Write pattern summary to DREAMS.md (append).\n if (topClusters.length > 0) {\n await appendPatternSummary(params.workspaceDir, topClusters, now);\n }\n\n log.info(\n {\n workspaceDir: params.workspaceDir,\n patterns: topClusters.length,\n entriesAnalyzed: recentEntries.length,\n touched: touchedKeys.size,\n },\n 'REM pattern discovery complete',\n );\n\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'REM patterns complete', startMs,\n rem: { patternsDiscovered: topClusters.length, entriesAnalyzed: recentEntries.length },\n });\n\n return {\n ok: true,\n reason: 'REM patterns complete',\n patternsDiscovered: topClusters.length,\n entriesAnalyzed: recentEntries.length,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage, workspaceDir: params.workspaceDir }, `REM pattern discovery failed: ${errorMessage}`);\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: false, reason: `REM error: ${errorMessage}`, startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: 0 }, errorMessage,\n }).catch(() => undefined);\n return { ok: false, reason: errorMessage, patternsDiscovered: 0, entriesAnalyzed: 0 };\n }\n}\n\n// ── Pattern clustering ─────────────────────────────────────────────────\n\n/**\n * Build an inverted index of queryHash → entries, then form clusters\n * where multiple entries share overlapping query hashes. Each cluster's\n * \"strength\" is the ratio of shared queries to total unique queries.\n */\nfunction discoverPatternClusters(\n entries: DreamingStoreEntry[],\n minStrength: number,\n): PatternCluster[] {\n // Build inverted index: queryHash → entry keys.\n const hashToEntries = new Map<string, DreamingStoreEntry[]>();\n for (const entry of entries) {\n for (const queryHash of entry.queryHashes ?? []) {\n const group = hashToEntries.get(queryHash);\n if (group) {\n group.push(entry);\n } else {\n hashToEntries.set(queryHash, [entry]);\n }\n }\n }\n\n // Find query hashes that appear in 2+ distinct entries from different paths.\n const significantHashes: Array<{ hash: string; entries: DreamingStoreEntry[] }> = [];\n for (const [hash, group] of hashToEntries) {\n const uniquePaths = new Set(group.map((e) => e.path));\n if (group.length >= 2 && uniquePaths.size >= 2) {\n significantHashes.push({ hash, entries: group });\n }\n }\n\n if (significantHashes.length === 0) return [];\n\n // Merge overlapping groups into clusters using union-find.\n const keyToCluster = new Map<string, Set<string>>();\n const keyToEntry = new Map<string, DreamingStoreEntry>();\n\n for (const entry of entries) {\n keyToEntry.set(entry.key, entry);\n }\n\n for (const { entries: groupEntries } of significantHashes) {\n const keys = groupEntries.map((e) => e.key);\n // Find or create the cluster for the first key.\n let mergedCluster = keyToCluster.get(keys[0]!);\n if (!mergedCluster) {\n mergedCluster = new Set<string>();\n mergedCluster.add(keys[0]!);\n keyToCluster.set(keys[0]!, mergedCluster);\n }\n // Merge all other keys into this cluster.\n for (const key of keys.slice(1)) {\n const existingCluster = keyToCluster.get(key);\n if (existingCluster && existingCluster !== mergedCluster) {\n for (const existingKey of existingCluster) {\n mergedCluster.add(existingKey);\n keyToCluster.set(existingKey, mergedCluster);\n }\n } else {\n mergedCluster.add(key);\n keyToCluster.set(key, mergedCluster);\n }\n }\n }\n\n // Deduplicate cluster sets.\n const seenClusters = new Set<Set<string>>();\n const rawClusters: Set<string>[] = [];\n for (const cluster of keyToCluster.values()) {\n if (!seenClusters.has(cluster) && cluster.size >= 2) {\n seenClusters.add(cluster);\n rawClusters.push(cluster);\n }\n }\n\n // Score each cluster.\n const scoredClusters: PatternCluster[] = [];\n for (const clusterKeys of rawClusters) {\n const members: DreamingStoreEntry[] = [];\n for (const key of clusterKeys) {\n const entry = keyToEntry.get(key);\n if (entry) members.push(entry);\n }\n if (members.length < 2) continue;\n\n // Shared queries: hashes that appear in 2+ members.\n const hashCounts = new Map<string, number>();\n for (const member of members) {\n for (const hash of member.queryHashes ?? []) {\n hashCounts.set(hash, (hashCounts.get(hash) ?? 0) + 1);\n }\n }\n const sharedQueries = [...hashCounts.entries()]\n .filter(([, count]) => count >= 2)\n .map(([hash]) => hash);\n\n const allUniqueHashes = new Set<string>();\n for (const member of members) {\n for (const hash of member.queryHashes ?? []) allUniqueHashes.add(hash);\n }\n\n const strength = allUniqueHashes.size > 0 ? sharedQueries.length / allUniqueHashes.size : 0;\n if (strength < minStrength) continue;\n\n const distinctPaths = [...new Set(members.map((m) => m.path))];\n\n // Representative: the member with the highest totalSignalCount.\n const representative = members.reduce((best, current) =>\n (current.totalSignalCount ?? 0) > (best.totalSignalCount ?? 0) ? current : best,\n );\n\n scoredClusters.push({\n representative,\n members,\n strength,\n sharedQueries,\n distinctPaths,\n });\n }\n\n // Sort by strength descending, then by member count.\n scoredClusters.sort((a, b) => {\n if (b.strength !== a.strength) return b.strength - a.strength;\n return b.members.length - a.members.length;\n });\n\n return scoredClusters;\n}\n\n// ── DREAMS.md writer ───────────────────────────────────────────────────\n\nasync function appendPatternSummary(\n workspaceDir: string,\n clusters: PatternCluster[],\n now: Date,\n): Promise<void> {\n const dreamsPath = path.join(workspaceDir, DREAMS_MD_FILENAME);\n const existing = await fs.readFile(dreamsPath, 'utf-8').catch((err: unknown) => {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return '';\n throw err;\n });\n\n const day = isoDay(now);\n const lines: string[] = [];\n\n if (existing.trim().length === 0) {\n lines.push('# Dream Diary', '');\n }\n\n lines.push(`## REM Pattern Discovery — ${day}`, '');\n lines.push(`*${now.toISOString()}*`, '');\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i]!;\n lines.push(\n `### Pattern ${i + 1}: ${cluster.distinctPaths.length} files, strength=${cluster.strength.toFixed(2)}`,\n );\n lines.push('');\n lines.push(`**Files involved:** ${cluster.distinctPaths.join(', ')}`);\n lines.push(`**Shared query themes:** ${cluster.sharedQueries.length} overlapping queries`);\n lines.push(`**Members:** ${cluster.members.length} snippets`);\n lines.push('');\n // Include the representative snippet.\n const rep = cluster.representative;\n lines.push(`> ${rep.snippet?.slice(0, 200) ?? '(no snippet)'}`);\n lines.push(`> — ${rep.path}:${rep.startLine}-${rep.endLine}`);\n lines.push('');\n }\n\n lines.push('---', '');\n\n const separator = existing.trim().length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const next = `${existing}${separator}${lines.join('\\n')}`;\n await fs.writeFile(dreamsPath, next, 'utf-8');\n}\n\n// ── Last-run writer ────────────────────────────────────────────────────\n\nasync function writeLastRun(\n workspaceDir: string,\n params: {\n runId: string;\n startedAt: string;\n cfg: DreamingRemConfig;\n ok: boolean;\n reason: string;\n startMs: number;\n rem: DreamingRemLastRun['rem'];\n errorMessage?: string;\n },\n): Promise<void> {\n const finishedAt = new Date().toISOString();\n const durationMs = Math.max(0, Date.now() - params.startMs);\n\n const lastRun: DreamingRemLastRun = {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'rem',\n runId: params.runId,\n startedAt: params.startedAt,\n finishedAt,\n durationMs,\n ok: params.ok,\n reason: params.reason,\n config: params.cfg,\n rem: params.rem,\n ...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),\n };\n\n const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, 'last-run-rem.json');\n await fs.mkdir(path.dirname(lastRunPath), { recursive: true });\n const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, lastRunPath);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"rem-patterns.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/rem-patterns.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport { createLogger } from '../../../utils/logger.js';\nimport { DREAMING_DIR_RELATIVE, DREAMS_MD_FILENAME, MS_PER_DAY } from './constants.js';\nimport type { DreamingRemConfig } from './config.js';\nimport {\n bumpEntryPhaseSignal,\n loadDreamingStore,\n saveDreamingStore,\n type DreamingStoreEntry,\n} from './short-term-store.js';\nimport { isoDay } from './utils.js';\nimport {\n DREAMING_LAST_RUN_FORMAT_VERSION,\n type DreamingRemLastRun,\n} from './last-run.js';\n\nconst log = createLogger('Dreaming:REM');\n\n// ── Pattern types ──────────────────────────────────────────────────────\n\ntype PatternCluster = {\n representative: DreamingStoreEntry;\n members: DreamingStoreEntry[];\n strength: number;\n /** Shared query hashes across members. */\n sharedQueries: string[];\n /** Distinct source files involved. */\n distinctPaths: string[];\n};\n\n// ── Config defaults ────────────────────────────────────────────────────\n\nfunction resolveConfig(overrides?: Partial<DreamingRemConfig>): DreamingRemConfig {\n return {\n enabled: overrides?.enabled === true,\n cron: typeof overrides?.cron === 'string' ? overrides.cron : '0 5 * * 0',\n lookbackDays: Math.max(1, Math.floor(Number(overrides?.lookbackDays) || 7)),\n limit: Math.max(0, Math.floor(Number(overrides?.limit) || 10)),\n minPatternStrength: Math.max(0, Math.min(1, Number(overrides?.minPatternStrength) || 0.75)),\n };\n}\n\n// ── Core REM pattern discovery ─────────────────────────────────────────\n\n/**\n * REM phase: cross-session pattern discovery.\n *\n * Scans the short-term store for entries that share query hashes or\n * appear across multiple indexed memory sources, then clusters them to identify\n * recurring themes/patterns. Bumps `remHits` on touched entries and\n * optionally writes a pattern summary to DREAMS.md.\n *\n * Runs weekly; expensive but insightful.\n */\nexport async function runRemPatterns(params: {\n workspaceDir: string;\n config?: Partial<DreamingRemConfig>;\n now?: Date;\n}): Promise<{\n ok: boolean;\n reason: string;\n patternsDiscovered: number;\n entriesAnalyzed: number;\n}> {\n const cfg = resolveConfig(params.config);\n const now = params.now ?? new Date();\n const startedAt = now.toISOString();\n const runId = `rem:${startedAt}:${process.pid}`;\n const startMs = Date.now();\n const nowMs = now.getTime();\n\n if (!cfg.enabled) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'REM patterns disabled', startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: 0 },\n });\n return { ok: true, reason: 'REM patterns disabled', patternsDiscovered: 0, entriesAnalyzed: 0 };\n }\n\n try {\n const { store } = await loadDreamingStore({ workspaceDir: params.workspaceDir });\n\n // Filter entries within the lookback window.\n const cutoffMs = nowMs - cfg.lookbackDays * MS_PER_DAY;\n const recentEntries = Object.values(store.entries ?? {}).filter(\n (entry): entry is DreamingStoreEntry => {\n if (!entry || typeof entry !== 'object') return false;\n if (!entry.lastRecalledAt) return false;\n const lastMs = Date.parse(entry.lastRecalledAt);\n return Number.isFinite(lastMs) && lastMs >= cutoffMs;\n },\n );\n\n if (recentEntries.length < 2) {\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'not enough recent entries for pattern analysis', startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: recentEntries.length },\n });\n return {\n ok: true,\n reason: 'not enough recent entries for pattern analysis',\n patternsDiscovered: 0,\n entriesAnalyzed: recentEntries.length,\n };\n }\n\n // Discover patterns by clustering entries that share query hashes.\n const clusters = discoverPatternClusters(recentEntries, cfg.minPatternStrength);\n const topClusters = clusters.slice(0, cfg.limit);\n\n // Bump remHits on all entries that belong to a discovered pattern.\n const touchedKeys = new Set<string>();\n for (const cluster of topClusters) {\n for (const member of cluster.members) {\n if (!touchedKeys.has(member.key)) {\n touchedKeys.add(member.key);\n const storeEntry = store.entries[member.key];\n if (storeEntry) {\n bumpEntryPhaseSignal(storeEntry, 'remHits');\n }\n }\n }\n }\n\n store.updatedAt = now.toISOString();\n await saveDreamingStore({ workspaceDir: params.workspaceDir, store });\n\n // Write pattern summary to DREAMS.md (append).\n if (topClusters.length > 0) {\n await appendPatternSummary(params.workspaceDir, topClusters, now);\n }\n\n log.info(\n {\n workspaceDir: params.workspaceDir,\n patterns: topClusters.length,\n entriesAnalyzed: recentEntries.length,\n touched: touchedKeys.size,\n },\n 'REM pattern discovery complete',\n );\n\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: true, reason: 'REM patterns complete', startMs,\n rem: { patternsDiscovered: topClusters.length, entriesAnalyzed: recentEntries.length },\n });\n\n return {\n ok: true,\n reason: 'REM patterns complete',\n patternsDiscovered: topClusters.length,\n entriesAnalyzed: recentEntries.length,\n };\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage, workspaceDir: params.workspaceDir }, `REM pattern discovery failed: ${errorMessage}`);\n await writeLastRun(params.workspaceDir, {\n runId, startedAt, cfg, ok: false, reason: `REM error: ${errorMessage}`, startMs,\n rem: { patternsDiscovered: 0, entriesAnalyzed: 0 }, errorMessage,\n }).catch(() => undefined);\n return { ok: false, reason: errorMessage, patternsDiscovered: 0, entriesAnalyzed: 0 };\n }\n}\n\n// ── Pattern clustering ─────────────────────────────────────────────────\n\n/**\n * Build an inverted index of queryHash → entries, then form clusters\n * where multiple entries share overlapping query hashes. Each cluster's\n * \"strength\" is the ratio of shared queries to total unique queries.\n */\nfunction discoverPatternClusters(\n entries: DreamingStoreEntry[],\n minStrength: number,\n): PatternCluster[] {\n // Build inverted index: queryHash → entry keys.\n const hashToEntries = new Map<string, DreamingStoreEntry[]>();\n for (const entry of entries) {\n for (const queryHash of entry.queryHashes ?? []) {\n const group = hashToEntries.get(queryHash);\n if (group) {\n group.push(entry);\n } else {\n hashToEntries.set(queryHash, [entry]);\n }\n }\n }\n\n // Find query hashes that appear in 2+ distinct entries from different paths.\n const significantHashes: Array<{ hash: string; entries: DreamingStoreEntry[] }> = [];\n for (const [hash, group] of hashToEntries) {\n const uniquePaths = new Set(group.map((e) => e.path));\n if (group.length >= 2 && uniquePaths.size >= 2) {\n significantHashes.push({ hash, entries: group });\n }\n }\n\n if (significantHashes.length === 0) return [];\n\n // Merge overlapping groups into clusters using union-find.\n const keyToCluster = new Map<string, Set<string>>();\n const keyToEntry = new Map<string, DreamingStoreEntry>();\n\n for (const entry of entries) {\n keyToEntry.set(entry.key, entry);\n }\n\n for (const { entries: groupEntries } of significantHashes) {\n const keys = groupEntries.map((e) => e.key);\n // Find or create the cluster for the first key.\n let mergedCluster = keyToCluster.get(keys[0]!);\n if (!mergedCluster) {\n mergedCluster = new Set<string>();\n mergedCluster.add(keys[0]!);\n keyToCluster.set(keys[0]!, mergedCluster);\n }\n // Merge all other keys into this cluster.\n for (const key of keys.slice(1)) {\n const existingCluster = keyToCluster.get(key);\n if (existingCluster && existingCluster !== mergedCluster) {\n for (const existingKey of existingCluster) {\n mergedCluster.add(existingKey);\n keyToCluster.set(existingKey, mergedCluster);\n }\n } else {\n mergedCluster.add(key);\n keyToCluster.set(key, mergedCluster);\n }\n }\n }\n\n // Deduplicate cluster sets.\n const seenClusters = new Set<Set<string>>();\n const rawClusters: Set<string>[] = [];\n for (const cluster of keyToCluster.values()) {\n if (!seenClusters.has(cluster) && cluster.size >= 2) {\n seenClusters.add(cluster);\n rawClusters.push(cluster);\n }\n }\n\n // Score each cluster.\n const scoredClusters: PatternCluster[] = [];\n for (const clusterKeys of rawClusters) {\n const members: DreamingStoreEntry[] = [];\n for (const key of clusterKeys) {\n const entry = keyToEntry.get(key);\n if (entry) members.push(entry);\n }\n if (members.length < 2) continue;\n\n // Shared queries: hashes that appear in 2+ members.\n const hashCounts = new Map<string, number>();\n for (const member of members) {\n for (const hash of member.queryHashes ?? []) {\n hashCounts.set(hash, (hashCounts.get(hash) ?? 0) + 1);\n }\n }\n const sharedQueries = [...hashCounts.entries()]\n .filter(([, count]) => count >= 2)\n .map(([hash]) => hash);\n\n const allUniqueHashes = new Set<string>();\n for (const member of members) {\n for (const hash of member.queryHashes ?? []) allUniqueHashes.add(hash);\n }\n\n const strength = allUniqueHashes.size > 0 ? sharedQueries.length / allUniqueHashes.size : 0;\n if (strength < minStrength) continue;\n\n const distinctPaths = [...new Set(members.map((m) => m.path))];\n\n // Representative: the member with the highest totalSignalCount.\n const representative = members.reduce((best, current) =>\n (current.totalSignalCount ?? 0) > (best.totalSignalCount ?? 0) ? current : best,\n );\n\n scoredClusters.push({\n representative,\n members,\n strength,\n sharedQueries,\n distinctPaths,\n });\n }\n\n // Sort by strength descending, then by member count.\n scoredClusters.sort((a, b) => {\n if (b.strength !== a.strength) return b.strength - a.strength;\n return b.members.length - a.members.length;\n });\n\n return scoredClusters;\n}\n\n// ── DREAMS.md writer ───────────────────────────────────────────────────\n\nasync function appendPatternSummary(\n workspaceDir: string,\n clusters: PatternCluster[],\n now: Date,\n): Promise<void> {\n const dreamsPath = path.join(workspaceDir, DREAMS_MD_FILENAME);\n const existing = await fs.readFile(dreamsPath, 'utf-8').catch((err: unknown) => {\n if ((err as NodeJS.ErrnoException)?.code === 'ENOENT') return '';\n throw err;\n });\n\n const day = isoDay(now);\n const lines: string[] = [];\n\n if (existing.trim().length === 0) {\n lines.push('# Dream Diary', '');\n }\n\n lines.push(`## REM Pattern Discovery — ${day}`, '');\n lines.push(`*${now.toISOString()}*`, '');\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i]!;\n lines.push(\n `### Pattern ${i + 1}: ${cluster.distinctPaths.length} files, strength=${cluster.strength.toFixed(2)}`,\n );\n lines.push('');\n lines.push(`**Files involved:** ${cluster.distinctPaths.join(', ')}`);\n lines.push(`**Shared query themes:** ${cluster.sharedQueries.length} overlapping queries`);\n lines.push(`**Members:** ${cluster.members.length} snippets`);\n lines.push('');\n // Include the representative snippet.\n const rep = cluster.representative;\n lines.push(`> ${rep.snippet?.slice(0, 200) ?? '(no snippet)'}`);\n lines.push(`> — ${rep.path}:${rep.startLine}-${rep.endLine}`);\n lines.push('');\n }\n\n lines.push('---', '');\n\n const separator = existing.trim().length > 0 && !existing.endsWith('\\n') ? '\\n' : '';\n const next = `${existing}${separator}${lines.join('\\n')}`;\n await fs.writeFile(dreamsPath, next, 'utf-8');\n}\n\n// ── Last-run writer ────────────────────────────────────────────────────\n\nasync function writeLastRun(\n workspaceDir: string,\n params: {\n runId: string;\n startedAt: string;\n cfg: DreamingRemConfig;\n ok: boolean;\n reason: string;\n startMs: number;\n rem: DreamingRemLastRun['rem'];\n errorMessage?: string;\n },\n): Promise<void> {\n const finishedAt = new Date().toISOString();\n const durationMs = Math.max(0, Date.now() - params.startMs);\n\n const lastRun: DreamingRemLastRun = {\n version: DREAMING_LAST_RUN_FORMAT_VERSION,\n phase: 'rem',\n runId: params.runId,\n startedAt: params.startedAt,\n finishedAt,\n durationMs,\n ok: params.ok,\n reason: params.reason,\n config: params.cfg,\n rem: params.rem,\n ...(params.errorMessage ? { errorMessage: params.errorMessage } : {}),\n };\n\n const lastRunPath = path.join(workspaceDir, DREAMING_DIR_RELATIVE, 'last-run-rem.json');\n await fs.mkdir(path.dirname(lastRunPath), { recursive: true });\n const tmp = `${lastRunPath}.${process.pid}.${Date.now()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(lastRun, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, lastRunPath);\n}\n"],"mappings":"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"}
@@ -7,8 +7,8 @@ export type DreamingStoreEntry = {
7
7
  snippet: string;
8
8
  /** Number of times this snippet was returned by a memory recall query. */
9
9
  recallCount: number;
10
- /** Number of times recorded from daily log scanning (light sweep). */
11
- dailyCount: number;
10
+ /** Number of times recorded from source-side sweep phases. */
11
+ sourceCount: number;
12
12
  /** Number of times replayed from grounded context (agent-initiated). */
13
13
  groundedCount: number;
14
14
  /** Number of times the light phase touched this entry. */
@@ -55,7 +55,7 @@ export declare function saveDreamingStore(params: {
55
55
  workspaceDir: string;
56
56
  store: DreamingStore;
57
57
  }): Promise<void>;
58
- type PhaseSignalField = 'dailyCount' | 'groundedCount' | 'lightHits' | 'remHits';
58
+ type PhaseSignalField = 'sourceCount' | 'groundedCount' | 'lightHits' | 'remHits';
59
59
  /**
60
60
  * Increment a phase-specific signal counter on an existing store entry.
61
61
  * Also bumps `phaseHitCount` and `totalSignalCount`.
@@ -8,9 +8,9 @@ import fs from "node:fs/promises";
8
8
  //#region src/agent/memory/dreaming/short-term-store.ts
9
9
  init_logger();
10
10
  const log = createLogger("Dreaming:Store");
11
- function isDailyWorkspaceMemoryPath(rel) {
11
+ function isRecordableMemoryPath(rel) {
12
12
  const p = normalizeMemoryPath(rel);
13
- return /^memory\/\d{4}-\d{2}-\d{2}\.md$/i.test(p);
13
+ return p.length > 0 && !p.startsWith("../") && !path.isAbsolute(p);
14
14
  }
15
15
  function hashQuery(query) {
16
16
  return createHash("sha1").update(query.trim().toLowerCase()).digest("hex").slice(0, 12);
@@ -82,7 +82,7 @@ async function recordDreamingRecalls(params) {
82
82
  let skipped = 0;
83
83
  for (const match of params.matches) {
84
84
  const file = typeof match?.file === "string" ? match.file : "";
85
- if (!file || !isDailyWorkspaceMemoryPath(file)) {
85
+ if (!file || !isRecordableMemoryPath(file)) {
86
86
  skipped += 1;
87
87
  continue;
88
88
  }
@@ -106,7 +106,7 @@ async function recordDreamingRecalls(params) {
106
106
  ...existing,
107
107
  snippet,
108
108
  recallCount: Math.max(0, Math.floor(existing.recallCount + 1)),
109
- dailyCount: existing.dailyCount ?? 0,
109
+ sourceCount: existing.sourceCount ?? 0,
110
110
  groundedCount: existing.groundedCount ?? 0,
111
111
  lightHits: existing.lightHits ?? 0,
112
112
  remHits: existing.remHits ?? 0,
@@ -124,7 +124,7 @@ async function recordDreamingRecalls(params) {
124
124
  endLine,
125
125
  snippet,
126
126
  recallCount: 1,
127
- dailyCount: 0,
127
+ sourceCount: 0,
128
128
  groundedCount: 0,
129
129
  lightHits: 0,
130
130
  remHits: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"short-term-store.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/short-term-store.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash, randomUUID } from 'node:crypto';\n\nimport type { MemorySearchOptions } from '../../prompt/memory/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport {\n SHORT_TERM_PROMOTION_LOCK_RELATIVE,\n SHORT_TERM_RECALL_STORE_RELATIVE,\n} from './constants.js';\nimport { buildEntryKey, clamp01, isoDay, normalizeMemoryPath } from './utils.js';\n\nconst log = createLogger('Dreaming:Store');\n\nexport type DreamingStoreEntry = {\n key: string;\n path: string; // workspace-relative: memory/YYYY-MM-DD.md\n startLine: number;\n endLine: number;\n snippet: string;\n\n // ── Signal dimensions ────────────────────────────────────────────────\n /** Number of times this snippet was returned by a memory recall query. */\n recallCount: number;\n /** Number of times recorded from daily log scanning (light sweep). */\n dailyCount: number;\n /** Number of times replayed from grounded context (agent-initiated). */\n groundedCount: number;\n /** Number of times the light phase touched this entry. */\n lightHits: number;\n /** Number of times the REM phase touched this entry. */\n remHits: number;\n /** Cross-phase hit count (light + deep + rem combined touches). */\n phaseHitCount: number;\n /** Weighted aggregate of all signal dimensions. */\n totalSignalCount: number;\n\n // ── Score tracking ───────────────────────────────────────────────────\n totalScore: number;\n maxScore: number;\n queryHashes: string[];\n recallDays: string[];\n\n // ── Timestamps ───────────────────────────────────────────────────────\n firstRecalledAt: string;\n lastRecalledAt: string;\n promotedAt?: string;\n};\n\nexport type DreamingStore = {\n version: 1;\n updatedAt: string;\n entries: Record<string, DreamingStoreEntry>;\n};\n\ntype MemoryMatch = Awaited<ReturnType<typeof import('../../prompt/memory/index.js').memorySearch>>[number];\n\nfunction isDailyWorkspaceMemoryPath(rel: string): boolean {\n const p = normalizeMemoryPath(rel);\n return /^memory\\/\\d{4}-\\d{2}-\\d{2}\\.md$/i.test(p);\n}\n\nfunction hashQuery(query: string): string {\n return createHash('sha1').update(query.trim().toLowerCase()).digest('hex').slice(0, 12);\n}\n\nfunction mergeRecentDistinct(existing: string[], nextValue: string, limit: number): string[] {\n const seen = new Set<string>();\n const normalized = existing\n .filter((v): v is string => typeof v === 'string')\n .map((v) => v.trim())\n .filter((v) => v.length > 0 && !seen.has(v) && (seen.add(v), true));\n if (nextValue && !normalized.includes(nextValue)) {\n normalized.push(nextValue);\n }\n return normalized.length <= limit ? normalized : normalized.slice(-limit);\n}\n\nfunction mergeQueryHashes(existing: string[], nextHash: string): string[] {\n const out = mergeRecentDistinct(existing, nextHash, 32);\n return out;\n}\n\nfunction emptyStore(nowIso: string): DreamingStore {\n return { version: 1, updatedAt: nowIso, entries: {} };\n}\n\nasync function ensureDreamDir(workspaceDir: string): Promise<string> {\n const dir = path.join(workspaceDir, path.dirname(SHORT_TERM_RECALL_STORE_RELATIVE));\n await fs.mkdir(dir, { recursive: true });\n return dir;\n}\n\nasync function readStore(workspaceDir: string, nowIso: string): Promise<DreamingStore> {\n const storePath = path.join(workspaceDir, SHORT_TERM_RECALL_STORE_RELATIVE);\n try {\n const raw = await fs.readFile(storePath, 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== 'object') return emptyStore(nowIso);\n const rec = parsed as Partial<DreamingStore>;\n if (rec.version !== 1 || !rec.entries || typeof rec.entries !== 'object') {\n return emptyStore(nowIso);\n }\n return {\n version: 1,\n updatedAt: typeof rec.updatedAt === 'string' ? rec.updatedAt : nowIso,\n entries: rec.entries as Record<string, DreamingStoreEntry>,\n };\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code === 'ENOENT') return emptyStore(nowIso);\n log.warn({ err, workspaceDir }, 'Failed to read dreaming store; resetting');\n return emptyStore(nowIso);\n }\n}\n\nasync function writeStore(workspaceDir: string, store: DreamingStore): Promise<void> {\n await ensureDreamDir(workspaceDir);\n const storePath = path.join(workspaceDir, SHORT_TERM_RECALL_STORE_RELATIVE);\n const tmp = `${storePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(store, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, storePath);\n}\n\nexport async function recordDreamingRecalls(params: {\n workspaceDir: string;\n query: string;\n matches: MemoryMatch[];\n options?: MemorySearchOptions;\n now?: Date;\n}): Promise<{ recorded: number; skipped: number; storePath: string }> {\n const workspaceDir = params.workspaceDir.trim();\n const query = params.query.trim();\n if (!workspaceDir || !query) {\n return { recorded: 0, skipped: params.matches.length, storePath: SHORT_TERM_RECALL_STORE_RELATIVE };\n }\n const now = params.now ?? new Date();\n const nowIso = now.toISOString();\n const dayBucket = isoDay(now);\n const qHash = hashQuery(query);\n\n const store = await readStore(workspaceDir, nowIso);\n\n let recorded = 0;\n let skipped = 0;\n for (const match of params.matches) {\n const file = typeof match?.file === \"string\" ? match.file : \"\";\n if (!file || !isDailyWorkspaceMemoryPath(file)) {\n skipped += 1;\n continue;\n }\n const lines = typeof match?.lines === \"string\" ? match.lines.trim() : \"\";\n const lineNumbers = Array.isArray(match?.lineNumbers) ? match.lineNumbers : [];\n const startLine = Math.max(1, Math.min(...lineNumbers.filter((n) => Number.isFinite(n) && n > 0)));\n const endLine = Math.max(startLine, Math.max(...lineNumbers.filter((n) => Number.isFinite(n) && n > 0)));\n if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) {\n skipped += 1;\n continue;\n }\n const score = clamp01(Number(match.score));\n const key = buildEntryKey({ path: file, startLine, endLine });\n const existing = store.entries[key];\n const snippet = lines.length > 0 ? lines.slice(0, 360) : file;\n\n const next: DreamingStoreEntry = existing\n ? {\n ...existing,\n snippet,\n recallCount: Math.max(0, Math.floor(existing.recallCount + 1)),\n dailyCount: existing.dailyCount ?? 0,\n groundedCount: existing.groundedCount ?? 0,\n lightHits: existing.lightHits ?? 0,\n remHits: existing.remHits ?? 0,\n phaseHitCount: existing.phaseHitCount ?? 0,\n totalSignalCount: Math.max(0, (existing.totalSignalCount ?? existing.recallCount ?? 0) + 1),\n totalScore: Math.max(0, existing.totalScore + score),\n maxScore: Math.max(existing.maxScore, score),\n queryHashes: mergeQueryHashes(existing.queryHashes ?? [], qHash),\n recallDays: mergeRecentDistinct(existing.recallDays ?? [], dayBucket, 16),\n lastRecalledAt: nowIso,\n }\n : {\n key,\n path: normalizeMemoryPath(file),\n startLine,\n endLine,\n snippet,\n recallCount: 1,\n dailyCount: 0,\n groundedCount: 0,\n lightHits: 0,\n remHits: 0,\n phaseHitCount: 0,\n totalSignalCount: 1,\n totalScore: score,\n maxScore: score,\n queryHashes: [qHash],\n recallDays: [dayBucket],\n firstRecalledAt: nowIso,\n lastRecalledAt: nowIso,\n };\n\n store.entries[key] = next;\n recorded += 1;\n }\n\n if (recorded > 0) {\n store.updatedAt = nowIso;\n await writeStore(workspaceDir, store);\n }\n\n return {\n recorded,\n skipped,\n storePath: SHORT_TERM_RECALL_STORE_RELATIVE,\n };\n}\n\nexport async function withDreamingPromotionLock<T>(\n workspaceDir: string,\n task: () => Promise<T>,\n): Promise<T> {\n const lockPath = path.join(workspaceDir, SHORT_TERM_PROMOTION_LOCK_RELATIVE);\n await ensureDreamDir(workspaceDir);\n\n const startedAt = Date.now();\n const timeoutMs = 10_000;\n const retryDelayMs = 50;\n\n while (true) {\n try {\n const handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}\\n`, 'utf-8').catch(() => undefined);\n try {\n return await task();\n } finally {\n await handle.close().catch(() => undefined);\n await fs.unlink(lockPath).catch(() => undefined);\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code !== 'EEXIST') {\n throw err;\n }\n if (Date.now() - startedAt >= timeoutMs) {\n throw new Error(`Timed out waiting for dreaming promotion lock at ${lockPath}`);\n }\n await new Promise((r) => setTimeout(r, retryDelayMs));\n }\n }\n}\n\nexport async function loadDreamingStore(params: {\n workspaceDir: string;\n}): Promise<{ store: DreamingStore; storePath: string }> {\n const nowIso = new Date().toISOString();\n const store = await readStore(params.workspaceDir, nowIso);\n return { store, storePath: SHORT_TERM_RECALL_STORE_RELATIVE };\n}\n\nexport async function saveDreamingStore(params: {\n workspaceDir: string;\n store: DreamingStore;\n}): Promise<void> {\n await writeStore(params.workspaceDir, params.store);\n}\n\n// ── Phase-level signal helpers ─────────────────────────────────────────\n\ntype PhaseSignalField = 'dailyCount' | 'groundedCount' | 'lightHits' | 'remHits';\n\n/**\n * Increment a phase-specific signal counter on an existing store entry.\n * Also bumps `phaseHitCount` and `totalSignalCount`.\n * Returns `true` if the entry existed and was updated.\n */\nexport function bumpEntryPhaseSignal(\n entry: DreamingStoreEntry,\n field: PhaseSignalField,\n increment = 1,\n): void {\n entry[field] = (entry[field] ?? 0) + increment;\n entry.phaseHitCount = (entry.phaseHitCount ?? 0) + increment;\n entry.totalSignalCount = (entry.totalSignalCount ?? 0) + increment;\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"short-term-store.js","names":[],"sources":["../../../../../src/agent/memory/dreaming/short-term-store.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { createHash, randomUUID } from 'node:crypto';\n\nimport type { MemorySearchOptions } from '../../prompt/memory/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport {\n SHORT_TERM_PROMOTION_LOCK_RELATIVE,\n SHORT_TERM_RECALL_STORE_RELATIVE,\n} from './constants.js';\nimport { buildEntryKey, clamp01, isoDay, normalizeMemoryPath } from './utils.js';\n\nconst log = createLogger('Dreaming:Store');\n\nexport type DreamingStoreEntry = {\n key: string;\n path: string;\n startLine: number;\n endLine: number;\n snippet: string;\n\n // ── Signal dimensions ────────────────────────────────────────────────\n /** Number of times this snippet was returned by a memory recall query. */\n recallCount: number;\n /** Number of times recorded from source-side sweep phases. */\n sourceCount: number;\n /** Number of times replayed from grounded context (agent-initiated). */\n groundedCount: number;\n /** Number of times the light phase touched this entry. */\n lightHits: number;\n /** Number of times the REM phase touched this entry. */\n remHits: number;\n /** Cross-phase hit count (light + deep + rem combined touches). */\n phaseHitCount: number;\n /** Weighted aggregate of all signal dimensions. */\n totalSignalCount: number;\n\n // ── Score tracking ───────────────────────────────────────────────────\n totalScore: number;\n maxScore: number;\n queryHashes: string[];\n recallDays: string[];\n\n // ── Timestamps ───────────────────────────────────────────────────────\n firstRecalledAt: string;\n lastRecalledAt: string;\n promotedAt?: string;\n};\n\nexport type DreamingStore = {\n version: 1;\n updatedAt: string;\n entries: Record<string, DreamingStoreEntry>;\n};\n\ntype MemoryMatch = Awaited<ReturnType<typeof import('../../prompt/memory/index.js').memorySearch>>[number];\n\nfunction isRecordableMemoryPath(rel: string): boolean {\n const p = normalizeMemoryPath(rel);\n return p.length > 0 && !p.startsWith('../') && !path.isAbsolute(p);\n}\n\nfunction hashQuery(query: string): string {\n return createHash('sha1').update(query.trim().toLowerCase()).digest('hex').slice(0, 12);\n}\n\nfunction mergeRecentDistinct(existing: string[], nextValue: string, limit: number): string[] {\n const seen = new Set<string>();\n const normalized = existing\n .filter((v): v is string => typeof v === 'string')\n .map((v) => v.trim())\n .filter((v) => v.length > 0 && !seen.has(v) && (seen.add(v), true));\n if (nextValue && !normalized.includes(nextValue)) {\n normalized.push(nextValue);\n }\n return normalized.length <= limit ? normalized : normalized.slice(-limit);\n}\n\nfunction mergeQueryHashes(existing: string[], nextHash: string): string[] {\n const out = mergeRecentDistinct(existing, nextHash, 32);\n return out;\n}\n\nfunction emptyStore(nowIso: string): DreamingStore {\n return { version: 1, updatedAt: nowIso, entries: {} };\n}\n\nasync function ensureDreamDir(workspaceDir: string): Promise<string> {\n const dir = path.join(workspaceDir, path.dirname(SHORT_TERM_RECALL_STORE_RELATIVE));\n await fs.mkdir(dir, { recursive: true });\n return dir;\n}\n\nasync function readStore(workspaceDir: string, nowIso: string): Promise<DreamingStore> {\n const storePath = path.join(workspaceDir, SHORT_TERM_RECALL_STORE_RELATIVE);\n try {\n const raw = await fs.readFile(storePath, 'utf-8');\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== 'object') return emptyStore(nowIso);\n const rec = parsed as Partial<DreamingStore>;\n if (rec.version !== 1 || !rec.entries || typeof rec.entries !== 'object') {\n return emptyStore(nowIso);\n }\n return {\n version: 1,\n updatedAt: typeof rec.updatedAt === 'string' ? rec.updatedAt : nowIso,\n entries: rec.entries as Record<string, DreamingStoreEntry>,\n };\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code === 'ENOENT') return emptyStore(nowIso);\n log.warn({ err, workspaceDir }, 'Failed to read dreaming store; resetting');\n return emptyStore(nowIso);\n }\n}\n\nasync function writeStore(workspaceDir: string, store: DreamingStore): Promise<void> {\n await ensureDreamDir(workspaceDir);\n const storePath = path.join(workspaceDir, SHORT_TERM_RECALL_STORE_RELATIVE);\n const tmp = `${storePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;\n await fs.writeFile(tmp, `${JSON.stringify(store, null, 2)}\\n`, 'utf-8');\n await fs.rename(tmp, storePath);\n}\n\nexport async function recordDreamingRecalls(params: {\n workspaceDir: string;\n query: string;\n matches: MemoryMatch[];\n options?: MemorySearchOptions;\n now?: Date;\n}): Promise<{ recorded: number; skipped: number; storePath: string }> {\n const workspaceDir = params.workspaceDir.trim();\n const query = params.query.trim();\n if (!workspaceDir || !query) {\n return { recorded: 0, skipped: params.matches.length, storePath: SHORT_TERM_RECALL_STORE_RELATIVE };\n }\n const now = params.now ?? new Date();\n const nowIso = now.toISOString();\n const dayBucket = isoDay(now);\n const qHash = hashQuery(query);\n\n const store = await readStore(workspaceDir, nowIso);\n\n let recorded = 0;\n let skipped = 0;\n for (const match of params.matches) {\n const file = typeof match?.file === \"string\" ? match.file : \"\";\n if (!file || !isRecordableMemoryPath(file)) {\n skipped += 1;\n continue;\n }\n const lines = typeof match?.lines === \"string\" ? match.lines.trim() : \"\";\n const lineNumbers = Array.isArray(match?.lineNumbers) ? match.lineNumbers : [];\n const startLine = Math.max(1, Math.min(...lineNumbers.filter((n) => Number.isFinite(n) && n > 0)));\n const endLine = Math.max(startLine, Math.max(...lineNumbers.filter((n) => Number.isFinite(n) && n > 0)));\n if (!Number.isFinite(startLine) || !Number.isFinite(endLine)) {\n skipped += 1;\n continue;\n }\n const score = clamp01(Number(match.score));\n const key = buildEntryKey({ path: file, startLine, endLine });\n const existing = store.entries[key];\n const snippet = lines.length > 0 ? lines.slice(0, 360) : file;\n\n const next: DreamingStoreEntry = existing\n ? {\n ...existing,\n snippet,\n recallCount: Math.max(0, Math.floor(existing.recallCount + 1)),\n sourceCount: existing.sourceCount ?? 0,\n groundedCount: existing.groundedCount ?? 0,\n lightHits: existing.lightHits ?? 0,\n remHits: existing.remHits ?? 0,\n phaseHitCount: existing.phaseHitCount ?? 0,\n totalSignalCount: Math.max(0, (existing.totalSignalCount ?? existing.recallCount ?? 0) + 1),\n totalScore: Math.max(0, existing.totalScore + score),\n maxScore: Math.max(existing.maxScore, score),\n queryHashes: mergeQueryHashes(existing.queryHashes ?? [], qHash),\n recallDays: mergeRecentDistinct(existing.recallDays ?? [], dayBucket, 16),\n lastRecalledAt: nowIso,\n }\n : {\n key,\n path: normalizeMemoryPath(file),\n startLine,\n endLine,\n snippet,\n recallCount: 1,\n sourceCount: 0,\n groundedCount: 0,\n lightHits: 0,\n remHits: 0,\n phaseHitCount: 0,\n totalSignalCount: 1,\n totalScore: score,\n maxScore: score,\n queryHashes: [qHash],\n recallDays: [dayBucket],\n firstRecalledAt: nowIso,\n lastRecalledAt: nowIso,\n };\n\n store.entries[key] = next;\n recorded += 1;\n }\n\n if (recorded > 0) {\n store.updatedAt = nowIso;\n await writeStore(workspaceDir, store);\n }\n\n return {\n recorded,\n skipped,\n storePath: SHORT_TERM_RECALL_STORE_RELATIVE,\n };\n}\n\nexport async function withDreamingPromotionLock<T>(\n workspaceDir: string,\n task: () => Promise<T>,\n): Promise<T> {\n const lockPath = path.join(workspaceDir, SHORT_TERM_PROMOTION_LOCK_RELATIVE);\n await ensureDreamDir(workspaceDir);\n\n const startedAt = Date.now();\n const timeoutMs = 10_000;\n const retryDelayMs = 50;\n\n while (true) {\n try {\n const handle = await fs.open(lockPath, 'wx');\n await handle.writeFile(`${process.pid}:${Date.now()}\\n`, 'utf-8').catch(() => undefined);\n try {\n return await task();\n } finally {\n await handle.close().catch(() => undefined);\n await fs.unlink(lockPath).catch(() => undefined);\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException | undefined)?.code;\n if (code !== 'EEXIST') {\n throw err;\n }\n if (Date.now() - startedAt >= timeoutMs) {\n throw new Error(`Timed out waiting for dreaming promotion lock at ${lockPath}`);\n }\n await new Promise((r) => setTimeout(r, retryDelayMs));\n }\n }\n}\n\nexport async function loadDreamingStore(params: {\n workspaceDir: string;\n}): Promise<{ store: DreamingStore; storePath: string }> {\n const nowIso = new Date().toISOString();\n const store = await readStore(params.workspaceDir, nowIso);\n return { store, storePath: SHORT_TERM_RECALL_STORE_RELATIVE };\n}\n\nexport async function saveDreamingStore(params: {\n workspaceDir: string;\n store: DreamingStore;\n}): Promise<void> {\n await writeStore(params.workspaceDir, params.store);\n}\n\n// ── Phase-level signal helpers ─────────────────────────────────────────\n\ntype PhaseSignalField = 'sourceCount' | 'groundedCount' | 'lightHits' | 'remHits';\n\n/**\n * Increment a phase-specific signal counter on an existing store entry.\n * Also bumps `phaseHitCount` and `totalSignalCount`.\n * Returns `true` if the entry existed and was updated.\n */\nexport function bumpEntryPhaseSignal(\n entry: DreamingStoreEntry,\n field: PhaseSignalField,\n increment = 1,\n): void {\n entry[field] = (entry[field] ?? 0) + increment;\n entry.phaseHitCount = (entry.phaseHitCount ?? 0) + increment;\n entry.totalSignalCount = (entry.totalSignalCount ?? 0) + increment;\n}\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ type DreamingStoreEntryScoringView = {
4
4
  totalScore: number;
5
5
  lastRecalledAt?: string;
6
6
  queryHashes?: readonly string[];
7
- dailyCount: number;
7
+ sourceCount: number;
8
8
  groundedCount: number;
9
9
  lightHits: number;
10
10
  remHits: number;
@@ -20,7 +20,7 @@ export declare function buildEntryKey(parts: {
20
20
  startLine: number;
21
21
  endLine: number;
22
22
  }): string;
23
- /** YYYY-MM-DD in local time (for daily `memory/YYYY-MM-DD.md` names). */
23
+ /** YYYY-MM-DD in local time. */
24
24
  export declare function isoDay(d: Date): string;
25
25
  export declare function clamp01(value: number): number;
26
26
  /** Fills in deep-phase defaults; mirrors `resolveDreamingConfig` deep object when only partial overrides are given. */