@xopcai/xopc 0.0.117 → 0.0.118

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 (277) hide show
  1. package/README.md +24 -23
  2. package/README.zh-CN.md +45 -42
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BBLhJ2C6.js → agent-avatar-dicebear-dzUrQoeZ.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-BCxZbkOw.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-CBpLONvG.js → app-management-settings-panel-bxYJVJpx.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-CGcc54yj.js → appearance-settings-BCIykXlI.js} +1 -1
  9. package/dist/gateway/static/root/assets/{apps-page-DdDx0V4z.js → apps-page--wMEL00f.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-DZsVqMhU.js → archive-plugin-Cki4SfU2.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CIol6JWX.js → attachment-load-D-KnS2Do.js} +1 -1
  12. package/dist/gateway/static/root/assets/{binary-plugins-B3UauMfp.js → binary-plugins-D2sgvJja.js} +1 -1
  13. package/dist/gateway/static/root/assets/{block-editor-2HJoFchH.js → block-editor-DIq-4Gvb.js} +27 -27
  14. package/dist/gateway/static/root/assets/browser-settings-page-DRhKdn81.js +8 -0
  15. package/dist/gateway/static/root/assets/{capability-presets-api-XQoMTI0A.js → capability-presets-api-CorhiHlg.js} +1 -1
  16. package/dist/gateway/static/root/assets/capability-presets-settings-panel-qFx9Jtce.js +1 -0
  17. package/dist/gateway/static/root/assets/channels-settings-BAwAkqIA.js +1 -0
  18. package/dist/gateway/static/root/assets/connectors-page-BQLcfitM.js +2 -0
  19. package/dist/gateway/static/root/assets/{cron-api-R41aQCX9.js → cron-api-qGwmL-24.js} +1 -1
  20. package/dist/gateway/static/root/assets/cron-page-BBWMAj8-.js +3 -0
  21. package/dist/gateway/static/root/assets/{dreaming-settings-Bceaw1PG.js → dreaming-settings-Dw89Obml.js} +1 -1
  22. package/dist/gateway/static/root/assets/{extension-debug-page-DX5WRE_t.js → extension-debug-page-DYu1KaFQ.js} +1 -1
  23. package/dist/gateway/static/root/assets/{extension-page-Buah7Bw-.js → extension-page-B3W6QwlZ.js} +1 -1
  24. package/dist/gateway/static/root/assets/{extension-settings-page-DuroLVnf.js → extension-settings-page-D7VQ-cxE.js} +1 -1
  25. package/dist/gateway/static/root/assets/{fetch-B5zdl27C.js → fetch-B7xDPu-R.js} +1 -1
  26. package/dist/gateway/static/root/assets/{format-interval-label-Dn_QKIqb.js → format-interval-label-BzxafKxR.js} +1 -1
  27. package/dist/gateway/static/root/assets/{gateway-config-api-gT4ZhE7h.js → gateway-config-api-BTBLSeUu.js} +1 -1
  28. package/dist/gateway/static/root/assets/{gateway-settings-iISWAZRm.js → gateway-settings-Cmwy58rS.js} +1 -1
  29. package/dist/gateway/static/root/assets/{gateway-startup-retry-B3kL8KGY.js → gateway-startup-retry-CYj9FWCp.js} +1 -1
  30. package/dist/gateway/static/root/assets/goal-detail-page-l7mu5GWX.js +1 -0
  31. package/dist/gateway/static/root/assets/{goals-config-api-AR-fVh0P.js → goals-config-api-CQQgzPr3.js} +1 -1
  32. package/dist/gateway/static/root/assets/{goals-page-Cpb21ezg.js → goals-page-BHitvJAv.js} +2 -2
  33. package/dist/gateway/static/root/assets/{goals-settings-CPAuFwoD.js → goals-settings-CYVY4NGp.js} +1 -1
  34. package/dist/gateway/static/root/assets/{heartbeat-config-api-D7bKFEeO.js → heartbeat-config-api-DriO_CN9.js} +1 -1
  35. package/dist/gateway/static/root/assets/heartbeat-settings-CUQTKxg7.js +1 -0
  36. package/dist/gateway/static/root/assets/index-C17Tsd_b.css +1 -0
  37. package/dist/gateway/static/root/assets/{index-CwhK8qCh.js → index-Cc41r16l.js} +120 -51
  38. package/dist/gateway/static/root/assets/{interval-presets-0DtsnxE0.js → interval-presets-DFPCKW_W.js} +1 -1
  39. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BPREtN8B.js → keyboard-shortcuts-settings-CcVcqstx.js} +1 -1
  40. package/dist/gateway/static/root/assets/{logs-page-DefCgF4o.js → logs-page-C2Uqvae9.js} +2 -2
  41. package/dist/gateway/static/root/assets/{markdown-split-ChbR9LGO.js → markdown-split-BwOFrJ2E.js} +1 -1
  42. package/dist/gateway/static/root/assets/{media-plugins-B82oP80n.js → media-plugins-Cnz6Q5G6.js} +1 -1
  43. package/dist/gateway/static/root/assets/messages-B1iSKjiw.js +3 -0
  44. package/dist/gateway/static/root/assets/models-hub-panel-BfLfcta8.js +2 -0
  45. package/dist/gateway/static/root/assets/note-detail-page-BjwOQBfT.js +2 -0
  46. package/dist/gateway/static/root/assets/{note-image-lightbox-CDknITM3.js → note-image-lightbox-B-Svpmza.js} +1 -1
  47. package/dist/gateway/static/root/assets/notes-page-DktdBiwB.js +1 -0
  48. package/dist/gateway/static/root/assets/{preview-open-alternatives-DV3xQsWB.js → preview-open-alternatives-Bss4TiwP.js} +1 -1
  49. package/dist/gateway/static/root/assets/remote-access-hub-rfVx96fq.js +1 -0
  50. package/dist/gateway/static/root/assets/{save-bar-controls-BODCXnvY.js → save-bar-controls-BRNjdgKq.js} +1 -1
  51. package/dist/gateway/static/root/assets/{schedule-field-CgJSCD3B.js → schedule-field-CUCKODde.js} +1 -1
  52. package/dist/gateway/static/root/assets/{schema-form-qtfEI6QM.js → schema-form-Dub9sy8r.js} +1 -1
  53. package/dist/gateway/static/root/assets/sessions-page-DbtMFuuH.js +1 -0
  54. package/dist/gateway/static/root/assets/settings-advanced-gate-5re5gAnP.js +1 -0
  55. package/dist/gateway/static/root/assets/{settings-collapsible-section-BHZKjVcS.js → settings-collapsible-section-BeFLavGi.js} +1 -1
  56. package/dist/gateway/static/root/assets/{settings-form-section-5i35D-J1.js → settings-form-section-dmyaPOTG.js} +1 -1
  57. package/dist/gateway/static/root/assets/settings-page-D-WMyLlj.js +1 -0
  58. package/dist/gateway/static/root/assets/setup-status-panel-Cl-DEJAU.js +1 -0
  59. package/dist/gateway/static/root/assets/{share-preview-page-B0H63tDv.js → share-preview-page-C8glrdqe.js} +1 -1
  60. package/dist/gateway/static/root/assets/shares-settings-CyPVvbLt.js +1 -0
  61. package/dist/gateway/static/root/assets/skill-reload-api-CleTH1oz.js +1 -0
  62. package/dist/gateway/static/root/assets/skills-page-Ck8hdXqR.js +2 -0
  63. package/dist/gateway/static/root/assets/{system-settings-panel-DXs2VmBt.js → system-settings-panel-DI-LN_8G.js} +1 -1
  64. package/dist/gateway/static/root/assets/{typed-models-lib-4gPuydz_.js → typed-models-lib-kX9duch4.js} +1 -1
  65. package/dist/gateway/static/root/assets/{use-channel-catalog-BCjP_VHb.js → use-channel-catalog-DqlWTsDb.js} +1 -1
  66. package/dist/gateway/static/root/assets/user-profile-settings-panel-B-UFPMXy.js +1 -0
  67. package/dist/gateway/static/root/assets/utils-Dm0hKalR.js +1 -0
  68. package/dist/gateway/static/root/assets/voice-api-key-field-C73IVZeC.js +1 -0
  69. package/dist/gateway/static/root/assets/{voice-player-store-BlF9V05n.js → voice-player-store-C_ArLJPM.js} +1 -1
  70. package/dist/gateway/static/root/assets/workflows-page-BtFGp2y_.js +18 -0
  71. package/dist/gateway/static/root/index.html +5 -5
  72. package/dist/package.js +1 -1
  73. package/dist/src/agent/agent-manager.js +2 -1
  74. package/dist/src/agent/agent-manager.js.map +1 -1
  75. package/dist/src/agent/agent-scope.js +0 -2
  76. package/dist/src/agent/agent-scope.js.map +1 -1
  77. package/dist/src/agent/background-review/prompts.d.ts +2 -2
  78. package/dist/src/agent/background-review/prompts.js +2 -2
  79. package/dist/src/agent/background-review/prompts.js.map +1 -1
  80. package/dist/src/agent/background-review/settings.d.ts +1 -1
  81. package/dist/src/agent/background-review/settings.js +7 -8
  82. package/dist/src/agent/background-review/settings.js.map +1 -1
  83. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +1 -0
  84. package/dist/src/agent/bootstrap/bootstrap-cache.js +4 -3
  85. package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
  86. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +4 -0
  87. package/dist/src/agent/bootstrap/bootstrap-files.js +4 -3
  88. package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
  89. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +4 -2
  90. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  91. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +2 -1
  92. package/dist/src/agent/bootstrap/load-bootstrap-files.js +17 -16
  93. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  94. package/dist/src/agent/bootstrap/types.d.ts +1 -1
  95. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  96. package/dist/src/agent/context/workspace.d.ts +4 -2
  97. package/dist/src/agent/context/workspace.js +5 -4
  98. package/dist/src/agent/context/workspace.js.map +1 -1
  99. package/dist/src/agent/embedded/run-for-session.js +4 -1
  100. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  101. package/dist/src/agent/fallback/candidates.js +10 -11
  102. package/dist/src/agent/fallback/candidates.js.map +1 -1
  103. package/dist/src/agent/memory/builtin-memory-store.d.ts +4 -2
  104. package/dist/src/agent/memory/builtin-memory-store.js +11 -6
  105. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  106. package/dist/src/agent/memory/builtin-provider.js +36 -7
  107. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  108. package/dist/src/agent/memory/candidate-extractor.d.ts +6 -0
  109. package/dist/src/agent/memory/candidate-extractor.js +60 -0
  110. package/dist/src/agent/memory/candidate-extractor.js.map +1 -0
  111. package/dist/src/agent/memory/manager.d.ts +2 -1
  112. package/dist/src/agent/memory/manager.js +27 -3
  113. package/dist/src/agent/memory/manager.js.map +1 -1
  114. package/dist/src/agent/memory/memory-config.js +3 -0
  115. package/dist/src/agent/memory/memory-config.js.map +1 -1
  116. package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -1
  117. package/dist/src/agent/memory/types.d.ts +27 -4
  118. package/dist/src/agent/prompt/memory/index.d.ts +4 -2
  119. package/dist/src/agent/prompt/memory/index.js +18 -12
  120. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  121. package/dist/src/agent/prompt/sections/memory-skills.js +1 -1
  122. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  123. package/dist/src/agent/prompt/service-prompt-builder.js +4 -19
  124. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  125. package/dist/src/agent/reply/post-compaction-context.js +1 -3
  126. package/dist/src/agent/reply/post-compaction-context.js.map +1 -1
  127. package/dist/src/agent/reply/startup-context.js +1 -5
  128. package/dist/src/agent/reply/startup-context.js.map +1 -1
  129. package/dist/src/agent/service.d.ts +3 -3
  130. package/dist/src/agent/service.js +7 -8
  131. package/dist/src/agent/service.js.map +1 -1
  132. package/dist/src/agent/tools/curated-memory-tool.js +57 -2
  133. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  134. package/dist/src/agent/tools/web-extract.js +6 -8
  135. package/dist/src/agent/tools/web-extract.js.map +1 -1
  136. package/dist/src/agent-manifest/index.js +2 -2
  137. package/dist/src/agent-manifest/resolver.d.ts +3 -2
  138. package/dist/src/agent-manifest/resolver.js +5 -3
  139. package/dist/src/agent-manifest/resolver.js.map +1 -1
  140. package/dist/src/agent-manifest/schema.d.ts +232 -0
  141. package/dist/src/agent-manifest/schema.js +4 -2
  142. package/dist/src/agent-manifest/schema.js.map +1 -1
  143. package/dist/src/agent-manifest/validator.d.ts +3 -2
  144. package/dist/src/agent-manifest/validator.js +2 -1
  145. package/dist/src/agent-manifest/validator.js.map +1 -1
  146. package/dist/src/channels/pipeline.d.ts +1 -1
  147. package/dist/src/channels/pipeline.js.map +1 -1
  148. package/dist/src/chat-commands/agent-edit.js +0 -1
  149. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  150. package/dist/src/chat-commands/builtins/model.js +2 -2
  151. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  152. package/dist/src/cli/command-manifest.d.ts +1 -1
  153. package/dist/src/cli/command-manifest.js +1 -1
  154. package/dist/src/cli/command-manifest.js.map +1 -1
  155. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  156. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -0
  157. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  158. package/dist/src/cli/commands/doctor/checks/workspace-status.js +0 -1
  159. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  160. package/dist/src/cli/commands/init.js +7 -6
  161. package/dist/src/cli/commands/init.js.map +1 -1
  162. package/dist/src/cli/commands/models.js +13 -31
  163. package/dist/src/cli/commands/models.js.map +1 -1
  164. package/dist/src/cli/commands/onboard/model.js +17 -10
  165. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  166. package/dist/src/cli/commands/onboard.js +2 -2
  167. package/dist/src/cli/commands/onboard.js.map +1 -1
  168. package/dist/src/cli/commands/tui.js +2 -2
  169. package/dist/src/cli/commands/tui.js.map +1 -1
  170. package/dist/src/cli/index.d.ts +1 -0
  171. package/dist/src/cli/index.js +10 -5
  172. package/dist/src/cli/index.js.map +1 -1
  173. package/dist/src/cli/registry.js +1 -1
  174. package/dist/src/cli/registry.js.map +1 -1
  175. package/dist/src/cli/templates.d.ts +1 -1
  176. package/dist/src/cli/templates.js +1 -11
  177. package/dist/src/cli/templates.js.map +1 -1
  178. package/dist/src/commands/agents.config.js +2 -10
  179. package/dist/src/commands/agents.config.js.map +1 -1
  180. package/dist/src/config/agent-profile.js +3 -2
  181. package/dist/src/config/agent-profile.js.map +1 -1
  182. package/dist/src/config/agent-typed-models.js +3 -5
  183. package/dist/src/config/agent-typed-models.js.map +1 -1
  184. package/dist/src/config/index.js +2 -2
  185. package/dist/src/config/paths.d.ts +8 -1
  186. package/dist/src/config/paths.js +16 -3
  187. package/dist/src/config/paths.js.map +1 -1
  188. package/dist/src/config/schema.d.ts +32 -32
  189. package/dist/src/config/schema.js +46 -26
  190. package/dist/src/config/schema.js.map +1 -1
  191. package/dist/src/gateway/agents-admin.d.ts +7 -0
  192. package/dist/src/gateway/agents-admin.js +51 -20
  193. package/dist/src/gateway/agents-admin.js.map +1 -1
  194. package/dist/src/gateway/chat-stream/mapper.js +9 -2
  195. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  196. package/dist/src/gateway/global-defaults-admin.d.ts +36 -0
  197. package/dist/src/gateway/global-defaults-admin.js +146 -0
  198. package/dist/src/gateway/global-defaults-admin.js.map +1 -0
  199. package/dist/src/gateway/hono/routes/agents.js +33 -1
  200. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  201. package/dist/src/gateway/hono/routes/commands-skills.js +4 -5
  202. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  203. package/dist/src/gateway/hono/routes/global-defaults.d.ts +3 -0
  204. package/dist/src/gateway/hono/routes/global-defaults.js +61 -0
  205. package/dist/src/gateway/hono/routes/global-defaults.js.map +1 -0
  206. package/dist/src/gateway/hono/routes/lazy-bundles.js +11 -3
  207. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  208. package/dist/src/gateway/hono/routes/memory.js +75 -4
  209. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  210. package/dist/src/gateway/hono/routes/models.js +1 -1
  211. package/dist/src/gateway/service/marketplace-service.d.ts +4 -4
  212. package/dist/src/gateway/service/marketplace-service.js +11 -7
  213. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  214. package/dist/src/notes/service.js +3 -1
  215. package/dist/src/notes/service.js.map +1 -1
  216. package/dist/src/providers/index.d.ts +4 -5
  217. package/dist/src/providers/index.js +16 -16
  218. package/dist/src/providers/index.js.map +1 -1
  219. package/dist/src/session/session-workspace.js +2 -7
  220. package/dist/src/session/session-workspace.js.map +1 -1
  221. package/dist/src/session/store.js +0 -5
  222. package/dist/src/session/store.js.map +1 -1
  223. package/dist/src/storage/sqlite/index.d.ts +1 -1
  224. package/dist/src/storage/sqlite/index.js +2 -2
  225. package/dist/src/storage/sqlite/memory-index-repository.d.ts +1 -0
  226. package/dist/src/storage/sqlite/memory-index-repository.js +15 -14
  227. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  228. package/dist/src/storage/sqlite/memory-records-repository.d.ts +44 -1
  229. package/dist/src/storage/sqlite/memory-records-repository.js +164 -20
  230. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  231. package/dist/src/storage/sqlite/migrations/014_memory_record_governance.sql +10 -0
  232. package/dist/src/storage/sqlite/migrations/015_memory_trace_feedback.sql +4 -0
  233. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  234. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  235. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  236. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  237. package/dist/src/storage/sqlite/schema.js +1 -1
  238. package/dist/src/tui/backends/embedded-backend.d.ts +3 -0
  239. package/dist/src/tui/backends/embedded-backend.js +37 -20
  240. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  241. package/dist/src/tui/backends/gateway-sse-backend.d.ts +1 -0
  242. package/dist/src/tui/backends/gateway-sse-backend.js +16 -3
  243. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  244. package/dist/src/tui/components/tui-header.d.ts +0 -1
  245. package/dist/src/tui/components/tui-header.js +3 -8
  246. package/dist/src/tui/components/tui-header.js.map +1 -1
  247. package/dist/src/tui/tui-startup-resources.js +2 -1
  248. package/dist/src/tui/tui-startup-resources.js.map +1 -1
  249. package/dist/src/tui/tui-startup-text.js +12 -12
  250. package/dist/src/tui/tui-startup-text.js.map +1 -1
  251. package/dist/src/tui/tui.js +4 -1
  252. package/dist/src/tui/tui.js.map +1 -1
  253. package/package.json +1 -1
  254. package/dist/gateway/static/root/assets/agents-C6xgagZd.js +0 -71
  255. package/dist/gateway/static/root/assets/browser-settings-page-CUOO-PQk.js +0 -8
  256. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CfqF-kGr.js +0 -1
  257. package/dist/gateway/static/root/assets/channels-settings-BYyRzsex.js +0 -1
  258. package/dist/gateway/static/root/assets/connectors-page-DIvEz4NX.js +0 -2
  259. package/dist/gateway/static/root/assets/cron-page-D97nFqQD.js +0 -3
  260. package/dist/gateway/static/root/assets/goal-detail-page-DCUROLMQ.js +0 -1
  261. package/dist/gateway/static/root/assets/heartbeat-settings-CC69vNx0.js +0 -1
  262. package/dist/gateway/static/root/assets/index-CyfhARL-.css +0 -1
  263. package/dist/gateway/static/root/assets/messages-Cf1O9JB0.js +0 -3
  264. package/dist/gateway/static/root/assets/models-hub-panel-DmKiIihT.js +0 -2
  265. package/dist/gateway/static/root/assets/note-detail-page-CxxfLRJZ.js +0 -2
  266. package/dist/gateway/static/root/assets/notes-page-X2slSx7V.js +0 -1
  267. package/dist/gateway/static/root/assets/remote-access-hub-BvmUWqgu.js +0 -1
  268. package/dist/gateway/static/root/assets/sessions-page-B0yESuuL.js +0 -1
  269. package/dist/gateway/static/root/assets/settings-advanced-gate-q2M8RKOo.js +0 -1
  270. package/dist/gateway/static/root/assets/settings-page-CGozabLD.js +0 -1
  271. package/dist/gateway/static/root/assets/setup-status-panel-FoOSe6nU.js +0 -1
  272. package/dist/gateway/static/root/assets/shares-settings-Cy5zWyYQ.js +0 -1
  273. package/dist/gateway/static/root/assets/skill-reload-api-DaZNFro9.js +0 -1
  274. package/dist/gateway/static/root/assets/skills-page-CnwtUzvw.js +0 -2
  275. package/dist/gateway/static/root/assets/voice-api-key-field-DvKiOglO.js +0 -1
  276. package/dist/gateway/static/root/assets/workflows-page-CAVZcONQ.js +0 -18
  277. package/dist/src/agent/context/workspace-templates/USER.md +0 -24
