@xopcai/xopc 0.0.121 → 0.0.122

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 (293) hide show
  1. package/README.md +23 -3
  2. package/README.zh-CN.md +23 -3
  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-4AW4JgSU.js → agent-avatar-dicebear-CK3s5cJo.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-SsQrj9B-.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-CE6GkGU2.js → app-management-settings-panel-CWsNHtTs.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-BmaUjghw.js → appearance-settings-C4b8y6iZ.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CYb6fame.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-CX4_KWut.js → archive-plugin-DAtNW3Ia.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-jf-PIIUU.js → attachment-load-Dm-RY54y.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-BKHewSVT.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-DpOOq1nk.js +1 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-DG9XQikd.js → binary-plugins-BG6Xnk71.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-Up_VIxLJ.js → block-editor-DfndiO3h.js} +28 -28
  16. package/dist/gateway/static/root/assets/browser-settings-page-9nXxgh4u.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-CGM4OyMw.js → capability-presets-api-Cx93GLdw.js} +1 -1
  18. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-CzWt0LBb.js → capability-presets-settings-panel-D528_YFy.js} +1 -1
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-BEByL4_o.js → channel-recipient-api-DdPTtEs8.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-Ck-3h5lI.js +1 -0
  21. package/dist/gateway/static/root/assets/connectors-page-DL-fAqE_.js +2 -0
  22. package/dist/gateway/static/root/assets/directory-picker-path-field-D835EHJd.js +1 -0
  23. package/dist/gateway/static/root/assets/dreaming-settings-CCa1F7Fg.js +1 -0
  24. package/dist/gateway/static/root/assets/{extension-debug-page-DZxa_j7-.js → extension-debug-page-W2ITCPSA.js} +1 -1
  25. package/dist/gateway/static/root/assets/{extension-page-CseziW53.js → extension-page-DrvUytvn.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-settings-page-B_9J-xyo.js → extension-settings-page-qM8aLT5u.js} +1 -1
  27. package/dist/gateway/static/root/assets/{fetch-Cs4ck8zA.js → fetch-ovkvM8KQ.js} +1 -1
  28. package/dist/gateway/static/root/assets/{gateway-config-api-Dl223a7r.js → gateway-config-api-BB3biuD0.js} +1 -1
  29. package/dist/gateway/static/root/assets/gateway-settings-mmmnIH27.js +1 -0
  30. package/dist/gateway/static/root/assets/{gateway-startup-retry-IvePwjFE.js → gateway-startup-retry-CanQ8UcR.js} +1 -1
  31. package/dist/gateway/static/root/assets/goal-create-dialog-CNqNdEkQ.js +1 -0
  32. package/dist/gateway/static/root/assets/goal-detail-page-Ceu5zrN6.js +1 -0
  33. package/dist/gateway/static/root/assets/{goals-config-api-CUCP6yCl.js → goals-config-api-BBOX6mUl.js} +1 -1
  34. package/dist/gateway/static/root/assets/goals-page-BP1kfvWv.js +2 -0
  35. package/dist/gateway/static/root/assets/{goals-settings-Dj87qPxv.js → goals-settings-Bh3A7OZV.js} +1 -1
  36. package/dist/gateway/static/root/assets/heartbeat-settings-YoYgKlfX.js +1 -0
  37. package/dist/gateway/static/root/assets/index-DdqSO9R2.js +191 -0
  38. package/dist/gateway/static/root/assets/index-jGB-2nI-.css +1 -0
  39. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DJgYw0nB.js → keyboard-shortcuts-settings-B4TKJHla.js} +1 -1
  40. package/dist/gateway/static/root/assets/logs-page-BgVk5DvZ.js +2 -0
  41. package/dist/gateway/static/root/assets/{markdown-split-gnQ_EiGo.js → markdown-split-DcFtdLci.js} +1 -1
  42. package/dist/gateway/static/root/assets/{media-plugins-CQV-mgJn.js → media-plugins-B6SmeLVB.js} +1 -1
  43. package/dist/gateway/static/root/assets/messages-B5O4OIEo.js +3 -0
  44. package/dist/gateway/static/root/assets/models-hub-panel-BU0x8PGP.js +2 -0
  45. package/dist/gateway/static/root/assets/notes-page-D6JYVP4I.js +1 -0
  46. package/dist/gateway/static/root/assets/notes-workbench-mqRJYnJS.js +2 -0
  47. package/dist/gateway/static/root/assets/{preview-open-alternatives-BPMXC-2u.js → preview-open-alternatives-C29O19s7.js} +1 -1
  48. package/dist/gateway/static/root/assets/project-detail-page-DOTgzoeh.js +1 -0
  49. package/dist/gateway/static/root/assets/projects-page-DGUIb4y5.js +1 -0
  50. package/dist/gateway/static/root/assets/remote-access-hub-DVKKUj3u.js +1 -0
  51. package/dist/gateway/static/root/assets/{save-bar-controls-BEHqwZjz.js → save-bar-controls-B4ad9GfB.js} +1 -1
  52. package/dist/gateway/static/root/assets/{schedule-field-CMY25m97.js → schedule-field-DdYncfLR.js} +1 -1
  53. package/dist/gateway/static/root/assets/{schema-form-CxjxsFfg.js → schema-form-BMTrDE-7.js} +1 -1
  54. package/dist/gateway/static/root/assets/segmented-styles-BL8oLBEp.js +1 -0
  55. package/dist/gateway/static/root/assets/sessions-page-BVbzUWxW.js +1 -0
  56. package/dist/gateway/static/root/assets/settings-advanced-gate-DrNNoSqE.js +1 -0
  57. package/dist/gateway/static/root/assets/{settings-collapsible-section-s-kiLAxP.js → settings-collapsible-section-MwTW2eK4.js} +1 -1
  58. package/dist/gateway/static/root/assets/{settings-form-section-CIxIEYxU.js → settings-form-section-Dg6LBbcr.js} +1 -1
  59. package/dist/gateway/static/root/assets/settings-page-CMDqgeMR.js +1 -0
  60. package/dist/gateway/static/root/assets/settings-page-layout-BX4T-OLF.js +1 -0
  61. package/dist/gateway/static/root/assets/setup-status-panel-Ce1pcFtR.js +1 -0
  62. package/dist/gateway/static/root/assets/share-preview-page-DWE-dUFh.js +2 -0
  63. package/dist/gateway/static/root/assets/shares-settings-aKSraR8l.js +1 -0
  64. package/dist/gateway/static/root/assets/skill-reload-api-CS-FU_B-.js +1 -0
  65. package/dist/gateway/static/root/assets/skills-page-BaF3u0LA.js +2 -0
  66. package/dist/gateway/static/root/assets/{system-settings-panel-Czjf0kLJ.js → system-settings-panel-Dd6Y35Cm.js} +1 -1
  67. package/dist/gateway/static/root/assets/{typed-models-lib-Cmt8SYdI.js → typed-models-lib-Cx6XV5A2.js} +1 -1
  68. package/dist/gateway/static/root/assets/{use-channel-catalog-DyM-ckEQ.js → use-channel-catalog-D4sMbmy7.js} +1 -1
  69. package/dist/gateway/static/root/assets/{user-profile-settings-panel-BygLv8vm.js → user-profile-settings-panel-Bx-hjMQc.js} +1 -1
  70. package/dist/gateway/static/root/assets/{utils-CloW8coB.js → utils-D7b_vZnv.js} +1 -1
  71. package/dist/gateway/static/root/assets/voice-api-key-field-CkhbRt1q.js +1 -0
  72. package/dist/gateway/static/root/assets/workflow-run-setup-panel--TdohF5N.js +3 -0
  73. package/dist/gateway/static/root/assets/workflow-start-dialog-B0lavx_o.js +1 -0
  74. package/dist/gateway/static/root/assets/workflows-page-CZR05Bu_.js +18 -0
  75. package/dist/gateway/static/root/index.html +5 -5
  76. package/dist/package.js +1 -1
  77. package/dist/src/agent/agent-manager.d.ts +2 -0
  78. package/dist/src/agent/agent-manager.js +47 -7
  79. package/dist/src/agent/agent-manager.js.map +1 -1
  80. package/dist/src/agent/context/project-context.d.ts +19 -0
  81. package/dist/src/agent/context/project-context.js +90 -0
  82. package/dist/src/agent/context/project-context.js.map +1 -0
  83. package/dist/src/agent/goals/goal-locale.js +2 -2
  84. package/dist/src/agent/memory/types.d.ts +1 -0
  85. package/dist/src/agent/prompt/service-prompt-builder.d.ts +1 -0
  86. package/dist/src/agent/prompt/service-prompt-builder.js +2 -0
  87. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  88. package/dist/src/agent/prompt/system-prompt-params.d.ts +2 -0
  89. package/dist/src/agent/prompt/system-prompt-params.js +1 -0
  90. package/dist/src/agent/prompt/system-prompt-params.js.map +1 -1
  91. package/dist/src/agent/prompt/system-prompt.d.ts +1 -0
  92. package/dist/src/agent/prompt/system-prompt.js +2 -1
  93. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  94. package/dist/src/agent/service.js +4 -3
  95. package/dist/src/agent/service.js.map +1 -1
  96. package/dist/src/agent/session/session-config-service.js +6 -1
  97. package/dist/src/agent/session/session-config-service.js.map +1 -1
  98. package/dist/src/agent/session/session-hydrator.js +7 -3
  99. package/dist/src/agent/session/session-hydrator.js.map +1 -1
  100. package/dist/src/agent/session/session-inspector.js +9 -5
  101. package/dist/src/agent/session/session-inspector.js.map +1 -1
  102. package/dist/src/agent/starter-agents.js +5 -34
  103. package/dist/src/agent/starter-agents.js.map +1 -1
  104. package/dist/src/agent/workflow/index.js +2 -2
  105. package/dist/src/agent/workflow/runtime.js +1 -1
  106. package/dist/src/automations/api/routes.js +13 -2
  107. package/dist/src/automations/api/routes.js.map +1 -1
  108. package/dist/src/automations/domain/types.d.ts +2 -0
  109. package/dist/src/automations/domain/validation.d.ts +3 -0
  110. package/dist/src/automations/domain/validation.js +1 -0
  111. package/dist/src/automations/domain/validation.js.map +1 -1
  112. package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -0
  113. package/dist/src/automations/service/action-executor.js +3 -1
  114. package/dist/src/automations/service/action-executor.js.map +1 -1
  115. package/dist/src/automations/service/automation-service.d.ts +4 -1
  116. package/dist/src/automations/service/automation-service.js +2 -2
  117. package/dist/src/automations/service/automation-service.js.map +1 -1
  118. package/dist/src/automations/storage/automation-repository.d.ts +3 -1
  119. package/dist/src/automations/storage/automation-repository.js +7 -5
  120. package/dist/src/automations/storage/automation-repository.js.map +1 -1
  121. package/dist/src/automations/storage/automation-run-repository.d.ts +1 -0
  122. package/dist/src/automations/storage/automation-run-repository.js +12 -1
  123. package/dist/src/automations/storage/automation-run-repository.js.map +1 -1
  124. package/dist/src/chat-commands/context.js +2 -1
  125. package/dist/src/chat-commands/context.js.map +1 -1
  126. package/dist/src/cli/command-loaders.js +1 -0
  127. package/dist/src/cli/command-loaders.js.map +1 -1
  128. package/dist/src/cli/command-manifest.js +4 -0
  129. package/dist/src/cli/command-manifest.js.map +1 -1
  130. package/dist/src/cli/commands/agent.js +2 -2
  131. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  132. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  133. package/dist/src/cli/commands/goal.js +27 -4
  134. package/dist/src/cli/commands/goal.js.map +1 -1
  135. package/dist/src/cli/commands/models.js +1 -1
  136. package/dist/src/cli/commands/onboard.js +1 -1
  137. package/dist/src/cli/commands/profile.js +1 -1
  138. package/dist/src/cli/commands/project.d.ts +4 -0
  139. package/dist/src/cli/commands/project.js +239 -0
  140. package/dist/src/cli/commands/project.js.map +1 -0
  141. package/dist/src/cli/commands/tunnel.js +1 -1
  142. package/dist/src/cli/commands/update.js +1 -1
  143. package/dist/src/cli/extension-cli-register.js +1 -1
  144. package/dist/src/config/agent-profile.js +1 -1
  145. package/dist/src/config/index.js +1 -1
  146. package/dist/src/gateway/agents-admin.js +1 -1
  147. package/dist/src/gateway/hono/routes/goals.js +51 -4
  148. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  149. package/dist/src/gateway/hono/routes/index.js +2 -0
  150. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  151. package/dist/src/gateway/hono/routes/memory.js +5 -1
  152. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  153. package/dist/src/gateway/hono/routes/notes.js +5 -0
  154. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  155. package/dist/src/gateway/hono/routes/projects.d.ts +3 -0
  156. package/dist/src/gateway/hono/routes/projects.js +578 -0
  157. package/dist/src/gateway/hono/routes/projects.js.map +1 -0
  158. package/dist/src/gateway/hono/routes/sessions.js +47 -7
  159. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  160. package/dist/src/gateway/hono/routes/workflows.js +27 -4
  161. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  162. package/dist/src/gateway/run-loop.js +1 -1
  163. package/dist/src/gateway/service.d.ts +3 -0
  164. package/dist/src/gateway/service.js +10 -3
  165. package/dist/src/gateway/service.js.map +1 -1
  166. package/dist/src/goals/goal-service.d.ts +1 -1
  167. package/dist/src/goals/goal-service.js +2 -1
  168. package/dist/src/goals/goal-service.js.map +1 -1
  169. package/dist/src/goals/goal-store.d.ts +1 -1
  170. package/dist/src/goals/goal-store.js +12 -6
  171. package/dist/src/goals/goal-store.js.map +1 -1
  172. package/dist/src/goals/goal-workflow-judge.js +1 -1
  173. package/dist/src/goals/types.d.ts +3 -0
  174. package/dist/src/i18n/goals-bundle.js +1 -1
  175. package/dist/src/i18n/index.js +1 -1
  176. package/dist/src/i18n/share-tool-bundle.js +2 -2
  177. package/dist/src/mcp/channel-bridge.js +1 -1
  178. package/dist/src/notes/agent-context.js +2 -2
  179. package/dist/src/projects/automation-bind.d.ts +1 -0
  180. package/dist/src/projects/automation-bind.js +16 -0
  181. package/dist/src/projects/automation-bind.js.map +1 -0
  182. package/dist/src/projects/goal-bind.d.ts +4 -0
  183. package/dist/src/projects/goal-bind.js +40 -0
  184. package/dist/src/projects/goal-bind.js.map +1 -0
  185. package/dist/src/projects/index.d.ts +11 -0
  186. package/dist/src/projects/index.js +11 -0
  187. package/dist/src/projects/memory-bind.d.ts +1 -0
  188. package/dist/src/projects/memory-bind.js +16 -0
  189. package/dist/src/projects/memory-bind.js.map +1 -0
  190. package/dist/src/projects/project-agent.d.ts +10 -0
  191. package/dist/src/projects/project-agent.js +27 -0
  192. package/dist/src/projects/project-agent.js.map +1 -0
  193. package/dist/src/projects/project-loop.d.ts +58 -0
  194. package/dist/src/projects/project-loop.js +118 -0
  195. package/dist/src/projects/project-loop.js.map +1 -0
  196. package/dist/src/projects/project-service.d.ts +26 -0
  197. package/dist/src/projects/project-service.js +94 -0
  198. package/dist/src/projects/project-service.js.map +1 -0
  199. package/dist/src/projects/project-store.d.ts +31 -0
  200. package/dist/src/projects/project-store.js +193 -0
  201. package/dist/src/projects/project-store.js.map +1 -0
  202. package/dist/src/projects/session-bind.d.ts +5 -0
  203. package/dist/src/projects/session-bind.js +46 -0
  204. package/dist/src/projects/session-bind.js.map +1 -0
  205. package/dist/src/projects/types.d.ts +60 -0
  206. package/dist/src/projects/types.js +1 -0
  207. package/dist/src/projects/workflow-bind.d.ts +1 -0
  208. package/dist/src/projects/workflow-bind.js +16 -0
  209. package/dist/src/projects/workflow-bind.js.map +1 -0
  210. package/dist/src/projects/workspace.d.ts +5 -0
  211. package/dist/src/projects/workspace.js +25 -0
  212. package/dist/src/projects/workspace.js.map +1 -0
  213. package/dist/src/session/index.d.ts +1 -1
  214. package/dist/src/session/index.js +3 -3
  215. package/dist/src/session/session-workspace.d.ts +4 -2
  216. package/dist/src/session/session-workspace.js +10 -3
  217. package/dist/src/session/session-workspace.js.map +1 -1
  218. package/dist/src/session/types.d.ts +3 -0
  219. package/dist/src/session/types.js.map +1 -1
  220. package/dist/src/storage/sqlite/memory-records-repository.d.ts +3 -0
  221. package/dist/src/storage/sqlite/memory-records-repository.js +16 -5
  222. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  223. package/dist/src/storage/sqlite/migrations/019_projects.sql +40 -0
  224. package/dist/src/storage/sqlite/migrations/020_project_default_agent.sql +1 -0
  225. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  226. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  227. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  228. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  229. package/dist/src/storage/sqlite/notes-repository.js +20 -4
  230. package/dist/src/storage/sqlite/notes-repository.js.map +1 -1
  231. package/dist/src/storage/sqlite/row-mappers.d.ts +2 -0
  232. package/dist/src/storage/sqlite/row-mappers.js +2 -0
  233. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  234. package/dist/src/storage/sqlite/schema.js +1 -1
  235. package/dist/src/storage/sqlite/session-repository.js +10 -5
  236. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  237. package/dist/src/storage/sqlite/transcript-repository.js +8 -0
  238. package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
  239. package/dist/src/tui/backends/embedded-backend.js +1 -1
  240. package/dist/src/tui/tui-commands.js +145 -0
  241. package/dist/src/tui/tui-commands.js.map +1 -1
  242. package/dist/src/workflows/domain/run.d.ts +1 -0
  243. package/dist/src/workflows/domain/run.js.map +1 -1
  244. package/dist/src/workflows/index.js +1 -1
  245. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  246. package/dist/src/workflows/service/workflow-run-service.js +18 -4
  247. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  248. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -0
  249. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  250. package/dist/src/workflows/service/workflow-session-bridge.js +3 -0
  251. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  252. package/dist/src/workflows/store/run-index-store.d.ts +1 -0
  253. package/dist/src/workflows/store/run-index-store.js +13 -3
  254. package/dist/src/workflows/store/run-index-store.js.map +1 -1
  255. package/dist/src/workflows/store/run-store.d.ts +3 -1
  256. package/dist/src/workflows/store/run-store.js +5 -2
  257. package/dist/src/workflows/store/run-store.js.map +1 -1
  258. package/package.json +10 -1
  259. package/dist/gateway/static/root/assets/agents-2SVUUPlp.js +0 -2
  260. package/dist/gateway/static/root/assets/apps-page-BWeQ1I49.js +0 -1
  261. package/dist/gateway/static/root/assets/automation-suggestion-card-BHk5rtJz.js +0 -1
  262. package/dist/gateway/static/root/assets/automations-page-QHotl53D.js +0 -1
  263. package/dist/gateway/static/root/assets/browser-settings-page-Cmwi6IIQ.js +0 -8
  264. package/dist/gateway/static/root/assets/channels-settings-BOMCUe2J.js +0 -1
  265. package/dist/gateway/static/root/assets/connectors-page-C-Dexk_F.js +0 -2
  266. package/dist/gateway/static/root/assets/dreaming-settings-WPEj8pir.js +0 -1
  267. package/dist/gateway/static/root/assets/gateway-settings-DdzbtW9R.js +0 -1
  268. package/dist/gateway/static/root/assets/goal-detail-page-Dxldogms.js +0 -1
  269. package/dist/gateway/static/root/assets/goals-page-DU5Nd6Xp.js +0 -2
  270. package/dist/gateway/static/root/assets/heartbeat-settings-Cgm5JmwH.js +0 -1
  271. package/dist/gateway/static/root/assets/index-BU1pvxmS.js +0 -191
  272. package/dist/gateway/static/root/assets/index-l54WfSqe.css +0 -1
  273. package/dist/gateway/static/root/assets/logs-page-C10aS4XO.js +0 -2
  274. package/dist/gateway/static/root/assets/messages-C6Kc4Jhf.js +0 -3
  275. package/dist/gateway/static/root/assets/models-hub-panel-B35CAfg6.js +0 -2
  276. package/dist/gateway/static/root/assets/note-detail-page-Brlwse8x.js +0 -2
  277. package/dist/gateway/static/root/assets/note-image-lightbox-BthwKjLA.js +0 -1
  278. package/dist/gateway/static/root/assets/note-time-hm6JO_Wi.js +0 -1
  279. package/dist/gateway/static/root/assets/notes-page-CoAwRc7L.js +0 -1
  280. package/dist/gateway/static/root/assets/remote-access-hub-B36RQ05h.js +0 -1
  281. package/dist/gateway/static/root/assets/sessions-page-73THChnj.js +0 -1
  282. package/dist/gateway/static/root/assets/settings-advanced-gate-CR9VsY-R.js +0 -1
  283. package/dist/gateway/static/root/assets/settings-page-BJ1AhfKI.js +0 -1
  284. package/dist/gateway/static/root/assets/settings-page-layout--6qT7ZJa.js +0 -1
  285. package/dist/gateway/static/root/assets/setup-status-panel-C1TtS1vJ.js +0 -1
  286. package/dist/gateway/static/root/assets/share-preview-page-BZADSbS1.js +0 -2
  287. package/dist/gateway/static/root/assets/shares-settings-gqC8Rmhy.js +0 -1
  288. package/dist/gateway/static/root/assets/skill-reload-api-C9P-WYvS.js +0 -1
  289. package/dist/gateway/static/root/assets/skills-page-CEpSvOhF.js +0 -2
  290. package/dist/gateway/static/root/assets/voice-api-key-field-BsoqJba6.js +0 -1
  291. package/dist/gateway/static/root/assets/voice-player-store-DduWlJYV.js +0 -1
  292. package/dist/gateway/static/root/assets/workflow-run-setup-panel-CcQeX6l5.js +0 -3
  293. package/dist/gateway/static/root/assets/workflows-page-CeA8A9Ef.js +0 -18
