@xopcai/xopc 0.0.123 → 0.0.125

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 (436) hide show
  1. package/README.md +28 -11
  2. package/README.zh-CN.md +28 -11
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Bicr3ZBg.js → agent-avatar-dicebear-BKDKICZV.js} +1 -1
  7. package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +2 -0
  8. package/dist/gateway/static/root/assets/app-management-settings-panel-DI4BqHKW.js +1 -0
  9. package/dist/gateway/static/root/assets/appearance-settings-6_ie3NQ4.js +1 -0
  10. package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-Bpy64GjU.js → archive-plugin-kUHEJ1HK.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-DMkp4xSb.js → attachment-load-Dm-9prpU.js} +1 -1
  13. package/dist/gateway/static/root/assets/automation-suggestion-card-OTxQTPnC.js +1 -0
  14. package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +1 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-DA9C5mCw.js → binary-plugins-DllA_jQ0.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-CiSXk_YC.js → block-editor-Cm6CWNj1.js} +5 -5
  17. package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +8 -0
  18. package/dist/gateway/static/root/assets/capability-presets-api-VJ89b6I2.js +1 -0
  19. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BaPj8wC2.js +1 -0
  20. package/dist/gateway/static/root/assets/{channel-recipient-api-CDhrhfhN.js → channel-recipient-api-B5PwBEUx.js} +1 -1
  21. package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +1 -0
  22. package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
  23. package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +2 -0
  24. package/dist/gateway/static/root/assets/{directory-picker-path-field-7jKfbH0J.js → directory-picker-path-field-DySMzOF6.js} +1 -1
  25. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  26. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  27. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  28. package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +3 -0
  29. package/dist/gateway/static/root/assets/extension-debug-page-BaM0FpW7.js +1 -0
  30. package/dist/gateway/static/root/assets/extension-page-DuZWVOGA.js +1 -0
  31. package/dist/gateway/static/root/assets/extension-settings-page-DarVtbmJ.js +1 -0
  32. package/dist/gateway/static/root/assets/{fetch-Dtpbbe0s.js → fetch-NFKfkqrd.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-config-api-BN6pyX2c.js → gateway-config-api-CFEm9rgy.js} +1 -1
  34. package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +1 -0
  35. package/dist/gateway/static/root/assets/{gateway-startup-retry-BIET2x3y.js → gateway-startup-retry-Dtwh_yGg.js} +1 -1
  36. package/dist/gateway/static/root/assets/goal-create-dialog-BKP7ylcG.js +1 -0
  37. package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +1 -0
  38. package/dist/gateway/static/root/assets/{goals-config-api-CQm2r1Ty.js → goals-config-api-DTWZNA_Y.js} +1 -1
  39. package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +2 -0
  40. package/dist/gateway/static/root/assets/goals-settings-Bhct0ZT-.js +1 -0
  41. package/dist/gateway/static/root/assets/heartbeat-settings-C-UxSU4a.js +1 -0
  42. package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
  43. package/dist/gateway/static/root/assets/index-BNHDd2j1.css +1 -0
  44. package/dist/gateway/static/root/assets/index-BPXLPMuY.js +193 -0
  45. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-DCjy2y4d.js +1 -0
  46. package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +2 -0
  47. package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
  48. package/dist/gateway/static/root/assets/markdown-split-BaqxP-GQ.js +1 -0
  49. package/dist/gateway/static/root/assets/{media-plugins-DS44pJzr.js → media-plugins-DQ_EXloK.js} +1 -1
  50. package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +3 -0
  51. package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +2 -0
  52. package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +1 -0
  53. package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +2 -0
  54. package/dist/gateway/static/root/assets/page-tabs-EIZhLppK.js +1 -0
  55. package/dist/gateway/static/root/assets/{preview-open-alternatives-Dej6zHnr.js → preview-open-alternatives-r_uB4Epr.js} +1 -1
  56. package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +1 -0
  57. package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +1 -0
  58. package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +1 -0
  59. package/dist/gateway/static/root/assets/{save-bar-controls-Zu1FzH6z.js → save-bar-controls-B132Uf-2.js} +1 -1
  60. package/dist/gateway/static/root/assets/{schedule-field-BW78mKc0.js → schedule-field-B5qshALm.js} +1 -1
  61. package/dist/gateway/static/root/assets/{schema-form-Cc-IOydE.js → schema-form-CvLmkdS9.js} +1 -1
  62. package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +1 -0
  63. package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +1 -0
  64. package/dist/gateway/static/root/assets/{settings-collapsible-section-DIpIYht_.js → settings-collapsible-section-pRlvqsAf.js} +1 -1
  65. package/dist/gateway/static/root/assets/{settings-form-section-BFxBNxOG.js → settings-form-section-BBYUDLVd.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-page-C4fivemT.js → settings-page-DaO7zYZM.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-page-layout-CLx4o2PN.js → settings-page-layout-D8g9PAek.js} +1 -1
  68. package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +1 -0
  69. package/dist/gateway/static/root/assets/{share-preview-page-ZswWCrDu.js → share-preview-page-v6-IOp8t.js} +1 -1
  70. package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +1 -0
  71. package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +1 -0
  72. package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +2 -0
  73. package/dist/gateway/static/root/assets/{system-settings-panel-3ZNcGRhS.js → system-settings-panel-HUU2FFjM.js} +1 -1
  74. package/dist/gateway/static/root/assets/{typed-models-lib-bpzZjiVF.js → typed-models-lib-AH160QHh.js} +1 -1
  75. package/dist/gateway/static/root/assets/{use-channel-catalog-BCjZLZ3O.js → use-channel-catalog-BXzDmjCQ.js} +1 -1
  76. package/dist/gateway/static/root/assets/{user-profile-settings-panel-CIXafITi.js → user-profile-settings-panel-DxwnQvQ3.js} +1 -1
  77. package/dist/gateway/static/root/assets/{utils-DXMtz5j_.js → utils-i5POEtqd.js} +1 -1
  78. package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
  79. package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +1 -0
  80. package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +1 -0
  81. package/dist/gateway/static/root/assets/workflow-run-setup-panel-ClVVMgN-.js +3 -0
  82. package/dist/gateway/static/root/assets/{workflow-start-dialog-B4sZpTDQ.js → workflow-start-dialog-Dv4ZA1T0.js} +1 -1
  83. package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +18 -0
  84. package/dist/gateway/static/root/index.html +8 -7
  85. package/dist/package.js +1 -1
  86. package/dist/src/agent/agent-manager.d.ts +6 -1
  87. package/dist/src/agent/agent-manager.js +34 -14
  88. package/dist/src/agent/agent-manager.js.map +1 -1
  89. package/dist/src/agent/child-agent-factory.d.ts +2 -0
  90. package/dist/src/agent/child-agent-factory.js +2 -0
  91. package/dist/src/agent/child-agent-factory.js.map +1 -1
  92. package/dist/src/agent/coding/index.d.ts +1 -0
  93. package/dist/src/agent/coding/index.js +2 -0
  94. package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
  95. package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
  96. package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
  97. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  98. package/dist/src/agent/embedded/xopc-tools-bridge.js +11 -7
  99. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  100. package/dist/src/agent/lifecycle/progress.js +3 -1
  101. package/dist/src/agent/lifecycle/progress.js.map +1 -1
  102. package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +2 -2
  103. package/dist/src/agent/lifecycle/timeout-wrapper.js +4 -4
  104. package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
  105. package/dist/src/agent/memory/dreaming/config.d.ts +2 -2
  106. package/dist/src/agent/memory/dreaming/config.js +3 -3
  107. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  108. package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
  109. package/dist/src/agent/memory/dreaming/constants.js +1 -1
  110. package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
  111. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
  112. package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
  113. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  114. package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
  115. package/dist/src/agent/memory/dreaming/events.js +6 -6
  116. package/dist/src/agent/memory/dreaming/events.js.map +1 -1
  117. package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
  118. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  119. package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
  120. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
  121. package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
  122. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  123. package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
  124. package/dist/src/agent/memory/dreaming/preview.js +2 -2
  125. package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
  126. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  127. package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
  128. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  129. package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
  130. package/dist/src/agent/memory/dreaming/scope.js +27 -0
  131. package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
  132. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
  133. package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
  134. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  135. package/dist/src/agent/memory/summary-generator.d.ts +1 -1
  136. package/dist/src/agent/memory/summary-generator.js +1 -2
  137. package/dist/src/agent/memory/summary-generator.js.map +1 -1
  138. package/dist/src/agent/middleware/index.d.ts +1 -1
  139. package/dist/src/agent/middleware/self-verify.d.ts +44 -14
  140. package/dist/src/agent/middleware/self-verify.js +214 -44
  141. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  142. package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
  143. package/dist/src/agent/orchestration/agent-event-handler.js +69 -14
  144. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  145. package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
  146. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  147. package/dist/src/agent/prompt/sections/tooling.js +18 -13
  148. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  149. package/dist/src/agent/prompt/system-reminder.js +2 -2
  150. package/dist/src/agent/prompt/system-reminder.js.map +1 -1
  151. package/dist/src/agent/sandbox/command-validator.js +12 -0
  152. package/dist/src/agent/sandbox/command-validator.js.map +1 -1
  153. package/dist/src/agent/sandbox/sanitize-env-vars.d.ts +2 -2
  154. package/dist/src/agent/sandbox/sanitize-env-vars.js +2 -2
  155. package/dist/src/agent/sandbox/sanitize-env-vars.js.map +1 -1
  156. package/dist/src/agent/sandbox/types.d.ts +2 -2
  157. package/dist/src/agent/sandbox/types.js.map +1 -1
  158. package/dist/src/agent/service/btw-query.js +1 -1
  159. package/dist/src/agent/service/btw-query.js.map +1 -1
  160. package/dist/src/agent/service/process-direct-one-shot.js +6 -2
  161. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  162. package/dist/src/agent/service/process-direct-streaming.js +12 -7
  163. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  164. package/dist/src/agent/service.d.ts +2 -1
  165. package/dist/src/agent/service.js +19 -6
  166. package/dist/src/agent/service.js.map +1 -1
  167. package/dist/src/agent/session/session-inspector.d.ts +5 -3
  168. package/dist/src/agent/session/session-inspector.js +16 -7
  169. package/dist/src/agent/session/session-inspector.js.map +1 -1
  170. package/dist/src/agent/skills/skill-tool-gating.js +1 -1
  171. package/dist/src/agent/skills/skill-tool-gating.js.map +1 -1
  172. package/dist/src/agent/source-context/types.d.ts +1 -1
  173. package/dist/src/agent/source-context/types.js +1 -1
  174. package/dist/src/agent/source-context/types.js.map +1 -1
  175. package/dist/src/agent/starter-agents.js +9 -9
  176. package/dist/src/agent/starter-agents.js.map +1 -1
  177. package/dist/src/agent/tools/apply-patch.d.ts +25 -0
  178. package/dist/src/agent/tools/apply-patch.js +310 -0
  179. package/dist/src/agent/tools/apply-patch.js.map +1 -0
  180. package/dist/src/agent/tools/concurrency.d.ts +8 -0
  181. package/dist/src/agent/tools/concurrency.js +31 -0
  182. package/dist/src/agent/tools/concurrency.js.map +1 -0
  183. package/dist/src/agent/tools/delegate-tool.d.ts +1 -1
  184. package/dist/src/agent/tools/delegate-tool.js +3 -3
  185. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  186. package/dist/src/agent/tools/dreaming-tool.d.ts +2 -0
  187. package/dist/src/agent/tools/dreaming-tool.js +13 -10
  188. package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
  189. package/dist/src/agent/tools/exec-command.d.ts +30 -0
  190. package/dist/src/agent/tools/exec-command.js +228 -0
  191. package/dist/src/agent/tools/exec-command.js.map +1 -0
  192. package/dist/src/agent/tools/execute-code-tool.js +7 -4
  193. package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
  194. package/dist/src/agent/tools/executor.d.ts +6 -4
  195. package/dist/src/agent/tools/executor.js +7 -4
  196. package/dist/src/agent/tools/executor.js.map +1 -1
  197. package/dist/src/agent/tools/factory.d.ts +6 -3
  198. package/dist/src/agent/tools/factory.js +14 -9
  199. package/dist/src/agent/tools/factory.js.map +1 -1
  200. package/dist/src/agent/tools/find.js +2 -0
  201. package/dist/src/agent/tools/find.js.map +1 -1
  202. package/dist/src/agent/tools/grep.js +2 -0
  203. package/dist/src/agent/tools/grep.js.map +1 -1
  204. package/dist/src/agent/tools/index.d.ts +5 -2
  205. package/dist/src/agent/tools/index.js +7 -4
  206. package/dist/src/agent/tools/list-dir.js +2 -0
  207. package/dist/src/agent/tools/list-dir.js.map +1 -1
  208. package/dist/src/agent/tools/memory-tool.d.ts +1 -0
  209. package/dist/src/agent/tools/memory-tool.js +2 -2
  210. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  211. package/dist/src/agent/tools/metadata.d.ts +15 -0
  212. package/dist/src/agent/tools/metadata.js +26 -0
  213. package/dist/src/agent/tools/metadata.js.map +1 -0
  214. package/dist/src/agent/tools/read.js +2 -0
  215. package/dist/src/agent/tools/read.js.map +1 -1
  216. package/dist/src/agent/tools/skills-tools.d.ts +1 -1
  217. package/dist/src/agent/tools/skills-tools.js.map +1 -1
  218. package/dist/src/agent/tools/update-plan-tool.d.ts +11 -0
  219. package/dist/src/agent/tools/update-plan-tool.js +72 -0
  220. package/dist/src/agent/tools/update-plan-tool.js.map +1 -0
  221. package/dist/src/agent/tools/write.js +6 -0
  222. package/dist/src/agent/tools/write.js.map +1 -1
  223. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
  224. package/dist/src/agent/workflow/builtins/debug-incident.js +1 -1
  225. package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
  226. package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
  227. package/dist/src/agent/workflow/builtins/pr-review.js +1 -1
  228. package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
  229. package/dist/src/agent/workflow/builtins/release-check.d.ts +1 -1
  230. package/dist/src/agent/workflow/builtins/release-check.js +1 -1
  231. package/dist/src/agent/workflow/builtins/release-check.js.map +1 -1
  232. package/dist/src/agent/workflow/step-labels.js +7 -3
  233. package/dist/src/agent/workflow/step-labels.js.map +1 -1
  234. package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
  235. package/dist/src/agent/workflow/subagent-runner.js +5 -1
  236. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  237. package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
  238. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  239. package/dist/src/chat-commands/agent-edit.js +1 -1
  240. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  241. package/dist/src/chat-commands/builtins/review.d.ts +1 -0
  242. package/dist/src/chat-commands/builtins/review.js +167 -0
  243. package/dist/src/chat-commands/builtins/review.js.map +1 -0
  244. package/dist/src/chat-commands/index.d.ts +1 -0
  245. package/dist/src/chat-commands/index.js +3 -1
  246. package/dist/src/chat-commands/index.js.map +1 -1
  247. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  248. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  249. package/dist/src/connectors/health.d.ts +2 -1
  250. package/dist/src/connectors/health.js +59 -1
  251. package/dist/src/connectors/health.js.map +1 -1
  252. package/dist/src/connectors/install.d.ts +1 -0
  253. package/dist/src/connectors/install.js +28 -1
  254. package/dist/src/connectors/install.js.map +1 -1
  255. package/dist/src/connectors/instances.js +7 -0
  256. package/dist/src/connectors/instances.js.map +1 -1
  257. package/dist/src/connectors/materialize.js +2 -1
  258. package/dist/src/connectors/materialize.js.map +1 -1
  259. package/dist/src/connectors/registries/modelscope.js +38 -13
  260. package/dist/src/connectors/registries/modelscope.js.map +1 -1
  261. package/dist/src/connectors/types.d.ts +2 -0
  262. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  263. package/dist/src/gateway/agent-builtin-tools.js +3 -2
  264. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  265. package/dist/src/gateway/chat-stream/mapper.d.ts +6 -0
  266. package/dist/src/gateway/chat-stream/mapper.js +149 -6
  267. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  268. package/dist/src/gateway/chat-stream/protocol.d.ts +51 -1
  269. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +1 -0
  270. package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
  271. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  272. package/dist/src/gateway/hono/app.js +7 -1
  273. package/dist/src/gateway/hono/app.js.map +1 -1
  274. package/dist/src/gateway/hono/routes/commands-skills.js +21 -0
  275. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  276. package/dist/src/gateway/hono/routes/connectors.js +46 -2
  277. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  278. package/dist/src/gateway/hono/routes/dreaming.js +111 -66
  279. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  280. package/dist/src/gateway/hono/routes/index.js +2 -0
  281. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  282. package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
  283. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  284. package/dist/src/gateway/hono/routes/projects.js +886 -45
  285. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  286. package/dist/src/gateway/hono/routes/search.d.ts +3 -0
  287. package/dist/src/gateway/hono/routes/search.js +47 -0
  288. package/dist/src/gateway/hono/routes/search.js.map +1 -0
  289. package/dist/src/gateway/hono/routes/sessions.js +1 -0
  290. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  291. package/dist/src/gateway/security/dangerous-tools.js +1 -1
  292. package/dist/src/gateway/security/dangerous-tools.js.map +1 -1
  293. package/dist/src/gateway/service.js +17 -8
  294. package/dist/src/gateway/service.js.map +1 -1
  295. package/dist/src/infra/update-restart.js +1 -1
  296. package/dist/src/mcp/channel-bridge.js +1 -1
  297. package/dist/src/media/store.js +1 -1
  298. package/dist/src/media/store.js.map +1 -1
  299. package/dist/src/media/types.d.ts +1 -1
  300. package/dist/src/media/uri.js +2 -1
  301. package/dist/src/media/uri.js.map +1 -1
  302. package/dist/src/projects/index.d.ts +2 -0
  303. package/dist/src/projects/index.js +3 -1
  304. package/dist/src/projects/project-agent-suggestion.d.ts +14 -0
  305. package/dist/src/projects/project-agent-suggestion.js +19 -0
  306. package/dist/src/projects/project-agent-suggestion.js.map +1 -0
  307. package/dist/src/projects/project-kind.d.ts +13 -0
  308. package/dist/src/projects/project-kind.js +147 -0
  309. package/dist/src/projects/project-kind.js.map +1 -0
  310. package/dist/src/projects/project-service.d.ts +1 -0
  311. package/dist/src/projects/project-service.js +1 -1
  312. package/dist/src/projects/project-service.js.map +1 -1
  313. package/dist/src/projects/project-store.js +32 -8
  314. package/dist/src/projects/project-store.js.map +1 -1
  315. package/dist/src/projects/types.d.ts +1 -0
  316. package/dist/src/review/review-git.d.ts +48 -0
  317. package/dist/src/review/review-git.js +333 -0
  318. package/dist/src/review/review-git.js.map +1 -0
  319. package/dist/src/review/review-types.d.ts +22 -0
  320. package/dist/src/review/review-types.js +29 -0
  321. package/dist/src/review/review-types.js.map +1 -0
  322. package/dist/src/session/session-context-for-llm.d.ts +2 -0
  323. package/dist/src/session/session-context-for-llm.js +165 -1
  324. package/dist/src/session/session-context-for-llm.js.map +1 -1
  325. package/dist/src/session/store.js +2 -2
  326. package/dist/src/session/store.js.map +1 -1
  327. package/dist/src/storage/sqlite/migrations/021_projects_fts.sql +21 -0
  328. package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
  329. package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -0
  330. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  331. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  332. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  333. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  334. package/dist/src/storage/sqlite/schema.js +1 -1
  335. package/dist/src/storage/sqlite/schema.sql +78 -0
  336. package/dist/src/tui/backends/embedded-backend.d.ts +1 -0
  337. package/dist/src/tui/backends/embedded-backend.js +20 -0
  338. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  339. package/dist/src/tui/backends/gateway-sse-backend.d.ts +2 -0
  340. package/dist/src/tui/backends/gateway-sse-backend.js +7 -0
  341. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  342. package/dist/src/tui/components/assistant-message.js +47 -2
  343. package/dist/src/tui/components/assistant-message.js.map +1 -1
  344. package/dist/src/tui/components/tool-execution.d.ts +8 -0
  345. package/dist/src/tui/components/tool-execution.js +87 -77
  346. package/dist/src/tui/components/tool-execution.js.map +1 -1
  347. package/dist/src/tui/components/visual-truncate.d.ts +1 -0
  348. package/dist/src/tui/components/visual-truncate.js +28 -1
  349. package/dist/src/tui/components/visual-truncate.js.map +1 -1
  350. package/dist/src/tui/tool-summary.d.ts +22 -0
  351. package/dist/src/tui/tool-summary.js +212 -0
  352. package/dist/src/tui/tool-summary.js.map +1 -0
  353. package/dist/src/tui/tui-agent-events.js +25 -0
  354. package/dist/src/tui/tui-agent-events.js.map +1 -1
  355. package/dist/src/tui/tui-backend.d.ts +4 -0
  356. package/dist/src/tui/tui-commands.d.ts +1 -0
  357. package/dist/src/tui/tui-commands.js +110 -4
  358. package/dist/src/tui/tui-commands.js.map +1 -1
  359. package/dist/src/tui/tui-picker-overlay.d.ts +2 -0
  360. package/dist/src/tui/tui-picker-overlay.js +153 -1
  361. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  362. package/dist/src/tui/tui-tool-diff.d.ts +15 -0
  363. package/dist/src/tui/tui-tool-diff.js +178 -7
  364. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  365. package/dist/src/tui/tui.js +16 -3
  366. package/dist/src/tui/tui.js.map +1 -1
  367. package/dist/src/work-items/agent-context.d.ts +3 -0
  368. package/dist/src/work-items/agent-context.js +39 -0
  369. package/dist/src/work-items/agent-context.js.map +1 -0
  370. package/dist/src/work-items/index.d.ts +4 -0
  371. package/dist/src/work-items/index.js +4 -0
  372. package/dist/src/work-items/types.d.ts +112 -0
  373. package/dist/src/work-items/types.js +1 -0
  374. package/dist/src/work-items/work-item-service.d.ts +33 -0
  375. package/dist/src/work-items/work-item-service.js +180 -0
  376. package/dist/src/work-items/work-item-service.js.map +1 -0
  377. package/dist/src/work-items/work-item-store.d.ts +21 -0
  378. package/dist/src/work-items/work-item-store.js +302 -0
  379. package/dist/src/work-items/work-item-store.js.map +1 -0
  380. package/dist/src/workflows/service/workflow-run-service.js +4 -3
  381. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  382. package/dist/src/workflows/service/workflow-session-bridge.js +3 -0
  383. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  384. package/package.json +1 -1
  385. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  386. package/dist/gateway/static/root/assets/agents-CxDSFHGx.js +0 -2
  387. package/dist/gateway/static/root/assets/app-management-settings-panel-CbEy9sR1.js +0 -1
  388. package/dist/gateway/static/root/assets/appearance-settings-CTHja6n9.js +0 -1
  389. package/dist/gateway/static/root/assets/apps-page-CyZdgqvm.js +0 -1
  390. package/dist/gateway/static/root/assets/automation-suggestion-card-KnYaP7NT.js +0 -1
  391. package/dist/gateway/static/root/assets/automations-page-8VLKM4au.js +0 -1
  392. package/dist/gateway/static/root/assets/browser-settings-page-5tPg0DcP.js +0 -8
  393. package/dist/gateway/static/root/assets/capability-presets-api-CEJ44WCU.js +0 -1
  394. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BJW3aVST.js +0 -1
  395. package/dist/gateway/static/root/assets/channels-settings-CorUCTrs.js +0 -1
  396. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
  397. package/dist/gateway/static/root/assets/connectors-page-VKstC3sP.js +0 -2
  398. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
  399. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
  400. package/dist/gateway/static/root/assets/dreaming-settings-m1-wmz4o.js +0 -1
  401. package/dist/gateway/static/root/assets/extension-debug-page-C9qQQrBS.js +0 -1
  402. package/dist/gateway/static/root/assets/extension-page-DcBBMEGl.js +0 -1
  403. package/dist/gateway/static/root/assets/extension-settings-page-BQ-jMMP9.js +0 -1
  404. package/dist/gateway/static/root/assets/gateway-settings-hQtgVmSR.js +0 -1
  405. package/dist/gateway/static/root/assets/goal-create-dialog-BuIMDx6C.js +0 -1
  406. package/dist/gateway/static/root/assets/goal-detail-page-FEypCq74.js +0 -1
  407. package/dist/gateway/static/root/assets/goals-page-C4-2_MLG.js +0 -2
  408. package/dist/gateway/static/root/assets/goals-settings-DDrdRMxB.js +0 -1
  409. package/dist/gateway/static/root/assets/heartbeat-settings-BJVok3Sl.js +0 -1
  410. package/dist/gateway/static/root/assets/index-CBDr5xjB.css +0 -1
  411. package/dist/gateway/static/root/assets/index-T0SaNd5a.js +0 -191
  412. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-C2TuQppb.js +0 -1
  413. package/dist/gateway/static/root/assets/logs-page-DwkwPgid.js +0 -2
  414. package/dist/gateway/static/root/assets/markdown-split-DhONQ81k.js +0 -1
  415. package/dist/gateway/static/root/assets/messages-avfvyZuQ.js +0 -3
  416. package/dist/gateway/static/root/assets/models-hub-panel-huNY4A1G.js +0 -2
  417. package/dist/gateway/static/root/assets/notes-page-DdfGuEZ1.js +0 -1
  418. package/dist/gateway/static/root/assets/notes-workbench-B0bT9Hqa.js +0 -2
  419. package/dist/gateway/static/root/assets/project-detail-page-CjxhPorG.js +0 -1
  420. package/dist/gateway/static/root/assets/projects-page-C4Z5OJMF.js +0 -1
  421. package/dist/gateway/static/root/assets/remote-access-hub-CVCOPUVd.js +0 -1
  422. package/dist/gateway/static/root/assets/sessions-page-B4qExXHC.js +0 -1
  423. package/dist/gateway/static/root/assets/settings-advanced-gate-Ce8yLTBi.js +0 -1
  424. package/dist/gateway/static/root/assets/setup-status-panel-Kyc4eUf0.js +0 -1
  425. package/dist/gateway/static/root/assets/shares-settings-Bu76CMiC.js +0 -1
  426. package/dist/gateway/static/root/assets/skill-reload-api-D-CFg86j.js +0 -1
  427. package/dist/gateway/static/root/assets/skills-page-CUU4f6Ss.js +0 -2
  428. package/dist/gateway/static/root/assets/voice-api-key-field-C1MrQD8R.js +0 -1
  429. package/dist/gateway/static/root/assets/workflow-run-setup-panel-DqizIcY5.js +0 -3
  430. package/dist/gateway/static/root/assets/workflows-page-B3sVNPFk.js +0 -18
  431. package/dist/src/agent/tools/edit.d.ts +0 -14
  432. package/dist/src/agent/tools/edit.js +0 -132
  433. package/dist/src/agent/tools/edit.js.map +0 -1
  434. package/dist/src/agent/tools/shell.d.ts +0 -15
  435. package/dist/src/agent/tools/shell.js +0 -158
  436. package/dist/src/agent/tools/shell.js.map +0 -1
