@xopcai/xopc 0.0.142 → 0.0.143

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 (543) hide show
  1. package/README.md +1 -1
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/telegram/xopc.extension.json +1 -1
  4. package/dist/gateway/static/root/assets/activity-center-store-jITiX2vJ.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BawPxiu5.js → agent-avatar-dicebear-DiME9u_P.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-DzBXhZXO.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-81xd1p9R.js → app-management-settings-panel-Cuo7SbUP.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-DYeQsYU8.js → appearance-settings-DUfdNQqk.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-CKuKK5AU.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-D_oa7oti.js → archive-plugin-B-Qk6cGr.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Cd-bwI2N.js → attachment-load-Di6EEbQX.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DGxvRxtO.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-D-FF_WKV.js +4 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-O8svLKWw.js → binary-plugins-ZaOZDH2I.js} +1 -1
  15. package/dist/gateway/static/root/assets/block-editor-BTFhjWfg.js +184 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-BvKLdEQt.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-dJy1Eqgx.js → capability-presets-api-BU-pVZiZ.js} +1 -1
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DgyeEwzh.js +2 -0
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-Bfuhp2ty.js → channel-recipient-api-DuulnhIj.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-BbVsdD_I.js +1 -0
  21. package/dist/gateway/static/root/assets/channels-status-swr-B5lVrUsN.js +1 -0
  22. package/dist/gateway/static/root/assets/check-BODqo66o.js +1 -0
  23. package/dist/gateway/static/root/assets/chunk-QUQL4437-DXsxWP7r.js +4 -0
  24. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-page-B8QqVy3I.js +2 -0
  26. package/dist/gateway/static/root/assets/{desktop-pet-DFMfIb5F.js → desktop-pet---yzVxVR.js} +1 -1
  27. package/dist/gateway/static/root/assets/desktop-pet-settings-Dc3gqBJE.js +1 -0
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-BrYt1gAr.js → directory-picker-path-field-DCmOGLtK.js} +1 -1
  29. package/dist/gateway/static/root/assets/dreaming-settings-BgT5KZVe.js +3 -0
  30. package/dist/gateway/static/root/assets/{extension-debug-page-Bh630pLD.js → extension-debug-page-ByaKTTq4.js} +1 -1
  31. package/dist/gateway/static/root/assets/extension-page-BmRzHAZr.js +1 -0
  32. package/dist/gateway/static/root/assets/extension-settings-page-JUtwIhbF.js +1 -0
  33. package/dist/gateway/static/root/assets/{fetch-B1WtuprY.js → fetch-8QNN25Sh.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-config-api-De2N821l.js → gateway-config-api-CxicF50_.js} +1 -1
  35. package/dist/gateway/static/root/assets/gateway-settings-Bz2I_EO5.js +1 -0
  36. package/dist/gateway/static/root/assets/{gateway-startup-retry-nEujFSDj.js → gateway-startup-retry-5YBnS9Fj.js} +1 -1
  37. package/dist/gateway/static/root/assets/goal-create-dialog-VcoyuZGN.js +1 -0
  38. package/dist/gateway/static/root/assets/goal-detail-page-Cilkap2G.js +4 -0
  39. package/dist/gateway/static/root/assets/{goals-config-api-DUy3eEse.js → goals-config-api-CwcHRdC0.js} +1 -1
  40. package/dist/gateway/static/root/assets/goals-page-C6eoni4z.js +2 -0
  41. package/dist/gateway/static/root/assets/goals-settings-o4i-qAOS.js +1 -0
  42. package/dist/gateway/static/root/assets/heartbeat-settings-DQQkETX8.js +1 -0
  43. package/dist/gateway/static/root/assets/index-BKRqeRHm.js +257 -0
  44. package/dist/gateway/static/root/assets/index-CphxClbs.css +1 -0
  45. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CVIwwM15.js → keyboard-shortcuts-settings-LT6qB-ua.js} +1 -1
  46. package/dist/gateway/static/root/assets/logs-page-Dli2e3fS.js +7 -0
  47. package/dist/gateway/static/root/assets/{markdown-split-B_6us9j7.js → markdown-split-Dw-yE2-y.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-D_fryIyj.js → media-plugins-D9NNNUgE.js} +1 -1
  49. package/dist/gateway/static/root/assets/messages-CzKxM6I4.js +5 -0
  50. package/dist/gateway/static/root/assets/models-hub-panel-DVn2Q1Ik.js +2 -0
  51. package/dist/gateway/static/root/assets/notes-page-CRgbJGgk.js +1 -0
  52. package/dist/gateway/static/root/assets/notes-workbench-BxZRHLWx.js +2 -0
  53. package/dist/gateway/static/root/assets/{page-tabs-D_8jGlqx.js → page-tabs-D4hkWVt_.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-BBLMK8Mp.js → preview-open-alternatives-CIckv0uy.js} +1 -1
  55. package/dist/gateway/static/root/assets/project-detail-page-Doz53xLn.js +1 -0
  56. package/dist/gateway/static/root/assets/projects-page-DoMtcRLg.js +1 -0
  57. package/dist/gateway/static/root/assets/remote-access-hub-BeHVEgrm.js +1 -0
  58. package/dist/gateway/static/root/assets/{save-bar-controls-DVS3FR5r.js → save-bar-controls-B0b42kB2.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schedule-field-D6vKd6-T.js → schedule-field-BtjEkczK.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schema-form-BPy4lbIh.js → schema-form-Bf0bk3i6.js} +1 -1
  61. package/dist/gateway/static/root/assets/sessions-page-Bk4bQsBe.js +1 -0
  62. package/dist/gateway/static/root/assets/settings-advanced-gate-DdFyaRMm.js +1 -0
  63. package/dist/gateway/static/root/assets/{settings-collapsible-section-WzdikxPt.js → settings-collapsible-section-BTKTdTNX.js} +1 -1
  64. package/dist/gateway/static/root/assets/{settings-form-section-CvfzhBV-.js → settings-form-section-DL4P0sAj.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BxR-Ulhi.js → settings-loading-skeleton-BV6KFNj4.js} +1 -1
  66. package/dist/gateway/static/root/assets/settings-page-B_4DsX5W.js +1 -0
  67. package/dist/gateway/static/root/assets/{settings-page-layout-CKefvbYi.js → settings-page-layout-CyGlrInB.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-DJ1_MLgX.js +1 -0
  69. package/dist/gateway/static/root/assets/share-preview-page-BQBV7YrV.js +2 -0
  70. package/dist/gateway/static/root/assets/shares-settings-0VuFLBeU.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-DO87Ckeo.js +1 -0
  72. package/dist/gateway/static/root/assets/skills-page-D3VdtxAn.js +2 -0
  73. package/dist/gateway/static/root/assets/{system-settings-panel-BokgAgf7.js → system-settings-panel-D85fBBuI.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-BwHlNL3L.js → typed-models-lib-CwEuYrHX.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-DR11ap3A.js → use-channel-catalog-COXIfXcl.js} +1 -1
  76. package/dist/gateway/static/root/assets/user-context-page-m9JVQ73F.js +1 -0
  77. package/dist/gateway/static/root/assets/user-profile-fields-editor-DtQiuY7E.js +1 -0
  78. package/dist/gateway/static/root/assets/user-profile-settings-panel-CWM0fEpb.js +1 -0
  79. package/dist/gateway/static/root/assets/{utils-BKUWB-TT.js → utils--BO6xT3u.js} +1 -1
  80. package/dist/gateway/static/root/assets/voice-api-key-field-LoT3wgZ9.js +1 -0
  81. package/dist/gateway/static/root/assets/with-selector-aYPsXwdl.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page-DSTMz_mO.js +1 -0
  83. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-CL_rnAUB.js → workflow-run-setup-panel-B35lJzvm.js} +2 -2
  84. package/dist/gateway/static/root/assets/workflows-page-BfSm9oR8.js +11 -0
  85. package/dist/gateway/static/root/assets/workflows-page-DLioOiRN.css +1 -0
  86. package/dist/gateway/static/root/connector-icons/README.md +11 -0
  87. package/dist/gateway/static/root/connector-icons/airtable.svg +13 -0
  88. package/dist/gateway/static/root/connector-icons/asana.svg +15 -0
  89. package/dist/gateway/static/root/connector-icons/brave-search.svg +1 -0
  90. package/dist/gateway/static/root/connector-icons/clickup.svg +19 -0
  91. package/dist/gateway/static/root/connector-icons/composio.svg +266 -0
  92. package/dist/gateway/static/root/connector-icons/discord.svg +15 -0
  93. package/dist/gateway/static/root/connector-icons/dropbox.svg +152 -0
  94. package/dist/gateway/static/root/connector-icons/excel.svg +56 -0
  95. package/dist/gateway/static/root/connector-icons/fetch.svg +6 -0
  96. package/dist/gateway/static/root/connector-icons/figma.svg +178 -0
  97. package/dist/gateway/static/root/connector-icons/filesystem.svg +6 -0
  98. package/dist/gateway/static/root/connector-icons/github.svg +10 -0
  99. package/dist/gateway/static/root/connector-icons/gmail.svg +3 -0
  100. package/dist/gateway/static/root/connector-icons/google-calendar.svg +3 -0
  101. package/dist/gateway/static/root/connector-icons/google-docs.svg +25 -0
  102. package/dist/gateway/static/root/connector-icons/google-drive.svg +25 -0
  103. package/dist/gateway/static/root/connector-icons/google-sheets.svg +1 -0
  104. package/dist/gateway/static/root/connector-icons/hubspot.svg +142 -0
  105. package/dist/gateway/static/root/connector-icons/jira.svg +15 -0
  106. package/dist/gateway/static/root/connector-icons/linear.svg +5 -0
  107. package/dist/gateway/static/root/connector-icons/memory.svg +5 -0
  108. package/dist/gateway/static/root/connector-icons/microsoft-teams.svg +33 -0
  109. package/dist/gateway/static/root/connector-icons/notion.svg +5 -0
  110. package/dist/gateway/static/root/connector-icons/one-drive.svg +13 -0
  111. package/dist/gateway/static/root/connector-icons/outlook.svg +76 -0
  112. package/dist/gateway/static/root/connector-icons/playwright.svg +9 -0
  113. package/dist/gateway/static/root/connector-icons/salesforce.svg +17 -0
  114. package/dist/gateway/static/root/connector-icons/sequential-thinking.svg +8 -0
  115. package/dist/gateway/static/root/connector-icons/shopify.svg +5 -0
  116. package/dist/gateway/static/root/connector-icons/slack.svg +9 -0
  117. package/dist/gateway/static/root/connector-icons/spotify.svg +43 -0
  118. package/dist/gateway/static/root/connector-icons/stripe.svg +11 -0
  119. package/dist/gateway/static/root/connector-icons/telegram.svg +130 -0
  120. package/dist/gateway/static/root/connector-icons/time.svg +6 -0
  121. package/dist/gateway/static/root/connector-icons/todoist.svg +277 -0
  122. package/dist/gateway/static/root/connector-icons/trello.svg +19 -0
  123. package/dist/gateway/static/root/connector-icons/twitter.svg +128 -0
  124. package/dist/gateway/static/root/connector-icons/whatsapp.svg +61 -0
  125. package/dist/gateway/static/root/connector-icons/youtube.svg +11 -0
  126. package/dist/gateway/static/root/index.html +9 -6
  127. package/dist/package.js +1 -1
  128. package/dist/src/agent/agent-manager.d.ts +2 -0
  129. package/dist/src/agent/agent-manager.js +8 -0
  130. package/dist/src/agent/agent-manager.js.map +1 -1
  131. package/dist/src/agent/background-review/prompts.d.ts +1 -1
  132. package/dist/src/agent/background-review/prompts.js +3 -2
  133. package/dist/src/agent/background-review/prompts.js.map +1 -1
  134. package/dist/src/agent/embedded/session-tool-result-guard.js +1 -1
  135. package/dist/src/agent/embedded/xopc-tools-bridge.d.ts +9 -0
  136. package/dist/src/agent/embedded/xopc-tools-bridge.js +71 -3
  137. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  138. package/dist/src/agent/goals/post-turn.js +5 -4
  139. package/dist/src/agent/goals/post-turn.js.map +1 -1
  140. package/dist/src/agent/mcp/mcp-transport.js +4 -1
  141. package/dist/src/agent/mcp/mcp-transport.js.map +1 -1
  142. package/dist/src/agent/memory/context/planner.d.ts +1 -0
  143. package/dist/src/agent/memory/context/planner.js +60 -14
  144. package/dist/src/agent/memory/context/planner.js.map +1 -1
  145. package/dist/src/agent/memory/context/types.d.ts +3 -1
  146. package/dist/src/agent/memory/lifecycle.d.ts +11 -0
  147. package/dist/src/agent/memory/lifecycle.js +50 -0
  148. package/dist/src/agent/memory/lifecycle.js.map +1 -0
  149. package/dist/src/agent/memory/source-origin.d.ts +3 -0
  150. package/dist/src/agent/memory/source-origin.js +19 -0
  151. package/dist/src/agent/memory/source-origin.js.map +1 -0
  152. package/dist/src/agent/memory/understanding/service.js +5 -0
  153. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  154. package/dist/src/agent/memory/user-context-coordinator.js +7 -2
  155. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  156. package/dist/src/agent/prompt/sections/behavior.d.ts +2 -0
  157. package/dist/src/agent/prompt/sections/behavior.js +30 -1
  158. package/dist/src/agent/prompt/sections/behavior.js.map +1 -1
  159. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  160. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  161. package/dist/src/agent/prompt/service-prompt-builder.js +8 -1
  162. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  163. package/dist/src/agent/prompt/system-prompt.d.ts +2 -0
  164. package/dist/src/agent/prompt/system-prompt.js +6 -3
  165. package/dist/src/agent/prompt/system-prompt.js.map +1 -1
  166. package/dist/src/agent/service/process-direct-streaming.js +22 -0
  167. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  168. package/dist/src/agent/service.d.ts +2 -0
  169. package/dist/src/agent/service.js +9 -3
  170. package/dist/src/agent/service.js.map +1 -1
  171. package/dist/src/agent/starter-agents.js +1 -1
  172. package/dist/src/agent/starter-agents.js.map +1 -1
  173. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  174. package/dist/src/agent/tool-manuals/xopc-use.js +1 -1
  175. package/dist/src/agent/tool-manuals/xopc-use.js.map +1 -1
  176. package/dist/src/agent/tools/composio-tool.d.ts +18 -5
  177. package/dist/src/agent/tools/composio-tool.js +252 -35
  178. package/dist/src/agent/tools/composio-tool.js.map +1 -1
  179. package/dist/src/agent/tools/factory.js +7 -3
  180. package/dist/src/agent/tools/factory.js.map +1 -1
  181. package/dist/src/agent/tools/index.d.ts +1 -1
  182. package/dist/src/agent/tools/index.js +2 -2
  183. package/dist/src/agent/tools/workflow-tool.d.ts +0 -1
  184. package/dist/src/agent/tools/workflow-tool.js +3 -16
  185. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  186. package/dist/src/agent/workflow/builtins/index.d.ts +2 -28
  187. package/dist/src/agent/workflow/builtins/index.js +226 -41
  188. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  189. package/dist/src/agent/workflow/catalog.d.ts +32 -34
  190. package/dist/src/agent/workflow/catalog.js +158 -154
  191. package/dist/src/agent/workflow/catalog.js.map +1 -1
  192. package/dist/src/agent/workflow/index.d.ts +4 -6
  193. package/dist/src/agent/workflow/index.js +2 -5
  194. package/dist/src/agent/workflow/snapshot.d.ts +2 -2
  195. package/dist/src/agent/workflow/snapshot.js +2 -2
  196. package/dist/src/agent/workflow/snapshot.js.map +1 -1
  197. package/dist/src/agent/workflow/structured-output-tool.d.ts +2 -2
  198. package/dist/src/agent/workflow/structured-output-tool.js +2 -2
  199. package/dist/src/agent/workflow/structured-output-tool.js.map +1 -1
  200. package/dist/src/agent/workflow/subagent-runner.js +1 -1
  201. package/dist/src/agent/workflow/types.d.ts +31 -26
  202. package/dist/src/agent-manifest/index.d.ts +1 -0
  203. package/dist/src/agent-manifest/index.js +3 -1
  204. package/dist/src/agent-manifest/index.js.map +1 -1
  205. package/dist/src/agent-manifest/preset-chain.d.ts +10 -0
  206. package/dist/src/agent-manifest/preset-chain.js +32 -0
  207. package/dist/src/agent-manifest/preset-chain.js.map +1 -0
  208. package/dist/src/agent-manifest/resolver.js +3 -10
  209. package/dist/src/agent-manifest/resolver.js.map +1 -1
  210. package/dist/src/agent-manifest/schema.d.ts +4 -4
  211. package/dist/src/automations/api/routes.js +13 -1
  212. package/dist/src/automations/api/routes.js.map +1 -1
  213. package/dist/src/automations/domain/validation.d.ts +14 -14
  214. package/dist/src/automations/draft/automation-draft-validator.d.ts +3 -3
  215. package/dist/src/browser/providers/browser-ext-install.d.ts +11 -1
  216. package/dist/src/browser/providers/browser-ext-install.js +39 -14
  217. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  218. package/dist/src/capabilities/store-connector.d.ts +0 -1
  219. package/dist/src/capabilities/store-connector.js +3 -5
  220. package/dist/src/capabilities/store-connector.js.map +1 -1
  221. package/dist/src/chat-commands/builtins/review.js +72 -73
  222. package/dist/src/chat-commands/builtins/review.js.map +1 -1
  223. package/dist/src/chat-commands/builtins/workflow.js +9 -54
  224. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  225. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  226. package/dist/src/cli/commands/extension-create.js +2 -2
  227. package/dist/src/cli/commands/extension-create.js.map +1 -1
  228. package/dist/src/cli/commands/extension-marketplace.js +42 -36
  229. package/dist/src/cli/commands/extension-marketplace.js.map +1 -1
  230. package/dist/src/cli/commands/extension-pack.d.ts +6 -0
  231. package/dist/src/cli/commands/extension-pack.js +3 -2
  232. package/dist/src/cli/commands/extension-pack.js.map +1 -1
  233. package/dist/src/commands/agents.config.d.ts +1 -0
  234. package/dist/src/commands/agents.config.js +1 -0
  235. package/dist/src/commands/agents.config.js.map +1 -1
  236. package/dist/src/config/schema.d.ts +6 -6
  237. package/dist/src/config/schema.js +6 -22
  238. package/dist/src/config/schema.js.map +1 -1
  239. package/dist/src/config/web-patch.d.ts +1 -1
  240. package/dist/src/connectors/approval.d.ts +2 -0
  241. package/dist/src/connectors/approval.js +33 -0
  242. package/dist/src/connectors/approval.js.map +1 -0
  243. package/dist/src/connectors/auth-provider-registry.d.ts +9 -0
  244. package/dist/src/connectors/auth-provider-registry.js +17 -0
  245. package/dist/src/connectors/auth-provider-registry.js.map +1 -0
  246. package/dist/src/connectors/builtin-catalog.js +55 -116
  247. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  248. package/dist/src/connectors/catalog.js +7 -2
  249. package/dist/src/connectors/catalog.js.map +1 -1
  250. package/dist/src/connectors/composio-catalog.d.ts +19 -0
  251. package/dist/src/connectors/composio-catalog.js +237 -0
  252. package/dist/src/connectors/composio-catalog.js.map +1 -0
  253. package/dist/src/connectors/composio-logo.d.ts +1 -0
  254. package/dist/src/connectors/composio-logo.js +51 -0
  255. package/dist/src/connectors/composio-logo.js.map +1 -0
  256. package/dist/src/connectors/composio-sessions.d.ts +116 -0
  257. package/dist/src/connectors/composio-sessions.js +296 -0
  258. package/dist/src/connectors/composio-sessions.js.map +1 -0
  259. package/dist/src/connectors/composio-triggers.d.ts +17 -0
  260. package/dist/src/connectors/composio-triggers.js +48 -5
  261. package/dist/src/connectors/composio-triggers.js.map +1 -1
  262. package/dist/src/connectors/composio.d.ts +31 -2
  263. package/dist/src/connectors/composio.js +374 -151
  264. package/dist/src/connectors/composio.js.map +1 -1
  265. package/dist/src/connectors/connector-memory-sync.d.ts +15 -0
  266. package/dist/src/connectors/connector-memory-sync.js +90 -0
  267. package/dist/src/connectors/connector-memory-sync.js.map +1 -0
  268. package/dist/src/connectors/install.js +35 -92
  269. package/dist/src/connectors/install.js.map +1 -1
  270. package/dist/src/connectors/instances.js +6 -2
  271. package/dist/src/connectors/instances.js.map +1 -1
  272. package/dist/src/connectors/integration-strategy.d.ts +3 -0
  273. package/dist/src/connectors/integration-strategy.js +29 -0
  274. package/dist/src/connectors/integration-strategy.js.map +1 -0
  275. package/dist/src/connectors/policy.d.ts +13 -0
  276. package/dist/src/connectors/policy.js +48 -0
  277. package/dist/src/connectors/policy.js.map +1 -0
  278. package/dist/src/connectors/providers.js +1 -1
  279. package/dist/src/connectors/runtime-adapter-registry.d.ts +25 -0
  280. package/dist/src/connectors/runtime-adapter-registry.js +154 -0
  281. package/dist/src/connectors/runtime-adapter-registry.js.map +1 -0
  282. package/dist/src/connectors/types.d.ts +113 -4
  283. package/dist/src/connectors/workflow-preflight.d.ts +20 -0
  284. package/dist/src/connectors/workflow-preflight.js +70 -0
  285. package/dist/src/connectors/workflow-preflight.js.map +1 -0
  286. package/dist/src/extensions/install-transaction.d.ts +16 -0
  287. package/dist/src/extensions/install-transaction.js +76 -0
  288. package/dist/src/extensions/install-transaction.js.map +1 -0
  289. package/dist/src/extensions/install.d.ts +2 -0
  290. package/dist/src/extensions/install.js +23 -1
  291. package/dist/src/extensions/install.js.map +1 -1
  292. package/dist/src/gateway/agents-admin.d.ts +2 -0
  293. package/dist/src/gateway/agents-admin.js +7 -0
  294. package/dist/src/gateway/agents-admin.js.map +1 -1
  295. package/dist/src/gateway/capability-presets-admin.d.ts +11 -0
  296. package/dist/src/gateway/capability-presets-admin.js +11 -4
  297. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  298. package/dist/src/gateway/chat-stream/mapper.js +17 -0
  299. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  300. package/dist/src/gateway/chat-stream/protocol.d.ts +18 -1
  301. package/dist/src/gateway/hono/lib/config-payload.d.ts +3 -3
  302. package/dist/src/gateway/hono/routes/agents.js +3 -0
  303. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  304. package/dist/src/gateway/hono/routes/capability-presets.js +19 -1
  305. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  306. package/dist/src/gateway/hono/routes/connectors.js +188 -25
  307. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  308. package/dist/src/gateway/hono/routes/goals.js +22 -3
  309. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  310. package/dist/src/gateway/hono/routes/home.d.ts +60 -1
  311. package/dist/src/gateway/hono/routes/home.js +244 -18
  312. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  313. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  314. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  315. package/dist/src/gateway/hono/routes/memory.js +14 -1
  316. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  317. package/dist/src/gateway/hono/routes/projects.js +103 -2
  318. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  319. package/dist/src/gateway/hono/routes/public-gateway.js +93 -0
  320. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  321. package/dist/src/gateway/hono/routes/workflows.js +137 -22
  322. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  323. package/dist/src/gateway/hono/routes/you.d.ts +23 -0
  324. package/dist/src/gateway/hono/routes/you.js +538 -0
  325. package/dist/src/gateway/hono/routes/you.js.map +1 -0
  326. package/dist/src/gateway/hono/sse.d.ts +2 -1
  327. package/dist/src/gateway/hono/sse.js +2 -1
  328. package/dist/src/gateway/hono/sse.js.map +1 -1
  329. package/dist/src/gateway/service/marketplace-service.d.ts +13 -1
  330. package/dist/src/gateway/service/marketplace-service.js +96 -40
  331. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  332. package/dist/src/gateway/service.d.ts +2 -0
  333. package/dist/src/gateway/service.js +7 -1
  334. package/dist/src/gateway/service.js.map +1 -1
  335. package/dist/src/goals/goal-service.d.ts +7 -5
  336. package/dist/src/goals/goal-service.js +25 -13
  337. package/dist/src/goals/goal-service.js.map +1 -1
  338. package/dist/src/goals/goal-store.js +46 -7
  339. package/dist/src/goals/goal-store.js.map +1 -1
  340. package/dist/src/goals/types.d.ts +24 -0
  341. package/dist/src/storage/sqlite/connector-repository.d.ts +49 -0
  342. package/dist/src/storage/sqlite/connector-repository.js +385 -0
  343. package/dist/src/storage/sqlite/connector-repository.js.map +1 -0
  344. package/dist/src/storage/sqlite/index.d.ts +3 -0
  345. package/dist/src/storage/sqlite/index.js +4 -1
  346. package/dist/src/storage/sqlite/migrations/030_connectors.sql +94 -0
  347. package/dist/src/storage/sqlite/migrations/031_connector_approvals.sql +24 -0
  348. package/dist/src/storage/sqlite/migrations/032_connector_webhook_deliveries.sql +15 -0
  349. package/dist/src/storage/sqlite/migrations/033_user_trust_policies.sql +6 -0
  350. package/dist/src/storage/sqlite/migrations/034_allow_global_auto_trust.sql +14 -0
  351. package/dist/src/storage/sqlite/migrations/035_user_profile_prompt_state.sql +7 -0
  352. package/dist/src/storage/sqlite/migrations/036_goal_outcome_metric.sql +12 -0
  353. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  354. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  355. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  356. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  357. package/dist/src/storage/sqlite/schema.js +1 -1
  358. package/dist/src/storage/sqlite/user-profile-setup-repository.d.ts +3 -0
  359. package/dist/src/storage/sqlite/user-profile-setup-repository.js +34 -0
  360. package/dist/src/storage/sqlite/user-profile-setup-repository.js.map +1 -0
  361. package/dist/src/storage/sqlite/user-trust-repository.d.ts +3 -0
  362. package/dist/src/storage/sqlite/user-trust-repository.js +34 -0
  363. package/dist/src/storage/sqlite/user-trust-repository.js.map +1 -0
  364. package/dist/src/tui/components/assistant-message.js +15 -0
  365. package/dist/src/tui/components/assistant-message.js.map +1 -1
  366. package/dist/src/tui/tui-agent-events.js +85 -1
  367. package/dist/src/tui/tui-agent-events.js.map +1 -1
  368. package/dist/src/tui/tui-command-formatters.js +7 -7
  369. package/dist/src/tui/tui-command-formatters.js.map +1 -1
  370. package/dist/src/tui/tui-commands.js +1 -1
  371. package/dist/src/tui/tui-startup-resources.js +1 -1
  372. package/dist/src/user-context/import.d.ts +12 -0
  373. package/dist/src/user-context/import.js +48 -0
  374. package/dist/src/user-context/import.js.map +1 -0
  375. package/dist/src/user-context/profile.d.ts +37 -0
  376. package/dist/src/user-context/profile.js +165 -0
  377. package/dist/src/user-context/profile.js.map +1 -0
  378. package/dist/src/user-context/projection.d.ts +54 -0
  379. package/dist/src/user-context/projection.js +121 -0
  380. package/dist/src/user-context/projection.js.map +1 -0
  381. package/dist/src/user-context/source-recommendations.d.ts +13 -0
  382. package/dist/src/user-context/source-recommendations.js +86 -0
  383. package/dist/src/user-context/source-recommendations.js.map +1 -0
  384. package/dist/src/user-context/trust-policy.d.ts +11 -0
  385. package/dist/src/user-context/trust-policy.js +31 -0
  386. package/dist/src/user-context/trust-policy.js.map +1 -0
  387. package/dist/src/workflows/authoring/index.d.ts +1 -0
  388. package/dist/src/workflows/authoring/index.js +2 -0
  389. package/dist/src/workflows/authoring/workflow-draft-store.d.ts +33 -0
  390. package/dist/src/workflows/authoring/workflow-draft-store.js +74 -0
  391. package/dist/src/workflows/authoring/workflow-draft-store.js.map +1 -0
  392. package/dist/src/workflows/domain/definition-utils.d.ts +6 -4
  393. package/dist/src/workflows/domain/definition-utils.js +28 -26
  394. package/dist/src/workflows/domain/definition-utils.js.map +1 -1
  395. package/dist/src/workflows/domain/definition.d.ts +79 -6
  396. package/dist/src/workflows/domain/event.d.ts +18 -2
  397. package/dist/src/workflows/domain/index.js +3 -3
  398. package/dist/src/workflows/domain/run.d.ts +16 -2
  399. package/dist/src/workflows/domain/run.js.map +1 -1
  400. package/dist/src/workflows/domain/validation.d.ts +9 -5
  401. package/dist/src/workflows/domain/validation.js +183 -40
  402. package/dist/src/workflows/domain/validation.js.map +1 -1
  403. package/dist/src/workflows/draft/workflow-draft-prompt.d.ts +2 -3
  404. package/dist/src/workflows/draft/workflow-draft-prompt.js +31 -73
  405. package/dist/src/workflows/draft/workflow-draft-prompt.js.map +1 -1
  406. package/dist/src/workflows/draft/workflow-draft-service.js +4 -8
  407. package/dist/src/workflows/draft/workflow-draft-service.js.map +1 -1
  408. package/dist/src/workflows/draft/workflow-draft-validator.js +29 -37
  409. package/dist/src/workflows/draft/workflow-draft-validator.js.map +1 -1
  410. package/dist/src/workflows/draft/workflow-draft.types.d.ts +4 -4
  411. package/dist/src/workflows/engine/projector.js +43 -1
  412. package/dist/src/workflows/engine/projector.js.map +1 -1
  413. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -3
  414. package/dist/src/workflows/engine/workflow-engine.js +24 -4
  415. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  416. package/dist/src/workflows/index.js +4 -7
  417. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js +1 -9
  418. package/dist/src/workflows/registry/catalog-workflow-definition-registry.js.map +1 -1
  419. package/dist/src/workflows/runtime/graph-workflow-runtime.d.ts +10 -0
  420. package/dist/src/workflows/runtime/graph-workflow-runtime.js +295 -0
  421. package/dist/src/workflows/runtime/graph-workflow-runtime.js.map +1 -0
  422. package/dist/src/workflows/runtime/index.d.ts +1 -2
  423. package/dist/src/workflows/runtime/index.js +2 -5
  424. package/dist/src/workflows/runtime/workflow-runtime-port.d.ts +5 -8
  425. package/dist/src/workflows/service/workflow-run-service.js +15 -1
  426. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  427. package/dist/src/workflows/service/workflow-run-service.types.d.ts +2 -1
  428. package/package.json +4 -3
  429. package/dist/gateway/static/root/assets/agents-CyvCIHnB.js +0 -2
  430. package/dist/gateway/static/root/assets/apps-page-DK_Vx6nl.js +0 -1
  431. package/dist/gateway/static/root/assets/automation-suggestion-card-B1LV3YYv.js +0 -1
  432. package/dist/gateway/static/root/assets/automations-page-fzrovqhv.js +0 -4
  433. package/dist/gateway/static/root/assets/block-editor-Dhj5f4Bx.js +0 -184
  434. package/dist/gateway/static/root/assets/browser-settings-page-BDn-n-UB.js +0 -8
  435. package/dist/gateway/static/root/assets/capability-presets-settings-panel-Co5ipo_Q.js +0 -1
  436. package/dist/gateway/static/root/assets/channels-settings-BWlpaxg9.js +0 -1
  437. package/dist/gateway/static/root/assets/channels-status-swr-D_jkIZLV.js +0 -1
  438. package/dist/gateway/static/root/assets/connectors-page-BcekbW4q.js +0 -2
  439. package/dist/gateway/static/root/assets/desktop-pet-settings-BJCUuL8Y.js +0 -1
  440. package/dist/gateway/static/root/assets/dreaming-settings-BN1Z2mIo.js +0 -3
  441. package/dist/gateway/static/root/assets/extension-page-B-1KxvVy.js +0 -1
  442. package/dist/gateway/static/root/assets/extension-settings-page-BF9NACI3.js +0 -1
  443. package/dist/gateway/static/root/assets/gateway-settings-DN9sNREz.js +0 -1
  444. package/dist/gateway/static/root/assets/goal-create-dialog-BpoQW8cD.js +0 -1
  445. package/dist/gateway/static/root/assets/goal-detail-page-CBRSPd0b.js +0 -4
  446. package/dist/gateway/static/root/assets/goals-page-BCcBi407.js +0 -2
  447. package/dist/gateway/static/root/assets/goals-settings-pkTXzXkh.js +0 -1
  448. package/dist/gateway/static/root/assets/heartbeat-settings-ezsufgLQ.js +0 -1
  449. package/dist/gateway/static/root/assets/index-B8s8Pq5U.css +0 -1
  450. package/dist/gateway/static/root/assets/index-DcUaXYeb.js +0 -262
  451. package/dist/gateway/static/root/assets/logs-page-DQtTRXtj.js +0 -7
  452. package/dist/gateway/static/root/assets/messages-BXNELNBa.js +0 -3
  453. package/dist/gateway/static/root/assets/models-hub-panel-BP2M9n6Q.js +0 -2
  454. package/dist/gateway/static/root/assets/notes-page-CspveYaO.js +0 -1
  455. package/dist/gateway/static/root/assets/notes-workbench-BHwzJ0OC.js +0 -2
  456. package/dist/gateway/static/root/assets/project-detail-page-Dy3rsobs.js +0 -1
  457. package/dist/gateway/static/root/assets/projects-page-CWKpPE0L.js +0 -1
  458. package/dist/gateway/static/root/assets/remote-access-hub-CqNRyXEo.js +0 -1
  459. package/dist/gateway/static/root/assets/sessions-page-MEME7ivF.js +0 -1
  460. package/dist/gateway/static/root/assets/settings-advanced-gate-JVd0qaSF.js +0 -1
  461. package/dist/gateway/static/root/assets/settings-page-DYEbB1EV.js +0 -1
  462. package/dist/gateway/static/root/assets/setup-status-panel-dWN8BJ3z.js +0 -1
  463. package/dist/gateway/static/root/assets/share-preview-page-D8foINzP.js +0 -2
  464. package/dist/gateway/static/root/assets/shares-settings-Tgbv1s7G.js +0 -1
  465. package/dist/gateway/static/root/assets/skill-reload-api-D_YK0b_Z.js +0 -1
  466. package/dist/gateway/static/root/assets/skills-page-DGytfoZK.js +0 -2
  467. package/dist/gateway/static/root/assets/toast-z0toXu32.js +0 -1
  468. package/dist/gateway/static/root/assets/user-profile-settings-panel-8YtygcJp.js +0 -1
  469. package/dist/gateway/static/root/assets/voice-api-key-field-BVH71EFf.js +0 -1
  470. package/dist/gateway/static/root/assets/work-item-detail-page-JeTE7XNM.js +0 -1
  471. package/dist/gateway/static/root/assets/workflow-start-dialog-_u8Uc1ze.js +0 -1
  472. package/dist/gateway/static/root/assets/workflows-page-ixgk_y1l.js +0 -18
  473. package/dist/src/agent/workflow/builtins/audit-repo.d.ts +0 -13
  474. package/dist/src/agent/workflow/builtins/audit-repo.js +0 -183
  475. package/dist/src/agent/workflow/builtins/audit-repo.js.map +0 -1
  476. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +0 -12
  477. package/dist/src/agent/workflow/builtins/client-proposal.js +0 -164
  478. package/dist/src/agent/workflow/builtins/client-proposal.js.map +0 -1
  479. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +0 -12
  480. package/dist/src/agent/workflow/builtins/competitor-scan.js +0 -164
  481. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +0 -1
  482. package/dist/src/agent/workflow/builtins/content-draft.d.ts +0 -13
  483. package/dist/src/agent/workflow/builtins/content-draft.js +0 -159
  484. package/dist/src/agent/workflow/builtins/content-draft.js.map +0 -1
  485. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +0 -11
  486. package/dist/src/agent/workflow/builtins/content-repurpose.js +0 -146
  487. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +0 -1
  488. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +0 -13
  489. package/dist/src/agent/workflow/builtins/debug-incident.js +0 -177
  490. package/dist/src/agent/workflow/builtins/debug-incident.js.map +0 -1
  491. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +0 -13
  492. package/dist/src/agent/workflow/builtins/decision-compare.js +0 -187
  493. package/dist/src/agent/workflow/builtins/decision-compare.js.map +0 -1
  494. package/dist/src/agent/workflow/builtins/implementation-plan.d.ts +0 -12
  495. package/dist/src/agent/workflow/builtins/implementation-plan.js +0 -185
  496. package/dist/src/agent/workflow/builtins/implementation-plan.js.map +0 -1
  497. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +0 -11
  498. package/dist/src/agent/workflow/builtins/inbox-triage.js +0 -158
  499. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +0 -1
  500. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +0 -12
  501. package/dist/src/agent/workflow/builtins/meeting-prep.js +0 -152
  502. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +0 -1
  503. package/dist/src/agent/workflow/builtins/multi-perspective-review.d.ts +0 -14
  504. package/dist/src/agent/workflow/builtins/multi-perspective-review.js +0 -171
  505. package/dist/src/agent/workflow/builtins/multi-perspective-review.js.map +0 -1
  506. package/dist/src/agent/workflow/builtins/offer-design.d.ts +0 -12
  507. package/dist/src/agent/workflow/builtins/offer-design.js +0 -170
  508. package/dist/src/agent/workflow/builtins/offer-design.js.map +0 -1
  509. package/dist/src/agent/workflow/builtins/pr-review.d.ts +0 -12
  510. package/dist/src/agent/workflow/builtins/pr-review.js +0 -178
  511. package/dist/src/agent/workflow/builtins/pr-review.js.map +0 -1
  512. package/dist/src/agent/workflow/builtins/release-check.d.ts +0 -11
  513. package/dist/src/agent/workflow/builtins/release-check.js +0 -174
  514. package/dist/src/agent/workflow/builtins/release-check.js.map +0 -1
  515. package/dist/src/agent/workflow/builtins/research.d.ts +0 -13
  516. package/dist/src/agent/workflow/builtins/research.js +0 -188
  517. package/dist/src/agent/workflow/builtins/research.js.map +0 -1
  518. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +0 -12
  519. package/dist/src/agent/workflow/builtins/weekly-review.js +0 -139
  520. package/dist/src/agent/workflow/builtins/weekly-review.js.map +0 -1
  521. package/dist/src/agent/workflow/last-run-memory.d.ts +0 -42
  522. package/dist/src/agent/workflow/last-run-memory.js +0 -60
  523. package/dist/src/agent/workflow/last-run-memory.js.map +0 -1
  524. package/dist/src/agent/workflow/lint.d.ts +0 -38
  525. package/dist/src/agent/workflow/lint.js +0 -74
  526. package/dist/src/agent/workflow/lint.js.map +0 -1
  527. package/dist/src/agent/workflow/meta-locale.d.ts +0 -12
  528. package/dist/src/agent/workflow/meta-locale.js +0 -62
  529. package/dist/src/agent/workflow/meta-locale.js.map +0 -1
  530. package/dist/src/agent/workflow/parser.d.ts +0 -20
  531. package/dist/src/agent/workflow/parser.js +0 -152
  532. package/dist/src/agent/workflow/parser.js.map +0 -1
  533. package/dist/src/agent/workflow/runtime.d.ts +0 -34
  534. package/dist/src/agent/workflow/runtime.js +0 -402
  535. package/dist/src/agent/workflow/runtime.js.map +0 -1
  536. package/dist/src/connectors/oauth.d.ts +0 -22
  537. package/dist/src/connectors/oauth.js +0 -99
  538. package/dist/src/connectors/oauth.js.map +0 -1
  539. package/dist/src/workflows/runtime/script-runtime.d.ts +0 -3
  540. package/dist/src/workflows/runtime/script-runtime.js +0 -3
  541. package/dist/src/workflows/runtime/script-workflow-runtime.d.ts +0 -5
  542. package/dist/src/workflows/runtime/script-workflow-runtime.js +0 -15
  543. package/dist/src/workflows/runtime/script-workflow-runtime.js.map +0 -1