@@ -4,7 +4,8 @@ import { join, relative } from "node:path";
4
4
  import { existsSync, readFileSync, statSync } from "node:fs";
5
5
  import { createHash } from "node:crypto";
6
6
  //#region src/storage/sqlite/memory-index-repository.ts
7
- const CURATED_MEMORY_FILENAMES = new Set(["MEMORY.md", "USER.md"]);
7
+ const AGENT_MEMORY_FILENAME = "MEMORY.md";
8
+ const USER_MEMORY_DISPLAY_PATH = "user/MEMORY.md";
8
9
  const MEMORY_SYNC_CACHE_TTL_MS = 3e4;
9
10
  const memorySyncCache = /* @__PURE__ */ new Map();
10
11
  function resolveAgentIdFromMemoriesDir(memoriesDir) {
@@ -15,13 +16,12 @@ function getDailyMemoryPath(baseDir, date) {
15
16
  const d = date || /* @__PURE__ */ new Date();
16
17
  return join(baseDir, "memory", `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}.md`);
17
18
  }
18
- function getCuratedMemoryPaths(memoriesDir) {
19
- if (!memoriesDir) return [];
20
- return [join(memoriesDir, "MEMORY.md"), join(memoriesDir, "USER.md")].filter((p) => existsSync(p));
19
+ function getCuratedMemoryPaths(memoriesDir, userMemoryPath) {
20
+ return [...memoriesDir ? [join(memoriesDir, AGENT_MEMORY_FILENAME)] : [], ...userMemoryPath ? [userMemoryPath] : []].filter((p) => existsSync(p));
21
21
  }
22
- function collectMemoryPaths(baseDir, memoriesDir) {
22
+ function collectMemoryPaths(baseDir, memoriesDir, userMemoryPath) {
23
23
  const paths = [];
24
- paths.push(...getCuratedMemoryPaths(memoriesDir));
24
+ paths.push(...getCuratedMemoryPaths(memoriesDir, userMemoryPath));
25
25
  const longTermPath = join(baseDir, "MEMORY.md");
26
26
  if (existsSync(longTermPath)) paths.push(longTermPath);
27
27
  if (existsSync(join(baseDir, "memory"))) {
@@ -35,13 +35,14 @@ function collectMemoryPaths(baseDir, memoriesDir) {
35
35
  }
36
36
  return paths;
37
37
  }
38
- function displayPath(baseDir, memoriesDir, absPath) {
38
+ function displayPath(baseDir, memoriesDir, userMemoryPath, absPath) {
39
39
  const normalized = absPath.replace(/\\/g, "/");
40
+ if (userMemoryPath && normalized === userMemoryPath.replace(/\\/g, "/")) return USER_MEMORY_DISPLAY_PATH;
40
41
  if (memoriesDir) {
41
42
  const memoriesRoot = memoriesDir.replace(/\\/g, "/");
42
43
  if (normalized.startsWith(memoriesRoot)) {
43
44
  const filename = normalized.slice(memoriesRoot.length).replace(/^\//, "");
44
- if (CURATED_MEMORY_FILENAMES.has(filename)) return filename;
45
+ if (filename === AGENT_MEMORY_FILENAME) return filename;
45
46
  }
46
47
  }
47
48
  return relative(baseDir, absPath).replace(/\\/g, "/");
@@ -52,11 +53,11 @@ function contentHash(content) {
52
53
  function bm25ToScore(rank) {
53
54
  return 1 / (1 + Math.max(0, -rank));
54
55
  }
55
- function indexFile(db, agentId, baseDir, memoriesDir, absPath) {
56
+ function indexFile(db, agentId, baseDir, memoriesDir, userMemoryPath, absPath) {
56
57
  const content = readFileSync(absPath, "utf-8");
57
58
  const mtimeMs = statSync(absPath).mtimeMs;
58
59
  const hash = contentHash(content);
59
- const relPath = displayPath(baseDir, memoriesDir, absPath);
60
+ const relPath = displayPath(baseDir, memoriesDir, userMemoryPath, absPath);
60
61
  const fileId = `${agentId}:${relPath}`;
61
62
  const existing = db.prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`).get(fileId);
62
63
  if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) return;
@@ -80,11 +81,11 @@ function indexFile(db, agentId, baseDir, memoriesDir, absPath) {
80
81
  }
81
82
  }
82
83
  function syncMemoryIndex(params) {
83
- const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ""}`;
84
+ const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ""}:${params.userMemoryPath ?? ""}`;
84
85
  const now = Date.now();
85
86
  const cached = memorySyncCache.get(cacheKey);
86
87
  if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) return;
87
- const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);
88
+ const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir, params.userMemoryPath);
88
89
  memorySyncCache.set(cacheKey, {
89
90
  timestamp: now,
90
91
  paths
@@ -92,8 +93,8 @@ function syncMemoryIndex(params) {
92
93
  runSqliteWriteTransaction((db) => {
93
94
  const seen = /* @__PURE__ */ new Set();
94
95
  for (const absPath of paths) {
95
- seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);
96
- indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);
96
+ seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, params.userMemoryPath, absPath)}`);
97
+ indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, params.userMemoryPath, absPath);
97
98
  }
98
99
  const stale = db.prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`).all(params.agentId);
99
100
  for (const row of stale) if (!seen.has(row.file_id)) {
@@ -1 +1 @@
1
- {"version":3,"file":"memory-index-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-index-repository.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nexport type MemorySearchHit = {\n path: string;\n lines: string;\n score: number;\n lineNumbers: number[];\n};\n\nconst CURATED_MEMORY_FILENAMES = new Set(['MEMORY.md', 'USER.md']);\nconst MEMORY_SYNC_CACHE_TTL_MS = 30_000;\n\ntype MemorySyncCache = {\n timestamp: number;\n paths: string[];\n};\n\nconst memorySyncCache = new Map<string, MemorySyncCache>();\n\nexport function resolveAgentIdFromMemoriesDir(memoriesDir: string | undefined): string {\n if (!memoriesDir) return 'main';\n const normalized = memoriesDir.replace(/\\\\/g, '/');\n const match = normalized.match(/\\/agents\\/([^/]+)\\/memories\\/?$/);\n return match?.[1] ?? 'main';\n}\n\nfunction getDailyMemoryPath(baseDir: string, date?: Date): string {\n const d = date || new Date();\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return join(baseDir, 'memory', `${year}-${month}-${day}.md`);\n}\n\nfunction getCuratedMemoryPaths(memoriesDir: string | undefined): string[] {\n if (!memoriesDir) return [];\n return [join(memoriesDir, 'MEMORY.md'), join(memoriesDir, 'USER.md')].filter((p) => existsSync(p));\n}\n\nfunction collectMemoryPaths(baseDir: string, memoriesDir?: string): string[] {\n const paths: string[] = [];\n paths.push(...getCuratedMemoryPaths(memoriesDir));\n\n const longTermPath = join(baseDir, 'MEMORY.md');\n if (existsSync(longTermPath)) {\n paths.push(longTermPath);\n }\n\n const memoryDir = join(baseDir, 'memory');\n if (existsSync(memoryDir)) {\n const today = new Date();\n for (let i = 0; i < 30; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n const path = getDailyMemoryPath(baseDir, date);\n if (existsSync(path)) {\n paths.push(path);\n }\n }\n }\n\n return paths;\n}\n\nfunction displayPath(baseDir: string, memoriesDir: string | undefined, absPath: string): string {\n const normalized = absPath.replace(/\\\\/g, '/');\n if (memoriesDir) {\n const memoriesRoot = memoriesDir.replace(/\\\\/g, '/');\n if (normalized.startsWith(memoriesRoot)) {\n const filename = normalized.slice(memoriesRoot.length).replace(/^\\//, '');\n if (CURATED_MEMORY_FILENAMES.has(filename)) {\n return filename;\n }\n }\n }\n return relative(baseDir, absPath).replace(/\\\\/g, '/');\n}\n\nfunction contentHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nfunction bm25ToScore(rank: number): number {\n return 1 / (1 + Math.max(0, -rank));\n}\n\nfunction indexFile(\n db: ReturnType<typeof getSqliteDatabase>,\n agentId: string,\n baseDir: string,\n memoriesDir: string | undefined,\n absPath: string,\n): void {\n const content = readFileSync(absPath, 'utf-8');\n const mtimeMs = statSync(absPath).mtimeMs;\n const hash = contentHash(content);\n const relPath = displayPath(baseDir, memoriesDir, absPath);\n const fileId = `${agentId}:${relPath}`;\n\n const existing = db\n .prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`)\n .get(fileId) as { content_hash: string; mtime_ms: number } | undefined;\n if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) {\n return;\n }\n\n db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(\n fileId,\n );\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);\n\n db.prepare(\n `INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)\n VALUES (?, ?, ?, ?, ?)`,\n ).run(fileId, agentId, relPath, mtimeMs, hash);\n\n const lines = content.split('\\n');\n const insertChunk = db.prepare(\n `INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)\n VALUES (?, ?, ?, ?, ?)`,\n );\n const insertFts = db.prepare(\n `INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim()) continue;\n const lineNo = i + 1;\n const chunkId = `${fileId}:${lineNo}`;\n insertChunk.run(chunkId, fileId, lineNo, lineNo, line);\n insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);\n }\n}\n\nexport function syncMemoryIndex(params: {\n agentId: string;\n workspaceDir: string;\n memoriesDir?: string;\n}): void {\n const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ''}`;\n const now = Date.now();\n const cached = memorySyncCache.get(cacheKey);\n if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) {\n return;\n }\n\n const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir);\n memorySyncCache.set(cacheKey, { timestamp: now, paths });\n runSqliteWriteTransaction((db) => {\n const seen = new Set<string>();\n for (const absPath of paths) {\n seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, absPath)}`);\n indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, absPath);\n }\n\n const stale = db\n .prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`)\n .all(params.agentId) as Array<{ file_id: string }>;\n for (const row of stale) {\n if (!seen.has(row.file_id)) {\n db.prepare(\n `DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`,\n ).run(row.file_id);\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);\n }\n }\n });\n}\n\nexport function searchMemoryIndex(params: {\n agentId: string;\n query: string;\n maxResults?: number;\n minScore?: number;\n}): MemorySearchHit[] {\n const { agentId, query, maxResults = 5, minScore = 0.3 } = params;\n const ftsQuery = escapeFts5Query(query);\n if (!ftsQuery) {\n return [];\n }\n\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank\n FROM memory_fts\n WHERE memory_fts MATCH ? AND agent_id = ?\n ORDER BY rank\n LIMIT ?`,\n )\n .all(ftsQuery, agentId, maxResults * 3) as Array<{\n chunk_id: string;\n path: string;\n start_line: number;\n end_line: number;\n content: string;\n rank: number;\n }>;\n\n const results: MemorySearchHit[] = [];\n for (const row of rows) {\n const score = bm25ToScore(row.rank);\n if (score < minScore) continue;\n results.push({\n path: row.path,\n lines: row.content,\n score,\n lineNumbers: [row.start_line],\n });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, maxResults);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory-index-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-index-repository.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { existsSync, readFileSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\nexport type MemorySearchHit = {\n path: string;\n lines: string;\n score: number;\n lineNumbers: number[];\n};\n\nconst AGENT_MEMORY_FILENAME = 'MEMORY.md';\nconst USER_MEMORY_DISPLAY_PATH = 'user/MEMORY.md';\nconst MEMORY_SYNC_CACHE_TTL_MS = 30_000;\n\ntype MemorySyncCache = {\n timestamp: number;\n paths: string[];\n};\n\nconst memorySyncCache = new Map<string, MemorySyncCache>();\n\nexport function resolveAgentIdFromMemoriesDir(memoriesDir: string | undefined): string {\n if (!memoriesDir) return 'main';\n const normalized = memoriesDir.replace(/\\\\/g, '/');\n const match = normalized.match(/\\/agents\\/([^/]+)\\/memories\\/?$/);\n return match?.[1] ?? 'main';\n}\n\nfunction getDailyMemoryPath(baseDir: string, date?: Date): string {\n const d = date || new Date();\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return join(baseDir, 'memory', `${year}-${month}-${day}.md`);\n}\n\nfunction getCuratedMemoryPaths(memoriesDir: string | undefined, userMemoryPath: string | undefined): string[] {\n return [\n ...(memoriesDir ? [join(memoriesDir, AGENT_MEMORY_FILENAME)] : []),\n ...(userMemoryPath ? [userMemoryPath] : []),\n ].filter((p) => existsSync(p));\n}\n\nfunction collectMemoryPaths(baseDir: string, memoriesDir?: string, userMemoryPath?: string): string[] {\n const paths: string[] = [];\n paths.push(...getCuratedMemoryPaths(memoriesDir, userMemoryPath));\n\n const longTermPath = join(baseDir, 'MEMORY.md');\n if (existsSync(longTermPath)) {\n paths.push(longTermPath);\n }\n\n const memoryDir = join(baseDir, 'memory');\n if (existsSync(memoryDir)) {\n const today = new Date();\n for (let i = 0; i < 30; i++) {\n const date = new Date(today);\n date.setDate(date.getDate() - i);\n const path = getDailyMemoryPath(baseDir, date);\n if (existsSync(path)) {\n paths.push(path);\n }\n }\n }\n\n return paths;\n}\n\nfunction displayPath(\n baseDir: string,\n memoriesDir: string | undefined,\n userMemoryPath: string | undefined,\n absPath: string,\n): string {\n const normalized = absPath.replace(/\\\\/g, '/');\n if (userMemoryPath && normalized === userMemoryPath.replace(/\\\\/g, '/')) {\n return USER_MEMORY_DISPLAY_PATH;\n }\n if (memoriesDir) {\n const memoriesRoot = memoriesDir.replace(/\\\\/g, '/');\n if (normalized.startsWith(memoriesRoot)) {\n const filename = normalized.slice(memoriesRoot.length).replace(/^\\//, '');\n if (filename === AGENT_MEMORY_FILENAME) {\n return filename;\n }\n }\n }\n return relative(baseDir, absPath).replace(/\\\\/g, '/');\n}\n\nfunction contentHash(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nfunction bm25ToScore(rank: number): number {\n return 1 / (1 + Math.max(0, -rank));\n}\n\nfunction indexFile(\n db: ReturnType<typeof getSqliteDatabase>,\n agentId: string,\n baseDir: string,\n memoriesDir: string | undefined,\n userMemoryPath: string | undefined,\n absPath: string,\n): void {\n const content = readFileSync(absPath, 'utf-8');\n const mtimeMs = statSync(absPath).mtimeMs;\n const hash = contentHash(content);\n const relPath = displayPath(baseDir, memoriesDir, userMemoryPath, absPath);\n const fileId = `${agentId}:${relPath}`;\n\n const existing = db\n .prepare(`SELECT content_hash, mtime_ms FROM memory_files WHERE file_id = ?`)\n .get(fileId) as { content_hash: string; mtime_ms: number } | undefined;\n if (existing && existing.content_hash === hash && existing.mtime_ms === mtimeMs) {\n return;\n }\n\n db.prepare(`DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`).run(\n fileId,\n );\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(fileId);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(fileId);\n\n db.prepare(\n `INSERT INTO memory_files (file_id, agent_id, path, mtime_ms, content_hash)\n VALUES (?, ?, ?, ?, ?)`,\n ).run(fileId, agentId, relPath, mtimeMs, hash);\n\n const lines = content.split('\\n');\n const insertChunk = db.prepare(\n `INSERT INTO memory_chunks (chunk_id, file_id, start_line, end_line, content)\n VALUES (?, ?, ?, ?, ?)`,\n );\n const insertFts = db.prepare(\n `INSERT INTO memory_fts (content, chunk_id, agent_id, path, start_line, end_line)\n VALUES (?, ?, ?, ?, ?, ?)`,\n );\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim()) continue;\n const lineNo = i + 1;\n const chunkId = `${fileId}:${lineNo}`;\n insertChunk.run(chunkId, fileId, lineNo, lineNo, line);\n insertFts.run(line, chunkId, agentId, relPath, lineNo, lineNo);\n }\n}\n\nexport function syncMemoryIndex(params: {\n agentId: string;\n workspaceDir: string;\n memoriesDir?: string;\n userMemoryPath?: string;\n}): void {\n const cacheKey = `${params.agentId}:${params.workspaceDir}:${params.memoriesDir ?? ''}:${params.userMemoryPath ?? ''}`;\n const now = Date.now();\n const cached = memorySyncCache.get(cacheKey);\n if (cached && now - cached.timestamp < MEMORY_SYNC_CACHE_TTL_MS) {\n return;\n }\n\n const paths = collectMemoryPaths(params.workspaceDir, params.memoriesDir, params.userMemoryPath);\n memorySyncCache.set(cacheKey, { timestamp: now, paths });\n runSqliteWriteTransaction((db) => {\n const seen = new Set<string>();\n for (const absPath of paths) {\n seen.add(`${params.agentId}:${displayPath(params.workspaceDir, params.memoriesDir, params.userMemoryPath, absPath)}`);\n indexFile(db, params.agentId, params.workspaceDir, params.memoriesDir, params.userMemoryPath, absPath);\n }\n\n const stale = db\n .prepare(`SELECT file_id FROM memory_files WHERE agent_id = ?`)\n .all(params.agentId) as Array<{ file_id: string }>;\n for (const row of stale) {\n if (!seen.has(row.file_id)) {\n db.prepare(\n `DELETE FROM memory_fts WHERE chunk_id IN (SELECT chunk_id FROM memory_chunks WHERE file_id = ?)`,\n ).run(row.file_id);\n db.prepare(`DELETE FROM memory_chunks WHERE file_id = ?`).run(row.file_id);\n db.prepare(`DELETE FROM memory_files WHERE file_id = ?`).run(row.file_id);\n }\n }\n });\n}\n\nexport function searchMemoryIndex(params: {\n agentId: string;\n query: string;\n maxResults?: number;\n minScore?: number;\n}): MemorySearchHit[] {\n const { agentId, query, maxResults = 5, minScore = 0.3 } = params;\n const ftsQuery = escapeFts5Query(query);\n if (!ftsQuery) {\n return [];\n }\n\n const db = getSqliteDatabase();\n const rows = db\n .prepare(\n `SELECT chunk_id, path, start_line, end_line, content, bm25(memory_fts) AS rank\n FROM memory_fts\n WHERE memory_fts MATCH ? AND agent_id = ?\n ORDER BY rank\n LIMIT ?`,\n )\n .all(ftsQuery, agentId, maxResults * 3) as Array<{\n chunk_id: string;\n path: string;\n start_line: number;\n end_line: number;\n content: string;\n rank: number;\n }>;\n\n const results: MemorySearchHit[] = [];\n for (const row of rows) {\n const score = bm25ToScore(row.rank);\n if (score < minScore) continue;\n results.push({\n path: row.path,\n lines: row.content,\n score,\n lineNumbers: [row.start_line],\n });\n }\n\n results.sort((a, b) => b.score - a.score);\n return results.slice(0, maxResults);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { MemoryKind, MemoryRecord, MemorySearchResult, MemorySignal } from '../../agent/memory/types.js';
1
+ import type { MemoryKind, MemoryRecord, MemorySensitivity, MemorySearchResult, MemorySignal, MemoryStatus } from '../../agent/memory/types.js';
2
2
  export interface UpsertMemoryRecordInput {
3
3
  id?: string;
4
4
  providerId: string;
@@ -10,6 +10,11 @@ export interface UpsertMemoryRecordInput {
10
10
  source?: MemoryRecord['source'];
11
11
  confidence?: number;
12
12
  tags?: string[];
13
+ status?: MemoryStatus;
14
+ sensitivity?: MemorySensitivity;
15
+ evidence?: MemoryRecord['evidence'];
16
+ reviewAfter?: string;
17
+ expiresAt?: string;
13
18
  nowMs?: number;
14
19
  }
15
20
  export interface ListMemoryRecordsOptions {
@@ -17,6 +22,7 @@ export interface ListMemoryRecordsOptions {
17
22
  agentId?: string;
18
23
  workspaceId?: string;
19
24
  kind?: MemoryKind;
25
+ status?: MemoryStatus;
20
26
  limit?: number;
21
27
  offset?: number;
22
28
  }
@@ -26,6 +32,7 @@ export interface SearchMemoryRecordsOptions {
26
32
  workspaceId?: string;
27
33
  providerId?: string;
28
34
  kinds?: MemoryKind[];
35
+ statuses?: MemoryStatus[];
29
36
  maxResults?: number;
30
37
  minScore?: number;
31
38
  }
@@ -50,6 +57,15 @@ export interface MemorySignalRowPayload {
50
57
  metadata: Record<string, unknown>;
51
58
  createdAt: string;
52
59
  }
60
+ export type MemoryTraceFeedbackOutcome = 'helpful' | 'not_helpful' | 'mixed' | 'irrelevant';
61
+ export interface MemoryTraceFeedback {
62
+ outcome: MemoryTraceFeedbackOutcome;
63
+ score?: number;
64
+ reason?: string;
65
+ source?: 'user' | 'evaluator' | 'system';
66
+ createdAt: string;
67
+ updatedAt?: string;
68
+ }
53
69
  export interface AppendMemoryTraceEventInput {
54
70
  sessionKey?: string;
55
71
  turnId?: string;
@@ -60,9 +76,18 @@ export interface AppendMemoryTraceEventInput {
60
76
  selectedRecordIds?: string[];
61
77
  skippedReason?: string;
62
78
  error?: string;
79
+ feedback?: MemoryTraceFeedback;
63
80
  durationMs?: number;
64
81
  nowMs?: number;
65
82
  }
83
+ export interface SetMemoryTraceFeedbackInput {
84
+ traceId: string;
85
+ feedback: Omit<MemoryTraceFeedback, 'createdAt' | 'updatedAt'> & {
86
+ createdAt?: string;
87
+ updatedAt?: string;
88
+ };
89
+ nowMs?: number;
90
+ }
66
91
  export interface MemoryTraceEventPayload {
67
92
  traceId: string;
68
93
  sessionKey?: string;
@@ -74,9 +99,20 @@ export interface MemoryTraceEventPayload {
74
99
  selectedRecordIds: string[];
75
100
  skippedReason?: string;
76
101
  error?: string;
102
+ feedback?: MemoryTraceFeedback;
77
103
  durationMs: number;
78
104
  createdAt: string;
79
105
  }
106
+ export interface MemoryRecallFeedbackSummary {
107
+ recordId: string;
108
+ helpful: number;
109
+ notHelpful: number;
110
+ mixed: number;
111
+ irrelevant: number;
112
+ total: number;
113
+ averageScore: number | null;
114
+ lastFeedbackAt?: string;
115
+ }
80
116
  export declare function upsertMemoryRecord(input: UpsertMemoryRecordInput): MemoryRecord;
81
117
  export declare function getMemoryRecord(recordId: string): MemoryRecord | null;
82
118
  export declare function listMemoryRecords(options?: ListMemoryRecordsOptions): MemoryRecord[];
@@ -99,3 +135,10 @@ export declare function listMemoryTraceEvents(options?: {
99
135
  phase?: string;
100
136
  limit?: number;
101
137
  }): MemoryTraceEventPayload[];
138
+ export declare function setMemoryTraceFeedback(input: SetMemoryTraceFeedbackInput): MemoryTraceEventPayload | null;
139
+ export declare function summarizeMemoryRecallFeedback(options?: {
140
+ recordId?: string;
141
+ providerId?: string;
142
+ sessionKey?: string;
143
+ limit?: number;
144
+ }): MemoryRecallFeedbackSummary[];
@@ -10,6 +10,73 @@ function parseStringArray(json) {
10
10
  return [];
11
11
  }
12
12
  }
13
+ function parseEvidence(json) {
14
+ try {
15
+ const parsed = JSON.parse(json);
16
+ if (!Array.isArray(parsed)) return [];
17
+ return parsed.filter((item) => Boolean(item) && typeof item === "object");
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+ function parseMemoryTraceFeedback(json) {
23
+ try {
24
+ const parsed = JSON.parse(json);
25
+ if (!parsed || typeof parsed !== "object") return void 0;
26
+ const obj = parsed;
27
+ const outcome = obj.outcome;
28
+ if (outcome !== "helpful" && outcome !== "not_helpful" && outcome !== "mixed" && outcome !== "irrelevant") return;
29
+ return {
30
+ outcome,
31
+ ...typeof obj.score === "number" ? { score: obj.score } : {},
32
+ ...typeof obj.reason === "string" ? { reason: obj.reason } : {},
33
+ ...obj.source === "user" || obj.source === "evaluator" || obj.source === "system" ? { source: obj.source } : {},
34
+ createdAt: typeof obj.createdAt === "string" ? obj.createdAt : (/* @__PURE__ */ new Date(0)).toISOString(),
35
+ ...typeof obj.updatedAt === "string" ? { updatedAt: obj.updatedAt } : {}
36
+ };
37
+ } catch {
38
+ return;
39
+ }
40
+ }
41
+ function normalizeMemoryTraceFeedback(input, nowMs = Date.now(), existing) {
42
+ const score = typeof input.score === "number" ? Math.max(-1, Math.min(1, input.score)) : void 0;
43
+ const reason = typeof input.reason === "string" && input.reason.trim() ? input.reason.trim().slice(0, 1e3) : void 0;
44
+ const nowIso = new Date(nowMs).toISOString();
45
+ return {
46
+ outcome: input.outcome,
47
+ ...score != null ? { score } : {},
48
+ ...reason ? { reason } : {},
49
+ ...input.source ? { source: input.source } : {},
50
+ createdAt: input.createdAt ?? existing?.createdAt ?? nowIso,
51
+ updatedAt: input.updatedAt ?? nowIso
52
+ };
53
+ }
54
+ function memoryTraceRowToPayload(row) {
55
+ const feedback = parseMemoryTraceFeedback(row.feedback_json);
56
+ return {
57
+ traceId: row.trace_id,
58
+ ...row.session_key ? { sessionKey: row.session_key } : {},
59
+ ...row.turn_id ? { turnId: row.turn_id } : {},
60
+ phase: row.phase,
61
+ providerId: row.provider_id,
62
+ request: parseJsonValue(row.request_json, {}),
63
+ ...row.result_count != null ? { resultCount: row.result_count } : {},
64
+ selectedRecordIds: parseStringArray(row.selected_record_ids_json),
65
+ ...row.skipped_reason ? { skippedReason: row.skipped_reason } : {},
66
+ ...row.error ? { error: row.error } : {},
67
+ ...feedback ? { feedback } : {},
68
+ durationMs: row.duration_ms,
69
+ createdAt: new Date(row.created_at).toISOString()
70
+ };
71
+ }
72
+ function parseOptionalTimestamp(value) {
73
+ if (!value?.trim()) return null;
74
+ const parsed = Date.parse(value);
75
+ return Number.isFinite(parsed) ? parsed : null;
76
+ }
77
+ function timestampToIso(value) {
78
+ return value == null ? void 0 : new Date(value).toISOString();
79
+ }
13
80
  function parseSource(json) {
14
81
  try {
15
82
  const parsed = JSON.parse(json);
@@ -22,6 +89,7 @@ function rowToRecord(row) {
22
89
  return {
23
90
  id: row.record_id,
24
91
  kind: row.kind,
92
+ status: row.status,
25
93
  scope: {
26
94
  agentId: row.agent_id,
27
95
  ...row.workspace_id ? { workspaceId: row.workspace_id } : {},
@@ -30,6 +98,10 @@ function rowToRecord(row) {
30
98
  content: row.content,
31
99
  source: parseSource(row.source_json),
32
100
  ...row.confidence != null ? { confidence: row.confidence } : {},
101
+ sensitivity: row.sensitivity,
102
+ evidence: parseEvidence(row.evidence_json),
103
+ ...timestampToIso(row.review_after) ? { reviewAfter: timestampToIso(row.review_after) } : {},
104
+ ...timestampToIso(row.expires_at) ? { expiresAt: timestampToIso(row.expires_at) } : {},
33
105
  createdAt: new Date(row.created_at).toISOString(),
34
106
  updatedAt: new Date(row.updated_at).toISOString(),
35
107
  tags: parseStringArray(row.tags_json)
@@ -48,6 +120,10 @@ function upsertMemoryRecordFts(db, row) {
48
120
  function upsertMemoryRecord(input) {
49
121
  const id = input.id ?? randomUUID();
50
122
  const now = input.nowMs ?? Date.now();
123
+ const status = input.status ?? "active";
124
+ const sensitivity = input.sensitivity ?? "normal";
125
+ const reviewAfter = parseOptionalTimestamp(input.reviewAfter);
126
+ const expiresAt = parseOptionalTimestamp(input.expiresAt);
51
127
  const source = {
52
128
  ...input.source ?? {},
53
129
  provider: input.source?.provider ?? input.providerId
@@ -55,8 +131,9 @@ function upsertMemoryRecord(input) {
55
131
  runSqliteWriteTransaction((db) => {
56
132
  db.prepare(`INSERT INTO memory_records (
57
133
  record_id, provider_id, kind, agent_id, workspace_id, session_key,
58
- content, source_json, confidence, tags_json, created_at, updated_at
59
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
134
+ content, source_json, confidence, tags_json, status, sensitivity,
135
+ evidence_json, review_after, expires_at, created_at, updated_at
136
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
60
137
  ON CONFLICT(record_id) DO UPDATE SET
61
138
  provider_id = excluded.provider_id,
62
139
  kind = excluded.kind,
@@ -67,7 +144,12 @@ function upsertMemoryRecord(input) {
67
144
  source_json = excluded.source_json,
68
145
  confidence = excluded.confidence,
69
146
  tags_json = excluded.tags_json,
70
- updated_at = excluded.updated_at`).run(id, input.providerId, input.kind, input.agentId, input.workspaceId ?? null, input.sessionKey ?? null, input.content, JSON.stringify(source), input.confidence ?? null, JSON.stringify(input.tags ?? []), now, now);
147
+ status = excluded.status,
148
+ sensitivity = excluded.sensitivity,
149
+ evidence_json = excluded.evidence_json,
150
+ review_after = excluded.review_after,
151
+ expires_at = excluded.expires_at,
152
+ updated_at = excluded.updated_at`).run(id, input.providerId, input.kind, input.agentId, input.workspaceId ?? null, input.sessionKey ?? null, input.content, JSON.stringify(source), input.confidence ?? null, JSON.stringify(input.tags ?? []), status, sensitivity, JSON.stringify(input.evidence ?? []), reviewAfter, expiresAt, now, now);
71
153
  upsertMemoryRecordFts(db, {
72
154
  ...input,
73
155
  id
@@ -76,6 +158,7 @@ function upsertMemoryRecord(input) {
76
158
  return {
77
159
  id,
78
160
  kind: input.kind,
161
+ status,
79
162
  scope: {
80
163
  agentId: input.agentId,
81
164
  ...input.workspaceId ? { workspaceId: input.workspaceId } : {},
@@ -84,6 +167,10 @@ function upsertMemoryRecord(input) {
84
167
  content: input.content,
85
168
  source,
86
169
  ...input.confidence != null ? { confidence: input.confidence } : {},
170
+ sensitivity,
171
+ evidence: input.evidence ?? [],
172
+ ...reviewAfter != null ? { reviewAfter: new Date(reviewAfter).toISOString() } : {},
173
+ ...expiresAt != null ? { expiresAt: new Date(expiresAt).toISOString() } : {},
87
174
  createdAt: new Date(now).toISOString(),
88
175
  updatedAt: new Date(now).toISOString(),
89
176
  tags: input.tags ?? []
@@ -112,6 +199,10 @@ function listMemoryRecords(options = {}) {
112
199
  where.push("kind = ?");
113
200
  params.push(options.kind);
114
201
  }
202
+ if (options.status) {
203
+ where.push("status = ?");
204
+ params.push(options.status);
205
+ }
115
206
  const limit = Math.max(1, Math.min(500, options.limit ?? 100));
116
207
  const offset = Math.max(0, options.offset ?? 0);
117
208
  return getSqliteDatabase().prepare(`SELECT * FROM memory_records
@@ -140,6 +231,9 @@ function searchMemoryRecords(options) {
140
231
  filters.push(`f.kind IN (${options.kinds.map(() => "?").join(", ")})`);
141
232
  params.push(...options.kinds);
142
233
  }
234
+ const statuses = options.statuses && options.statuses.length > 0 ? options.statuses : ["active"];
235
+ filters.push(`r.status IN (${statuses.map(() => "?").join(", ")})`);
236
+ params.push(...statuses);
143
237
  const maxResults = Math.max(1, Math.min(50, options.maxResults ?? 5));
144
238
  const minScore = options.minScore ?? 0;
145
239
  return getSqliteDatabase().prepare(`SELECT
@@ -254,11 +348,12 @@ function setMemoryProviderState(providerId, scopeKey, state) {
254
348
  function appendMemoryTraceEvent(input) {
255
349
  const id = randomUUID();
256
350
  const now = input.nowMs ?? Date.now();
351
+ const feedback = input.feedback ? normalizeMemoryTraceFeedback(input.feedback, now) : void 0;
257
352
  runSqliteWriteTransaction((db) => {
258
353
  db.prepare(`INSERT INTO memory_trace_events (
259
354
  trace_id, session_key, turn_id, phase, provider_id, request_json,
260
- result_count, selected_record_ids_json, skipped_reason, error, duration_ms, created_at
261
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.sessionKey ?? null, input.turnId ?? null, input.phase, input.providerId, JSON.stringify(input.request ?? {}), input.resultCount ?? null, JSON.stringify(input.selectedRecordIds ?? []), input.skippedReason ?? null, input.error ?? null, Math.max(0, Math.floor(input.durationMs ?? 0)), now);
355
+ result_count, selected_record_ids_json, skipped_reason, error, feedback_json, duration_ms, created_at
356
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.sessionKey ?? null, input.turnId ?? null, input.phase, input.providerId, JSON.stringify(input.request ?? {}), input.resultCount ?? null, JSON.stringify(input.selectedRecordIds ?? []), input.skippedReason ?? null, input.error ?? null, JSON.stringify(feedback ?? {}), Math.max(0, Math.floor(input.durationMs ?? 0)), now);
262
357
  });
263
358
  return id;
264
359
  }
@@ -281,20 +376,69 @@ function listMemoryTraceEvents(options = {}) {
281
376
  return getSqliteDatabase().prepare(`SELECT * FROM memory_trace_events
282
377
  ${where.length > 0 ? `WHERE ${where.join(" AND ")}` : ""}
283
378
  ORDER BY created_at DESC
284
- LIMIT ?`).all(...params, limit).map((row) => ({
285
- traceId: row.trace_id,
286
- ...row.session_key ? { sessionKey: row.session_key } : {},
287
- ...row.turn_id ? { turnId: row.turn_id } : {},
288
- phase: row.phase,
289
- providerId: row.provider_id,
290
- request: parseJsonValue(row.request_json, {}),
291
- ...row.result_count != null ? { resultCount: row.result_count } : {},
292
- selectedRecordIds: parseStringArray(row.selected_record_ids_json),
293
- ...row.skipped_reason ? { skippedReason: row.skipped_reason } : {},
294
- ...row.error ? { error: row.error } : {},
295
- durationMs: row.duration_ms,
296
- createdAt: new Date(row.created_at).toISOString()
297
- }));
379
+ LIMIT ?`).all(...params, limit).map(memoryTraceRowToPayload);
380
+ }
381
+ function setMemoryTraceFeedback(input) {
382
+ const existing = getSqliteDatabase().prepare(`SELECT * FROM memory_trace_events WHERE trace_id = ?`).get(input.traceId);
383
+ if (!existing) return null;
384
+ const feedback = normalizeMemoryTraceFeedback(input.feedback, input.nowMs, parseMemoryTraceFeedback(existing.feedback_json));
385
+ runSqliteWriteTransaction((db) => {
386
+ db.prepare(`UPDATE memory_trace_events SET feedback_json = ? WHERE trace_id = ?`).run(JSON.stringify(feedback), input.traceId);
387
+ });
388
+ return memoryTraceRowToPayload({
389
+ ...existing,
390
+ feedback_json: JSON.stringify(feedback)
391
+ });
392
+ }
393
+ function summarizeMemoryRecallFeedback(options = {}) {
394
+ const where = ["phase IN (?, ?)"];
395
+ const params = ["search", "inject"];
396
+ if (options.providerId) {
397
+ where.push("provider_id = ?");
398
+ params.push(options.providerId);
399
+ }
400
+ if (options.sessionKey) {
401
+ where.push("session_key = ?");
402
+ params.push(options.sessionKey);
403
+ }
404
+ const limit = Math.max(1, Math.min(5e3, options.limit ?? 1e3));
405
+ const rows = getSqliteDatabase().prepare(`SELECT * FROM memory_trace_events
406
+ WHERE ${where.join(" AND ")}
407
+ ORDER BY created_at DESC
408
+ LIMIT ?`).all(...params, limit);
409
+ const summaries = /* @__PURE__ */ new Map();
410
+ for (const row of rows) {
411
+ const feedback = parseMemoryTraceFeedback(row.feedback_json);
412
+ if (!feedback) continue;
413
+ const recordIds = parseStringArray(row.selected_record_ids_json);
414
+ for (const recordId of recordIds) {
415
+ if (options.recordId && recordId !== options.recordId) continue;
416
+ const current = summaries.get(recordId) ?? {
417
+ recordId,
418
+ helpful: 0,
419
+ notHelpful: 0,
420
+ mixed: 0,
421
+ irrelevant: 0,
422
+ total: 0,
423
+ averageScore: null,
424
+ scoreTotal: 0,
425
+ scoreCount: 0
426
+ };
427
+ if (feedback.outcome === "helpful") current.helpful += 1;
428
+ if (feedback.outcome === "not_helpful") current.notHelpful += 1;
429
+ if (feedback.outcome === "mixed") current.mixed += 1;
430
+ if (feedback.outcome === "irrelevant") current.irrelevant += 1;
431
+ current.total += 1;
432
+ if (typeof feedback.score === "number") {
433
+ current.scoreTotal += feedback.score;
434
+ current.scoreCount += 1;
435
+ current.averageScore = current.scoreTotal / current.scoreCount;
436
+ }
437
+ current.lastFeedbackAt ??= feedback.updatedAt ?? feedback.createdAt;
438
+ summaries.set(recordId, current);
439
+ }
440
+ }
441
+ return [...summaries.values()].map(({ scoreTotal: _scoreTotal, scoreCount: _scoreCount, ...summary }) => summary).sort((a, b) => b.total - a.total);
298
442
  }
299
443
  function parseJsonValue(json, fallback) {
300
444
  try {
@@ -304,6 +448,6 @@ function parseJsonValue(json, fallback) {
304
448
  }
305
449
  }
306
450
  //#endregion
307
- export { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryRecord, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, searchMemoryRecords, setMemoryProviderState, upsertMemoryRecord };
451
+ export { appendMemorySignal, appendMemoryTraceEvent, deleteMemoryRecord, getMemoryProviderState, getMemoryRecord, listMemoryRecords, listMemorySignals, listMemoryTraceEvents, searchMemoryRecords, setMemoryProviderState, setMemoryTraceFeedback, summarizeMemoryRecallFeedback, upsertMemoryRecord };
308
452
 
309
453
  //# sourceMappingURL=memory-records-repository.js.map