@@ -174,6 +174,40 @@ function appendTextToToolResult(result, text) {
174
174
  }
175
175
  return result;
176
176
  }
177
+ function readRecord(value) {
178
+ return value && typeof value === "object" ? value : null;
179
+ }
180
+ function readToolResultDetails(result) {
181
+ const rec = readRecord(result);
182
+ if (!rec) return null;
183
+ return readRecord(rec.details);
184
+ }
185
+ function readStringArray(value) {
186
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
187
+ }
188
+ function readChangedPathsFromToolEnd(toolName, args, result) {
189
+ const name = toolName.toLowerCase();
190
+ const details = readToolResultDetails(result);
191
+ if (name === "apply_patch") {
192
+ const files = readStringArray(details?.files);
193
+ if (files.length > 0) return files;
194
+ return (Array.isArray(details?.changes) ? details.changes : []).flatMap((change) => {
195
+ const rec = readRecord(change);
196
+ if (!rec) return [];
197
+ return readStringArray([rec.moveTo, rec.path]);
198
+ });
199
+ }
200
+ if (name === "write_file") {
201
+ if (typeof details?.size !== "number") return [];
202
+ const rec = readRecord(args);
203
+ return typeof rec?.path === "string" ? [rec.path] : [];
204
+ }
205
+ if (name.includes("write") || name.includes("edit")) {
206
+ const rec = readRecord(args);
207
+ return typeof rec?.path === "string" ? [rec.path] : [];
208
+ }
209
+ return [];
210
+ }
177
211
  function installToolChainListener(bus, toolChainTracker) {
178
212
  bus.on("turn_start", (_event, context) => {
179
213
  toolChainTracker.startChain(context.sessionKey);
@@ -232,24 +266,44 @@ function installErrorTrackingListener(bus, deps) {
232
266
  });
233
267
  }
234
268
  function installSelfVerifyListener(bus, selfVerifyMiddleware) {
235
- bus.on("tool_execution_start", (event) => {
269
+ bus.on("tool_execution_end", (event, context) => {
236
270
  const e = event;
271
+ const name = e.toolName?.toLowerCase() ?? "";
237
272
  const args = e.args;
238
- const toolName = e.toolName;
239
- if (!toolName || !args) return;
240
- const name = toolName.toLowerCase();
241
- if (name.includes("write") && args.path) selfVerifyMiddleware.recordEdit(String(args.path), "write");
242
- else if (name.includes("edit") && args.path) selfVerifyMiddleware.recordEdit(String(args.path), "edit");
243
- else selfVerifyMiddleware.recordVerification(toolName, args);
273
+ if (name === "exec_command") {
274
+ selfVerifyMiddleware.recordVerification(e.toolName, args, {
275
+ isError: e.isError,
276
+ result: e.result
277
+ }, context.sessionKey);
278
+ return;
279
+ }
280
+ if (!e.isError) {
281
+ const changedPaths = readChangedPathsFromToolEnd(e.toolName, args, e.result);
282
+ for (const path of changedPaths) selfVerifyMiddleware.recordEdit(path, name.includes("write") ? "write" : "edit", context.sessionKey);
283
+ if (changedPaths.length > 0) {
284
+ e.result = appendTextToToolResult(e.result, selfVerifyMiddleware.consumePostEditReminder(context.sessionKey));
285
+ return;
286
+ }
287
+ selfVerifyMiddleware.recordVerification(e.toolName, args, {
288
+ isError: e.isError,
289
+ result: e.result
290
+ }, context.sessionKey);
291
+ }
244
292
  });
245
- bus.on("tool_execution_end", (event) => {
246
- const e = event;
247
- const name = e.toolName?.toLowerCase() ?? "";
248
- if (!name.includes("write") && !name.includes("edit")) return;
249
- e.result = appendTextToToolResult(e.result, selfVerifyMiddleware.consumePostEditReminder());
293
+ bus.on("turn_start", (_event, context) => {
294
+ selfVerifyMiddleware.onTurnStart(context.sessionKey);
250
295
  });
251
- bus.on("turn_start", () => {
252
- selfVerifyMiddleware.onTurnStart();
296
+ }
297
+ function installTurnDiffTrackerListener(bus, turnDiffTracker) {
298
+ bus.on("tool_execution_end", (event, context) => {
299
+ const e = event;
300
+ turnDiffTracker.recordToolResult({
301
+ sessionKey: context.sessionKey,
302
+ toolName: e.toolName,
303
+ args: e.args,
304
+ result: e.result,
305
+ isError: e.isError
306
+ });
253
307
  });
254
308
  }
255
309
  /**
@@ -270,6 +324,7 @@ var AgentEventHandler = class {
270
324
  });
271
325
  installLifecycleHookListener(this.bus, config.lifecycleManager);
272
326
  installSystemReminderListener(this.bus, config.systemReminder);
327
+ if (config.turnDiffTracker) installTurnDiffTrackerListener(this.bus, config.turnDiffTracker);
273
328
  installSelfVerifyListener(this.bus, config.selfVerifyMiddleware);
274
329
  installToolUsageListener(this.bus, config.toolUsageAnalyzer);
275
330
  installToolChainListener(this.bus, config.toolChainTracker);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-event-handler.js","names":[],"sources":["../../../../src/agent/orchestration/agent-event-handler.ts"],"sourcesContent":["/**\n * Agent Event Handler — coordinates listeners on pi-agent events.\n *\n * Previously a single god-handler with ten manager fields and one `switch`. Now a\n * thin façade around {@link SessionEventBus}: each concern (progress, lifecycle\n * hooks, tool-chain recording, error tracking, self-verify, etc.) registers its\n * own listener at construction time, and external code can add new listeners via\n * {@link AgentEventHandler.registerListener} without modifying this file (OCP).\n *\n * Ordering note: a few listeners are order-sensitive (notably the\n * `tool_execution_end` chain — `SystemReminder` mutates `event.result` in place\n * and downstream listeners read the mutated value). The `installX` calls below\n * preserve the exact order from the previous implementation.\n */\n\nimport type { AgentEvent } from '@earendil-works/pi-agent-core';\nimport type { SessionContext } from '../session/session-context.js';\nimport type { ProgressFeedbackManager } from '../lifecycle/progress.js';\nimport type { ToolErrorTracker } from '../tools/error-tracker.js';\nimport type { RequestLimiter } from '../models/request-limiter.js';\nimport type { LifecycleManager } from '../lifecycle/index.js';\nimport type { ToolChainTracker } from '../tools/chain-tracker.js';\nimport type { SelfVerifyMiddleware } from '../middleware/index.js';\nimport type { SystemReminder } from '../prompt/system-reminder.js';\nimport type { ToolUsageAnalyzer } from '../tools/usage-analyzer.js';\nimport type { ErrorPatternMatcher } from '../tools/error-pattern-matcher.js';\nimport { extractTextContent } from '../context/workspace.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('AgentEventHandler');\n\n// ── Event bus ──────────────────────────────────────────────────────────────\n\nexport type SessionEventListener = (event: AgentEvent, context: SessionContext) => void;\nexport type SessionEventTypeFilter = AgentEvent['type'] | 'all';\n\n/**\n * Typed pub/sub for agent events. Listeners run in registration order; the bus\n * itself is synchronous — listeners that need async work must dispatch their own\n * promises (typically by awaiting and logging on error, like the lifecycle hooks).\n */\nexport class SessionEventBus {\n private readonly listeners = new Map<SessionEventTypeFilter, SessionEventListener[]>();\n\n on(type: SessionEventTypeFilter, listener: SessionEventListener): () => void {\n const bucket = this.listeners.get(type) ?? [];\n bucket.push(listener);\n this.listeners.set(type, bucket);\n return () => {\n const current = this.listeners.get(type);\n if (!current) return;\n const idx = current.indexOf(listener);\n if (idx >= 0) current.splice(idx, 1);\n };\n }\n\n dispatch(event: AgentEvent, context: SessionContext | null): void {\n if (!context) {\n if (event.type !== 'message_update') {\n log.warn(\n { eventType: event.type },\n `Agent event ignored (no SessionContext): ${event.type}`,\n );\n }\n return;\n }\n const exact = this.listeners.get(event.type);\n if (exact) {\n for (const listener of exact) {\n listener(event, context);\n }\n }\n const all = this.listeners.get('all');\n if (all) {\n for (const listener of all) {\n listener(event, context);\n }\n }\n }\n}\n\n// ── Built-in listener installers ───────────────────────────────────────────\n\nfunction installProgressListener(bus: SessionEventBus, progressManager: ProgressFeedbackManager): void {\n bus.on('agent_start', () => {\n log.debug('Agent turn started');\n progressManager.startTask();\n });\n bus.on('turn_start', () => {\n log.debug('Turn started');\n progressManager.onTurnStart();\n });\n bus.on('tool_execution_start', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n log.debug({ tool: e.toolName, args: e.args }, 'Tool execution started');\n progressManager.onToolStart(e.toolName, e.args || {});\n });\n bus.on('tool_execution_update', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_update' }>;\n progressManager.onToolUpdate(e.toolName, e.partialResult);\n });\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n log.debug({ tool: e.toolName, isError: e.isError }, 'Tool execution complete');\n progressManager.onToolEnd(e.toolName, e.result, e.isError);\n });\n bus.on('agent_end', () => {\n progressManager.endTask();\n });\n}\n\nfunction installRequestLimitListener(\n bus: SessionEventBus,\n deps: {\n requestLimiter: RequestLimiter;\n progressManager: ProgressFeedbackManager;\n lifecycleManager: LifecycleManager;\n },\n): void {\n bus.on('agent_start', (_event, context) => {\n const result = deps.requestLimiter.recordRequest();\n\n deps.lifecycleManager\n .emit(\n 'llm_request',\n context.sessionKey,\n { requestNumber: result.count, maxRequests: result.limit },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n {\n err,\n errorMessage: em,\n sessionKey: context.sessionKey,\n requestNumber: result.count,\n maxRequests: result.limit,\n },\n `Lifecycle emit llm_request failed: ${em}`,\n );\n });\n\n deps.progressManager.onRequestLimitStatus(\n result.count,\n result.limit,\n result.remaining,\n result.isWarning,\n result.shouldStop,\n );\n\n if (result.shouldStop) {\n log.error(\n { count: result.count, limit: result.limit, sessionKey: context.sessionKey },\n `Request limit reached (${result.count}/${result.limit}) for session`,\n );\n }\n });\n\n bus.on('turn_end', () => {\n deps.requestLimiter.reset();\n });\n}\n\nfunction installLifecycleHookListener(bus: SessionEventBus, lifecycleManager: LifecycleManager): void {\n bus.on('message_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'message_end' }>;\n if (e.message?.role !== 'assistant') return;\n const content = e.message.content;\n const text = Array.isArray(content)\n ? extractTextContent(content as Array<{ type: string; text?: string }>)\n : String(content);\n log.debug({ contentLength: text.length }, 'Assistant response complete');\n\n lifecycleManager\n .emit(\n 'llm_response',\n context.sessionKey,\n { response: text, usage: (e.message as { usage?: unknown }).usage },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, responseChars: text.length },\n `Lifecycle emit llm_response failed: ${em}`,\n );\n });\n });\n\n bus.on('tool_execution_start', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n lifecycleManager\n .emit(\n 'tool_call_start',\n context.sessionKey,\n {\n toolName: e.toolName,\n arguments: e.args || {},\n attemptNumber: 1,\n maxAttempts: 3,\n },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, tool: e.toolName },\n `Lifecycle emit tool_call_start failed: ${em}`,\n );\n });\n });\n\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n lifecycleManager\n .emit(\n 'tool_call_end',\n context.sessionKey,\n {\n toolName: e.toolName,\n success: !e.isError,\n result: e.result,\n error: e.isError ? String(e.result) : undefined,\n durationMs,\n },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, tool: e.toolName },\n `Lifecycle hook tool_call_end failed: ${em}`,\n );\n });\n });\n}\n\nfunction installSystemReminderListener(bus: SessionEventBus, systemReminder: SystemReminder): void {\n // MUTATES `event.result` so downstream listeners (tool-chain, error-tracking) see\n // the decorated text. Must run AFTER progress + lifecycle hooks (they consume the\n // original) and BEFORE tool-chain + error-tracking.\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }> & { result: unknown };\n e.result = systemReminder.appendToResult(e.result, e.toolName);\n });\n}\n\nfunction appendTextToToolResult(result: unknown, text: string): unknown {\n if (!text.trim()) {\n return result;\n }\n if (result && typeof result === 'object') {\n const res = result as Record<string, unknown>;\n if (Array.isArray(res.content)) {\n res.content = [\n ...res.content,\n { type: 'text', text: `\\n${text}` },\n ];\n return res;\n }\n if (typeof res.content === 'string') {\n res.content = `${res.content}\\n${text}`;\n return res;\n }\n }\n return result;\n}\n\nfunction installToolChainListener(bus: SessionEventBus, toolChainTracker: ToolChainTracker): void {\n bus.on('turn_start', (_event, context) => {\n // One chain per LLM turn (pi-agent emits turn_start each round; turn_end clears the chain).\n toolChainTracker.startChain(context.sessionKey);\n });\n bus.on('tool_execution_start', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n toolChainTracker.recordCall(context.sessionKey, e.toolName, e.args || {}, 0);\n });\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n const chain = toolChainTracker.getCurrentChain(context.sessionKey);\n if (!chain) return;\n const lastNode = chain.nodes[chain.nodes.length - 1];\n if (lastNode && lastNode.toolName === e.toolName) {\n toolChainTracker.recordResult(\n context.sessionKey,\n lastNode.id,\n e.result,\n e.isError ? 'Tool execution failed' : undefined,\n durationMs,\n );\n }\n });\n bus.on('turn_end', (_event, context) => {\n toolChainTracker.endChain(context.sessionKey);\n });\n}\n\nfunction installToolUsageListener(bus: SessionEventBus, toolUsageAnalyzer: ToolUsageAnalyzer): void {\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n toolUsageAnalyzer.recordUsage(e.toolName, !e.isError, durationMs);\n });\n}\n\nfunction extractErrorText(result: unknown): string {\n if (typeof result === 'string') return result;\n if (result && typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n if (typeof obj.error === 'string') return obj.error;\n if (typeof obj.message === 'string') return obj.message;\n return JSON.stringify(result);\n }\n return String(result);\n}\n\nfunction installErrorTrackingListener(\n bus: SessionEventBus,\n deps: { errorTracker: ToolErrorTracker; errorPatternMatcher: ErrorPatternMatcher },\n): void {\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n if (!e.isError) return;\n const errorText = extractErrorText(e.result);\n deps.errorTracker.recordFailure(e.toolName, errorText);\n\n const errorMatch = deps.errorPatternMatcher.matchError(errorText);\n if (errorMatch.matched && errorMatch.pattern) {\n const preview = errorText.length > 120 ? `${errorText.slice(0, 120)}…` : errorText;\n log.warn(\n { tool: e.toolName, pattern: errorMatch.pattern.name, errorPreview: preview },\n `Tool error matched pattern \"${errorMatch.pattern.name}\" (${e.toolName}): ${preview}`,\n );\n }\n });\n bus.on('turn_end', () => {\n deps.errorTracker.reset();\n });\n}\n\nfunction installSelfVerifyListener(bus: SessionEventBus, selfVerifyMiddleware: SelfVerifyMiddleware): void {\n bus.on('tool_execution_start', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n const args = e.args;\n const toolName = e.toolName;\n if (!toolName || !args) return;\n const name = toolName.toLowerCase();\n if (name.includes('write') && args.path) {\n selfVerifyMiddleware.recordEdit(String(args.path), 'write');\n } else if (name.includes('edit') && args.path) {\n selfVerifyMiddleware.recordEdit(String(args.path), 'edit');\n } else {\n selfVerifyMiddleware.recordVerification(toolName, args);\n }\n });\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }> & { result: unknown };\n const name = e.toolName?.toLowerCase() ?? '';\n if (!name.includes('write') && !name.includes('edit')) {\n return;\n }\n e.result = appendTextToToolResult(e.result, selfVerifyMiddleware.consumePostEditReminder());\n });\n bus.on('turn_start', () => {\n selfVerifyMiddleware.onTurnStart();\n });\n}\n\n// ── Public façade ───────────────────────────────────────────────────────────\n\nexport interface AgentEventHandlerConfig {\n progressManager: ProgressFeedbackManager;\n errorTracker: ToolErrorTracker;\n requestLimiter: RequestLimiter;\n lifecycleManager: LifecycleManager;\n toolChainTracker: ToolChainTracker;\n selfVerifyMiddleware: SelfVerifyMiddleware;\n systemReminder: SystemReminder;\n toolUsageAnalyzer: ToolUsageAnalyzer;\n errorPatternMatcher: ErrorPatternMatcher;\n}\n\n/**\n * Thin façade over {@link SessionEventBus} that pre-registers all built-in\n * listeners in their required order. `handle(event, ctx)` is the entry point\n * used by `AgentService.handleSessionEvent`; extensions can hook in via\n * {@link registerListener} without touching this class.\n */\nexport class AgentEventHandler {\n private readonly bus: SessionEventBus;\n\n constructor(config: AgentEventHandlerConfig) {\n this.bus = new SessionEventBus();\n\n // Order matters for `tool_execution_end`: SystemReminder mutates `event.result`\n // and ToolChain + ErrorTracking depend on the mutated value. Keep these in this\n // exact sequence.\n installProgressListener(this.bus, config.progressManager);\n installRequestLimitListener(this.bus, {\n requestLimiter: config.requestLimiter,\n progressManager: config.progressManager,\n lifecycleManager: config.lifecycleManager,\n });\n installLifecycleHookListener(this.bus, config.lifecycleManager);\n installSystemReminderListener(this.bus, config.systemReminder);\n installSelfVerifyListener(this.bus, config.selfVerifyMiddleware);\n installToolUsageListener(this.bus, config.toolUsageAnalyzer);\n installToolChainListener(this.bus, config.toolChainTracker);\n installErrorTrackingListener(this.bus, {\n errorTracker: config.errorTracker,\n errorPatternMatcher: config.errorPatternMatcher,\n });\n }\n\n /** Dispatch a pi-agent event to all registered listeners. */\n handle(event: AgentEvent, context: SessionContext | null): void {\n this.bus.dispatch(event, context);\n }\n\n /**\n * Register an additional listener (e.g. from an extension). Returns an\n * unsubscribe function. Listeners run after the built-ins in registration\n * order; if you need to run before a built-in, you must create your own\n * {@link SessionEventBus} instance.\n */\n registerListener(type: SessionEventTypeFilter, listener: SessionEventListener): () => void {\n return this.bus.on(type, listener);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-event-handler.js","names":[],"sources":["../../../../src/agent/orchestration/agent-event-handler.ts"],"sourcesContent":["/**\n * Agent Event Handler — coordinates listeners on pi-agent events.\n *\n * Previously a single god-handler with ten manager fields and one `switch`. Now a\n * thin façade around {@link SessionEventBus}: each concern (progress, lifecycle\n * hooks, tool-chain recording, error tracking, self-verify, etc.) registers its\n * own listener at construction time, and external code can add new listeners via\n * {@link AgentEventHandler.registerListener} without modifying this file (OCP).\n *\n * Ordering note: a few listeners are order-sensitive (notably the\n * `tool_execution_end` chain — `SystemReminder` mutates `event.result` in place\n * and downstream listeners read the mutated value). The `installX` calls below\n * preserve the exact order from the previous implementation.\n */\n\nimport type { AgentEvent } from '@earendil-works/pi-agent-core';\nimport type { SessionContext } from '../session/session-context.js';\nimport type { ProgressFeedbackManager } from '../lifecycle/progress.js';\nimport type { ToolErrorTracker } from '../tools/error-tracker.js';\nimport type { RequestLimiter } from '../models/request-limiter.js';\nimport type { LifecycleManager } from '../lifecycle/index.js';\nimport type { ToolChainTracker } from '../tools/chain-tracker.js';\nimport type { SelfVerifyMiddleware } from '../middleware/index.js';\nimport type { SystemReminder } from '../prompt/system-reminder.js';\nimport type { ToolUsageAnalyzer } from '../tools/usage-analyzer.js';\nimport type { ErrorPatternMatcher } from '../tools/error-pattern-matcher.js';\nimport type { TurnDiffTracker } from '../coding/index.js';\nimport { extractTextContent } from '../context/workspace.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('AgentEventHandler');\n\n// ── Event bus ──────────────────────────────────────────────────────────────\n\nexport type SessionEventListener = (event: AgentEvent, context: SessionContext) => void;\nexport type SessionEventTypeFilter = AgentEvent['type'] | 'all';\n\n/**\n * Typed pub/sub for agent events. Listeners run in registration order; the bus\n * itself is synchronous — listeners that need async work must dispatch their own\n * promises (typically by awaiting and logging on error, like the lifecycle hooks).\n */\nexport class SessionEventBus {\n private readonly listeners = new Map<SessionEventTypeFilter, SessionEventListener[]>();\n\n on(type: SessionEventTypeFilter, listener: SessionEventListener): () => void {\n const bucket = this.listeners.get(type) ?? [];\n bucket.push(listener);\n this.listeners.set(type, bucket);\n return () => {\n const current = this.listeners.get(type);\n if (!current) return;\n const idx = current.indexOf(listener);\n if (idx >= 0) current.splice(idx, 1);\n };\n }\n\n dispatch(event: AgentEvent, context: SessionContext | null): void {\n if (!context) {\n if (event.type !== 'message_update') {\n log.warn(\n { eventType: event.type },\n `Agent event ignored (no SessionContext): ${event.type}`,\n );\n }\n return;\n }\n const exact = this.listeners.get(event.type);\n if (exact) {\n for (const listener of exact) {\n listener(event, context);\n }\n }\n const all = this.listeners.get('all');\n if (all) {\n for (const listener of all) {\n listener(event, context);\n }\n }\n }\n}\n\n// ── Built-in listener installers ───────────────────────────────────────────\n\nfunction installProgressListener(bus: SessionEventBus, progressManager: ProgressFeedbackManager): void {\n bus.on('agent_start', () => {\n log.debug('Agent turn started');\n progressManager.startTask();\n });\n bus.on('turn_start', () => {\n log.debug('Turn started');\n progressManager.onTurnStart();\n });\n bus.on('tool_execution_start', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n log.debug({ tool: e.toolName, args: e.args }, 'Tool execution started');\n progressManager.onToolStart(e.toolName, e.args || {});\n });\n bus.on('tool_execution_update', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_update' }>;\n progressManager.onToolUpdate(e.toolName, e.partialResult);\n });\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n log.debug({ tool: e.toolName, isError: e.isError }, 'Tool execution complete');\n progressManager.onToolEnd(e.toolName, e.result, e.isError);\n });\n bus.on('agent_end', () => {\n progressManager.endTask();\n });\n}\n\nfunction installRequestLimitListener(\n bus: SessionEventBus,\n deps: {\n requestLimiter: RequestLimiter;\n progressManager: ProgressFeedbackManager;\n lifecycleManager: LifecycleManager;\n },\n): void {\n bus.on('agent_start', (_event, context) => {\n const result = deps.requestLimiter.recordRequest();\n\n deps.lifecycleManager\n .emit(\n 'llm_request',\n context.sessionKey,\n { requestNumber: result.count, maxRequests: result.limit },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n {\n err,\n errorMessage: em,\n sessionKey: context.sessionKey,\n requestNumber: result.count,\n maxRequests: result.limit,\n },\n `Lifecycle emit llm_request failed: ${em}`,\n );\n });\n\n deps.progressManager.onRequestLimitStatus(\n result.count,\n result.limit,\n result.remaining,\n result.isWarning,\n result.shouldStop,\n );\n\n if (result.shouldStop) {\n log.error(\n { count: result.count, limit: result.limit, sessionKey: context.sessionKey },\n `Request limit reached (${result.count}/${result.limit}) for session`,\n );\n }\n });\n\n bus.on('turn_end', () => {\n deps.requestLimiter.reset();\n });\n}\n\nfunction installLifecycleHookListener(bus: SessionEventBus, lifecycleManager: LifecycleManager): void {\n bus.on('message_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'message_end' }>;\n if (e.message?.role !== 'assistant') return;\n const content = e.message.content;\n const text = Array.isArray(content)\n ? extractTextContent(content as Array<{ type: string; text?: string }>)\n : String(content);\n log.debug({ contentLength: text.length }, 'Assistant response complete');\n\n lifecycleManager\n .emit(\n 'llm_response',\n context.sessionKey,\n { response: text, usage: (e.message as { usage?: unknown }).usage },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, responseChars: text.length },\n `Lifecycle emit llm_response failed: ${em}`,\n );\n });\n });\n\n bus.on('tool_execution_start', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n lifecycleManager\n .emit(\n 'tool_call_start',\n context.sessionKey,\n {\n toolName: e.toolName,\n arguments: e.args || {},\n attemptNumber: 1,\n maxAttempts: 3,\n },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, tool: e.toolName },\n `Lifecycle emit tool_call_start failed: ${em}`,\n );\n });\n });\n\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n lifecycleManager\n .emit(\n 'tool_call_end',\n context.sessionKey,\n {\n toolName: e.toolName,\n success: !e.isError,\n result: e.result,\n error: e.isError ? String(e.result) : undefined,\n durationMs,\n },\n context,\n )\n .catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, errorMessage: em, sessionKey: context.sessionKey, tool: e.toolName },\n `Lifecycle hook tool_call_end failed: ${em}`,\n );\n });\n });\n}\n\nfunction installSystemReminderListener(bus: SessionEventBus, systemReminder: SystemReminder): void {\n // MUTATES `event.result` so downstream listeners (tool-chain, error-tracking) see\n // the decorated text. Must run AFTER progress + lifecycle hooks (they consume the\n // original) and BEFORE tool-chain + error-tracking.\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }> & { result: unknown };\n e.result = systemReminder.appendToResult(e.result, e.toolName);\n });\n}\n\nfunction appendTextToToolResult(result: unknown, text: string): unknown {\n if (!text.trim()) {\n return result;\n }\n if (result && typeof result === 'object') {\n const res = result as Record<string, unknown>;\n if (Array.isArray(res.content)) {\n res.content = [\n ...res.content,\n { type: 'text', text: `\\n${text}` },\n ];\n return res;\n }\n if (typeof res.content === 'string') {\n res.content = `${res.content}\\n${text}`;\n return res;\n }\n }\n return result;\n}\n\nfunction readRecord(value: unknown): Record<string, unknown> | null {\n return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;\n}\n\nfunction readToolResultDetails(result: unknown): Record<string, unknown> | null {\n const rec = readRecord(result);\n if (!rec) return null;\n return readRecord(rec.details);\n}\n\nfunction readStringArray(value: unknown): string[] {\n return Array.isArray(value) ? value.filter((item): item is string => typeof item === 'string') : [];\n}\n\nfunction readChangedPathsFromToolEnd(toolName: string, args: unknown, result: unknown): string[] {\n const name = toolName.toLowerCase();\n const details = readToolResultDetails(result);\n\n if (name === 'apply_patch') {\n const files = readStringArray(details?.files);\n if (files.length > 0) return files;\n\n const changes = Array.isArray(details?.changes) ? details.changes : [];\n return changes.flatMap((change) => {\n const rec = readRecord(change);\n if (!rec) return [];\n return readStringArray([rec.moveTo, rec.path]);\n });\n }\n\n if (name === 'write_file') {\n if (typeof details?.size !== 'number') return [];\n const rec = readRecord(args);\n return typeof rec?.path === 'string' ? [rec.path] : [];\n }\n\n if (name.includes('write') || name.includes('edit')) {\n const rec = readRecord(args);\n return typeof rec?.path === 'string' ? [rec.path] : [];\n }\n\n return [];\n}\n\nfunction installToolChainListener(bus: SessionEventBus, toolChainTracker: ToolChainTracker): void {\n bus.on('turn_start', (_event, context) => {\n // One chain per LLM turn (pi-agent emits turn_start each round; turn_end clears the chain).\n toolChainTracker.startChain(context.sessionKey);\n });\n bus.on('tool_execution_start', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_start' }>;\n toolChainTracker.recordCall(context.sessionKey, e.toolName, e.args || {}, 0);\n });\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n const chain = toolChainTracker.getCurrentChain(context.sessionKey);\n if (!chain) return;\n const lastNode = chain.nodes[chain.nodes.length - 1];\n if (lastNode && lastNode.toolName === e.toolName) {\n toolChainTracker.recordResult(\n context.sessionKey,\n lastNode.id,\n e.result,\n e.isError ? 'Tool execution failed' : undefined,\n durationMs,\n );\n }\n });\n bus.on('turn_end', (_event, context) => {\n toolChainTracker.endChain(context.sessionKey);\n });\n}\n\nfunction installToolUsageListener(bus: SessionEventBus, toolUsageAnalyzer: ToolUsageAnalyzer): void {\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n const durationMs = (e as { durationMs?: number }).durationMs || 0;\n toolUsageAnalyzer.recordUsage(e.toolName, !e.isError, durationMs);\n });\n}\n\nfunction extractErrorText(result: unknown): string {\n if (typeof result === 'string') return result;\n if (result && typeof result === 'object') {\n const obj = result as Record<string, unknown>;\n if (typeof obj.error === 'string') return obj.error;\n if (typeof obj.message === 'string') return obj.message;\n return JSON.stringify(result);\n }\n return String(result);\n}\n\nfunction installErrorTrackingListener(\n bus: SessionEventBus,\n deps: { errorTracker: ToolErrorTracker; errorPatternMatcher: ErrorPatternMatcher },\n): void {\n bus.on('tool_execution_end', (event) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }>;\n if (!e.isError) return;\n const errorText = extractErrorText(e.result);\n deps.errorTracker.recordFailure(e.toolName, errorText);\n\n const errorMatch = deps.errorPatternMatcher.matchError(errorText);\n if (errorMatch.matched && errorMatch.pattern) {\n const preview = errorText.length > 120 ? `${errorText.slice(0, 120)}…` : errorText;\n log.warn(\n { tool: e.toolName, pattern: errorMatch.pattern.name, errorPreview: preview },\n `Tool error matched pattern \"${errorMatch.pattern.name}\" (${e.toolName}): ${preview}`,\n );\n }\n });\n bus.on('turn_end', () => {\n deps.errorTracker.reset();\n });\n}\n\nfunction installSelfVerifyListener(bus: SessionEventBus, selfVerifyMiddleware: SelfVerifyMiddleware): void {\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }> & { result: unknown };\n const name = e.toolName?.toLowerCase() ?? '';\n const args = (e as { args?: unknown }).args;\n\n if (name === 'exec_command') {\n selfVerifyMiddleware.recordVerification(e.toolName, args, {\n isError: e.isError,\n result: e.result,\n }, context.sessionKey);\n return;\n }\n\n if (!e.isError) {\n const changedPaths = readChangedPathsFromToolEnd(e.toolName, args, e.result);\n for (const path of changedPaths) {\n selfVerifyMiddleware.recordEdit(\n path,\n name.includes('write') ? 'write' : 'edit',\n context.sessionKey,\n );\n }\n if (changedPaths.length > 0) {\n e.result = appendTextToToolResult(\n e.result,\n selfVerifyMiddleware.consumePostEditReminder(context.sessionKey),\n );\n return;\n }\n selfVerifyMiddleware.recordVerification(e.toolName, args, {\n isError: e.isError,\n result: e.result,\n }, context.sessionKey);\n }\n });\n bus.on('turn_start', (_event, context) => {\n selfVerifyMiddleware.onTurnStart(context.sessionKey);\n });\n}\n\nfunction installTurnDiffTrackerListener(bus: SessionEventBus, turnDiffTracker: TurnDiffTracker): void {\n bus.on('tool_execution_end', (event, context) => {\n const e = event as Extract<AgentEvent, { type: 'tool_execution_end' }> & {\n args?: unknown;\n result: unknown;\n };\n turnDiffTracker.recordToolResult({\n sessionKey: context.sessionKey,\n toolName: e.toolName,\n args: e.args,\n result: e.result,\n isError: e.isError,\n });\n });\n}\n\n// ── Public façade ───────────────────────────────────────────────────────────\n\nexport interface AgentEventHandlerConfig {\n progressManager: ProgressFeedbackManager;\n errorTracker: ToolErrorTracker;\n requestLimiter: RequestLimiter;\n lifecycleManager: LifecycleManager;\n toolChainTracker: ToolChainTracker;\n selfVerifyMiddleware: SelfVerifyMiddleware;\n systemReminder: SystemReminder;\n toolUsageAnalyzer: ToolUsageAnalyzer;\n errorPatternMatcher: ErrorPatternMatcher;\n turnDiffTracker?: TurnDiffTracker;\n}\n\n/**\n * Thin façade over {@link SessionEventBus} that pre-registers all built-in\n * listeners in their required order. `handle(event, ctx)` is the entry point\n * used by `AgentService.handleSessionEvent`; extensions can hook in via\n * {@link registerListener} without touching this class.\n */\nexport class AgentEventHandler {\n private readonly bus: SessionEventBus;\n\n constructor(config: AgentEventHandlerConfig) {\n this.bus = new SessionEventBus();\n\n // Order matters for `tool_execution_end`: SystemReminder mutates `event.result`\n // and ToolChain + ErrorTracking depend on the mutated value. Keep these in this\n // exact sequence.\n installProgressListener(this.bus, config.progressManager);\n installRequestLimitListener(this.bus, {\n requestLimiter: config.requestLimiter,\n progressManager: config.progressManager,\n lifecycleManager: config.lifecycleManager,\n });\n installLifecycleHookListener(this.bus, config.lifecycleManager);\n installSystemReminderListener(this.bus, config.systemReminder);\n if (config.turnDiffTracker) {\n installTurnDiffTrackerListener(this.bus, config.turnDiffTracker);\n }\n installSelfVerifyListener(this.bus, config.selfVerifyMiddleware);\n installToolUsageListener(this.bus, config.toolUsageAnalyzer);\n installToolChainListener(this.bus, config.toolChainTracker);\n installErrorTrackingListener(this.bus, {\n errorTracker: config.errorTracker,\n errorPatternMatcher: config.errorPatternMatcher,\n });\n }\n\n /** Dispatch a pi-agent event to all registered listeners. */\n handle(event: AgentEvent, context: SessionContext | null): void {\n this.bus.dispatch(event, context);\n }\n\n /**\n * Register an additional listener (e.g. from an extension). Returns an\n * unsubscribe function. Listeners run after the built-ins in registration\n * order; if you need to run before a built-in, you must create your own\n * {@link SessionEventBus} instance.\n */\n registerListener(type: SessionEventTypeFilter, listener: SessionEventListener): () => void {\n return this.bus.on(type, listener);\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
+ import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
1
2
  import { createLogger } from "../../utils/logger/index.js";
2
3
  import { init_logger } from "../../utils/logger.js";
3
4
  import "../memory/dreaming/constants.js";
4
- import { resolveDreamingConfig } from "../memory/dreaming/config.js";
5
+ import { resolveDreamingAgentScope } from "../memory/dreaming/scope.js";
5
6
  import { persistInboundAttachments } from "../../channels/attachments/inbound-persist.js";
6
7
  import { buildTranscriptUserMessage, clearPendingTranscriptUserMessage, hydrateUserTurnForLlm, setPendingTranscriptUserMessage } from "../inbound/attachment-pipeline.js";
7
8
  import { extractAgentUserPlainText } from "../memory/user-message-text.js";
@@ -52,15 +53,20 @@ var AgentOrchestrator = class {
52
53
  if (typeof msg.content === "string" && (sessionKey.startsWith("cron:") || sessionKey.includes(":cron:") || sessionKey.includes(":automation:") || context.channel === "cron" || context.channel === "automation")) {
53
54
  const content = msg.content;
54
55
  if (content.includes("__xopc_memory_dreaming_sweep__") || content.includes("__xopc_memory_dreaming_light_sweep__") || content.includes("__xopc_memory_dreaming_rem_sweep__")) {
55
- const workspaceDir = this.agentManager.getResolvedWorkspaceForSession(sessionKey);
56
- const resolved = resolveDreamingConfig(this.getConfig?.());
56
+ const cfg = this.getConfig?.();
57
+ if (!cfg) {
58
+ log.warn({ sessionKey }, "Dreaming sweep skipped: config unavailable");
59
+ return;
60
+ }
61
+ const scope = resolveDreamingAgentScope(cfg, resolveEffectiveAgentProfileForSession(cfg, sessionKey).agentId);
62
+ const resolved = scope.config;
57
63
  const t0 = Date.now();
58
64
  if (content.includes("__xopc_memory_dreaming_light_sweep__")) {
59
65
  const result = await runLightSweep({
60
- workspaceDir,
66
+ dreamingRoot: scope.memoriesDir,
61
67
  config: resolved.phases.light
62
68
  });
63
- await appendDreamingEvent(workspaceDir, {
69
+ const event = {
64
70
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
65
71
  phase: "light",
66
72
  ok: result.ok,
@@ -69,13 +75,14 @@ var AgentOrchestrator = class {
69
75
  scannedEntries: result.scannedEntries,
70
76
  newSignals: result.newSignals,
71
77
  deduped: result.deduped
72
- });
78
+ };
79
+ await appendDreamingEvent(scope.memoriesDir, event);
73
80
  } else if (content.includes("__xopc_memory_dreaming_rem_sweep__")) {
74
81
  const result = await runRemPatterns({
75
- workspaceDir,
82
+ dreamingRoot: scope.memoriesDir,
76
83
  config: resolved.phases.rem
77
84
  });
78
- await appendDreamingEvent(workspaceDir, {
85
+ const event = {
79
86
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
80
87
  phase: "rem",
81
88
  ok: result.ok,
@@ -83,14 +90,16 @@ var AgentOrchestrator = class {
83
90
  durationMs: Date.now() - t0,
84
91
  patternsDiscovered: result.patternsDiscovered,
85
92
  entriesAnalyzed: result.entriesAnalyzed
86
- });
93
+ };
94
+ await appendDreamingEvent(scope.memoriesDir, event);
87
95
  } else {
88
96
  const result = await runDreamingDeepPromotion({
89
- workspaceDir,
97
+ workspaceDir: scope.workspaceDir,
98
+ dreamingRoot: scope.memoriesDir,
90
99
  config: resolved.phases.deep,
91
100
  memoryManager: this.agentManager.getMemoryManagerForSession(sessionKey)
92
101
  });
93
- await appendDreamingEvent(workspaceDir, {
102
+ const event = {
94
103
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
95
104
  phase: "deep",
96
105
  ok: result.ok,
@@ -98,7 +107,8 @@ var AgentOrchestrator = class {
98
107
  durationMs: Date.now() - t0,
99
108
  candidates: result.candidates,
100
109
  applied: result.applied
101
- });
110
+ };
111
+ await appendDreamingEvent(scope.memoriesDir, event);
102
112
  }
103
113
  return;
104
114
  }
@@ -1 +1 @@
1
- {"version":3,"file":"agent-orchestrator.js","names":[],"sources":["../../../../src/agent/orchestration/agent-orchestrator.ts"],"sourcesContent":["/**\n * Agent Orchestrator - Coordinates Agent execution flow\n *\n * Manages the complete agent execution pipeline from message processing\n * to response generation.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport type { InboundMessage } from '../../infra/bus/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { SessionHydrator } from '../session/index.js';\nimport { resolveEffectiveThinkingLevel } from '../../session/thinking-resolve.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionContext } from '../session/session-context.js';\nimport type { AgentEventHandler } from './agent-event-handler.js';\nimport type { FeedbackCoordinator } from '../feedback/feedback-coordinator.js';\nimport type { AgentManager } from '../agent-manager.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\nimport { persistInboundAttachments } from '../../channels/attachments/inbound-persist.js';\nimport {\n buildTranscriptUserMessage,\n clearPendingTranscriptUserMessage,\n hydrateUserTurnForLlm,\n setPendingTranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\nimport {\n DREAMING_SWEEP_TOKEN,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_REM_SWEEP_TOKEN,\n} from '../memory/dreaming/constants.js';\nimport { resolveDreamingConfig } from '../memory/dreaming/config.js';\nimport { runDreamingDeepPromotion } from '../memory/dreaming/deep-promotion.js';\nimport { appendDreamingEvent, type DreamingEvent } from '../memory/dreaming/events.js';\nimport { runLightSweep } from '../memory/dreaming/light-sweep.js';\nimport { runRemPatterns } from '../memory/dreaming/rem-patterns.js';\n\nconst log = createLogger('AgentOrchestrator');\n\nexport interface AgentOrchestratorConfig {\n agentManager: AgentManager;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n eventHandler: AgentEventHandler;\n feedbackCoordinator: FeedbackCoordinator;\n sessionConfigStore: SessionConfigStore;\n /** Per-session hydration (workspace override + model override) before the agent runs. */\n sessionHydrator: SessionHydrator;\n getThinkingDefault: () => ThinkLevel | undefined;\n /** Per-session default from merged `agents.list` / defaults (optional). */\n getThinkingDefaultForSession?: (sessionKey: string) => ThinkLevel | undefined;\n /** Default workspace root when no per-session resolver is set. */\n workspaceRoot: string;\n /** Per-agent workspace root for attachments (optional; defaults to `workspaceRoot`). */\n getWorkspaceRootForSession?: (sessionKey: string) => string;\n /** Agent home (`…/agents/<id>/`) for inbound/TTS files — keeps internal state out of the markdown workspace. */\n getAgentInternalStorageRootForSession?: (sessionKey: string) => string;\n /** Fire-and-forget after full session persist (e.g. LLM session title); not called from mid-turn snapshots. */\n enqueueAutoTitle?: (sessionKey: string) => void;\n /** For per-turn timeout. */\n getConfig?: () => Config | undefined;\n /** Channel streaming: token/tool events from pi embedded session. */\n onEmbeddedStreamEvent?: (sessionKey: string, event: EmbeddedStreamEvent) => void;\n /** Called after a successful embedded turn with assistant plain text. */\n onEmbeddedTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n}\n\nexport class AgentOrchestrator {\n private agentManager: AgentManager;\n private sessionStore: SessionStore;\n private modelManager: ModelManager;\n private feedbackCoordinator: FeedbackCoordinator;\n private sessionConfigStore: SessionConfigStore;\n private sessionHydrator: SessionHydrator;\n private getThinkingDefault: () => ThinkLevel | undefined;\n private getThinkingDefaultForSession?: (sessionKey: string) => ThinkLevel | undefined;\n private enqueueAutoTitle?: (sessionKey: string) => void;\n private getConfig?: () => Config | undefined;\n private onEmbeddedStreamEvent?: (sessionKey: string, event: EmbeddedStreamEvent) => void;\n private onEmbeddedTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n\n constructor(config: AgentOrchestratorConfig) {\n this.agentManager = config.agentManager;\n this.sessionStore = config.sessionStore;\n this.modelManager = config.modelManager;\n this.feedbackCoordinator = config.feedbackCoordinator;\n this.sessionConfigStore = config.sessionConfigStore;\n this.sessionHydrator = config.sessionHydrator;\n this.getThinkingDefault = config.getThinkingDefault;\n this.getThinkingDefaultForSession = config.getThinkingDefaultForSession;\n this.enqueueAutoTitle = config.enqueueAutoTitle;\n this.getConfig = config.getConfig;\n this.onEmbeddedStreamEvent = config.onEmbeddedStreamEvent;\n this.onEmbeddedTurnComplete = config.onEmbeddedTurnComplete;\n }\n\n /**\n * Process a message through the agent orchestration pipeline\n */\n async process(msg: InboundMessage, context: SessionContext): Promise<void> {\n const { sessionKey } = context;\n\n log.debug({ sessionKey }, 'Processing message through agent orchestrator');\n\n await this.sessionHydrator.workspace(sessionKey);\n\n // Dreaming: short-circuit scheduled maintenance tokens into local runs.\n // This avoids spending LLM tokens for scheduled memory consolidation.\n if (\n typeof msg.content === 'string' &&\n (\n sessionKey.startsWith('cron:') ||\n sessionKey.includes(':cron:') ||\n sessionKey.includes(':automation:') ||\n context.channel === 'cron' ||\n context.channel === 'automation'\n )\n ) {\n const content = msg.content;\n const isDreamingSweep =\n content.includes(DREAMING_SWEEP_TOKEN) ||\n content.includes(DREAMING_LIGHT_SWEEP_TOKEN) ||\n content.includes(DREAMING_REM_SWEEP_TOKEN);\n\n if (isDreamingSweep) {\n const workspaceDir = this.agentManager.getResolvedWorkspaceForSession(sessionKey);\n const resolved = resolveDreamingConfig(this.getConfig?.());\n const t0 = Date.now();\n\n if (content.includes(DREAMING_LIGHT_SWEEP_TOKEN)) {\n const result = await runLightSweep({ workspaceDir, config: resolved.phases.light });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'light',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n scannedEntries: result.scannedEntries, newSignals: result.newSignals, deduped: result.deduped,\n };\n await appendDreamingEvent(workspaceDir, event);\n } else if (content.includes(DREAMING_REM_SWEEP_TOKEN)) {\n const result = await runRemPatterns({ workspaceDir, config: resolved.phases.rem });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'rem',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n patternsDiscovered: result.patternsDiscovered, entriesAnalyzed: result.entriesAnalyzed,\n };\n await appendDreamingEvent(workspaceDir, event);\n } else {\n const result = await runDreamingDeepPromotion({\n workspaceDir,\n config: resolved.phases.deep,\n memoryManager: this.agentManager.getMemoryManagerForSession(sessionKey),\n });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'deep',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n candidates: result.candidates, applied: result.applied,\n };\n await appendDreamingEvent(workspaceDir, event);\n }\n return;\n }\n }\n\n try {\n await this.sessionHydrator.model(sessionKey);\n\n const channelSystemPrompt =\n typeof context.metadata?.channelSystemPrompt === 'string'\n ? context.metadata.channelSystemPrompt.trim()\n : '';\n if (channelSystemPrompt) {\n this.agentManager.getOrCreateAgent(sessionKey);\n this.agentManager.applyTurnChannelSystemPrompt(sessionKey, channelSystemPrompt);\n }\n\n const thinkingDefault =\n this.getThinkingDefaultForSession?.(sessionKey) ?? this.getThinkingDefault();\n const thinkingLevel = await resolveEffectiveThinkingLevel(\n this.sessionConfigStore,\n sessionKey,\n null,\n thinkingDefault,\n );\n this.agentManager.setThinkingLevel(sessionKey, thinkingLevel);\n\n const persistedAttachments = await persistInboundAttachments(msg.attachments);\n const modelRef = this.modelManager.getModelForSession(sessionKey);\n const userMessage = await buildTranscriptUserMessage({\n text: msg.content,\n prepared: persistedAttachments,\n sessionKey,\n modelRef,\n config: this.getConfig?.(),\n agentManager: this.agentManager,\n });\n setPendingTranscriptUserMessage(sessionKey, userMessage);\n\n const userPlainForMemory = extractAgentUserPlainText(userMessage);\n const userMessageForModel = await this.agentManager.applyMemoryPrefetchToUserMessage(\n userMessage,\n sessionKey,\n );\n\n const llmTurn = await hydrateUserTurnForLlm({\n message: userMessage,\n modelRef,\n });\n\n this.feedbackCoordinator.startTask();\n\n const turnResult = await (async () => {\n try {\n return await runEmbeddedTurnForSession({\n sessionKey,\n userMessage: userMessageForModel,\n llmImages: llmTurn.images,\n sessionStore: this.sessionStore,\n agentManager: this.agentManager,\n modelManager: this.modelManager,\n thinkingOverride: thinkingLevel,\n getConfig: this.getConfig,\n beforeTurn: () => this.agentManager.beginBackgroundReviewUserTurn(sessionKey),\n onEvent: (event) => this.onEmbeddedStreamEvent?.(sessionKey, event),\n });\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, userMessage);\n }\n })();\n\n this.agentManager.afterAgentTurn(sessionKey, userPlainForMemory);\n this.agentManager.scheduleBackgroundReviewAfterUserTurn(sessionKey);\n\n if (turnResult.ok) {\n this.onEmbeddedTurnComplete?.(sessionKey, turnResult.lastAssistantText);\n this.enqueueAutoTitle?.(sessionKey);\n } else if (turnResult.errorMessage) {\n log.warn({ sessionKey, errorMessage: turnResult.errorMessage }, 'Embedded inbound turn failed');\n }\n\n this.feedbackCoordinator.endTask();\n\n } catch (error) {\n log.error({ err: error, sessionKey }, 'Error in agent orchestration');\n this.feedbackCoordinator.endTask();\n throw error;\n }\n }\n\n /**\n * Get the current agent model ID\n */\n getCurrentModel(): string {\n return this.modelManager.getCurrentModel();\n }\n\n /**\n * Check if agent is currently processing for a session\n */\n isProcessing(sessionKey: string): boolean {\n const agent = this.agentManager.getAgent(sessionKey);\n if (!agent) {\n return false;\n }\n return agent.state.messages.length > 0;\n }\n\n /**\n * Abort current agent execution for a session\n */\n abort(sessionKey: string): void {\n void abortEmbeddedRun(sessionKey);\n const agent = this.agentManager.getAgent(sessionKey);\n agent?.abort();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-orchestrator.js","names":[],"sources":["../../../../src/agent/orchestration/agent-orchestrator.ts"],"sourcesContent":["/**\n * Agent Orchestrator - Coordinates Agent execution flow\n *\n * Manages the complete agent execution pipeline from message processing\n * to response generation.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport { resolveEffectiveAgentProfileForSession } from '../../config/agent-profile.js';\nimport type { InboundMessage } from '../../infra/bus/index.js';\nimport type { SessionConfigStore, SessionStore } from '../../session/index.js';\nimport type { SessionHydrator } from '../session/index.js';\nimport { resolveEffectiveThinkingLevel } from '../../session/thinking-resolve.js';\nimport type { ThinkLevel } from '../transcript/thinking-types.js';\nimport type { ModelManager } from '../models/index.js';\nimport type { SessionContext } from '../session/session-context.js';\nimport type { AgentEventHandler } from './agent-event-handler.js';\nimport type { FeedbackCoordinator } from '../feedback/feedback-coordinator.js';\nimport type { AgentManager } from '../agent-manager.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\nimport { persistInboundAttachments } from '../../channels/attachments/inbound-persist.js';\nimport {\n buildTranscriptUserMessage,\n clearPendingTranscriptUserMessage,\n hydrateUserTurnForLlm,\n setPendingTranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\nimport {\n DREAMING_SWEEP_TOKEN,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_REM_SWEEP_TOKEN,\n} from '../memory/dreaming/constants.js';\nimport { runDreamingDeepPromotion } from '../memory/dreaming/deep-promotion.js';\nimport { appendDreamingEvent, type DreamingEvent } from '../memory/dreaming/events.js';\nimport { runLightSweep } from '../memory/dreaming/light-sweep.js';\nimport { runRemPatterns } from '../memory/dreaming/rem-patterns.js';\nimport { resolveDreamingAgentScope } from '../memory/dreaming/scope.js';\n\nconst log = createLogger('AgentOrchestrator');\n\nexport interface AgentOrchestratorConfig {\n agentManager: AgentManager;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n eventHandler: AgentEventHandler;\n feedbackCoordinator: FeedbackCoordinator;\n sessionConfigStore: SessionConfigStore;\n /** Per-session hydration (workspace override + model override) before the agent runs. */\n sessionHydrator: SessionHydrator;\n getThinkingDefault: () => ThinkLevel | undefined;\n /** Per-session default from merged `agents.list` / defaults (optional). */\n getThinkingDefaultForSession?: (sessionKey: string) => ThinkLevel | undefined;\n /** Default workspace root when no per-session resolver is set. */\n workspaceRoot: string;\n /** Per-agent workspace root for attachments (optional; defaults to `workspaceRoot`). */\n getWorkspaceRootForSession?: (sessionKey: string) => string;\n /** Agent home (`…/agents/<id>/`) for inbound/TTS files — keeps internal state out of the markdown workspace. */\n getAgentInternalStorageRootForSession?: (sessionKey: string) => string;\n /** Fire-and-forget after full session persist (e.g. LLM session title); not called from mid-turn snapshots. */\n enqueueAutoTitle?: (sessionKey: string) => void;\n /** For per-turn timeout. */\n getConfig?: () => Config | undefined;\n /** Channel streaming: token/tool events from pi embedded session. */\n onEmbeddedStreamEvent?: (sessionKey: string, event: EmbeddedStreamEvent) => void;\n /** Called after a successful embedded turn with assistant plain text. */\n onEmbeddedTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n}\n\nexport class AgentOrchestrator {\n private agentManager: AgentManager;\n private sessionStore: SessionStore;\n private modelManager: ModelManager;\n private feedbackCoordinator: FeedbackCoordinator;\n private sessionConfigStore: SessionConfigStore;\n private sessionHydrator: SessionHydrator;\n private getThinkingDefault: () => ThinkLevel | undefined;\n private getThinkingDefaultForSession?: (sessionKey: string) => ThinkLevel | undefined;\n private enqueueAutoTitle?: (sessionKey: string) => void;\n private getConfig?: () => Config | undefined;\n private onEmbeddedStreamEvent?: (sessionKey: string, event: EmbeddedStreamEvent) => void;\n private onEmbeddedTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n\n constructor(config: AgentOrchestratorConfig) {\n this.agentManager = config.agentManager;\n this.sessionStore = config.sessionStore;\n this.modelManager = config.modelManager;\n this.feedbackCoordinator = config.feedbackCoordinator;\n this.sessionConfigStore = config.sessionConfigStore;\n this.sessionHydrator = config.sessionHydrator;\n this.getThinkingDefault = config.getThinkingDefault;\n this.getThinkingDefaultForSession = config.getThinkingDefaultForSession;\n this.enqueueAutoTitle = config.enqueueAutoTitle;\n this.getConfig = config.getConfig;\n this.onEmbeddedStreamEvent = config.onEmbeddedStreamEvent;\n this.onEmbeddedTurnComplete = config.onEmbeddedTurnComplete;\n }\n\n /**\n * Process a message through the agent orchestration pipeline\n */\n async process(msg: InboundMessage, context: SessionContext): Promise<void> {\n const { sessionKey } = context;\n\n log.debug({ sessionKey }, 'Processing message through agent orchestrator');\n\n await this.sessionHydrator.workspace(sessionKey);\n\n // Dreaming: short-circuit scheduled maintenance tokens into local runs.\n // This avoids spending LLM tokens for scheduled memory consolidation.\n if (\n typeof msg.content === 'string' &&\n (\n sessionKey.startsWith('cron:') ||\n sessionKey.includes(':cron:') ||\n sessionKey.includes(':automation:') ||\n context.channel === 'cron' ||\n context.channel === 'automation'\n )\n ) {\n const content = msg.content;\n const isDreamingSweep =\n content.includes(DREAMING_SWEEP_TOKEN) ||\n content.includes(DREAMING_LIGHT_SWEEP_TOKEN) ||\n content.includes(DREAMING_REM_SWEEP_TOKEN);\n\n if (isDreamingSweep) {\n const cfg = this.getConfig?.();\n if (!cfg) {\n log.warn({ sessionKey }, 'Dreaming sweep skipped: config unavailable');\n return;\n }\n const profile = resolveEffectiveAgentProfileForSession(cfg, sessionKey);\n const scope = resolveDreamingAgentScope(cfg, profile.agentId);\n const resolved = scope.config;\n const t0 = Date.now();\n\n if (content.includes(DREAMING_LIGHT_SWEEP_TOKEN)) {\n const result = await runLightSweep({ dreamingRoot: scope.memoriesDir, config: resolved.phases.light });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'light',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n scannedEntries: result.scannedEntries, newSignals: result.newSignals, deduped: result.deduped,\n };\n await appendDreamingEvent(scope.memoriesDir, event);\n } else if (content.includes(DREAMING_REM_SWEEP_TOKEN)) {\n const result = await runRemPatterns({ dreamingRoot: scope.memoriesDir, config: resolved.phases.rem });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'rem',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n patternsDiscovered: result.patternsDiscovered, entriesAnalyzed: result.entriesAnalyzed,\n };\n await appendDreamingEvent(scope.memoriesDir, event);\n } else {\n const result = await runDreamingDeepPromotion({\n workspaceDir: scope.workspaceDir,\n dreamingRoot: scope.memoriesDir,\n config: resolved.phases.deep,\n memoryManager: this.agentManager.getMemoryManagerForSession(sessionKey),\n });\n const event: DreamingEvent = {\n timestamp: new Date().toISOString(), phase: 'deep',\n ok: result.ok, reason: result.reason, durationMs: Date.now() - t0,\n candidates: result.candidates, applied: result.applied,\n };\n await appendDreamingEvent(scope.memoriesDir, event);\n }\n return;\n }\n }\n\n try {\n await this.sessionHydrator.model(sessionKey);\n\n const channelSystemPrompt =\n typeof context.metadata?.channelSystemPrompt === 'string'\n ? context.metadata.channelSystemPrompt.trim()\n : '';\n if (channelSystemPrompt) {\n this.agentManager.getOrCreateAgent(sessionKey);\n this.agentManager.applyTurnChannelSystemPrompt(sessionKey, channelSystemPrompt);\n }\n\n const thinkingDefault =\n this.getThinkingDefaultForSession?.(sessionKey) ?? this.getThinkingDefault();\n const thinkingLevel = await resolveEffectiveThinkingLevel(\n this.sessionConfigStore,\n sessionKey,\n null,\n thinkingDefault,\n );\n this.agentManager.setThinkingLevel(sessionKey, thinkingLevel);\n\n const persistedAttachments = await persistInboundAttachments(msg.attachments);\n const modelRef = this.modelManager.getModelForSession(sessionKey);\n const userMessage = await buildTranscriptUserMessage({\n text: msg.content,\n prepared: persistedAttachments,\n sessionKey,\n modelRef,\n config: this.getConfig?.(),\n agentManager: this.agentManager,\n });\n setPendingTranscriptUserMessage(sessionKey, userMessage);\n\n const userPlainForMemory = extractAgentUserPlainText(userMessage);\n const userMessageForModel = await this.agentManager.applyMemoryPrefetchToUserMessage(\n userMessage,\n sessionKey,\n );\n\n const llmTurn = await hydrateUserTurnForLlm({\n message: userMessage,\n modelRef,\n });\n\n this.feedbackCoordinator.startTask();\n\n const turnResult = await (async () => {\n try {\n return await runEmbeddedTurnForSession({\n sessionKey,\n userMessage: userMessageForModel,\n llmImages: llmTurn.images,\n sessionStore: this.sessionStore,\n agentManager: this.agentManager,\n modelManager: this.modelManager,\n thinkingOverride: thinkingLevel,\n getConfig: this.getConfig,\n beforeTurn: () => this.agentManager.beginBackgroundReviewUserTurn(sessionKey),\n onEvent: (event) => this.onEmbeddedStreamEvent?.(sessionKey, event),\n });\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, userMessage);\n }\n })();\n\n this.agentManager.afterAgentTurn(sessionKey, userPlainForMemory);\n this.agentManager.scheduleBackgroundReviewAfterUserTurn(sessionKey);\n\n if (turnResult.ok) {\n this.onEmbeddedTurnComplete?.(sessionKey, turnResult.lastAssistantText);\n this.enqueueAutoTitle?.(sessionKey);\n } else if (turnResult.errorMessage) {\n log.warn({ sessionKey, errorMessage: turnResult.errorMessage }, 'Embedded inbound turn failed');\n }\n\n this.feedbackCoordinator.endTask();\n\n } catch (error) {\n log.error({ err: error, sessionKey }, 'Error in agent orchestration');\n this.feedbackCoordinator.endTask();\n throw error;\n }\n }\n\n /**\n * Get the current agent model ID\n */\n getCurrentModel(): string {\n return this.modelManager.getCurrentModel();\n }\n\n /**\n * Check if agent is currently processing for a session\n */\n isProcessing(sessionKey: string): boolean {\n const agent = this.agentManager.getAgent(sessionKey);\n if (!agent) {\n return false;\n }\n return agent.state.messages.length > 0;\n }\n\n /**\n * Abort current agent execution for a session\n */\n abort(sessionKey: string): void {\n void abortEmbeddedRun(sessionKey);\n const agent = this.agentManager.getAgent(sessionKey);\n agent?.abort();\n }\n}\n"],"mappings":"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"}
@@ -2,11 +2,12 @@
2
2
  const CORE_TOOL_ORDER = [
3
3
  "read_file",
4
4
  "write_file",
5
- "edit_file",
5
+ "apply_patch",
6
6
  "grep",
7
7
  "find",
8
8
  "list_dir",
9
- "shell",
9
+ "exec_command",
10
+ "update_plan",
10
11
  "web_search",
11
12
  "web_fetch",
12
13
  "web_extract",
@@ -34,13 +35,14 @@ const CORE_TOOL_ORDER = [
34
35
  "execute_code"
35
36
  ];
36
37
  const CORE_TOOL_SUMMARIES = {
37
- read_file: "Read targeted file contents; prefer this over shell cat/sed for inspection",
38
- write_file: "Create new files or intentional complete rewrites",
39
- edit_file: "Make precise, minimal edits to existing files",
38
+ read_file: "Read targeted file contents before editing",
39
+ write_file: "Create new files or intentional complete rewrites; prefer apply_patch for code changes",
40
+ apply_patch: "Apply strict patches for source edits",
40
41
  grep: "Search file contents for literals, errors, config values, and docs",
41
42
  find: "Find files by glob pattern",
42
43
  list_dir: "List directory contents",
43
- shell: "Run tests, type checks, builds, package scripts, and safe inspection commands",
44
+ exec_command: "Run tests, type checks, builds, package scripts, and safe inspection commands",
45
+ update_plan: "Keep the current multi-step coding plan visible and accurate",
44
46
  web_search: "Search the web",
45
47
  web_fetch: "Fetch and extract readable content from a URL",
46
48
  web_extract: "Extract structured content from a URL",
@@ -94,9 +96,10 @@ function buildToolingSection(params) {
94
96
  const name = resolveToolName(tool);
95
97
  toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);
96
98
  }
97
- const shellToolName = resolveToolName("shell");
99
+ const execToolName = resolveToolName("exec_command");
100
+ const planToolName = resolveToolName("update_plan");
98
101
  const readToolName = resolveToolName("read_file");
99
- const editToolName = resolveToolName("edit_file");
102
+ const patchToolName = resolveToolName("apply_patch");
100
103
  const writeToolName = resolveToolName("write_file");
101
104
  const grepToolName = resolveToolName("grep");
102
105
  const findToolName = resolveToolName("find");
@@ -104,11 +107,12 @@ function buildToolingSection(params) {
104
107
  const hasWorkflow = availableTools.has("workflow");
105
108
  const hasToolManual = availableTools.has("tool_manual");
106
109
  const hasRead = availableTools.has("read_file");
107
- const hasEdit = availableTools.has("edit_file");
110
+ const hasPatch = availableTools.has("apply_patch");
108
111
  const hasWrite = availableTools.has("write_file");
109
112
  const hasGrep = availableTools.has("grep");
110
113
  const hasFind = availableTools.has("find");
111
- const hasShell = availableTools.has("shell");
114
+ const hasExec = availableTools.has("exec_command");
115
+ const hasPlan = availableTools.has("update_plan");
112
116
  const orchestrationLines = [];
113
117
  if (hasDelegate) orchestrationLines.push("- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.");
114
118
  if (hasWorkflow) orchestrationLines.push("- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.");
@@ -117,12 +121,13 @@ function buildToolingSection(params) {
117
121
  "Tool availability (filtered by policy):",
118
122
  "Tool names are case-sensitive. Call tools exactly as listed.",
119
123
  toolLines.length > 0 ? toolLines.join("\n") : "- No tools are registered for this session.",
120
- `For long waits, avoid rapid poll loops: use \`${shellToolName}\` with enough yieldMs or poll in reasonable intervals.`,
124
+ `For long waits, avoid rapid poll loops: use \`${execToolName}\` with a sufficient timeout or poll in reasonable intervals.`,
121
125
  hasRead ? `Use \`${readToolName}\` for targeted file inspection before editing; do not rely on filenames alone.` : "",
122
- hasEdit ? `Use \`${editToolName}\` for small source changes; keep patches focused.` : "",
126
+ hasPatch ? `Use \`${patchToolName}\` for source changes; keep patches focused and inspect failures carefully.` : "",
123
127
  hasWrite ? `Use \`${writeToolName}\` only for new files or intentional complete rewrites.` : "",
124
128
  hasGrep || hasFind ? `Use ${[hasGrep ? `\`${grepToolName}\`` : "", hasFind ? `\`${findToolName}\`` : ""].filter(Boolean).join(" and ")} for text/file discovery; use code graph or symbol tools when available for definitions and call relationships.` : "",
125
- hasShell ? `Use \`${shellToolName}\` for verification and safe inspection, not routine file editing.` : "",
129
+ hasExec ? `Use \`${execToolName}\` for verification and safe inspection, not routine file editing.` : "",
130
+ hasPlan ? `Use \`${planToolName}\` for multi-step coding work: keep exactly one active step when work is in progress, and update it after meaningful progress or review.` : "",
126
131
  hasToolManual ? "Some complex tools have built-in manuals. Use `tool_manual(tool)` before non-trivial use." : "",
127
132
  hasDelegate ? "If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done." : "",
128
133
  ...orchestrationLines,
@@ -1 +1 @@
1
- {"version":3,"file":"tooling.js","names":[],"sources":["../../../../../src/agent/prompt/sections/tooling.ts"],"sourcesContent":["const CORE_TOOL_ORDER = [\n 'read_file',\n 'write_file',\n 'edit_file',\n 'grep',\n 'find',\n 'list_dir',\n 'shell',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'browser_use',\n 'send_message',\n 'send_media',\n 'memory_search',\n 'memory_get',\n 'session_search',\n 'curated_memory',\n 'session_status',\n 'tool_manual',\n 'delegate_task',\n 'workflow',\n 'automation',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'todo',\n 'clarify',\n 'text_to_speech',\n 'image',\n 'image_generate',\n 'create_share',\n 'execute_code',\n] as const;\n\nconst CORE_TOOL_SUMMARIES: Record<string, string> = {\n read_file: 'Read targeted file contents; prefer this over shell cat/sed for inspection',\n write_file: 'Create new files or intentional complete rewrites',\n edit_file: 'Make precise, minimal edits to existing files',\n grep: 'Search file contents for literals, errors, config values, and docs',\n find: 'Find files by glob pattern',\n list_dir: 'List directory contents',\n shell: 'Run tests, type checks, builds, package scripts, and safe inspection commands',\n web_search: 'Search the web',\n web_fetch: 'Fetch and extract readable content from a URL',\n web_extract: 'Extract structured content from a URL',\n browser_use: 'Control the configured browser',\n send_message: 'Send messages to the current channel',\n send_media: 'Send media attachments to the current channel',\n memory_search: 'Semantic search over indexed memory sources',\n memory_get: 'Read specific lines from memory sources returned by search',\n session_search: 'Search other chat sessions or list recent sessions',\n curated_memory: 'Read/write structured notes under agent home memories/',\n session_status: 'Show session usage/time/model state',\n tool_manual: 'Load built-in usage manuals for complex tools',\n delegate_task: 'Spawn an isolated sub-agent for a delegated task',\n workflow: 'Start a persisted multi-phase workflow run',\n automation: 'Manage product automations',\n skills_list: 'List available skills',\n skill_view: 'Load a skill SKILL.md or sub-documents',\n skill_manage: 'Create or update skills on disk',\n todo: 'Manage in-session todo items',\n clarify: 'Ask the user a blocking clarification question',\n text_to_speech: 'Send a standalone voice message',\n image: 'Analyze an image with the configured vision model',\n image_generate: 'Generate images with the configured image model',\n create_share: 'Create a shareable link for workspace files',\n execute_code: 'Run code in a sandbox with a restricted tool subset',\n};\n\nexport function buildToolingSection(params: {\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n}): string {\n const rawToolNames = (params.toolNames ?? []).map((tool) => tool.trim()).filter(Boolean);\n const canonicalByNormalized = new Map<string, string>();\n for (const name of rawToolNames) {\n const normalized = name.toLowerCase();\n if (!canonicalByNormalized.has(normalized)) {\n canonicalByNormalized.set(normalized, name);\n }\n }\n const resolveToolName = (normalized: string) =>\n canonicalByNormalized.get(normalized) ?? normalized;\n\n const normalizedTools = rawToolNames.map((tool) => tool.toLowerCase());\n const availableTools = new Set(normalizedTools);\n\n const externalToolSummaries = new Map<string, string>();\n for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {\n const normalized = key.trim().toLowerCase();\n if (!normalized || !value?.trim()) {\n continue;\n }\n externalToolSummaries.set(normalized, value.trim());\n }\n\n const extraTools = Array.from(\n new Set(normalizedTools.filter((tool) => !CORE_TOOL_ORDER.includes(tool as (typeof CORE_TOOL_ORDER)[number]))),\n );\n const enabledTools = CORE_TOOL_ORDER.filter((tool) => availableTools.has(tool));\n const toolLines = enabledTools.map((tool) => {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n return summary ? `- ${name}: ${summary}` : `- ${name}`;\n });\n for (const tool of extraTools.toSorted()) {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);\n }\n\n const shellToolName = resolveToolName('shell');\n const readToolName = resolveToolName('read_file');\n const editToolName = resolveToolName('edit_file');\n const writeToolName = resolveToolName('write_file');\n const grepToolName = resolveToolName('grep');\n const findToolName = resolveToolName('find');\n const hasDelegate = availableTools.has('delegate_task');\n const hasWorkflow = availableTools.has('workflow');\n const hasToolManual = availableTools.has('tool_manual');\n const hasRead = availableTools.has('read_file');\n const hasEdit = availableTools.has('edit_file');\n const hasWrite = availableTools.has('write_file');\n const hasGrep = availableTools.has('grep');\n const hasFind = availableTools.has('find');\n const hasShell = availableTools.has('shell');\n\n const orchestrationLines: string[] = [];\n if (hasDelegate) {\n orchestrationLines.push(\n '- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.',\n );\n }\n if (hasWorkflow) {\n orchestrationLines.push(\n '- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.',\n );\n }\n\n return [\n '## Tooling',\n 'Tool availability (filtered by policy):',\n 'Tool names are case-sensitive. Call tools exactly as listed.',\n toolLines.length > 0\n ? toolLines.join('\\n')\n : '- No tools are registered for this session.',\n `For long waits, avoid rapid poll loops: use \\`${shellToolName}\\` with enough yieldMs or poll in reasonable intervals.`,\n hasRead\n ? `Use \\`${readToolName}\\` for targeted file inspection before editing; do not rely on filenames alone.`\n : '',\n hasEdit\n ? `Use \\`${editToolName}\\` for small source changes; keep patches focused.`\n : '',\n hasWrite\n ? `Use \\`${writeToolName}\\` only for new files or intentional complete rewrites.`\n : '',\n hasGrep || hasFind\n ? `Use ${[\n hasGrep ? `\\`${grepToolName}\\`` : '',\n hasFind ? `\\`${findToolName}\\`` : '',\n ].filter(Boolean).join(' and ')} for text/file discovery; use code graph or symbol tools when available for definitions and call relationships.`\n : '',\n hasShell\n ? `Use \\`${shellToolName}\\` for verification and safe inspection, not routine file editing.`\n : '',\n hasToolManual\n ? 'Some complex tools have built-in manuals. Use `tool_manual(tool)` before non-trivial use.'\n : '',\n hasDelegate\n ? 'If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done.'\n : '',\n ...orchestrationLines,\n 'Do not poll delegate/workflow status in a tight loop; check on-demand or wait for completion.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nexport function hasSkillsTools(toolNames: string[]): boolean {\n const normalized = new Set(toolNames.map((t) => t.toLowerCase()));\n return normalized.has('skills_list') || normalized.has('skill_view');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tooling.js","names":[],"sources":["../../../../../src/agent/prompt/sections/tooling.ts"],"sourcesContent":["const CORE_TOOL_ORDER = [\n 'read_file',\n 'write_file',\n 'apply_patch',\n 'grep',\n 'find',\n 'list_dir',\n 'exec_command',\n 'update_plan',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'browser_use',\n 'send_message',\n 'send_media',\n 'memory_search',\n 'memory_get',\n 'session_search',\n 'curated_memory',\n 'session_status',\n 'tool_manual',\n 'delegate_task',\n 'workflow',\n 'automation',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'todo',\n 'clarify',\n 'text_to_speech',\n 'image',\n 'image_generate',\n 'create_share',\n 'execute_code',\n] as const;\n\nconst CORE_TOOL_SUMMARIES: Record<string, string> = {\n read_file: 'Read targeted file contents before editing',\n write_file: 'Create new files or intentional complete rewrites; prefer apply_patch for code changes',\n apply_patch: 'Apply strict patches for source edits',\n grep: 'Search file contents for literals, errors, config values, and docs',\n find: 'Find files by glob pattern',\n list_dir: 'List directory contents',\n exec_command: 'Run tests, type checks, builds, package scripts, and safe inspection commands',\n update_plan: 'Keep the current multi-step coding plan visible and accurate',\n web_search: 'Search the web',\n web_fetch: 'Fetch and extract readable content from a URL',\n web_extract: 'Extract structured content from a URL',\n browser_use: 'Control the configured browser',\n send_message: 'Send messages to the current channel',\n send_media: 'Send media attachments to the current channel',\n memory_search: 'Semantic search over indexed memory sources',\n memory_get: 'Read specific lines from memory sources returned by search',\n session_search: 'Search other chat sessions or list recent sessions',\n curated_memory: 'Read/write structured notes under agent home memories/',\n session_status: 'Show session usage/time/model state',\n tool_manual: 'Load built-in usage manuals for complex tools',\n delegate_task: 'Spawn an isolated sub-agent for a delegated task',\n workflow: 'Start a persisted multi-phase workflow run',\n automation: 'Manage product automations',\n skills_list: 'List available skills',\n skill_view: 'Load a skill SKILL.md or sub-documents',\n skill_manage: 'Create or update skills on disk',\n todo: 'Manage in-session todo items',\n clarify: 'Ask the user a blocking clarification question',\n text_to_speech: 'Send a standalone voice message',\n image: 'Analyze an image with the configured vision model',\n image_generate: 'Generate images with the configured image model',\n create_share: 'Create a shareable link for workspace files',\n execute_code: 'Run code in a sandbox with a restricted tool subset',\n};\n\nexport function buildToolingSection(params: {\n toolNames?: string[];\n toolSummaries?: Record<string, string>;\n}): string {\n const rawToolNames = (params.toolNames ?? []).map((tool) => tool.trim()).filter(Boolean);\n const canonicalByNormalized = new Map<string, string>();\n for (const name of rawToolNames) {\n const normalized = name.toLowerCase();\n if (!canonicalByNormalized.has(normalized)) {\n canonicalByNormalized.set(normalized, name);\n }\n }\n const resolveToolName = (normalized: string) =>\n canonicalByNormalized.get(normalized) ?? normalized;\n\n const normalizedTools = rawToolNames.map((tool) => tool.toLowerCase());\n const availableTools = new Set(normalizedTools);\n\n const externalToolSummaries = new Map<string, string>();\n for (const [key, value] of Object.entries(params.toolSummaries ?? {})) {\n const normalized = key.trim().toLowerCase();\n if (!normalized || !value?.trim()) {\n continue;\n }\n externalToolSummaries.set(normalized, value.trim());\n }\n\n const extraTools = Array.from(\n new Set(normalizedTools.filter((tool) => !CORE_TOOL_ORDER.includes(tool as (typeof CORE_TOOL_ORDER)[number]))),\n );\n const enabledTools = CORE_TOOL_ORDER.filter((tool) => availableTools.has(tool));\n const toolLines = enabledTools.map((tool) => {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n return summary ? `- ${name}: ${summary}` : `- ${name}`;\n });\n for (const tool of extraTools.toSorted()) {\n const summary = CORE_TOOL_SUMMARIES[tool] ?? externalToolSummaries.get(tool);\n const name = resolveToolName(tool);\n toolLines.push(summary ? `- ${name}: ${summary}` : `- ${name}`);\n }\n\n const execToolName = resolveToolName('exec_command');\n const planToolName = resolveToolName('update_plan');\n const readToolName = resolveToolName('read_file');\n const patchToolName = resolveToolName('apply_patch');\n const writeToolName = resolveToolName('write_file');\n const grepToolName = resolveToolName('grep');\n const findToolName = resolveToolName('find');\n const hasDelegate = availableTools.has('delegate_task');\n const hasWorkflow = availableTools.has('workflow');\n const hasToolManual = availableTools.has('tool_manual');\n const hasRead = availableTools.has('read_file');\n const hasPatch = availableTools.has('apply_patch');\n const hasWrite = availableTools.has('write_file');\n const hasGrep = availableTools.has('grep');\n const hasFind = availableTools.has('find');\n const hasExec = availableTools.has('exec_command');\n const hasPlan = availableTools.has('update_plan');\n\n const orchestrationLines: string[] = [];\n if (hasDelegate) {\n orchestrationLines.push(\n '- Sub-agent delegation → use `delegate_task(goal, context?, toolset?)` for focused parallel work; results return to you automatically.',\n );\n }\n if (hasWorkflow) {\n orchestrationLines.push(\n '- Multi-phase workflows → use `workflow` to start persisted runs with subagents when a script defines phases.',\n );\n }\n\n return [\n '## Tooling',\n 'Tool availability (filtered by policy):',\n 'Tool names are case-sensitive. Call tools exactly as listed.',\n toolLines.length > 0\n ? toolLines.join('\\n')\n : '- No tools are registered for this session.',\n `For long waits, avoid rapid poll loops: use \\`${execToolName}\\` with a sufficient timeout or poll in reasonable intervals.`,\n hasRead\n ? `Use \\`${readToolName}\\` for targeted file inspection before editing; do not rely on filenames alone.`\n : '',\n hasPatch\n ? `Use \\`${patchToolName}\\` for source changes; keep patches focused and inspect failures carefully.`\n : '',\n hasWrite\n ? `Use \\`${writeToolName}\\` only for new files or intentional complete rewrites.`\n : '',\n hasGrep || hasFind\n ? `Use ${[\n hasGrep ? `\\`${grepToolName}\\`` : '',\n hasFind ? `\\`${findToolName}\\`` : '',\n ].filter(Boolean).join(' and ')} for text/file discovery; use code graph or symbol tools when available for definitions and call relationships.`\n : '',\n hasExec\n ? `Use \\`${execToolName}\\` for verification and safe inspection, not routine file editing.`\n : '',\n hasPlan\n ? `Use \\`${planToolName}\\` for multi-step coding work: keep exactly one active step when work is in progress, and update it after meaningful progress or review.`\n : '',\n hasToolManual\n ? 'Some complex tools have built-in manuals. Use `tool_manual(tool)` before non-trivial use.'\n : '',\n hasDelegate\n ? 'If a task is complex or long-running, delegate it. Completion is push-based: the sub-agent result returns when done.'\n : '',\n ...orchestrationLines,\n 'Do not poll delegate/workflow status in a tight loop; check on-demand or wait for completion.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nexport function hasSkillsTools(toolNames: string[]): boolean {\n const normalized = new Set(toolNames.map((t) => t.toLowerCase()));\n return normalized.has('skills_list') || normalized.has('skill_view');\n}\n"],"mappings":"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"}
@@ -3,9 +3,9 @@ const DEFAULT_CONFIG = {
3
3
  enabled: true,
4
4
  defaultReminders: [],
5
5
  contextualReminders: {
6
- "file.write": ["💡 Tip: edit > write for small changes"],
6
+ "file.write": ["Tip: apply_patch > write_file for small changes"],
7
7
  "file.delete": ["⚠️ Confirming: file deletion"],
8
- "shell.exec": ["🐚 Shell: use pty=true for interactive commands"],
8
+ exec_command: ["Command: use non-interactive commands with clear timeouts"],
9
9
  "web.fetch": ["🌐 Web: check for rate limits on repeated calls"]
10
10
  },
11
11
  appendToToolResults: true,
@@ -1 +1 @@
1
- {"version":3,"file":"system-reminder.js","names":[],"sources":["../../../../src/agent/prompt/system-reminder.ts"],"sourcesContent":["/**\n * System Reminder - Contextual tips after tool execution\n * \n * Based on Agent Harness theory: \"Fixed system reminders appended after \n * tool execution are more effective than instructions in System Prompt alone\"\n * \n * Optimized: Contextual reminders instead of fixed spam\n */\n\nexport interface SystemReminderConfig {\n enabled: boolean;\n defaultReminders: string[];\n contextualReminders: Record<string, string[]>;\n appendToToolResults: boolean;\n maxRemindersPerTurn: number;\n}\n\n// Default minimal reminders (only essentials)\nconst DEFAULT_REMINDERS: string[] = [];\n\n// Contextual reminders based on tool type\nconst CONTEXTUAL_REMINDERS: Record<string, string[]> = {\n 'file.write': ['💡 Tip: edit > write for small changes'],\n 'file.delete': ['⚠️ Confirming: file deletion'],\n 'shell.exec': ['🐚 Shell: use pty=true for interactive commands'],\n 'web.fetch': ['🌐 Web: check for rate limits on repeated calls'],\n};\n\nconst DEFAULT_CONFIG: SystemReminderConfig = {\n enabled: true,\n defaultReminders: DEFAULT_REMINDERS,\n contextualReminders: CONTEXTUAL_REMINDERS,\n appendToToolResults: true,\n maxRemindersPerTurn: 2, // Reduced from 3\n};\n\nexport class SystemReminder {\n private config: SystemReminderConfig;\n private reminderCountThisTurn = 0;\n\n constructor(config: Partial<SystemReminderConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Append default reminders (when configured and under per-turn cap).\n */\n getReminderText(): string {\n if (!this.config.enabled) {\n return '';\n }\n\n if (this.reminderCountThisTurn >= this.config.maxRemindersPerTurn) {\n return ''; // Don't spam too many reminders\n }\n\n if (this.config.defaultReminders.length === 0) {\n return '';\n }\n\n this.reminderCountThisTurn++;\n return this.config.defaultReminders.join('\\n');\n }\n\n /**\n * Get contextual reminder based on tool name\n */\n getContextualReminder(toolName: string): string {\n if (!this.config.enabled) {\n return '';\n }\n\n if (this.reminderCountThisTurn >= this.config.maxRemindersPerTurn) {\n return '';\n }\n\n const reminders = this.config.contextualReminders[toolName];\n if (!reminders || reminders.length === 0) {\n return '';\n }\n\n this.reminderCountThisTurn++;\n // Pick first matching reminder (could randomize if multiple)\n return reminders[0];\n }\n\n /**\n * Append reminder to tool result content\n */\n appendToResult(result: unknown, toolName?: string): unknown {\n if (!this.config.enabled || !this.config.appendToToolResults) {\n return result;\n }\n\n // Try contextual reminder first, fall back to default\n const reminderText = toolName \n ? this.getContextualReminder(toolName) \n : this.getReminderText();\n \n if (!reminderText) {\n return result;\n }\n\n // Handle different result formats\n if (result && typeof result === 'object') {\n const res = result as Record<string, unknown>;\n \n if (res.content && Array.isArray(res.content)) {\n // Append to content array\n res.content = [\n ...res.content,\n { type: 'text', text: `\\n${reminderText}` },\n ];\n } else if (typeof res.content === 'string') {\n // Append to string content\n res.content = `${res.content}\\n${reminderText}`;\n }\n \n return res;\n }\n\n return result;\n }\n\n /**\n * Reset turn counter (called at end of turn)\n */\n resetTurn(): void {\n this.reminderCountThisTurn = 0;\n }\n\n /**\n * Update configuration\n */\n setConfig(config: Partial<SystemReminderConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get current config\n */\n getConfig(): SystemReminderConfig {\n return { ...this.config };\n }\n}\n"],"mappings":";AA4BA,MAAM,iBAAuC;CAC3C,SAAS;CACT,kBAAkB,EAAiB;CACnC,qBAAqB;EATrB,cAAc,CAAC,yCAAyC;EACxD,eAAe,CAAC,+BAA+B;EAC/C,cAAc,CAAC,kDAAkD;EACjE,aAAa,CAAC,kDAAkD;EAMvB;CACzC,qBAAqB;CACrB,qBAAqB;CACtB;AAED,IAAa,iBAAb,MAA4B;CAC1B;CACA,wBAAgC;CAEhC,YAAY,SAAwC,EAAE,EAAE;AACtD,OAAK,SAAS;GAAE,GAAG;GAAgB,GAAG;GAAQ;;;;;CAMhD,kBAA0B;AACxB,MAAI,CAAC,KAAK,OAAO,QACf,QAAO;AAGT,MAAI,KAAK,yBAAyB,KAAK,OAAO,oBAC5C,QAAO;AAGT,MAAI,KAAK,OAAO,iBAAiB,WAAW,EAC1C,QAAO;AAGT,OAAK;AACL,SAAO,KAAK,OAAO,iBAAiB,KAAK,KAAK;;;;;CAMhD,sBAAsB,UAA0B;AAC9C,MAAI,CAAC,KAAK,OAAO,QACf,QAAO;AAGT,MAAI,KAAK,yBAAyB,KAAK,OAAO,oBAC5C,QAAO;EAGT,MAAM,YAAY,KAAK,OAAO,oBAAoB;AAClD,MAAI,CAAC,aAAa,UAAU,WAAW,EACrC,QAAO;AAGT,OAAK;AAEL,SAAO,UAAU;;;;;CAMnB,eAAe,QAAiB,UAA4B;AAC1D,MAAI,CAAC,KAAK,OAAO,WAAW,CAAC,KAAK,OAAO,oBACvC,QAAO;EAIT,MAAM,eAAe,WACjB,KAAK,sBAAsB,SAAS,GACpC,KAAK,iBAAiB;AAE1B,MAAI,CAAC,aACH,QAAO;AAIT,MAAI,UAAU,OAAO,WAAW,UAAU;GACxC,MAAM,MAAM;AAEZ,OAAI,IAAI,WAAW,MAAM,QAAQ,IAAI,QAAQ,CAE3C,KAAI,UAAU,CACZ,GAAG,IAAI,SACP;IAAE,MAAM;IAAQ,MAAM,KAAK;IAAgB,CAC5C;YACQ,OAAO,IAAI,YAAY,SAEhC,KAAI,UAAU,GAAG,IAAI,QAAQ,IAAI;AAGnC,UAAO;;AAGT,SAAO;;;;;CAMT,YAAkB;AAChB,OAAK,wBAAwB;;;;;CAM/B,UAAU,QAA6C;AACrD,OAAK,SAAS;GAAE,GAAG,KAAK;GAAQ,GAAG;GAAQ;;;;;CAM7C,YAAkC;AAChC,SAAO,EAAE,GAAG,KAAK,QAAQ"}
1
+ {"version":3,"file":"system-reminder.js","names":[],"sources":["../../../../src/agent/prompt/system-reminder.ts"],"sourcesContent":["/**\n * System Reminder - Contextual tips after tool execution\n * \n * Based on Agent Harness theory: \"Fixed system reminders appended after \n * tool execution are more effective than instructions in System Prompt alone\"\n * \n * Optimized: Contextual reminders instead of fixed spam\n */\n\nexport interface SystemReminderConfig {\n enabled: boolean;\n defaultReminders: string[];\n contextualReminders: Record<string, string[]>;\n appendToToolResults: boolean;\n maxRemindersPerTurn: number;\n}\n\n// Default minimal reminders (only essentials)\nconst DEFAULT_REMINDERS: string[] = [];\n\n// Contextual reminders based on tool type\nconst CONTEXTUAL_REMINDERS: Record<string, string[]> = {\n 'file.write': ['Tip: apply_patch > write_file for small changes'],\n 'file.delete': ['⚠️ Confirming: file deletion'],\n exec_command: ['Command: use non-interactive commands with clear timeouts'],\n 'web.fetch': ['🌐 Web: check for rate limits on repeated calls'],\n};\n\nconst DEFAULT_CONFIG: SystemReminderConfig = {\n enabled: true,\n defaultReminders: DEFAULT_REMINDERS,\n contextualReminders: CONTEXTUAL_REMINDERS,\n appendToToolResults: true,\n maxRemindersPerTurn: 2, // Reduced from 3\n};\n\nexport class SystemReminder {\n private config: SystemReminderConfig;\n private reminderCountThisTurn = 0;\n\n constructor(config: Partial<SystemReminderConfig> = {}) {\n this.config = { ...DEFAULT_CONFIG, ...config };\n }\n\n /**\n * Append default reminders (when configured and under per-turn cap).\n */\n getReminderText(): string {\n if (!this.config.enabled) {\n return '';\n }\n\n if (this.reminderCountThisTurn >= this.config.maxRemindersPerTurn) {\n return ''; // Don't spam too many reminders\n }\n\n if (this.config.defaultReminders.length === 0) {\n return '';\n }\n\n this.reminderCountThisTurn++;\n return this.config.defaultReminders.join('\\n');\n }\n\n /**\n * Get contextual reminder based on tool name\n */\n getContextualReminder(toolName: string): string {\n if (!this.config.enabled) {\n return '';\n }\n\n if (this.reminderCountThisTurn >= this.config.maxRemindersPerTurn) {\n return '';\n }\n\n const reminders = this.config.contextualReminders[toolName];\n if (!reminders || reminders.length === 0) {\n return '';\n }\n\n this.reminderCountThisTurn++;\n // Pick first matching reminder (could randomize if multiple)\n return reminders[0];\n }\n\n /**\n * Append reminder to tool result content\n */\n appendToResult(result: unknown, toolName?: string): unknown {\n if (!this.config.enabled || !this.config.appendToToolResults) {\n return result;\n }\n\n // Try contextual reminder first, fall back to default\n const reminderText = toolName \n ? this.getContextualReminder(toolName) \n : this.getReminderText();\n \n if (!reminderText) {\n return result;\n }\n\n // Handle different result formats\n if (result && typeof result === 'object') {\n const res = result as Record<string, unknown>;\n \n if (res.content && Array.isArray(res.content)) {\n // Append to content array\n res.content = [\n ...res.content,\n { type: 'text', text: `\\n${reminderText}` },\n ];\n } else if (typeof res.content === 'string') {\n // Append to string content\n res.content = `${res.content}\\n${reminderText}`;\n }\n \n return res;\n }\n\n return result;\n }\n\n /**\n * Reset turn counter (called at end of turn)\n */\n resetTurn(): void {\n this.reminderCountThisTurn = 0;\n }\n\n /**\n * Update configuration\n */\n setConfig(config: Partial<SystemReminderConfig>): void {\n this.config = { ...this.config, ...config };\n }\n\n /**\n * Get current config\n */\n getConfig(): SystemReminderConfig {\n return { ...this.config };\n }\n}\n"],"mappings":";AA4BA,MAAM,iBAAuC;CAC3C,SAAS;CACT,kBAAkB,EAAiB;CACnC,qBAAqB;EATrB,cAAc,CAAC,kDAAkD;EACjE,eAAe,CAAC,+BAA+B;EAC/C,cAAc,CAAC,4DAA4D;EAC3E,aAAa,CAAC,kDAAkD;EAMvB;CACzC,qBAAqB;CACrB,qBAAqB;CACtB;AAED,IAAa,iBAAb,MAA4B;CAC1B;CACA,wBAAgC;CAEhC,YAAY,SAAwC,EAAE,EAAE;AACtD,OAAK,SAAS;GAAE,GAAG;GAAgB,GAAG;GAAQ;;;;;CAMhD,kBAA0B;AACxB,MAAI,CAAC,KAAK,OAAO,QACf,QAAO;AAGT,MAAI,KAAK,yBAAyB,KAAK,OAAO,oBAC5C,QAAO;AAGT,MAAI,KAAK,OAAO,iBAAiB,WAAW,EAC1C,QAAO;AAGT,OAAK;AACL,SAAO,KAAK,OAAO,iBAAiB,KAAK,KAAK;;;;;CAMhD,sBAAsB,UAA0B;AAC9C,MAAI,CAAC,KAAK,OAAO,QACf,QAAO;AAGT,MAAI,KAAK,yBAAyB,KAAK,OAAO,oBAC5C,QAAO;EAGT,MAAM,YAAY,KAAK,OAAO,oBAAoB;AAClD,MAAI,CAAC,aAAa,UAAU,WAAW,EACrC,QAAO;AAGT,OAAK;AAEL,SAAO,UAAU;;;;;CAMnB,eAAe,QAAiB,UAA4B;AAC1D,MAAI,CAAC,KAAK,OAAO,WAAW,CAAC,KAAK,OAAO,oBACvC,QAAO;EAIT,MAAM,eAAe,WACjB,KAAK,sBAAsB,SAAS,GACpC,KAAK,iBAAiB;AAE1B,MAAI,CAAC,aACH,QAAO;AAIT,MAAI,UAAU,OAAO,WAAW,UAAU;GACxC,MAAM,MAAM;AAEZ,OAAI,IAAI,WAAW,MAAM,QAAQ,IAAI,QAAQ,CAE3C,KAAI,UAAU,CACZ,GAAG,IAAI,SACP;IAAE,MAAM;IAAQ,MAAM,KAAK;IAAgB,CAC5C;YACQ,OAAO,IAAI,YAAY,SAEhC,KAAI,UAAU,GAAG,IAAI,QAAQ,IAAI;AAGnC,UAAO;;AAGT,SAAO;;;;;CAMT,YAAkB;AAChB,OAAK,wBAAwB;;;;;CAM/B,UAAU,QAA6C;AACrD,OAAK,SAAS;GAAE,GAAG,KAAK;GAAQ,GAAG;GAAQ;;;;;CAM7C,YAAkC;AAChC,SAAO,EAAE,GAAG,KAAK,QAAQ"}
@@ -122,6 +122,18 @@ const HIGH_PATTERNS = [
122
122
  pattern: /\blaunchctl\s+(load|unload|start|stop)\b/,
123
123
  reason: "macOS launchctl manipulation"
124
124
  },
125
+ {
126
+ pattern: /\bgit\s+(?:-[^\s]+\s+)*(?!push\s+--force\b)(commit|push|checkout|switch|restore|reset|rebase|merge|cherry-pick|clean|apply|am|stash)\b/,
127
+ reason: "Git command may mutate repository state or publish changes"
128
+ },
129
+ {
130
+ pattern: /\bgit\s+(?:-[^\s]+\s+)*branch\s+(-[dD]|--delete|--move|-m|-M|--set-upstream-to)\b/,
131
+ reason: "Git branch mutation"
132
+ },
133
+ {
134
+ pattern: /\bgit\s+(?:-[^\s]+\s+)*tag\s+(-[adfs]|--delete|--annotate|--force|--sign)\b/,
135
+ reason: "Git tag mutation"
136
+ },
125
137
  {
126
138
  pattern: /\bsudo\s+/,
127
139
  reason: "Sudo command execution"