@xopcai/xopc 0.0.307 → 0.0.309

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 (261) hide show
  1. package/dist/browser-ext/_locales/en/messages.json +8 -0
  2. package/dist/browser-ext/_locales/zh_CN/messages.json +8 -0
  3. package/dist/browser-ext/dist/assets/{sidepanel-BbSQr-6P.css → sidepanel-DD6GEMvc.css} +16 -0
  4. package/dist/browser-ext/dist/sidepanel.html +1 -1
  5. package/dist/browser-ext/dist/sidepanel.js +537 -96
  6. package/dist/browser-ext/manifest.json +1 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/gateway/static/root/assets/{activity-store-wgSB2HYK.js → activity-store-XKNYlFUI.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CZeQo09T.js → agent-avatar-dicebear-1S2TFECE.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-f0-YFMUz.js +1 -0
  11. package/dist/gateway/static/root/assets/{agents-BlrHMbRx.js → agents-CPqUMtCL.js} +1 -1
  12. package/dist/gateway/static/root/assets/{api-BKHmTb0w.js → api-BEUEE4f2.js} +1 -1
  13. package/dist/gateway/static/root/assets/api-CN4id43t.js +1 -0
  14. package/dist/gateway/static/root/assets/{app-management-settings-panel-Bzw4fQP8.js → app-management-settings-panel-CgVBSqzu.js} +1 -1
  15. package/dist/gateway/static/root/assets/{appearance-settings-8GZpUXva.js → appearance-settings-CoWdCokb.js} +1 -1
  16. package/dist/gateway/static/root/assets/{apps-page-BkQQtIxH.js → apps-page-CexHOcWg.js} +1 -1
  17. package/dist/gateway/static/root/assets/{archive-plugin-CQ2NaoHb.js → archive-plugin-C3ZA6LRS.js} +1 -1
  18. package/dist/gateway/static/root/assets/{attachment-load-BFi1H7yJ.js → attachment-load-CdgS6_zy.js} +1 -1
  19. package/dist/gateway/static/root/assets/{automations-page-CDBXcii_.js → automations-page-BtHL2hpg.js} +1 -1
  20. package/dist/gateway/static/root/assets/automations-workspace-onJPfmO6.js +6 -0
  21. package/dist/gateway/static/root/assets/{binary-plugins-D07eWmOx.js → binary-plugins-CiDhtq_H.js} +1 -1
  22. package/dist/gateway/static/root/assets/{block-editor-CtVnjyYU.js → block-editor-Br00T83w.js} +3 -3
  23. package/dist/gateway/static/root/assets/{browser-automation-inputs-BzkJog8e.js → browser-automation-inputs-D2tILykA.js} +1 -1
  24. package/dist/gateway/static/root/assets/{browser-automations-page-DyrSbDdG.js → browser-automations-page-BVuEmryB.js} +1 -1
  25. package/dist/gateway/static/root/assets/browser-settings-page-BgVTyPFY.js +3 -0
  26. package/dist/gateway/static/root/assets/capabilities-settings-panel-Dra8wj1S.js +8 -0
  27. package/dist/gateway/static/root/assets/{channels-settings-DAD9qE3J.js → channels-settings-CkxiMDJ4.js} +1 -1
  28. package/dist/gateway/static/root/assets/{channels-status-swr-B2JwuTjG.js → channels-status-swr-Dtder4G_.js} +1 -1
  29. package/dist/gateway/static/root/assets/{chat-terminal-dock-B62SZdAo.js → chat-terminal-dock-JsMtzDao.js} +1 -1
  30. package/dist/gateway/static/root/assets/{computer-settings-page-ClSresNq.js → computer-settings-page-DHerePwo.js} +1 -1
  31. package/dist/gateway/static/root/assets/connector-service-page-DZFNUTiN.js +1 -0
  32. package/dist/gateway/static/root/assets/connectors-page-cl9ZrV4D.js +2 -0
  33. package/dist/gateway/static/root/assets/{cron-expression-CTMi_tql.js → cron-expression-DAhdv_Xv.js} +1 -1
  34. package/dist/gateway/static/root/assets/{date-picker-B71AJK50.js → date-picker-PacO1m3a.js} +1 -1
  35. package/dist/gateway/static/root/assets/{dependency-picker-DlyGK-kA.js → dependency-picker-B-BcuG1y.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-DGkbTE8_.js → desktop-pet-CdBBhhdY.js} +1 -1
  37. package/dist/gateway/static/root/assets/{desktop-pet-settings-BY8r9j66.js → desktop-pet-settings-Gy03NgMI.js} +1 -1
  38. package/dist/gateway/static/root/assets/{device-pairing-wizard-DzRrgd59.js → device-pairing-wizard-aV25nKag.js} +1 -1
  39. package/dist/gateway/static/root/assets/{extension-debug-page-L8Mm1n3A.js → extension-debug-page-BFp5eKtY.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-page-CFc4vSNU.js → extension-page-DL3vyyH6.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-settings-page-B5zWyHr3.js → extension-settings-page-BXtvdAsY.js} +1 -1
  42. package/dist/gateway/static/root/assets/{gateway-config-swr-B6wHa6ZI.js → gateway-config-swr-xAOGtenO.js} +1 -1
  43. package/dist/gateway/static/root/assets/{gateway-realtime-B53R0CA4.js → gateway-realtime-BuaTsMSi.js} +1 -1
  44. package/dist/gateway/static/root/assets/gateway-realtime-store-BG95uGVW.js +1 -0
  45. package/dist/gateway/static/root/assets/{gateway-settings-D7qmTH4R.js → gateway-settings-Dcr2Ikeh.js} +1 -1
  46. package/dist/gateway/static/root/assets/{gateway-startup-retry-DRzGnEV-.js → gateway-startup-retry-BwDxKHd4.js} +1 -1
  47. package/dist/gateway/static/root/assets/{heartbeat-settings-Glsl3X5b.js → heartbeat-settings-DOy3alvT.js} +1 -1
  48. package/dist/gateway/static/root/assets/home-page-CDm3dGVy.js +1 -0
  49. package/dist/gateway/static/root/assets/{image-generation-api-Ck_pyDom.js → image-generation-api-wGMeI_yW.js} +1 -1
  50. package/dist/gateway/static/root/assets/{imports-page-ByBX7ome.js → imports-page-zexFT5Rq.js} +1 -1
  51. package/dist/gateway/static/root/assets/index-D-vczw_0.css +1 -0
  52. package/dist/gateway/static/root/assets/index-DJo4DimT.js +79 -0
  53. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-C45RlO8a.js → keyboard-shortcuts-settings-CutG9zLh.js} +1 -1
  54. package/dist/gateway/static/root/assets/{local-app-workbench-page-DP0x2jpR.js → local-app-workbench-page-CwLvTwjn.js} +2 -2
  55. package/dist/gateway/static/root/assets/{local-apps-page-C_AQc2bI.js → local-apps-page-CJy6I7Dt.js} +1 -1
  56. package/dist/gateway/static/root/assets/{locale-store-msTfRK8P.js → locale-store-DPZ79W1-.js} +1 -1
  57. package/dist/gateway/static/root/assets/{logs-page-DvM8Pyok.js → logs-page-egGcPHNi.js} +1 -1
  58. package/dist/gateway/static/root/assets/{management-settings-D1uwSutV.js → management-settings-BQhIOELc.js} +1 -1
  59. package/dist/gateway/static/root/assets/{markdown-view-BInabSKf.js → markdown-view-p2P5hP1U.js} +1 -1
  60. package/dist/gateway/static/root/assets/{media-plugins-C4mhf13f.js → media-plugins-CsBylqlN.js} +1 -1
  61. package/dist/gateway/static/root/assets/messages-BiYTyLJr.js +3 -0
  62. package/dist/gateway/static/root/assets/note-detail-panel-c2k5Uz6X.js +5 -0
  63. package/dist/gateway/static/root/assets/notes-page-BLQWJMhf.js +8 -0
  64. package/dist/gateway/static/root/assets/{page-tabs-1go_BtX1.js → page-tabs-ChQ4jJFs.js} +1 -1
  65. package/dist/gateway/static/root/assets/{preview-open-alternatives-DmoSC0j1.js → preview-open-alternatives-9B5W7nVE.js} +1 -1
  66. package/dist/gateway/static/root/assets/{proactive-page-xAjKTIID.js → proactive-page-iOjI0d_e.js} +1 -1
  67. package/dist/gateway/static/root/assets/{product-open-page-gmi5LLwM.js → product-open-page-BADxWEdP.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-BcxbQn2M.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-BuSvld0O.js +1 -0
  70. package/dist/gateway/static/root/assets/{registry-api-BSWtko7U.js → registry-api-B_e_nZSN.js} +1 -1
  71. package/dist/gateway/static/root/assets/remote-access-hub-CFS8LQKW.js +1 -0
  72. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-ClkOoxDl.js → runtime-tools-settings-panel-D-pwiIyp.js} +1 -1
  73. package/dist/gateway/static/root/assets/{schema-form-BuEmLiaU.js → schema-form-IWmb05DX.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-DZjc__ok.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-C1SM5B93.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-Dor39QON.js → settings-form-section-B0veRBZs.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-Xj-yvIc8.js → settings-page-CxRWyWYe.js} +1 -1
  78. package/dist/gateway/static/root/assets/setup-status-panel-D9Rl7Tec.js +1 -0
  79. package/dist/gateway/static/root/assets/{share-preview-page-BFWZoXdm.js → share-preview-page-CirpgkfD.js} +1 -1
  80. package/dist/gateway/static/root/assets/shares-settings-CwCThBs0.js +1 -0
  81. package/dist/gateway/static/root/assets/skill-reload-api-DG6VGbOX.js +1 -0
  82. package/dist/gateway/static/root/assets/skills-page-BdRJ2vnL.js +2 -0
  83. package/dist/gateway/static/root/assets/{skills-page.utils-Ii8qeXhs.js → skills-page.utils-B42mpWKV.js} +1 -1
  84. package/dist/gateway/static/root/assets/{system-settings-panel-Di6OSO-0.js → system-settings-panel-DXIZpAvU.js} +1 -1
  85. package/dist/gateway/static/root/assets/task-detail-page-QXo9LJly.js +1 -0
  86. package/dist/gateway/static/root/assets/{theme-store-1SZ-HFHX.js → theme-store-BFbj_2Tu.js} +1 -1
  87. package/dist/gateway/static/root/assets/{tunnel-api-DDOlOYlj.js → tunnel-api-Db2guRdW.js} +1 -1
  88. package/dist/gateway/static/root/assets/{use-autosave-CQ8uWNnB.js → use-autosave-DDY9qoXZ.js} +1 -1
  89. package/dist/gateway/static/root/assets/user-model-page-CzPmMkaO.js +2 -0
  90. package/dist/gateway/static/root/assets/{voice-api-key-field-COTzshjL.js → voice-api-key-field-BZbKQ8HT.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-config-api-DgJML_uM.js → voice-config-api-SKCeQLrH.js} +1 -1
  92. package/dist/gateway/static/root/assets/{work-discovery-overlay-_URrXbi4.js → work-discovery-overlay-BRVTTXNG.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CALs-1nd.js → workflow-run-setup-panel-D2kuwv5e.js} +2 -2
  94. package/dist/gateway/static/root/assets/workflows-page-CQXtiYtq.js +6 -0
  95. package/dist/gateway/static/root/index.html +12 -12
  96. package/dist/package.js +1 -1
  97. package/dist/packages/gateway-contract/src/notifications.js +1 -1
  98. package/dist/packages/gateway-contract/src/sessions.js +6 -1
  99. package/dist/src/agent/agent-manager.js +29 -4
  100. package/dist/src/agent/background-review/prompts.js +3 -1
  101. package/dist/src/agent/child-agent-factory.d.ts +1 -0
  102. package/dist/src/agent/child-agent-factory.js +18 -4
  103. package/dist/src/agent/coding/repository-instructions.d.ts +4 -0
  104. package/dist/src/agent/coding/repository-instructions.js +46 -2
  105. package/dist/src/agent/context/execution-context.js +4 -4
  106. package/dist/src/agent/data-acquisition/git.d.ts +17 -0
  107. package/dist/src/agent/data-acquisition/git.js +100 -0
  108. package/dist/src/agent/data-acquisition/render.d.ts +7 -0
  109. package/dist/src/agent/data-acquisition/render.js +79 -0
  110. package/dist/src/agent/data-acquisition/scheduler.d.ts +12 -0
  111. package/dist/src/agent/data-acquisition/scheduler.js +53 -0
  112. package/dist/src/agent/data-acquisition/schema.d.ts +75 -0
  113. package/dist/src/agent/data-acquisition/schema.js +206 -0
  114. package/dist/src/agent/data-acquisition/service.d.ts +10 -0
  115. package/dist/src/agent/data-acquisition/service.js +292 -0
  116. package/dist/src/agent/data-acquisition/types.d.ts +37 -0
  117. package/dist/src/agent/data-acquisition/types.js +5 -0
  118. package/dist/src/agent/embedded/run-turn.js +16 -4
  119. package/dist/src/agent/embedded/session-runner.d.ts +1 -0
  120. package/dist/src/agent/embedded/session-runner.js +3 -0
  121. package/dist/src/agent/embedded/tool-result-truncation.js +11 -0
  122. package/dist/src/agent/embedded/xopc-tools-bridge.js +2 -1
  123. package/dist/src/agent/external-tools/composio-provider.js +12 -1
  124. package/dist/src/agent/external-tools/gateway-tools.js +2 -1
  125. package/dist/src/agent/external-tools/index.js +8 -1
  126. package/dist/src/agent/external-tools/read-policy.d.ts +6 -0
  127. package/dist/src/agent/external-tools/read-policy.js +21 -0
  128. package/dist/src/agent/external-tools/service.d.ts +1 -0
  129. package/dist/src/agent/external-tools/service.js +4 -1
  130. package/dist/src/agent/external-tools/types.d.ts +2 -0
  131. package/dist/src/agent/memory/compaction-promotion.d.ts +1 -1
  132. package/dist/src/agent/memory/compaction-promotion.js +4 -3
  133. package/dist/src/agent/orchestration/agent-turn-policy.js +25 -10
  134. package/dist/src/agent/orchestration/delegation-scope.d.ts +9 -0
  135. package/dist/src/agent/orchestration/delegation-scope.js +11 -0
  136. package/dist/src/agent/prompt/sections/tooling.js +3 -1
  137. package/dist/src/agent/prompt/subagent-context.js +4 -2
  138. package/dist/src/agent/sandbox/fileAccess.d.ts +2 -0
  139. package/dist/src/agent/sandbox/fileAccess.js +31 -2
  140. package/dist/src/agent/tools/dataBatch.d.ts +4 -0
  141. package/dist/src/agent/tools/dataBatch.js +50 -0
  142. package/dist/src/agent/tools/delegate-tool.d.ts +6 -3
  143. package/dist/src/agent/tools/delegate-tool.js +65 -48
  144. package/dist/src/agent/tools/delegation-parent-policy.d.ts +7 -0
  145. package/dist/src/agent/tools/delegation-parent-policy.js +41 -0
  146. package/dist/src/agent/tools/delegation-policy.d.ts +16 -0
  147. package/dist/src/agent/tools/delegation-policy.js +93 -0
  148. package/dist/src/agent/tools/factory.d.ts +2 -0
  149. package/dist/src/agent/tools/factory.js +42 -3
  150. package/dist/src/agent/tools/fetch-text.d.ts +7 -0
  151. package/dist/src/agent/tools/fetch-text.js +86 -0
  152. package/dist/src/agent/tools/find.js +1 -1
  153. package/dist/src/agent/tools/grep.js +11 -23
  154. package/dist/src/agent/tools/index.d.ts +1 -0
  155. package/dist/src/agent/tools/index.js +2 -1
  156. package/dist/src/agent/tools/knowledge-memory-tool.d.ts +1 -1
  157. package/dist/src/agent/tools/knowledge-memory-tool.js +13 -5
  158. package/dist/src/agent/tools/read.js +7 -5
  159. package/dist/src/agent/tools/repository-search.d.ts +12 -2
  160. package/dist/src/agent/tools/repository-search.js +127 -74
  161. package/dist/src/agent/tools/user-context-tool.js +17 -7
  162. package/dist/src/agent/tools/web.js +19 -28
  163. package/dist/src/agent/workflow/subagent-runner.js +25 -3
  164. package/dist/src/agent/workflow/workflow-child-tools.js +13 -8
  165. package/dist/src/agent-config/schema.d.ts +7 -0
  166. package/dist/src/agent-config/schema.js +2 -0
  167. package/dist/src/chat-commands/builtins/understanding.js +1 -1
  168. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  169. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  170. package/dist/src/config/schema.d.ts +6 -4
  171. package/dist/src/config/schema.js +2 -2
  172. package/dist/src/connectors/connected-source-understanding.d.ts +1 -0
  173. package/dist/src/connectors/connected-source-understanding.js +1 -0
  174. package/dist/src/connectors/learning-coordinator.js +31 -9
  175. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  176. package/dist/src/gateway/heartbeat/service.js +2 -2
  177. package/dist/src/gateway/hono/lib/config-payload.d.ts +4 -2
  178. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  179. package/dist/src/gateway/hono/routes/context-sources.js +0 -23
  180. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  181. package/dist/src/gateway/hono/routes/projects.js +8 -0
  182. package/dist/src/gateway/hono/routes/sessions.js +141 -13
  183. package/dist/src/gateway/hono/routes/user-model-refresh.d.ts +5 -0
  184. package/dist/src/gateway/hono/routes/user-model-refresh.js +128 -0
  185. package/dist/src/gateway/hono/routes/user-model.js +12 -5
  186. package/dist/src/gateway/hono/routes/work-discovery.js +0 -30
  187. package/dist/src/gateway/service.js +6 -6
  188. package/dist/src/heartbeat/index.js +1 -1
  189. package/dist/src/infra/update-restart.js +1 -1
  190. package/dist/src/knowledge/connected-knowledge-pipeline.js +1 -1
  191. package/dist/src/knowledge-memory/index.js +2 -2
  192. package/dist/src/knowledge-memory/repository.d.ts +7 -0
  193. package/dist/src/knowledge-memory/repository.js +58 -8
  194. package/dist/src/memory-maintenance/service.js +61 -31
  195. package/dist/src/migrations/memory-config.d.ts +2 -0
  196. package/dist/src/migrations/memory-config.js +77 -0
  197. package/dist/src/migrations/runner.js +2 -2
  198. package/dist/src/notifications/planner.js +5 -5
  199. package/dist/src/notifications/service.d.ts +2 -2
  200. package/dist/src/notifications/service.js +1 -1
  201. package/dist/src/storage/sqlite/index.d.ts +1 -0
  202. package/dist/src/storage/sqlite/index.js +2 -1
  203. package/dist/src/storage/sqlite/migrations/184_memory_suppressions.sql +12 -0
  204. package/dist/src/storage/sqlite/migrations/185_understanding_refresh_batches.sql +6 -0
  205. package/dist/src/storage/sqlite/migrations/186_sidebar_layout.sql +16 -0
  206. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  207. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  208. package/dist/src/storage/sqlite/schema.js +1 -1
  209. package/dist/src/storage/sqlite/sidebar-layout-repository.d.ts +12 -0
  210. package/dist/src/storage/sqlite/sidebar-layout-repository.js +53 -0
  211. package/dist/src/user-context/config.d.ts +4 -9
  212. package/dist/src/user-context/config.js +7 -27
  213. package/dist/src/user-context/memory-suppression.d.ts +7 -0
  214. package/dist/src/user-context/memory-suppression.js +23 -0
  215. package/dist/src/user-context/relationship-continuity.js +1 -1
  216. package/dist/src/user-context/sources/refresh-service.d.ts +48 -0
  217. package/dist/src/user-context/sources/refresh-service.js +221 -0
  218. package/dist/src/user-context/sources/repository.js +1 -1
  219. package/dist/src/user-model/bootstrap.js +27 -24
  220. package/dist/src/user-model/capture/executor.d.ts +1 -1
  221. package/dist/src/user-model/capture/executor.js +17 -11
  222. package/dist/src/user-model/capture/semantic.js +1 -1
  223. package/dist/src/user-model/domain.d.ts +6 -2
  224. package/dist/src/user-model/index.js +3 -3
  225. package/dist/src/user-model/profile.js +1 -1
  226. package/dist/src/user-model/repository.d.ts +4 -1
  227. package/dist/src/user-model/repository.js +96 -6
  228. package/dist/src/user-model/usage-policy.d.ts +2 -0
  229. package/dist/src/user-model/usage-policy.js +6 -2
  230. package/dist/src/work-discovery/project-understanding.js +2 -1
  231. package/dist/src/work-discovery/service.d.ts +8 -24
  232. package/dist/src/work-discovery/service.js +138 -180
  233. package/package.json +1 -1
  234. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BPsRb9Ck.js +0 -1
  235. package/dist/gateway/static/root/assets/api-DFOlahZv.js +0 -1
  236. package/dist/gateway/static/root/assets/automations-workspace-CUpiTTiY.js +0 -6
  237. package/dist/gateway/static/root/assets/browser-settings-page-CqTxLpil.js +0 -3
  238. package/dist/gateway/static/root/assets/capabilities-settings-panel-BZ_-pnS6.js +0 -8
  239. package/dist/gateway/static/root/assets/connector-service-page-CPqVmNvx.js +0 -1
  240. package/dist/gateway/static/root/assets/connectors-page-BUQyg3CW.js +0 -2
  241. package/dist/gateway/static/root/assets/gateway-realtime-store-BLDgrJ30.js +0 -1
  242. package/dist/gateway/static/root/assets/home-page-s9hDQ8Hc.js +0 -1
  243. package/dist/gateway/static/root/assets/index-RBCkv8a_.js +0 -79
  244. package/dist/gateway/static/root/assets/index-cFU4S35z.css +0 -1
  245. package/dist/gateway/static/root/assets/messages-F74LVAiU.js +0 -3
  246. package/dist/gateway/static/root/assets/note-detail-panel-D35sErp2.js +0 -5
  247. package/dist/gateway/static/root/assets/notes-page-8jCDklDn.js +0 -8
  248. package/dist/gateway/static/root/assets/project-detail-page-BUMQHy_N.js +0 -1
  249. package/dist/gateway/static/root/assets/projects-page-DT-Mt7XR.js +0 -1
  250. package/dist/gateway/static/root/assets/remote-access-hub-Clz3byir.js +0 -1
  251. package/dist/gateway/static/root/assets/sessions-page-tQRwktKm.js +0 -1
  252. package/dist/gateway/static/root/assets/settings-advanced-gate-DqWg9XS5.js +0 -1
  253. package/dist/gateway/static/root/assets/setup-status-panel-BB_sMB7P.js +0 -1
  254. package/dist/gateway/static/root/assets/shares-settings-oDALm4b6.js +0 -1
  255. package/dist/gateway/static/root/assets/skill-reload-api-DmwelnfK.js +0 -1
  256. package/dist/gateway/static/root/assets/skills-page-BE9JXz4U.js +0 -2
  257. package/dist/gateway/static/root/assets/task-detail-page-D1AWszc7.js +0 -1
  258. package/dist/gateway/static/root/assets/user-model-page-C00i4ea0.js +0 -2
  259. package/dist/gateway/static/root/assets/workflows-page-BUiBjz6m.js +0 -6
  260. package/dist/src/migrations/knowledge-memory-read-policy-config.d.ts +0 -2
  261. package/dist/src/migrations/knowledge-memory-read-policy-config.js +0 -48