@@ -102,8 +102,9 @@ async function handlePersistentGoalPostTurn(opts) {
102
102
  uiLocale: resolveGoalUiLocale(state)
103
103
  });
104
104
  const completionReadiness = goalService.getCompletionReadiness(goal.id);
105
- if (decision.verdict === "done" && completionReadiness && !completionReadiness.ready && decision.newState) {
106
- const reason = `Completion evidence still needed: ${completionReadiness.missingEvidence.join("; ")}`;
105
+ const executionGaps = completionReadiness ? [...completionReadiness.missingEvidence, ...completionReadiness.pendingOutcome] : [];
106
+ if (decision.verdict === "done" && executionGaps.length > 0 && decision.newState) {
107
+ const reason = `Completion evidence or outcome still needed: ${executionGaps.join("; ")}`;
107
108
  decision = {
108
109
  ...decision,
109
110
  newState: {
@@ -113,11 +114,11 @@ async function handlePersistentGoalPostTurn(opts) {
113
114
  lastReason: reason
114
115
  },
115
116
  shouldContinue: true,
116
- continuationPrompt: `Before declaring the goal complete, collect this evidence:\n${completionReadiness.missingEvidence.map((item) => `- ${item}`).join("\n")}`,
117
+ continuationPrompt: `Before declaring the goal complete, address these gaps:\n${executionGaps.map((item) => `- ${item}`).join("\n")}`,
117
118
  verdict: "continue",
118
119
  reason,
119
120
  message: reason,
120
- missingEvidence: completionReadiness.missingEvidence
121
+ missingEvidence: executionGaps
121
122
  };
122
123
  }
123
124
  if (decision.newState) {
@@ -1 +1 @@
1
- {"version":3,"file":"post-turn.js","names":[],"sources":["../../../../src/agent/goals/post-turn.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config, GoalsConfig } from '../../config/schema.js';\nimport { getAgentDefaultModelRef } from '../../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { GoalService } from '../../goals/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { evaluateAfterTurnHermesLike } from './evaluate-turn.js';\nimport { resolveGoalUiLocale } from './goal-locale.js';\nimport type { PersistentGoalApis } from './persistent-goal-apis.js';\nimport type { PersistentGoalState } from './state.js';\n\nconst log = createLogger('PersistentGoal');\nconst goalService = new GoalService();\n\nfunction buildHistoryExcerpt(messages: AgentMessage[], maxChars: number): string {\n if (maxChars <= 0) return '';\n try {\n const raw = JSON.stringify(messages);\n if (raw.length <= maxChars) return raw;\n return raw.slice(-maxChars);\n } catch {\n return '';\n }\n}\n\nfunction buildGoalContextText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n const lines = [`Title: ${goal.contract?.objective || goal.title}`];\n if (goal.contract?.scopeBoundary) {\n lines.push(`Scope boundary:\\n${goal.contract.scopeBoundary}`);\n }\n if (goal.contract?.evidencePlan.length) {\n lines.push(`Expected completion evidence:\\n${goal.contract.evidencePlan.map((item) => `- ${item}`).join('\\n')}`);\n }\n if (goal.contextMessage?.text.trim()) {\n lines.push(`Context:\\n${goal.contextMessage.text.trim()}`);\n }\n if (goal.contextMessage?.attachments.length) {\n lines.push(\n [\n 'Attachments:',\n ...goal.contextMessage.attachments.map((attachment) =>\n `- ${attachment.name} (${attachment.mimeType}, ${attachment.size} bytes) ${attachment.uri}`,\n ),\n ].join('\\n'),\n );\n }\n return lines.join('\\n\\n');\n}\n\nfunction resolveJudgeModelRef(\n config: Config | undefined,\n sessionKey: string,\n storedJudge?: string,\n runtimeSessionModelRef?: string,\n): string | undefined {\n const fromCfg = config?.goals?.judgeModelRef?.trim();\n if (fromCfg) return fromCfg;\n if (storedJudge?.trim()) return storedJudge.trim();\n if (config) {\n const profile = resolveEffectiveAgentProfileForSession(config, sessionKey);\n if (profile.primaryModelRef?.trim()) return profile.primaryModelRef.trim();\n }\n if (runtimeSessionModelRef?.trim()) return runtimeSessionModelRef.trim();\n if (config) return getAgentDefaultModelRef(config);\n return undefined;\n}\n\nexport function shouldRunInitialChecklistDecomposition(input: {\n checklistLength: number;\n turnsUsed: number;\n checklistDecomposePolicy?: GoalsConfig['checklistDecomposePolicy'];\n}): boolean {\n if (input.checklistLength === 0) return true;\n return input.checklistDecomposePolicy === 'supplement_existing' && input.turnsUsed === 0;\n}\n\nasync function appendAssistantLine(apis: PersistentGoalApis, sessionKey: string, text: string): Promise<void> {\n await apis.appendAssistantReceipt(sessionKey, text);\n}\n\nexport async function handlePersistentGoalPostTurn(opts: {\n apis: PersistentGoalApis;\n sessionKey: string;\n assistantPlainText: string;\n aborted: boolean;\n streamError?: string;\n skipPersistentGoalPostTurn: boolean;\n config: Config | undefined;\n /** Active session model (overrides, per-agent defaults) when goals/global defaults are unset. */\n runtimeSessionModelRef?: string;\n signal?: AbortSignal;\n /** Hermes-style: verdict line also sent as a normal outbound message (non-webchat). */\n publishVerdictToChannel?: (text: string) => Promise<void>;\n onGoalStatusUpdated?: (payload: {\n goalId: string;\n sessionKey: string;\n previousStatus: string;\n status: string;\n goal: import('../../goals/types.js').GoalWithDetails;\n }) => void;\n}): Promise<void> {\n const {\n apis,\n sessionKey,\n assistantPlainText,\n aborted,\n streamError,\n skipPersistentGoalPostTurn,\n config,\n runtimeSessionModelRef,\n signal,\n publishVerdictToChannel,\n onGoalStatusUpdated,\n } = opts;\n\n if (skipPersistentGoalPostTurn) return;\n if (aborted || streamError) return;\n\n const meta = await apis.getSessionMetadata(sessionKey);\n if (!meta) return;\n\n const goal = goalService.getActiveForSession(sessionKey);\n if (!goal || goal.status !== 'active') return;\n\n const goalsCfg = config?.goals;\n const shouldDecomposeChecklist = shouldRunInitialChecklistDecomposition({\n checklistLength: goal.checklist.length,\n turnsUsed: goal.turnsUsed,\n checklistDecomposePolicy: goalsCfg?.checklistDecomposePolicy,\n });\n const state: PersistentGoalState = {\n goal: buildGoalContextText(goal),\n status: 'active',\n turnsUsed: goal.turnsUsed,\n maxTurns: goal.maxTurns,\n createdAt: goal.createdAt,\n lastTurnAt: goal.updatedAt,\n lastReason: goal.blockedReason,\n judgeModelRef: goal.judgeModelRef,\n decomposed: shouldDecomposeChecklist ? undefined : true,\n uiLocale: goal.uiLocale,\n checklist: goal.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidence: it.evidenceSummary,\n })),\n };\n\n const judgeRef = resolveJudgeModelRef(config, sessionKey, state.judgeModelRef, runtimeSessionModelRef);\n if (!judgeRef) {\n log.warn({ sessionKey }, 'Persistent goal: no judge model ref; skipping post-turn');\n return;\n }\n\n const historyCap = goalsCfg?.checklistHistoryChars ?? 24_000;\n let historyExcerpt = '';\n try {\n const msgs = await apis.loadMessages(sessionKey);\n historyExcerpt = buildHistoryExcerpt(msgs, historyCap);\n } catch (err) {\n log.debug(\n { err, sessionKey },\n `Persistent goal: could not load messages for judge context: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n let decision = await evaluateAfterTurnHermesLike(state, assistantPlainText, judgeRef, signal, {\n goalsSlice: goalsCfg,\n historyExcerpt,\n goalContextExcerpt: buildGoalContextText(goal),\n uiLocale: resolveGoalUiLocale(state),\n });\n\n const completionReadiness = goalService.getCompletionReadiness(goal.id);\n if (decision.verdict === 'done' && completionReadiness && !completionReadiness.ready && decision.newState) {\n const reason = `Completion evidence still needed: ${completionReadiness.missingEvidence.join('; ')}`;\n decision = {\n ...decision,\n newState: {\n ...decision.newState,\n status: 'active',\n lastVerdict: 'continue',\n lastReason: reason,\n },\n shouldContinue: true,\n continuationPrompt: `Before declaring the goal complete, collect this evidence:\\n${completionReadiness.missingEvidence.map((item) => `- ${item}`).join('\\n')}`,\n verdict: 'continue',\n reason,\n message: reason,\n missingEvidence: completionReadiness.missingEvidence,\n };\n }\n\n if (decision.newState) {\n const ns = decision.newState;\n const completedChecklistItemIds = decision.completedChecklistItemIndexes\n ?.map((index) => goal.checklist[index]?.id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n try {\n const updatedGoal = goalService.syncPostTurnState({\n goalId: goal.id,\n sessionKey,\n source: 'chat',\n status: ns.status === 'done'\n ? 'done'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : ns.status === 'paused'\n ? 'paused'\n : 'active',\n turnsUsed: ns.turnsUsed,\n maxTurns: ns.maxTurns,\n reason: ns.pausedReason ?? decision.reason,\n nextAction: decision.continuationPrompt ?? undefined,\n assistantPreview: assistantPlainText,\n verdict: decision.verdict === 'done'\n ? 'done'\n : decision.verdict === 'decompose'\n ? 'decompose'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : 'continue',\n confidence: decision.confidence,\n missingEvidence: decision.missingEvidence,\n userQuestion: decision.userQuestion,\n completedChecklistItemIds,\n checklist: ns.checklist?.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidenceSummary: it.evidence,\n })),\n });\n if (updatedGoal && updatedGoal.status !== goal.status) {\n onGoalStatusUpdated?.({\n goalId: goal.id,\n sessionKey,\n previousStatus: goal.status,\n status: updatedGoal.status,\n goal: updatedGoal,\n });\n }\n } catch (err) {\n log.warn(\n { err, sessionKey, goalId: goal.id },\n `Persistent goal: SQLite goal update failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n if (decision.message) {\n if (publishVerdictToChannel) {\n try {\n await publishVerdictToChannel(decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: channel verdict send failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n try {\n await appendAssistantLine(apis, sessionKey, decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: failed to append status message: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n if (decision.shouldContinue && decision.continuationPrompt) {\n apis.scheduleContinuation(sessionKey, decision.continuationPrompt);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"post-turn.js","names":[],"sources":["../../../../src/agent/goals/post-turn.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport type { Config, GoalsConfig } from '../../config/schema.js';\nimport { getAgentDefaultModelRef } from '../../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport { GoalService } from '../../goals/index.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport { evaluateAfterTurnHermesLike } from './evaluate-turn.js';\nimport { resolveGoalUiLocale } from './goal-locale.js';\nimport type { PersistentGoalApis } from './persistent-goal-apis.js';\nimport type { PersistentGoalState } from './state.js';\n\nconst log = createLogger('PersistentGoal');\nconst goalService = new GoalService();\n\nfunction buildHistoryExcerpt(messages: AgentMessage[], maxChars: number): string {\n if (maxChars <= 0) return '';\n try {\n const raw = JSON.stringify(messages);\n if (raw.length <= maxChars) return raw;\n return raw.slice(-maxChars);\n } catch {\n return '';\n }\n}\n\nfunction buildGoalContextText(goal: NonNullable<ReturnType<GoalService['get']>>): string {\n const lines = [`Title: ${goal.contract?.objective || goal.title}`];\n if (goal.contract?.scopeBoundary) {\n lines.push(`Scope boundary:\\n${goal.contract.scopeBoundary}`);\n }\n if (goal.contract?.evidencePlan.length) {\n lines.push(`Expected completion evidence:\\n${goal.contract.evidencePlan.map((item) => `- ${item}`).join('\\n')}`);\n }\n if (goal.contextMessage?.text.trim()) {\n lines.push(`Context:\\n${goal.contextMessage.text.trim()}`);\n }\n if (goal.contextMessage?.attachments.length) {\n lines.push(\n [\n 'Attachments:',\n ...goal.contextMessage.attachments.map((attachment) =>\n `- ${attachment.name} (${attachment.mimeType}, ${attachment.size} bytes) ${attachment.uri}`,\n ),\n ].join('\\n'),\n );\n }\n return lines.join('\\n\\n');\n}\n\nfunction resolveJudgeModelRef(\n config: Config | undefined,\n sessionKey: string,\n storedJudge?: string,\n runtimeSessionModelRef?: string,\n): string | undefined {\n const fromCfg = config?.goals?.judgeModelRef?.trim();\n if (fromCfg) return fromCfg;\n if (storedJudge?.trim()) return storedJudge.trim();\n if (config) {\n const profile = resolveEffectiveAgentProfileForSession(config, sessionKey);\n if (profile.primaryModelRef?.trim()) return profile.primaryModelRef.trim();\n }\n if (runtimeSessionModelRef?.trim()) return runtimeSessionModelRef.trim();\n if (config) return getAgentDefaultModelRef(config);\n return undefined;\n}\n\nexport function shouldRunInitialChecklistDecomposition(input: {\n checklistLength: number;\n turnsUsed: number;\n checklistDecomposePolicy?: GoalsConfig['checklistDecomposePolicy'];\n}): boolean {\n if (input.checklistLength === 0) return true;\n return input.checklistDecomposePolicy === 'supplement_existing' && input.turnsUsed === 0;\n}\n\nasync function appendAssistantLine(apis: PersistentGoalApis, sessionKey: string, text: string): Promise<void> {\n await apis.appendAssistantReceipt(sessionKey, text);\n}\n\nexport async function handlePersistentGoalPostTurn(opts: {\n apis: PersistentGoalApis;\n sessionKey: string;\n assistantPlainText: string;\n aborted: boolean;\n streamError?: string;\n skipPersistentGoalPostTurn: boolean;\n config: Config | undefined;\n /** Active session model (overrides, per-agent defaults) when goals/global defaults are unset. */\n runtimeSessionModelRef?: string;\n signal?: AbortSignal;\n /** Hermes-style: verdict line also sent as a normal outbound message (non-webchat). */\n publishVerdictToChannel?: (text: string) => Promise<void>;\n onGoalStatusUpdated?: (payload: {\n goalId: string;\n sessionKey: string;\n previousStatus: string;\n status: string;\n goal: import('../../goals/types.js').GoalWithDetails;\n }) => void;\n}): Promise<void> {\n const {\n apis,\n sessionKey,\n assistantPlainText,\n aborted,\n streamError,\n skipPersistentGoalPostTurn,\n config,\n runtimeSessionModelRef,\n signal,\n publishVerdictToChannel,\n onGoalStatusUpdated,\n } = opts;\n\n if (skipPersistentGoalPostTurn) return;\n if (aborted || streamError) return;\n\n const meta = await apis.getSessionMetadata(sessionKey);\n if (!meta) return;\n\n const goal = goalService.getActiveForSession(sessionKey);\n if (!goal || goal.status !== 'active') return;\n\n const goalsCfg = config?.goals;\n const shouldDecomposeChecklist = shouldRunInitialChecklistDecomposition({\n checklistLength: goal.checklist.length,\n turnsUsed: goal.turnsUsed,\n checklistDecomposePolicy: goalsCfg?.checklistDecomposePolicy,\n });\n const state: PersistentGoalState = {\n goal: buildGoalContextText(goal),\n status: 'active',\n turnsUsed: goal.turnsUsed,\n maxTurns: goal.maxTurns,\n createdAt: goal.createdAt,\n lastTurnAt: goal.updatedAt,\n lastReason: goal.blockedReason,\n judgeModelRef: goal.judgeModelRef,\n decomposed: shouldDecomposeChecklist ? undefined : true,\n uiLocale: goal.uiLocale,\n checklist: goal.checklist.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidence: it.evidenceSummary,\n })),\n };\n\n const judgeRef = resolveJudgeModelRef(config, sessionKey, state.judgeModelRef, runtimeSessionModelRef);\n if (!judgeRef) {\n log.warn({ sessionKey }, 'Persistent goal: no judge model ref; skipping post-turn');\n return;\n }\n\n const historyCap = goalsCfg?.checklistHistoryChars ?? 24_000;\n let historyExcerpt = '';\n try {\n const msgs = await apis.loadMessages(sessionKey);\n historyExcerpt = buildHistoryExcerpt(msgs, historyCap);\n } catch (err) {\n log.debug(\n { err, sessionKey },\n `Persistent goal: could not load messages for judge context: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n let decision = await evaluateAfterTurnHermesLike(state, assistantPlainText, judgeRef, signal, {\n goalsSlice: goalsCfg,\n historyExcerpt,\n goalContextExcerpt: buildGoalContextText(goal),\n uiLocale: resolveGoalUiLocale(state),\n });\n\n const completionReadiness = goalService.getCompletionReadiness(goal.id);\n const executionGaps = completionReadiness\n ? [...completionReadiness.missingEvidence, ...completionReadiness.pendingOutcome]\n : [];\n if (decision.verdict === 'done' && executionGaps.length > 0 && decision.newState) {\n const reason = `Completion evidence or outcome still needed: ${executionGaps.join('; ')}`;\n decision = {\n ...decision,\n newState: {\n ...decision.newState,\n status: 'active',\n lastVerdict: 'continue',\n lastReason: reason,\n },\n shouldContinue: true,\n continuationPrompt: `Before declaring the goal complete, address these gaps:\\n${executionGaps.map((item) => `- ${item}`).join('\\n')}`,\n verdict: 'continue',\n reason,\n message: reason,\n missingEvidence: executionGaps,\n };\n }\n\n if (decision.newState) {\n const ns = decision.newState;\n const completedChecklistItemIds = decision.completedChecklistItemIndexes\n ?.map((index) => goal.checklist[index]?.id)\n .filter((id): id is string => typeof id === 'string' && id.length > 0);\n try {\n const updatedGoal = goalService.syncPostTurnState({\n goalId: goal.id,\n sessionKey,\n source: 'chat',\n status: ns.status === 'done'\n ? 'done'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : ns.status === 'paused'\n ? 'paused'\n : 'active',\n turnsUsed: ns.turnsUsed,\n maxTurns: ns.maxTurns,\n reason: ns.pausedReason ?? decision.reason,\n nextAction: decision.continuationPrompt ?? undefined,\n assistantPreview: assistantPlainText,\n verdict: decision.verdict === 'done'\n ? 'done'\n : decision.verdict === 'decompose'\n ? 'decompose'\n : decision.verdict === 'blocked'\n ? 'blocked'\n : decision.verdict === 'needs_input'\n ? 'needs_input'\n : 'continue',\n confidence: decision.confidence,\n missingEvidence: decision.missingEvidence,\n userQuestion: decision.userQuestion,\n completedChecklistItemIds,\n checklist: ns.checklist?.map((it) => ({\n text: it.text,\n status: it.status,\n addedBy: it.addedBy,\n addedAt: it.addedAt,\n completedAt: it.completedAt,\n evidenceSummary: it.evidence,\n })),\n });\n if (updatedGoal && updatedGoal.status !== goal.status) {\n onGoalStatusUpdated?.({\n goalId: goal.id,\n sessionKey,\n previousStatus: goal.status,\n status: updatedGoal.status,\n goal: updatedGoal,\n });\n }\n } catch (err) {\n log.warn(\n { err, sessionKey, goalId: goal.id },\n `Persistent goal: SQLite goal update failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n if (decision.message) {\n if (publishVerdictToChannel) {\n try {\n await publishVerdictToChannel(decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: channel verdict send failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n } else {\n try {\n await appendAssistantLine(apis, sessionKey, decision.message);\n } catch (err) {\n log.warn(\n { err, sessionKey },\n `Persistent goal: failed to append status message: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n if (decision.shouldContinue && decision.continuationPrompt) {\n apis.scheduleContinuation(sessionKey, decision.continuationPrompt);\n }\n}\n"],"mappings":"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"}
@@ -64,7 +64,10 @@ function resolveMcpTransport(serverName, rawServer) {
64
64
  };
65
65
  }
66
66
  if (resolved.transportType === "streamable-http") return {
67
- transport: new StreamableHTTPClientTransport(new URL(resolved.url), { requestInit: resolved.headers ? { headers: resolved.headers } : void 0 }),
67
+ transport: new StreamableHTTPClientTransport(new URL(resolved.url), {
68
+ requestInit: resolved.headers ? { headers: resolved.headers } : void 0,
69
+ fetch: fetchWithUndici
70
+ }),
68
71
  description: resolved.description,
69
72
  transportType: "streamable-http",
70
73
  connectionTimeoutMs: resolved.connectionTimeoutMs
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-transport.js","names":["undiciFetch"],"sources":["../../../../src/agent/mcp/mcp-transport.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { FetchLike, Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { createLogger } from \"../../utils/logger.js\";\nconst log = createLogger(\"Mcp:Transport\");\nimport { normalizeOptionalString } from \"../../utils/string-coerce.js\";\nimport { XopcStdioClientTransport } from \"./mcp-stdio-transport.js\";\nimport { resolveMcpTransportConfig } from \"./mcp-transport-config.js\";\n\nexport type ResolvedMcpTransport = {\n transport: Transport;\n description: string;\n transportType: \"stdio\" | \"sse\" | \"streamable-http\";\n connectionTimeoutMs: number;\n detachStderr?: () => void;\n};\n\nfunction attachStderrLogging(serverName: string, transport: XopcStdioClientTransport) {\n const stderr = transport.stderr;\n if (!stderr || typeof stderr.on !== \"function\") {\n return undefined;\n }\n const onData = (chunk: Buffer | string) => {\n const message =\n normalizeOptionalString(typeof chunk === \"string\" ? chunk : String(chunk)) ?? \"\";\n if (!message) {\n return;\n }\n for (const line of message.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed) {\n log.debug(`bundle-mcp:${serverName}: ${trimmed}`);\n }\n }\n };\n stderr.on(\"data\", onData);\n return () => {\n if (typeof stderr.off === \"function\") {\n stderr.off(\"data\", onData);\n } else if (typeof stderr.removeListener === \"function\") {\n stderr.removeListener(\"data\", onData);\n }\n };\n}\n\ntype SseEventSourceFetch = NonNullable<\n NonNullable<SSEClientTransportOptions[\"eventSourceInit\"]>[\"fetch\"]\n>;\n\nconst fetchWithUndici: FetchLike = async (url, init) =>\n (await undiciFetch(url, init as unknown as Parameters<typeof undiciFetch>[1])) as unknown as Response;\n\nfunction buildSseEventSourceFetch(headers: Record<string, string>): SseEventSourceFetch {\n return (url: string | URL, init?: RequestInit) => {\n const sdkHeaders: Record<string, string> = {};\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n sdkHeaders[key] = value;\n });\n } else {\n Object.assign(sdkHeaders, init.headers);\n }\n }\n return fetchWithUndici(url, {\n ...(init as RequestInit),\n headers: { ...sdkHeaders, ...headers },\n }) as ReturnType<SseEventSourceFetch>;\n };\n}\n\nexport function resolveMcpTransport(\n serverName: string,\n rawServer: unknown,\n): ResolvedMcpTransport | null {\n const resolved = resolveMcpTransportConfig(serverName, rawServer);\n if (!resolved) {\n return null;\n }\n if (resolved.kind === \"stdio\") {\n const transport = new XopcStdioClientTransport({\n command: resolved.command,\n args: resolved.args,\n env: resolved.env,\n cwd: resolved.cwd,\n stderr: \"pipe\",\n });\n return {\n transport,\n description: resolved.description,\n transportType: \"stdio\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n detachStderr: attachStderrLogging(serverName, transport),\n };\n }\n if (resolved.transportType === \"streamable-http\") {\n return {\n transport: new StreamableHTTPClientTransport(new URL(resolved.url), {\n requestInit: resolved.headers ? { headers: resolved.headers } : undefined,\n }),\n description: resolved.description,\n transportType: \"streamable-http\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n }\n const headers: Record<string, string> = {\n ...resolved.headers,\n };\n const hasHeaders = Object.keys(headers).length > 0;\n return {\n transport: new SSEClientTransport(new URL(resolved.url), {\n requestInit: hasHeaders ? { headers } : undefined,\n fetch: fetchWithUndici,\n eventSourceInit: { fetch: buildSseEventSourceFetch(headers) },\n }),\n description: resolved.description,\n transportType: \"sse\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n}\n"],"mappings":";;;;;;;;;aAOqD;oBAEkB;AADvE,MAAM,MAAM,aAAa,gBAAgB;AAazC,SAAS,oBAAoB,YAAoB,WAAqC;CACpF,MAAM,SAAS,UAAU;AACzB,KAAI,CAAC,UAAU,OAAO,OAAO,OAAO,WAClC;CAEF,MAAM,UAAU,UAA2B;EACzC,MAAM,UACJ,wBAAwB,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM,CAAC,IAAI;AAChF,MAAI,CAAC,QACH;AAEF,OAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,EAAE;GACzC,MAAM,UAAU,KAAK,MAAM;AAC3B,OAAI,QACF,KAAI,MAAM,cAAc,WAAW,IAAI,UAAU;;;AAIvD,QAAO,GAAG,QAAQ,OAAO;AACzB,cAAa;AACX,MAAI,OAAO,OAAO,QAAQ,WACxB,QAAO,IAAI,QAAQ,OAAO;WACjB,OAAO,OAAO,mBAAmB,WAC1C,QAAO,eAAe,QAAQ,OAAO;;;AAS3C,MAAM,kBAA6B,OAAO,KAAK,SAC5C,MAAMA,MAAY,KAAK,KAAqD;AAE/E,SAAS,yBAAyB,SAAsD;AACtF,SAAQ,KAAmB,SAAuB;EAChD,MAAM,aAAqC,EAAE;AAC7C,MAAI,MAAM,QACR,KAAI,KAAK,mBAAmB,QAC1B,MAAK,QAAQ,SAAS,OAAO,QAAQ;AACnC,cAAW,OAAO;IAClB;MAEF,QAAO,OAAO,YAAY,KAAK,QAAQ;AAG3C,SAAO,gBAAgB,KAAK;GAC1B,GAAI;GACJ,SAAS;IAAE,GAAG;IAAY,GAAG;IAAS;GACvC,CAAC;;;AAIN,SAAgB,oBACd,YACA,WAC6B;CAC7B,MAAM,WAAW,0BAA0B,YAAY,UAAU;AACjE,KAAI,CAAC,SACH,QAAO;AAET,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,YAAY,IAAI,yBAAyB;GAC7C,SAAS,SAAS;GAClB,MAAM,SAAS;GACf,KAAK,SAAS;GACd,KAAK,SAAS;GACd,QAAQ;GACT,CAAC;AACF,SAAO;GACL;GACA,aAAa,SAAS;GACtB,eAAe;GACf,qBAAqB,SAAS;GAC9B,cAAc,oBAAoB,YAAY,UAAU;GACzD;;AAEH,KAAI,SAAS,kBAAkB,kBAC7B,QAAO;EACL,WAAW,IAAI,8BAA8B,IAAI,IAAI,SAAS,IAAI,EAAE,EAClE,aAAa,SAAS,UAAU,EAAE,SAAS,SAAS,SAAS,GAAG,KAAA,GACjE,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B;CAEH,MAAM,UAAkC,EACtC,GAAG,SAAS,SACb;CACD,MAAM,aAAa,OAAO,KAAK,QAAQ,CAAC,SAAS;AACjD,QAAO;EACL,WAAW,IAAI,mBAAmB,IAAI,IAAI,SAAS,IAAI,EAAE;GACvD,aAAa,aAAa,EAAE,SAAS,GAAG,KAAA;GACxC,OAAO;GACP,iBAAiB,EAAE,OAAO,yBAAyB,QAAQ,EAAE;GAC9D,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B"}
1
+ {"version":3,"file":"mcp-transport.js","names":["undiciFetch"],"sources":["../../../../src/agent/mcp/mcp-transport.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { FetchLike, Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { fetch as undiciFetch } from \"undici\";\nimport { createLogger } from \"../../utils/logger.js\";\nconst log = createLogger(\"Mcp:Transport\");\nimport { normalizeOptionalString } from \"../../utils/string-coerce.js\";\nimport { XopcStdioClientTransport } from \"./mcp-stdio-transport.js\";\nimport { resolveMcpTransportConfig } from \"./mcp-transport-config.js\";\n\nexport type ResolvedMcpTransport = {\n transport: Transport;\n description: string;\n transportType: \"stdio\" | \"sse\" | \"streamable-http\";\n connectionTimeoutMs: number;\n detachStderr?: () => void;\n};\n\nfunction attachStderrLogging(serverName: string, transport: XopcStdioClientTransport) {\n const stderr = transport.stderr;\n if (!stderr || typeof stderr.on !== \"function\") {\n return undefined;\n }\n const onData = (chunk: Buffer | string) => {\n const message =\n normalizeOptionalString(typeof chunk === \"string\" ? chunk : String(chunk)) ?? \"\";\n if (!message) {\n return;\n }\n for (const line of message.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (trimmed) {\n log.debug(`bundle-mcp:${serverName}: ${trimmed}`);\n }\n }\n };\n stderr.on(\"data\", onData);\n return () => {\n if (typeof stderr.off === \"function\") {\n stderr.off(\"data\", onData);\n } else if (typeof stderr.removeListener === \"function\") {\n stderr.removeListener(\"data\", onData);\n }\n };\n}\n\ntype SseEventSourceFetch = NonNullable<\n NonNullable<SSEClientTransportOptions[\"eventSourceInit\"]>[\"fetch\"]\n>;\n\nconst fetchWithUndici: FetchLike = async (url, init) =>\n (await undiciFetch(url, init as unknown as Parameters<typeof undiciFetch>[1])) as unknown as Response;\n\nfunction buildSseEventSourceFetch(headers: Record<string, string>): SseEventSourceFetch {\n return (url: string | URL, init?: RequestInit) => {\n const sdkHeaders: Record<string, string> = {};\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n sdkHeaders[key] = value;\n });\n } else {\n Object.assign(sdkHeaders, init.headers);\n }\n }\n return fetchWithUndici(url, {\n ...(init as RequestInit),\n headers: { ...sdkHeaders, ...headers },\n }) as ReturnType<SseEventSourceFetch>;\n };\n}\n\nexport function resolveMcpTransport(\n serverName: string,\n rawServer: unknown,\n): ResolvedMcpTransport | null {\n const resolved = resolveMcpTransportConfig(serverName, rawServer);\n if (!resolved) {\n return null;\n }\n if (resolved.kind === \"stdio\") {\n const transport = new XopcStdioClientTransport({\n command: resolved.command,\n args: resolved.args,\n env: resolved.env,\n cwd: resolved.cwd,\n stderr: \"pipe\",\n });\n return {\n transport,\n description: resolved.description,\n transportType: \"stdio\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n detachStderr: attachStderrLogging(serverName, transport),\n };\n }\n if (resolved.transportType === \"streamable-http\") {\n return {\n transport: new StreamableHTTPClientTransport(new URL(resolved.url), {\n requestInit: resolved.headers ? { headers: resolved.headers } : undefined,\n fetch: fetchWithUndici,\n }),\n description: resolved.description,\n transportType: \"streamable-http\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n }\n const headers: Record<string, string> = {\n ...resolved.headers,\n };\n const hasHeaders = Object.keys(headers).length > 0;\n return {\n transport: new SSEClientTransport(new URL(resolved.url), {\n requestInit: hasHeaders ? { headers } : undefined,\n fetch: fetchWithUndici,\n eventSourceInit: { fetch: buildSseEventSourceFetch(headers) },\n }),\n description: resolved.description,\n transportType: \"sse\",\n connectionTimeoutMs: resolved.connectionTimeoutMs,\n };\n}\n"],"mappings":";;;;;;;;;aAOqD;oBAEkB;AADvE,MAAM,MAAM,aAAa,gBAAgB;AAazC,SAAS,oBAAoB,YAAoB,WAAqC;CACpF,MAAM,SAAS,UAAU;AACzB,KAAI,CAAC,UAAU,OAAO,OAAO,OAAO,WAClC;CAEF,MAAM,UAAU,UAA2B;EACzC,MAAM,UACJ,wBAAwB,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM,CAAC,IAAI;AAChF,MAAI,CAAC,QACH;AAEF,OAAK,MAAM,QAAQ,QAAQ,MAAM,QAAQ,EAAE;GACzC,MAAM,UAAU,KAAK,MAAM;AAC3B,OAAI,QACF,KAAI,MAAM,cAAc,WAAW,IAAI,UAAU;;;AAIvD,QAAO,GAAG,QAAQ,OAAO;AACzB,cAAa;AACX,MAAI,OAAO,OAAO,QAAQ,WACxB,QAAO,IAAI,QAAQ,OAAO;WACjB,OAAO,OAAO,mBAAmB,WAC1C,QAAO,eAAe,QAAQ,OAAO;;;AAS3C,MAAM,kBAA6B,OAAO,KAAK,SAC5C,MAAMA,MAAY,KAAK,KAAqD;AAE/E,SAAS,yBAAyB,SAAsD;AACtF,SAAQ,KAAmB,SAAuB;EAChD,MAAM,aAAqC,EAAE;AAC7C,MAAI,MAAM,QACR,KAAI,KAAK,mBAAmB,QAC1B,MAAK,QAAQ,SAAS,OAAO,QAAQ;AACnC,cAAW,OAAO;IAClB;MAEF,QAAO,OAAO,YAAY,KAAK,QAAQ;AAG3C,SAAO,gBAAgB,KAAK;GAC1B,GAAI;GACJ,SAAS;IAAE,GAAG;IAAY,GAAG;IAAS;GACvC,CAAC;;;AAIN,SAAgB,oBACd,YACA,WAC6B;CAC7B,MAAM,WAAW,0BAA0B,YAAY,UAAU;AACjE,KAAI,CAAC,SACH,QAAO;AAET,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,YAAY,IAAI,yBAAyB;GAC7C,SAAS,SAAS;GAClB,MAAM,SAAS;GACf,KAAK,SAAS;GACd,KAAK,SAAS;GACd,QAAQ;GACT,CAAC;AACF,SAAO;GACL;GACA,aAAa,SAAS;GACtB,eAAe;GACf,qBAAqB,SAAS;GAC9B,cAAc,oBAAoB,YAAY,UAAU;GACzD;;AAEH,KAAI,SAAS,kBAAkB,kBAC7B,QAAO;EACL,WAAW,IAAI,8BAA8B,IAAI,IAAI,SAAS,IAAI,EAAE;GAClE,aAAa,SAAS,UAAU,EAAE,SAAS,SAAS,SAAS,GAAG,KAAA;GAChE,OAAO;GACR,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B;CAEH,MAAM,UAAkC,EACtC,GAAG,SAAS,SACb;CACD,MAAM,aAAa,OAAO,KAAK,QAAQ,CAAC,SAAS;AACjD,QAAO;EACL,WAAW,IAAI,mBAAmB,IAAI,IAAI,SAAS,IAAI,EAAE;GACvD,aAAa,aAAa,EAAE,SAAS,GAAG,KAAA;GACxC,OAAO;GACP,iBAAiB,EAAE,OAAO,yBAAyB,QAAQ,EAAE;GAC9D,CAAC;EACF,aAAa,SAAS;EACtB,eAAe;EACf,qBAAqB,SAAS;EAC/B"}
@@ -8,5 +8,6 @@ export declare class UserContextPlanner {
8
8
  sessionKey: string;
9
9
  query: string;
10
10
  userMessage: AgentMessage;
11
+ excludedRecordIds?: string[];
11
12
  }): Promise<UserContextPlan>;
12
13
  }
@@ -4,11 +4,21 @@ import { appendMemoryTraceEvent } from "../../../storage/sqlite/memory-records-r
4
4
  import "../../../storage/sqlite/index.js";
5
5
  import { readAgentMessageContent } from "../agent-message-access.js";
6
6
  import { buildUserContextBlock } from "../context-fence.js";
7
+ import { resolveMemoryStability } from "../lifecycle.js";
8
+ import { classifyMemoryContextOrigin } from "../source-origin.js";
7
9
  import { randomUUID } from "node:crypto";
8
10
  //#region src/agent/memory/context/planner.ts
9
11
  init_logger();
10
12
  const MAX_CONTEXT_CHARS = 6e3;
11
13
  const MAX_RESULTS = 8;
14
+ const BASELINE_KINDS = [
15
+ "boundary",
16
+ "preference",
17
+ "tool_preference",
18
+ "routine",
19
+ "user_profile",
20
+ "personal_logistics"
21
+ ];
12
22
  const log = createLogger("UserContextPlanner");
13
23
  function sectionFor(record) {
14
24
  if (record.kind === "boundary") return "safety";
@@ -20,13 +30,13 @@ function rejectReason(record, now) {
20
30
  if (record.validTo && Date.parse(record.validTo) < now || record.expiresAt && Date.parse(record.expiresAt) < now) return "expired";
21
31
  if (record.sensitivity === "secret" || record.sensitivity === "regulated") return "sensitive";
22
32
  if (record.disclosurePolicy === "ask_before_reference") return "requires_consent";
33
+ if (record.status === "needs_review" || record.status === "stale" || resolveMemoryStability(record, now).reviewDue) return "needs_review";
23
34
  }
24
35
  function scoreResult(result, now) {
25
36
  const confidence = result.record.confidence ?? .5;
26
37
  const explicitness = result.record.explicitness === "explicit" ? 1 : result.record.explicitness === "observed" ? .65 : .4;
27
- const ageDays = Math.max(0, (now - Date.parse(result.record.updatedAt)) / 864e5);
28
- const freshness = Math.exp(-ageDays / 180);
29
- return Math.max(0, Math.min(1, result.score * .5 + confidence * .15 + result.record.importance * .2 + explicitness * .1 + freshness * .05));
38
+ const stability = resolveMemoryStability(result.record, now).score;
39
+ return Math.max(0, Math.min(1, result.score * .45 + confidence * .1 + result.record.importance * .2 + explicitness * .1 + stability * .15));
30
40
  }
31
41
  function citationFor(result, requesterAgentId) {
32
42
  const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;
@@ -35,6 +45,12 @@ function citationFor(result, requesterAgentId) {
35
45
  const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart ? `-L${result.citation.lineEnd}` : "";
36
46
  return `${ownerPrefix}${base}#L${result.citation.lineStart}${end}`;
37
47
  }
48
+ function evidenceLabel(item) {
49
+ if (item.origin === "told_by_user") return "The user explicitly shared this";
50
+ if (item.origin === "observed") return "Observed across prior work";
51
+ if (item.origin === "connected_source") return "A connected source provided this";
52
+ return "An inference that may be wrong";
53
+ }
38
54
  function prependContext(message, block) {
39
55
  if (!block) return message;
40
56
  const prefix = `${block}\n\n`;
@@ -78,21 +94,42 @@ var UserContextPlanner = class {
78
94
  estimatedTokens: 0
79
95
  };
80
96
  const started = Date.now();
81
- const results = await params.memoryManager.search({
97
+ const scope = {
98
+ agentId: params.agentId,
99
+ sessionKey: params.sessionKey
100
+ };
101
+ const [taskResults, baselineLists] = await Promise.all([params.memoryManager.search({
82
102
  query,
83
- scope: {
84
- agentId: params.agentId,
85
- sessionKey: params.sessionKey
86
- },
103
+ scope,
87
104
  maxResults: MAX_RESULTS,
88
105
  minScore: .15
89
- }).catch(() => []);
106
+ }).catch(() => []), Promise.all(BASELINE_KINDS.map((kind) => params.memoryManager.list({
107
+ kind,
108
+ status: "active",
109
+ scope
110
+ }).catch(() => [])))]);
111
+ const taskIds = new Set(taskResults.map((result) => result.record.id));
112
+ const baselineResults = baselineLists.flat().filter((record) => !taskIds.has(record.id)).filter((record) => record.kind === "boundary" || record.explicitness === "explicit" || record.importance >= .7).map((record) => ({
113
+ record,
114
+ score: record.kind === "boundary" ? .7 : .42,
115
+ snippet: record.content,
116
+ citation: {
117
+ providerId: record.source.provider ?? "local",
118
+ recordId: record.id,
119
+ path: record.source.path,
120
+ lineStart: record.source.lineStart,
121
+ lineEnd: record.source.lineEnd,
122
+ createdAt: record.createdAt
123
+ }
124
+ }));
125
+ const results = [...taskResults, ...baselineResults];
90
126
  const now = Date.now();
127
+ const excluded = new Set(params.excludedRecordIds ?? []);
91
128
  const rejected = [];
92
- const ranked = results.map((result) => ({
129
+ const ranked = results.filter((result) => !excluded.has(result.record.id)).map((result) => ({
93
130
  result,
94
131
  score: scoreResult(result, now)
95
- })).sort((a, b) => b.score - a.score);
132
+ })).sort((a, b) => b.score - a.score).filter((entry, index, all) => all.findIndex((candidate) => candidate.result.record.id === entry.result.record.id) === index).slice(0, MAX_RESULTS);
96
133
  const items = [];
97
134
  let usedChars = 0;
98
135
  for (const { result, score } of ranked) {
@@ -118,7 +155,9 @@ var UserContextPlanner = class {
118
155
  content,
119
156
  score,
120
157
  section: sectionFor(result.record),
121
- citation: citationFor(result, params.agentId)
158
+ citation: citationFor(result, params.agentId),
159
+ origin: classifyMemoryContextOrigin(result.record),
160
+ stability: resolveMemoryStability(result.record, now).score
122
161
  });
123
162
  }
124
163
  const sections = [];
@@ -128,7 +167,7 @@ var UserContextPlanner = class {
128
167
  ["interaction", "Interaction preferences"]
129
168
  ]) {
130
169
  const sectionItems = items.filter((item) => item.section === section);
131
- if (sectionItems.length > 0) sections.push(`${title}:\n${sectionItems.map((item) => `- ${item.content}\n Source: ${item.citation}`).join("\n")}`);
170
+ if (sectionItems.length > 0) sections.push(`${title}:\n${sectionItems.map((item) => `- ${item.content}\n Evidence: ${evidenceLabel(item)}`).join("\n")}`);
132
171
  }
133
172
  const block = buildUserContextBlock(sections.join("\n\n"));
134
173
  try {
@@ -139,7 +178,14 @@ var UserContextPlanner = class {
139
178
  sessionKey: params.sessionKey,
140
179
  request: {
141
180
  query,
142
- rejected
181
+ rejected,
182
+ contextItems: items.map((item) => ({
183
+ recordId: item.recordId,
184
+ section: item.section,
185
+ origin: item.origin,
186
+ stability: item.stability,
187
+ citation: item.citation
188
+ }))
143
189
  },
144
190
  resultCount: items.length,
145
191
  selectedRecordIds: items.map((item) => item.recordId),
@@ -1 +1 @@
1
- {"version":3,"file":"planner.js","names":[],"sources":["../../../../../src/agent/memory/context/planner.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { appendMemoryTraceEvent } from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport { readAgentMessageContent } from '../agent-message-access.js';\nimport { buildUserContextBlock } from '../context-fence.js';\nimport type { MemoryManager } from '../manager.js';\nimport type { MemoryRecord, MemorySearchResult } from '../types.js';\nimport type {\n PlannedUserContextItem,\n UserContextPlan,\n UserContextRejectionReason,\n} from './types.js';\n\nconst MAX_CONTEXT_CHARS = 6_000;\nconst MAX_RESULTS = 8;\nconst log = createLogger('UserContextPlanner');\n\nfunction sectionFor(record: MemoryRecord): PlannedUserContextItem['section'] {\n if (record.kind === 'boundary') return 'safety';\n if (\n record.kind === 'preference' ||\n record.kind === 'user_profile' ||\n record.kind === 'relationship' ||\n record.kind === 'routine' ||\n record.kind === 'personal_logistics' ||\n record.kind === 'tool_preference'\n ) return 'interaction';\n return 'task';\n}\n\nfunction rejectReason(record: MemoryRecord, now: number): UserContextRejectionReason | undefined {\n if (record.validFrom && Date.parse(record.validFrom) > now) return 'not_yet_valid';\n if (\n (record.validTo && Date.parse(record.validTo) < now) ||\n (record.expiresAt && Date.parse(record.expiresAt) < now)\n ) return 'expired';\n if (record.sensitivity === 'secret' || record.sensitivity === 'regulated') return 'sensitive';\n if (record.disclosurePolicy === 'ask_before_reference') return 'requires_consent';\n return undefined;\n}\n\nfunction scoreResult(result: MemorySearchResult, now: number): number {\n const confidence = result.record.confidence ?? 0.5;\n const explicitness = result.record.explicitness === 'explicit'\n ? 1\n : result.record.explicitness === 'observed' ? 0.65 : 0.4;\n const ageDays = Math.max(0, (now - Date.parse(result.record.updatedAt)) / 86_400_000);\n const freshness = Math.exp(-ageDays / 180);\n return Math.max(0, Math.min(1,\n result.score * 0.5 + confidence * 0.15 + result.record.importance * 0.2 + explicitness * 0.1 + freshness * 0.05,\n ));\n}\n\nfunction citationFor(result: MemorySearchResult, requesterAgentId: string): string {\n const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;\n const ownerPrefix = result.record.scope.agentId !== requesterAgentId\n ? `shared-from-agent:${result.record.scope.agentId} `\n : '';\n if (result.citation.lineStart == null) return `${ownerPrefix}${base}`;\n const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart\n ? `-L${result.citation.lineEnd}`\n : '';\n return `${ownerPrefix}${base}#L${result.citation.lineStart}${end}`;\n}\n\nfunction prependContext(message: AgentMessage, block: string): AgentMessage {\n if (!block) return message;\n const prefix = `${block}\\n\\n`;\n const content = readAgentMessageContent(message);\n if (typeof content === 'string') return { ...message, content: prefix + content } as AgentMessage;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0] as { type?: string; text?: string };\n if (first.type === 'text' && typeof first.text === 'string') {\n const copy = [...content];\n copy[0] = { type: 'text', text: prefix + first.text };\n return { ...message, content: copy } as AgentMessage;\n }\n return { ...message, content: [{ type: 'text' as const, text: prefix }, ...content] } as AgentMessage;\n }\n return message;\n}\n\nexport class UserContextPlanner {\n async plan(params: {\n memoryManager: MemoryManager;\n agentId: string;\n sessionKey: string;\n query: string;\n userMessage: AgentMessage;\n }): Promise<UserContextPlan> {\n const traceId = randomUUID();\n const query = params.query.trim();\n if (!query) {\n return { traceId, modelMessage: params.userMessage, items: [], rejected: [], estimatedTokens: 0 };\n }\n const started = Date.now();\n const results = await params.memoryManager.search({\n query,\n scope: { agentId: params.agentId, sessionKey: params.sessionKey },\n maxResults: MAX_RESULTS,\n minScore: 0.15,\n }).catch(() => []);\n const now = Date.now();\n const rejected: UserContextPlan['rejected'] = [];\n const ranked = results\n .map((result) => ({ result, score: scoreResult(result, now) }))\n .sort((a, b) => b.score - a.score);\n const items: PlannedUserContextItem[] = [];\n let usedChars = 0;\n for (const { result, score } of ranked) {\n const reason = rejectReason(result.record, now) ?? (score < 0.25 ? 'low_score' : undefined);\n if (reason) {\n rejected.push({ recordId: result.record.id, reason });\n continue;\n }\n const content = result.snippet.trim();\n if (usedChars + content.length > MAX_CONTEXT_CHARS) {\n rejected.push({ recordId: result.record.id, reason: 'budget' });\n continue;\n }\n usedChars += content.length;\n items.push({\n recordId: result.record.id,\n content,\n score,\n section: sectionFor(result.record),\n citation: citationFor(result, params.agentId),\n });\n }\n const sections: string[] = [];\n for (const [section, title] of [['safety', 'Boundaries'], ['task', 'Relevant facts'], ['interaction', 'Interaction preferences']] as const) {\n const sectionItems = items.filter((item) => item.section === section);\n if (sectionItems.length > 0) {\n sections.push(`${title}:\\n${sectionItems.map((item) => `- ${item.content}\\n Source: ${item.citation}`).join('\\n')}`);\n }\n }\n const block = buildUserContextBlock(sections.join('\\n\\n'));\n try {\n appendMemoryTraceEvent({\n traceId,\n phase: 'inject',\n providerId: 'user-understanding',\n sessionKey: params.sessionKey,\n request: { query, rejected },\n resultCount: items.length,\n selectedRecordIds: items.map((item) => item.recordId),\n durationMs: Date.now() - started,\n });\n } catch (err) {\n log.debug({ err, traceId, sessionKey: params.sessionKey }, 'Context plan trace was not persisted');\n }\n return {\n traceId,\n modelMessage: prependContext(params.userMessage, block),\n items,\n rejected,\n estimatedTokens: Math.ceil(block.length / 4),\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"planner.js","names":[],"sources":["../../../../../src/agent/memory/context/planner.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\n\nimport { appendMemoryTraceEvent } from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport { readAgentMessageContent } from '../agent-message-access.js';\nimport { buildUserContextBlock } from '../context-fence.js';\nimport type { MemoryManager } from '../manager.js';\nimport { resolveMemoryStability } from '../lifecycle.js';\nimport { classifyMemoryContextOrigin } from '../source-origin.js';\nimport type { MemoryRecord, MemorySearchResult } from '../types.js';\nimport type {\n PlannedUserContextItem,\n UserContextPlan,\n UserContextRejectionReason,\n} from './types.js';\n\nconst MAX_CONTEXT_CHARS = 6_000;\nconst MAX_RESULTS = 8;\nconst BASELINE_KINDS = [\n 'boundary',\n 'preference',\n 'tool_preference',\n 'routine',\n 'user_profile',\n 'personal_logistics',\n] as const;\nconst log = createLogger('UserContextPlanner');\n\nfunction sectionFor(record: MemoryRecord): PlannedUserContextItem['section'] {\n if (record.kind === 'boundary') return 'safety';\n if (\n record.kind === 'preference' ||\n record.kind === 'user_profile' ||\n record.kind === 'relationship' ||\n record.kind === 'routine' ||\n record.kind === 'personal_logistics' ||\n record.kind === 'tool_preference'\n ) return 'interaction';\n return 'task';\n}\n\nfunction rejectReason(record: MemoryRecord, now: number): UserContextRejectionReason | undefined {\n if (record.validFrom && Date.parse(record.validFrom) > now) return 'not_yet_valid';\n if (\n (record.validTo && Date.parse(record.validTo) < now) ||\n (record.expiresAt && Date.parse(record.expiresAt) < now)\n ) return 'expired';\n if (record.sensitivity === 'secret' || record.sensitivity === 'regulated') return 'sensitive';\n if (record.disclosurePolicy === 'ask_before_reference') return 'requires_consent';\n if (record.status === 'needs_review' || record.status === 'stale' || resolveMemoryStability(record, now).reviewDue) return 'needs_review';\n return undefined;\n}\n\nfunction scoreResult(result: MemorySearchResult, now: number): number {\n const confidence = result.record.confidence ?? 0.5;\n const explicitness = result.record.explicitness === 'explicit'\n ? 1\n : result.record.explicitness === 'observed' ? 0.65 : 0.4;\n const stability = resolveMemoryStability(result.record, now).score;\n return Math.max(0, Math.min(1,\n result.score * 0.45 + confidence * 0.1 + result.record.importance * 0.2 + explicitness * 0.1 + stability * 0.15,\n ));\n}\n\nfunction citationFor(result: MemorySearchResult, requesterAgentId: string): string {\n const base = result.citation.path ?? `${result.citation.providerId}:${result.citation.recordId}`;\n const ownerPrefix = result.record.scope.agentId !== requesterAgentId\n ? `shared-from-agent:${result.record.scope.agentId} `\n : '';\n if (result.citation.lineStart == null) return `${ownerPrefix}${base}`;\n const end = result.citation.lineEnd && result.citation.lineEnd !== result.citation.lineStart\n ? `-L${result.citation.lineEnd}`\n : '';\n return `${ownerPrefix}${base}#L${result.citation.lineStart}${end}`;\n}\n\nfunction evidenceLabel(item: PlannedUserContextItem): string {\n if (item.origin === 'told_by_user') return 'The user explicitly shared this';\n if (item.origin === 'observed') return 'Observed across prior work';\n if (item.origin === 'connected_source') return 'A connected source provided this';\n return 'An inference that may be wrong';\n}\n\nfunction prependContext(message: AgentMessage, block: string): AgentMessage {\n if (!block) return message;\n const prefix = `${block}\\n\\n`;\n const content = readAgentMessageContent(message);\n if (typeof content === 'string') return { ...message, content: prefix + content } as AgentMessage;\n if (Array.isArray(content) && content.length > 0) {\n const first = content[0] as { type?: string; text?: string };\n if (first.type === 'text' && typeof first.text === 'string') {\n const copy = [...content];\n copy[0] = { type: 'text', text: prefix + first.text };\n return { ...message, content: copy } as AgentMessage;\n }\n return { ...message, content: [{ type: 'text' as const, text: prefix }, ...content] } as AgentMessage;\n }\n return message;\n}\n\nexport class UserContextPlanner {\n async plan(params: {\n memoryManager: MemoryManager;\n agentId: string;\n sessionKey: string;\n query: string;\n userMessage: AgentMessage;\n excludedRecordIds?: string[];\n }): Promise<UserContextPlan> {\n const traceId = randomUUID();\n const query = params.query.trim();\n if (!query) {\n return { traceId, modelMessage: params.userMessage, items: [], rejected: [], estimatedTokens: 0 };\n }\n const started = Date.now();\n const scope = { agentId: params.agentId, sessionKey: params.sessionKey };\n const [taskResults, baselineLists] = await Promise.all([\n params.memoryManager.search({\n query,\n scope,\n maxResults: MAX_RESULTS,\n minScore: 0.15,\n }).catch(() => []),\n Promise.all(BASELINE_KINDS.map((kind) => (\n params.memoryManager.list({ kind, status: 'active', scope }).catch(() => [])\n ))),\n ]);\n const taskIds = new Set(taskResults.map((result) => result.record.id));\n const baselineResults: MemorySearchResult[] = baselineLists\n .flat()\n .filter((record) => !taskIds.has(record.id))\n .filter((record) => record.kind === 'boundary' || record.explicitness === 'explicit' || record.importance >= 0.7)\n .map((record) => ({\n record,\n score: record.kind === 'boundary' ? 0.7 : 0.42,\n snippet: record.content,\n citation: {\n providerId: record.source.provider ?? 'local',\n recordId: record.id,\n path: record.source.path,\n lineStart: record.source.lineStart,\n lineEnd: record.source.lineEnd,\n createdAt: record.createdAt,\n },\n }));\n const results = [...taskResults, ...baselineResults];\n const now = Date.now();\n const excluded = new Set(params.excludedRecordIds ?? []);\n const rejected: UserContextPlan['rejected'] = [];\n const ranked = results\n .filter((result) => !excluded.has(result.record.id))\n .map((result) => ({ result, score: scoreResult(result, now) }))\n .sort((a, b) => b.score - a.score)\n .filter((entry, index, all) => all.findIndex((candidate) => candidate.result.record.id === entry.result.record.id) === index)\n .slice(0, MAX_RESULTS);\n const items: PlannedUserContextItem[] = [];\n let usedChars = 0;\n for (const { result, score } of ranked) {\n const reason = rejectReason(result.record, now) ?? (score < 0.25 ? 'low_score' : undefined);\n if (reason) {\n rejected.push({ recordId: result.record.id, reason });\n continue;\n }\n const content = result.snippet.trim();\n if (usedChars + content.length > MAX_CONTEXT_CHARS) {\n rejected.push({ recordId: result.record.id, reason: 'budget' });\n continue;\n }\n usedChars += content.length;\n items.push({\n recordId: result.record.id,\n content,\n score,\n section: sectionFor(result.record),\n citation: citationFor(result, params.agentId),\n origin: classifyMemoryContextOrigin(result.record),\n stability: resolveMemoryStability(result.record, now).score,\n });\n }\n const sections: string[] = [];\n for (const [section, title] of [['safety', 'Boundaries'], ['task', 'Relevant facts'], ['interaction', 'Interaction preferences']] as const) {\n const sectionItems = items.filter((item) => item.section === section);\n if (sectionItems.length > 0) {\n sections.push(`${title}:\\n${sectionItems.map((item) => `- ${item.content}\\n Evidence: ${evidenceLabel(item)}`).join('\\n')}`);\n }\n }\n const block = buildUserContextBlock(sections.join('\\n\\n'));\n try {\n appendMemoryTraceEvent({\n traceId,\n phase: 'inject',\n providerId: 'user-understanding',\n sessionKey: params.sessionKey,\n request: {\n query,\n rejected,\n contextItems: items.map((item) => ({\n recordId: item.recordId,\n section: item.section,\n origin: item.origin,\n stability: item.stability,\n citation: item.citation,\n })),\n },\n resultCount: items.length,\n selectedRecordIds: items.map((item) => item.recordId),\n durationMs: Date.now() - started,\n });\n } catch (err) {\n log.debug({ err, traceId, sessionKey: params.sessionKey }, 'Context plan trace was not persisted');\n }\n return {\n traceId,\n modelMessage: prependContext(params.userMessage, block),\n items,\n rejected,\n estimatedTokens: Math.ceil(block.length / 4),\n };\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,13 @@
1
1
  import type { AgentMessage } from '@earendil-works/pi-agent-core';
2
- export type UserContextRejectionReason = 'expired' | 'not_yet_valid' | 'sensitive' | 'requires_consent' | 'low_score' | 'budget';
2
+ export type UserContextRejectionReason = 'expired' | 'not_yet_valid' | 'sensitive' | 'requires_consent' | 'needs_review' | 'low_score' | 'budget';
3
3
  export interface PlannedUserContextItem {
4
4
  recordId: string;
5
5
  content: string;
6
6
  score: number;
7
7
  section: 'task' | 'interaction' | 'safety';
8
8
  citation: string;
9
+ origin: 'told_by_user' | 'observed' | 'inferred' | 'connected_source';
10
+ stability: number;
9
11
  }
10
12
  export interface UserContextPlan {
11
13
  traceId: string;
@@ -0,0 +1,11 @@
1
+ import type { MemoryRecord, MemoryStatus } from './types.js';
2
+ export type MemoryStabilityBand = 'strong' | 'working' | 'fragile';
3
+ export declare function nextMemoryReviewAt(record: Pick<MemoryRecord, 'durability' | 'explicitness'>, fromMs?: number): string;
4
+ export declare function resolveMemoryStability(record: MemoryRecord, nowMs?: number): {
5
+ score: number;
6
+ band: MemoryStabilityBand;
7
+ reviewAt: string;
8
+ reviewDue: boolean;
9
+ expired: boolean;
10
+ };
11
+ export declare function effectiveMemoryStatus(record: MemoryRecord, nowMs?: number): MemoryStatus;
@@ -0,0 +1,50 @@
1
+ //#region src/agent/memory/lifecycle.ts
2
+ const DAY_MS = 864e5;
3
+ function clamp01(value) {
4
+ return Math.max(0, Math.min(1, value));
5
+ }
6
+ function reviewIntervalDays(record) {
7
+ if (record.durability === "ephemeral") return 14;
8
+ if (record.durability === "recurring") return record.explicitness === "explicit" ? 120 : 60;
9
+ if (record.explicitness === "explicit") return 365;
10
+ if (record.explicitness === "observed") return 180;
11
+ return 90;
12
+ }
13
+ function nextMemoryReviewAt(record, fromMs = Date.now()) {
14
+ return new Date(fromMs + reviewIntervalDays(record) * DAY_MS).toISOString();
15
+ }
16
+ function resolveMemoryStability(record, nowMs = Date.now()) {
17
+ const confidence = clamp01(record.confidence ?? .5);
18
+ const explicitness = record.explicitness === "explicit" ? 1 : record.explicitness === "observed" ? .7 : .45;
19
+ const durability = record.durability === "durable" ? 1 : record.durability === "recurring" ? .85 : .55;
20
+ const evidence = record.evidence ?? [];
21
+ const evidenceStrength = clamp01((evidence.length > 0 ? evidence.reduce((sum, item) => sum + clamp01(item.confidence ?? confidence), 0) / evidence.length : confidence * .8) * .75 + Math.min(evidence.length, 4) * .0625);
22
+ const updatedAtMs = Date.parse(record.updatedAt);
23
+ const ageDays = Number.isFinite(updatedAtMs) ? Math.max(0, (nowMs - updatedAtMs) / DAY_MS) : 0;
24
+ const halfLifeDays = record.durability === "ephemeral" ? 21 : record.durability === "recurring" ? 120 : 365;
25
+ const freshnessFloor = record.explicitness === "explicit" ? .72 : record.explicitness === "observed" ? .48 : .28;
26
+ const freshness = freshnessFloor + (1 - freshnessFloor) * Math.pow(.5, ageDays / halfLifeDays);
27
+ const raw = confidence * .32 + explicitness * .2 + clamp01(record.importance) * .16 + durability * .14 + evidenceStrength * .18;
28
+ const score = Math.round(clamp01(raw * freshness) * 1e3) / 1e3;
29
+ const band = score >= .75 ? "strong" : score >= .5 ? "working" : "fragile";
30
+ const inferredReviewAt = nextMemoryReviewAt(record, Number.isFinite(updatedAtMs) ? updatedAtMs : nowMs);
31
+ const reviewAt = record.reviewAfter && Number.isFinite(Date.parse(record.reviewAfter)) ? record.reviewAfter : inferredReviewAt;
32
+ const expired = Boolean(record.expiresAt && Date.parse(record.expiresAt) <= nowMs || record.validTo && Date.parse(record.validTo) <= nowMs);
33
+ return {
34
+ score,
35
+ band,
36
+ reviewAt,
37
+ reviewDue: record.status === "candidate" || record.status === "needs_review" || record.status === "stale" || Date.parse(reviewAt) <= nowMs,
38
+ expired
39
+ };
40
+ }
41
+ function effectiveMemoryStatus(record, nowMs = Date.now()) {
42
+ const lifecycle = resolveMemoryStability(record, nowMs);
43
+ if (lifecycle.expired && record.status === "active") return "stale";
44
+ if (lifecycle.reviewDue && record.status === "active") return "needs_review";
45
+ return record.status ?? "active";
46
+ }
47
+ //#endregion
48
+ export { effectiveMemoryStatus, nextMemoryReviewAt, resolveMemoryStability };
49
+
50
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","names":[],"sources":["../../../../src/agent/memory/lifecycle.ts"],"sourcesContent":["import type { MemoryRecord, MemoryStatus } from './types.js';\n\nexport type MemoryStabilityBand = 'strong' | 'working' | 'fragile';\n\nconst DAY_MS = 86_400_000;\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nfunction reviewIntervalDays(record: Pick<MemoryRecord, 'durability' | 'explicitness'>): number {\n if (record.durability === 'ephemeral') return 14;\n if (record.durability === 'recurring') return record.explicitness === 'explicit' ? 120 : 60;\n if (record.explicitness === 'explicit') return 365;\n if (record.explicitness === 'observed') return 180;\n return 90;\n}\n\nexport function nextMemoryReviewAt(\n record: Pick<MemoryRecord, 'durability' | 'explicitness'>,\n fromMs = Date.now(),\n): string {\n return new Date(fromMs + reviewIntervalDays(record) * DAY_MS).toISOString();\n}\n\nexport function resolveMemoryStability(record: MemoryRecord, nowMs = Date.now()): {\n score: number;\n band: MemoryStabilityBand;\n reviewAt: string;\n reviewDue: boolean;\n expired: boolean;\n} {\n const confidence = clamp01(record.confidence ?? 0.5);\n const explicitness = record.explicitness === 'explicit' ? 1 : record.explicitness === 'observed' ? 0.7 : 0.45;\n const durability = record.durability === 'durable' ? 1 : record.durability === 'recurring' ? 0.85 : 0.55;\n const evidence = record.evidence ?? [];\n const evidenceConfidence = evidence.length > 0\n ? evidence.reduce((sum, item) => sum + clamp01(item.confidence ?? confidence), 0) / evidence.length\n : confidence * 0.8;\n const evidenceStrength = clamp01(evidenceConfidence * 0.75 + Math.min(evidence.length, 4) * 0.0625);\n const updatedAtMs = Date.parse(record.updatedAt);\n const ageDays = Number.isFinite(updatedAtMs) ? Math.max(0, (nowMs - updatedAtMs) / DAY_MS) : 0;\n const halfLifeDays = record.durability === 'ephemeral' ? 21 : record.durability === 'recurring' ? 120 : 365;\n const freshnessFloor = record.explicitness === 'explicit' ? 0.72 : record.explicitness === 'observed' ? 0.48 : 0.28;\n const freshness = freshnessFloor + (1 - freshnessFloor) * Math.pow(0.5, ageDays / halfLifeDays);\n const raw = confidence * 0.32\n + explicitness * 0.2\n + clamp01(record.importance) * 0.16\n + durability * 0.14\n + evidenceStrength * 0.18;\n const score = Math.round(clamp01(raw * freshness) * 1000) / 1000;\n const band: MemoryStabilityBand = score >= 0.75 ? 'strong' : score >= 0.5 ? 'working' : 'fragile';\n const inferredReviewAt = nextMemoryReviewAt(record, Number.isFinite(updatedAtMs) ? updatedAtMs : nowMs);\n const reviewAt = record.reviewAfter && Number.isFinite(Date.parse(record.reviewAfter))\n ? record.reviewAfter\n : inferredReviewAt;\n const expired = Boolean(\n (record.expiresAt && Date.parse(record.expiresAt) <= nowMs)\n || (record.validTo && Date.parse(record.validTo) <= nowMs),\n );\n const reviewDue = record.status === 'candidate'\n || record.status === 'needs_review'\n || record.status === 'stale'\n || Date.parse(reviewAt) <= nowMs;\n return { score, band, reviewAt, reviewDue, expired };\n}\n\nexport function effectiveMemoryStatus(record: MemoryRecord, nowMs = Date.now()): MemoryStatus {\n const lifecycle = resolveMemoryStability(record, nowMs);\n if (lifecycle.expired && record.status === 'active') return 'stale';\n if (lifecycle.reviewDue && record.status === 'active') return 'needs_review';\n return record.status ?? 'active';\n}\n"],"mappings":";AAIA,MAAM,SAAS;AAEf,SAAS,QAAQ,OAAuB;AACtC,QAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;;AAGxC,SAAS,mBAAmB,QAAmE;AAC7F,KAAI,OAAO,eAAe,YAAa,QAAO;AAC9C,KAAI,OAAO,eAAe,YAAa,QAAO,OAAO,iBAAiB,aAAa,MAAM;AACzF,KAAI,OAAO,iBAAiB,WAAY,QAAO;AAC/C,KAAI,OAAO,iBAAiB,WAAY,QAAO;AAC/C,QAAO;;AAGT,SAAgB,mBACd,QACA,SAAS,KAAK,KAAK,EACX;AACR,QAAO,IAAI,KAAK,SAAS,mBAAmB,OAAO,GAAG,OAAO,CAAC,aAAa;;AAG7E,SAAgB,uBAAuB,QAAsB,QAAQ,KAAK,KAAK,EAM7E;CACA,MAAM,aAAa,QAAQ,OAAO,cAAc,GAAI;CACpD,MAAM,eAAe,OAAO,iBAAiB,aAAa,IAAI,OAAO,iBAAiB,aAAa,KAAM;CACzG,MAAM,aAAa,OAAO,eAAe,YAAY,IAAI,OAAO,eAAe,cAAc,MAAO;CACpG,MAAM,WAAW,OAAO,YAAY,EAAE;CAItC,MAAM,mBAAmB,SAHE,SAAS,SAAS,IACzC,SAAS,QAAQ,KAAK,SAAS,MAAM,QAAQ,KAAK,cAAc,WAAW,EAAE,EAAE,GAAG,SAAS,SAC3F,aAAa,MACqC,MAAO,KAAK,IAAI,SAAS,QAAQ,EAAE,GAAG,MAAO;CACnG,MAAM,cAAc,KAAK,MAAM,OAAO,UAAU;CAChD,MAAM,UAAU,OAAO,SAAS,YAAY,GAAG,KAAK,IAAI,IAAI,QAAQ,eAAe,OAAO,GAAG;CAC7F,MAAM,eAAe,OAAO,eAAe,cAAc,KAAK,OAAO,eAAe,cAAc,MAAM;CACxG,MAAM,iBAAiB,OAAO,iBAAiB,aAAa,MAAO,OAAO,iBAAiB,aAAa,MAAO;CAC/G,MAAM,YAAY,kBAAkB,IAAI,kBAAkB,KAAK,IAAI,IAAK,UAAU,aAAa;CAC/F,MAAM,MAAM,aAAa,MACrB,eAAe,KACf,QAAQ,OAAO,WAAW,GAAG,MAC7B,aAAa,MACb,mBAAmB;CACvB,MAAM,QAAQ,KAAK,MAAM,QAAQ,MAAM,UAAU,GAAG,IAAK,GAAG;CAC5D,MAAM,OAA4B,SAAS,MAAO,WAAW,SAAS,KAAM,YAAY;CACxF,MAAM,mBAAmB,mBAAmB,QAAQ,OAAO,SAAS,YAAY,GAAG,cAAc,MAAM;CACvG,MAAM,WAAW,OAAO,eAAe,OAAO,SAAS,KAAK,MAAM,OAAO,YAAY,CAAC,GAClF,OAAO,cACP;CACJ,MAAM,UAAU,QACb,OAAO,aAAa,KAAK,MAAM,OAAO,UAAU,IAAI,SACjD,OAAO,WAAW,KAAK,MAAM,OAAO,QAAQ,IAAI,MACrD;AAKD,QAAO;EAAE;EAAO;EAAM;EAAU,WAJd,OAAO,WAAW,eAC/B,OAAO,WAAW,kBAClB,OAAO,WAAW,WAClB,KAAK,MAAM,SAAS,IAAI;EACc;EAAS;;AAGtD,SAAgB,sBAAsB,QAAsB,QAAQ,KAAK,KAAK,EAAgB;CAC5F,MAAM,YAAY,uBAAuB,QAAQ,MAAM;AACvD,KAAI,UAAU,WAAW,OAAO,WAAW,SAAU,QAAO;AAC5D,KAAI,UAAU,aAAa,OAAO,WAAW,SAAU,QAAO;AAC9D,QAAO,OAAO,UAAU"}
@@ -0,0 +1,3 @@
1
+ import type { MemoryRecord } from './types.js';
2
+ export type MemoryContextOrigin = 'told_by_user' | 'observed' | 'inferred' | 'connected_source';
3
+ export declare function classifyMemoryContextOrigin(record: MemoryRecord): MemoryContextOrigin;
@@ -0,0 +1,19 @@
1
+ //#region src/agent/memory/source-origin.ts
2
+ const INTERNAL_MEMORY_PROVIDERS = new Set([
3
+ "local",
4
+ "builtin",
5
+ "user-understanding",
6
+ "dreaming",
7
+ "workflow-run"
8
+ ]);
9
+ function classifyMemoryContextOrigin(record) {
10
+ const provider = record.source.provider?.trim().toLowerCase();
11
+ if (provider && !INTERNAL_MEMORY_PROVIDERS.has(provider)) return "connected_source";
12
+ if (record.explicitness === "explicit") return "told_by_user";
13
+ if (record.explicitness === "observed") return "observed";
14
+ return "inferred";
15
+ }
16
+ //#endregion
17
+ export { classifyMemoryContextOrigin };
18
+
19
+ //# sourceMappingURL=source-origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-origin.js","names":[],"sources":["../../../../src/agent/memory/source-origin.ts"],"sourcesContent":["import type { MemoryRecord } from './types.js';\n\nexport type MemoryContextOrigin = 'told_by_user' | 'observed' | 'inferred' | 'connected_source';\n\nconst INTERNAL_MEMORY_PROVIDERS = new Set([\n 'local',\n 'builtin',\n 'user-understanding',\n 'dreaming',\n 'workflow-run',\n]);\n\nexport function classifyMemoryContextOrigin(record: MemoryRecord): MemoryContextOrigin {\n const provider = record.source.provider?.trim().toLowerCase();\n if (provider && !INTERNAL_MEMORY_PROVIDERS.has(provider)) return 'connected_source';\n if (record.explicitness === 'explicit') return 'told_by_user';\n if (record.explicitness === 'observed') return 'observed';\n return 'inferred';\n}\n"],"mappings":";AAIA,MAAM,4BAA4B,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAgB,4BAA4B,QAA2C;CACrF,MAAM,WAAW,OAAO,OAAO,UAAU,MAAM,CAAC,aAAa;AAC7D,KAAI,YAAY,CAAC,0BAA0B,IAAI,SAAS,CAAE,QAAO;AACjE,KAAI,OAAO,iBAAiB,WAAY,QAAO;AAC/C,KAAI,OAAO,iBAAiB,WAAY,QAAO;AAC/C,QAAO"}
@@ -3,6 +3,7 @@ import { init_logger } from "../../../utils/logger.js";
3
3
  import { appendMemoryTraceEvent } from "../../../storage/sqlite/memory-records-repository.js";
4
4
  import { attachMemoryEvidence, upsertKnowledgeSourceItems } from "../../../storage/sqlite/knowledge-repository.js";
5
5
  import "../../../storage/sqlite/index.js";
6
+ import { nextMemoryReviewAt } from "../lifecycle.js";
6
7
  import { extractExplicitUnderstandingCorrectionContent } from "./correction.js";
7
8
  import { inferMemorySensitivity, redactSensitiveMemoryText } from "../sensitivity.js";
8
9
  import { createHash } from "node:crypto";
@@ -172,6 +173,10 @@ var UserUnderstandingService = class {
172
173
  evidence: [evidence],
173
174
  validFrom: candidate.validFrom,
174
175
  validTo: candidate.validTo,
176
+ reviewAfter: nextMemoryReviewAt({
177
+ durability: candidate.durability,
178
+ explicitness: candidate.explicitness
179
+ }),
175
180
  supersedesRecordId
176
181
  });
177
182
  if (write.success) {
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":[],"sources":["../../../../../src/agent/memory/understanding/service.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nimport {\n appendMemoryTraceEvent,\n attachMemoryEvidence,\n upsertKnowledgeSourceItems,\n} from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport type {\n MemoryEvidence,\n MemoryKind,\n MemoryRecord,\n MemorySensitivity,\n MemoryWriteRequest,\n MemoryWriteResult,\n} from '../types.js';\nimport { extractExplicitUnderstandingCorrectionContent } from './correction.js';\nimport type { UnderstandingCandidate, UnderstandingReviewResult } from './types.js';\nimport { inferMemorySensitivity, redactSensitiveMemoryText } from '../sensitivity.js';\n\nconst log = createLogger('UserUnderstanding');\nconst MAX_CANDIDATE_CHARS = 600;\n\nconst EXPLICIT_PATTERNS: RegExp[] = [\n /\\b(?:please\\s+)?remember(?:\\s+that)?\\s+(.+)/i,\n /\\bkeep\\s+in\\s+mind(?:\\s+that)?\\s+(.+)/i,\n /(?:请)?记住[::\\s]*(.+)/,\n /以后(?:都)?(?:请)?[::\\s]*(.+)/,\n /下次(?:请)?[::\\s]*(.+)/,\n];\n\nfunction normalizeContent(raw: string): string {\n return raw\n .replace(/^[\"'“”‘’\\s]+|[\"'“”‘’\\s]+$/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, MAX_CANDIDATE_CHARS);\n}\n\nfunction inferKind(content: string): MemoryKind {\n if (/\\b(don't|do not|never|avoid)\\b/i.test(content) || /不要|别再|禁止|底线/.test(content)) {\n return 'boundary';\n }\n if (/\\b(prefer|preference|like)\\b/i.test(content) || /喜欢|偏好|习惯/.test(content)) {\n return 'preference';\n }\n if (/\\b(tool|command|pnpm|npm|git|ripgrep|rg)\\b/i.test(content) || /工具|命令/.test(content)) {\n return 'tool_preference';\n }\n if (/\\b(project|repo|codebase|workspace)\\b/i.test(content) || /项目|仓库|代码库/.test(content)) {\n return 'project_context';\n }\n if (/\\b(goal|plan|commit|deadline)\\b/i.test(content) || /目标|计划|承诺|截止/.test(content)) {\n return 'commitment';\n }\n if (/\\b(next time|lesson|failed|error)\\b/i.test(content) || /下次|教训|失败|错误/.test(content)) {\n return 'task_lesson';\n }\n return 'agent_note';\n}\n\nconst SENSITIVITY_RANK: Record<MemorySensitivity, number> = {\n normal: 0,\n personal: 1,\n regulated: 2,\n secret: 3,\n};\n\nfunction stricterSensitivity(content: string, declared: MemorySensitivity): MemorySensitivity {\n const inferred = inferMemorySensitivity(content);\n return SENSITIVITY_RANK[inferred] > SENSITIVITY_RANK[declared] ? inferred : declared;\n}\n\nfunction canonicalKey(kind: MemoryKind, content: string): string {\n const normalized = content\n .toLocaleLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .trim();\n return `${kind}:${createHash('sha256').update(normalized).digest('hex').slice(0, 20)}`;\n}\n\nexport function extractExplicitUnderstandingCandidates(userContent: string): UnderstandingCandidate[] {\n const correction = extractExplicitUnderstandingCorrectionContent(userContent);\n if (correction) {\n const kind = inferKind(correction);\n return [{\n kind,\n content: correction,\n canonicalKey: canonicalKey(kind, correction),\n confidence: 0.95,\n importance: kind === 'boundary' ? 0.9 : 0.8,\n explicitness: 'explicit',\n durability: 'durable',\n sensitivity: inferMemorySensitivity(correction),\n disclosurePolicy: kind === 'boundary' ? 'silent' : 'referenceable',\n tags: ['user-understanding', 'explicit-user-correction'],\n }];\n }\n const lines = userContent.split(/\\r?\\n/).map((line) => line.trim()).filter(Boolean);\n for (const line of lines.length > 0 ? lines : [userContent.trim()]) {\n for (const pattern of EXPLICIT_PATTERNS) {\n const content = normalizeContent(pattern.exec(line)?.[1] ?? '');\n if (content.length < 8) continue;\n const kind = inferKind(content);\n return [{\n kind,\n content,\n canonicalKey: canonicalKey(kind, content),\n confidence: 0.92,\n importance: kind === 'boundary' ? 0.9 : 0.75,\n explicitness: 'explicit',\n durability: 'durable',\n sensitivity: inferMemorySensitivity(content),\n disclosurePolicy: kind === 'boundary' ? 'silent' : 'referenceable',\n tags: ['user-understanding', 'explicit-user-request'],\n }];\n }\n }\n return [];\n}\n\nexport interface UserUnderstandingServiceOptions {\n write: (request: MemoryWriteRequest) => Promise<MemoryWriteResult>;\n list: (canonicalKey: string) => Promise<MemoryRecord[]>;\n}\n\nexport class UserUnderstandingService {\n constructor(private readonly options: UserUnderstandingServiceOptions) {}\n\n async reviewTurn(params: {\n agentId?: string;\n userContent: string;\n assistantContent: string;\n sessionKey?: string;\n correctionTargetRecordIds?: string[];\n }): Promise<UnderstandingReviewResult> {\n const candidates = extractExplicitUnderstandingCandidates(params.userContent);\n const sourceText = `User:\\n${params.userContent.trim()}\\n\\nAssistant:\\n${params.assistantContent.trim()}`;\n const normalizedText = redactSensitiveMemoryText(sourceText);\n const contentHash = createHash('sha256').update(sourceText).digest('hex');\n const stored = upsertKnowledgeSourceItems([{\n sourceInstanceId: params.sessionKey ? `session:${params.sessionKey}` : 'session:unknown',\n externalId: contentHash,\n itemType: 'conversation_turn',\n authorRole: 'user',\n occurredAt: new Date().toISOString(),\n contentHash,\n normalizedText,\n metadata: params.sessionKey ? { sessionKey: params.sessionKey } : {},\n sensitivity: 'personal',\n retentionClass: 'bounded',\n synthesisStatus: 'pending',\n }]);\n const sourceItemId = stored.items[0]?.id;\n const result = await this.applyCandidates(candidates, {\n agentId: params.agentId,\n sessionKey: params.sessionKey,\n sourceItemId,\n sourceText: params.userContent,\n reviewSource: 'turn',\n supersedesRecordIds: params.correctionTargetRecordIds,\n });\n return { ...result, sourceItemId };\n }\n\n async applyCandidates(\n candidates: UnderstandingCandidate[],\n context: {\n agentId?: string;\n sessionKey?: string;\n sourceItemId?: string;\n sourceText?: string;\n reviewSource?: 'turn' | 'background';\n supersedesRecordIds?: string[];\n },\n ): Promise<Omit<UnderstandingReviewResult, 'sourceItemId'>> {\n const startedAt = Date.now();\n let created = 0;\n let deduplicated = 0;\n let rejected = 0;\n const recordIds: string[] = [];\n for (const candidate of candidates.slice(0, 10)) {\n const content = normalizeContent(candidate.content);\n const sensitivity = stricterSensitivity(content, candidate.sensitivity);\n if (\n content.length < 4\n || candidate.confidence < 0.55\n || sensitivity === 'secret'\n || sensitivity === 'regulated'\n ) {\n rejected += 1;\n continue;\n }\n const evidenceText = context.sourceText\n ? redactSensitiveMemoryText(context.sourceText).slice(0, MAX_CANDIDATE_CHARS)\n : undefined;\n const key = candidate.canonicalKey ?? canonicalKey(candidate.kind, content);\n const supersedesRecordId = context.supersedesRecordIds\n && [...new Set(context.supersedesRecordIds)].length === 1\n ? context.supersedesRecordIds[0]\n : undefined;\n const existing = await this.options.list(key);\n const evidence: MemoryEvidence = {\n ...(context.sourceItemId ? { sourceItemId: context.sourceItemId } : {}),\n relation: 'supports',\n ...(context.sessionKey ? { sessionKey: context.sessionKey } : {}),\n ...(evidenceText ? { sourceText: evidenceText } : {}),\n observedAt: new Date().toISOString(),\n confidence: candidate.confidence,\n };\n if (existing[0]) {\n deduplicated += 1;\n recordIds.push(existing[0].id);\n if (context.sourceItemId) {\n attachMemoryEvidence({\n recordId: existing[0].id,\n sourceItemId: context.sourceItemId,\n relation: 'supports',\n excerpt: evidenceText,\n confidence: candidate.confidence,\n });\n }\n continue;\n }\n const write = await this.options.write({\n kind: candidate.kind,\n content,\n canonicalKey: key,\n scope: context.agentId || context.sessionKey\n ? { agentId: context.agentId, sessionKey: context.sessionKey }\n : undefined,\n target: candidate.kind === 'preference' ? 'user' : 'memory',\n tags: [...new Set(['user-understanding', ...(candidate.tags ?? [])])],\n source: { provider: 'user-understanding' },\n confidence: candidate.confidence,\n status: 'candidate',\n sensitivity,\n explicitness: candidate.explicitness,\n durability: candidate.durability,\n importance: candidate.importance,\n disclosurePolicy: candidate.disclosurePolicy,\n evidence: [evidence],\n validFrom: candidate.validFrom,\n validTo: candidate.validTo,\n supersedesRecordId,\n });\n if (write.success) {\n created += 1;\n if (write.record) recordIds.push(write.record.id);\n if (write.record && context.sourceItemId) {\n attachMemoryEvidence({\n recordId: write.record.id,\n sourceItemId: context.sourceItemId,\n relation: 'supports',\n excerpt: evidenceText,\n confidence: candidate.confidence,\n });\n }\n } else {\n rejected += 1;\n log.debug({ errorMessage: write.error, canonicalKey: key }, 'Understanding candidate was not stored');\n }\n }\n try {\n appendMemoryTraceEvent({\n sessionKey: context.sessionKey,\n phase: 'understanding',\n providerId: 'user-understanding',\n request: {\n ...(context.agentId ? { agentId: context.agentId } : {}),\n source: context.reviewSource ?? 'turn',\n proposed: candidates.length,\n created,\n deduplicated,\n rejected,\n },\n resultCount: created,\n selectedRecordIds: recordIds,\n durationMs: Date.now() - startedAt,\n });\n } catch (err) {\n log.debug({ err, sessionKey: context.sessionKey }, 'Understanding quality trace append failed');\n }\n return { proposed: candidates.length, created, deduplicated, rejected };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service.js","names":[],"sources":["../../../../../src/agent/memory/understanding/service.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\n\nimport {\n appendMemoryTraceEvent,\n attachMemoryEvidence,\n upsertKnowledgeSourceItems,\n} from '../../../storage/sqlite/index.js';\nimport { createLogger } from '../../../utils/logger.js';\nimport type {\n MemoryEvidence,\n MemoryKind,\n MemoryRecord,\n MemorySensitivity,\n MemoryWriteRequest,\n MemoryWriteResult,\n} from '../types.js';\nimport { nextMemoryReviewAt } from '../lifecycle.js';\nimport { extractExplicitUnderstandingCorrectionContent } from './correction.js';\nimport type { UnderstandingCandidate, UnderstandingReviewResult } from './types.js';\nimport { inferMemorySensitivity, redactSensitiveMemoryText } from '../sensitivity.js';\n\nconst log = createLogger('UserUnderstanding');\nconst MAX_CANDIDATE_CHARS = 600;\n\nconst EXPLICIT_PATTERNS: RegExp[] = [\n /\\b(?:please\\s+)?remember(?:\\s+that)?\\s+(.+)/i,\n /\\bkeep\\s+in\\s+mind(?:\\s+that)?\\s+(.+)/i,\n /(?:请)?记住[::\\s]*(.+)/,\n /以后(?:都)?(?:请)?[::\\s]*(.+)/,\n /下次(?:请)?[::\\s]*(.+)/,\n];\n\nfunction normalizeContent(raw: string): string {\n return raw\n .replace(/^[\"'“”‘’\\s]+|[\"'“”‘’\\s]+$/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n .slice(0, MAX_CANDIDATE_CHARS);\n}\n\nfunction inferKind(content: string): MemoryKind {\n if (/\\b(don't|do not|never|avoid)\\b/i.test(content) || /不要|别再|禁止|底线/.test(content)) {\n return 'boundary';\n }\n if (/\\b(prefer|preference|like)\\b/i.test(content) || /喜欢|偏好|习惯/.test(content)) {\n return 'preference';\n }\n if (/\\b(tool|command|pnpm|npm|git|ripgrep|rg)\\b/i.test(content) || /工具|命令/.test(content)) {\n return 'tool_preference';\n }\n if (/\\b(project|repo|codebase|workspace)\\b/i.test(content) || /项目|仓库|代码库/.test(content)) {\n return 'project_context';\n }\n if (/\\b(goal|plan|commit|deadline)\\b/i.test(content) || /目标|计划|承诺|截止/.test(content)) {\n return 'commitment';\n }\n if (/\\b(next time|lesson|failed|error)\\b/i.test(content) || /下次|教训|失败|错误/.test(content)) {\n return 'task_lesson';\n }\n return 'agent_note';\n}\n\nconst SENSITIVITY_RANK: Record<MemorySensitivity, number> = {\n normal: 0,\n personal: 1,\n regulated: 2,\n secret: 3,\n};\n\nfunction stricterSensitivity(content: string, declared: MemorySensitivity): MemorySensitivity {\n const inferred = inferMemorySensitivity(content);\n return SENSITIVITY_RANK[inferred] > SENSITIVITY_RANK[declared] ? inferred : declared;\n}\n\nfunction canonicalKey(kind: MemoryKind, content: string): string {\n const normalized = content\n .toLocaleLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .trim();\n return `${kind}:${createHash('sha256').update(normalized).digest('hex').slice(0, 20)}`;\n}\n\nexport function extractExplicitUnderstandingCandidates(userContent: string): UnderstandingCandidate[] {\n const correction = extractExplicitUnderstandingCorrectionContent(userContent);\n if (correction) {\n const kind = inferKind(correction);\n return [{\n kind,\n content: correction,\n canonicalKey: canonicalKey(kind, correction),\n confidence: 0.95,\n importance: kind === 'boundary' ? 0.9 : 0.8,\n explicitness: 'explicit',\n durability: 'durable',\n sensitivity: inferMemorySensitivity(correction),\n disclosurePolicy: kind === 'boundary' ? 'silent' : 'referenceable',\n tags: ['user-understanding', 'explicit-user-correction'],\n }];\n }\n const lines = userContent.split(/\\r?\\n/).map((line) => line.trim()).filter(Boolean);\n for (const line of lines.length > 0 ? lines : [userContent.trim()]) {\n for (const pattern of EXPLICIT_PATTERNS) {\n const content = normalizeContent(pattern.exec(line)?.[1] ?? '');\n if (content.length < 8) continue;\n const kind = inferKind(content);\n return [{\n kind,\n content,\n canonicalKey: canonicalKey(kind, content),\n confidence: 0.92,\n importance: kind === 'boundary' ? 0.9 : 0.75,\n explicitness: 'explicit',\n durability: 'durable',\n sensitivity: inferMemorySensitivity(content),\n disclosurePolicy: kind === 'boundary' ? 'silent' : 'referenceable',\n tags: ['user-understanding', 'explicit-user-request'],\n }];\n }\n }\n return [];\n}\n\nexport interface UserUnderstandingServiceOptions {\n write: (request: MemoryWriteRequest) => Promise<MemoryWriteResult>;\n list: (canonicalKey: string) => Promise<MemoryRecord[]>;\n}\n\nexport class UserUnderstandingService {\n constructor(private readonly options: UserUnderstandingServiceOptions) {}\n\n async reviewTurn(params: {\n agentId?: string;\n userContent: string;\n assistantContent: string;\n sessionKey?: string;\n correctionTargetRecordIds?: string[];\n }): Promise<UnderstandingReviewResult> {\n const candidates = extractExplicitUnderstandingCandidates(params.userContent);\n const sourceText = `User:\\n${params.userContent.trim()}\\n\\nAssistant:\\n${params.assistantContent.trim()}`;\n const normalizedText = redactSensitiveMemoryText(sourceText);\n const contentHash = createHash('sha256').update(sourceText).digest('hex');\n const stored = upsertKnowledgeSourceItems([{\n sourceInstanceId: params.sessionKey ? `session:${params.sessionKey}` : 'session:unknown',\n externalId: contentHash,\n itemType: 'conversation_turn',\n authorRole: 'user',\n occurredAt: new Date().toISOString(),\n contentHash,\n normalizedText,\n metadata: params.sessionKey ? { sessionKey: params.sessionKey } : {},\n sensitivity: 'personal',\n retentionClass: 'bounded',\n synthesisStatus: 'pending',\n }]);\n const sourceItemId = stored.items[0]?.id;\n const result = await this.applyCandidates(candidates, {\n agentId: params.agentId,\n sessionKey: params.sessionKey,\n sourceItemId,\n sourceText: params.userContent,\n reviewSource: 'turn',\n supersedesRecordIds: params.correctionTargetRecordIds,\n });\n return { ...result, sourceItemId };\n }\n\n async applyCandidates(\n candidates: UnderstandingCandidate[],\n context: {\n agentId?: string;\n sessionKey?: string;\n sourceItemId?: string;\n sourceText?: string;\n reviewSource?: 'turn' | 'background';\n supersedesRecordIds?: string[];\n },\n ): Promise<Omit<UnderstandingReviewResult, 'sourceItemId'>> {\n const startedAt = Date.now();\n let created = 0;\n let deduplicated = 0;\n let rejected = 0;\n const recordIds: string[] = [];\n for (const candidate of candidates.slice(0, 10)) {\n const content = normalizeContent(candidate.content);\n const sensitivity = stricterSensitivity(content, candidate.sensitivity);\n if (\n content.length < 4\n || candidate.confidence < 0.55\n || sensitivity === 'secret'\n || sensitivity === 'regulated'\n ) {\n rejected += 1;\n continue;\n }\n const evidenceText = context.sourceText\n ? redactSensitiveMemoryText(context.sourceText).slice(0, MAX_CANDIDATE_CHARS)\n : undefined;\n const key = candidate.canonicalKey ?? canonicalKey(candidate.kind, content);\n const supersedesRecordId = context.supersedesRecordIds\n && [...new Set(context.supersedesRecordIds)].length === 1\n ? context.supersedesRecordIds[0]\n : undefined;\n const existing = await this.options.list(key);\n const evidence: MemoryEvidence = {\n ...(context.sourceItemId ? { sourceItemId: context.sourceItemId } : {}),\n relation: 'supports',\n ...(context.sessionKey ? { sessionKey: context.sessionKey } : {}),\n ...(evidenceText ? { sourceText: evidenceText } : {}),\n observedAt: new Date().toISOString(),\n confidence: candidate.confidence,\n };\n if (existing[0]) {\n deduplicated += 1;\n recordIds.push(existing[0].id);\n if (context.sourceItemId) {\n attachMemoryEvidence({\n recordId: existing[0].id,\n sourceItemId: context.sourceItemId,\n relation: 'supports',\n excerpt: evidenceText,\n confidence: candidate.confidence,\n });\n }\n continue;\n }\n const write = await this.options.write({\n kind: candidate.kind,\n content,\n canonicalKey: key,\n scope: context.agentId || context.sessionKey\n ? { agentId: context.agentId, sessionKey: context.sessionKey }\n : undefined,\n target: candidate.kind === 'preference' ? 'user' : 'memory',\n tags: [...new Set(['user-understanding', ...(candidate.tags ?? [])])],\n source: { provider: 'user-understanding' },\n confidence: candidate.confidence,\n status: 'candidate',\n sensitivity,\n explicitness: candidate.explicitness,\n durability: candidate.durability,\n importance: candidate.importance,\n disclosurePolicy: candidate.disclosurePolicy,\n evidence: [evidence],\n validFrom: candidate.validFrom,\n validTo: candidate.validTo,\n reviewAfter: nextMemoryReviewAt({\n durability: candidate.durability,\n explicitness: candidate.explicitness,\n }),\n supersedesRecordId,\n });\n if (write.success) {\n created += 1;\n if (write.record) recordIds.push(write.record.id);\n if (write.record && context.sourceItemId) {\n attachMemoryEvidence({\n recordId: write.record.id,\n sourceItemId: context.sourceItemId,\n relation: 'supports',\n excerpt: evidenceText,\n confidence: candidate.confidence,\n });\n }\n } else {\n rejected += 1;\n log.debug({ errorMessage: write.error, canonicalKey: key }, 'Understanding candidate was not stored');\n }\n }\n try {\n appendMemoryTraceEvent({\n sessionKey: context.sessionKey,\n phase: 'understanding',\n providerId: 'user-understanding',\n request: {\n ...(context.agentId ? { agentId: context.agentId } : {}),\n source: context.reviewSource ?? 'turn',\n proposed: candidates.length,\n created,\n deduplicated,\n rejected,\n },\n resultCount: created,\n selectedRecordIds: recordIds,\n durationMs: Date.now() - startedAt,\n });\n } catch (err) {\n log.debug({ err, sessionKey: context.sessionKey }, 'Understanding quality trace append failed');\n }\n return { proposed: candidates.length, created, deduplicated, rejected };\n }\n}\n"],"mappings":"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"}
@@ -36,6 +36,7 @@ var UserContextCoordinator = class {
36
36
  if (!this.options.isEnabledForSession(sessionKey)) return empty();
37
37
  const query = extractAgentUserPlainText(userMessage);
38
38
  this.correctionTargets.delete(sessionKey);
39
+ let excludedRecordIds;
39
40
  if (isExplicitUnderstandingCorrection(query)) try {
40
41
  const trace = setLatestMemoryInjectFeedback({
41
42
  sessionKey,
@@ -46,7 +47,10 @@ var UserContextCoordinator = class {
46
47
  reason: "detected_explicit_user_correction"
47
48
  }
48
49
  });
49
- if (trace?.selectedRecordIds.length) this.correctionTargets.set(sessionKey, trace.selectedRecordIds);
50
+ if (trace?.selectedRecordIds.length) {
51
+ this.correctionTargets.set(sessionKey, trace.selectedRecordIds);
52
+ excludedRecordIds = trace.selectedRecordIds;
53
+ }
50
54
  } catch (err) {
51
55
  log.debug({
52
56
  err,
@@ -61,7 +65,8 @@ var UserContextCoordinator = class {
61
65
  agentId: this.options.getAgentIdForSession(sessionKey),
62
66
  sessionKey,
63
67
  query,
64
- userMessage
68
+ userMessage,
69
+ excludedRecordIds
65
70
  });
66
71
  }
67
72
  async afterTurn(sessionKey, userPlainText) {