@xopcai/xopc 0.0.136 → 0.0.138

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 (271) hide show
  1. package/README.md +4 -0
  2. package/README.zh-CN.md +4 -0
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/demo-memory/src/index.js +4 -0
  5. package/dist/extensions/demo-memory/src/index.js.map +1 -1
  6. package/dist/extensions/telegram/xopc.extension.json +1 -1
  7. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CER17NHM.js → agent-avatar-dicebear-CIsGDJzd.js} +1 -1
  8. package/dist/gateway/static/root/assets/agents-fX97A6iN.js +2 -0
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-B3Ap_wpX.js → app-management-settings-panel-ByM4Bzwm.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-3kBO22Xd.js → appearance-settings-BF_poRd3.js} +1 -1
  11. package/dist/gateway/static/root/assets/{apps-page-BHYbGQcZ.js → apps-page-BssdA5Qc.js} +1 -1
  12. package/dist/gateway/static/root/assets/{archive-plugin-D_vGeNB8.js → archive-plugin-DJaYoyGn.js} +1 -1
  13. package/dist/gateway/static/root/assets/{attachment-load-hWV_8pHL.js → attachment-load-xx6dBaZU.js} +1 -1
  14. package/dist/gateway/static/root/assets/{automation-suggestion-card-DVKmVTIo.js → automation-suggestion-card-BMvGqYob.js} +1 -1
  15. package/dist/gateway/static/root/assets/{automations-page-BCTXpOBp.js → automations-page-Dip8ZFmx.js} +1 -1
  16. package/dist/gateway/static/root/assets/{binary-plugins-BuXIeSPc.js → binary-plugins-CuPLWibr.js} +1 -1
  17. package/dist/gateway/static/root/assets/{block-editor-C1m0u-UU.js → block-editor-bzfvlJnh.js} +58 -54
  18. package/dist/gateway/static/root/assets/{browser-settings-page-ChUF08V5.js → browser-settings-page-lbx_8Dku.js} +4 -4
  19. package/dist/gateway/static/root/assets/{capability-presets-api-B7WWYaEh.js → capability-presets-api-X4Imbf8n.js} +1 -1
  20. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-D_Bh1PnA.js → capability-presets-settings-panel-v9JgKjJu.js} +1 -1
  21. package/dist/gateway/static/root/assets/{channel-recipient-api-sV06LCht.js → channel-recipient-api-DllrPmp-.js} +1 -1
  22. package/dist/gateway/static/root/assets/{channels-settings-BI2ChQc7.js → channels-settings-CED7Oy5Y.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-status-swr-EUwWYx8l.js +1 -0
  24. package/dist/gateway/static/root/assets/{connectors-page-qgvEp09M.js → connectors-page-BMfp0jWL.js} +1 -1
  25. package/dist/gateway/static/root/assets/{desktop-pet-BxMJlvb-.js → desktop-pet-oTig6qFO.js} +1 -1
  26. package/dist/gateway/static/root/assets/{desktop-pet-settings-DCvpDImn.js → desktop-pet-settings-DXJiPL_H.js} +1 -1
  27. package/dist/gateway/static/root/assets/{directory-picker-path-field-D1nxs9PA.js → directory-picker-path-field-CltkXSR2.js} +1 -1
  28. package/dist/gateway/static/root/assets/{dreaming-settings-EAWkpOgw.js → dreaming-settings-CYrZQxoL.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-debug-page-LUQ8dE8z.js → extension-debug-page-C-4BOy1R.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-page-B_mnhoRd.js → extension-page-C8nMpXqh.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-settings-page-BWQsGmvW.js → extension-settings-page-CXWYOwka.js} +1 -1
  32. package/dist/gateway/static/root/assets/{fetch-BWXmBizE.js → fetch-BID89uCH.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-config-api-M9bzPASf.js → gateway-config-api-B3TGdim5.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-settings-CbgtpprN.js → gateway-settings-D7tOnGAJ.js} +1 -1
  35. package/dist/gateway/static/root/assets/{gateway-startup-retry-BALL91S7.js → gateway-startup-retry-BkrLLlpE.js} +1 -1
  36. package/dist/gateway/static/root/assets/{goal-create-dialog-CbP4t9aM.js → goal-create-dialog-BL_cRshf.js} +1 -1
  37. package/dist/gateway/static/root/assets/{goal-detail-page-DlwI-MZZ.js → goal-detail-page-T1vg6Ng_.js} +1 -1
  38. package/dist/gateway/static/root/assets/{goals-config-api-BBhFVzBS.js → goals-config-api-D-WZWhP2.js} +1 -1
  39. package/dist/gateway/static/root/assets/{goals-page-D26r7knp.js → goals-page-1vzWXl5W.js} +1 -1
  40. package/dist/gateway/static/root/assets/{goals-settings-DdmVG_TR.js → goals-settings-DgGwvLVC.js} +1 -1
  41. package/dist/gateway/static/root/assets/{heartbeat-settings-DZW2Xq-U.js → heartbeat-settings-yh0bEIwQ.js} +1 -1
  42. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +1 -0
  43. package/dist/gateway/static/root/assets/index-NwiCnzI-.js +262 -0
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-1IWd88-T.js → keyboard-shortcuts-settings-CnxRFbgA.js} +1 -1
  45. package/dist/gateway/static/root/assets/{logs-page-DxoKJO7-.js → logs-page-DebnvTpD.js} +1 -1
  46. package/dist/gateway/static/root/assets/{markdown-split-BtdBj32h.js → markdown-split-BU69Nof8.js} +1 -1
  47. package/dist/gateway/static/root/assets/{media-plugins-CpoPj3s8.js → media-plugins-CDs7OvWt.js} +1 -1
  48. package/dist/gateway/static/root/assets/messages-DbNQuFdA.js +3 -0
  49. package/dist/gateway/static/root/assets/{models-hub-panel-D1Rp__dV.js → models-hub-panel-Ca_jy26S.js} +1 -1
  50. package/dist/gateway/static/root/assets/{notes-page-CgR1bO2W.js → notes-page-DTpeaI65.js} +1 -1
  51. package/dist/gateway/static/root/assets/{notes-workbench-ozsnmDTV.js → notes-workbench-uKMYsjUU.js} +2 -2
  52. package/dist/gateway/static/root/assets/{page-tabs-CVLqCfQB.js → page-tabs-CROo8Vgz.js} +1 -1
  53. package/dist/gateway/static/root/assets/{preview-open-alternatives-CKUXJk2t.js → preview-open-alternatives-BxsS9i1G.js} +1 -1
  54. package/dist/gateway/static/root/assets/{project-detail-page-B4dqFAQF.js → project-detail-page-BWKOhshy.js} +1 -1
  55. package/dist/gateway/static/root/assets/{projects-page-DlRGXv4a.js → projects-page-CoowiCLe.js} +1 -1
  56. package/dist/gateway/static/root/assets/{remote-access-hub-rZEYQMZV.js → remote-access-hub-CiOaX1wd.js} +1 -1
  57. package/dist/gateway/static/root/assets/{save-bar-controls-BtGni268.js → save-bar-controls-B4N17dMG.js} +1 -1
  58. package/dist/gateway/static/root/assets/{schedule-field-BDGzKVWn.js → schedule-field-ClJzQ2vz.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schema-form-DQJsKMCE.js → schema-form-oZvQUfDg.js} +1 -1
  60. package/dist/gateway/static/root/assets/{sessions-page-DxGoCGU8.js → sessions-page-Sx9Gc0cv.js} +1 -1
  61. package/dist/gateway/static/root/assets/settings-advanced-gate-CnbVdze4.js +1 -0
  62. package/dist/gateway/static/root/assets/{settings-collapsible-section-c8XGd4-8.js → settings-collapsible-section-B0kOLXUf.js} +1 -1
  63. package/dist/gateway/static/root/assets/{settings-form-section-By0YiDWo.js → settings-form-section-DoVPlVFd.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-loading-skeleton-SYCPY-WM.js → settings-loading-skeleton-C7J96bLc.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-page-D9NwvnBt.js → settings-page-CXiAByF0.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-page-layout-CrICyGob.js → settings-page-layout-R-6ArlMI.js} +1 -1
  67. package/dist/gateway/static/root/assets/{setup-status-panel-IjK-hDxf.js → setup-status-panel-Drz23n9l.js} +1 -1
  68. package/dist/gateway/static/root/assets/{share-preview-page-Dfnk9M_m.js → share-preview-page-Bn1umseg.js} +1 -1
  69. package/dist/gateway/static/root/assets/{shares-settings-vQiRBra7.js → shares-settings-Bb-pcMWg.js} +1 -1
  70. package/dist/gateway/static/root/assets/skill-reload-api-DE9HCHct.js +1 -0
  71. package/dist/gateway/static/root/assets/{skills-page-CruV215G.js → skills-page-B6cDPqkk.js} +1 -1
  72. package/dist/gateway/static/root/assets/{system-settings-panel-BBVbSDFD.js → system-settings-panel-CtEddAy-.js} +1 -1
  73. package/dist/gateway/static/root/assets/{typed-models-lib-CwFayhxu.js → typed-models-lib-BkhSnYq7.js} +1 -1
  74. package/dist/gateway/static/root/assets/{use-channel-catalog-BKtHOM50.js → use-channel-catalog-EA4hfbsP.js} +1 -1
  75. package/dist/gateway/static/root/assets/{user-profile-settings-panel-_KDWzagh.js → user-profile-settings-panel-BssTVOBS.js} +1 -1
  76. package/dist/gateway/static/root/assets/{utils-BiUjIHb4.js → utils-CI3ywKLT.js} +1 -1
  77. package/dist/gateway/static/root/assets/{voice-api-key-field-agJqlm4o.js → voice-api-key-field-DXMEGw9O.js} +1 -1
  78. package/dist/gateway/static/root/assets/{work-item-detail-page-Bdw4ATCb.js → work-item-detail-page-DsFqU0tK.js} +1 -1
  79. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-D-Dy6mTy.js → workflow-run-setup-panel-DImBi-m6.js} +1 -1
  80. package/dist/gateway/static/root/assets/{workflow-start-dialog-GammZ2GK.js → workflow-start-dialog-DuPpKAAc.js} +1 -1
  81. package/dist/gateway/static/root/assets/{workflows-page-Cw5zrqti.js → workflows-page-DfTVzTNY.js} +1 -1
  82. package/dist/gateway/static/root/index.html +5 -5
  83. package/dist/package.js +1 -1
  84. package/dist/src/agent/agent-instance-gateway.d.ts +3 -3
  85. package/dist/src/agent/agent-manager.d.ts +7 -8
  86. package/dist/src/agent/agent-manager.js +24 -25
  87. package/dist/src/agent/agent-manager.js.map +1 -1
  88. package/dist/src/agent/background-review/coordinator.d.ts +9 -23
  89. package/dist/src/agent/background-review/coordinator.js +45 -54
  90. package/dist/src/agent/background-review/coordinator.js.map +1 -1
  91. package/dist/src/agent/background-review/prompts.d.ts +2 -4
  92. package/dist/src/agent/background-review/prompts.js +7 -19
  93. package/dist/src/agent/background-review/prompts.js.map +1 -1
  94. package/dist/src/agent/background-review/run-background-review.d.ts +0 -8
  95. package/dist/src/agent/background-review/run-background-review.js +87 -72
  96. package/dist/src/agent/background-review/run-background-review.js.map +1 -1
  97. package/dist/src/agent/background-review/settings.d.ts +4 -4
  98. package/dist/src/agent/background-review/settings.js +25 -10
  99. package/dist/src/agent/background-review/settings.js.map +1 -1
  100. package/dist/src/agent/code-intelligence/binary.d.ts +1 -0
  101. package/dist/src/agent/code-intelligence/binary.js +42 -0
  102. package/dist/src/agent/code-intelligence/binary.js.map +1 -0
  103. package/dist/src/agent/code-intelligence/index.d.ts +4 -0
  104. package/dist/src/agent/code-intelligence/index.js +4 -0
  105. package/dist/src/agent/code-intelligence/runtime.d.ts +34 -0
  106. package/dist/src/agent/code-intelligence/runtime.js +282 -0
  107. package/dist/src/agent/code-intelligence/runtime.js.map +1 -0
  108. package/dist/src/agent/code-intelligence/tools.d.ts +6 -0
  109. package/dist/src/agent/code-intelligence/tools.js +268 -0
  110. package/dist/src/agent/code-intelligence/tools.js.map +1 -0
  111. package/dist/src/agent/code-intelligence/types.d.ts +22 -0
  112. package/dist/src/agent/code-intelligence/types.js +1 -0
  113. package/dist/src/agent/memory/builtin-provider.d.ts +1 -2
  114. package/dist/src/agent/memory/builtin-provider.js +31 -12
  115. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  116. package/dist/src/agent/memory/context/planner.d.ts +11 -0
  117. package/dist/src/agent/memory/context/planner.js +163 -0
  118. package/dist/src/agent/memory/context/planner.js.map +1 -0
  119. package/dist/src/agent/memory/context/types.d.ts +19 -0
  120. package/dist/src/agent/memory/context/types.js +1 -0
  121. package/dist/src/agent/memory/context-fence.d.ts +3 -3
  122. package/dist/src/agent/memory/context-fence.js +9 -9
  123. package/dist/src/agent/memory/context-fence.js.map +1 -1
  124. package/dist/src/agent/memory/index.d.ts +6 -4
  125. package/dist/src/agent/memory/index.js +5 -5
  126. package/dist/src/agent/memory/manager.d.ts +16 -4
  127. package/dist/src/agent/memory/manager.js +32 -34
  128. package/dist/src/agent/memory/manager.js.map +1 -1
  129. package/dist/src/agent/memory/memory-config.d.ts +1 -1
  130. package/dist/src/agent/memory/memory-config.js +2 -2
  131. package/dist/src/agent/memory/memory-config.js.map +1 -1
  132. package/dist/src/agent/memory/provider.d.ts +1 -3
  133. package/dist/src/agent/memory/stub-memory-provider.d.ts +0 -1
  134. package/dist/src/agent/memory/stub-memory-provider.js +0 -5
  135. package/dist/src/agent/memory/stub-memory-provider.js.map +1 -1
  136. package/dist/src/agent/memory/types.d.ts +31 -2
  137. package/dist/src/agent/memory/understanding/correction.d.ts +3 -0
  138. package/dist/src/agent/memory/understanding/correction.js +41 -0
  139. package/dist/src/agent/memory/understanding/correction.js.map +1 -0
  140. package/dist/src/agent/memory/understanding/quality.d.ts +8 -0
  141. package/dist/src/agent/memory/understanding/quality.js +20 -0
  142. package/dist/src/agent/memory/understanding/quality.js.map +1 -0
  143. package/dist/src/agent/memory/understanding/service.d.ts +26 -0
  144. package/dist/src/agent/memory/understanding/service.js +233 -0
  145. package/dist/src/agent/memory/understanding/service.js.map +1 -0
  146. package/dist/src/agent/memory/understanding/types.d.ts +22 -0
  147. package/dist/src/agent/memory/understanding/types.js +1 -0
  148. package/dist/src/agent/memory/user-context-coordinator.d.ts +21 -0
  149. package/dist/src/agent/memory/user-context-coordinator.js +90 -0
  150. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -0
  151. package/dist/src/agent/orchestration/agent-event-handler.d.ts +1 -0
  152. package/dist/src/agent/orchestration/agent-event-handler.js +1 -1
  153. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  154. package/dist/src/agent/orchestration/agent-orchestrator.js +2 -2
  155. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  156. package/dist/src/agent/orchestration/index.d.ts +1 -1
  157. package/dist/src/agent/orchestration/index.js +2 -2
  158. package/dist/src/agent/prompt/sections/tooling.js +10 -0
  159. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  160. package/dist/src/agent/prompt/system-prompt.js +2 -0
  161. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  162. package/dist/src/agent/service/direct-turn-helpers.js +2 -2
  163. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  164. package/dist/src/agent/service.js +7 -1
  165. package/dist/src/agent/service.js.map +1 -1
  166. package/dist/src/agent/session/session-inspector.d.ts +1 -0
  167. package/dist/src/agent/session/session-inspector.js +8 -2
  168. package/dist/src/agent/session/session-inspector.js.map +1 -1
  169. package/dist/src/agent/tools/factory.d.ts +3 -0
  170. package/dist/src/agent/tools/factory.js +17 -10
  171. package/dist/src/agent/tools/factory.js.map +1 -1
  172. package/dist/src/agent/tools/index.d.ts +1 -0
  173. package/dist/src/agent/tools/index.js +2 -1
  174. package/dist/src/agent/workspace-runtime/registry.d.ts +2 -0
  175. package/dist/src/agent/workspace-runtime/registry.js +11 -3
  176. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  177. package/dist/src/agent-manifest/index.js +2 -2
  178. package/dist/src/agent-manifest/schema.d.ts +91 -0
  179. package/dist/src/agent-manifest/schema.js +27 -5
  180. package/dist/src/agent-manifest/schema.js.map +1 -1
  181. package/dist/src/agent-runtime/memory-runtime.d.ts +1 -1
  182. package/dist/src/agent-runtime/memory-runtime.js.map +1 -1
  183. package/dist/src/automations/domain/validation.d.ts +22 -22
  184. package/dist/src/automations/draft/automation-draft-validator.d.ts +4 -4
  185. package/dist/src/cli/command-loaders.js +1 -0
  186. package/dist/src/cli/command-loaders.js.map +1 -1
  187. package/dist/src/cli/command-manifest.js +4 -0
  188. package/dist/src/cli/command-manifest.js.map +1 -1
  189. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  190. package/dist/src/cli/commands/resume.d.ts +1 -0
  191. package/dist/src/cli/commands/resume.js +31 -0
  192. package/dist/src/cli/commands/resume.js.map +1 -0
  193. package/dist/src/cli/commands/tui-runner.d.ts +9 -0
  194. package/dist/src/cli/commands/tui-runner.js +40 -0
  195. package/dist/src/cli/commands/tui-runner.js.map +1 -0
  196. package/dist/src/cli/commands/tui.js +4 -28
  197. package/dist/src/cli/commands/tui.js.map +1 -1
  198. package/dist/src/config/agent-profile.js +1 -1
  199. package/dist/src/config/index.js +2 -2
  200. package/dist/src/config/schema.d.ts +115 -0
  201. package/dist/src/config/schema.js +53 -4
  202. package/dist/src/config/schema.js.map +1 -1
  203. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  204. package/dist/src/gateway/agent-builtin-tools.js +5 -0
  205. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  206. package/dist/src/gateway/agents-admin.js +1 -1
  207. package/dist/src/gateway/hono/lib/config-payload.d.ts +18 -4
  208. package/dist/src/gateway/hono/routes/home.js +37 -2
  209. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  210. package/dist/src/gateway/hono/routes/memory.js +129 -4
  211. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  212. package/dist/src/gateway/hono/routes/projects.js +16 -0
  213. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  214. package/dist/src/knowledge/index.d.ts +2 -0
  215. package/dist/src/knowledge/index.js +2 -0
  216. package/dist/src/knowledge/ingestion-service.d.ts +20 -0
  217. package/dist/src/knowledge/ingestion-service.js +75 -0
  218. package/dist/src/knowledge/ingestion-service.js.map +1 -0
  219. package/dist/src/knowledge/types.d.ts +70 -0
  220. package/dist/src/knowledge/types.js +1 -0
  221. package/dist/src/projects/project-kind.js +0 -1
  222. package/dist/src/projects/project-kind.js.map +1 -1
  223. package/dist/src/providers/presentation.js +1 -1
  224. package/dist/src/providers/presentation.js.map +1 -1
  225. package/dist/src/storage/sqlite/index.d.ts +2 -1
  226. package/dist/src/storage/sqlite/index.js +3 -2
  227. package/dist/src/storage/sqlite/knowledge-repository.d.ts +50 -0
  228. package/dist/src/storage/sqlite/knowledge-repository.js +237 -0
  229. package/dist/src/storage/sqlite/knowledge-repository.js.map +1 -0
  230. package/dist/src/storage/sqlite/memory-records-repository.d.ts +80 -2
  231. package/dist/src/storage/sqlite/memory-records-repository.js +271 -9
  232. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  233. package/dist/src/storage/sqlite/migrations/029_user_understanding.sql +133 -0
  234. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  235. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  236. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  237. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  238. package/dist/src/storage/sqlite/schema.js +1 -1
  239. package/dist/src/tui/tui-picker-overlay.d.ts +6 -1
  240. package/dist/src/tui/tui-picker-overlay.js +4 -1
  241. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  242. package/dist/src/tui/tui-types.d.ts +2 -0
  243. package/dist/src/tui/tui-types.js.map +1 -1
  244. package/dist/src/tui/tui.js +17 -2
  245. package/dist/src/tui/tui.js.map +1 -1
  246. package/dist/src/work-items/work-item-service.d.ts +1 -0
  247. package/dist/src/work-items/work-item-service.js +3 -0
  248. package/dist/src/work-items/work-item-service.js.map +1 -1
  249. package/dist/src/work-items/work-item-store.d.ts +1 -0
  250. package/dist/src/work-items/work-item-store.js +13 -0
  251. package/dist/src/work-items/work-item-store.js.map +1 -1
  252. package/package.json +2 -1
  253. package/dist/gateway/static/root/assets/agents-Bv5R-N8Q.js +0 -2
  254. package/dist/gateway/static/root/assets/channels-status-swr-MY4Xh4fM.js +0 -1
  255. package/dist/gateway/static/root/assets/index-CPwVzi9x.css +0 -1
  256. package/dist/gateway/static/root/assets/index-DZOm5_ex.js +0 -262
  257. package/dist/gateway/static/root/assets/messages-CQ_k8RHj.js +0 -3
  258. package/dist/gateway/static/root/assets/settings-advanced-gate-4e8ZQwxr.js +0 -1
  259. package/dist/gateway/static/root/assets/skill-reload-api-BIWv778A.js +0 -1
  260. package/dist/src/agent/memory/candidate-extractor.d.ts +0 -6
  261. package/dist/src/agent/memory/candidate-extractor.js +0 -60
  262. package/dist/src/agent/memory/candidate-extractor.js.map +0 -1
  263. package/dist/src/agent/memory/context-assembler.d.ts +0 -10
  264. package/dist/src/agent/memory/context-assembler.js +0 -26
  265. package/dist/src/agent/memory/context-assembler.js.map +0 -1
  266. package/dist/src/agent/memory/inject-prefetch.d.ts +0 -6
  267. package/dist/src/agent/memory/inject-prefetch.js +0 -48
  268. package/dist/src/agent/memory/inject-prefetch.js.map +0 -1
  269. package/dist/src/agent/memory/prefetch-coordinator.d.ts +0 -37
  270. package/dist/src/agent/memory/prefetch-coordinator.js +0 -45
  271. package/dist/src/agent/memory/prefetch-coordinator.js.map +0 -1