@@ -216,36 +216,6 @@ function registerWorkDiscoveryRoutes(authenticated, deps) {
216
216
  }, 400);
217
217
  }
218
218
  });
219
- authenticated.post("/api/work-discovery/runs/:runId/profile", limited, async (c) => {
220
- const body = await c.req.json().catch(() => null);
221
- const decisions = (body && typeof body === "object" && Array.isArray(body.decisions) ? body.decisions : []).flatMap((value) => {
222
- if (!value || typeof value !== "object") return [];
223
- const item = value;
224
- const id = typeof item.id === "string" ? item.id.trim() : "";
225
- const status = item.status === "accepted" || item.status === "edited" || item.status === "rejected" ? item.status : void 0;
226
- if (!id || !status) return [];
227
- return [{
228
- id,
229
- status,
230
- ...typeof item.statement === "string" ? { statement: item.statement } : {}
231
- }];
232
- }).slice(0, 10);
233
- if (!decisions.length) return c.json({
234
- ok: false,
235
- error: "At least one valid decision is required"
236
- }, 400);
237
- const run = service.updateProfileCandidates({
238
- runId: c.req.param("runId"),
239
- decisions
240
- });
241
- return run ? c.json({
242
- ok: true,
243
- run
244
- }) : c.json({
245
- ok: false,
246
- error: "Profile candidates not found"
247
- }, 404);
248
- });
249
219
  authenticated.post("/api/work-discovery/runs/:runId/suggestions/:suggestionId/select", (c) => {
250
220
  return service.selectSuggestion(c.req.param("runId"), c.req.param("suggestionId")) ? c.json({ ok: true }) : c.json({
251
221
  ok: false,
@@ -59,12 +59,6 @@ import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
59
59
  import { ChannelManager } from "../channels/manager.js";
60
60
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
61
61
  import "../config/index.js";
62
- import { DiscussionService } from "../discussions/service.js";
63
- import { DiscussionOrganizer } from "../discussions/organizer.js";
64
- import { DiscussionLiveWorker } from "../discussions/live-worker.js";
65
- import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
66
- import { DiscussionSealer } from "../discussions/sealer.js";
67
- import "../discussions/index.js";
68
62
  import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
69
63
  import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
70
64
  import "../knowledge/index.js";
@@ -72,6 +66,12 @@ import { ConnectionRecoveryService } from "../connectors/connection-recovery-ser
72
66
  import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
73
67
  import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
74
68
  import { startConnectorSupervisor } from "../connectors/supervisor.js";
69
+ import { DiscussionService } from "../discussions/service.js";
70
+ import { DiscussionOrganizer } from "../discussions/organizer.js";
71
+ import { DiscussionLiveWorker } from "../discussions/live-worker.js";
72
+ import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
73
+ import { DiscussionSealer } from "../discussions/sealer.js";
74
+ import "../discussions/index.js";
75
75
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
76
76
  import "../endpoint-tools/index.js";
77
77
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
2
+ import { appendCronEventLines } from "./event-prompt.js";
2
3
  import { isWithinActiveHours } from "./active-hours.js";
3
4
  import { isHeartbeatContentEmpty } from "./content-check.js";
4
- import { appendCronEventLines } from "./event-prompt.js";
5
5
  import { createHeartbeatWake } from "./wake.js";
6
6
  export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
@@ -2,8 +2,8 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { init_paths, resolveConfigPath } from "../config/paths.js";
4
4
  import { init_loader, loadConfig } from "../config/loader.js";
5
- import { resolveGatewayService } from "../daemon/service.js";
6
5
  import { isRestartEnabled } from "../config/commands.flags.js";
6
+ import { resolveGatewayService } from "../daemon/service.js";
7
7
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "./restart.js";
8
8
  import { findVerifiedGatewayListenerPidsOnPortSync, signalVerifiedGatewayPidSync } from "./gateway-processes.js";
9
9
  import { refreshGatewayServiceAfterUpdate } from "./update-service-refresh.js";
@@ -106,7 +106,7 @@ var ConnectedKnowledgePipeline = class {
106
106
  status: "completed"
107
107
  });
108
108
  result.completed += 1;
109
- result.recordIds.push(written.item.id);
109
+ if (written.item) result.recordIds.push(written.item.id);
110
110
  } catch (error) {
111
111
  const message = error instanceof Error ? error.message : String(error);
112
112
  completeKnowledgeSourceItemSynthesis({
@@ -1,2 +1,2 @@
1
- import { KnowledgeReviewConflictError, classifyKnowledgeContentSource, getKnowledgeItem, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem } from "./repository.js";
2
- export { KnowledgeReviewConflictError, classifyKnowledgeContentSource, getKnowledgeItem, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem };
1
+ import { KnowledgeReviewConflictError, classifyKnowledgeContentSource, deleteKnowledgeItem, getKnowledgeItem, isKnowledgeCurrent, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem } from "./repository.js";
2
+ export { KnowledgeReviewConflictError, classifyKnowledgeContentSource, deleteKnowledgeItem, getKnowledgeItem, isKnowledgeCurrent, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem };
@@ -21,6 +21,7 @@ export interface WriteKnowledgeInput {
21
21
  derivedFromRecalledContext?: boolean;
22
22
  source?: Record<string, unknown>;
23
23
  replaceExisting?: boolean;
24
+ restoreDeleted?: boolean;
24
25
  now?: number;
25
26
  }
26
27
  export declare class KnowledgeReviewConflictError extends Error {
@@ -29,6 +30,10 @@ export declare class KnowledgeReviewConflictError extends Error {
29
30
  export declare function writeKnowledgeItem(input: WriteKnowledgeInput): {
30
31
  item: KnowledgeItem;
31
32
  created: boolean;
33
+ } | {
34
+ item?: undefined;
35
+ created: false;
36
+ suppressed: true;
32
37
  };
33
38
  export declare function getKnowledgeItem(id: string): KnowledgeItem | undefined;
34
39
  export declare function listKnowledgeItems(input?: {
@@ -70,3 +75,5 @@ export declare function searchKnowledgeItems(input: {
70
75
  }): KnowledgeItem[];
71
76
  export declare function classifyKnowledgeContentSource(item: KnowledgeItem): KnowledgeContentSource;
72
77
  export declare function knowledgeItemAllowed(item: KnowledgeItem, policy: KnowledgeReadPolicy): boolean;
78
+ export declare function deleteKnowledgeItem(id: string, now?: number): boolean;
79
+ export declare function isKnowledgeCurrent(item: KnowledgeItem, asOf?: number): boolean;
@@ -1,6 +1,7 @@
1
1
  import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
2
  import { validateScope } from "../user-model/domain.js";
3
3
  import { buildFts5SearchQuery, init_fts } from "../storage/sqlite/fts.js";
4
+ import { clearMemoryAudit, isMemorySuppressed, memoryFingerprint, restoreMemory, suppressMemory } from "../user-context/memory-suppression.js";
4
5
  import { randomUUID } from "node:crypto";
5
6
  //#region src/knowledge-memory/repository.ts
6
7
  init_fts();
@@ -60,7 +61,14 @@ function writeKnowledgeItem(input) {
60
61
  if (input.validFrom !== void 0 && input.validTo !== void 0 && input.validTo < input.validFrom) throw new Error("Knowledge validTo must be greater than or equal to validFrom.");
61
62
  const principalId = input.principalId ?? "local-owner";
62
63
  const now = input.now ?? Date.now();
64
+ const admittedStatus = input.status ?? (input.originClass === "owner" || input.originClass !== "untrusted" && input.confidence >= .7 && !input.derivedFromRecalledContext ? "active" : "candidate");
63
65
  return runSqliteWriteTransaction((db) => {
66
+ const keys = knowledgeFingerprints(input);
67
+ if (input.restoreDeleted && input.originClass === "owner") restoreMemory(db, keys);
68
+ if (isMemorySuppressed(db, keys)) return {
69
+ created: false,
70
+ suppressed: true
71
+ };
64
72
  const existingStatuses = input.replaceExisting ? [
65
73
  "candidate",
66
74
  "active",
@@ -76,12 +84,12 @@ function writeKnowledgeItem(input) {
76
84
  const existing = db.prepare(`SELECT * FROM knowledge_items WHERE principal_id = ?
77
85
  AND canonical_key = ? AND scope_type = ? AND COALESCE(scope_id, '') = COALESCE(?, '')
78
86
  AND status IN (${existingStatuses.map(() => "?").join(", ")})`).get(principalId, input.canonicalKey.trim(), input.scope.type, input.scope.id ?? null, ...existingStatuses);
79
- if (existing && !input.replaceExisting) return {
87
+ if (existing && (!input.replaceExisting || existing.origin_class === "owner" && input.originClass !== "owner")) return {
80
88
  item: fromRow(existing),
81
89
  created: false
82
90
  };
83
91
  if (existing) {
84
- const nextStatus = input.status ?? (input.originClass === "owner" ? "active" : "candidate");
92
+ const nextStatus = admittedStatus;
85
93
  db.prepare(`UPDATE knowledge_items SET kind = ?, content = ?, record_class = ?, status = ?, confidence = ?,
86
94
  importance = ?, valid_from = ?, valid_to = ?, expires_at = ?, review_at = ?,
87
95
  origin_class = ?, source_agent_id = ?, source_conversation_id = ?, source_turn_id = ?,
@@ -102,7 +110,7 @@ function writeKnowledgeItem(input) {
102
110
  };
103
111
  }
104
112
  const id = randomUUID();
105
- const status = input.status ?? (input.originClass === "owner" ? "active" : "candidate");
113
+ const status = admittedStatus;
106
114
  db.prepare(`INSERT INTO knowledge_items (
107
115
  knowledge_id, principal_id, kind, scope_type, scope_id, content, canonical_key, record_class,
108
116
  status, confidence, importance, valid_from, valid_to, expires_at, review_at,
@@ -154,12 +162,14 @@ function transitionKnowledgeStatus(input) {
154
162
  const current = db.prepare("SELECT * FROM knowledge_items WHERE knowledge_id = ?").get(input.id);
155
163
  if (!current) return void 0;
156
164
  if (input.expectedStatus && current.status !== input.expectedStatus) throw new KnowledgeReviewConflictError(`Knowledge status changed from ${input.expectedStatus} to ${current.status}.`);
157
- db.prepare(`UPDATE knowledge_items SET status = ?, content = COALESCE(?, content), updated_at = ?
158
- WHERE knowledge_id = ?`).run(input.status, content ?? null, now, input.id);
165
+ db.prepare(`UPDATE knowledge_items SET status = ?, content = COALESCE(?, content),
166
+ origin_class = CASE WHEN ? THEN 'owner' ELSE origin_class END, updated_at = ?
167
+ WHERE knowledge_id = ?`).run(input.status, content ?? null, input.actor === "user" && input.status === "active" ? 1 : 0, now, input.id);
159
168
  if (content !== void 0) {
160
169
  db.prepare("DELETE FROM knowledge_items_fts WHERE knowledge_id = ?").run(input.id);
161
170
  db.prepare("INSERT INTO knowledge_items_fts(content, knowledge_id) VALUES (?, ?)").run(content, input.id);
162
171
  }
172
+ if (input.actor === "user" && (input.status === "rejected" || input.status === "archived")) suppressMemory(db, knowledgeFingerprints(fromRow(current)), now);
163
173
  insertStatusEvent(db, {
164
174
  knowledgeId: input.id,
165
175
  fromStatus: current.status,
@@ -184,7 +194,8 @@ const REVIEW_TRANSITIONS = {
184
194
  from: [
185
195
  "candidate",
186
196
  "needs_review",
187
- "stale"
197
+ "stale",
198
+ "active"
188
199
  ],
189
200
  to: "active",
190
201
  requiresContent: true
@@ -292,11 +303,12 @@ function searchKnowledgeItems(input) {
292
303
  AND (k.valid_from IS NULL OR k.valid_from <= ?)
293
304
  AND (k.valid_to IS NULL OR k.valid_to >= ?)
294
305
  AND (k.expires_at IS NULL OR k.expires_at >= ?)
306
+ AND (k.review_at IS NULL OR k.review_at > ?)
295
307
  ${input.recordClass ? "AND k.record_class = ?" : ""}
296
308
  ${input.trustedOnly ? "AND k.origin_class != 'untrusted'" : ""}
297
309
  AND ${contentSource}
298
310
  AND ${visible.sql}
299
- ORDER BY rank ASC, k.importance DESC, k.updated_at DESC LIMIT ?`).all(fts, principalId, asOf, asOf, asOf, ...input.recordClass ? [input.recordClass] : [], ...visible.values, limit).map(fromRow);
311
+ ORDER BY rank ASC, k.importance DESC, k.updated_at DESC LIMIT ?`).all(fts, principalId, asOf, asOf, asOf, asOf, ...input.recordClass ? [input.recordClass] : [], ...visible.values, limit).map(fromRow);
300
312
  }
301
313
  function classifyKnowledgeContentSource(item) {
302
314
  if (item.recordClass === "memory") return "memory";
@@ -305,5 +317,43 @@ function classifyKnowledgeContentSource(item) {
305
317
  function knowledgeItemAllowed(item, policy) {
306
318
  return policy.scopes.includes(item.scope.type) && policy.contentSources.includes(classifyKnowledgeContentSource(item));
307
319
  }
320
+ function knowledgeFingerprints(input) {
321
+ const principal = input.principalId ?? "local-owner";
322
+ return [memoryFingerprint([
323
+ "knowledge-key",
324
+ principal,
325
+ input.scope.type,
326
+ input.scope.id ?? "",
327
+ input.canonicalKey
328
+ ]), memoryFingerprint([
329
+ "knowledge-content",
330
+ principal,
331
+ input.scope.type,
332
+ input.scope.id ?? "",
333
+ input.content
334
+ ])];
335
+ }
336
+ function deleteKnowledgeItem(id, now = Date.now()) {
337
+ return runSqliteWriteTransaction((db) => {
338
+ const rows = db.prepare(`WITH RECURSIVE deleted(id) AS (
339
+ SELECT knowledge_id FROM knowledge_items WHERE knowledge_id = ?
340
+ UNION SELECT k.knowledge_id FROM knowledge_items k JOIN deleted d
341
+ ON json_extract(k.source_json, '$.episodeKnowledgeId') = d.id
342
+ OR k.knowledge_id = (SELECT json_extract(source_json, '$.episodeKnowledgeId')
343
+ FROM knowledge_items WHERE knowledge_id = d.id)
344
+ ) SELECT * FROM knowledge_items WHERE knowledge_id IN (SELECT id FROM deleted)`).all(id);
345
+ for (const row of rows) {
346
+ const item = fromRow(row);
347
+ suppressMemory(db, knowledgeFingerprints(item), now);
348
+ clearMemoryAudit(db, "knowledge", item.id);
349
+ db.prepare("DELETE FROM knowledge_items_fts WHERE knowledge_id = ?").run(item.id);
350
+ db.prepare("DELETE FROM knowledge_items WHERE knowledge_id = ?").run(item.id);
351
+ }
352
+ return rows.length > 0;
353
+ });
354
+ }
355
+ function isKnowledgeCurrent(item, asOf = Date.now()) {
356
+ return item.status === "active" && (item.validFrom === void 0 || item.validFrom <= asOf) && (item.validTo === void 0 || item.validTo >= asOf) && (item.expiresAt === void 0 || item.expiresAt >= asOf) && (item.reviewAt === void 0 || item.reviewAt > asOf);
357
+ }
308
358
  //#endregion
309
- export { KnowledgeReviewConflictError, classifyKnowledgeContentSource, getKnowledgeItem, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem };
359
+ export { KnowledgeReviewConflictError, classifyKnowledgeContentSource, deleteKnowledgeItem, getKnowledgeItem, isKnowledgeCurrent, knowledgeItemAllowed, listKnowledgeItems, listKnowledgeStatusEvents, reviewKnowledgeItem, searchKnowledgeItems, transitionKnowledgeStatus, writeKnowledgeItem };
@@ -3,7 +3,7 @@ import "../user-model/domain.js";
3
3
  import { randomUUID } from "node:crypto";
4
4
  //#region src/memory-maintenance/service.ts
5
5
  init_transaction();
6
- const ALGORITHM_VERSION = "user-model-maintenance-v1";
6
+ const ALGORITHM_VERSION = "user-model-maintenance-v2";
7
7
  function emptyMetrics() {
8
8
  return {
9
9
  scanned: 0,
@@ -32,29 +32,22 @@ function addDecision(db, runId, objectType, objectId, action, reason, before, af
32
32
  decision_id, run_id, object_type, object_id, action, reason, before_json, after_json, created_at
33
33
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(randomUUID(), runId, objectType, objectId, action, reason, before === void 0 ? null : JSON.stringify(before), after === void 0 ? null : JSON.stringify(after), now);
34
34
  }
35
- function transitionAssertions(db, runId, now, limit, metrics) {
36
- const expired = db.prepare(`SELECT assertion_id, status, valid_to FROM user_assertions
37
- WHERE status = 'active' AND valid_to IS NOT NULL AND valid_to < ? LIMIT ?`).all(now, limit);
38
- metrics.scanned += expired.length;
39
- for (const row of expired) {
40
- db.prepare("UPDATE user_assertions SET status = 'stale' WHERE assertion_id = ? AND status = 'active'").run(row.assertion_id);
35
+ function transitionAssertions(db, runId, principalId, now, limit, metrics) {
36
+ const rows = db.prepare(`SELECT a.assertion_id, a.status FROM user_assertions a
37
+ JOIN user_assertion_slots s ON s.slot_id = a.slot_id
38
+ WHERE s.principal_id = ? AND a.status IN ('active', 'candidate', 'needs_review')
39
+ AND ((a.valid_to IS NOT NULL AND a.valid_to < ?)
40
+ OR (a.review_at IS NOT NULL AND a.review_at <= ?))
41
+ ORDER BY COALESCE(a.valid_to, a.review_at), a.assertion_id LIMIT ?`).all(principalId, now, now, limit);
42
+ metrics.scanned += rows.length;
43
+ for (const row of rows) {
44
+ db.prepare("UPDATE user_assertions SET status = 'stale' WHERE assertion_id = ?").run(row.assertion_id);
41
45
  db.prepare(`INSERT INTO user_assertion_status_events (
42
46
  event_id, assertion_id, from_status, to_status, actor_type, reason, source_run_id, created_at
43
- ) VALUES (?, ?, 'active', 'stale', 'maintenance', 'Validity interval ended.', ?, ?)`).run(randomUUID(), row.assertion_id, runId, now);
44
- addDecision(db, runId, "assertion", row.assertion_id, "stale", "validity_ended", row, { status: "stale" }, now);
47
+ ) VALUES (?, ?, ?, 'stale', 'maintenance', 'No current supporting evidence at review time.', ?, ?)`).run(randomUUID(), row.assertion_id, row.status, runId, now);
48
+ addDecision(db, runId, "assertion", row.assertion_id, "stale", "validity_or_review_ended", row, { status: "stale" }, now);
45
49
  metrics.stale += 1;
46
50
  }
47
- const reviewDue = db.prepare(`SELECT assertion_id, status, review_at FROM user_assertions
48
- WHERE status = 'active' AND review_at IS NOT NULL AND review_at <= ? LIMIT ?`).all(now, Math.max(0, limit - expired.length));
49
- metrics.scanned += reviewDue.length;
50
- for (const row of reviewDue) {
51
- db.prepare("UPDATE user_assertions SET status = 'needs_review' WHERE assertion_id = ? AND status = 'active'").run(row.assertion_id);
52
- db.prepare(`INSERT INTO user_assertion_status_events (
53
- event_id, assertion_id, from_status, to_status, actor_type, reason, source_run_id, created_at
54
- ) VALUES (?, ?, 'active', 'needs_review', 'maintenance', 'Scheduled review became due.', ?, ?)`).run(randomUUID(), row.assertion_id, runId, now);
55
- addDecision(db, runId, "assertion", row.assertion_id, "needs_review", "review_due", row, { status: "needs_review" }, now);
56
- metrics.needsReview += 1;
57
- }
58
51
  }
59
52
  function transitionPriorities(db, runId, principalId, now, limit, metrics) {
60
53
  const rows = db.prepare(`SELECT priority_id, status, valid_to FROM user_priority_windows
@@ -68,7 +61,7 @@ function transitionPriorities(db, runId, principalId, now, limit, metrics) {
68
61
  }
69
62
  function transitionKnowledge(db, runId, principalId, now, limit, metrics) {
70
63
  const expired = db.prepare(`SELECT knowledge_id, status, expires_at FROM knowledge_items
71
- WHERE principal_id = ? AND status = 'active' AND expires_at IS NOT NULL AND expires_at < ? LIMIT ?`).all(principalId, now, limit);
64
+ WHERE principal_id = ? AND status IN ('active', 'candidate') AND expires_at IS NOT NULL AND expires_at < ? LIMIT ?`).all(principalId, now, limit);
72
65
  metrics.scanned += expired.length;
73
66
  for (const row of expired) {
74
67
  db.prepare("UPDATE knowledge_items SET status = 'stale', updated_at = ? WHERE knowledge_id = ?").run(now, row.knowledge_id);
@@ -76,12 +69,12 @@ function transitionKnowledge(db, runId, principalId, now, limit, metrics) {
76
69
  metrics.stale += 1;
77
70
  }
78
71
  const reviewDue = db.prepare(`SELECT knowledge_id, status, review_at FROM knowledge_items
79
- WHERE principal_id = ? AND status = 'active' AND review_at IS NOT NULL AND review_at <= ? LIMIT ?`).all(principalId, now, Math.max(0, limit - expired.length));
72
+ WHERE principal_id = ? AND status IN ('active', 'candidate', 'needs_review') AND review_at IS NOT NULL AND review_at <= ? LIMIT ?`).all(principalId, now, Math.max(0, limit - expired.length));
80
73
  metrics.scanned += reviewDue.length;
81
74
  for (const row of reviewDue) {
82
- db.prepare("UPDATE knowledge_items SET status = 'needs_review', updated_at = ? WHERE knowledge_id = ?").run(now, row.knowledge_id);
83
- addDecision(db, runId, "knowledge", row.knowledge_id, "needs_review", "review_due", row, { status: "needs_review" }, now);
84
- metrics.needsReview += 1;
75
+ db.prepare("UPDATE knowledge_items SET status = 'stale', updated_at = ? WHERE knowledge_id = ?").run(now, row.knowledge_id);
76
+ addDecision(db, runId, "knowledge", row.knowledge_id, "stale", "review_due", row, { status: "stale" }, now);
77
+ metrics.stale += 1;
85
78
  }
86
79
  }
87
80
  function reconcileEvidence(db, runId, principalId, now, limit, evidenceThreshold, metrics) {
@@ -89,7 +82,10 @@ function reconcileEvidence(db, runId, principalId, now, limit, evidenceThreshold
89
82
  FROM user_assertions a
90
83
  JOIN user_assertion_slots s ON s.slot_id = a.slot_id
91
84
  JOIN user_assertion_evidence ae ON ae.assertion_id = a.assertion_id AND ae.relation = 'contradicts'
92
- WHERE s.principal_id = ? AND a.status = 'active' LIMIT ?`).all(principalId, limit);
85
+ JOIN context_evidence e ON e.evidence_id = ae.evidence_id
86
+ WHERE s.principal_id = ? AND a.status = 'active'
87
+ AND e.trust_level = 'owner' AND e.source_type IN ('conversation', 'user')
88
+ AND e.observed_at > a.observed_at AND ae.confidence >= 0.7 LIMIT ?`).all(principalId, limit);
93
89
  metrics.scanned += contradicted.length;
94
90
  for (const row of contradicted) {
95
91
  db.prepare("UPDATE user_assertions SET status = 'needs_review' WHERE assertion_id = ?").run(row.assertion_id);
@@ -99,16 +95,31 @@ function reconcileEvidence(db, runId, principalId, now, limit, evidenceThreshold
99
95
  addDecision(db, runId, "assertion", row.assertion_id, "needs_review", "contradictory_evidence", row, { status: "needs_review" }, now);
100
96
  metrics.needsReview += 1;
101
97
  }
102
- const candidates = db.prepare(`SELECT a.assertion_id, a.status, COUNT(DISTINCT
103
- e.source_type || ':' || COALESCE(e.source_instance_id, '') || ':' || e.source_ref
104
- ) AS evidence_count
98
+ const candidates = db.prepare(`SELECT a.assertion_id, a.status,
99
+ MIN(COUNT(DISTINCT COALESCE(e.content_hash, e.source_ref)),
100
+ COUNT(DISTINCT e.source_type || ':' || COALESCE(e.source_instance_id, '') || ':' ||
101
+ COALESCE(e.source_item_id, e.source_ref))) AS evidence_count
105
102
  FROM user_assertions a
106
103
  JOIN user_assertion_slots s ON s.slot_id = a.slot_id
107
104
  JOIN user_assertion_evidence ae ON ae.assertion_id = a.assertion_id AND ae.relation = 'supports'
108
105
  JOIN context_evidence e ON e.evidence_id = ae.evidence_id AND e.trust_level = 'owner'
109
106
  WHERE s.principal_id = ? AND a.status = 'candidate'
110
107
  AND a.authority IN ('user_observed', 'system_inferred')
111
- GROUP BY a.assertion_id HAVING evidence_count >= ? LIMIT ?`).all(principalId, evidenceThreshold, limit);
108
+ AND a.confidence >= 0.7 AND ae.confidence >= 0.7
109
+ AND a.sensitivity = 'normal' AND a.consequence IN ('low', 'medium')
110
+ AND a.disclosure_policy != 'ask_before_reference'
111
+ AND e.source_type IN ('conversation', 'user', 'connector')
112
+ AND (a.valid_from IS NULL OR a.valid_from <= ?)
113
+ AND (a.valid_to IS NULL OR a.valid_to >= ?)
114
+ AND (a.review_at IS NULL OR a.review_at > ?)
115
+ AND NOT EXISTS (SELECT 1 FROM user_assertion_evidence bad
116
+ WHERE bad.assertion_id = a.assertion_id AND bad.relation = 'contradicts')
117
+ AND (s.cardinality = 'multiple' OR NOT EXISTS (
118
+ SELECT 1 FROM user_assertions other WHERE other.slot_id = a.slot_id
119
+ AND other.assertion_id != a.assertion_id AND other.status IN ('active', 'conflicted')
120
+ AND other.normalized_value != a.normalized_value
121
+ AND (other.valid_to IS NULL OR other.valid_to >= ?)))
122
+ GROUP BY a.assertion_id HAVING evidence_count >= ? ORDER BY a.recorded_at LIMIT ?`).all(principalId, now, now, now, now, evidenceThreshold, limit);
112
123
  metrics.scanned += candidates.length;
113
124
  for (const row of candidates) {
114
125
  db.prepare("UPDATE user_assertions SET status = 'active' WHERE assertion_id = ? AND status = 'candidate'").run(row.assertion_id);
@@ -119,6 +130,24 @@ function reconcileEvidence(db, runId, principalId, now, limit, evidenceThreshold
119
130
  metrics.activated += 1;
120
131
  }
121
132
  }
133
+ function activateKnowledge(db, runId, principalId, now, limit, metrics) {
134
+ const rows = db.prepare(`SELECT knowledge_id FROM knowledge_items
135
+ WHERE principal_id = ? AND record_class = 'memory' AND status = 'candidate'
136
+ AND origin_class IN ('owner', 'agent', 'system') AND confidence >= 0.7
137
+ AND derived_from_recalled_context = 0
138
+ AND (valid_from IS NULL OR valid_from <= ?) AND (valid_to IS NULL OR valid_to >= ?)
139
+ AND (expires_at IS NULL OR expires_at >= ?) AND (review_at IS NULL OR review_at > ?)
140
+ ORDER BY created_at, knowledge_id LIMIT ?`).all(principalId, now, now, now, now, limit);
141
+ metrics.scanned += rows.length;
142
+ for (const row of rows) {
143
+ db.prepare("UPDATE knowledge_items SET status = 'active', updated_at = ? WHERE knowledge_id = ?").run(now, row.knowledge_id);
144
+ db.prepare(`INSERT INTO knowledge_item_status_events
145
+ (event_id, knowledge_id, from_status, to_status, actor_type, reason, created_at)
146
+ VALUES (?, ?, 'candidate', 'active', 'maintenance', 'Eligible scoped memory activated automatically.', ?)`).run(randomUUID(), row.knowledge_id, now);
147
+ addDecision(db, runId, "knowledge", row.knowledge_id, "activated", "eligible_scoped_memory", { status: "candidate" }, { status: "active" }, now);
148
+ metrics.activated += 1;
149
+ }
150
+ }
122
151
  function repairIndexes(db, runId, now, metrics) {
123
152
  const assertionMissing = db.prepare(`SELECT COUNT(*) AS count FROM user_assertions a
124
153
  LEFT JOIN user_assertions_fts f ON f.assertion_id = a.assertion_id
@@ -178,11 +207,12 @@ function runMemoryMaintenance(input) {
178
207
  });
179
208
  try {
180
209
  runSqliteWriteTransaction((db) => {
181
- transitionAssertions(db, runId, now, limit, metrics);
210
+ transitionAssertions(db, runId, principalId, now, limit, metrics);
182
211
  transitionPriorities(db, runId, principalId, now, limit, metrics);
183
212
  transitionKnowledge(db, runId, principalId, now, limit, metrics);
184
213
  if (input.jobType === "daily_reconciliation" || input.jobType === "manual_repair") {
185
214
  reconcileEvidence(db, runId, principalId, now, limit, evidenceThreshold, metrics);
215
+ activateKnowledge(db, runId, principalId, now, limit, metrics);
186
216
  repairIndexes(db, runId, now, metrics);
187
217
  }
188
218
  if (input.jobType === "weekly_knowledge" || input.jobType === "manual_repair") archiveOldKnowledge(db, runId, principalId, now - (input.staleRetentionDays ?? 30) * 24 * 60 * 60 * 1e3, now, limit, metrics);
@@ -0,0 +1,2 @@
1
+ import type { Migration } from './types.js';
2
+ export declare const memoryConfigMigration: Migration;
@@ -0,0 +1,77 @@
1
+ import { init_lock, isGatewayConfigLockedByAnotherProcessSync } from "../gateway/lock.js";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ //#region src/migrations/memory-config.ts
4
+ init_lock();
5
+ const id = "automatic-memory-config";
6
+ function normalizeKnowledgeMemoryConfigInput(input) {
7
+ if (!input || typeof input !== "object" || Array.isArray(input)) return input;
8
+ const memory = input;
9
+ if (!Array.isArray(memory.sources)) return input;
10
+ const oldSources = memory.sources.filter((source) => typeof source === "string");
11
+ const visibilityScopes = new Set([
12
+ "session",
13
+ "workspace",
14
+ "project"
15
+ ]);
16
+ const normalized = { ...memory };
17
+ if (!Array.isArray(normalized.readScopes)) normalized.readScopes = oldSources.filter((source) => visibilityScopes.has(source));
18
+ if (!Array.isArray(normalized.contentSources)) normalized.contentSources = [
19
+ ...oldSources.some((source) => visibilityScopes.has(source)) ? ["memory"] : [],
20
+ ...oldSources.includes("workspace") ? ["local_import"] : [],
21
+ ...oldSources.includes("connector") ? ["connector"] : []
22
+ ];
23
+ delete normalized.sources;
24
+ return normalized;
25
+ }
26
+ function convertedConfig(ctx) {
27
+ if (!existsSync(ctx.configPath)) return null;
28
+ const config = JSON.parse(readFileSync(ctx.configPath, "utf8"));
29
+ const userContext = config.userContext;
30
+ if (!userContext || typeof userContext !== "object" || Array.isArray(userContext)) return null;
31
+ const context = userContext;
32
+ let changed = false;
33
+ for (const key of ["userModel", "knowledgeMemory"]) {
34
+ const section = context[key];
35
+ if (!section || typeof section !== "object" || Array.isArray(section)) continue;
36
+ const memory = section;
37
+ if (memory.writePolicy === "confirm") {
38
+ memory.writePolicy = "allow";
39
+ changed = true;
40
+ }
41
+ if (key === "knowledgeMemory" && Array.isArray(memory.sources)) {
42
+ context[key] = normalizeKnowledgeMemoryConfigInput(memory);
43
+ changed = true;
44
+ }
45
+ }
46
+ if (!changed) return null;
47
+ return config;
48
+ }
49
+ function item(status) {
50
+ return {
51
+ id,
52
+ title: "Automatic memory configuration",
53
+ kind: "config",
54
+ safety: "auto",
55
+ status,
56
+ message: "Enable automatic ordinary memory and separate visibility scopes from content sources."
57
+ };
58
+ }
59
+ const memoryConfigMigration = {
60
+ id,
61
+ kind: "config",
62
+ safety: "auto",
63
+ detect: (ctx) => convertedConfig(ctx) ? item("planned") : null,
64
+ apply: (ctx) => {
65
+ if (isGatewayConfigLockedByAnotherProcessSync(ctx.configPath)) return {
66
+ ...item("skipped"),
67
+ message: "Deferred knowledge memory config migration until the running gateway restarts."
68
+ };
69
+ const config = convertedConfig(ctx);
70
+ return config ? {
71
+ ...item("applied"),
72
+ details: { config }
73
+ } : item("not_needed");
74
+ }
75
+ };
76
+ //#endregion
77
+ export { memoryConfigMigration };
@@ -3,7 +3,7 @@ import { init_logger } from "../utils/logger.js";
3
3
  import { ConfigSchema, init_schema } from "../config/schema.js";
4
4
  import { listRegisteredMigrations } from "./registry.js";
5
5
  import { conversationRoutingConfigMigration } from "./conversation-routing-config.js";
6
- import { knowledgeMemoryReadPolicyConfigMigration } from "./knowledge-memory-read-policy-config.js";
6
+ import { memoryConfigMigration } from "./memory-config.js";
7
7
  import { dirname, join } from "node:path";
8
8
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
9
9
  //#region src/migrations/runner.ts
@@ -12,7 +12,7 @@ init_logger();
12
12
  const log = createLogger("Migrations");
13
13
  const MIGRATION_LEDGER_FILENAME = "migrations.json";
14
14
  const CONFIG_BACKUP_COUNT = 10;
15
- const CORE_MIGRATIONS = [conversationRoutingConfigMigration, knowledgeMemoryReadPolicyConfigMigration];
15
+ const CORE_MIGRATIONS = [conversationRoutingConfigMigration, memoryConfigMigration];
16
16
  function listAllMigrations() {
17
17
  return [...CORE_MIGRATIONS, ...listRegisteredMigrations().map((entry) => entry.migration)];
18
18
  }
@@ -162,7 +162,7 @@ function workDiscoveryPlan(eventType, payload) {
162
162
  const event = payload;
163
163
  const completed = eventType === "work-discovery.completed";
164
164
  if (typeof event.runId !== "string" || !event.runId || typeof event.conversationId !== "string" || !event.conversationId || event.status !== (completed ? "completed" : "failed")) return null;
165
- const type = completed ? "work_discovery.review_ready" : "work_discovery.failed";
165
+ const type = completed ? "work_discovery.completed" : "work_discovery.failed";
166
166
  return {
167
167
  dedupeKey: `${type}:${event.runId}`,
168
168
  notification: {
@@ -174,15 +174,15 @@ function workDiscoveryPlan(eventType, payload) {
174
174
  },
175
175
  priority: completed ? "normal" : "high",
176
176
  title: completed ? {
177
- en: "Understanding ready for review",
178
- zh: "用户理解已可确认"
177
+ en: "Understanding updated",
178
+ zh: "用户理解已更新"
179
179
  } : {
180
180
  en: "Understanding needs attention",
181
181
  zh: "用户理解需要处理"
182
182
  },
183
183
  body: completed ? {
184
- en: "Review what xopc learned about your work.",
185
- zh: "查看并确认 xopc 对你工作的理解。"
184
+ en: "See what xopc learned. You can edit or delete it anytime.",
185
+ zh: "理解已自动整理,可随时查看、修改或删除。"
186
186
  } : {
187
187
  en: "Open user understanding to review or retry.",
188
188
  zh: "打开用户理解,查看详情或重试。"
@@ -19,7 +19,7 @@ export declare class NotificationService {
19
19
  persistGatewayEvent(type: string, payload: unknown): {
20
20
  schemaVersion: 1;
21
21
  id: string;
22
- type: "work_discovery.failed" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "proactive.insight" | "work_discovery.review_ready";
22
+ type: "work_discovery.completed" | "work_discovery.failed" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "proactive.insight";
23
23
  priority: "normal" | "high";
24
24
  title: {
25
25
  en: string;
@@ -56,7 +56,7 @@ export declare class NotificationService {
56
56
  persistPlan(plan: NotificationPlan): {
57
57
  schemaVersion: 1;
58
58
  id: string;
59
- type: "work_discovery.failed" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "proactive.insight" | "work_discovery.review_ready";
59
+ type: "work_discovery.completed" | "work_discovery.failed" | "chat.completed" | "chat.failed" | "task.needs_input" | "task.blocked" | "task.failed" | "task.completed" | "automation.completed" | "automation.failed" | "proactive.insight";
60
60
  priority: "normal" | "high";
61
61
  title: {
62
62
  en: string;
@@ -40,7 +40,7 @@ function preferenceAllows(type, preferences) {
40
40
  case "automation.completed": return preferences.automationCompleted;
41
41
  case "automation.failed": return preferences.automationFailed;
42
42
  case "proactive.insight": return preferences.proactiveInsight;
43
- case "work_discovery.review_ready":
43
+ case "work_discovery.completed":
44
44
  case "work_discovery.failed": return true;
45
45
  }
46
46
  }
@@ -29,6 +29,7 @@ export { buildRelationshipPrompt, getRelationshipSettings, isProactiveSupportAll
29
29
  export { buildDefaultSessionMetadata, type SessionMetadataSeed, } from './session-metadata.js';
30
30
  export { buildGlobalSessionStats, classifyStoredRow, estimateTokensFromMessages, extractFtsContent, metadataToSessionInsert, sessionConfigRowToConfig, sessionRowToMetadata, transcriptEntryRowToStoredRow, type SessionConfigRow, type SessionRow, type TranscriptEntryRow, } from './row-mappers.js';
31
31
  export { deleteSessionRecord, ensureSessionRecord, getCurrentTranscriptId, getGlobalSessionStats, findConversationIdByTranscriptId, getSessionPersistedLevels, getSessionMetadata, incrementSessionStatsOnAppend, listSessionMetadata, listSessionsByAgent, patchSessionMetadata, resetSessionRecord, resolveSessionAgentId, updateSessionStats, } from './session-repository.js';
32
+ export { getSidebarLayout, replaceSidebarLayout, sortBySidebarLayout, SidebarLayoutConflictError, type SidebarLayout, } from './sidebar-layout-repository.js';
32
33
  export { appendCompactionBoundaryIfUnchanged, appendMediaToAssistantTranscriptEntry, appendTranscriptEntry, findLatestAssistantTranscriptEntryId, listCompactionBoundaries, loadLlmMessagesForSession, loadTranscriptHistoryRowsForSession, loadTranscriptRows, loadTranscriptRowsForSession, loadCompactionSourceSnapshot, paginateTranscriptMessages, replaceTranscriptRows, restoreBeforeCompactionBoundary, searchSessionTranscript, type CompactionSourceSnapshot, type SessionTranscriptRecallMatch, type TranscriptSourceEntry, } from './transcript-repository.js';
33
34
  export { deleteNoteRecord, getNoteRecord, listNoteRecords, upsertNoteRecord, } from './notes-repository.js';
34
35
  export { deleteNoteAgentContextRecord, getNoteAgentContextRecord, upsertNoteAgentContextRecord, type NoteAgentContextRecord, } from './note-agent-context-repository.js';