@@ -0,0 +1,60 @@
1
+ import type { PaginatedResult } from '../session/types.js';
2
+ export type ProjectStatus = 'active' | 'paused' | 'archived';
3
+ export interface Project {
4
+ id: string;
5
+ name: string;
6
+ slug: string;
7
+ description?: string;
8
+ status: ProjectStatus;
9
+ defaultAgentId?: string;
10
+ workspaceRoot?: string;
11
+ brief?: string;
12
+ instructions?: string;
13
+ createdAt: number;
14
+ updatedAt: number;
15
+ lastActiveAt?: number;
16
+ }
17
+ export interface ProjectWithDetails extends Project {
18
+ sessionCount: number;
19
+ goalCount: number;
20
+ activeGoalCount: number;
21
+ recentSessions: Array<{
22
+ key: string;
23
+ name?: string;
24
+ updatedAt: string;
25
+ agentId: string;
26
+ }>;
27
+ recentWorkflowRuns: Array<{
28
+ runId: string;
29
+ definitionId: string;
30
+ status: string;
31
+ createdAt: number;
32
+ }>;
33
+ }
34
+ export interface ProjectListQuery {
35
+ status?: ProjectStatus | ProjectStatus[];
36
+ search?: string;
37
+ sortBy?: 'updatedAt' | 'createdAt' | 'name';
38
+ sortOrder?: 'asc' | 'desc';
39
+ limit?: number;
40
+ offset?: number;
41
+ }
42
+ export interface CreateProjectInput {
43
+ name: string;
44
+ slug?: string;
45
+ description?: string;
46
+ defaultAgentId?: string;
47
+ workspaceRoot?: string;
48
+ brief?: string;
49
+ instructions?: string;
50
+ }
51
+ export interface UpdateProjectInput {
52
+ name?: string;
53
+ description?: string | null;
54
+ defaultAgentId?: string | null;
55
+ status?: ProjectStatus;
56
+ workspaceRoot?: string | null;
57
+ brief?: string | null;
58
+ instructions?: string | null;
59
+ }
60
+ export type ProjectListResult = PaginatedResult<Project>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function bindWorkflowRunToProject(runId: string, projectId: string): void;
@@ -0,0 +1,16 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ //#region src/projects/workflow-bind.ts
3
+ function bindWorkflowRunToProject(runId, projectId) {
4
+ const db = getSqliteDatabase();
5
+ if (!db.prepare(`SELECT 1 FROM projects WHERE project_id = ?`).get(projectId)) throw new Error(`Project not found: ${projectId}`);
6
+ if (!db.prepare(`SELECT 1 FROM workflow_runs WHERE run_id = ?`).get(runId)) throw new Error(`Workflow run not found: ${runId}`);
7
+ runSqliteWriteTransaction((tx) => {
8
+ const now = Date.now();
9
+ tx.prepare(`UPDATE workflow_runs SET project_id = ? WHERE run_id = ?`).run(projectId, runId);
10
+ tx.prepare(`UPDATE projects SET last_active_at = ?, updated_at = ? WHERE project_id = ?`).run(now, now, projectId);
11
+ });
12
+ }
13
+ //#endregion
14
+ export { bindWorkflowRunToProject };
15
+
16
+ //# sourceMappingURL=workflow-bind.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workflow-bind.js","names":[],"sources":["../../../src/projects/workflow-bind.ts"],"sourcesContent":["import { getSqliteDatabase, runSqliteWriteTransaction } from '../storage/sqlite/transaction.js';\n\nexport function bindWorkflowRunToProject(runId: string, projectId: string): void {\n const db = getSqliteDatabase();\n if (!db.prepare(`SELECT 1 FROM projects WHERE project_id = ?`).get(projectId)) throw new Error(`Project not found: ${projectId}`);\n if (!db.prepare(`SELECT 1 FROM workflow_runs WHERE run_id = ?`).get(runId)) throw new Error(`Workflow run not found: ${runId}`);\n runSqliteWriteTransaction((tx) => {\n const now = Date.now();\n tx.prepare(`UPDATE workflow_runs SET project_id = ? WHERE run_id = ?`).run(projectId, runId);\n tx.prepare(`UPDATE projects SET last_active_at = ?, updated_at = ? WHERE project_id = ?`).run(now, now, projectId);\n });\n}\n"],"mappings":";;AAEA,SAAgB,yBAAyB,OAAe,WAAyB;CAC/E,MAAM,KAAK,mBAAmB;AAC9B,KAAI,CAAC,GAAG,QAAQ,8CAA8C,CAAC,IAAI,UAAU,CAAE,OAAM,IAAI,MAAM,sBAAsB,YAAY;AACjI,KAAI,CAAC,GAAG,QAAQ,+CAA+C,CAAC,IAAI,MAAM,CAAE,OAAM,IAAI,MAAM,2BAA2B,QAAQ;AAC/H,4BAA2B,OAAO;EAChC,MAAM,MAAM,KAAK,KAAK;AACtB,KAAG,QAAQ,2DAA2D,CAAC,IAAI,WAAW,MAAM;AAC5F,KAAG,QAAQ,8EAA8E,CAAC,IAAI,KAAK,KAAK,UAAU;GAClH"}
@@ -0,0 +1,5 @@
1
+ import type { Config } from '../config/schema.js';
2
+ import type { Project } from './types.js';
3
+ export declare function resolveProjectWorkspacePath(config: Config, sessionKey: string, project: Project | null): string;
4
+ export declare function getProjectForSession(sessionKey: string): Project | null;
5
+ export declare function getProjectWorkspacePathForSession(sessionKey: string): string | null;
@@ -0,0 +1,25 @@
1
+ import { resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
2
+ import { isXopcDatabaseOpen } from "../storage/sqlite/connection.js";
3
+ import { getSessionMetadata } from "../storage/sqlite/session-repository.js";
4
+ import "../storage/sqlite/index.js";
5
+ import { projectWorkspacePath } from "../session/session-workspace.js";
6
+ import { ProjectStore } from "./project-store.js";
7
+ //#region src/projects/workspace.ts
8
+ function resolveProjectWorkspacePath(config, sessionKey, project) {
9
+ const projectWorkspace = projectWorkspacePath(project);
10
+ if (projectWorkspace) return projectWorkspace;
11
+ return resolveEffectiveAgentProfileForSession(config, sessionKey).resolvedWorkspacePath;
12
+ }
13
+ function getProjectForSession(sessionKey) {
14
+ if (!isXopcDatabaseOpen()) return null;
15
+ const projectId = getSessionMetadata(sessionKey)?.projectId;
16
+ if (!projectId) return null;
17
+ return new ProjectStore().get(projectId);
18
+ }
19
+ function getProjectWorkspacePathForSession(sessionKey) {
20
+ return projectWorkspacePath(getProjectForSession(sessionKey));
21
+ }
22
+ //#endregion
23
+ export { getProjectForSession, getProjectWorkspacePathForSession, resolveProjectWorkspacePath };
24
+
25
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","names":[],"sources":["../../../src/projects/workspace.ts"],"sourcesContent":["import { resolveEffectiveAgentProfileForSession } from '../config/agent-profile.js';\nimport type { Config } from '../config/schema.js';\nimport {\n getSessionMetadata,\n isXopcDatabaseOpen,\n} from '../storage/sqlite/index.js';\nimport { projectWorkspacePath } from '../session/session-workspace.js';\nimport { ProjectStore } from './project-store.js';\nimport type { Project } from './types.js';\n\nexport function resolveProjectWorkspacePath(\n config: Config,\n sessionKey: string,\n project: Project | null,\n): string {\n const projectWorkspace = projectWorkspacePath(project);\n if (projectWorkspace) {\n return projectWorkspace;\n }\n return resolveEffectiveAgentProfileForSession(config, sessionKey).resolvedWorkspacePath;\n}\n\nexport function getProjectForSession(sessionKey: string): Project | null {\n if (!isXopcDatabaseOpen()) {\n return null;\n }\n const projectId = getSessionMetadata(sessionKey)?.projectId;\n if (!projectId) {\n return null;\n }\n return new ProjectStore().get(projectId);\n}\n\nexport function getProjectWorkspacePathForSession(sessionKey: string): string | null {\n return projectWorkspacePath(getProjectForSession(sessionKey));\n}\n"],"mappings":";;;;;;;AAUA,SAAgB,4BACd,QACA,YACA,SACQ;CACR,MAAM,mBAAmB,qBAAqB,QAAQ;AACtD,KAAI,iBACF,QAAO;AAET,QAAO,uCAAuC,QAAQ,WAAW,CAAC;;AAGpE,SAAgB,qBAAqB,YAAoC;AACvE,KAAI,CAAC,oBAAoB,CACvB,QAAO;CAET,MAAM,YAAY,mBAAmB,WAAW,EAAE;AAClD,KAAI,CAAC,UACH,QAAO;AAET,QAAO,IAAI,cAAc,CAAC,IAAI,UAAU;;AAG1C,SAAgB,kCAAkC,YAAmC;AACnF,QAAO,qBAAqB,qBAAqB,WAAW,CAAC"}
@@ -5,7 +5,7 @@ export type { SessionStoreOptions } from './store.js';
5
5
  export { SessionConfigStore, resolveThinkingLevel, resolveReasoningLevel, resolveVerboseLevel } from './config-store.js';
6
6
  export { resolveEffectiveThinkingLevel, resolveEffectiveReasoningLevel } from './thinking-resolve.js';
7
7
  export type { SessionAgentConfig } from './config-types.js';
8
- export { normalizeWorkingDirectoryInput, effectiveWorkspacePathForSession, } from './session-workspace.js';
8
+ export { normalizeWorkingDirectoryInput, effectiveWorkspacePathForSession, projectWorkspacePath, } from './session-workspace.js';
9
9
  export { SessionStatus, type SessionMetadata, type SessionDetail, type SessionListQuery, type PaginatedResult, type SessionStats, type ExportFormat, type SessionExport, type SessionTranscriptSummary, type CompactionCheckpointSummary, type CompactionCheckpointDetail, } from './types.js';
10
10
  export { normalizeCompactionCheckpointId } from './compaction-checkpoints.js';
11
11
  export { shouldSkipWebchatInboundByAbortCutoff } from './abort-cutoff.js';
@@ -1,6 +1,7 @@
1
- import { emitSessionTranscriptUpdate, onSessionTranscriptUpdate } from "./transcript-events.js";
2
1
  import { SessionStatus } from "./types.js";
3
2
  import { buildSessionContextForLlm, isTranscriptContextEntry, mergeLlmMessagesPreservingContextRows, transcriptRowsFromJsonArray } from "./session-context-for-llm.js";
3
+ import { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput, projectWorkspacePath } from "./session-workspace.js";
4
+ import { emitSessionTranscriptUpdate, onSessionTranscriptUpdate } from "./transcript-events.js";
4
5
  import { fallbackTitleFromMessages, generateSessionTitleFromMessages, getSessionTitleSource, isWebchatSessionKey, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, provisionalTitleFromUserText, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm } from "./session-title.js";
5
6
  import { normalizeCompactionCheckpointId } from "./compaction-checkpoints.js";
6
7
  import { SessionStore } from "./store.js";
@@ -8,7 +9,6 @@ import { applySessionPatchToMetadata } from "./patch-metadata.js";
8
9
  import { SessionIndex } from "./manager.js";
9
10
  import { SessionConfigStore, resolveReasoningLevel, resolveThinkingLevel, resolveVerboseLevel } from "./config-store.js";
10
11
  import { resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel } from "./thinking-resolve.js";
11
- import { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput } from "./session-workspace.js";
12
12
  import { shouldSkipWebchatInboundByAbortCutoff } from "./abort-cutoff.js";
13
13
  import { DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, evaluateSessionFreshness, resolveDailyResetAtMs, resolveSessionResetPolicy } from "./reset-policy.js";
14
14
  import { resolveChannelResetConfig, resolveSessionResetType } from "./reset-type.js";
@@ -18,4 +18,4 @@ import { DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, bareResetAckMessage, ma
18
18
  import { initSessionTurn } from "./init-session-turn.js";
19
19
  import { flattenMessageContent, messagesToClientHistory } from "./client-history.js";
20
20
  import { CURRENT_SESSION_TRANSCRIPT_VERSION, XOPC_SESSION_TRANSCRIPT_TYPE } from "./transcript-format.js";
21
- export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getSessionTitleSource, initSessionTurn, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeCompactionCheckpointId, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, provisionalTitleFromUserText, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
21
+ export { CURRENT_SESSION_TRANSCRIPT_VERSION, DEFAULT_IDLE_MINUTES, DEFAULT_RESET_AT_HOUR, DEFAULT_RESET_MODE, DEFAULT_RESET_TRIGGERS, RESET_OVERLAP_COMMANDS, SessionConfigStore, SessionIndex, SessionStatus, SessionStore, XOPC_SESSION_TRANSCRIPT_TYPE, applySessionPatchToMetadata, bareResetAckMessage, buildSessionContextForLlm, effectiveWorkspacePathForSession, emitSessionTranscriptUpdate, evaluateSessionFreshness, fallbackTitleFromMessages, flattenMessageContent, generateSessionTitleFromMessages, getSessionTitleSource, initSessionTurn, isTranscriptContextEntry, isWebchatSessionKey, matchResetTriggers, maybeRefineSessionTitleWithLlm, maybeSetProvisionalSessionTitle, mergeLlmMessagesPreservingContextRows, messagesToClientHistory, normalizeCompactionCheckpointId, normalizeWorkingDirectoryInput, onSessionTranscriptUpdate, projectWorkspacePath, provisionalTitleFromUserText, resolveChannelResetConfig, resolveDailyResetAtMs, resolveEffectiveReasoningLevel, resolveEffectiveThinkingLevel, resolveReasoningLevel, resolveResetTriggers, resolveSession, resolveSessionKeyForRequest, resolveSessionLifecycleTimestamps, resolveSessionResetPolicy, resolveSessionResetType, resolveThinkingLevel, resolveVerboseLevel, sanitizeSessionTitle, shouldAutoTitleSessionKey, shouldRefineSessionTitleWithLlm, shouldSkipResetOverlapCommand, shouldSkipWebchatInboundByAbortCutoff, stripLeadingEnvelopeTimestamp, transcriptRowsFromJsonArray };
@@ -2,6 +2,7 @@
2
2
  * Per-session markdown workspace override (stored in SessionAgentConfig).
3
3
  */
4
4
  import type { Config } from '../config/schema.js';
5
+ import type { Project } from '../projects/types.js';
5
6
  import type { SessionAgentConfig } from './config-types.js';
6
7
  /**
7
8
  * Normalize user input for `workingDirectoryOverride`. Rejects empty and filesystem roots.
@@ -13,7 +14,8 @@ export declare function normalizeWorkingDirectoryInput(raw: string): {
13
14
  ok: false;
14
15
  error: string;
15
16
  };
17
+ export declare function projectWorkspacePath(project: Pick<Project, 'workspaceRoot'> | null | undefined): string | null;
16
18
  /**
17
- * Resolved markdown workspace for tools/shell: session override or merged agent profile default.
19
+ * Resolved markdown workspace for tools/shell: project workspace, session override, or merged agent profile default.
18
20
  */
19
- export declare function effectiveWorkspacePathForSession(cfg: Config, sessionKey: string, sessionAgentConfig: SessionAgentConfig | null | undefined): string;
21
+ export declare function effectiveWorkspacePathForSession(cfg: Config, sessionKey: string, sessionAgentConfig: SessionAgentConfig | null | undefined, project?: Pick<Project, 'workspaceRoot'> | null): string;
@@ -23,16 +23,23 @@ function normalizeWorkingDirectoryInput(raw) {
23
23
  path: normalized
24
24
  };
25
25
  }
26
+ function projectWorkspacePath(project) {
27
+ const raw = project?.workspaceRoot?.trim();
28
+ if (!raw) return null;
29
+ return normalizeWorkspaceDir(resolveUserPath(raw));
30
+ }
26
31
  /**
27
- * Resolved markdown workspace for tools/shell: session override or merged agent profile default.
32
+ * Resolved markdown workspace for tools/shell: project workspace, session override, or merged agent profile default.
28
33
  */
29
- function effectiveWorkspacePathForSession(cfg, sessionKey, sessionAgentConfig) {
34
+ function effectiveWorkspacePathForSession(cfg, sessionKey, sessionAgentConfig, project) {
30
35
  const base = resolveEffectiveAgentProfileForSession(cfg, sessionKey).resolvedWorkspacePath;
36
+ const projectWorkspace = projectWorkspacePath(project);
37
+ if (projectWorkspace) return projectWorkspace;
31
38
  const o = sessionAgentConfig?.workingDirectoryOverride?.trim();
32
39
  if (!o) return base;
33
40
  return normalizeWorkspaceDir(resolveUserPath(o)) ?? base;
34
41
  }
35
42
  //#endregion
36
- export { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput };
43
+ export { effectiveWorkspacePathForSession, normalizeWorkingDirectoryInput, projectWorkspacePath };
37
44
 
38
45
  //# sourceMappingURL=session-workspace.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-workspace.js","names":[],"sources":["../../../src/session/session-workspace.ts"],"sourcesContent":["/**\n * Per-session markdown workspace override (stored in SessionAgentConfig).\n */\n\nimport type { Config } from '../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../config/agent-profile.js';\nimport { resolveUserPath } from '../agent/agent-scope.js';\nimport { normalizeWorkspaceDir } from '../config/workspace-path.js';\nimport type { SessionAgentConfig } from './config-types.js';\n\n/**\n * Normalize user input for `workingDirectoryOverride`. Rejects empty and filesystem roots.\n */\nexport function normalizeWorkingDirectoryInput(raw: string): { ok: true; path: string } | { ok: false; error: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n return { ok: false, error: 'working directory is empty' };\n }\n const resolved = resolveUserPath(trimmed);\n const normalized = normalizeWorkspaceDir(resolved);\n if (!normalized) {\n return { ok: false, error: 'invalid working directory path' };\n }\n return { ok: true, path: normalized };\n}\n\n/**\n * Resolved markdown workspace for tools/shell: session override or merged agent profile default.\n */\nexport function effectiveWorkspacePathForSession(\n cfg: Config,\n sessionKey: string,\n sessionAgentConfig: SessionAgentConfig | null | undefined,\n): string {\n const base = resolveEffectiveAgentProfileForSession(cfg, sessionKey).resolvedWorkspacePath;\n const o = sessionAgentConfig?.workingDirectoryOverride?.trim();\n if (!o) {\n return base;\n }\n const resolved = resolveUserPath(o);\n const normalized = normalizeWorkspaceDir(resolved);\n return normalized ?? base;\n}\n"],"mappings":";;;;kBAM0D;qBACU;;;;AAMpE,SAAgB,+BAA+B,KAAwE;CACrH,MAAM,UAAU,IAAI,MAAM;AAC1B,KAAI,CAAC,QACH,QAAO;EAAE,IAAI;EAAO,OAAO;EAA8B;CAG3D,MAAM,aAAa,sBADF,gBAAgB,QACgB,CAAC;AAClD,KAAI,CAAC,WACH,QAAO;EAAE,IAAI;EAAO,OAAO;EAAkC;AAE/D,QAAO;EAAE,IAAI;EAAM,MAAM;EAAY;;;;;AAMvC,SAAgB,iCACd,KACA,YACA,oBACQ;CACR,MAAM,OAAO,uCAAuC,KAAK,WAAW,CAAC;CACrE,MAAM,IAAI,oBAAoB,0BAA0B,MAAM;AAC9D,KAAI,CAAC,EACH,QAAO;AAIT,QADmB,sBADF,gBAAgB,EACgB,CAChC,IAAI"}
1
+ {"version":3,"file":"session-workspace.js","names":[],"sources":["../../../src/session/session-workspace.ts"],"sourcesContent":["/**\n * Per-session markdown workspace override (stored in SessionAgentConfig).\n */\n\nimport type { Config } from '../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../config/agent-profile.js';\nimport { resolveUserPath } from '../agent/agent-scope.js';\nimport { normalizeWorkspaceDir } from '../config/workspace-path.js';\nimport type { Project } from '../projects/types.js';\nimport type { SessionAgentConfig } from './config-types.js';\n\n/**\n * Normalize user input for `workingDirectoryOverride`. Rejects empty and filesystem roots.\n */\nexport function normalizeWorkingDirectoryInput(raw: string): { ok: true; path: string } | { ok: false; error: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n return { ok: false, error: 'working directory is empty' };\n }\n const resolved = resolveUserPath(trimmed);\n const normalized = normalizeWorkspaceDir(resolved);\n if (!normalized) {\n return { ok: false, error: 'invalid working directory path' };\n }\n return { ok: true, path: normalized };\n}\n\nexport function projectWorkspacePath(\n project: Pick<Project, 'workspaceRoot'> | null | undefined,\n): string | null {\n const raw = project?.workspaceRoot?.trim();\n if (!raw) return null;\n const resolved = resolveUserPath(raw);\n return normalizeWorkspaceDir(resolved);\n}\n\n/**\n * Resolved markdown workspace for tools/shell: project workspace, session override, or merged agent profile default.\n */\nexport function effectiveWorkspacePathForSession(\n cfg: Config,\n sessionKey: string,\n sessionAgentConfig: SessionAgentConfig | null | undefined,\n project?: Pick<Project, 'workspaceRoot'> | null,\n): string {\n const base = resolveEffectiveAgentProfileForSession(cfg, sessionKey).resolvedWorkspacePath;\n const projectWorkspace = projectWorkspacePath(project);\n if (projectWorkspace) {\n return projectWorkspace;\n }\n const o = sessionAgentConfig?.workingDirectoryOverride?.trim();\n if (!o) {\n return base;\n }\n const resolved = resolveUserPath(o);\n const normalized = normalizeWorkspaceDir(resolved);\n return normalized ?? base;\n}\n"],"mappings":";;;;kBAM0D;qBACU;;;;AAOpE,SAAgB,+BAA+B,KAAwE;CACrH,MAAM,UAAU,IAAI,MAAM;AAC1B,KAAI,CAAC,QACH,QAAO;EAAE,IAAI;EAAO,OAAO;EAA8B;CAG3D,MAAM,aAAa,sBADF,gBAAgB,QACgB,CAAC;AAClD,KAAI,CAAC,WACH,QAAO;EAAE,IAAI;EAAO,OAAO;EAAkC;AAE/D,QAAO;EAAE,IAAI;EAAM,MAAM;EAAY;;AAGvC,SAAgB,qBACd,SACe;CACf,MAAM,MAAM,SAAS,eAAe,MAAM;AAC1C,KAAI,CAAC,IAAK,QAAO;AAEjB,QAAO,sBADU,gBAAgB,IACI,CAAC;;;;;AAMxC,SAAgB,iCACd,KACA,YACA,oBACA,SACQ;CACR,MAAM,OAAO,uCAAuC,KAAK,WAAW,CAAC;CACrE,MAAM,mBAAmB,qBAAqB,QAAQ;AACtD,KAAI,iBACF,QAAO;CAET,MAAM,IAAI,oBAAoB,0BAA0B,MAAM;AAC9D,KAAI,CAAC,EACH,QAAO;AAIT,QADmB,sBADF,gBAAgB,EACgB,CAChC,IAAI"}
@@ -93,6 +93,8 @@ export interface SessionMetadata {
93
93
  sourceChannel: string;
94
94
  sourceChatId: string;
95
95
  customData?: Record<string, unknown>;
96
+ /** Optional project grouping for sessions, goals, workflows, and related context. */
97
+ projectId?: string;
96
98
  /** Routing metadata */
97
99
  routing?: SessionRoutingMeta;
98
100
  /** Session statistics */
@@ -147,6 +149,7 @@ export interface SessionListQuery {
147
149
  search?: string;
148
150
  sessionTypes?: SessionType[];
149
151
  includeHidden?: boolean;
152
+ projectId?: string;
150
153
  sortBy?: 'updatedAt' | 'createdAt' | 'messageCount' | 'lastAccessedAt';
151
154
  sortOrder?: 'asc' | 'desc';
152
155
  limit?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/session/types.ts"],"sourcesContent":["// Session management types\n\nimport type { TranscriptStoredRow } from './session-context-for-llm.js';\n\nexport interface Message {\n role: 'system' | 'user' | 'assistant' | 'tool' | 'toolResult';\n /** Plain string or structured content blocks (tool calls, multimodal). */\n content: string | unknown[];\n timestamp?: string;\n tool_call_id?: string;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n }>;\n tool_call_id$?: string;\n toolName?: string;\n isError?: boolean;\n name?: string;\n /** Token usage from the LLM response (assistant messages only). */\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n totalTokens?: number;\n };\n /** Inbound attachment metadata (no base64). */\n media?: Array<{\n id: string;\n bucket: string;\n type: string;\n mimeType: string;\n name: string;\n size: number;\n uri: string;\n path: string;\n }>;\n}\n\n/** Session status enum */\nexport enum SessionStatus {\n ACTIVE = 'active',\n IDLE = 'idle',\n ARCHIVED = 'archived',\n PINNED = 'pinned',\n}\n\n/** Session routing metadata */\nexport interface SessionRoutingMeta {\n agentId: string;\n source: string;\n accountId: string;\n peerKind: string;\n peerId: string;\n threadId?: string;\n scopeId?: string;\n mainSessionKey?: string;\n lastRoutePolicy?: 'main' | 'session';\n}\n\n/** Session-level statistics (per session) */\nexport interface SessionStats {\n messageCount: number;\n tokenCount: number;\n turnCount?: number;\n lastTurnAt?: number;\n}\n\n/** Global session statistics (aggregate) */\nexport interface GlobalSessionStats {\n totalSessions: number;\n activeSessions: number;\n archivedSessions: number;\n pinnedSessions: number;\n totalMessages: number;\n totalTokens: number;\n oldestSession?: string;\n newestSession?: string;\n byChannel: Record<string, number>;\n}\n\nexport type SessionType = 'chat' | 'workflow-run' | 'workflow-subagent' | 'cron' | 'heartbeat';\n\n/** Session metadata (stored in index) */\nexport interface SessionMetadata {\n key: string;\n name?: string;\n status: SessionStatus;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n lastAccessedAt: string;\n messageCount: number;\n estimatedTokens: number;\n compactedCount: number;\n lastFlushedAt?: string;\n flushCount?: number;\n sourceChannel: string;\n sourceChatId: string;\n customData?: Record<string, unknown>;\n /** Routing metadata */\n routing?: SessionRoutingMeta;\n /** Session statistics */\n stats?: SessionStats;\n /**\n * High-level origin for filtering/UI (e.g. `cron`, `heartbeat`, `webchat`).\n * Distinct from `sourceChannel` (routing namespace).\n */\n sessionType: SessionType;\n hiddenFromSessionList?: boolean;\n parentSessionKey?: string;\n workflowRunId?: string;\n workflowDefinitionId?: string;\n workflowAgentId?: string;\n workflowAgentLabel?: string;\n /** Active OpenClaw-style session instance id. Rotates on reset while `key` stays stable. */\n sessionId?: string;\n /** Workspace/cwd recorded for the active transcript. */\n cwd?: string;\n /** First activity time for this session row (ISO), from transcript header when available. */\n sessionStartedAt?: string;\n /** Last transcript write / interaction (ISO), updated on each persist. */\n lastInteractionAt?: string;\n /**\n * Epoch ms when the last webchat run was aborted (`POST /api/agent/abort`).\n * Used with `clientCreatedAtMs` on the next POST /api/agent to drop stale queued sends.\n */\n abortCutoffTimestamp?: number;\n}\n\n/** Summary of wrapped transcript (no duplicate message bodies). */\nexport interface SessionTranscriptSummary {\n id: string;\n version: number;\n createdAt: string;\n updatedAt: string;\n compactionCount: number;\n}\n\n/** Session detail (metadata + messages) */\nexport interface SessionDetail extends SessionMetadata {\n messages: Message[];\n /** Present when loaded with `includeTranscriptSummary` (gateway `?include=transcript`). */\n transcriptSummary?: SessionTranscriptSummary;\n /** Present when loaded with `include=transcriptRows` (full on-disk rows, LLM + `kind: 'context'`). */\n transcriptRows?: TranscriptStoredRow[];\n}\n\n/** Session list query parameters */\nexport interface SessionListQuery {\n status?: SessionStatus | SessionStatus[];\n /** Single `sourceChannel`, or comma-separated list (e.g. `telegram,weixin`). */\n channel?: string;\n tags?: string[];\n search?: string;\n sessionTypes?: SessionType[];\n includeHidden?: boolean;\n sortBy?: 'updatedAt' | 'createdAt' | 'messageCount' | 'lastAccessedAt';\n sortOrder?: 'asc' | 'desc';\n limit?: number;\n offset?: number;\n}\n\n/** Paginated result */\nexport interface PaginatedResult<T> {\n items: T[];\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n}\n\n/** Export format */\nexport type ExportFormat = 'json' | 'markdown';\n\n/** Session export data */\nexport interface SessionExport {\n version: string;\n exportedAt: string;\n metadata: SessionMetadata;\n messages: Message[];\n /** Full on-disk rows (LLM + `kind: 'context'`) for audit / round-trip. */\n transcriptRows: TranscriptStoredRow[];\n}\n\n/** On-disk pre-compaction snapshot (OpenClaw-style checkpoint list). */\nexport interface CompactionCheckpointSummary {\n id: string;\n sizeBytes: number;\n modifiedAt: string;\n}\n\nexport interface CompactionCheckpointDetail extends CompactionCheckpointSummary {\n messageCount: number;\n}\n"],"mappings":";;AA4CA,IAAY,gBAAL,yBAAA,eAAA;AACL,eAAA,YAAA;AACA,eAAA,UAAA;AACA,eAAA,cAAA;AACA,eAAA,YAAA;;KACD"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/session/types.ts"],"sourcesContent":["// Session management types\n\nimport type { TranscriptStoredRow } from './session-context-for-llm.js';\n\nexport interface Message {\n role: 'system' | 'user' | 'assistant' | 'tool' | 'toolResult';\n /** Plain string or structured content blocks (tool calls, multimodal). */\n content: string | unknown[];\n timestamp?: string;\n tool_call_id?: string;\n tool_calls?: Array<{\n id: string;\n type: 'function';\n function: {\n name: string;\n arguments: string;\n };\n }>;\n tool_call_id$?: string;\n toolName?: string;\n isError?: boolean;\n name?: string;\n /** Token usage from the LLM response (assistant messages only). */\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n totalTokens?: number;\n };\n /** Inbound attachment metadata (no base64). */\n media?: Array<{\n id: string;\n bucket: string;\n type: string;\n mimeType: string;\n name: string;\n size: number;\n uri: string;\n path: string;\n }>;\n}\n\n/** Session status enum */\nexport enum SessionStatus {\n ACTIVE = 'active',\n IDLE = 'idle',\n ARCHIVED = 'archived',\n PINNED = 'pinned',\n}\n\n/** Session routing metadata */\nexport interface SessionRoutingMeta {\n agentId: string;\n source: string;\n accountId: string;\n peerKind: string;\n peerId: string;\n threadId?: string;\n scopeId?: string;\n mainSessionKey?: string;\n lastRoutePolicy?: 'main' | 'session';\n}\n\n/** Session-level statistics (per session) */\nexport interface SessionStats {\n messageCount: number;\n tokenCount: number;\n turnCount?: number;\n lastTurnAt?: number;\n}\n\n/** Global session statistics (aggregate) */\nexport interface GlobalSessionStats {\n totalSessions: number;\n activeSessions: number;\n archivedSessions: number;\n pinnedSessions: number;\n totalMessages: number;\n totalTokens: number;\n oldestSession?: string;\n newestSession?: string;\n byChannel: Record<string, number>;\n}\n\nexport type SessionType = 'chat' | 'workflow-run' | 'workflow-subagent' | 'cron' | 'heartbeat';\n\n/** Session metadata (stored in index) */\nexport interface SessionMetadata {\n key: string;\n name?: string;\n status: SessionStatus;\n tags: string[];\n createdAt: string;\n updatedAt: string;\n lastAccessedAt: string;\n messageCount: number;\n estimatedTokens: number;\n compactedCount: number;\n lastFlushedAt?: string;\n flushCount?: number;\n sourceChannel: string;\n sourceChatId: string;\n customData?: Record<string, unknown>;\n /** Optional project grouping for sessions, goals, workflows, and related context. */\n projectId?: string;\n /** Routing metadata */\n routing?: SessionRoutingMeta;\n /** Session statistics */\n stats?: SessionStats;\n /**\n * High-level origin for filtering/UI (e.g. `cron`, `heartbeat`, `webchat`).\n * Distinct from `sourceChannel` (routing namespace).\n */\n sessionType: SessionType;\n hiddenFromSessionList?: boolean;\n parentSessionKey?: string;\n workflowRunId?: string;\n workflowDefinitionId?: string;\n workflowAgentId?: string;\n workflowAgentLabel?: string;\n /** Active OpenClaw-style session instance id. Rotates on reset while `key` stays stable. */\n sessionId?: string;\n /** Workspace/cwd recorded for the active transcript. */\n cwd?: string;\n /** First activity time for this session row (ISO), from transcript header when available. */\n sessionStartedAt?: string;\n /** Last transcript write / interaction (ISO), updated on each persist. */\n lastInteractionAt?: string;\n /**\n * Epoch ms when the last webchat run was aborted (`POST /api/agent/abort`).\n * Used with `clientCreatedAtMs` on the next POST /api/agent to drop stale queued sends.\n */\n abortCutoffTimestamp?: number;\n}\n\n/** Summary of wrapped transcript (no duplicate message bodies). */\nexport interface SessionTranscriptSummary {\n id: string;\n version: number;\n createdAt: string;\n updatedAt: string;\n compactionCount: number;\n}\n\n/** Session detail (metadata + messages) */\nexport interface SessionDetail extends SessionMetadata {\n messages: Message[];\n /** Present when loaded with `includeTranscriptSummary` (gateway `?include=transcript`). */\n transcriptSummary?: SessionTranscriptSummary;\n /** Present when loaded with `include=transcriptRows` (full on-disk rows, LLM + `kind: 'context'`). */\n transcriptRows?: TranscriptStoredRow[];\n}\n\n/** Session list query parameters */\nexport interface SessionListQuery {\n status?: SessionStatus | SessionStatus[];\n /** Single `sourceChannel`, or comma-separated list (e.g. `telegram,weixin`). */\n channel?: string;\n tags?: string[];\n search?: string;\n sessionTypes?: SessionType[];\n includeHidden?: boolean;\n projectId?: string;\n sortBy?: 'updatedAt' | 'createdAt' | 'messageCount' | 'lastAccessedAt';\n sortOrder?: 'asc' | 'desc';\n limit?: number;\n offset?: number;\n}\n\n/** Paginated result */\nexport interface PaginatedResult<T> {\n items: T[];\n total: number;\n limit: number;\n offset: number;\n hasMore: boolean;\n}\n\n/** Export format */\nexport type ExportFormat = 'json' | 'markdown';\n\n/** Session export data */\nexport interface SessionExport {\n version: string;\n exportedAt: string;\n metadata: SessionMetadata;\n messages: Message[];\n /** Full on-disk rows (LLM + `kind: 'context'`) for audit / round-trip. */\n transcriptRows: TranscriptStoredRow[];\n}\n\n/** On-disk pre-compaction snapshot (OpenClaw-style checkpoint list). */\nexport interface CompactionCheckpointSummary {\n id: string;\n sizeBytes: number;\n modifiedAt: string;\n}\n\nexport interface CompactionCheckpointDetail extends CompactionCheckpointSummary {\n messageCount: number;\n}\n"],"mappings":";;AA4CA,IAAY,gBAAL,yBAAA,eAAA;AACL,eAAA,YAAA;AACA,eAAA,UAAA;AACA,eAAA,cAAA;AACA,eAAA,YAAA;;KACD"}
@@ -6,6 +6,7 @@ export interface UpsertMemoryRecordInput {
6
6
  agentId: string;
7
7
  workspaceId?: string;
8
8
  sessionKey?: string;
9
+ projectId?: string;
9
10
  content: string;
10
11
  source?: MemoryRecord['source'];
11
12
  confidence?: number;
@@ -21,6 +22,7 @@ export interface ListMemoryRecordsOptions {
21
22
  providerId?: string;
22
23
  agentId?: string;
23
24
  workspaceId?: string;
25
+ projectId?: string;
24
26
  kind?: MemoryKind;
25
27
  status?: MemoryStatus;
26
28
  limit?: number;
@@ -30,6 +32,7 @@ export interface SearchMemoryRecordsOptions {
30
32
  query: string;
31
33
  agentId?: string;
32
34
  workspaceId?: string;
35
+ projectId?: string;
33
36
  providerId?: string;
34
37
  kinds?: MemoryKind[];
35
38
  statuses?: MemoryStatus[];
@@ -93,7 +93,8 @@ function rowToRecord(row) {
93
93
  scope: {
94
94
  agentId: row.agent_id,
95
95
  ...row.workspace_id ? { workspaceId: row.workspace_id } : {},
96
- ...row.session_key ? { sessionKey: row.session_key } : {}
96
+ ...row.session_key ? { sessionKey: row.session_key } : {},
97
+ ...row.project_id ? { projectId: row.project_id } : {}
97
98
  },
98
99
  content: row.content,
99
100
  source: parseSource(row.source_json),
@@ -130,16 +131,17 @@ function upsertMemoryRecord(input) {
130
131
  };
131
132
  runSqliteWriteTransaction((db) => {
132
133
  db.prepare(`INSERT INTO memory_records (
133
- record_id, provider_id, kind, agent_id, workspace_id, session_key,
134
+ record_id, provider_id, kind, agent_id, workspace_id, session_key, project_id,
134
135
  content, source_json, confidence, tags_json, status, sensitivity,
135
136
  evidence_json, review_after, expires_at, created_at, updated_at
136
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
137
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
137
138
  ON CONFLICT(record_id) DO UPDATE SET
138
139
  provider_id = excluded.provider_id,
139
140
  kind = excluded.kind,
140
141
  agent_id = excluded.agent_id,
141
142
  workspace_id = excluded.workspace_id,
142
143
  session_key = excluded.session_key,
144
+ project_id = excluded.project_id,
143
145
  content = excluded.content,
144
146
  source_json = excluded.source_json,
145
147
  confidence = excluded.confidence,
@@ -149,7 +151,7 @@ function upsertMemoryRecord(input) {
149
151
  evidence_json = excluded.evidence_json,
150
152
  review_after = excluded.review_after,
151
153
  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);
154
+ updated_at = excluded.updated_at`).run(id, input.providerId, input.kind, input.agentId, input.workspaceId ?? null, input.sessionKey ?? null, input.projectId ?? null, input.content, JSON.stringify(source), input.confidence ?? null, JSON.stringify(input.tags ?? []), status, sensitivity, JSON.stringify(input.evidence ?? []), reviewAfter, expiresAt, now, now);
153
155
  upsertMemoryRecordFts(db, {
154
156
  ...input,
155
157
  id
@@ -162,7 +164,8 @@ function upsertMemoryRecord(input) {
162
164
  scope: {
163
165
  agentId: input.agentId,
164
166
  ...input.workspaceId ? { workspaceId: input.workspaceId } : {},
165
- ...input.sessionKey ? { sessionKey: input.sessionKey } : {}
167
+ ...input.sessionKey ? { sessionKey: input.sessionKey } : {},
168
+ ...input.projectId ? { projectId: input.projectId } : {}
166
169
  },
167
170
  content: input.content,
168
171
  source,
@@ -195,6 +198,10 @@ function listMemoryRecords(options = {}) {
195
198
  where.push("workspace_id = ?");
196
199
  params.push(options.workspaceId);
197
200
  }
201
+ if (options.projectId) {
202
+ where.push("project_id = ?");
203
+ params.push(options.projectId);
204
+ }
198
205
  if (options.kind) {
199
206
  where.push("kind = ?");
200
207
  params.push(options.kind);
@@ -223,6 +230,10 @@ function searchMemoryRecords(options) {
223
230
  filters.push("f.workspace_id = ?");
224
231
  params.push(options.workspaceId);
225
232
  }
233
+ if (options.projectId) {
234
+ filters.push("r.project_id = ?");
235
+ params.push(options.projectId);
236
+ }
226
237
  if (options.providerId) {
227
238
  filters.push("f.provider_id = ?");
228
239
  params.push(options.providerId);
@@ -1 +1 @@
1
- {"version":3,"file":"memory-records-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-records-repository.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type {\n MemoryKind,\n MemoryRecord,\n MemorySensitivity,\n MemorySearchResult,\n MemorySignal,\n MemoryStatus,\n} from '../../agent/memory/types.js';\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\ntype MemoryRecordRow = {\n record_id: string;\n provider_id: string;\n kind: string;\n agent_id: string;\n workspace_id: string | null;\n session_key: string | null;\n content: string;\n source_json: string;\n confidence: number | null;\n tags_json: string;\n status: string;\n sensitivity: string;\n evidence_json: string;\n review_after: number | null;\n expires_at: number | null;\n created_at: number;\n updated_at: number;\n};\n\ntype MemoryRecordSearchRow = MemoryRecordRow & {\n rank: number;\n};\n\nexport interface UpsertMemoryRecordInput {\n id?: string;\n providerId: string;\n kind: MemoryKind;\n agentId: string;\n workspaceId?: string;\n sessionKey?: string;\n content: string;\n source?: MemoryRecord['source'];\n confidence?: number;\n tags?: string[];\n status?: MemoryStatus;\n sensitivity?: MemorySensitivity;\n evidence?: MemoryRecord['evidence'];\n reviewAfter?: string;\n expiresAt?: string;\n nowMs?: number;\n}\n\nexport interface ListMemoryRecordsOptions {\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n kind?: MemoryKind;\n status?: MemoryStatus;\n limit?: number;\n offset?: number;\n}\n\nexport interface SearchMemoryRecordsOptions {\n query: string;\n agentId?: string;\n workspaceId?: string;\n providerId?: string;\n kinds?: MemoryKind[];\n statuses?: MemoryStatus[];\n maxResults?: number;\n minScore?: number;\n}\n\nexport interface AppendMemorySignalInput {\n signal: MemorySignal;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n sessionKey?: string;\n nowMs?: number;\n}\n\nexport interface MemorySignalRowPayload {\n signalId: string;\n source: string;\n recordId?: string;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n sessionKey?: string;\n score?: number;\n content?: string;\n metadata: Record<string, unknown>;\n createdAt: string;\n}\n\ntype MemorySignalRow = {\n signal_id: string;\n source: string;\n record_id: string | null;\n provider_id: string | null;\n agent_id: string | null;\n workspace_id: string | null;\n session_key: string | null;\n score: number | null;\n content: string | null;\n metadata_json: string;\n created_at: number;\n};\n\ntype MemoryTraceRow = {\n trace_id: string;\n session_key: string | null;\n turn_id: string | null;\n phase: string;\n provider_id: string;\n request_json: string;\n result_count: number | null;\n selected_record_ids_json: string;\n skipped_reason: string | null;\n error: string | null;\n feedback_json: string;\n duration_ms: number;\n created_at: number;\n};\n\nexport type MemoryTraceFeedbackOutcome = 'helpful' | 'not_helpful' | 'mixed' | 'irrelevant';\n\nexport interface MemoryTraceFeedback {\n outcome: MemoryTraceFeedbackOutcome;\n score?: number;\n reason?: string;\n source?: 'user' | 'evaluator' | 'system';\n createdAt: string;\n updatedAt?: string;\n}\n\nexport interface AppendMemoryTraceEventInput {\n sessionKey?: string;\n turnId?: string;\n phase: 'search' | 'read' | 'write' | 'update' | 'delete' | 'sync' | 'inject' | 'test';\n providerId: string;\n request?: unknown;\n resultCount?: number;\n selectedRecordIds?: string[];\n skippedReason?: string;\n error?: string;\n feedback?: MemoryTraceFeedback;\n durationMs?: number;\n nowMs?: number;\n}\n\nexport interface SetMemoryTraceFeedbackInput {\n traceId: string;\n feedback: Omit<MemoryTraceFeedback, 'createdAt' | 'updatedAt'> & {\n createdAt?: string;\n updatedAt?: string;\n };\n nowMs?: number;\n}\n\nexport interface MemoryTraceEventPayload {\n traceId: string;\n sessionKey?: string;\n turnId?: string;\n phase: string;\n providerId: string;\n request: unknown;\n resultCount?: number;\n selectedRecordIds: string[];\n skippedReason?: string;\n error?: string;\n feedback?: MemoryTraceFeedback;\n durationMs: number;\n createdAt: string;\n}\n\nexport interface MemoryRecallFeedbackSummary {\n recordId: string;\n helpful: number;\n notHelpful: number;\n mixed: number;\n irrelevant: number;\n total: number;\n averageScore: number | null;\n lastFeedbackAt?: string;\n}\n\nfunction parseStringArray(json: string): string[] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((v): v is string => typeof v === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseEvidence(json: string): MemoryRecord['evidence'] {\n try {\n const parsed = JSON.parse(json) as unknown;\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((item): item is NonNullable<MemoryRecord['evidence']>[number] =>\n Boolean(item) && typeof item === 'object',\n );\n } catch {\n return [];\n }\n}\n\nfunction parseMemoryTraceFeedback(json: string): MemoryTraceFeedback | undefined {\n try {\n const parsed = JSON.parse(json) as unknown;\n if (!parsed || typeof parsed !== 'object') return undefined;\n const obj = parsed as Record<string, unknown>;\n const outcome = obj.outcome;\n if (\n outcome !== 'helpful' &&\n outcome !== 'not_helpful' &&\n outcome !== 'mixed' &&\n outcome !== 'irrelevant'\n ) {\n return undefined;\n }\n return {\n outcome,\n ...(typeof obj.score === 'number' ? { score: obj.score } : {}),\n ...(typeof obj.reason === 'string' ? { reason: obj.reason } : {}),\n ...(obj.source === 'user' || obj.source === 'evaluator' || obj.source === 'system'\n ? { source: obj.source }\n : {}),\n createdAt: typeof obj.createdAt === 'string' ? obj.createdAt : new Date(0).toISOString(),\n ...(typeof obj.updatedAt === 'string' ? { updatedAt: obj.updatedAt } : {}),\n };\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeMemoryTraceFeedback(\n input: SetMemoryTraceFeedbackInput['feedback'],\n nowMs = Date.now(),\n existing?: MemoryTraceFeedback,\n): MemoryTraceFeedback {\n const score = typeof input.score === 'number'\n ? Math.max(-1, Math.min(1, input.score))\n : undefined;\n const reason = typeof input.reason === 'string' && input.reason.trim()\n ? input.reason.trim().slice(0, 1000)\n : undefined;\n const nowIso = new Date(nowMs).toISOString();\n return {\n outcome: input.outcome,\n ...(score != null ? { score } : {}),\n ...(reason ? { reason } : {}),\n ...(input.source ? { source: input.source } : {}),\n createdAt: input.createdAt ?? existing?.createdAt ?? nowIso,\n updatedAt: input.updatedAt ?? nowIso,\n };\n}\n\nfunction memoryTraceRowToPayload(row: MemoryTraceRow): MemoryTraceEventPayload {\n const feedback = parseMemoryTraceFeedback(row.feedback_json);\n return {\n traceId: row.trace_id,\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n ...(row.turn_id ? { turnId: row.turn_id } : {}),\n phase: row.phase,\n providerId: row.provider_id,\n request: parseJsonValue(row.request_json, {}),\n ...(row.result_count != null ? { resultCount: row.result_count } : {}),\n selectedRecordIds: parseStringArray(row.selected_record_ids_json),\n ...(row.skipped_reason ? { skippedReason: row.skipped_reason } : {}),\n ...(row.error ? { error: row.error } : {}),\n ...(feedback ? { feedback } : {}),\n durationMs: row.duration_ms,\n createdAt: new Date(row.created_at).toISOString(),\n };\n}\n\nfunction parseOptionalTimestamp(value: string | undefined): number | null {\n if (!value?.trim()) return null;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction timestampToIso(value: number | null): string | undefined {\n return value == null ? undefined : new Date(value).toISOString();\n}\n\nfunction parseSource(json: string): MemoryRecord['source'] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return parsed && typeof parsed === 'object' ? (parsed as MemoryRecord['source']) : {};\n } catch {\n return {};\n }\n}\n\nfunction rowToRecord(row: MemoryRecordRow): MemoryRecord {\n return {\n id: row.record_id,\n kind: row.kind as MemoryKind,\n status: row.status as MemoryStatus,\n scope: {\n agentId: row.agent_id,\n ...(row.workspace_id ? { workspaceId: row.workspace_id } : {}),\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n },\n content: row.content,\n source: parseSource(row.source_json),\n ...(row.confidence != null ? { confidence: row.confidence } : {}),\n sensitivity: row.sensitivity as MemorySensitivity,\n evidence: parseEvidence(row.evidence_json),\n ...(timestampToIso(row.review_after) ? { reviewAfter: timestampToIso(row.review_after) } : {}),\n ...(timestampToIso(row.expires_at) ? { expiresAt: timestampToIso(row.expires_at) } : {}),\n createdAt: new Date(row.created_at).toISOString(),\n updatedAt: new Date(row.updated_at).toISOString(),\n tags: parseStringArray(row.tags_json),\n };\n}\n\nfunction bm25ToScore(rank: number): number {\n return Math.max(0, Math.min(1, 1 / (1 + Math.max(0, rank))));\n}\n\nfunction upsertMemoryRecordFts(\n db: ReturnType<typeof getSqliteDatabase>,\n row: Pick<UpsertMemoryRecordInput, 'providerId' | 'kind' | 'agentId' | 'workspaceId' | 'content'> & { id: string },\n): void {\n db.prepare(`DELETE FROM memory_records_fts WHERE record_id = ?`).run(row.id);\n if (!row.content.trim()) return;\n db.prepare(\n `INSERT INTO memory_records_fts (\n content, record_id, provider_id, kind, agent_id, workspace_id\n ) VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(row.content, row.id, row.providerId, row.kind, row.agentId, row.workspaceId ?? null);\n}\n\nexport function upsertMemoryRecord(input: UpsertMemoryRecordInput): MemoryRecord {\n const id = input.id ?? randomUUID();\n const now = input.nowMs ?? Date.now();\n const status = input.status ?? 'active';\n const sensitivity = input.sensitivity ?? 'normal';\n const reviewAfter = parseOptionalTimestamp(input.reviewAfter);\n const expiresAt = parseOptionalTimestamp(input.expiresAt);\n const source = {\n ...(input.source ?? {}),\n provider: input.source?.provider ?? input.providerId,\n };\n\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_records (\n record_id, provider_id, kind, agent_id, workspace_id, session_key,\n content, source_json, confidence, tags_json, status, sensitivity,\n evidence_json, review_after, expires_at, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(record_id) DO UPDATE SET\n provider_id = excluded.provider_id,\n kind = excluded.kind,\n agent_id = excluded.agent_id,\n workspace_id = excluded.workspace_id,\n session_key = excluded.session_key,\n content = excluded.content,\n source_json = excluded.source_json,\n confidence = excluded.confidence,\n tags_json = excluded.tags_json,\n status = excluded.status,\n sensitivity = excluded.sensitivity,\n evidence_json = excluded.evidence_json,\n review_after = excluded.review_after,\n expires_at = excluded.expires_at,\n updated_at = excluded.updated_at`,\n ).run(\n id,\n input.providerId,\n input.kind,\n input.agentId,\n input.workspaceId ?? null,\n input.sessionKey ?? null,\n input.content,\n JSON.stringify(source),\n input.confidence ?? null,\n JSON.stringify(input.tags ?? []),\n status,\n sensitivity,\n JSON.stringify(input.evidence ?? []),\n reviewAfter,\n expiresAt,\n now,\n now,\n );\n upsertMemoryRecordFts(db, { ...input, id });\n });\n\n return {\n id,\n kind: input.kind,\n status,\n scope: {\n agentId: input.agentId,\n ...(input.workspaceId ? { workspaceId: input.workspaceId } : {}),\n ...(input.sessionKey ? { sessionKey: input.sessionKey } : {}),\n },\n content: input.content,\n source,\n ...(input.confidence != null ? { confidence: input.confidence } : {}),\n sensitivity,\n evidence: input.evidence ?? [],\n ...(reviewAfter != null ? { reviewAfter: new Date(reviewAfter).toISOString() } : {}),\n ...(expiresAt != null ? { expiresAt: new Date(expiresAt).toISOString() } : {}),\n createdAt: new Date(now).toISOString(),\n updatedAt: new Date(now).toISOString(),\n tags: input.tags ?? [],\n };\n}\n\nexport function getMemoryRecord(recordId: string): MemoryRecord | null {\n const row = getSqliteDatabase()\n .prepare(`SELECT * FROM memory_records WHERE record_id = ?`)\n .get(recordId) as MemoryRecordRow | undefined;\n return row ? rowToRecord(row) : null;\n}\n\nexport function listMemoryRecords(options: ListMemoryRecordsOptions = {}): MemoryRecord[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.agentId) {\n where.push('agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n where.push('workspace_id = ?');\n params.push(options.workspaceId);\n }\n if (options.kind) {\n where.push('kind = ?');\n params.push(options.kind);\n }\n if (options.status) {\n where.push('status = ?');\n params.push(options.status);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const offset = Math.max(0, options.offset ?? 0);\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_records\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY updated_at DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset) as MemoryRecordRow[];\n return rows.map(rowToRecord);\n}\n\nexport function searchMemoryRecords(options: SearchMemoryRecordsOptions): MemorySearchResult[] {\n const query = escapeFts5Query(options.query);\n if (!query) return [];\n\n const filters: string[] = ['memory_records_fts MATCH ?'];\n const params: Array<string | number | null> = [query];\n if (options.agentId) {\n filters.push('f.agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n filters.push('f.workspace_id = ?');\n params.push(options.workspaceId);\n }\n if (options.providerId) {\n filters.push('f.provider_id = ?');\n params.push(options.providerId);\n }\n if (options.kinds && options.kinds.length > 0) {\n filters.push(`f.kind IN (${options.kinds.map(() => '?').join(', ')})`);\n params.push(...options.kinds);\n }\n const statuses = options.statuses && options.statuses.length > 0 ? options.statuses : ['active'];\n filters.push(`r.status IN (${statuses.map(() => '?').join(', ')})`);\n params.push(...statuses);\n\n const maxResults = Math.max(1, Math.min(50, options.maxResults ?? 5));\n const minScore = options.minScore ?? 0;\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT\n r.*,\n bm25(memory_records_fts) AS rank\n FROM memory_records_fts f\n JOIN memory_records r ON r.record_id = f.record_id\n WHERE ${filters.join(' AND ')}\n ORDER BY rank\n LIMIT ?`,\n )\n .all(...params, maxResults * 3) as MemoryRecordSearchRow[];\n\n return rows\n .map((row) => {\n const record = rowToRecord(row);\n const score = bm25ToScore(row.rank);\n return {\n record,\n score,\n snippet: record.content,\n citation: {\n providerId: row.provider_id,\n recordId: row.record_id,\n path: record.source.path,\n lineStart: record.source.lineStart,\n lineEnd: record.source.lineEnd,\n createdAt: record.createdAt,\n },\n };\n })\n .filter((result) => result.score >= minScore)\n .slice(0, maxResults);\n}\n\nexport function deleteMemoryRecord(recordId: string): boolean {\n return runSqliteWriteTransaction((db) => {\n db.prepare(`DELETE FROM memory_records_fts WHERE record_id = ?`).run(recordId);\n const result = db.prepare(`DELETE FROM memory_records WHERE record_id = ?`).run(recordId);\n return result.changes > 0;\n });\n}\n\nexport function appendMemorySignal(input: AppendMemorySignalInput): string {\n const id = randomUUID();\n const now = input.nowMs ?? Date.now();\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_signals (\n signal_id, source, record_id, provider_id, agent_id, workspace_id,\n session_key, score, content, metadata_json, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.signal.source,\n input.signal.recordId ?? null,\n input.providerId ?? null,\n input.agentId ?? null,\n input.workspaceId ?? null,\n input.sessionKey ?? null,\n input.signal.score ?? null,\n input.signal.content ?? null,\n JSON.stringify(input.signal.metadata ?? {}),\n now,\n );\n if (input.signal.recordId) {\n db.prepare(\n `UPDATE memory_records\n SET recall_count = recall_count + 1, last_recalled_at = ?, updated_at = MAX(updated_at, ?)\n WHERE record_id = ?`,\n ).run(now, now, input.signal.recordId);\n }\n });\n return id;\n}\n\nexport function listMemorySignals(options: {\n recordId?: string;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n limit?: number;\n} = {}): MemorySignalRowPayload[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.recordId) {\n where.push('record_id = ?');\n params.push(options.recordId);\n }\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.agentId) {\n where.push('agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n where.push('workspace_id = ?');\n params.push(options.workspaceId);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_signals\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemorySignalRow[];\n return rows.map((row) => {\n let metadata: Record<string, unknown> = {};\n try {\n const parsed = JSON.parse(row.metadata_json) as unknown;\n if (parsed && typeof parsed === 'object') metadata = parsed as Record<string, unknown>;\n } catch {\n metadata = {};\n }\n return {\n signalId: row.signal_id,\n source: row.source,\n ...(row.record_id ? { recordId: row.record_id } : {}),\n ...(row.provider_id ? { providerId: row.provider_id } : {}),\n ...(row.agent_id ? { agentId: row.agent_id } : {}),\n ...(row.workspace_id ? { workspaceId: row.workspace_id } : {}),\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n ...(row.score != null ? { score: row.score } : {}),\n ...(row.content ? { content: row.content } : {}),\n metadata,\n createdAt: new Date(row.created_at).toISOString(),\n };\n });\n}\n\nexport function getMemoryProviderState(providerId: string, scopeKey: string): unknown | null {\n const row = getSqliteDatabase()\n .prepare(`SELECT state_json FROM memory_provider_state WHERE provider_id = ? AND scope_key = ?`)\n .get(providerId, scopeKey) as { state_json: string } | undefined;\n if (!row) return null;\n try {\n return JSON.parse(row.state_json) as unknown;\n } catch {\n return null;\n }\n}\n\nexport function setMemoryProviderState(providerId: string, scopeKey: string, state: unknown): void {\n const now = Date.now();\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_provider_state (provider_id, scope_key, state_json, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(provider_id, scope_key) DO UPDATE SET\n state_json = excluded.state_json,\n updated_at = excluded.updated_at`,\n ).run(providerId, scopeKey, JSON.stringify(state ?? null), now);\n });\n}\n\nexport function appendMemoryTraceEvent(input: AppendMemoryTraceEventInput): string {\n const id = randomUUID();\n const now = input.nowMs ?? Date.now();\n const feedback = input.feedback\n ? normalizeMemoryTraceFeedback(input.feedback, now)\n : undefined;\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_trace_events (\n trace_id, session_key, turn_id, phase, provider_id, request_json,\n result_count, selected_record_ids_json, skipped_reason, error, feedback_json, duration_ms, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.sessionKey ?? null,\n input.turnId ?? null,\n input.phase,\n input.providerId,\n JSON.stringify(input.request ?? {}),\n input.resultCount ?? null,\n JSON.stringify(input.selectedRecordIds ?? []),\n input.skippedReason ?? null,\n input.error ?? null,\n JSON.stringify(feedback ?? {}),\n Math.max(0, Math.floor(input.durationMs ?? 0)),\n now,\n );\n });\n return id;\n}\n\nexport function listMemoryTraceEvents(options: {\n providerId?: string;\n sessionKey?: string;\n phase?: string;\n limit?: number;\n} = {}): MemoryTraceEventPayload[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.sessionKey) {\n where.push('session_key = ?');\n params.push(options.sessionKey);\n }\n if (options.phase) {\n where.push('phase = ?');\n params.push(options.phase);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_trace_events\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemoryTraceRow[];\n return rows.map(memoryTraceRowToPayload);\n}\n\nexport function setMemoryTraceFeedback(input: SetMemoryTraceFeedbackInput): MemoryTraceEventPayload | null {\n const existing = getSqliteDatabase()\n .prepare(`SELECT * FROM memory_trace_events WHERE trace_id = ?`)\n .get(input.traceId) as MemoryTraceRow | undefined;\n if (!existing) {\n return null;\n }\n const feedback = normalizeMemoryTraceFeedback(\n input.feedback,\n input.nowMs,\n parseMemoryTraceFeedback(existing.feedback_json),\n );\n runSqliteWriteTransaction((db) => {\n db.prepare(`UPDATE memory_trace_events SET feedback_json = ? WHERE trace_id = ?`)\n .run(JSON.stringify(feedback), input.traceId);\n });\n return memoryTraceRowToPayload({ ...existing, feedback_json: JSON.stringify(feedback) });\n}\n\nexport function summarizeMemoryRecallFeedback(options: {\n recordId?: string;\n providerId?: string;\n sessionKey?: string;\n limit?: number;\n} = {}): MemoryRecallFeedbackSummary[] {\n const where = ['phase IN (?, ?)'];\n const params: Array<string | number> = ['search', 'inject'];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.sessionKey) {\n where.push('session_key = ?');\n params.push(options.sessionKey);\n }\n const limit = Math.max(1, Math.min(5000, options.limit ?? 1000));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_trace_events\n WHERE ${where.join(' AND ')}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemoryTraceRow[];\n\n const summaries = new Map<string, MemoryRecallFeedbackSummary & { scoreTotal: number; scoreCount: number }>();\n for (const row of rows) {\n const feedback = parseMemoryTraceFeedback(row.feedback_json);\n if (!feedback) continue;\n const recordIds = parseStringArray(row.selected_record_ids_json);\n for (const recordId of recordIds) {\n if (options.recordId && recordId !== options.recordId) continue;\n const current = summaries.get(recordId) ?? {\n recordId,\n helpful: 0,\n notHelpful: 0,\n mixed: 0,\n irrelevant: 0,\n total: 0,\n averageScore: null,\n scoreTotal: 0,\n scoreCount: 0,\n };\n if (feedback.outcome === 'helpful') current.helpful += 1;\n if (feedback.outcome === 'not_helpful') current.notHelpful += 1;\n if (feedback.outcome === 'mixed') current.mixed += 1;\n if (feedback.outcome === 'irrelevant') current.irrelevant += 1;\n current.total += 1;\n if (typeof feedback.score === 'number') {\n current.scoreTotal += feedback.score;\n current.scoreCount += 1;\n current.averageScore = current.scoreTotal / current.scoreCount;\n }\n current.lastFeedbackAt ??= feedback.updatedAt ?? feedback.createdAt;\n summaries.set(recordId, current);\n }\n }\n\n return [...summaries.values()]\n .map(({ scoreTotal: _scoreTotal, scoreCount: _scoreCount, ...summary }) => summary)\n .sort((a, b) => b.total - a.total);\n}\n\nfunction parseJsonValue(json: string, fallback: unknown): unknown {\n try {\n return JSON.parse(json) as unknown;\n } catch {\n return fallback;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory-records-repository.js","names":[],"sources":["../../../../src/storage/sqlite/memory-records-repository.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type {\n MemoryKind,\n MemoryRecord,\n MemorySensitivity,\n MemorySearchResult,\n MemorySignal,\n MemoryStatus,\n} from '../../agent/memory/types.js';\nimport { escapeFts5Query } from './fts.js';\nimport { getSqliteDatabase, runSqliteWriteTransaction } from './transaction.js';\n\ntype MemoryRecordRow = {\n record_id: string;\n provider_id: string;\n kind: string;\n agent_id: string;\n workspace_id: string | null;\n session_key: string | null;\n project_id: string | null;\n content: string;\n source_json: string;\n confidence: number | null;\n tags_json: string;\n status: string;\n sensitivity: string;\n evidence_json: string;\n review_after: number | null;\n expires_at: number | null;\n created_at: number;\n updated_at: number;\n};\n\ntype MemoryRecordSearchRow = MemoryRecordRow & {\n rank: number;\n};\n\nexport interface UpsertMemoryRecordInput {\n id?: string;\n providerId: string;\n kind: MemoryKind;\n agentId: string;\n workspaceId?: string;\n sessionKey?: string;\n projectId?: string;\n content: string;\n source?: MemoryRecord['source'];\n confidence?: number;\n tags?: string[];\n status?: MemoryStatus;\n sensitivity?: MemorySensitivity;\n evidence?: MemoryRecord['evidence'];\n reviewAfter?: string;\n expiresAt?: string;\n nowMs?: number;\n}\n\nexport interface ListMemoryRecordsOptions {\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n projectId?: string;\n kind?: MemoryKind;\n status?: MemoryStatus;\n limit?: number;\n offset?: number;\n}\n\nexport interface SearchMemoryRecordsOptions {\n query: string;\n agentId?: string;\n workspaceId?: string;\n projectId?: string;\n providerId?: string;\n kinds?: MemoryKind[];\n statuses?: MemoryStatus[];\n maxResults?: number;\n minScore?: number;\n}\n\nexport interface AppendMemorySignalInput {\n signal: MemorySignal;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n sessionKey?: string;\n nowMs?: number;\n}\n\nexport interface MemorySignalRowPayload {\n signalId: string;\n source: string;\n recordId?: string;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n sessionKey?: string;\n score?: number;\n content?: string;\n metadata: Record<string, unknown>;\n createdAt: string;\n}\n\ntype MemorySignalRow = {\n signal_id: string;\n source: string;\n record_id: string | null;\n provider_id: string | null;\n agent_id: string | null;\n workspace_id: string | null;\n session_key: string | null;\n score: number | null;\n content: string | null;\n metadata_json: string;\n created_at: number;\n};\n\ntype MemoryTraceRow = {\n trace_id: string;\n session_key: string | null;\n turn_id: string | null;\n phase: string;\n provider_id: string;\n request_json: string;\n result_count: number | null;\n selected_record_ids_json: string;\n skipped_reason: string | null;\n error: string | null;\n feedback_json: string;\n duration_ms: number;\n created_at: number;\n};\n\nexport type MemoryTraceFeedbackOutcome = 'helpful' | 'not_helpful' | 'mixed' | 'irrelevant';\n\nexport interface MemoryTraceFeedback {\n outcome: MemoryTraceFeedbackOutcome;\n score?: number;\n reason?: string;\n source?: 'user' | 'evaluator' | 'system';\n createdAt: string;\n updatedAt?: string;\n}\n\nexport interface AppendMemoryTraceEventInput {\n sessionKey?: string;\n turnId?: string;\n phase: 'search' | 'read' | 'write' | 'update' | 'delete' | 'sync' | 'inject' | 'test';\n providerId: string;\n request?: unknown;\n resultCount?: number;\n selectedRecordIds?: string[];\n skippedReason?: string;\n error?: string;\n feedback?: MemoryTraceFeedback;\n durationMs?: number;\n nowMs?: number;\n}\n\nexport interface SetMemoryTraceFeedbackInput {\n traceId: string;\n feedback: Omit<MemoryTraceFeedback, 'createdAt' | 'updatedAt'> & {\n createdAt?: string;\n updatedAt?: string;\n };\n nowMs?: number;\n}\n\nexport interface MemoryTraceEventPayload {\n traceId: string;\n sessionKey?: string;\n turnId?: string;\n phase: string;\n providerId: string;\n request: unknown;\n resultCount?: number;\n selectedRecordIds: string[];\n skippedReason?: string;\n error?: string;\n feedback?: MemoryTraceFeedback;\n durationMs: number;\n createdAt: string;\n}\n\nexport interface MemoryRecallFeedbackSummary {\n recordId: string;\n helpful: number;\n notHelpful: number;\n mixed: number;\n irrelevant: number;\n total: number;\n averageScore: number | null;\n lastFeedbackAt?: string;\n}\n\nfunction parseStringArray(json: string): string[] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return Array.isArray(parsed) ? parsed.filter((v): v is string => typeof v === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction parseEvidence(json: string): MemoryRecord['evidence'] {\n try {\n const parsed = JSON.parse(json) as unknown;\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((item): item is NonNullable<MemoryRecord['evidence']>[number] =>\n Boolean(item) && typeof item === 'object',\n );\n } catch {\n return [];\n }\n}\n\nfunction parseMemoryTraceFeedback(json: string): MemoryTraceFeedback | undefined {\n try {\n const parsed = JSON.parse(json) as unknown;\n if (!parsed || typeof parsed !== 'object') return undefined;\n const obj = parsed as Record<string, unknown>;\n const outcome = obj.outcome;\n if (\n outcome !== 'helpful' &&\n outcome !== 'not_helpful' &&\n outcome !== 'mixed' &&\n outcome !== 'irrelevant'\n ) {\n return undefined;\n }\n return {\n outcome,\n ...(typeof obj.score === 'number' ? { score: obj.score } : {}),\n ...(typeof obj.reason === 'string' ? { reason: obj.reason } : {}),\n ...(obj.source === 'user' || obj.source === 'evaluator' || obj.source === 'system'\n ? { source: obj.source }\n : {}),\n createdAt: typeof obj.createdAt === 'string' ? obj.createdAt : new Date(0).toISOString(),\n ...(typeof obj.updatedAt === 'string' ? { updatedAt: obj.updatedAt } : {}),\n };\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeMemoryTraceFeedback(\n input: SetMemoryTraceFeedbackInput['feedback'],\n nowMs = Date.now(),\n existing?: MemoryTraceFeedback,\n): MemoryTraceFeedback {\n const score = typeof input.score === 'number'\n ? Math.max(-1, Math.min(1, input.score))\n : undefined;\n const reason = typeof input.reason === 'string' && input.reason.trim()\n ? input.reason.trim().slice(0, 1000)\n : undefined;\n const nowIso = new Date(nowMs).toISOString();\n return {\n outcome: input.outcome,\n ...(score != null ? { score } : {}),\n ...(reason ? { reason } : {}),\n ...(input.source ? { source: input.source } : {}),\n createdAt: input.createdAt ?? existing?.createdAt ?? nowIso,\n updatedAt: input.updatedAt ?? nowIso,\n };\n}\n\nfunction memoryTraceRowToPayload(row: MemoryTraceRow): MemoryTraceEventPayload {\n const feedback = parseMemoryTraceFeedback(row.feedback_json);\n return {\n traceId: row.trace_id,\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n ...(row.turn_id ? { turnId: row.turn_id } : {}),\n phase: row.phase,\n providerId: row.provider_id,\n request: parseJsonValue(row.request_json, {}),\n ...(row.result_count != null ? { resultCount: row.result_count } : {}),\n selectedRecordIds: parseStringArray(row.selected_record_ids_json),\n ...(row.skipped_reason ? { skippedReason: row.skipped_reason } : {}),\n ...(row.error ? { error: row.error } : {}),\n ...(feedback ? { feedback } : {}),\n durationMs: row.duration_ms,\n createdAt: new Date(row.created_at).toISOString(),\n };\n}\n\nfunction parseOptionalTimestamp(value: string | undefined): number | null {\n if (!value?.trim()) return null;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction timestampToIso(value: number | null): string | undefined {\n return value == null ? undefined : new Date(value).toISOString();\n}\n\nfunction parseSource(json: string): MemoryRecord['source'] {\n try {\n const parsed = JSON.parse(json) as unknown;\n return parsed && typeof parsed === 'object' ? (parsed as MemoryRecord['source']) : {};\n } catch {\n return {};\n }\n}\n\nfunction rowToRecord(row: MemoryRecordRow): MemoryRecord {\n return {\n id: row.record_id,\n kind: row.kind as MemoryKind,\n status: row.status as MemoryStatus,\n scope: {\n agentId: row.agent_id,\n ...(row.workspace_id ? { workspaceId: row.workspace_id } : {}),\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n ...(row.project_id ? { projectId: row.project_id } : {}),\n },\n content: row.content,\n source: parseSource(row.source_json),\n ...(row.confidence != null ? { confidence: row.confidence } : {}),\n sensitivity: row.sensitivity as MemorySensitivity,\n evidence: parseEvidence(row.evidence_json),\n ...(timestampToIso(row.review_after) ? { reviewAfter: timestampToIso(row.review_after) } : {}),\n ...(timestampToIso(row.expires_at) ? { expiresAt: timestampToIso(row.expires_at) } : {}),\n createdAt: new Date(row.created_at).toISOString(),\n updatedAt: new Date(row.updated_at).toISOString(),\n tags: parseStringArray(row.tags_json),\n };\n}\n\nfunction bm25ToScore(rank: number): number {\n return Math.max(0, Math.min(1, 1 / (1 + Math.max(0, rank))));\n}\n\nfunction upsertMemoryRecordFts(\n db: ReturnType<typeof getSqliteDatabase>,\n row: Pick<UpsertMemoryRecordInput, 'providerId' | 'kind' | 'agentId' | 'workspaceId' | 'content'> & { id: string },\n): void {\n db.prepare(`DELETE FROM memory_records_fts WHERE record_id = ?`).run(row.id);\n if (!row.content.trim()) return;\n db.prepare(\n `INSERT INTO memory_records_fts (\n content, record_id, provider_id, kind, agent_id, workspace_id\n ) VALUES (?, ?, ?, ?, ?, ?)`,\n ).run(row.content, row.id, row.providerId, row.kind, row.agentId, row.workspaceId ?? null);\n}\n\nexport function upsertMemoryRecord(input: UpsertMemoryRecordInput): MemoryRecord {\n const id = input.id ?? randomUUID();\n const now = input.nowMs ?? Date.now();\n const status = input.status ?? 'active';\n const sensitivity = input.sensitivity ?? 'normal';\n const reviewAfter = parseOptionalTimestamp(input.reviewAfter);\n const expiresAt = parseOptionalTimestamp(input.expiresAt);\n const source = {\n ...(input.source ?? {}),\n provider: input.source?.provider ?? input.providerId,\n };\n\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_records (\n record_id, provider_id, kind, agent_id, workspace_id, session_key, project_id,\n content, source_json, confidence, tags_json, status, sensitivity,\n evidence_json, review_after, expires_at, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(record_id) DO UPDATE SET\n provider_id = excluded.provider_id,\n kind = excluded.kind,\n agent_id = excluded.agent_id,\n workspace_id = excluded.workspace_id,\n session_key = excluded.session_key,\n project_id = excluded.project_id,\n content = excluded.content,\n source_json = excluded.source_json,\n confidence = excluded.confidence,\n tags_json = excluded.tags_json,\n status = excluded.status,\n sensitivity = excluded.sensitivity,\n evidence_json = excluded.evidence_json,\n review_after = excluded.review_after,\n expires_at = excluded.expires_at,\n updated_at = excluded.updated_at`,\n ).run(\n id,\n input.providerId,\n input.kind,\n input.agentId,\n input.workspaceId ?? null,\n input.sessionKey ?? null,\n input.projectId ?? null,\n input.content,\n JSON.stringify(source),\n input.confidence ?? null,\n JSON.stringify(input.tags ?? []),\n status,\n sensitivity,\n JSON.stringify(input.evidence ?? []),\n reviewAfter,\n expiresAt,\n now,\n now,\n );\n upsertMemoryRecordFts(db, { ...input, id });\n });\n\n return {\n id,\n kind: input.kind,\n status,\n scope: {\n agentId: input.agentId,\n ...(input.workspaceId ? { workspaceId: input.workspaceId } : {}),\n ...(input.sessionKey ? { sessionKey: input.sessionKey } : {}),\n ...(input.projectId ? { projectId: input.projectId } : {}),\n },\n content: input.content,\n source,\n ...(input.confidence != null ? { confidence: input.confidence } : {}),\n sensitivity,\n evidence: input.evidence ?? [],\n ...(reviewAfter != null ? { reviewAfter: new Date(reviewAfter).toISOString() } : {}),\n ...(expiresAt != null ? { expiresAt: new Date(expiresAt).toISOString() } : {}),\n createdAt: new Date(now).toISOString(),\n updatedAt: new Date(now).toISOString(),\n tags: input.tags ?? [],\n };\n}\n\nexport function getMemoryRecord(recordId: string): MemoryRecord | null {\n const row = getSqliteDatabase()\n .prepare(`SELECT * FROM memory_records WHERE record_id = ?`)\n .get(recordId) as MemoryRecordRow | undefined;\n return row ? rowToRecord(row) : null;\n}\n\nexport function listMemoryRecords(options: ListMemoryRecordsOptions = {}): MemoryRecord[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.agentId) {\n where.push('agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n where.push('workspace_id = ?');\n params.push(options.workspaceId);\n }\n if (options.projectId) {\n where.push('project_id = ?');\n params.push(options.projectId);\n }\n if (options.kind) {\n where.push('kind = ?');\n params.push(options.kind);\n }\n if (options.status) {\n where.push('status = ?');\n params.push(options.status);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const offset = Math.max(0, options.offset ?? 0);\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_records\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY updated_at DESC\n LIMIT ? OFFSET ?`,\n )\n .all(...params, limit, offset) as MemoryRecordRow[];\n return rows.map(rowToRecord);\n}\n\nexport function searchMemoryRecords(options: SearchMemoryRecordsOptions): MemorySearchResult[] {\n const query = escapeFts5Query(options.query);\n if (!query) return [];\n\n const filters: string[] = ['memory_records_fts MATCH ?'];\n const params: Array<string | number | null> = [query];\n if (options.agentId) {\n filters.push('f.agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n filters.push('f.workspace_id = ?');\n params.push(options.workspaceId);\n }\n if (options.projectId) {\n filters.push('r.project_id = ?');\n params.push(options.projectId);\n }\n if (options.providerId) {\n filters.push('f.provider_id = ?');\n params.push(options.providerId);\n }\n if (options.kinds && options.kinds.length > 0) {\n filters.push(`f.kind IN (${options.kinds.map(() => '?').join(', ')})`);\n params.push(...options.kinds);\n }\n const statuses = options.statuses && options.statuses.length > 0 ? options.statuses : ['active'];\n filters.push(`r.status IN (${statuses.map(() => '?').join(', ')})`);\n params.push(...statuses);\n\n const maxResults = Math.max(1, Math.min(50, options.maxResults ?? 5));\n const minScore = options.minScore ?? 0;\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT\n r.*,\n bm25(memory_records_fts) AS rank\n FROM memory_records_fts f\n JOIN memory_records r ON r.record_id = f.record_id\n WHERE ${filters.join(' AND ')}\n ORDER BY rank\n LIMIT ?`,\n )\n .all(...params, maxResults * 3) as MemoryRecordSearchRow[];\n\n return rows\n .map((row) => {\n const record = rowToRecord(row);\n const score = bm25ToScore(row.rank);\n return {\n record,\n score,\n snippet: record.content,\n citation: {\n providerId: row.provider_id,\n recordId: row.record_id,\n path: record.source.path,\n lineStart: record.source.lineStart,\n lineEnd: record.source.lineEnd,\n createdAt: record.createdAt,\n },\n };\n })\n .filter((result) => result.score >= minScore)\n .slice(0, maxResults);\n}\n\nexport function deleteMemoryRecord(recordId: string): boolean {\n return runSqliteWriteTransaction((db) => {\n db.prepare(`DELETE FROM memory_records_fts WHERE record_id = ?`).run(recordId);\n const result = db.prepare(`DELETE FROM memory_records WHERE record_id = ?`).run(recordId);\n return result.changes > 0;\n });\n}\n\nexport function appendMemorySignal(input: AppendMemorySignalInput): string {\n const id = randomUUID();\n const now = input.nowMs ?? Date.now();\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_signals (\n signal_id, source, record_id, provider_id, agent_id, workspace_id,\n session_key, score, content, metadata_json, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.signal.source,\n input.signal.recordId ?? null,\n input.providerId ?? null,\n input.agentId ?? null,\n input.workspaceId ?? null,\n input.sessionKey ?? null,\n input.signal.score ?? null,\n input.signal.content ?? null,\n JSON.stringify(input.signal.metadata ?? {}),\n now,\n );\n if (input.signal.recordId) {\n db.prepare(\n `UPDATE memory_records\n SET recall_count = recall_count + 1, last_recalled_at = ?, updated_at = MAX(updated_at, ?)\n WHERE record_id = ?`,\n ).run(now, now, input.signal.recordId);\n }\n });\n return id;\n}\n\nexport function listMemorySignals(options: {\n recordId?: string;\n providerId?: string;\n agentId?: string;\n workspaceId?: string;\n limit?: number;\n} = {}): MemorySignalRowPayload[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.recordId) {\n where.push('record_id = ?');\n params.push(options.recordId);\n }\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.agentId) {\n where.push('agent_id = ?');\n params.push(options.agentId);\n }\n if (options.workspaceId) {\n where.push('workspace_id = ?');\n params.push(options.workspaceId);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_signals\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemorySignalRow[];\n return rows.map((row) => {\n let metadata: Record<string, unknown> = {};\n try {\n const parsed = JSON.parse(row.metadata_json) as unknown;\n if (parsed && typeof parsed === 'object') metadata = parsed as Record<string, unknown>;\n } catch {\n metadata = {};\n }\n return {\n signalId: row.signal_id,\n source: row.source,\n ...(row.record_id ? { recordId: row.record_id } : {}),\n ...(row.provider_id ? { providerId: row.provider_id } : {}),\n ...(row.agent_id ? { agentId: row.agent_id } : {}),\n ...(row.workspace_id ? { workspaceId: row.workspace_id } : {}),\n ...(row.session_key ? { sessionKey: row.session_key } : {}),\n ...(row.score != null ? { score: row.score } : {}),\n ...(row.content ? { content: row.content } : {}),\n metadata,\n createdAt: new Date(row.created_at).toISOString(),\n };\n });\n}\n\nexport function getMemoryProviderState(providerId: string, scopeKey: string): unknown | null {\n const row = getSqliteDatabase()\n .prepare(`SELECT state_json FROM memory_provider_state WHERE provider_id = ? AND scope_key = ?`)\n .get(providerId, scopeKey) as { state_json: string } | undefined;\n if (!row) return null;\n try {\n return JSON.parse(row.state_json) as unknown;\n } catch {\n return null;\n }\n}\n\nexport function setMemoryProviderState(providerId: string, scopeKey: string, state: unknown): void {\n const now = Date.now();\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_provider_state (provider_id, scope_key, state_json, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(provider_id, scope_key) DO UPDATE SET\n state_json = excluded.state_json,\n updated_at = excluded.updated_at`,\n ).run(providerId, scopeKey, JSON.stringify(state ?? null), now);\n });\n}\n\nexport function appendMemoryTraceEvent(input: AppendMemoryTraceEventInput): string {\n const id = randomUUID();\n const now = input.nowMs ?? Date.now();\n const feedback = input.feedback\n ? normalizeMemoryTraceFeedback(input.feedback, now)\n : undefined;\n runSqliteWriteTransaction((db) => {\n db.prepare(\n `INSERT INTO memory_trace_events (\n trace_id, session_key, turn_id, phase, provider_id, request_json,\n result_count, selected_record_ids_json, skipped_reason, error, feedback_json, duration_ms, created_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n ).run(\n id,\n input.sessionKey ?? null,\n input.turnId ?? null,\n input.phase,\n input.providerId,\n JSON.stringify(input.request ?? {}),\n input.resultCount ?? null,\n JSON.stringify(input.selectedRecordIds ?? []),\n input.skippedReason ?? null,\n input.error ?? null,\n JSON.stringify(feedback ?? {}),\n Math.max(0, Math.floor(input.durationMs ?? 0)),\n now,\n );\n });\n return id;\n}\n\nexport function listMemoryTraceEvents(options: {\n providerId?: string;\n sessionKey?: string;\n phase?: string;\n limit?: number;\n} = {}): MemoryTraceEventPayload[] {\n const where: string[] = [];\n const params: Array<string | number | null> = [];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.sessionKey) {\n where.push('session_key = ?');\n params.push(options.sessionKey);\n }\n if (options.phase) {\n where.push('phase = ?');\n params.push(options.phase);\n }\n const limit = Math.max(1, Math.min(500, options.limit ?? 100));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_trace_events\n ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemoryTraceRow[];\n return rows.map(memoryTraceRowToPayload);\n}\n\nexport function setMemoryTraceFeedback(input: SetMemoryTraceFeedbackInput): MemoryTraceEventPayload | null {\n const existing = getSqliteDatabase()\n .prepare(`SELECT * FROM memory_trace_events WHERE trace_id = ?`)\n .get(input.traceId) as MemoryTraceRow | undefined;\n if (!existing) {\n return null;\n }\n const feedback = normalizeMemoryTraceFeedback(\n input.feedback,\n input.nowMs,\n parseMemoryTraceFeedback(existing.feedback_json),\n );\n runSqliteWriteTransaction((db) => {\n db.prepare(`UPDATE memory_trace_events SET feedback_json = ? WHERE trace_id = ?`)\n .run(JSON.stringify(feedback), input.traceId);\n });\n return memoryTraceRowToPayload({ ...existing, feedback_json: JSON.stringify(feedback) });\n}\n\nexport function summarizeMemoryRecallFeedback(options: {\n recordId?: string;\n providerId?: string;\n sessionKey?: string;\n limit?: number;\n} = {}): MemoryRecallFeedbackSummary[] {\n const where = ['phase IN (?, ?)'];\n const params: Array<string | number> = ['search', 'inject'];\n if (options.providerId) {\n where.push('provider_id = ?');\n params.push(options.providerId);\n }\n if (options.sessionKey) {\n where.push('session_key = ?');\n params.push(options.sessionKey);\n }\n const limit = Math.max(1, Math.min(5000, options.limit ?? 1000));\n const rows = getSqliteDatabase()\n .prepare(\n `SELECT * FROM memory_trace_events\n WHERE ${where.join(' AND ')}\n ORDER BY created_at DESC\n LIMIT ?`,\n )\n .all(...params, limit) as MemoryTraceRow[];\n\n const summaries = new Map<string, MemoryRecallFeedbackSummary & { scoreTotal: number; scoreCount: number }>();\n for (const row of rows) {\n const feedback = parseMemoryTraceFeedback(row.feedback_json);\n if (!feedback) continue;\n const recordIds = parseStringArray(row.selected_record_ids_json);\n for (const recordId of recordIds) {\n if (options.recordId && recordId !== options.recordId) continue;\n const current = summaries.get(recordId) ?? {\n recordId,\n helpful: 0,\n notHelpful: 0,\n mixed: 0,\n irrelevant: 0,\n total: 0,\n averageScore: null,\n scoreTotal: 0,\n scoreCount: 0,\n };\n if (feedback.outcome === 'helpful') current.helpful += 1;\n if (feedback.outcome === 'not_helpful') current.notHelpful += 1;\n if (feedback.outcome === 'mixed') current.mixed += 1;\n if (feedback.outcome === 'irrelevant') current.irrelevant += 1;\n current.total += 1;\n if (typeof feedback.score === 'number') {\n current.scoreTotal += feedback.score;\n current.scoreCount += 1;\n current.averageScore = current.scoreTotal / current.scoreCount;\n }\n current.lastFeedbackAt ??= feedback.updatedAt ?? feedback.createdAt;\n summaries.set(recordId, current);\n }\n }\n\n return [...summaries.values()]\n .map(({ scoreTotal: _scoreTotal, scoreCount: _scoreCount, ...summary }) => summary)\n .sort((a, b) => b.total - a.total);\n}\n\nfunction parseJsonValue(json: string, fallback: unknown): unknown {\n try {\n return JSON.parse(json) as unknown;\n } catch {\n return fallback;\n }\n}\n"],"mappings":";;;;AAoMA,SAAS,iBAAiB,MAAwB;AAChD,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,MAAM,QAAQ,OAAO,GAAG,OAAO,QAAQ,MAAmB,OAAO,MAAM,SAAS,GAAG,EAAE;SACtF;AACN,SAAO,EAAE;;;AAIb,SAAS,cAAc,MAAwC;AAC7D,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,CAAC,MAAM,QAAQ,OAAO,CAAE,QAAO,EAAE;AACrC,SAAO,OAAO,QAAQ,SACpB,QAAQ,KAAK,IAAI,OAAO,SAAS,SAClC;SACK;AACN,SAAO,EAAE;;;AAIb,SAAS,yBAAyB,MAA+C;AAC/E,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO,KAAA;EAClD,MAAM,MAAM;EACZ,MAAM,UAAU,IAAI;AACpB,MACE,YAAY,aACZ,YAAY,iBACZ,YAAY,WACZ,YAAY,aAEZ;AAEF,SAAO;GACL;GACA,GAAI,OAAO,IAAI,UAAU,WAAW,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;GAC7D,GAAI,OAAO,IAAI,WAAW,WAAW,EAAE,QAAQ,IAAI,QAAQ,GAAG,EAAE;GAChE,GAAI,IAAI,WAAW,UAAU,IAAI,WAAW,eAAe,IAAI,WAAW,WACtE,EAAE,QAAQ,IAAI,QAAQ,GACtB,EAAE;GACN,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,6BAAY,IAAI,KAAK,EAAE,EAAC,aAAa;GACxF,GAAI,OAAO,IAAI,cAAc,WAAW,EAAE,WAAW,IAAI,WAAW,GAAG,EAAE;GAC1E;SACK;AACN;;;AAIJ,SAAS,6BACP,OACA,QAAQ,KAAK,KAAK,EAClB,UACqB;CACrB,MAAM,QAAQ,OAAO,MAAM,UAAU,WACjC,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,MAAM,CAAC,GACtC,KAAA;CACJ,MAAM,SAAS,OAAO,MAAM,WAAW,YAAY,MAAM,OAAO,MAAM,GAClE,MAAM,OAAO,MAAM,CAAC,MAAM,GAAG,IAAK,GAClC,KAAA;CACJ,MAAM,SAAS,IAAI,KAAK,MAAM,CAAC,aAAa;AAC5C,QAAO;EACL,SAAS,MAAM;EACf,GAAI,SAAS,OAAO,EAAE,OAAO,GAAG,EAAE;EAClC,GAAI,SAAS,EAAE,QAAQ,GAAG,EAAE;EAC5B,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,QAAQ,GAAG,EAAE;EAChD,WAAW,MAAM,aAAa,UAAU,aAAa;EACrD,WAAW,MAAM,aAAa;EAC/B;;AAGH,SAAS,wBAAwB,KAA8C;CAC7E,MAAM,WAAW,yBAAyB,IAAI,cAAc;AAC5D,QAAO;EACL,SAAS,IAAI;EACb,GAAI,IAAI,cAAc,EAAE,YAAY,IAAI,aAAa,GAAG,EAAE;EAC1D,GAAI,IAAI,UAAU,EAAE,QAAQ,IAAI,SAAS,GAAG,EAAE;EAC9C,OAAO,IAAI;EACX,YAAY,IAAI;EAChB,SAAS,eAAe,IAAI,cAAc,EAAE,CAAC;EAC7C,GAAI,IAAI,gBAAgB,OAAO,EAAE,aAAa,IAAI,cAAc,GAAG,EAAE;EACrE,mBAAmB,iBAAiB,IAAI,yBAAyB;EACjE,GAAI,IAAI,iBAAiB,EAAE,eAAe,IAAI,gBAAgB,GAAG,EAAE;EACnE,GAAI,IAAI,QAAQ,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;EACzC,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;EAChC,YAAY,IAAI;EAChB,WAAW,IAAI,KAAK,IAAI,WAAW,CAAC,aAAa;EAClD;;AAGH,SAAS,uBAAuB,OAA0C;AACxE,KAAI,CAAC,OAAO,MAAM,CAAE,QAAO;CAC3B,MAAM,SAAS,KAAK,MAAM,MAAM;AAChC,QAAO,OAAO,SAAS,OAAO,GAAG,SAAS;;AAG5C,SAAS,eAAe,OAA0C;AAChE,QAAO,SAAS,OAAO,KAAA,IAAY,IAAI,KAAK,MAAM,CAAC,aAAa;;AAGlE,SAAS,YAAY,MAAsC;AACzD,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,UAAU,OAAO,WAAW,WAAY,SAAoC,EAAE;SAC/E;AACN,SAAO,EAAE;;;AAIb,SAAS,YAAY,KAAoC;AACvD,QAAO;EACL,IAAI,IAAI;EACR,MAAM,IAAI;EACV,QAAQ,IAAI;EACZ,OAAO;GACL,SAAS,IAAI;GACb,GAAI,IAAI,eAAe,EAAE,aAAa,IAAI,cAAc,GAAG,EAAE;GAC7D,GAAI,IAAI,cAAc,EAAE,YAAY,IAAI,aAAa,GAAG,EAAE;GAC1D,GAAI,IAAI,aAAa,EAAE,WAAW,IAAI,YAAY,GAAG,EAAE;GACxD;EACD,SAAS,IAAI;EACb,QAAQ,YAAY,IAAI,YAAY;EACpC,GAAI,IAAI,cAAc,OAAO,EAAE,YAAY,IAAI,YAAY,GAAG,EAAE;EAChE,aAAa,IAAI;EACjB,UAAU,cAAc,IAAI,cAAc;EAC1C,GAAI,eAAe,IAAI,aAAa,GAAG,EAAE,aAAa,eAAe,IAAI,aAAa,EAAE,GAAG,EAAE;EAC7F,GAAI,eAAe,IAAI,WAAW,GAAG,EAAE,WAAW,eAAe,IAAI,WAAW,EAAE,GAAG,EAAE;EACvF,WAAW,IAAI,KAAK,IAAI,WAAW,CAAC,aAAa;EACjD,WAAW,IAAI,KAAK,IAAI,WAAW,CAAC,aAAa;EACjD,MAAM,iBAAiB,IAAI,UAAU;EACtC;;AAGH,SAAS,YAAY,MAAsB;AACzC,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,EAAE,CAAC;;AAG9D,SAAS,sBACP,IACA,KACM;AACN,IAAG,QAAQ,qDAAqD,CAAC,IAAI,IAAI,GAAG;AAC5E,KAAI,CAAC,IAAI,QAAQ,MAAM,CAAE;AACzB,IAAG,QACD;;iCAGD,CAAC,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,YAAY,IAAI,MAAM,IAAI,SAAS,IAAI,eAAe,KAAK;;AAG5F,SAAgB,mBAAmB,OAA8C;CAC/E,MAAM,KAAK,MAAM,MAAM,YAAY;CACnC,MAAM,MAAM,MAAM,SAAS,KAAK,KAAK;CACrC,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,cAAc,MAAM,eAAe;CACzC,MAAM,cAAc,uBAAuB,MAAM,YAAY;CAC7D,MAAM,YAAY,uBAAuB,MAAM,UAAU;CACzD,MAAM,SAAS;EACb,GAAI,MAAM,UAAU,EAAE;EACtB,UAAU,MAAM,QAAQ,YAAY,MAAM;EAC3C;AAED,4BAA2B,OAAO;AAChC,KAAG,QACD;;;;;;;;;;;;;;;;;;;;;0CAsBD,CAAC,IACA,IACA,MAAM,YACN,MAAM,MACN,MAAM,SACN,MAAM,eAAe,MACrB,MAAM,cAAc,MACpB,MAAM,aAAa,MACnB,MAAM,SACN,KAAK,UAAU,OAAO,EACtB,MAAM,cAAc,MACpB,KAAK,UAAU,MAAM,QAAQ,EAAE,CAAC,EAChC,QACA,aACA,KAAK,UAAU,MAAM,YAAY,EAAE,CAAC,EACpC,aACA,WACA,KACA,IACD;AACD,wBAAsB,IAAI;GAAE,GAAG;GAAO;GAAI,CAAC;GAC3C;AAEF,QAAO;EACL;EACA,MAAM,MAAM;EACZ;EACA,OAAO;GACL,SAAS,MAAM;GACf,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,aAAa,GAAG,EAAE;GAC/D,GAAI,MAAM,aAAa,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;GAC5D,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,WAAW,GAAG,EAAE;GAC1D;EACD,SAAS,MAAM;EACf;EACA,GAAI,MAAM,cAAc,OAAO,EAAE,YAAY,MAAM,YAAY,GAAG,EAAE;EACpE;EACA,UAAU,MAAM,YAAY,EAAE;EAC9B,GAAI,eAAe,OAAO,EAAE,aAAa,IAAI,KAAK,YAAY,CAAC,aAAa,EAAE,GAAG,EAAE;EACnF,GAAI,aAAa,OAAO,EAAE,WAAW,IAAI,KAAK,UAAU,CAAC,aAAa,EAAE,GAAG,EAAE;EAC7E,WAAW,IAAI,KAAK,IAAI,CAAC,aAAa;EACtC,WAAW,IAAI,KAAK,IAAI,CAAC,aAAa;EACtC,MAAM,MAAM,QAAQ,EAAE;EACvB;;AAGH,SAAgB,gBAAgB,UAAuC;CACrE,MAAM,MAAM,mBAAmB,CAC5B,QAAQ,mDAAmD,CAC3D,IAAI,SAAS;AAChB,QAAO,MAAM,YAAY,IAAI,GAAG;;AAGlC,SAAgB,kBAAkB,UAAoC,EAAE,EAAkB;CACxF,MAAM,QAAkB,EAAE;CAC1B,MAAM,SAAwC,EAAE;AAChD,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,SAAS;AACnB,QAAM,KAAK,eAAe;AAC1B,SAAO,KAAK,QAAQ,QAAQ;;AAE9B,KAAI,QAAQ,aAAa;AACvB,QAAM,KAAK,mBAAmB;AAC9B,SAAO,KAAK,QAAQ,YAAY;;AAElC,KAAI,QAAQ,WAAW;AACrB,QAAM,KAAK,iBAAiB;AAC5B,SAAO,KAAK,QAAQ,UAAU;;AAEhC,KAAI,QAAQ,MAAM;AAChB,QAAM,KAAK,WAAW;AACtB,SAAO,KAAK,QAAQ,KAAK;;AAE3B,KAAI,QAAQ,QAAQ;AAClB,QAAM,KAAK,aAAa;AACxB,SAAO,KAAK,QAAQ,OAAO;;CAE7B,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,SAAS,IAAI,CAAC;CAC9D,MAAM,SAAS,KAAK,IAAI,GAAG,QAAQ,UAAU,EAAE;AAS/C,QARa,mBAAmB,CAC7B,QACC;SACG,MAAM,SAAS,IAAI,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG;;yBAG3D,CACA,IAAI,GAAG,QAAQ,OAAO,OACd,CAAC,IAAI,YAAY;;AAG9B,SAAgB,oBAAoB,SAA2D;CAC7F,MAAM,QAAQ,gBAAgB,QAAQ,MAAM;AAC5C,KAAI,CAAC,MAAO,QAAO,EAAE;CAErB,MAAM,UAAoB,CAAC,6BAA6B;CACxD,MAAM,SAAwC,CAAC,MAAM;AACrD,KAAI,QAAQ,SAAS;AACnB,UAAQ,KAAK,iBAAiB;AAC9B,SAAO,KAAK,QAAQ,QAAQ;;AAE9B,KAAI,QAAQ,aAAa;AACvB,UAAQ,KAAK,qBAAqB;AAClC,SAAO,KAAK,QAAQ,YAAY;;AAElC,KAAI,QAAQ,WAAW;AACrB,UAAQ,KAAK,mBAAmB;AAChC,SAAO,KAAK,QAAQ,UAAU;;AAEhC,KAAI,QAAQ,YAAY;AACtB,UAAQ,KAAK,oBAAoB;AACjC,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS,GAAG;AAC7C,UAAQ,KAAK,cAAc,QAAQ,MAAM,UAAU,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG;AACtE,SAAO,KAAK,GAAG,QAAQ,MAAM;;CAE/B,MAAM,WAAW,QAAQ,YAAY,QAAQ,SAAS,SAAS,IAAI,QAAQ,WAAW,CAAC,SAAS;AAChG,SAAQ,KAAK,gBAAgB,SAAS,UAAU,IAAI,CAAC,KAAK,KAAK,CAAC,GAAG;AACnE,QAAO,KAAK,GAAG,SAAS;CAExB,MAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,QAAQ,cAAc,EAAE,CAAC;CACrE,MAAM,WAAW,QAAQ,YAAY;AAcrC,QAba,mBAAmB,CAC7B,QACC;;;;;eAKS,QAAQ,KAAK,QAAQ,CAAC;;gBAGhC,CACA,IAAI,GAAG,QAAQ,aAAa,EAEpB,CACR,KAAK,QAAQ;EACZ,MAAM,SAAS,YAAY,IAAI;AAE/B,SAAO;GACL;GACA,OAHY,YAAY,IAAI,KAGvB;GACL,SAAS,OAAO;GAChB,UAAU;IACR,YAAY,IAAI;IAChB,UAAU,IAAI;IACd,MAAM,OAAO,OAAO;IACpB,WAAW,OAAO,OAAO;IACzB,SAAS,OAAO,OAAO;IACvB,WAAW,OAAO;IACnB;GACF;GACD,CACD,QAAQ,WAAW,OAAO,SAAS,SAAS,CAC5C,MAAM,GAAG,WAAW;;AAGzB,SAAgB,mBAAmB,UAA2B;AAC5D,QAAO,2BAA2B,OAAO;AACvC,KAAG,QAAQ,qDAAqD,CAAC,IAAI,SAAS;AAE9E,SADe,GAAG,QAAQ,iDAAiD,CAAC,IAAI,SACnE,CAAC,UAAU;GACxB;;AAGJ,SAAgB,mBAAmB,OAAwC;CACzE,MAAM,KAAK,YAAY;CACvB,MAAM,MAAM,MAAM,SAAS,KAAK,KAAK;AACrC,4BAA2B,OAAO;AAChC,KAAG,QACD;;;kDAID,CAAC,IACA,IACA,MAAM,OAAO,QACb,MAAM,OAAO,YAAY,MACzB,MAAM,cAAc,MACpB,MAAM,WAAW,MACjB,MAAM,eAAe,MACrB,MAAM,cAAc,MACpB,MAAM,OAAO,SAAS,MACtB,MAAM,OAAO,WAAW,MACxB,KAAK,UAAU,MAAM,OAAO,YAAY,EAAE,CAAC,EAC3C,IACD;AACD,MAAI,MAAM,OAAO,SACf,IAAG,QACD;;8BAGD,CAAC,IAAI,KAAK,KAAK,MAAM,OAAO,SAAS;GAExC;AACF,QAAO;;AAGT,SAAgB,kBAAkB,UAM9B,EAAE,EAA4B;CAChC,MAAM,QAAkB,EAAE;CAC1B,MAAM,SAAwC,EAAE;AAChD,KAAI,QAAQ,UAAU;AACpB,QAAM,KAAK,gBAAgB;AAC3B,SAAO,KAAK,QAAQ,SAAS;;AAE/B,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,SAAS;AACnB,QAAM,KAAK,eAAe;AAC1B,SAAO,KAAK,QAAQ,QAAQ;;AAE9B,KAAI,QAAQ,aAAa;AACvB,QAAM,KAAK,mBAAmB;AAC9B,SAAO,KAAK,QAAQ,YAAY;;CAElC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,SAAS,IAAI,CAAC;AAS9D,QARa,mBAAmB,CAC7B,QACC;SACG,MAAM,SAAS,IAAI,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG;;gBAG3D,CACA,IAAI,GAAG,QAAQ,MACP,CAAC,KAAK,QAAQ;EACvB,IAAI,WAAoC,EAAE;AAC1C,MAAI;GACF,MAAM,SAAS,KAAK,MAAM,IAAI,cAAc;AAC5C,OAAI,UAAU,OAAO,WAAW,SAAU,YAAW;UAC/C;AACN,cAAW,EAAE;;AAEf,SAAO;GACL,UAAU,IAAI;GACd,QAAQ,IAAI;GACZ,GAAI,IAAI,YAAY,EAAE,UAAU,IAAI,WAAW,GAAG,EAAE;GACpD,GAAI,IAAI,cAAc,EAAE,YAAY,IAAI,aAAa,GAAG,EAAE;GAC1D,GAAI,IAAI,WAAW,EAAE,SAAS,IAAI,UAAU,GAAG,EAAE;GACjD,GAAI,IAAI,eAAe,EAAE,aAAa,IAAI,cAAc,GAAG,EAAE;GAC7D,GAAI,IAAI,cAAc,EAAE,YAAY,IAAI,aAAa,GAAG,EAAE;GAC1D,GAAI,IAAI,SAAS,OAAO,EAAE,OAAO,IAAI,OAAO,GAAG,EAAE;GACjD,GAAI,IAAI,UAAU,EAAE,SAAS,IAAI,SAAS,GAAG,EAAE;GAC/C;GACA,WAAW,IAAI,KAAK,IAAI,WAAW,CAAC,aAAa;GAClD;GACD;;AAGJ,SAAgB,uBAAuB,YAAoB,UAAkC;CAC3F,MAAM,MAAM,mBAAmB,CAC5B,QAAQ,uFAAuF,CAC/F,IAAI,YAAY,SAAS;AAC5B,KAAI,CAAC,IAAK,QAAO;AACjB,KAAI;AACF,SAAO,KAAK,MAAM,IAAI,WAAW;SAC3B;AACN,SAAO;;;AAIX,SAAgB,uBAAuB,YAAoB,UAAkB,OAAsB;CACjG,MAAM,MAAM,KAAK,KAAK;AACtB,4BAA2B,OAAO;AAChC,KAAG,QACD;;;;2CAKD,CAAC,IAAI,YAAY,UAAU,KAAK,UAAU,SAAS,KAAK,EAAE,IAAI;GAC/D;;AAGJ,SAAgB,uBAAuB,OAA4C;CACjF,MAAM,KAAK,YAAY;CACvB,MAAM,MAAM,MAAM,SAAS,KAAK,KAAK;CACrC,MAAM,WAAW,MAAM,WACnB,6BAA6B,MAAM,UAAU,IAAI,GACjD,KAAA;AACJ,4BAA2B,OAAO;AAChC,KAAG,QACD;;;wDAID,CAAC,IACA,IACA,MAAM,cAAc,MACpB,MAAM,UAAU,MAChB,MAAM,OACN,MAAM,YACN,KAAK,UAAU,MAAM,WAAW,EAAE,CAAC,EACnC,MAAM,eAAe,MACrB,KAAK,UAAU,MAAM,qBAAqB,EAAE,CAAC,EAC7C,MAAM,iBAAiB,MACvB,MAAM,SAAS,MACf,KAAK,UAAU,YAAY,EAAE,CAAC,EAC9B,KAAK,IAAI,GAAG,KAAK,MAAM,MAAM,cAAc,EAAE,CAAC,EAC9C,IACD;GACD;AACF,QAAO;;AAGT,SAAgB,sBAAsB,UAKlC,EAAE,EAA6B;CACjC,MAAM,QAAkB,EAAE;CAC1B,MAAM,SAAwC,EAAE;AAChD,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,OAAO;AACjB,QAAM,KAAK,YAAY;AACvB,SAAO,KAAK,QAAQ,MAAM;;CAE5B,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,QAAQ,SAAS,IAAI,CAAC;AAS9D,QARa,mBAAmB,CAC7B,QACC;SACG,MAAM,SAAS,IAAI,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG;;gBAG3D,CACA,IAAI,GAAG,QAAQ,MACP,CAAC,IAAI,wBAAwB;;AAG1C,SAAgB,uBAAuB,OAAoE;CACzG,MAAM,WAAW,mBAAmB,CACjC,QAAQ,uDAAuD,CAC/D,IAAI,MAAM,QAAQ;AACrB,KAAI,CAAC,SACH,QAAO;CAET,MAAM,WAAW,6BACf,MAAM,UACN,MAAM,OACN,yBAAyB,SAAS,cAAc,CACjD;AACD,4BAA2B,OAAO;AAChC,KAAG,QAAQ,sEAAsE,CAC9E,IAAI,KAAK,UAAU,SAAS,EAAE,MAAM,QAAQ;GAC/C;AACF,QAAO,wBAAwB;EAAE,GAAG;EAAU,eAAe,KAAK,UAAU,SAAS;EAAE,CAAC;;AAG1F,SAAgB,8BAA8B,UAK1C,EAAE,EAAiC;CACrC,MAAM,QAAQ,CAAC,kBAAkB;CACjC,MAAM,SAAiC,CAAC,UAAU,SAAS;AAC3D,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;AAEjC,KAAI,QAAQ,YAAY;AACtB,QAAM,KAAK,kBAAkB;AAC7B,SAAO,KAAK,QAAQ,WAAW;;CAEjC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,KAAM,QAAQ,SAAS,IAAK,CAAC;CAChE,MAAM,OAAO,mBAAmB,CAC7B,QACC;eACS,MAAM,KAAK,QAAQ,CAAC;;gBAG9B,CACA,IAAI,GAAG,QAAQ,MAAM;CAExB,MAAM,4BAAY,IAAI,KAAuF;AAC7G,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,WAAW,yBAAyB,IAAI,cAAc;AAC5D,MAAI,CAAC,SAAU;EACf,MAAM,YAAY,iBAAiB,IAAI,yBAAyB;AAChE,OAAK,MAAM,YAAY,WAAW;AAChC,OAAI,QAAQ,YAAY,aAAa,QAAQ,SAAU;GACvD,MAAM,UAAU,UAAU,IAAI,SAAS,IAAI;IACzC;IACA,SAAS;IACT,YAAY;IACZ,OAAO;IACP,YAAY;IACZ,OAAO;IACP,cAAc;IACd,YAAY;IACZ,YAAY;IACb;AACD,OAAI,SAAS,YAAY,UAAW,SAAQ,WAAW;AACvD,OAAI,SAAS,YAAY,cAAe,SAAQ,cAAc;AAC9D,OAAI,SAAS,YAAY,QAAS,SAAQ,SAAS;AACnD,OAAI,SAAS,YAAY,aAAc,SAAQ,cAAc;AAC7D,WAAQ,SAAS;AACjB,OAAI,OAAO,SAAS,UAAU,UAAU;AACtC,YAAQ,cAAc,SAAS;AAC/B,YAAQ,cAAc;AACtB,YAAQ,eAAe,QAAQ,aAAa,QAAQ;;AAEtD,WAAQ,mBAAmB,SAAS,aAAa,SAAS;AAC1D,aAAU,IAAI,UAAU,QAAQ;;;AAIpC,QAAO,CAAC,GAAG,UAAU,QAAQ,CAAC,CAC3B,KAAK,EAAE,YAAY,aAAa,YAAY,aAAa,GAAG,cAAc,QAAQ,CAClF,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;AAGtC,SAAS,eAAe,MAAc,UAA4B;AAChE,KAAI;AACF,SAAO,KAAK,MAAM,KAAK;SACjB;AACN,SAAO"}
@@ -0,0 +1,40 @@
1
+ CREATE TABLE IF NOT EXISTS projects (
2
+ project_id TEXT PRIMARY KEY,
3
+ name TEXT NOT NULL,
4
+ slug TEXT NOT NULL UNIQUE,
5
+ description TEXT,
6
+ status TEXT NOT NULL DEFAULT 'active',
7
+ workspace_root TEXT,
8
+ brief TEXT,
9
+ instructions TEXT,
10
+ created_at INTEGER NOT NULL,
11
+ updated_at INTEGER NOT NULL,
12
+ last_active_at INTEGER
13
+ );
14
+
15
+ CREATE INDEX IF NOT EXISTS idx_projects_status
16
+ ON projects(status, updated_at DESC);
17
+ CREATE INDEX IF NOT EXISTS idx_projects_slug
18
+ ON projects(slug);
19
+ CREATE INDEX IF NOT EXISTS idx_projects_updated
20
+ ON projects(updated_at DESC);
21
+
22
+ ALTER TABLE sessions ADD COLUMN project_id TEXT;
23
+ CREATE INDEX IF NOT EXISTS idx_sessions_project
24
+ ON sessions(project_id, updated_at DESC);
25
+
26
+ ALTER TABLE goals ADD COLUMN project_id TEXT;
27
+ CREATE INDEX IF NOT EXISTS idx_goals_project
28
+ ON goals(project_id, updated_at DESC);
29
+
30
+ ALTER TABLE workflow_runs ADD COLUMN project_id TEXT;
31
+ CREATE INDEX IF NOT EXISTS idx_workflow_runs_project
32
+ ON workflow_runs(project_id, created_at_ms DESC);
33
+
34
+ ALTER TABLE automations ADD COLUMN project_id TEXT;
35
+ CREATE INDEX IF NOT EXISTS idx_automations_project
36
+ ON automations(project_id, updated_at_ms DESC);
37
+
38
+ ALTER TABLE memory_records ADD COLUMN project_id TEXT;
39
+ CREATE INDEX IF NOT EXISTS idx_memory_records_project
40
+ ON memory_records(project_id, updated_at DESC);
@@ -0,0 +1 @@
1
+ ALTER TABLE projects ADD COLUMN default_agent_id TEXT;
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 18;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 20;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.