@@ -1,5 +1,8 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { summarizeUserUnderstandingQuality } from "../../storage/sqlite/memory-records-repository.js";
4
+ import "../../storage/sqlite/index.js";
5
+ import { resolveAdaptiveUnderstandingCadence } from "../memory/understanding/quality.js";
3
6
  import { isAssistantTurnAborted, isAssistantTurnFailed } from "../orchestration/llm-turn-retry.js";
4
7
  import { resolveBackgroundReviewSettings } from "./settings.js";
5
8
  import { runBackgroundReviewTurn } from "./run-background-review.js";
@@ -14,41 +17,22 @@ var BackgroundReviewCoordinator = class {
14
17
  }
15
18
  /**
16
19
  * Called before the main `agent.prompt` for a user turn — bumps the memory
17
- * counter and arms `pendingMemoryReview` when the cadence interval is hit.
20
+ * counter and arms a review when the cadence interval is hit.
18
21
  */
19
- beginUserTurn(sessionKey, registeredToolNames) {
20
- const cfg = resolveBackgroundReviewSettings(this.opts.getConfig());
21
- if (!cfg.enabled || cfg.memoryNudgeInterval <= 0) return;
22
- if (!registeredToolNames.includes("curated_memory")) return;
22
+ beginUserTurn(sessionKey) {
23
+ const cfg = resolveBackgroundReviewSettings(this.opts.getConfig(), sessionKey);
24
+ if (!cfg.enabled) return;
23
25
  const state = this.ensureState(sessionKey);
24
- state.turnsSinceMemory += 1;
25
- if (state.turnsSinceMemory >= cfg.memoryNudgeInterval) {
26
- state.pendingMemoryReview = true;
27
- state.turnsSinceMemory = 0;
26
+ const intervalTurns = this.resolveReviewInterval(cfg, state);
27
+ state.turnsSinceReview += 1;
28
+ if (state.turnsSinceReview >= intervalTurns) {
29
+ state.pendingReview = true;
30
+ state.turnsSinceReview = 0;
28
31
  }
29
32
  }
30
33
  /**
31
- * Subscribe to the agent's events to update the skill counter as the
32
- * conversation progresses. Idempotent per session — the previous subscription
33
- * is torn down before installing the new one.
34
- */
35
- attachToAgent(sessionKey, agent, registeredToolNames) {
36
- const state = this.ensureState(sessionKey);
37
- state.unsubscribe?.();
38
- state.unsubscribe = agent.subscribe((ev) => {
39
- const cfg = resolveBackgroundReviewSettings(this.opts.getConfig());
40
- if (!cfg.enabled || cfg.skillNudgeInterval <= 0) return;
41
- if (!registeredToolNames.includes("skill_manage")) return;
42
- if (ev.type === "turn_start") state.itersSinceSkill += 1;
43
- if (ev.type === "tool_execution_end") {
44
- const te = ev;
45
- if (!te.isError && typeof te.toolName === "string" && te.toolName.trim() === "skill_manage") state.itersSinceSkill = 0;
46
- }
47
- });
48
- }
49
- /**
50
34
  * Fire-and-forget review after the main user turn. Decides whether to run a
51
- * memory and/or skills sweep based on the counter state + last assistant text,
35
+ * understanding sweep based on the counter state + last assistant text,
52
36
  * and delegates the actual review to {@link runBackgroundReviewTurn}.
53
37
  */
54
38
  scheduleAfterUserTurn(ctx) {
@@ -61,55 +45,62 @@ var BackgroundReviewCoordinator = class {
61
45
  }
62
46
  /** Tear down state for a session (called by `AgentManager.removeAgent`). */
63
47
  forgetSession(sessionKey) {
64
- const state = this.states.get(sessionKey);
65
- if (!state) return;
66
- state.unsubscribe?.();
67
48
  this.states.delete(sessionKey);
68
49
  }
69
- /** Tear down every subscription (`AgentManager.dispose` / hot reload). */
50
+ /** Clear every counter (`AgentManager.dispose` / hot reload). */
70
51
  clear() {
71
- for (const state of this.states.values()) state.unsubscribe?.();
72
52
  this.states.clear();
73
53
  }
74
54
  ensureState(sessionKey) {
75
55
  const existing = this.states.get(sessionKey);
76
56
  if (existing) return existing;
77
57
  const state = {
78
- turnsSinceMemory: 0,
79
- itersSinceSkill: 0,
80
- pendingMemoryReview: false
58
+ turnsSinceReview: 0,
59
+ pendingReview: false
81
60
  };
82
61
  this.states.set(sessionKey, state);
83
62
  return state;
84
63
  }
64
+ resolveReviewInterval(settings, state) {
65
+ if (!settings.adaptiveCadence || !settings.agentId) return settings.reviewIntervalTurns;
66
+ const now = Date.now();
67
+ if (state.adaptiveIntervalTurns != null && (state.adaptiveIntervalExpiresAt ?? 0) > now) return state.adaptiveIntervalTurns;
68
+ try {
69
+ const metrics = summarizeUserUnderstandingQuality({
70
+ agentId: settings.agentId,
71
+ windowDays: 30,
72
+ nowMs: now
73
+ });
74
+ const decision = resolveAdaptiveUnderstandingCadence(settings.reviewIntervalTurns, metrics);
75
+ state.adaptiveIntervalTurns = decision.effectiveIntervalTurns;
76
+ state.adaptiveIntervalExpiresAt = now + 5 * 6e4;
77
+ if (decision.slowed) log.debug({
78
+ agentId: settings.agentId,
79
+ baseIntervalTurns: decision.baseIntervalTurns,
80
+ effectiveIntervalTurns: decision.effectiveIntervalTurns,
81
+ reasons: decision.reasons
82
+ }, "User-understanding review cadence slowed by quality signals");
83
+ return decision.effectiveIntervalTurns;
84
+ } catch {
85
+ return settings.reviewIntervalTurns;
86
+ }
87
+ }
85
88
  async runReviewIfNeeded(ctx) {
86
89
  const state = this.states.get(ctx.sessionKey);
87
90
  if (!state) return;
88
- const settings = resolveBackgroundReviewSettings(this.opts.getConfig());
91
+ const settings = resolveBackgroundReviewSettings(this.opts.getConfig(), ctx.sessionKey);
89
92
  if (!settings.enabled) return;
90
93
  if (isAssistantTurnAborted(ctx.agent) || isAssistantTurnFailed(ctx.agent)) return;
91
94
  if (!ctx.lastAssistantText?.trim()) return;
92
- const reviewMemory = state.pendingMemoryReview;
93
- state.pendingMemoryReview = false;
94
- let reviewSkills = false;
95
- if (settings.skillNudgeInterval > 0 && ctx.registeredToolNames.includes("skill_manage") && state.itersSinceSkill >= settings.skillNudgeInterval) {
96
- reviewSkills = true;
97
- state.itersSinceSkill = 0;
98
- }
99
- if (!reviewMemory && !reviewSkills) return;
95
+ const shouldReview = state.pendingReview;
96
+ state.pendingReview = false;
97
+ if (!shouldReview) return;
100
98
  await runBackgroundReviewTurn({
101
99
  sessionKey: ctx.sessionKey,
102
100
  mainAgent: ctx.agent,
103
101
  settings,
104
- reviewMemory,
105
- reviewSkills,
106
- registeredToolNames: [...ctx.registeredToolNames],
107
- skillAllowlist: ctx.skillAllowlist ? [...ctx.skillAllowlist] : void 0,
108
- workspacePath: ctx.workspacePath,
109
- skillManager: ctx.workspaceRuntime.skillManager,
110
102
  memoryManager: ctx.workspaceRuntime.memoryManager,
111
- getConfig: () => this.opts.getConfig(),
112
- onSkillsFilesystemMutate: this.opts.onSkillsFilesystemMutate
103
+ getConfig: () => this.opts.getConfig()
113
104
  });
114
105
  }
115
106
  };
@@ -1 +1 @@
1
- {"version":3,"file":"coordinator.js","names":[],"sources":["../../../../src/agent/background-review/coordinator.ts"],"sourcesContent":["/**\n * BackgroundReviewCoordinator — owns the per-session counters that decide when\n * to nudge the model into running a quiet \"review memory / review skills\" follow-up\n * after a normal user turn finishes.\n *\n * Previously the nudge state, the `agent.subscribe` plumbing for the skill counter,\n * and the call to `runBackgroundReviewTurn` lived as private methods + a per-instance\n * field on `AgentManager`. Extracted so:\n * - `AgentInstance` no longer carries an inline counter object.\n * - The agent-event subscription used to count `tool_execution_end` events is\n * owned by the coordinator; teardown is automatic on `forgetSession`.\n * - Future changes to the nudge cadence (per-agent intervals, per-tool counters,\n * etc.) only touch this file.\n */\n\nimport type { Agent, AgentEvent } from '@earendil-works/pi-agent-core';\n\nimport type { Config } from '../../config/schema.js';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n} from '../orchestration/llm-turn-retry.js';\nimport type { WorkspaceRuntime } from '../workspace-runtime/registry.js';\nimport { resolveBackgroundReviewSettings } from './settings.js';\nimport { runBackgroundReviewTurn } from './run-background-review.js';\n\nconst log = createLogger('BackgroundReviewCoordinator');\n\ninterface NudgeState {\n turnsSinceMemory: number;\n itersSinceSkill: number;\n pendingMemoryReview: boolean;\n unsubscribe?: () => void;\n}\n\nexport interface BackgroundReviewCoordinatorOptions {\n /** Effective config snapshot used to look up review-cadence settings. */\n getConfig: () => Config | undefined;\n /** Trigger after the review turn writes skill files (lets agents reload prompts). */\n onSkillsFilesystemMutate: () => void;\n}\n\nexport interface ScheduleReviewContext {\n sessionKey: string;\n agent: Agent;\n registeredToolNames: readonly string[];\n skillAllowlist?: readonly string[];\n workspacePath: string;\n /** Last assistant text — review is skipped when empty. */\n lastAssistantText: string | null;\n workspaceRuntime: WorkspaceRuntime;\n}\n\nexport class BackgroundReviewCoordinator {\n private readonly opts: BackgroundReviewCoordinatorOptions;\n private readonly states = new Map<string, NudgeState>();\n\n constructor(opts: BackgroundReviewCoordinatorOptions) {\n this.opts = opts;\n }\n\n /**\n * Called before the main `agent.prompt` for a user turn — bumps the memory\n * counter and arms `pendingMemoryReview` when the cadence interval is hit.\n */\n beginUserTurn(sessionKey: string, registeredToolNames: readonly string[]): void {\n const cfg = resolveBackgroundReviewSettings(this.opts.getConfig());\n if (!cfg.enabled || cfg.memoryNudgeInterval <= 0) return;\n if (!registeredToolNames.includes('curated_memory')) return;\n\n const state = this.ensureState(sessionKey);\n state.turnsSinceMemory += 1;\n if (state.turnsSinceMemory >= cfg.memoryNudgeInterval) {\n state.pendingMemoryReview = true;\n state.turnsSinceMemory = 0;\n }\n }\n\n /**\n * Subscribe to the agent's events to update the skill counter as the\n * conversation progresses. Idempotent per session — the previous subscription\n * is torn down before installing the new one.\n */\n attachToAgent(\n sessionKey: string,\n agent: Agent,\n registeredToolNames: readonly string[],\n ): void {\n const state = this.ensureState(sessionKey);\n state.unsubscribe?.();\n const unsub = agent.subscribe((ev: AgentEvent) => {\n const cfg = resolveBackgroundReviewSettings(this.opts.getConfig());\n if (!cfg.enabled || cfg.skillNudgeInterval <= 0) return;\n if (!registeredToolNames.includes('skill_manage')) return;\n if (ev.type === 'turn_start') {\n state.itersSinceSkill += 1;\n }\n if (ev.type === 'tool_execution_end') {\n const te = ev as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n if (!te.isError && typeof te.toolName === 'string' && te.toolName.trim() === 'skill_manage') {\n state.itersSinceSkill = 0;\n }\n }\n });\n state.unsubscribe = unsub;\n }\n\n /**\n * Fire-and-forget review after the main user turn. Decides whether to run a\n * memory and/or skills sweep based on the counter state + last assistant text,\n * and delegates the actual review to {@link runBackgroundReviewTurn}.\n */\n scheduleAfterUserTurn(ctx: ScheduleReviewContext): void {\n void this.runReviewIfNeeded(ctx).catch((err) => {\n log.warn({ err, sessionKey: ctx.sessionKey }, 'Background review failed');\n });\n }\n\n /** Tear down state for a session (called by `AgentManager.removeAgent`). */\n forgetSession(sessionKey: string): void {\n const state = this.states.get(sessionKey);\n if (!state) return;\n state.unsubscribe?.();\n this.states.delete(sessionKey);\n }\n\n /** Tear down every subscription (`AgentManager.dispose` / hot reload). */\n clear(): void {\n for (const state of this.states.values()) {\n state.unsubscribe?.();\n }\n this.states.clear();\n }\n\n private ensureState(sessionKey: string): NudgeState {\n const existing = this.states.get(sessionKey);\n if (existing) return existing;\n const state: NudgeState = {\n turnsSinceMemory: 0,\n itersSinceSkill: 0,\n pendingMemoryReview: false,\n };\n this.states.set(sessionKey, state);\n return state;\n }\n\n private async runReviewIfNeeded(ctx: ScheduleReviewContext): Promise<void> {\n const state = this.states.get(ctx.sessionKey);\n if (!state) return;\n const settings = resolveBackgroundReviewSettings(this.opts.getConfig());\n if (!settings.enabled) return;\n if (isAssistantTurnAborted(ctx.agent) || isAssistantTurnFailed(ctx.agent)) return;\n if (!ctx.lastAssistantText?.trim()) return;\n\n const reviewMemory = state.pendingMemoryReview;\n state.pendingMemoryReview = false;\n\n let reviewSkills = false;\n if (\n settings.skillNudgeInterval > 0 &&\n ctx.registeredToolNames.includes('skill_manage') &&\n state.itersSinceSkill >= settings.skillNudgeInterval\n ) {\n reviewSkills = true;\n state.itersSinceSkill = 0;\n }\n\n if (!reviewMemory && !reviewSkills) return;\n\n await runBackgroundReviewTurn({\n sessionKey: ctx.sessionKey,\n mainAgent: ctx.agent,\n settings,\n reviewMemory,\n reviewSkills,\n registeredToolNames: [...ctx.registeredToolNames],\n skillAllowlist: ctx.skillAllowlist ? [...ctx.skillAllowlist] : undefined,\n workspacePath: ctx.workspacePath,\n skillManager: ctx.workspaceRuntime.skillManager,\n memoryManager: ctx.workspaceRuntime.memoryManager,\n getConfig: () => this.opts.getConfig(),\n onSkillsFilesystemMutate: this.opts.onSkillsFilesystemMutate,\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"coordinator.js","names":[],"sources":["../../../../src/agent/background-review/coordinator.ts"],"sourcesContent":["/**\n * BackgroundReviewCoordinator — owns the per-session counters that decide when\n * to nudge the model into running a quiet user-understanding review\n * after a normal user turn finishes.\n *\n * The nudge state and review scheduling are kept out of the per-session agent\n * instance so:\n * - `AgentInstance` no longer carries an inline counter object.\n * - Future changes to the review cadence only touch this file.\n */\n\nimport type { Agent } from '@earendil-works/pi-agent-core';\n\nimport type { Config } from '../../config/schema.js';\nimport { summarizeUserUnderstandingQuality } from '../../storage/sqlite/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveAdaptiveUnderstandingCadence } from '../memory/understanding/quality.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n} from '../orchestration/llm-turn-retry.js';\nimport type { WorkspaceRuntime } from '../workspace-runtime/registry.js';\nimport {\n resolveBackgroundReviewSettings,\n type BackgroundReviewSettings,\n} from './settings.js';\nimport { runBackgroundReviewTurn } from './run-background-review.js';\n\nconst log = createLogger('BackgroundReviewCoordinator');\n\ninterface NudgeState {\n turnsSinceReview: number;\n pendingReview: boolean;\n adaptiveIntervalTurns?: number;\n adaptiveIntervalExpiresAt?: number;\n}\n\nexport interface BackgroundReviewCoordinatorOptions {\n /** Effective config snapshot used to look up review-cadence settings. */\n getConfig: () => Config | undefined;\n}\n\nexport interface ScheduleReviewContext {\n sessionKey: string;\n agent: Agent;\n /** Last assistant text — review is skipped when empty. */\n lastAssistantText: string | null;\n workspaceRuntime: WorkspaceRuntime;\n}\n\nexport class BackgroundReviewCoordinator {\n private readonly opts: BackgroundReviewCoordinatorOptions;\n private readonly states = new Map<string, NudgeState>();\n\n constructor(opts: BackgroundReviewCoordinatorOptions) {\n this.opts = opts;\n }\n\n /**\n * Called before the main `agent.prompt` for a user turn — bumps the memory\n * counter and arms a review when the cadence interval is hit.\n */\n beginUserTurn(sessionKey: string): void {\n const cfg = resolveBackgroundReviewSettings(this.opts.getConfig(), sessionKey);\n if (!cfg.enabled) return;\n\n const state = this.ensureState(sessionKey);\n const intervalTurns = this.resolveReviewInterval(cfg, state);\n state.turnsSinceReview += 1;\n if (state.turnsSinceReview >= intervalTurns) {\n state.pendingReview = true;\n state.turnsSinceReview = 0;\n }\n }\n\n /**\n * Fire-and-forget review after the main user turn. Decides whether to run a\n * understanding sweep based on the counter state + last assistant text,\n * and delegates the actual review to {@link runBackgroundReviewTurn}.\n */\n scheduleAfterUserTurn(ctx: ScheduleReviewContext): void {\n void this.runReviewIfNeeded(ctx).catch((err) => {\n log.warn({ err, sessionKey: ctx.sessionKey }, 'Background review failed');\n });\n }\n\n /** Tear down state for a session (called by `AgentManager.removeAgent`). */\n forgetSession(sessionKey: string): void {\n this.states.delete(sessionKey);\n }\n\n /** Clear every counter (`AgentManager.dispose` / hot reload). */\n clear(): void {\n this.states.clear();\n }\n\n private ensureState(sessionKey: string): NudgeState {\n const existing = this.states.get(sessionKey);\n if (existing) return existing;\n const state: NudgeState = {\n turnsSinceReview: 0,\n pendingReview: false,\n };\n this.states.set(sessionKey, state);\n return state;\n }\n\n private resolveReviewInterval(settings: BackgroundReviewSettings, state: NudgeState): number {\n if (!settings.adaptiveCadence || !settings.agentId) return settings.reviewIntervalTurns;\n const now = Date.now();\n if (\n state.adaptiveIntervalTurns != null\n && (state.adaptiveIntervalExpiresAt ?? 0) > now\n ) {\n return state.adaptiveIntervalTurns;\n }\n try {\n const metrics = summarizeUserUnderstandingQuality({ agentId: settings.agentId, windowDays: 30, nowMs: now });\n const decision = resolveAdaptiveUnderstandingCadence(settings.reviewIntervalTurns, metrics);\n state.adaptiveIntervalTurns = decision.effectiveIntervalTurns;\n state.adaptiveIntervalExpiresAt = now + 5 * 60_000;\n if (decision.slowed) {\n log.debug({\n agentId: settings.agentId,\n baseIntervalTurns: decision.baseIntervalTurns,\n effectiveIntervalTurns: decision.effectiveIntervalTurns,\n reasons: decision.reasons,\n }, 'User-understanding review cadence slowed by quality signals');\n }\n return decision.effectiveIntervalTurns;\n } catch {\n return settings.reviewIntervalTurns;\n }\n }\n\n private async runReviewIfNeeded(ctx: ScheduleReviewContext): Promise<void> {\n const state = this.states.get(ctx.sessionKey);\n if (!state) return;\n const settings = resolveBackgroundReviewSettings(this.opts.getConfig(), ctx.sessionKey);\n if (!settings.enabled) return;\n if (isAssistantTurnAborted(ctx.agent) || isAssistantTurnFailed(ctx.agent)) return;\n if (!ctx.lastAssistantText?.trim()) return;\n\n const shouldReview = state.pendingReview;\n state.pendingReview = false;\n if (!shouldReview) return;\n\n await runBackgroundReviewTurn({\n sessionKey: ctx.sessionKey,\n mainAgent: ctx.agent,\n settings,\n memoryManager: ctx.workspaceRuntime.memoryManager,\n getConfig: () => this.opts.getConfig(),\n });\n }\n}\n"],"mappings":";;;;;;;;;aAeqD;AAarD,MAAM,MAAM,aAAa,8BAA8B;AAsBvD,IAAa,8BAAb,MAAyC;CACvC;CACA,yBAA0B,IAAI,KAAyB;CAEvD,YAAY,MAA0C;AACpD,OAAK,OAAO;;;;;;CAOd,cAAc,YAA0B;EACtC,MAAM,MAAM,gCAAgC,KAAK,KAAK,WAAW,EAAE,WAAW;AAC9E,MAAI,CAAC,IAAI,QAAS;EAElB,MAAM,QAAQ,KAAK,YAAY,WAAW;EAC1C,MAAM,gBAAgB,KAAK,sBAAsB,KAAK,MAAM;AAC5D,QAAM,oBAAoB;AAC1B,MAAI,MAAM,oBAAoB,eAAe;AAC3C,SAAM,gBAAgB;AACtB,SAAM,mBAAmB;;;;;;;;CAS7B,sBAAsB,KAAkC;AACjD,OAAK,kBAAkB,IAAI,CAAC,OAAO,QAAQ;AAC9C,OAAI,KAAK;IAAE;IAAK,YAAY,IAAI;IAAY,EAAE,2BAA2B;IACzE;;;CAIJ,cAAc,YAA0B;AACtC,OAAK,OAAO,OAAO,WAAW;;;CAIhC,QAAc;AACZ,OAAK,OAAO,OAAO;;CAGrB,YAAoB,YAAgC;EAClD,MAAM,WAAW,KAAK,OAAO,IAAI,WAAW;AAC5C,MAAI,SAAU,QAAO;EACrB,MAAM,QAAoB;GACxB,kBAAkB;GAClB,eAAe;GAChB;AACD,OAAK,OAAO,IAAI,YAAY,MAAM;AAClC,SAAO;;CAGT,sBAA8B,UAAoC,OAA2B;AAC3F,MAAI,CAAC,SAAS,mBAAmB,CAAC,SAAS,QAAS,QAAO,SAAS;EACpE,MAAM,MAAM,KAAK,KAAK;AACtB,MACE,MAAM,yBAAyB,SAC3B,MAAM,6BAA6B,KAAK,IAE5C,QAAO,MAAM;AAEf,MAAI;GACF,MAAM,UAAU,kCAAkC;IAAE,SAAS,SAAS;IAAS,YAAY;IAAI,OAAO;IAAK,CAAC;GAC5G,MAAM,WAAW,oCAAoC,SAAS,qBAAqB,QAAQ;AAC3F,SAAM,wBAAwB,SAAS;AACvC,SAAM,4BAA4B,MAAM,IAAI;AAC5C,OAAI,SAAS,OACX,KAAI,MAAM;IACR,SAAS,SAAS;IAClB,mBAAmB,SAAS;IAC5B,wBAAwB,SAAS;IACjC,SAAS,SAAS;IACnB,EAAE,8DAA8D;AAEnE,UAAO,SAAS;UACV;AACN,UAAO,SAAS;;;CAIpB,MAAc,kBAAkB,KAA2C;EACzE,MAAM,QAAQ,KAAK,OAAO,IAAI,IAAI,WAAW;AAC7C,MAAI,CAAC,MAAO;EACZ,MAAM,WAAW,gCAAgC,KAAK,KAAK,WAAW,EAAE,IAAI,WAAW;AACvF,MAAI,CAAC,SAAS,QAAS;AACvB,MAAI,uBAAuB,IAAI,MAAM,IAAI,sBAAsB,IAAI,MAAM,CAAE;AAC3E,MAAI,CAAC,IAAI,mBAAmB,MAAM,CAAE;EAEpC,MAAM,eAAe,MAAM;AAC3B,QAAM,gBAAgB;AACtB,MAAI,CAAC,aAAc;AAEnB,QAAM,wBAAwB;GAC5B,YAAY,IAAI;GAChB,WAAW,IAAI;GACf;GACA,eAAe,IAAI,iBAAiB;GACpC,iBAAiB,KAAK,KAAK,WAAW;GACvC,CAAC"}
@@ -1,4 +1,2 @@
1
- export declare const MEMORY_REVIEW_USER_PROMPT = "Review the conversation above and consider saving to curated memory if appropriate.\n\nFocus on:\n1. Has the user revealed things about themselves \u2014 persona, desires, preferences, or personal details worth remembering?\n2. Has the user expressed expectations about how you should behave, their work style, or how they want you to operate?\n\nUse curated_memory (MEMORY.md for agent-facing notes, user/MEMORY.md for global user memory) only for durable facts that will still matter in future sessions.\nIf nothing is worth saving, reply with exactly: Nothing to save.";
2
- export declare const SKILL_REVIEW_USER_PROMPT = "Review the conversation above and consider saving or updating a skill if appropriate.\n\nFocus on: was a non-trivial approach used to complete a task that required trial and error, or changing course from experience, or did the user expect a different reusable method?\n\nUse skills_list / skill_view to inspect existing skills. If a relevant skill exists, update it with skill_manage. Otherwise create a new skill if the approach is reusable.\nIf nothing is worth saving, reply with exactly: Nothing to save.";
3
- export declare const COMBINED_REVIEW_USER_PROMPT = "Review the conversation above for two separate concerns:\n\n**Curated memory (declarative):** Has the user revealed durable facts about themselves, preferences, or how they want you to behave? If so, save with curated_memory (MEMORY.md vs user/MEMORY.md per tool rules).\n\n**Skills (procedural):** Was a non-trivial reusable workflow established (trial-and-error, environment-specific steps)? Use skills_list / skill_view, then skill_manage to create or patch.\n\nOnly act when something genuinely deserves persistence. If nothing stands out, reply with exactly: Nothing to save.";
4
- export declare const REVIEW_SYSTEM_PROMPT = "You are a background persistence assistant for the same user session. You do NOT chat with the user \u2014 there is no end user reading this channel.\n\nYour only job: decide whether to write curated_memory and/or skill_manage (plus skills_list / skill_view to inspect skills). Keep tool calls minimal. If nothing deserves saving, reply with exactly: Nothing to save.";
1
+ export declare const MEMORY_REVIEW_USER_PROMPT = "Review the conversation above and identify durable user-understanding candidates.\n\nFocus on:\n1. Has the user revealed things about themselves \u2014 persona, desires, preferences, or personal details worth remembering?\n2. Has the user expressed expectations about how you should behave, their work style, or how they want you to operate?\n\nReturn JSON only, with this shape:\n{\"candidates\":[{\"kind\":\"preference\",\"content\":\"...\",\"confidence\":0.8,\"importance\":0.7,\"durability\":\"durable\",\"sensitivity\":\"normal\",\"disclosurePolicy\":\"referenceable\",\"tags\":[\"background-review\"]}]}\n\nAllowed kinds: preference, boundary, relationship, project_context, commitment, routine, personal_logistics, open_question, milestone, current_state, task_lesson, tool_preference, long_term_goal, derived_insight.\nOnly include facts supported by the conversation and likely to matter in a future session. Never include passwords, tokens, credentials, or speculative diagnoses. Use {\"candidates\":[]} when nothing qualifies.";
2
+ export declare const UNDERSTANDING_REVIEW_SYSTEM_PROMPT = "You are the user-understanding synthesis stage for the same session. You do not chat with the user and cannot write storage directly. Extract only evidence-backed, durable candidates and return strict JSON matching the requested schema.";
@@ -1,29 +1,17 @@
1
1
  //#region src/agent/background-review/prompts.ts
2
- const MEMORY_REVIEW_USER_PROMPT = `Review the conversation above and consider saving to curated memory if appropriate.
2
+ const MEMORY_REVIEW_USER_PROMPT = `Review the conversation above and identify durable user-understanding candidates.
3
3
 
4
4
  Focus on:
5
5
  1. Has the user revealed things about themselves — persona, desires, preferences, or personal details worth remembering?
6
6
  2. Has the user expressed expectations about how you should behave, their work style, or how they want you to operate?
7
7
 
8
- Use curated_memory (MEMORY.md for agent-facing notes, user/MEMORY.md for global user memory) only for durable facts that will still matter in future sessions.
9
- If nothing is worth saving, reply with exactly: Nothing to save.`;
10
- const SKILL_REVIEW_USER_PROMPT = `Review the conversation above and consider saving or updating a skill if appropriate.
8
+ Return JSON only, with this shape:
9
+ {"candidates":[{"kind":"preference","content":"...","confidence":0.8,"importance":0.7,"durability":"durable","sensitivity":"normal","disclosurePolicy":"referenceable","tags":["background-review"]}]}
11
10
 
12
- Focus on: was a non-trivial approach used to complete a task that required trial and error, or changing course from experience, or did the user expect a different reusable method?
13
-
14
- Use skills_list / skill_view to inspect existing skills. If a relevant skill exists, update it with skill_manage. Otherwise create a new skill if the approach is reusable.
15
- If nothing is worth saving, reply with exactly: Nothing to save.`;
16
- const COMBINED_REVIEW_USER_PROMPT = `Review the conversation above for two separate concerns:
17
-
18
- **Curated memory (declarative):** Has the user revealed durable facts about themselves, preferences, or how they want you to behave? If so, save with curated_memory (MEMORY.md vs user/MEMORY.md per tool rules).
19
-
20
- **Skills (procedural):** Was a non-trivial reusable workflow established (trial-and-error, environment-specific steps)? Use skills_list / skill_view, then skill_manage to create or patch.
21
-
22
- Only act when something genuinely deserves persistence. If nothing stands out, reply with exactly: Nothing to save.`;
23
- const REVIEW_SYSTEM_PROMPT = `You are a background persistence assistant for the same user session. You do NOT chat with the user — there is no end user reading this channel.
24
-
25
- Your only job: decide whether to write curated_memory and/or skill_manage (plus skills_list / skill_view to inspect skills). Keep tool calls minimal. If nothing deserves saving, reply with exactly: Nothing to save.`;
11
+ Allowed kinds: preference, boundary, relationship, project_context, commitment, routine, personal_logistics, open_question, milestone, current_state, task_lesson, tool_preference, long_term_goal, derived_insight.
12
+ Only include facts supported by the conversation and likely to matter in a future session. Never include passwords, tokens, credentials, or speculative diagnoses. Use {"candidates":[]} when nothing qualifies.`;
13
+ const UNDERSTANDING_REVIEW_SYSTEM_PROMPT = `You are the user-understanding synthesis stage for the same session. You do not chat with the user and cannot write storage directly. Extract only evidence-backed, durable candidates and return strict JSON matching the requested schema.`;
26
14
  //#endregion
27
- export { COMBINED_REVIEW_USER_PROMPT, MEMORY_REVIEW_USER_PROMPT, REVIEW_SYSTEM_PROMPT, SKILL_REVIEW_USER_PROMPT };
15
+ export { MEMORY_REVIEW_USER_PROMPT, UNDERSTANDING_REVIEW_SYSTEM_PROMPT };
28
16
 
29
17
  //# sourceMappingURL=prompts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","names":[],"sources":["../../../../src/agent/background-review/prompts.ts"],"sourcesContent":["export const MEMORY_REVIEW_USER_PROMPT = `Review the conversation above and consider saving to curated memory if appropriate.\n\nFocus on:\n1. Has the user revealed things about themselves — persona, desires, preferences, or personal details worth remembering?\n2. Has the user expressed expectations about how you should behave, their work style, or how they want you to operate?\n\nUse curated_memory (MEMORY.md for agent-facing notes, user/MEMORY.md for global user memory) only for durable facts that will still matter in future sessions.\nIf nothing is worth saving, reply with exactly: Nothing to save.`;\n\nexport const SKILL_REVIEW_USER_PROMPT = `Review the conversation above and consider saving or updating a skill if appropriate.\n\nFocus on: was a non-trivial approach used to complete a task that required trial and error, or changing course from experience, or did the user expect a different reusable method?\n\nUse skills_list / skill_view to inspect existing skills. If a relevant skill exists, update it with skill_manage. Otherwise create a new skill if the approach is reusable.\nIf nothing is worth saving, reply with exactly: Nothing to save.`;\n\nexport const COMBINED_REVIEW_USER_PROMPT = `Review the conversation above for two separate concerns:\n\n**Curated memory (declarative):** Has the user revealed durable facts about themselves, preferences, or how they want you to behave? If so, save with curated_memory (MEMORY.md vs user/MEMORY.md per tool rules).\n\n**Skills (procedural):** Was a non-trivial reusable workflow established (trial-and-error, environment-specific steps)? Use skills_list / skill_view, then skill_manage to create or patch.\n\nOnly act when something genuinely deserves persistence. If nothing stands out, reply with exactly: Nothing to save.`;\n\nexport const REVIEW_SYSTEM_PROMPT = `You are a background persistence assistant for the same user session. You do NOT chat with the user there is no end user reading this channel.\n\nYour only job: decide whether to write curated_memory and/or skill_manage (plus skills_list / skill_view to inspect skills). Keep tool calls minimal. If nothing deserves saving, reply with exactly: Nothing to save.`;\n"],"mappings":";AAAA,MAAa,4BAA4B;;;;;;;;AASzC,MAAa,2BAA2B;;;;;;AAOxC,MAAa,8BAA8B;;;;;;;AAQ3C,MAAa,uBAAuB"}
1
+ {"version":3,"file":"prompts.js","names":[],"sources":["../../../../src/agent/background-review/prompts.ts"],"sourcesContent":["export const MEMORY_REVIEW_USER_PROMPT = `Review the conversation above and identify durable user-understanding candidates.\n\nFocus on:\n1. Has the user revealed things about themselves — persona, desires, preferences, or personal details worth remembering?\n2. Has the user expressed expectations about how you should behave, their work style, or how they want you to operate?\n\nReturn JSON only, with this shape:\n{\"candidates\":[{\"kind\":\"preference\",\"content\":\"...\",\"confidence\":0.8,\"importance\":0.7,\"durability\":\"durable\",\"sensitivity\":\"normal\",\"disclosurePolicy\":\"referenceable\",\"tags\":[\"background-review\"]}]}\n\nAllowed kinds: preference, boundary, relationship, project_context, commitment, routine, personal_logistics, open_question, milestone, current_state, task_lesson, tool_preference, long_term_goal, derived_insight.\nOnly include facts supported by the conversation and likely to matter in a future session. Never include passwords, tokens, credentials, or speculative diagnoses. Use {\"candidates\":[]} when nothing qualifies.`;\n\nexport const UNDERSTANDING_REVIEW_SYSTEM_PROMPT = `You are the user-understanding synthesis stage for the same session. You do not chat with the user and cannot write storage directly. Extract only evidence-backed, durable candidates and return strict JSON matching the requested schema.`;\n"],"mappings":";AAAA,MAAa,4BAA4B;;;;;;;;;;;AAYzC,MAAa,qCAAqC"}
@@ -1,20 +1,12 @@
1
1
  import { Agent } from '@earendil-works/pi-agent-core';
2
2
  import type { Config } from '../../config/schema.js';
3
3
  import type { MemoryManager } from '../memory/manager.js';
4
- import type { SkillManager } from '../skills/skill-manager.js';
5
4
  import type { BackgroundReviewSettings } from './settings.js';
6
5
  export interface RunBackgroundReviewParams {
7
6
  sessionKey: string;
8
7
  mainAgent: Agent;
9
8
  settings: BackgroundReviewSettings;
10
- reviewMemory: boolean;
11
- reviewSkills: boolean;
12
- registeredToolNames: string[];
13
- skillAllowlist?: string[];
14
- workspacePath: string;
15
- skillManager: SkillManager;
16
9
  memoryManager: MemoryManager;
17
10
  getConfig: () => Config | undefined;
18
- onSkillsFilesystemMutate: () => void;
19
11
  }
20
12
  export declare function runBackgroundReviewTurn(params: RunBackgroundReviewParams): Promise<void>;
@@ -4,14 +4,9 @@ import { init_sync_provider_auth, resolveProviderApiKeySync } from "../../auth/s
4
4
  import { getApiKeySync, init_providers } from "../../providers/index.js";
5
5
  import { createExtensionAwareStreamFn } from "../../providers/extension-stream-bridge.js";
6
6
  import { extractTextContent } from "../context/workspace.js";
7
- import { createCuratedMemoryTool } from "../tools/curated-memory-tool.js";
8
7
  import { resolveAgentTurnTimeoutMs, runAgentTurnWithTimeout } from "../orchestration/run-agent-turn-with-timeout.js";
9
- import { createSkillViewTool, createSkillsListTool } from "../tools/skills-tools.js";
10
- import { createSkillManageTool } from "../tools/skill-manage-tool.js";
11
- import { shouldRegisterCuratedMemoryTool } from "../memory/memory-config.js";
12
- import { wrapToolsWithProtection } from "../tools/executor.js";
13
8
  import { isAssistantTurnAborted, isAssistantTurnFailed } from "../orchestration/llm-turn-retry.js";
14
- import { COMBINED_REVIEW_USER_PROMPT, MEMORY_REVIEW_USER_PROMPT, REVIEW_SYSTEM_PROMPT, SKILL_REVIEW_USER_PROMPT } from "./prompts.js";
9
+ import { MEMORY_REVIEW_USER_PROMPT, UNDERSTANDING_REVIEW_SYSTEM_PROMPT } from "./prompts.js";
15
10
  import { Agent } from "@earendil-works/pi-agent-core";
16
11
  //#region src/agent/background-review/run-background-review.ts
17
12
  init_sync_provider_auth();
@@ -22,59 +17,84 @@ function cloneMessageTail(messages, max) {
22
17
  const tail = messages.length <= max ? messages : messages.slice(-max);
23
18
  return JSON.parse(JSON.stringify(tail));
24
19
  }
25
- async function runBackgroundReviewTurn(params) {
26
- const { sessionKey, mainAgent, settings, reviewMemory, reviewSkills, registeredToolNames, skillAllowlist, workspacePath, skillManager, memoryManager, getConfig, onSkillsFilesystemMutate } = params;
27
- const userPrompt = reviewMemory && reviewSkills ? COMBINED_REVIEW_USER_PROMPT : reviewMemory ? MEMORY_REVIEW_USER_PROMPT : SKILL_REVIEW_USER_PROMPT;
28
- const rawTools = [];
29
- if (reviewMemory && shouldRegisterCuratedMemoryTool(getConfig())) rawTools.push(createCuratedMemoryTool(() => memoryManager));
30
- if (reviewSkills) {
31
- const ctx = () => ({
32
- registeredToolNames,
33
- skillAllowlist
34
- });
35
- rawTools.push(createSkillsListTool({
36
- getSkillManager: () => skillManager,
37
- getSkillIndexingContext: ctx
38
- }), createSkillViewTool({
39
- getSkillManager: () => skillManager,
40
- getSkillIndexingContext: ctx
41
- }), createSkillManageTool({
42
- getSkillManager: () => skillManager,
43
- getWorkspace: () => workspacePath,
44
- onSkillsFilesystemMutate
45
- }));
20
+ const ALLOWED_UNDERSTANDING_KINDS = new Set([
21
+ "preference",
22
+ "boundary",
23
+ "relationship",
24
+ "project_context",
25
+ "commitment",
26
+ "routine",
27
+ "personal_logistics",
28
+ "open_question",
29
+ "milestone",
30
+ "current_state",
31
+ "task_lesson",
32
+ "tool_preference",
33
+ "long_term_goal",
34
+ "derived_insight"
35
+ ]);
36
+ const ALLOWED_SENSITIVITIES = new Set([
37
+ "normal",
38
+ "personal",
39
+ "secret",
40
+ "regulated"
41
+ ]);
42
+ function lastAssistantText(agent) {
43
+ for (let i = agent.state.messages.length - 1; i >= 0; i--) {
44
+ const message = agent.state.messages[i];
45
+ if (message.role !== "assistant") continue;
46
+ return Array.isArray(message.content) ? extractTextContent(message.content) : String(message.content);
46
47
  }
47
- if (rawTools.length === 0) {
48
- log.debug({ sessionKey }, "Background review skipped: no tools registered for selected channels");
49
- return;
48
+ return "";
49
+ }
50
+ function parseUnderstandingCandidates(raw) {
51
+ const fenced = /```(?:json)?\s*([\s\S]*?)```/i.exec(raw)?.[1];
52
+ const start = raw.indexOf("{");
53
+ const end = raw.lastIndexOf("}");
54
+ const candidateJson = fenced ?? (start >= 0 && end > start ? raw.slice(start, end + 1) : raw);
55
+ try {
56
+ const parsed = JSON.parse(candidateJson);
57
+ if (!Array.isArray(parsed.candidates)) return [];
58
+ const output = [];
59
+ for (const value of parsed.candidates.slice(0, 8)) {
60
+ if (!value || typeof value !== "object") continue;
61
+ const item = value;
62
+ if (!ALLOWED_UNDERSTANDING_KINDS.has(item.kind)) continue;
63
+ if (typeof item.content !== "string" || item.content.trim().length < 4) continue;
64
+ const confidence = typeof item.confidence === "number" ? item.confidence : .65;
65
+ const importance = typeof item.importance === "number" ? item.importance : .5;
66
+ const durability = item.durability === "ephemeral" || item.durability === "recurring" ? item.durability : "durable";
67
+ const sensitivity = ALLOWED_SENSITIVITIES.has(item.sensitivity) ? item.sensitivity : "personal";
68
+ const disclosurePolicy = item.disclosurePolicy === "silent" || item.disclosurePolicy === "ask_before_reference" ? item.disclosurePolicy : "referenceable";
69
+ output.push({
70
+ kind: item.kind,
71
+ content: item.content.trim(),
72
+ confidence: Math.max(0, Math.min(1, confidence)),
73
+ importance: Math.max(0, Math.min(1, importance)),
74
+ explicitness: "inferred",
75
+ durability,
76
+ sensitivity,
77
+ disclosurePolicy,
78
+ tags: Array.isArray(item.tags) ? item.tags.filter((tag) => typeof tag === "string").slice(0, 8) : ["background-review"]
79
+ });
80
+ }
81
+ return output;
82
+ } catch {
83
+ return [];
50
84
  }
51
- const tools = wrapToolsWithProtection(rawTools, {});
52
- const model = mainAgent.state.model;
53
- let toolRounds = 0;
54
- let aborted = false;
85
+ }
86
+ async function runUnderstandingReview(params) {
87
+ const { sessionKey, mainAgent, settings, memoryManager, getConfig } = params;
55
88
  const reviewAgent = new Agent({
56
89
  initialState: {
57
- systemPrompt: REVIEW_SYSTEM_PROMPT,
58
- model,
90
+ systemPrompt: UNDERSTANDING_REVIEW_SYSTEM_PROMPT,
91
+ model: mainAgent.state.model,
59
92
  thinkingLevel: "off",
60
- tools,
93
+ tools: [],
61
94
  messages: []
62
95
  },
63
96
  streamFn: createExtensionAwareStreamFn(),
64
- getApiKey: (provider) => resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? "",
65
- beforeToolCall: async () => {
66
- if (aborted) return {
67
- block: true,
68
- reason: "Background review aborted."
69
- };
70
- if (toolRounds >= settings.maxToolRounds) return {
71
- block: true,
72
- reason: `Background review reached max tool rounds (${settings.maxToolRounds}).`
73
- };
74
- },
75
- afterToolCall: async () => {
76
- toolRounds += 1;
77
- }
97
+ getApiKey: (provider) => resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? ""
78
98
  });
79
99
  reviewAgent.state.messages = cloneMessageTail(mainAgent.state.messages, settings.maxHistoryMessages);
80
100
  const timeoutMs = Math.min(settings.maxDurationMs, resolveAgentTurnTimeoutMs(getConfig()));
@@ -82,7 +102,7 @@ async function runBackgroundReviewTurn(params) {
82
102
  await runAgentTurnWithTimeout(reviewAgent, async () => {
83
103
  await reviewAgent.prompt({
84
104
  role: "user",
85
- content: userPrompt,
105
+ content: MEMORY_REVIEW_USER_PROMPT,
86
106
  timestamp: Date.now()
87
107
  });
88
108
  await reviewAgent.waitForIdle();
@@ -91,30 +111,25 @@ async function runBackgroundReviewTurn(params) {
91
111
  log.warn({
92
112
  err,
93
113
  sessionKey
94
- }, "Background review turn failed or timed out");
95
- aborted = true;
114
+ }, "User-understanding review failed or timed out");
96
115
  reviewAgent.abort();
97
116
  await reviewAgent.waitForIdle().catch(() => {});
98
117
  return;
99
118
  }
100
- if (isAssistantTurnAborted(reviewAgent) || isAssistantTurnFailed(reviewAgent)) {
101
- log.debug({ sessionKey }, "Background review produced aborted/failed assistant turn");
102
- return;
103
- }
104
- const last = reviewAgent.state.messages;
105
- for (let i = last.length - 1; i >= 0; i--) {
106
- const msg = last[i];
107
- if (msg.role === "assistant") {
108
- const content = msg.content;
109
- const trimmed = (Array.isArray(content) ? extractTextContent(content) : String(content)).trim();
110
- if (trimmed && !/^nothing to save\.?$/i.test(trimmed)) log.info({
111
- sessionKey,
112
- preview: trimmed.slice(0, 120)
113
- }, "Background review completed");
114
- else log.debug({ sessionKey }, "Background review: nothing to save");
115
- return;
116
- }
117
- }
119
+ if (isAssistantTurnAborted(reviewAgent) || isAssistantTurnFailed(reviewAgent)) return;
120
+ const candidates = parseUnderstandingCandidates(lastAssistantText(reviewAgent));
121
+ await memoryManager.applyUnderstandingCandidates(candidates, {
122
+ sessionKey,
123
+ sourceText: "Background review of the current session transcript",
124
+ reviewSource: "background"
125
+ });
126
+ log.debug({
127
+ sessionKey,
128
+ candidateCount: candidates.length
129
+ }, "User-understanding review completed");
130
+ }
131
+ async function runBackgroundReviewTurn(params) {
132
+ await runUnderstandingReview(params);
118
133
  }
119
134
  //#endregion
120
135
  export { runBackgroundReviewTurn };
@@ -1 +1 @@
1
- {"version":3,"file":"run-background-review.js","names":[],"sources":["../../../../src/agent/background-review/run-background-review.ts"],"sourcesContent":["import { Agent, type AgentMessage, type ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveProviderApiKeySync } from '../../auth/sync-provider-auth.js';\nimport { getApiKeySync } from '../../providers/index.js';\nimport { createExtensionAwareStreamFn } from '../../providers/extension-stream-bridge.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { extractTextContent } from '../context/workspace.js';\nimport { shouldRegisterCuratedMemoryTool } from '../memory/memory-config.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport {\n runAgentTurnWithTimeout,\n resolveAgentTurnTimeoutMs,\n} from '../orchestration/run-agent-turn-with-timeout.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n} from '../orchestration/llm-turn-retry.js';\nimport type { SkillManager } from '../skills/skill-manager.js';\nimport { createCuratedMemoryTool } from '../tools/curated-memory-tool.js';\nimport { createSkillManageTool } from '../tools/skill-manage-tool.js';\nimport { createSkillsListTool, createSkillViewTool } from '../tools/skills-tools.js';\nimport { wrapToolsWithProtection } from '../tools/executor.js';\n\nimport type { BackgroundReviewSettings } from './settings.js';\nimport {\n COMBINED_REVIEW_USER_PROMPT,\n MEMORY_REVIEW_USER_PROMPT,\n REVIEW_SYSTEM_PROMPT,\n SKILL_REVIEW_USER_PROMPT,\n} from './prompts.js';\n\nconst log = createLogger('BackgroundReview');\n\nfunction cloneMessageTail(messages: AgentMessage[], max: number): AgentMessage[] {\n const tail = messages.length <= max ? messages : messages.slice(-max);\n return JSON.parse(JSON.stringify(tail)) as AgentMessage[];\n}\n\nexport interface RunBackgroundReviewParams {\n sessionKey: string;\n mainAgent: Agent;\n settings: BackgroundReviewSettings;\n reviewMemory: boolean;\n reviewSkills: boolean;\n registeredToolNames: string[];\n skillAllowlist?: string[];\n workspacePath: string;\n skillManager: SkillManager;\n memoryManager: MemoryManager;\n getConfig: () => Config | undefined;\n onSkillsFilesystemMutate: () => void;\n}\n\nexport async function runBackgroundReviewTurn(params: RunBackgroundReviewParams): Promise<void> {\n const {\n sessionKey,\n mainAgent,\n settings,\n reviewMemory,\n reviewSkills,\n registeredToolNames,\n skillAllowlist,\n workspacePath,\n skillManager,\n memoryManager,\n getConfig,\n onSkillsFilesystemMutate,\n } = params;\n\n const userPrompt =\n reviewMemory && reviewSkills\n ? COMBINED_REVIEW_USER_PROMPT\n : reviewMemory\n ? MEMORY_REVIEW_USER_PROMPT\n : SKILL_REVIEW_USER_PROMPT;\n\n const rawTools: any[] = [];\n\n if (reviewMemory && shouldRegisterCuratedMemoryTool(getConfig())) {\n rawTools.push(createCuratedMemoryTool(() => memoryManager));\n }\n\n if (reviewSkills) {\n const ctx = () => ({ registeredToolNames, skillAllowlist });\n rawTools.push(\n createSkillsListTool({\n getSkillManager: () => skillManager,\n getSkillIndexingContext: ctx,\n }),\n createSkillViewTool({\n getSkillManager: () => skillManager,\n getSkillIndexingContext: ctx,\n }),\n createSkillManageTool({\n getSkillManager: () => skillManager,\n getWorkspace: () => workspacePath,\n onSkillsFilesystemMutate,\n }),\n );\n }\n\n if (rawTools.length === 0) {\n log.debug({ sessionKey }, 'Background review skipped: no tools registered for selected channels');\n return;\n }\n\n const tools = wrapToolsWithProtection(rawTools, {});\n\n const model = mainAgent.state.model as Model<Api>;\n let toolRounds = 0;\n let aborted = false;\n\n const reviewAgent = new Agent({\n initialState: {\n systemPrompt: REVIEW_SYSTEM_PROMPT,\n model,\n thinkingLevel: 'off' as ThinkingLevel,\n tools,\n messages: [],\n },\n streamFn: createExtensionAwareStreamFn(),\n getApiKey: (provider: string) =>\n resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? '',\n beforeToolCall: async () => {\n if (aborted) {\n return { block: true, reason: 'Background review aborted.' };\n }\n if (toolRounds >= settings.maxToolRounds) {\n return {\n block: true,\n reason: `Background review reached max tool rounds (${settings.maxToolRounds}).`,\n };\n }\n return undefined;\n },\n afterToolCall: async () => {\n toolRounds += 1;\n return undefined;\n },\n });\n\n reviewAgent.state.messages = cloneMessageTail(mainAgent.state.messages, settings.maxHistoryMessages);\n\n const timeoutMs = Math.min(settings.maxDurationMs, resolveAgentTurnTimeoutMs(getConfig()));\n\n try {\n await runAgentTurnWithTimeout(\n reviewAgent,\n async () => {\n await reviewAgent.prompt({\n role: 'user',\n content: userPrompt,\n timestamp: Date.now(),\n });\n await reviewAgent.waitForIdle();\n },\n timeoutMs,\n );\n } catch (err) {\n log.warn({ err, sessionKey }, 'Background review turn failed or timed out');\n aborted = true;\n reviewAgent.abort();\n await reviewAgent.waitForIdle().catch(() => {});\n return;\n }\n\n if (isAssistantTurnAborted(reviewAgent) || isAssistantTurnFailed(reviewAgent)) {\n log.debug({ sessionKey }, 'Background review produced aborted/failed assistant turn');\n return;\n }\n\n const last = reviewAgent.state.messages;\n for (let i = last.length - 1; i >= 0; i--) {\n const msg = last[i];\n if (msg.role === 'assistant') {\n const content = msg.content;\n const text = Array.isArray(content)\n ? extractTextContent(content as Array<{ type: string; text?: string }>)\n : String(content);\n const trimmed = text.trim();\n if (trimmed && !/^nothing to save\\.?$/i.test(trimmed)) {\n log.info({ sessionKey, preview: trimmed.slice(0, 120) }, 'Background review completed');\n } else {\n log.debug({ sessionKey }, 'Background review: nothing to save');\n }\n return;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;yBAI6E;gBACpB;aAEJ;AA2BrD,MAAM,MAAM,aAAa,mBAAmB;AAE5C,SAAS,iBAAiB,UAA0B,KAA6B;CAC/E,MAAM,OAAO,SAAS,UAAU,MAAM,WAAW,SAAS,MAAM,CAAC,IAAI;AACrE,QAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;;AAkBzC,eAAsB,wBAAwB,QAAkD;CAC9F,MAAM,EACJ,YACA,WACA,UACA,cACA,cACA,qBACA,gBACA,eACA,cACA,eACA,WACA,6BACE;CAEJ,MAAM,aACJ,gBAAgB,eACZ,8BACA,eACE,4BACA;CAER,MAAM,WAAkB,EAAE;AAE1B,KAAI,gBAAgB,gCAAgC,WAAW,CAAC,CAC9D,UAAS,KAAK,8BAA8B,cAAc,CAAC;AAG7D,KAAI,cAAc;EAChB,MAAM,aAAa;GAAE;GAAqB;GAAgB;AAC1D,WAAS,KACP,qBAAqB;GACnB,uBAAuB;GACvB,yBAAyB;GAC1B,CAAC,EACF,oBAAoB;GAClB,uBAAuB;GACvB,yBAAyB;GAC1B,CAAC,EACF,sBAAsB;GACpB,uBAAuB;GACvB,oBAAoB;GACpB;GACD,CAAC,CACH;;AAGH,KAAI,SAAS,WAAW,GAAG;AACzB,MAAI,MAAM,EAAE,YAAY,EAAE,uEAAuE;AACjG;;CAGF,MAAM,QAAQ,wBAAwB,UAAU,EAAE,CAAC;CAEnD,MAAM,QAAQ,UAAU,MAAM;CAC9B,IAAI,aAAa;CACjB,IAAI,UAAU;CAEd,MAAM,cAAc,IAAI,MAAM;EAC5B,cAAc;GACZ,cAAc;GACd;GACA,eAAe;GACf;GACA,UAAU,EAAE;GACb;EACD,UAAU,8BAA8B;EACxC,YAAY,aACV,0BAA0B,SAAS,IAAI,cAAc,SAAS,IAAI;EACpE,gBAAgB,YAAY;AAC1B,OAAI,QACF,QAAO;IAAE,OAAO;IAAM,QAAQ;IAA8B;AAE9D,OAAI,cAAc,SAAS,cACzB,QAAO;IACL,OAAO;IACP,QAAQ,8CAA8C,SAAS,cAAc;IAC9E;;EAIL,eAAe,YAAY;AACzB,iBAAc;;EAGjB,CAAC;AAEF,aAAY,MAAM,WAAW,iBAAiB,UAAU,MAAM,UAAU,SAAS,mBAAmB;CAEpG,MAAM,YAAY,KAAK,IAAI,SAAS,eAAe,0BAA0B,WAAW,CAAC,CAAC;AAE1F,KAAI;AACF,QAAM,wBACJ,aACA,YAAY;AACV,SAAM,YAAY,OAAO;IACvB,MAAM;IACN,SAAS;IACT,WAAW,KAAK,KAAK;IACtB,CAAC;AACF,SAAM,YAAY,aAAa;KAEjC,UACD;UACM,KAAK;AACZ,MAAI,KAAK;GAAE;GAAK;GAAY,EAAE,6CAA6C;AAC3E,YAAU;AACV,cAAY,OAAO;AACnB,QAAM,YAAY,aAAa,CAAC,YAAY,GAAG;AAC/C;;AAGF,KAAI,uBAAuB,YAAY,IAAI,sBAAsB,YAAY,EAAE;AAC7E,MAAI,MAAM,EAAE,YAAY,EAAE,2DAA2D;AACrF;;CAGF,MAAM,OAAO,YAAY,MAAM;AAC/B,MAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;EACzC,MAAM,MAAM,KAAK;AACjB,MAAI,IAAI,SAAS,aAAa;GAC5B,MAAM,UAAU,IAAI;GAIpB,MAAM,WAHO,MAAM,QAAQ,QAAQ,GAC/B,mBAAmB,QAAkD,GACrE,OAAO,QAAQ,EACE,MAAM;AAC3B,OAAI,WAAW,CAAC,wBAAwB,KAAK,QAAQ,CACnD,KAAI,KAAK;IAAE;IAAY,SAAS,QAAQ,MAAM,GAAG,IAAI;IAAE,EAAE,8BAA8B;OAEvF,KAAI,MAAM,EAAE,YAAY,EAAE,qCAAqC;AAEjE"}
1
+ {"version":3,"file":"run-background-review.js","names":[],"sources":["../../../../src/agent/background-review/run-background-review.ts"],"sourcesContent":["import { Agent, type AgentMessage, type ThinkingLevel } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveProviderApiKeySync } from '../../auth/sync-provider-auth.js';\nimport { getApiKeySync } from '../../providers/index.js';\nimport { createExtensionAwareStreamFn } from '../../providers/extension-stream-bridge.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { extractTextContent } from '../context/workspace.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport type { UnderstandingCandidate } from '../memory/understanding/types.js';\nimport {\n runAgentTurnWithTimeout,\n resolveAgentTurnTimeoutMs,\n} from '../orchestration/run-agent-turn-with-timeout.js';\nimport {\n isAssistantTurnAborted,\n isAssistantTurnFailed,\n} from '../orchestration/llm-turn-retry.js';\n\nimport type { BackgroundReviewSettings } from './settings.js';\nimport {\n MEMORY_REVIEW_USER_PROMPT,\n UNDERSTANDING_REVIEW_SYSTEM_PROMPT,\n} from './prompts.js';\n\nconst log = createLogger('BackgroundReview');\n\nfunction cloneMessageTail(messages: AgentMessage[], max: number): AgentMessage[] {\n const tail = messages.length <= max ? messages : messages.slice(-max);\n return JSON.parse(JSON.stringify(tail)) as AgentMessage[];\n}\n\nexport interface RunBackgroundReviewParams {\n sessionKey: string;\n mainAgent: Agent;\n settings: BackgroundReviewSettings;\n memoryManager: MemoryManager;\n getConfig: () => Config | undefined;\n}\n\nconst ALLOWED_UNDERSTANDING_KINDS = new Set<UnderstandingCandidate['kind']>([\n 'preference', 'boundary', 'relationship', 'project_context', 'commitment', 'routine',\n 'personal_logistics', 'open_question', 'milestone', 'current_state', 'task_lesson',\n 'tool_preference', 'long_term_goal', 'derived_insight',\n]);\nconst ALLOWED_SENSITIVITIES = new Set<UnderstandingCandidate['sensitivity']>([\n 'normal', 'personal', 'secret', 'regulated',\n]);\n\nfunction lastAssistantText(agent: Agent): string {\n for (let i = agent.state.messages.length - 1; i >= 0; i--) {\n const message = agent.state.messages[i];\n if (message.role !== 'assistant') continue;\n return Array.isArray(message.content)\n ? extractTextContent(message.content as Array<{ type: string; text?: string }>)\n : String(message.content);\n }\n return '';\n}\n\nfunction parseUnderstandingCandidates(raw: string): UnderstandingCandidate[] {\n const fenced = /```(?:json)?\\s*([\\s\\S]*?)```/i.exec(raw)?.[1];\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n const candidateJson = fenced ?? (start >= 0 && end > start ? raw.slice(start, end + 1) : raw);\n try {\n const parsed = JSON.parse(candidateJson) as { candidates?: unknown };\n if (!Array.isArray(parsed.candidates)) return [];\n const output: UnderstandingCandidate[] = [];\n for (const value of parsed.candidates.slice(0, 8)) {\n if (!value || typeof value !== 'object') continue;\n const item = value as Record<string, unknown>;\n if (!ALLOWED_UNDERSTANDING_KINDS.has(item.kind as UnderstandingCandidate['kind'])) continue;\n if (typeof item.content !== 'string' || item.content.trim().length < 4) continue;\n const confidence = typeof item.confidence === 'number' ? item.confidence : 0.65;\n const importance = typeof item.importance === 'number' ? item.importance : 0.5;\n const durability = item.durability === 'ephemeral' || item.durability === 'recurring'\n ? item.durability\n : 'durable';\n const sensitivity = ALLOWED_SENSITIVITIES.has(item.sensitivity as UnderstandingCandidate['sensitivity'])\n ? item.sensitivity as UnderstandingCandidate['sensitivity']\n : 'personal';\n const disclosurePolicy = item.disclosurePolicy === 'silent' || item.disclosurePolicy === 'ask_before_reference'\n ? item.disclosurePolicy\n : 'referenceable';\n output.push({\n kind: item.kind as UnderstandingCandidate['kind'],\n content: item.content.trim(),\n confidence: Math.max(0, Math.min(1, confidence)),\n importance: Math.max(0, Math.min(1, importance)),\n explicitness: 'inferred',\n durability,\n sensitivity,\n disclosurePolicy,\n tags: Array.isArray(item.tags)\n ? item.tags.filter((tag): tag is string => typeof tag === 'string').slice(0, 8)\n : ['background-review'],\n });\n }\n return output;\n } catch {\n return [];\n }\n}\n\nasync function runUnderstandingReview(params: RunBackgroundReviewParams): Promise<void> {\n const { sessionKey, mainAgent, settings, memoryManager, getConfig } = params;\n const reviewAgent = new Agent({\n initialState: {\n systemPrompt: UNDERSTANDING_REVIEW_SYSTEM_PROMPT,\n model: mainAgent.state.model as Model<Api>,\n thinkingLevel: 'off' as ThinkingLevel,\n tools: [],\n messages: [],\n },\n streamFn: createExtensionAwareStreamFn(),\n getApiKey: (provider: string) => resolveProviderApiKeySync(provider) ?? getApiKeySync(provider) ?? '',\n });\n reviewAgent.state.messages = cloneMessageTail(mainAgent.state.messages, settings.maxHistoryMessages);\n const timeoutMs = Math.min(settings.maxDurationMs, resolveAgentTurnTimeoutMs(getConfig()));\n try {\n await runAgentTurnWithTimeout(reviewAgent, async () => {\n await reviewAgent.prompt({ role: 'user', content: MEMORY_REVIEW_USER_PROMPT, timestamp: Date.now() });\n await reviewAgent.waitForIdle();\n }, timeoutMs);\n } catch (err) {\n log.warn({ err, sessionKey }, 'User-understanding review failed or timed out');\n reviewAgent.abort();\n await reviewAgent.waitForIdle().catch(() => {});\n return;\n }\n if (isAssistantTurnAborted(reviewAgent) || isAssistantTurnFailed(reviewAgent)) return;\n const candidates = parseUnderstandingCandidates(lastAssistantText(reviewAgent));\n await memoryManager.applyUnderstandingCandidates(candidates, {\n sessionKey,\n sourceText: 'Background review of the current session transcript',\n reviewSource: 'background',\n });\n log.debug({ sessionKey, candidateCount: candidates.length }, 'User-understanding review completed');\n}\n\nexport async function runBackgroundReviewTurn(params: RunBackgroundReviewParams): Promise<void> {\n await runUnderstandingReview(params);\n}\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import type { Config } from '../../config/schema.js';
2
2
  export interface BackgroundReviewSettings {
3
3
  enabled: boolean;
4
- memoryNudgeInterval: number;
5
- skillNudgeInterval: number;
6
- maxToolRounds: number;
4
+ agentId?: string;
5
+ adaptiveCadence: boolean;
6
+ reviewIntervalTurns: number;
7
7
  maxHistoryMessages: number;
8
8
  maxDurationMs: number;
9
9
  }
10
- export declare function resolveBackgroundReviewSettings(_config: Config | undefined): BackgroundReviewSettings;
10
+ export declare function resolveBackgroundReviewSettings(config: Config | undefined, sessionKey?: string): BackgroundReviewSettings;
@@ -1,14 +1,29 @@
1
+ import { resolveEffectiveAgentManifestForSession } from "../../config/agent-profile.js";
1
2
  //#region src/agent/background-review/settings.ts
2
- function resolveBackgroundReviewSettings(_config) {
3
- const numberOrDefault = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.trunc(value) : fallback;
4
- return {
5
- enabled: false,
6
- memoryNudgeInterval: numberOrDefault(void 0, 10),
7
- skillNudgeInterval: numberOrDefault(void 0, 10),
8
- maxToolRounds: numberOrDefault(void 0, 8),
9
- maxHistoryMessages: numberOrDefault(void 0, 80),
10
- maxDurationMs: numberOrDefault(void 0, 12e4)
11
- };
3
+ const DEFAULT_SETTINGS = {
4
+ enabled: false,
5
+ adaptiveCadence: true,
6
+ reviewIntervalTurns: 10,
7
+ maxHistoryMessages: 80,
8
+ maxDurationMs: 12e4
9
+ };
10
+ function resolveBackgroundReviewSettings(config, sessionKey) {
11
+ if (!config) return DEFAULT_SETTINGS;
12
+ try {
13
+ const manifest = resolveEffectiveAgentManifestForSession(config, sessionKey);
14
+ const memory = manifest.memory;
15
+ const understanding = memory.understanding;
16
+ return {
17
+ enabled: (memory.mode === "confirmWrite" || memory.mode === "auto") && (understanding?.enabled ?? true),
18
+ agentId: manifest.id,
19
+ adaptiveCadence: understanding?.adaptiveCadence ?? true,
20
+ reviewIntervalTurns: understanding?.reviewIntervalTurns ?? DEFAULT_SETTINGS.reviewIntervalTurns,
21
+ maxHistoryMessages: understanding?.maxHistoryMessages ?? DEFAULT_SETTINGS.maxHistoryMessages,
22
+ maxDurationMs: understanding?.maxDurationMs ?? DEFAULT_SETTINGS.maxDurationMs
23
+ };
24
+ } catch {
25
+ return DEFAULT_SETTINGS;
26
+ }
12
27
  }
13
28
  //#endregion
14
29
  export { resolveBackgroundReviewSettings };