@xopcai/xopc 0.0.110 → 0.0.112

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 (583) hide show
  1. package/README.md +46 -4
  2. package/README.zh-CN.md +46 -4
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  7. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  8. package/dist/extensions/telegram/src/plugin.js +1 -1
  9. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  10. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  11. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/api/api.js +2 -2
  14. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  15. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  16. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  17. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  18. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  19. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  20. package/dist/extensions/weixin/src/plugin.js +1 -1
  21. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  22. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  23. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  24. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  25. package/dist/gateway/static/root/assets/agent-avatar-dicebear-EhRp-ZMa.js +1 -0
  26. package/dist/gateway/static/root/assets/agent-browser-settings-page-H4foVCiS.js +6 -0
  27. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-DDNw2oNU.js +1 -0
  28. package/dist/gateway/static/root/assets/agents-E_X2kzS1.js +71 -0
  29. package/dist/gateway/static/root/assets/app-management-settings-panel-BIy7KEsM.js +1 -0
  30. package/dist/gateway/static/root/assets/appearance-settings-DGQG8NwA.js +1 -0
  31. package/dist/gateway/static/root/assets/apps-page-BZLvInLr.js +1 -0
  32. package/dist/gateway/static/root/assets/archive-plugin-uuQPupqx.js +1 -0
  33. package/dist/gateway/static/root/assets/attachment-load-DBkv0cAv.js +2 -0
  34. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CybMSIoS.js → attachment-preview-renderer-DonnL2dL.js} +1 -1
  35. package/dist/gateway/static/root/assets/binary-plugins-DxxN_VAR.js +2 -0
  36. package/dist/gateway/static/root/assets/block-editor-CwnUlRmO.js +180 -0
  37. package/dist/gateway/static/root/assets/channels-settings-BHvUKlzw.js +1 -0
  38. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  39. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +1 -0
  40. package/dist/gateway/static/root/assets/config-api-BD-NcD5d.js +3 -0
  41. package/dist/gateway/static/root/assets/config-reload-event-Bjh2zoKp.js +1 -0
  42. package/dist/gateway/static/root/assets/connectors-settings-VBzXcEXL.js +2 -0
  43. package/dist/gateway/static/root/assets/cron-api-C5DoipZA.js +1 -0
  44. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +1 -0
  45. package/dist/gateway/static/root/assets/cron-page-BLTpdm34.js +3 -0
  46. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  47. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  48. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  49. package/dist/gateway/static/root/assets/dreaming-scene-BHMRVEUS.js +4585 -0
  50. package/dist/gateway/static/root/assets/dreaming-settings-DSVhXTPq.js +1 -0
  51. package/dist/gateway/static/root/assets/extension-debug-page-BDHA9o_e.js +1 -0
  52. package/dist/gateway/static/root/assets/{extension-page-W1wiG38F.js → extension-page-DmDLVSPE.js} +1 -1
  53. package/dist/gateway/static/root/assets/extension-settings-page-1124aHw_.js +1 -0
  54. package/dist/gateway/static/root/assets/fetch-DOe56Wmy.js +1 -0
  55. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +2 -0
  56. package/dist/gateway/static/root/assets/format-interval-label-tsMSvBSR.js +1 -0
  57. package/dist/gateway/static/root/assets/gateway-config-api-CsD4FC9D.js +1 -0
  58. package/dist/gateway/static/root/assets/gateway-settings-HQ8FBhY2.js +1 -0
  59. package/dist/gateway/static/root/assets/gateway-startup-retry-C1zg7pH3.js +1 -0
  60. package/dist/gateway/static/root/assets/goal-detail-page-BG3Onph0.js +1 -0
  61. package/dist/gateway/static/root/assets/goals-page-DgeKn8zL.js +2 -0
  62. package/dist/gateway/static/root/assets/goals-settings-B5nI6lgz.js +1 -0
  63. package/dist/gateway/static/root/assets/heartbeat-config-api-CIv42nJD.js +1 -0
  64. package/dist/gateway/static/root/assets/heartbeat-settings-DFcVuJ3M.js +1 -0
  65. package/dist/gateway/static/root/assets/html-workspace-editor-CQLWDiwE.js +1 -0
  66. package/dist/gateway/static/root/assets/index-5A_ZaABy.css +1 -0
  67. package/dist/gateway/static/root/assets/index-BTmbp2AU.js +121 -0
  68. package/dist/gateway/static/root/assets/interval-presets-DGP3S7OB.js +1 -0
  69. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-fETaDYQP.js +1 -0
  70. package/dist/gateway/static/root/assets/locale-store-DjbfSsfA.js +1 -0
  71. package/dist/gateway/static/root/assets/logs-page-B1-b27lK.js +2 -0
  72. package/dist/gateway/static/root/assets/markdown-editor-AssmZFx4.js +2 -0
  73. package/dist/gateway/static/root/assets/markdown-split-CgeBJMOD.js +1 -0
  74. package/dist/gateway/static/root/assets/media-plugins-C30GzlV2.js +1 -0
  75. package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +134 -0
  76. package/dist/gateway/static/root/assets/messages-BUUfPaZ9.js +3 -0
  77. package/dist/gateway/static/root/assets/middleware-Pd0e8Igk.js +1 -0
  78. package/dist/gateway/static/root/assets/models-hub-panel-DPcTS1-u.js +2 -0
  79. package/dist/gateway/static/root/assets/note-detail-page-xeGb4owe.js +2 -0
  80. package/dist/gateway/static/root/assets/note-image-lightbox-t1g0qZYh.js +1 -0
  81. package/dist/gateway/static/root/assets/note-time-hm6JO_Wi.js +1 -0
  82. package/dist/gateway/static/root/assets/notes-page-C_TdnKBe.js +1 -0
  83. package/dist/gateway/static/root/assets/preview-open-alternatives-DeWp9x5g.js +1 -0
  84. package/dist/gateway/static/root/assets/remote-access-hub-BtkPmJIN.js +1 -0
  85. package/dist/gateway/static/root/assets/save-bar-controls-BOaAOJI3.js +1 -0
  86. package/dist/gateway/static/root/assets/schedule-field-BLWLKqgw.js +1 -0
  87. package/dist/gateway/static/root/assets/schema-form-plqRFYT8.js +1 -0
  88. package/dist/gateway/static/root/assets/sessions-page-DOUjxzJm.js +1 -0
  89. package/dist/gateway/static/root/assets/settings-advanced-gate-qK_bnTrw.js +1 -0
  90. package/dist/gateway/static/root/assets/settings-collapsible-section-BP5zRrDI.js +1 -0
  91. package/dist/gateway/static/root/assets/settings-form-section-Bv8MZplG.js +1 -0
  92. package/dist/gateway/static/root/assets/settings-page-DmDfE1ww.js +1 -0
  93. package/dist/gateway/static/root/assets/setup-status-panel-BEFwNcIZ.js +1 -0
  94. package/dist/gateway/static/root/assets/share-preview-page-4OX1YCgp.js +2 -0
  95. package/dist/gateway/static/root/assets/shares-settings-CbKmJZot.js +1 -0
  96. package/dist/gateway/static/root/assets/skill-reload-api-YdtnUHtK.js +1 -0
  97. package/dist/gateway/static/root/assets/skills-page-DwW1IzQ0.js +2 -0
  98. package/dist/gateway/static/root/assets/system-settings-panel-CGy4f_s2.js +1 -0
  99. package/dist/gateway/static/root/assets/theme-store-CD2wtgZV.js +1 -0
  100. package/dist/gateway/static/root/assets/use-agent-defaults-form-BMuMvzl_.js +1 -0
  101. package/dist/gateway/static/root/assets/use-blob-object-url-D4BFuzZB.js +1 -0
  102. package/dist/gateway/static/root/assets/use-channel-catalog-CjGHnDvN.js +1 -0
  103. package/dist/gateway/static/root/assets/use-settings-tab-guard-BMMFa0oA.js +1 -0
  104. package/dist/gateway/static/root/assets/vendor-codemirror-CNP1wPe7.js +45 -0
  105. package/dist/gateway/static/root/assets/voice-api-key-field-DnRbhMNq.js +1 -0
  106. package/dist/gateway/static/root/assets/voice-player-store-D5vzWwls.js +1 -0
  107. package/dist/gateway/static/root/assets/{workflow-page.utils-EYg_xBQS.js → workflow-page.utils-tjGpRVnw.js} +1 -1
  108. package/dist/gateway/static/root/assets/workflows-page-DqqHKGj2.js +18 -0
  109. package/dist/gateway/static/root/favicon-16x16.png +0 -0
  110. package/dist/gateway/static/root/favicon-32x32.png +0 -0
  111. package/dist/gateway/static/root/favicon.ico +0 -0
  112. package/dist/gateway/static/root/favicon.svg +14 -12
  113. package/dist/gateway/static/root/index.html +18 -15
  114. package/dist/package.js +1 -1
  115. package/dist/src/agent/agent-manager.d.ts +28 -2
  116. package/dist/src/agent/agent-manager.js +82 -11
  117. package/dist/src/agent/agent-manager.js.map +1 -1
  118. package/dist/src/agent/agent-scope.js +1 -1
  119. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  120. package/dist/src/agent/context/workspace-seed.js +2 -2
  121. package/dist/src/agent/context/workspace-state.js +1 -1
  122. package/dist/src/agent/context/workspace.js +1 -1
  123. package/dist/src/agent/goals/checklist-judge.d.ts +5 -0
  124. package/dist/src/agent/goals/checklist-judge.js +26 -2
  125. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  126. package/dist/src/agent/goals/evaluate-turn.d.ts +5 -1
  127. package/dist/src/agent/goals/evaluate-turn.js +29 -3
  128. package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
  129. package/dist/src/agent/goals/goal-locale.d.ts +0 -2
  130. package/dist/src/agent/goals/goal-locale.js +3 -16
  131. package/dist/src/agent/goals/goal-locale.js.map +1 -1
  132. package/dist/src/agent/goals/persistent-goal-service.d.ts +9 -0
  133. package/dist/src/agent/goals/persistent-goal-service.js +3 -2
  134. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  135. package/dist/src/agent/goals/post-turn.d.ts +7 -0
  136. package/dist/src/agent/goals/post-turn.js +70 -25
  137. package/dist/src/agent/goals/post-turn.js.map +1 -1
  138. package/dist/src/agent/goals/state.d.ts +0 -5
  139. package/dist/src/agent/goals/state.js +1 -96
  140. package/dist/src/agent/goals/state.js.map +1 -1
  141. package/dist/src/agent/image/load-image-media.js +2 -2
  142. package/dist/src/agent/ipc/inbox.js +3 -3
  143. package/dist/src/agent/ipc/socket.js +1 -1
  144. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  145. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  146. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  147. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  148. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  149. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  150. package/dist/src/agent/memory/dreaming/events.js +1 -1
  151. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  152. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  153. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  154. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  155. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  156. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  157. package/dist/src/agent/memory/memory-flush.js +1 -1
  158. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  159. package/dist/src/agent/messaging/command-handler.d.ts +7 -0
  160. package/dist/src/agent/messaging/command-handler.js +11 -2
  161. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  162. package/dist/src/agent/models/manager.js +1 -1
  163. package/dist/src/agent/prompt/memory/index.js +1 -1
  164. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  165. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  166. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  167. package/dist/src/agent/sandbox/path-policy.js +2 -2
  168. package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
  169. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  170. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  171. package/dist/src/agent/service/process-direct-streaming.js +10 -1
  172. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  173. package/dist/src/agent/service/reconcile-dreaming-cron.js +8 -5
  174. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -1
  175. package/dist/src/agent/service.d.ts +2 -1
  176. package/dist/src/agent/service.js +30 -6
  177. package/dist/src/agent/service.js.map +1 -1
  178. package/dist/src/agent/service.types.d.ts +12 -0
  179. package/dist/src/agent/session/session-config-service.d.ts +8 -0
  180. package/dist/src/agent/session/session-config-service.js +20 -0
  181. package/dist/src/agent/session/session-config-service.js.map +1 -1
  182. package/dist/src/agent/session/session-inspector.js +1 -1
  183. package/dist/src/agent/skills/config.js +2 -2
  184. package/dist/src/agent/skills/filesystem-watcher.d.ts +19 -0
  185. package/dist/src/agent/skills/filesystem-watcher.js +182 -0
  186. package/dist/src/agent/skills/filesystem-watcher.js.map +1 -0
  187. package/dist/src/agent/skills/hub-hash.js +2 -2
  188. package/dist/src/agent/skills/hub-lock.js +1 -1
  189. package/dist/src/agent/skills/hub-pull.js +30 -36
  190. package/dist/src/agent/skills/hub-pull.js.map +1 -1
  191. package/dist/src/agent/skills/index.js +82 -38
  192. package/dist/src/agent/skills/index.js.map +1 -1
  193. package/dist/src/agent/skills/installer.js +2 -2
  194. package/dist/src/agent/skills/managed-store.d.ts +19 -0
  195. package/dist/src/agent/skills/managed-store.js +97 -38
  196. package/dist/src/agent/skills/managed-store.js.map +1 -1
  197. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  198. package/dist/src/agent/skills/skill-manager.d.ts +16 -6
  199. package/dist/src/agent/skills/skill-manager.js +79 -24
  200. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  201. package/dist/src/agent/skills/skill-view-path.js +1 -1
  202. package/dist/src/agent/skills/test-framework.js +1 -1
  203. package/dist/src/agent/skills/types.d.ts +11 -0
  204. package/dist/src/agent/skills/watcher.js +1 -1
  205. package/dist/src/agent/starter-agents.js +1 -1
  206. package/dist/src/agent/tools/cronjob-tool.d.ts +8 -3
  207. package/dist/src/agent/tools/cronjob-tool.js +82 -24
  208. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  209. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  210. package/dist/src/agent/tools/edit.d.ts +2 -0
  211. package/dist/src/agent/tools/edit.js +10 -0
  212. package/dist/src/agent/tools/edit.js.map +1 -1
  213. package/dist/src/agent/tools/factory.js +17 -4
  214. package/dist/src/agent/tools/factory.js.map +1 -1
  215. package/dist/src/agent/tools/find.js +1 -1
  216. package/dist/src/agent/tools/goal-evidence-recorder.d.ts +6 -0
  217. package/dist/src/agent/tools/goal-evidence-recorder.js +34 -0
  218. package/dist/src/agent/tools/goal-evidence-recorder.js.map +1 -0
  219. package/dist/src/agent/tools/goal-tool.d.ts +19 -0
  220. package/dist/src/agent/tools/goal-tool.js +101 -0
  221. package/dist/src/agent/tools/goal-tool.js.map +1 -0
  222. package/dist/src/agent/tools/grep.js +1 -1
  223. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  224. package/dist/src/agent/tools/index.d.ts +1 -0
  225. package/dist/src/agent/tools/index.js +2 -1
  226. package/dist/src/agent/tools/shell.d.ts +2 -0
  227. package/dist/src/agent/tools/shell.js +17 -2
  228. package/dist/src/agent/tools/shell.js.map +1 -1
  229. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  230. package/dist/src/agent/tools/workflow-tool.d.ts +1 -0
  231. package/dist/src/agent/tools/workflow-tool.js +11 -3
  232. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  233. package/dist/src/agent/tools/write.d.ts +2 -0
  234. package/dist/src/agent/tools/write.js +11 -0
  235. package/dist/src/agent/tools/write.js.map +1 -1
  236. package/dist/src/agent/workflow/catalog.js +1 -1
  237. package/dist/src/agent/workspace-runtime/registry.d.ts +5 -0
  238. package/dist/src/agent/workspace-runtime/registry.js +7 -0
  239. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  240. package/dist/src/ai-assist/text-assist.d.ts +39 -0
  241. package/dist/src/ai-assist/text-assist.js +234 -0
  242. package/dist/src/ai-assist/text-assist.js.map +1 -0
  243. package/dist/src/auth/credentials.js +2 -2
  244. package/dist/src/auth/profiles/store.js +2 -2
  245. package/dist/src/auth/sync-provider-auth.js +1 -1
  246. package/dist/src/browser/cache-dir-policy.js +1 -1
  247. package/dist/src/browser/cdp-local-launcher.js +2 -2
  248. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  249. package/dist/src/browser/providers/cloakbrowser.js +5 -5
  250. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  251. package/dist/src/browser/stealth.js +1 -1
  252. package/dist/src/channels/attachments/inbound-persist.d.ts +7 -0
  253. package/dist/src/channels/attachments/inbound-persist.js +20 -2
  254. package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
  255. package/dist/src/channels/outbound/persist-store.js +1 -1
  256. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  257. package/dist/src/channels/pairing/pairing-store.js +2 -2
  258. package/dist/src/chat-commands/agent-edit.js +2 -2
  259. package/dist/src/chat-commands/builtins/config.js +3 -3
  260. package/dist/src/chat-commands/builtins/goal.d.ts +1 -1
  261. package/dist/src/chat-commands/builtins/goal.js +55 -97
  262. package/dist/src/chat-commands/builtins/goal.js.map +1 -1
  263. package/dist/src/chat-commands/builtins/subgoal.d.ts +1 -1
  264. package/dist/src/chat-commands/builtins/subgoal.js +49 -108
  265. package/dist/src/chat-commands/builtins/subgoal.js.map +1 -1
  266. package/dist/src/chat-commands/builtins/system.js +11 -4
  267. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  268. package/dist/src/chat-commands/builtins/workflow.js +132 -8
  269. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  270. package/dist/src/chat-commands/context.d.ts +6 -0
  271. package/dist/src/chat-commands/context.js +12 -0
  272. package/dist/src/chat-commands/context.js.map +1 -1
  273. package/dist/src/chat-commands/types.d.ts +7 -0
  274. package/dist/src/cli/command-catalog.js +43 -0
  275. package/dist/src/cli/command-catalog.js.map +1 -1
  276. package/dist/src/cli/command-loaders.js +1 -0
  277. package/dist/src/cli/command-loaders.js.map +1 -1
  278. package/dist/src/cli/command-manifest.js +4 -0
  279. package/dist/src/cli/command-manifest.js.map +1 -1
  280. package/dist/src/cli/commands/config.js +1 -1
  281. package/dist/src/cli/commands/cron.js +55 -16
  282. package/dist/src/cli/commands/cron.js.map +1 -1
  283. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  284. package/dist/src/cli/commands/doctor/checks/cron-health.js +2 -83
  285. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
  286. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  287. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  288. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  289. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  290. package/dist/src/cli/commands/extension-create.js +1 -1
  291. package/dist/src/cli/commands/extension-dev.js +2 -2
  292. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  293. package/dist/src/cli/commands/extension-pack.js +2 -2
  294. package/dist/src/cli/commands/extension.js +3 -3
  295. package/dist/src/cli/commands/gateway/logs.js +1 -1
  296. package/dist/src/cli/commands/goal.d.ts +4 -0
  297. package/dist/src/cli/commands/goal.js +213 -0
  298. package/dist/src/cli/commands/goal.js.map +1 -0
  299. package/dist/src/cli/commands/image.js +1 -1
  300. package/dist/src/cli/commands/init.js +2 -2
  301. package/dist/src/cli/commands/models.js +1 -1
  302. package/dist/src/cli/commands/onboard.js +11 -5
  303. package/dist/src/cli/commands/onboard.js.map +1 -1
  304. package/dist/src/cli/commands/skills-test.js +1 -1
  305. package/dist/src/cli/templates.js +1 -1
  306. package/dist/src/cli/utils/gateway-client.js +1 -1
  307. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  308. package/dist/src/config/agent-profile.js +1 -1
  309. package/dist/src/config/agent-typed-models.js +1 -1
  310. package/dist/src/config/gateway-bind.js +1 -1
  311. package/dist/src/config/index.js +8 -8
  312. package/dist/src/config/loader.js +4 -4
  313. package/dist/src/config/models-json.js +2 -2
  314. package/dist/src/config/paths-state.js +1 -1
  315. package/dist/src/config/paths.js +1 -1
  316. package/dist/src/config/profile.js +1 -1
  317. package/dist/src/config/reload.js +1 -1
  318. package/dist/src/config/schema.d.ts +115 -2
  319. package/dist/src/config/schema.js +63 -7
  320. package/dist/src/config/schema.js.map +1 -1
  321. package/dist/src/config/web-patch.d.ts +14 -1
  322. package/dist/src/config/web-patch.js +45 -8
  323. package/dist/src/config/web-patch.js.map +1 -1
  324. package/dist/src/config/workspace-path.js +1 -1
  325. package/dist/src/cron/executor.d.ts +2 -0
  326. package/dist/src/cron/executor.js +126 -70
  327. package/dist/src/cron/executor.js.map +1 -1
  328. package/dist/src/cron/index.d.ts +1 -1
  329. package/dist/src/cron/index.js +3 -3
  330. package/dist/src/cron/job-content.js +1 -0
  331. package/dist/src/cron/job-content.js.map +1 -1
  332. package/dist/src/cron/run-log-store.d.ts +1 -0
  333. package/dist/src/cron/run-log-store.js +4 -2
  334. package/dist/src/cron/run-log-store.js.map +1 -1
  335. package/dist/src/cron/schedule.d.ts +10 -0
  336. package/dist/src/cron/schedule.js +85 -0
  337. package/dist/src/cron/schedule.js.map +1 -0
  338. package/dist/src/cron/service.d.ts +34 -77
  339. package/dist/src/cron/service.js +327 -264
  340. package/dist/src/cron/service.js.map +1 -1
  341. package/dist/src/cron/types.d.ts +97 -49
  342. package/dist/src/cron/validation.d.ts +374 -86
  343. package/dist/src/cron/validation.js +156 -129
  344. package/dist/src/cron/validation.js.map +1 -1
  345. package/dist/src/cron/workflow-run-completion.js +1 -1
  346. package/dist/src/daemon/constants.js +1 -1
  347. package/dist/src/daemon/install-plan.js +2 -2
  348. package/dist/src/daemon/launchd.js +2 -2
  349. package/dist/src/daemon/schtasks.js +2 -2
  350. package/dist/src/daemon/systemd.js +2 -2
  351. package/dist/src/extensions/bundle-mcp.js +1 -1
  352. package/dist/src/extensions/discover-extensions.js +2 -2
  353. package/dist/src/extensions/health.js +1 -1
  354. package/dist/src/extensions/install.js +2 -2
  355. package/dist/src/extensions/loader.js +2 -2
  356. package/dist/src/extensions/lockfile.js +3 -3
  357. package/dist/src/extensions/security.js +1 -1
  358. package/dist/src/extensions/update.js +2 -2
  359. package/dist/src/gateway/agents-admin.js +2 -2
  360. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  361. package/dist/src/gateway/chat-stream/mapper.js +6 -2
  362. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  363. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
  364. package/dist/src/gateway/file-path-classifier.js +2 -2
  365. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -1
  366. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  367. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  368. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  369. package/dist/src/gateway/hono/oauth-async.js +1 -1
  370. package/dist/src/gateway/hono/routes/agents.js +1 -1
  371. package/dist/src/gateway/hono/routes/ai-assist.d.ts +3 -0
  372. package/dist/src/gateway/hono/routes/ai-assist.js +66 -0
  373. package/dist/src/gateway/hono/routes/ai-assist.js.map +1 -0
  374. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  375. package/dist/src/gateway/hono/routes/commands-skills.js +7 -0
  376. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  377. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  378. package/dist/src/gateway/hono/routes/cron.js +24 -5
  379. package/dist/src/gateway/hono/routes/cron.js.map +1 -1
  380. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  381. package/dist/src/gateway/hono/routes/goals.d.ts +1 -1
  382. package/dist/src/gateway/hono/routes/goals.js +670 -173
  383. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  384. package/dist/src/gateway/hono/routes/home.d.ts +5 -0
  385. package/dist/src/gateway/hono/routes/home.js +90 -3
  386. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  387. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  388. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  389. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  390. package/dist/src/gateway/hono/routes/models.js +1 -1
  391. package/dist/src/gateway/hono/routes/notes.js +20 -14
  392. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  393. package/dist/src/gateway/hono/routes/shares.js +1 -1
  394. package/dist/src/gateway/hono/routes/workflows.js +8 -4
  395. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  396. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  397. package/dist/src/gateway/hono/sse.js.map +1 -1
  398. package/dist/src/gateway/lock.js +3 -3
  399. package/dist/src/gateway/ports.js +1 -1
  400. package/dist/src/gateway/service/agent-runner.d.ts +2 -0
  401. package/dist/src/gateway/service/agent-runner.js +8 -4
  402. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  403. package/dist/src/gateway/service/config-coordinator.js +1 -1
  404. package/dist/src/gateway/service/marketplace-service.d.ts +22 -10
  405. package/dist/src/gateway/service/marketplace-service.js +46 -5
  406. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  407. package/dist/src/gateway/service/run-gateway-agent.d.ts +3 -0
  408. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  409. package/dist/src/gateway/service.d.ts +8 -0
  410. package/dist/src/gateway/service.js +79 -6
  411. package/dist/src/gateway/service.js.map +1 -1
  412. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  413. package/dist/src/goals/goal-notifications.d.ts +29 -0
  414. package/dist/src/goals/goal-notifications.js +154 -0
  415. package/dist/src/goals/goal-notifications.js.map +1 -0
  416. package/dist/src/goals/goal-queue-store.d.ts +16 -0
  417. package/dist/src/goals/goal-queue-store.js +131 -0
  418. package/dist/src/goals/goal-queue-store.js.map +1 -0
  419. package/dist/src/goals/goal-queue-types.d.ts +31 -0
  420. package/dist/src/goals/goal-queue-types.js +1 -0
  421. package/dist/src/goals/goal-runner.d.ts +17 -0
  422. package/dist/src/goals/goal-runner.js +127 -0
  423. package/dist/src/goals/goal-runner.js.map +1 -0
  424. package/dist/src/goals/goal-service.d.ts +77 -0
  425. package/dist/src/goals/goal-service.js +261 -0
  426. package/dist/src/goals/goal-service.js.map +1 -0
  427. package/dist/src/goals/goal-store.d.ts +38 -0
  428. package/dist/src/goals/goal-store.js +404 -0
  429. package/dist/src/goals/goal-store.js.map +1 -0
  430. package/dist/src/goals/goal-workflow-judge.d.ts +13 -0
  431. package/dist/src/goals/goal-workflow-judge.js +147 -0
  432. package/dist/src/goals/goal-workflow-judge.js.map +1 -0
  433. package/dist/src/goals/index.d.ts +10 -0
  434. package/dist/src/goals/index.js +7 -0
  435. package/dist/src/goals/types.d.ts +119 -0
  436. package/dist/src/goals/types.js +1 -0
  437. package/dist/src/i18n/goals-bundle.js +1 -1
  438. package/dist/src/i18n/index.js +1 -1
  439. package/dist/src/i18n/share-tool-bundle.js +2 -2
  440. package/dist/src/infra/brew.js +1 -1
  441. package/dist/src/infra/package-json.js +1 -1
  442. package/dist/src/infra/package-update-steps.js +1 -1
  443. package/dist/src/infra/path-env.js +2 -2
  444. package/dist/src/infra/restart.js +1 -1
  445. package/dist/src/infra/stable-node-path.js +1 -1
  446. package/dist/src/infra/update-check.js +1 -1
  447. package/dist/src/infra/update-global.js +1 -1
  448. package/dist/src/infra/update-lock.js +2 -2
  449. package/dist/src/infra/update-restart.js +1 -1
  450. package/dist/src/infra/update-runner.js +1 -1
  451. package/dist/src/infra/update-startup.js +1 -1
  452. package/dist/src/infra/write-file-atomic.js +2 -2
  453. package/dist/src/media/store.js +1 -1
  454. package/dist/src/notes/agent-context.js +1 -1
  455. package/dist/src/notes/service.js +1 -1
  456. package/dist/src/notes/store.js +2 -2
  457. package/dist/src/project-trust/trust-store.js +2 -2
  458. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  459. package/dist/src/providers/index.js +1 -1
  460. package/dist/src/providers/model-registry.js +4 -4
  461. package/dist/src/session/init-session-turn.js +2 -2
  462. package/dist/src/session/resolve-session.js +3 -3
  463. package/dist/src/session/session-title.js +2 -2
  464. package/dist/src/session/store.js +1 -1
  465. package/dist/src/share/share-auto.js +2 -2
  466. package/dist/src/share/share-store.js +3 -3
  467. package/dist/src/share/share-thumbnail.js +2 -2
  468. package/dist/src/share/share-zip.js +1 -1
  469. package/dist/src/share/site-share-store.js +3 -3
  470. package/dist/src/share/site-static-serve.js +1 -1
  471. package/dist/src/storage/sqlite/connection.js +1 -1
  472. package/dist/src/storage/sqlite/cron-job-repository.d.ts +6 -0
  473. package/dist/src/storage/sqlite/cron-job-repository.js +70 -0
  474. package/dist/src/storage/sqlite/cron-job-repository.js.map +1 -0
  475. package/dist/src/storage/sqlite/cron-run-repository.js +0 -1
  476. package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -1
  477. package/dist/src/storage/sqlite/index.d.ts +1 -0
  478. package/dist/src/storage/sqlite/index.js +2 -1
  479. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  480. package/dist/src/storage/sqlite/migrations/006_add_goals.sql +108 -0
  481. package/dist/src/storage/sqlite/migrations/007_goal_run_judge_schema.sql +4 -0
  482. package/dist/src/storage/sqlite/migrations/008_goal_queue_workflow_runs.sql +53 -0
  483. package/dist/src/storage/sqlite/migrations/009_cron_jobs.sql +24 -0
  484. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  485. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  486. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  487. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  488. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  489. package/dist/src/storage/sqlite/schema.js +2 -2
  490. package/dist/src/storage/sqlite/schema.sql +188 -0
  491. package/dist/src/tui/clipboard-image.js +3 -3
  492. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  493. package/dist/src/tui/theme-manager.js +1 -1
  494. package/dist/src/tui/tui-command-formatters.js +4 -4
  495. package/dist/src/tui/tui-commands.js +2 -2
  496. package/dist/src/tui/tui-keybindings-file.js +1 -1
  497. package/dist/src/tui/tui-scoped-models.js +2 -2
  498. package/dist/src/tui/tui-settings.js +1 -1
  499. package/dist/src/tui/tui-startup-resources.js +1 -1
  500. package/dist/src/tui/tui.js +6 -6
  501. package/dist/src/tunnel/frpc-binary.js +4 -4
  502. package/dist/src/tunnel/frpc-config.js +1 -1
  503. package/dist/src/tunnel/frpc-extract.js +1 -1
  504. package/dist/src/tunnel/tunnel-state.js +1 -1
  505. package/dist/src/utils/logger/audit.js +1 -1
  506. package/dist/src/utils/logger/log-store.js +1 -1
  507. package/dist/src/utils/logger/rotation.js +1 -1
  508. package/dist/src/utils/logger/stats.d.ts +1 -1
  509. package/dist/src/utils/logger/streams.js +1 -1
  510. package/dist/src/voice/tts/audio.js +1 -1
  511. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  512. package/dist/src/workflows/domain/run.d.ts +1 -0
  513. package/dist/src/workflows/domain/run.js.map +1 -1
  514. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  515. package/dist/src/workflows/engine/projector.js +23 -14
  516. package/dist/src/workflows/engine/projector.js.map +1 -1
  517. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  518. package/dist/src/workflows/engine/workflow-engine.js +36 -0
  519. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  520. package/dist/src/workflows/index.js +1 -1
  521. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  522. package/dist/src/workflows/service/workflow-run-service.js +7 -3
  523. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  524. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  525. package/dist/src/workflows/service/workflow-session-bridge.js +8 -1
  526. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  527. package/dist/src/workflows/store/event-store.js +1 -1
  528. package/dist/src/workflows/store/run-index-store.d.ts +8 -0
  529. package/dist/src/workflows/store/run-index-store.js +58 -0
  530. package/dist/src/workflows/store/run-index-store.js.map +1 -0
  531. package/dist/src/workflows/store/run-store.d.ts +2 -0
  532. package/dist/src/workflows/store/run-store.js +15 -22
  533. package/dist/src/workflows/store/run-store.js.map +1 -1
  534. package/package.json +10 -5
  535. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  536. package/dist/gateway/static/root/assets/agents-CFFioJCI.js +0 -78
  537. package/dist/gateway/static/root/assets/apps-page-BYDmkbzG.js +0 -1
  538. package/dist/gateway/static/root/assets/channels-settings-CsbDaMvd.js +0 -1
  539. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +0 -1
  540. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +0 -1
  541. package/dist/gateway/static/root/assets/cron-page-Apk-7p4p.js +0 -1
  542. package/dist/gateway/static/root/assets/dist-DmGDgpy2.js +0 -1
  543. package/dist/gateway/static/root/assets/extension-debug-page-pxFC-tUa.js +0 -1
  544. package/dist/gateway/static/root/assets/extension-settings-page-COXSv6xP.js +0 -1
  545. package/dist/gateway/static/root/assets/fetch-CFdKBnE6.js +0 -1
  546. package/dist/gateway/static/root/assets/gateway-startup-retry-DdngdObI.js +0 -1
  547. package/dist/gateway/static/root/assets/heartbeat-config-api-DcmAMYmN.js +0 -1
  548. package/dist/gateway/static/root/assets/index-C_2yKRJX.js +0 -4845
  549. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +0 -1
  550. package/dist/gateway/static/root/assets/logs-page-DvTWUOzd.js +0 -2
  551. package/dist/gateway/static/root/assets/note-detail-page-CZbdugWZ.js +0 -180
  552. package/dist/gateway/static/root/assets/note-time-RdyBZxj3.js +0 -1
  553. package/dist/gateway/static/root/assets/notes-page-mEAwy3e1.js +0 -1
  554. package/dist/gateway/static/root/assets/schema-form-DEvdni_r.js +0 -1
  555. package/dist/gateway/static/root/assets/sessions-page-BsgffzV4.js +0 -1
  556. package/dist/gateway/static/root/assets/settings-advanced-gate-t6v8Dwb8.js +0 -2
  557. package/dist/gateway/static/root/assets/settings-form-section-BoYYZmJG.js +0 -1
  558. package/dist/gateway/static/root/assets/settings-page-ClIthYF8.js +0 -3
  559. package/dist/gateway/static/root/assets/share-preview-page-Dd9et7KD.js +0 -2
  560. package/dist/gateway/static/root/assets/skills-page-DEXtxyfQ.js +0 -2
  561. package/dist/gateway/static/root/assets/theme-store-BZozwAeK.js +0 -1
  562. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +0 -3
  563. package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +0 -45
  564. package/dist/gateway/static/root/assets/voice-api-key-field-CNrKzQrf.js +0 -1
  565. package/dist/gateway/static/root/assets/workflows-page-EMZkzJNN.js +0 -18
  566. package/dist/gateway/static/root/favicon-16.png +0 -0
  567. package/dist/gateway/static/root/favicon-32.png +0 -0
  568. package/dist/src/agent/goals/checklist-user.d.ts +0 -24
  569. package/dist/src/agent/goals/checklist-user.js +0 -92
  570. package/dist/src/agent/goals/checklist-user.js.map +0 -1
  571. package/dist/src/agent/goals/goal-run-store.d.ts +0 -19
  572. package/dist/src/agent/goals/goal-run-store.js +0 -138
  573. package/dist/src/agent/goals/goal-run-store.js.map +0 -1
  574. package/dist/src/agent/goals/goal-run-types.d.ts +0 -28
  575. package/dist/src/agent/goals/goal-run-types.js +0 -6
  576. package/dist/src/agent/goals/goal-run-types.js.map +0 -1
  577. package/dist/src/agent/goals/patch-from-user-action.d.ts +0 -20
  578. package/dist/src/agent/goals/patch-from-user-action.js +0 -103
  579. package/dist/src/agent/goals/patch-from-user-action.js.map +0 -1
  580. package/dist/src/cron/persistence.d.ts +0 -62
  581. package/dist/src/cron/persistence.js +0 -188
  582. package/dist/src/cron/persistence.js.map +0 -1
  583. /package/dist/gateway/static/root/assets/{note-detail-page-D4ZIVQbk.css → block-editor-D4ZIVQbk.css} +0 -0
@@ -41,7 +41,7 @@ async function tryRunSlashCommand(deps, ctx, content, options) {
41
41
  aggregatedText: ""
42
42
  };
43
43
  try {
44
- const { aggregatedText } = await deps.commandHandler.executeCommandAndAggregateReply(parsed.command, parsed.args, {
44
+ const { aggregatedText, metadata } = await deps.commandHandler.executeCommandAndAggregateReply(parsed.command, parsed.args, {
45
45
  sessionKey: ctx.sessionKey,
46
46
  channel: ctx.channel,
47
47
  chatId: ctx.chatId,
@@ -52,7 +52,8 @@ async function tryRunSlashCommand(deps, ctx, content, options) {
52
52
  return {
53
53
  matched: true,
54
54
  aggregatedText: aggregatedText ?? "",
55
- command: parsed.command
55
+ command: parsed.command,
56
+ metadata
56
57
  };
57
58
  } catch (err) {
58
59
  const em = err instanceof Error ? err.message : String(err);
@@ -1 +1 @@
1
- {"version":3,"file":"direct-turn-helpers.js","names":[],"sources":["../../../../src/agent/service/direct-turn-helpers.ts"],"sourcesContent":["/**\n * Shared building blocks for the two direct-turn entry points (streaming\n * webchat SSE and one-shot CLI). Both flows do the same hydrate → maybe-slash\n * → run-embedded-turn → after-turn dance; this module captures that core so\n * the entry points only manage their I/O specifics (event sink, voice STT,\n * TTS, transcript persistence).\n */\n\nimport crypto from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport { commandRegistry } from '../../chat-commands/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport { shouldSkipResetOverlapCommand } from '../../session/reset-triggers.js';\nimport { hydrateUserTurnForLlm, type TranscriptUserMessage } from '../inbound/attachment-pipeline.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\n\nexport interface HydratePerTurnStateDeps {\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n}\n\n/** Workspace + model + thinking level — common prep before any direct turn. */\nexport async function hydratePerTurnState(\n deps: HydratePerTurnStateDeps,\n sessionKey: string,\n thinking?: string,\n): Promise<void> {\n await deps.hydrateSessionWorkspaceFromStore(sessionKey);\n await deps.hydrateSessionModelFromStore(sessionKey);\n await deps.applyResolvedThinkingLevel(sessionKey, thinking);\n}\n\nexport interface SlashCommandOutcome {\n /** True if the input parsed as a registered slash command (handled or not). */\n matched: boolean;\n /** Aggregated user-visible reply text (assistant view). */\n aggregatedText: string;\n /** The parsed command name when matched. */\n command?: string;\n}\n\nexport interface TryRunSlashCommandDeps {\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n log: { warn: (obj: Record<string, unknown>, msg: string) => void };\n}\n\n/**\n * Detect a slash command and, if registered, execute it and aggregate the reply\n * text. Errors thrown inside the command surface as `aggregatedText` so callers\n * can persist the receipt or stream it as a token.\n */\nexport async function tryRunSlashCommand(\n deps: TryRunSlashCommandDeps,\n ctx: {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId?: string;\n isGroup?: boolean;\n inboundMetadata?: Record<string, unknown>;\n },\n content: string,\n options?: { skipResetCommands?: boolean },\n): Promise<SlashCommandOutcome> {\n const parsed = parseSlashCommand(content);\n if (!parsed) {\n return { matched: false, aggregatedText: '' };\n }\n if (options?.skipResetCommands && shouldSkipResetOverlapCommand(parsed.command, true)) {\n return { matched: false, aggregatedText: '' };\n }\n if (!commandRegistry.has(parsed.command)) {\n return { matched: false, aggregatedText: '' };\n }\n try {\n const { aggregatedText } = await deps.commandHandler.executeCommandAndAggregateReply(\n parsed.command,\n parsed.args,\n {\n sessionKey: ctx.sessionKey,\n channel: ctx.channel,\n chatId: ctx.chatId,\n senderId: ctx.senderId ?? '',\n isGroup: ctx.isGroup ?? false,\n inboundMetadata: ctx.inboundMetadata ?? {},\n },\n );\n return { matched: true, aggregatedText: aggregatedText ?? '', command: parsed.command };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n deps.log.warn(\n { err, sessionKey: ctx.sessionKey, command: parsed.command },\n `Slash command failed: ${em}`,\n );\n return { matched: true, aggregatedText: `Command error: ${em}`, command: parsed.command };\n }\n}\n\nexport interface RunDirectAgentTurnDeps {\n sessionStore: SessionStore;\n agentManager: AgentInstanceGateway;\n modelManager: ModelManager;\n config: Config | undefined;\n}\n\nexport interface RunDirectAgentTurnInput {\n sessionKey: string;\n runId?: string;\n userMessage: AgentMessage;\n abortSignal?: AbortSignal;\n sourceImages?: ImageContent[];\n onEvent?: (event: EmbeddedStreamEvent) => void;\n}\n\nexport interface RunDirectAgentTurnResult {\n ok: boolean;\n errorMessage?: string;\n lastAssistantText?: string;\n}\n\n/**\n * Convert a user message into an embedded turn, including the standard memory\n * prefetch + background-review nudge wiring used by every direct entry point.\n */\nexport async function runDirectAgentTurn(\n deps: RunDirectAgentTurnDeps,\n input: RunDirectAgentTurnInput,\n): Promise<RunDirectAgentTurnResult> {\n const userPlain = extractAgentUserPlainText(input.userMessage);\n const userMessageForModel = await deps.agentManager.applyMemoryPrefetchToUserMessage(\n input.userMessage,\n input.sessionKey,\n );\n\n const modelRef = deps.modelManager.getModelForSession(input.sessionKey);\n const llmTurn = await hydrateUserTurnForLlm({\n message: input.userMessage as TranscriptUserMessage,\n modelRef,\n });\n const sourceImages = resolveImageHandlingStrategy(modelRef) === 'native' ? (input.sourceImages ?? []) : [];\n const llmImages = [...llmTurn.images, ...sourceImages];\n\n const result = await runEmbeddedTurnForSession({\n sessionKey: input.sessionKey,\n runId: input.runId ?? crypto.randomUUID(),\n userMessage: userMessageForModel,\n llmImages,\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n getConfig: () => deps.config,\n abortSignal: input.abortSignal,\n beforeTurn: () => deps.agentManager.beginBackgroundReviewUserTurn(input.sessionKey),\n onEvent: input.onEvent,\n });\n\n deps.agentManager.afterAgentTurn(input.sessionKey, userPlain);\n deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.sessionKey);\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkCA,eAAsB,oBACpB,MACA,YACA,UACe;AACf,OAAM,KAAK,iCAAiC,WAAW;AACvD,OAAM,KAAK,6BAA6B,WAAW;AACnD,OAAM,KAAK,2BAA2B,YAAY,SAAS;;;;;;;AAsB7D,eAAsB,mBACpB,MACA,KAQA,SACA,SAC8B;CAC9B,MAAM,SAAS,kBAAkB,QAAQ;AACzC,KAAI,CAAC,OACH,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,SAAS,qBAAqB,8BAA8B,OAAO,SAAS,KAAK,CACnF,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,CAAC,gBAAgB,IAAI,OAAO,QAAQ,CACtC,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI;EACF,MAAM,EAAE,mBAAmB,MAAM,KAAK,eAAe,gCACnD,OAAO,SACP,OAAO,MACP;GACE,YAAY,IAAI;GAChB,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ,UAAU,IAAI,YAAY;GAC1B,SAAS,IAAI,WAAW;GACxB,iBAAiB,IAAI,mBAAmB,EAAE;GAC3C,CACF;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAI,SAAS,OAAO;GAAS;UAChF,KAAK;EACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAK,IAAI,KACP;GAAE;GAAK,YAAY,IAAI;GAAY,SAAS,OAAO;GAAS,EAC5D,yBAAyB,KAC1B;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAM,SAAS,OAAO;GAAS;;;;;;;AA8B7F,eAAsB,mBACpB,MACA,OACmC;CACnC,MAAM,YAAY,0BAA0B,MAAM,YAAY;CAC9D,MAAM,sBAAsB,MAAM,KAAK,aAAa,iCAClD,MAAM,aACN,MAAM,WACP;CAED,MAAM,WAAW,KAAK,aAAa,mBAAmB,MAAM,WAAW;CACvE,MAAM,UAAU,MAAM,sBAAsB;EAC1C,SAAS,MAAM;EACf;EACD,CAAC;CACF,MAAM,eAAe,6BAA6B,SAAS,KAAK,WAAY,MAAM,gBAAgB,EAAE,GAAI,EAAE;CAC1G,MAAM,YAAY,CAAC,GAAG,QAAQ,QAAQ,GAAG,aAAa;CAEtD,MAAM,SAAS,MAAM,0BAA0B;EAC7C,YAAY,MAAM;EAClB,OAAO,MAAM,SAAS,OAAO,YAAY;EACzC,aAAa;EACb;EACA,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,iBAAiB,KAAK;EACtB,aAAa,MAAM;EACnB,kBAAkB,KAAK,aAAa,8BAA8B,MAAM,WAAW;EACnF,SAAS,MAAM;EAChB,CAAC;AAEF,MAAK,aAAa,eAAe,MAAM,YAAY,UAAU;AAC7D,MAAK,aAAa,sCAAsC,MAAM,WAAW;AAEzE,QAAO"}
1
+ {"version":3,"file":"direct-turn-helpers.js","names":[],"sources":["../../../../src/agent/service/direct-turn-helpers.ts"],"sourcesContent":["/**\n * Shared building blocks for the two direct-turn entry points (streaming\n * webchat SSE and one-shot CLI). Both flows do the same hydrate → maybe-slash\n * → run-embedded-turn → after-turn dance; this module captures that core so\n * the entry points only manage their I/O specifics (event sink, voice STT,\n * TTS, transcript persistence).\n */\n\nimport crypto from 'node:crypto';\n\nimport type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport { commandRegistry } from '../../chat-commands/index.js';\nimport { parseSlashCommand } from '../../chat-commands/command-parse.js';\nimport { shouldSkipResetOverlapCommand } from '../../session/reset-triggers.js';\nimport { hydrateUserTurnForLlm, type TranscriptUserMessage } from '../inbound/attachment-pipeline.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { SessionStore } from '../../session/index.js';\nimport type { Config } from '../../config/schema.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { ModelManager } from '../models/index.js';\nimport { extractAgentUserPlainText } from '../memory/user-message-text.js';\nimport { runEmbeddedTurnForSession } from '../embedded/run-for-session.js';\nimport type { EmbeddedStreamEvent } from '../embedded/types.js';\nimport { resolveImageHandlingStrategy } from '../image/vision-detection.js';\n\nexport interface HydratePerTurnStateDeps {\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n}\n\n/** Workspace + model + thinking level — common prep before any direct turn. */\nexport async function hydratePerTurnState(\n deps: HydratePerTurnStateDeps,\n sessionKey: string,\n thinking?: string,\n): Promise<void> {\n await deps.hydrateSessionWorkspaceFromStore(sessionKey);\n await deps.hydrateSessionModelFromStore(sessionKey);\n await deps.applyResolvedThinkingLevel(sessionKey, thinking);\n}\n\nexport interface SlashCommandOutcome {\n /** True if the input parsed as a registered slash command (handled or not). */\n matched: boolean;\n /** Aggregated user-visible reply text (assistant view). */\n aggregatedText: string;\n /** The parsed command name when matched. */\n command?: string;\n /** Structured command result metadata for webchat and other rich clients. */\n metadata?: Record<string, unknown>;\n}\n\nexport interface TryRunSlashCommandDeps {\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n log: { warn: (obj: Record<string, unknown>, msg: string) => void };\n}\n\n/**\n * Detect a slash command and, if registered, execute it and aggregate the reply\n * text. Errors thrown inside the command surface as `aggregatedText` so callers\n * can persist the receipt or stream it as a token.\n */\nexport async function tryRunSlashCommand(\n deps: TryRunSlashCommandDeps,\n ctx: {\n sessionKey: string;\n channel: string;\n chatId: string;\n senderId?: string;\n isGroup?: boolean;\n inboundMetadata?: Record<string, unknown>;\n },\n content: string,\n options?: { skipResetCommands?: boolean },\n): Promise<SlashCommandOutcome> {\n const parsed = parseSlashCommand(content);\n if (!parsed) {\n return { matched: false, aggregatedText: '' };\n }\n if (options?.skipResetCommands && shouldSkipResetOverlapCommand(parsed.command, true)) {\n return { matched: false, aggregatedText: '' };\n }\n if (!commandRegistry.has(parsed.command)) {\n return { matched: false, aggregatedText: '' };\n }\n try {\n const { aggregatedText, metadata } = await deps.commandHandler.executeCommandAndAggregateReply(\n parsed.command,\n parsed.args,\n {\n sessionKey: ctx.sessionKey,\n channel: ctx.channel,\n chatId: ctx.chatId,\n senderId: ctx.senderId ?? '',\n isGroup: ctx.isGroup ?? false,\n inboundMetadata: ctx.inboundMetadata ?? {},\n },\n );\n return { matched: true, aggregatedText: aggregatedText ?? '', command: parsed.command, metadata };\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n deps.log.warn(\n { err, sessionKey: ctx.sessionKey, command: parsed.command },\n `Slash command failed: ${em}`,\n );\n return { matched: true, aggregatedText: `Command error: ${em}`, command: parsed.command };\n }\n}\n\nexport interface RunDirectAgentTurnDeps {\n sessionStore: SessionStore;\n agentManager: AgentInstanceGateway;\n modelManager: ModelManager;\n config: Config | undefined;\n}\n\nexport interface RunDirectAgentTurnInput {\n sessionKey: string;\n runId?: string;\n userMessage: AgentMessage;\n abortSignal?: AbortSignal;\n sourceImages?: ImageContent[];\n onEvent?: (event: EmbeddedStreamEvent) => void;\n}\n\nexport interface RunDirectAgentTurnResult {\n ok: boolean;\n errorMessage?: string;\n lastAssistantText?: string;\n}\n\n/**\n * Convert a user message into an embedded turn, including the standard memory\n * prefetch + background-review nudge wiring used by every direct entry point.\n */\nexport async function runDirectAgentTurn(\n deps: RunDirectAgentTurnDeps,\n input: RunDirectAgentTurnInput,\n): Promise<RunDirectAgentTurnResult> {\n const userPlain = extractAgentUserPlainText(input.userMessage);\n const userMessageForModel = await deps.agentManager.applyMemoryPrefetchToUserMessage(\n input.userMessage,\n input.sessionKey,\n );\n\n const modelRef = deps.modelManager.getModelForSession(input.sessionKey);\n const llmTurn = await hydrateUserTurnForLlm({\n message: input.userMessage as TranscriptUserMessage,\n modelRef,\n });\n const sourceImages = resolveImageHandlingStrategy(modelRef) === 'native' ? (input.sourceImages ?? []) : [];\n const llmImages = [...llmTurn.images, ...sourceImages];\n\n const result = await runEmbeddedTurnForSession({\n sessionKey: input.sessionKey,\n runId: input.runId ?? crypto.randomUUID(),\n userMessage: userMessageForModel,\n llmImages,\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n getConfig: () => deps.config,\n abortSignal: input.abortSignal,\n beforeTurn: () => deps.agentManager.beginBackgroundReviewUserTurn(input.sessionKey),\n onEvent: input.onEvent,\n });\n\n deps.agentManager.afterAgentTurn(input.sessionKey, userPlain);\n deps.agentManager.scheduleBackgroundReviewAfterUserTurn(input.sessionKey);\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkCA,eAAsB,oBACpB,MACA,YACA,UACe;AACf,OAAM,KAAK,iCAAiC,WAAW;AACvD,OAAM,KAAK,6BAA6B,WAAW;AACnD,OAAM,KAAK,2BAA2B,YAAY,SAAS;;;;;;;AAwB7D,eAAsB,mBACpB,MACA,KAQA,SACA,SAC8B;CAC9B,MAAM,SAAS,kBAAkB,QAAQ;AACzC,KAAI,CAAC,OACH,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,SAAS,qBAAqB,8BAA8B,OAAO,SAAS,KAAK,CACnF,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI,CAAC,gBAAgB,IAAI,OAAO,QAAQ,CACtC,QAAO;EAAE,SAAS;EAAO,gBAAgB;EAAI;AAE/C,KAAI;EACF,MAAM,EAAE,gBAAgB,aAAa,MAAM,KAAK,eAAe,gCAC7D,OAAO,SACP,OAAO,MACP;GACE,YAAY,IAAI;GAChB,SAAS,IAAI;GACb,QAAQ,IAAI;GACZ,UAAU,IAAI,YAAY;GAC1B,SAAS,IAAI,WAAW;GACxB,iBAAiB,IAAI,mBAAmB,EAAE;GAC3C,CACF;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAI,SAAS,OAAO;GAAS;GAAU;UAC1F,KAAK;EACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAK,IAAI,KACP;GAAE;GAAK,YAAY,IAAI;GAAY,SAAS,OAAO;GAAS,EAC5D,yBAAyB,KAC1B;AACD,SAAO;GAAE,SAAS;GAAM,gBAAgB,kBAAkB;GAAM,SAAS,OAAO;GAAS;;;;;;;AA8B7F,eAAsB,mBACpB,MACA,OACmC;CACnC,MAAM,YAAY,0BAA0B,MAAM,YAAY;CAC9D,MAAM,sBAAsB,MAAM,KAAK,aAAa,iCAClD,MAAM,aACN,MAAM,WACP;CAED,MAAM,WAAW,KAAK,aAAa,mBAAmB,MAAM,WAAW;CACvE,MAAM,UAAU,MAAM,sBAAsB;EAC1C,SAAS,MAAM;EACf;EACD,CAAC;CACF,MAAM,eAAe,6BAA6B,SAAS,KAAK,WAAY,MAAM,gBAAgB,EAAE,GAAI,EAAE;CAC1G,MAAM,YAAY,CAAC,GAAG,QAAQ,QAAQ,GAAG,aAAa;CAEtD,MAAM,SAAS,MAAM,0BAA0B;EAC7C,YAAY,MAAM;EAClB,OAAO,MAAM,SAAS,OAAO,YAAY;EACzC,aAAa;EACb;EACA,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,cAAc,KAAK;EACnB,iBAAiB,KAAK;EACtB,aAAa,MAAM;EACnB,kBAAkB,KAAK,aAAa,8BAA8B,MAAM,WAAW;EACnF,SAAS,MAAM;EAChB,CAAC;AAEF,MAAK,aAAa,eAAe,MAAM,YAAY,UAAU;AAC7D,MAAK,aAAa,sCAAsC,MAAM,WAAW;AAEzE,QAAO"}
@@ -70,6 +70,7 @@ async function* runProcessDirectStreaming(deps, input) {
70
70
  let ranSlashCommand = false;
71
71
  let mergedUserText = input.content;
72
72
  let webchatSlashReceipt;
73
+ let slashCommandMetadata;
73
74
  const taskPromise = (async () => {
74
75
  try {
75
76
  const cfg = deps.getConfig();
@@ -145,6 +146,7 @@ async function* runProcessDirectStreaming(deps, input) {
145
146
  }, mergedUserText, { skipResetCommands: resetTriggeredAtInit });
146
147
  if (slash.matched) {
147
148
  ranSlashCommand = true;
149
+ slashCommandMetadata = slash.metadata;
148
150
  const text = slash.aggregatedText.trim();
149
151
  if (text) {
150
152
  webchatSlashReceipt = text;
@@ -153,6 +155,12 @@ async function* runProcessDirectStreaming(deps, input) {
153
155
  webchatSlashReceipt = "Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.";
154
156
  pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);
155
157
  }
158
+ const workflowRun = slash.metadata?.workflowRun;
159
+ if (workflowRun && typeof workflowRun === "object") queue.push({
160
+ type: "workflow_run_started",
161
+ runId: input.runId,
162
+ payload: { workflowRun }
163
+ });
156
164
  return;
157
165
  }
158
166
  const textForAgent = mergedUserText.trimStart().startsWith("/skill:") ? deps.agentManager.expandSkillUserText(mergedUserText) : mergedUserText;
@@ -234,7 +242,8 @@ async function* runProcessDirectStreaming(deps, input) {
234
242
  type: "text",
235
243
  text: webchatSlashReceipt.trim()
236
244
  }],
237
- timestamp: Date.now()
245
+ timestamp: Date.now(),
246
+ ...slashCommandMetadata && Object.keys(slashCommandMetadata).length > 0 ? { metadata: slashCommandMetadata } : {}
238
247
  };
239
248
  await deps.sessionStore.appendTranscriptMessage(sessionKey, assistantMsg);
240
249
  }
@@ -1 +1 @@
1
- {"version":3,"file":"process-direct-streaming.js","names":[],"sources":["../../../../src/agent/service/process-direct-streaming.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { InboundAttachmentInput, MediaRef } from '../../channels/attachments/inbound-persist.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport {\n isVoiceLikeAttachment,\n mergeVoiceTranscriptsIntoUserText,\n mergeSttConfigFromAppConfig,\n} from '../../channels/attachments/voice-stt-webchat.js';\nimport {\n resolveEffectiveReasoningLevel,\n initSessionTurn,\n type SessionConfigStore,\n type SessionStore,\n} from '../../session/index.js';\nimport type { SessionContext } from '../session/index.js';\nimport { applyReasoningVisibilityToSseEvent } from '../streaming/reasoning-visibility-sse.js';\nimport type { ReasoningLevel } from '../transcript/thinking-types.js';\nimport { formatAgentRunErrorForClient } from '../client-error-format.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport { injectSourceContextIntoUserMessage } from '../source-context/injector.js';\nimport { isSessionSourceBinding, type AgentSourceContextResolver } from '../source-context/types.js';\n\nimport { AsyncQueue } from './async-queue.js';\nimport {\n hydratePerTurnState,\n runDirectAgentTurn,\n tryRunSlashCommand,\n} from './direct-turn-helpers.js';\nimport {\n clearPendingTranscriptUserMessage,\n setPendingTranscriptUserMessage,\n type TranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\n\nexport type DirectStreamInboundAttachment = InboundAttachmentInput;\n\nexport type ProcessDirectStreamLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport interface ProcessDirectStreamingDeps {\n log: ProcessDirectStreamLog;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n initDirectStreamingSession: (\n sessionKey: string,\n channel: string,\n chatId: string,\n ) => SessionContext;\n registerWebchatSsePublisher: (\n sessionKey: string,\n publisher: (event: { type: string; [key: string]: unknown }) => void,\n ) => void;\n unregisterWebchatSsePublisher: (sessionKey: string) => void;\n agentManager: AgentInstanceGateway;\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n getConfig: () => Config | undefined;\n sessionConfigStore: SessionConfigStore;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: DirectStreamInboundAttachment[],\n ) => Promise<MediaRef[] | undefined>;\n buildTranscriptUserMessage: (\n content: string,\n prepared: MediaRef[] | undefined,\n sessionKey: string,\n ) => Promise<TranscriptUserMessage>;\n recordPersistentGoalStreamOutcome?: (\n sessionKey: string,\n outcome: { skipPersistentGoalPostTurn: boolean },\n ) => void;\n onTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n /** Disk-only transcript sync (slash receipt already streamed as tokens). */\n reloadWebchatTranscript?: (sessionKey: string) => void;\n maybeEmitWebchatTts: (\n sessionKey: string,\n hadInboundVoice: boolean,\n ) => Promise<{ type: 'tts_audio'; uri: string; mimeType: string; name: string } | null>;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n sourceContextResolver?: AgentSourceContextResolver;\n}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n runId?: string;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\n\nfunction makeAssistantReceiptMessage(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nfunction pushAssistantReceipt(\n queue: AsyncQueue<ProcessDirectStreamingSseEvent>,\n text: string,\n runId?: string,\n): void {\n const message = makeAssistantReceiptMessage(text);\n queue.push({ type: 'message_start', runId, message });\n queue.push({ type: 'message_update', runId, message });\n queue.push({ type: 'message_end', runId, message });\n}\n\nexport async function* runProcessDirectStreaming(\n deps: ProcessDirectStreamingDeps,\n input: ProcessDirectStreamingInput,\n): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n const sessionKey = input.sessionKey ?? 'agent:main:main';\n const { channel, chatId } = deps.parseSessionKey(sessionKey);\n const context = deps.initDirectStreamingSession(sessionKey, channel, chatId);\n\n const queue = new AsyncQueue<ProcessDirectStreamingSseEvent>();\n let reasoningLevel: ReasoningLevel = 'stream';\n\n const pushVisible = (event: ProcessDirectStreamingSseEvent) => {\n const visible = applyReasoningVisibilityToSseEvent(event, reasoningLevel);\n if (visible !== null) {\n queue.push(visible);\n }\n };\n\n const formatStreamError = (raw: string): string => {\n let provider: string | undefined;\n let modelRef: string | undefined;\n try {\n const resolved = deps.modelManager.getResolvedModelForSession(sessionKey);\n provider = resolved.provider;\n modelRef = deps.modelManager.getModelForSession(sessionKey);\n } catch {\n /* ignore — format without provider context */\n }\n return formatAgentRunErrorForClient(raw, { provider, modelRef });\n };\n\n if (channel === 'webchat') {\n deps.registerWebchatSsePublisher(sessionKey, pushVisible);\n }\n\n const signal = input.signal;\n let userAborted = false;\n let abortHandled = false;\n let inboundVoice = false;\n let ranSlashCommand = false;\n let mergedUserText = input.content;\n let webchatSlashReceipt: string | undefined;\n\n const taskPromise = (async () => {\n try {\n const cfg = deps.getConfig();\n let turnBody = input.content;\n let resetTriggeredAtInit = false;\n if (cfg) {\n const turn = await initSessionTurn({\n cfg,\n sessionKey,\n body: input.content,\n resetSession: deps.resetSession,\n });\n resetTriggeredAtInit = turn.resetTriggered;\n if (turn.bareReset && turn.ackMessage) {\n ranSlashCommand = true;\n webchatSlashReceipt = turn.ackMessage;\n pushAssistantReceipt(queue, turn.ackMessage, input.runId);\n return;\n }\n turnBody = turn.bodyStripped;\n if (turn.isNewSession) {\n deps.log.debug(\n {\n sessionKey,\n sessionId: turn.sessionId,\n previousSessionId: turn.previousSessionId,\n resetTriggered: turn.resetTriggered,\n staleRollover: turn.staleRollover,\n },\n 'Session reset boundary at direct turn start',\n );\n }\n }\n\n await hydratePerTurnState(deps, sessionKey, input.thinking);\n {\n const defReason = (deps.getConfig()?.agents?.defaults?.reasoningDefault ?? 'stream') as ReasoningLevel;\n reasoningLevel = await resolveEffectiveReasoningLevel(deps.sessionConfigStore, sessionKey, defReason);\n }\n\n const prepared = await deps.prepareInboundAttachments(sessionKey, input.attachments);\n\n const sttCfg = mergeSttConfigFromAppConfig(deps.getConfig()?.tools?.media?.audio, deps.getConfig()?.tools?.media);\n const voiceMerge = await mergeVoiceTranscriptsIntoUserText(prepared, turnBody, sttCfg);\n mergedUserText = voiceMerge.text;\n inboundVoice = voiceMerge.inboundVoice;\n\n if (inboundVoice) {\n const transcriptParts = [\n voiceMerge.voiceTranscripts.filter(Boolean).join('\\n'),\n turnBody.trim(),\n ].filter(Boolean);\n const voiceMedia = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({\n uri: att.uri,\n mimeType: att.mimeType,\n name: att.name,\n }));\n pushVisible({\n type: 'user_transcript',\n text: transcriptParts.join('\\n\\n'),\n media: voiceMedia,\n });\n }\n\n const armAbort = () => {\n if (abortHandled) {\n return;\n }\n abortHandled = true;\n userAborted = true;\n void abortEmbeddedRun(sessionKey);\n queue.close();\n };\n if (signal) {\n if (signal.aborted) {\n armAbort();\n return;\n }\n signal.addEventListener('abort', armAbort, { once: true });\n }\n\n const slash = await tryRunSlashCommand(\n deps,\n {\n sessionKey,\n channel,\n chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n inboundMetadata: context.metadata,\n },\n mergedUserText,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n ranSlashCommand = true;\n const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushAssistantReceipt(queue, text, input.runId);\n } else if (channel === 'webchat') {\n webchatSlashReceipt =\n 'Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.';\n pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);\n }\n return;\n }\n\n const textForAgent = mergedUserText.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(mergedUserText)\n : mergedUserText;\n const userMessage = await deps.buildTranscriptUserMessage(textForAgent, prepared, sessionKey);\n let sourceEnrichedUserMessage: AgentMessage = userMessage;\n let sourceImages: ImageContent[] | undefined;\n if (deps.sourceContextResolver) {\n const metadata = await deps.sessionStore.getMetadata(sessionKey).catch(() => null);\n const sourceBinding = metadata?.customData && typeof metadata.customData === 'object'\n ? (metadata.customData as Record<string, unknown>).sourceBinding\n : undefined;\n if (isSessionSourceBinding(sourceBinding)) {\n const sourceContext = await deps.sourceContextResolver(sourceBinding, sessionKey);\n sourceEnrichedUserMessage = injectSourceContextIntoUserMessage(userMessage, sourceContext);\n sourceImages = sourceContext?.images;\n }\n }\n\n if (channel === 'webchat') {\n pushVisible({\n type: 'user_message',\n timestamp: userMessage.timestamp ?? Date.now(),\n content: readAgentMessageContent(userMessage),\n media: userMessage.media,\n });\n if (textForAgent.trim()) {\n deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);\n }\n }\n\n const pendingUserMessage = userMessage as TranscriptUserMessage;\n setPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n\n try {\n const result = await runDirectAgentTurn(\n {\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n config: deps.getConfig(),\n },\n {\n sessionKey,\n userMessage: sourceEnrichedUserMessage,\n abortSignal: signal,\n sourceImages,\n runId: input.runId,\n onEvent: (embeddedEvent) => {\n const event = { ...embeddedEvent };\n if (event.type === 'error' && typeof event.content === 'string') {\n event.content = formatStreamError(event.content);\n }\n pushVisible(event);\n },\n },\n );\n\n if (result.lastAssistantText) {\n deps.onTurnComplete?.(sessionKey, result.lastAssistantText);\n }\n if (!result.ok && result.errorMessage && !abortHandled) {\n pushVisible({ type: 'error', content: formatStreamError(result.errorMessage) });\n }\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n }\n } catch (err) {\n if (!abortHandled) {\n const em = err instanceof Error ? err.message : String(err);\n pushVisible({ type: 'error', content: formatStreamError(em) });\n }\n } finally {\n queue.close();\n }\n })();\n\n try {\n for await (const event of queue) {\n yield event;\n }\n await taskPromise;\n\n if (channel === 'webchat' && ranSlashCommand) {\n try {\n const userMsg = {\n role: 'user' as const,\n content: [{ type: 'text' as const, text: mergedUserText }],\n timestamp: Date.now(),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, userMsg);\n if (webchatSlashReceipt?.trim()) {\n const assistantMsg = {\n role: 'assistant' as const,\n content: [{ type: 'text' as const, text: webchatSlashReceipt.trim() }],\n timestamp: Date.now(),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, assistantMsg);\n }\n deps.reloadWebchatTranscript?.(sessionKey);\n } catch (err) {\n deps.log.warn({ err, sessionKey }, 'Failed to persist webchat slash command receipt');\n }\n }\n\n if (!userAborted) {\n const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);\n if (ttsAudioEvent) {\n yield ttsAudioEvent;\n }\n }\n\n deps.recordPersistentGoalStreamOutcome?.(sessionKey, { skipPersistentGoalPostTurn: ranSlashCommand });\n } finally {\n if (channel === 'webchat') {\n deps.unregisterWebchatSsePublisher(sessionKey);\n }\n deps.endDirectRequestContext();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"process-direct-streaming.js","names":[],"sources":["../../../../src/agent/service/process-direct-streaming.ts"],"sourcesContent":["import type { AgentMessage } from '@earendil-works/pi-agent-core';\nimport type { ImageContent } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { InboundAttachmentInput, MediaRef } from '../../channels/attachments/inbound-persist.js';\nimport { readAgentMessageContent } from '../memory/agent-message-access.js';\nimport {\n isVoiceLikeAttachment,\n mergeVoiceTranscriptsIntoUserText,\n mergeSttConfigFromAppConfig,\n} from '../../channels/attachments/voice-stt-webchat.js';\nimport {\n resolveEffectiveReasoningLevel,\n initSessionTurn,\n type SessionConfigStore,\n type SessionStore,\n} from '../../session/index.js';\nimport type { SessionContext } from '../session/index.js';\nimport { applyReasoningVisibilityToSseEvent } from '../streaming/reasoning-visibility-sse.js';\nimport type { ReasoningLevel } from '../transcript/thinking-types.js';\nimport { formatAgentRunErrorForClient } from '../client-error-format.js';\nimport { abortEmbeddedRun } from '../embedded/runs.js';\nimport type { AgentInstanceGateway } from '../agent-instance-gateway.js';\nimport type { CommandHandler } from '../messaging/command-handler.js';\nimport type { ModelManager } from '../models/index.js';\nimport { injectSourceContextIntoUserMessage } from '../source-context/injector.js';\nimport { isSessionSourceBinding, type AgentSourceContextResolver } from '../source-context/types.js';\n\nimport { AsyncQueue } from './async-queue.js';\nimport {\n hydratePerTurnState,\n runDirectAgentTurn,\n tryRunSlashCommand,\n} from './direct-turn-helpers.js';\nimport {\n clearPendingTranscriptUserMessage,\n setPendingTranscriptUserMessage,\n type TranscriptUserMessage,\n} from '../inbound/attachment-pipeline.js';\n\nexport type DirectStreamInboundAttachment = InboundAttachmentInput;\n\nexport type ProcessDirectStreamLog = {\n info: (obj: Record<string, unknown>, msg: string) => void;\n warn: (obj: Record<string, unknown>, msg: string) => void;\n debug?: (obj: Record<string, unknown>, msg: string) => void;\n};\n\nexport interface ProcessDirectStreamingDeps {\n log: ProcessDirectStreamLog;\n parseSessionKey: (sessionKey: string) => { channel: string; chatId: string };\n initDirectStreamingSession: (\n sessionKey: string,\n channel: string,\n chatId: string,\n ) => SessionContext;\n registerWebchatSsePublisher: (\n sessionKey: string,\n publisher: (event: { type: string; [key: string]: unknown }) => void,\n ) => void;\n unregisterWebchatSsePublisher: (sessionKey: string) => void;\n agentManager: AgentInstanceGateway;\n hydrateSessionWorkspaceFromStore: (sessionKey: string) => Promise<void>;\n hydrateSessionModelFromStore: (sessionKey: string) => Promise<void>;\n sessionStore: SessionStore;\n modelManager: ModelManager;\n applyResolvedThinkingLevel: (sessionKey: string, thinking?: string | null) => Promise<void>;\n getConfig: () => Config | undefined;\n sessionConfigStore: SessionConfigStore;\n commandHandler: Pick<CommandHandler, 'executeCommandAndAggregateReply'>;\n prepareInboundAttachments: (\n sessionKey: string,\n attachments?: DirectStreamInboundAttachment[],\n ) => Promise<MediaRef[] | undefined>;\n buildTranscriptUserMessage: (\n content: string,\n prepared: MediaRef[] | undefined,\n sessionKey: string,\n ) => Promise<TranscriptUserMessage>;\n recordPersistentGoalStreamOutcome?: (\n sessionKey: string,\n outcome: { skipPersistentGoalPostTurn: boolean },\n ) => void;\n onTurnComplete?: (sessionKey: string, lastAssistantText?: string) => void;\n enqueueProvisionalSessionTitle?: (sessionKey: string, userText: string) => void;\n /** Disk-only transcript sync (slash receipt already streamed as tokens). */\n reloadWebchatTranscript?: (sessionKey: string) => void;\n maybeEmitWebchatTts: (\n sessionKey: string,\n hadInboundVoice: boolean,\n ) => Promise<{ type: 'tts_audio'; uri: string; mimeType: string; name: string } | null>;\n endDirectRequestContext: () => void;\n resetSession: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string } | null>;\n sourceContextResolver?: AgentSourceContextResolver;\n}\n\nexport interface ProcessDirectStreamingInput {\n content: string;\n sessionKey?: string;\n attachments?: DirectStreamInboundAttachment[];\n thinking?: string;\n signal?: AbortSignal;\n runId?: string;\n}\n\nexport type ProcessDirectStreamingSseEvent = { type: string; [key: string]: unknown };\n\nfunction makeAssistantReceiptMessage(text: string): AgentMessage {\n return {\n role: 'assistant',\n content: [{ type: 'text', text }],\n timestamp: Date.now(),\n } as AgentMessage;\n}\n\nfunction pushAssistantReceipt(\n queue: AsyncQueue<ProcessDirectStreamingSseEvent>,\n text: string,\n runId?: string,\n): void {\n const message = makeAssistantReceiptMessage(text);\n queue.push({ type: 'message_start', runId, message });\n queue.push({ type: 'message_update', runId, message });\n queue.push({ type: 'message_end', runId, message });\n}\n\nexport async function* runProcessDirectStreaming(\n deps: ProcessDirectStreamingDeps,\n input: ProcessDirectStreamingInput,\n): AsyncGenerator<ProcessDirectStreamingSseEvent, void, unknown> {\n const sessionKey = input.sessionKey ?? 'agent:main:main';\n const { channel, chatId } = deps.parseSessionKey(sessionKey);\n const context = deps.initDirectStreamingSession(sessionKey, channel, chatId);\n\n const queue = new AsyncQueue<ProcessDirectStreamingSseEvent>();\n let reasoningLevel: ReasoningLevel = 'stream';\n\n const pushVisible = (event: ProcessDirectStreamingSseEvent) => {\n const visible = applyReasoningVisibilityToSseEvent(event, reasoningLevel);\n if (visible !== null) {\n queue.push(visible);\n }\n };\n\n const formatStreamError = (raw: string): string => {\n let provider: string | undefined;\n let modelRef: string | undefined;\n try {\n const resolved = deps.modelManager.getResolvedModelForSession(sessionKey);\n provider = resolved.provider;\n modelRef = deps.modelManager.getModelForSession(sessionKey);\n } catch {\n /* ignore — format without provider context */\n }\n return formatAgentRunErrorForClient(raw, { provider, modelRef });\n };\n\n if (channel === 'webchat') {\n deps.registerWebchatSsePublisher(sessionKey, pushVisible);\n }\n\n const signal = input.signal;\n let userAborted = false;\n let abortHandled = false;\n let inboundVoice = false;\n let ranSlashCommand = false;\n let mergedUserText = input.content;\n let webchatSlashReceipt: string | undefined;\n let slashCommandMetadata: Record<string, unknown> | undefined;\n\n const taskPromise = (async () => {\n try {\n const cfg = deps.getConfig();\n let turnBody = input.content;\n let resetTriggeredAtInit = false;\n if (cfg) {\n const turn = await initSessionTurn({\n cfg,\n sessionKey,\n body: input.content,\n resetSession: deps.resetSession,\n });\n resetTriggeredAtInit = turn.resetTriggered;\n if (turn.bareReset && turn.ackMessage) {\n ranSlashCommand = true;\n webchatSlashReceipt = turn.ackMessage;\n pushAssistantReceipt(queue, turn.ackMessage, input.runId);\n return;\n }\n turnBody = turn.bodyStripped;\n if (turn.isNewSession) {\n deps.log.debug(\n {\n sessionKey,\n sessionId: turn.sessionId,\n previousSessionId: turn.previousSessionId,\n resetTriggered: turn.resetTriggered,\n staleRollover: turn.staleRollover,\n },\n 'Session reset boundary at direct turn start',\n );\n }\n }\n\n await hydratePerTurnState(deps, sessionKey, input.thinking);\n {\n const defReason = (deps.getConfig()?.agents?.defaults?.reasoningDefault ?? 'stream') as ReasoningLevel;\n reasoningLevel = await resolveEffectiveReasoningLevel(deps.sessionConfigStore, sessionKey, defReason);\n }\n\n const prepared = await deps.prepareInboundAttachments(sessionKey, input.attachments);\n\n const sttCfg = mergeSttConfigFromAppConfig(deps.getConfig()?.tools?.media?.audio, deps.getConfig()?.tools?.media);\n const voiceMerge = await mergeVoiceTranscriptsIntoUserText(prepared, turnBody, sttCfg);\n mergedUserText = voiceMerge.text;\n inboundVoice = voiceMerge.inboundVoice;\n\n if (inboundVoice) {\n const transcriptParts = [\n voiceMerge.voiceTranscripts.filter(Boolean).join('\\n'),\n turnBody.trim(),\n ].filter(Boolean);\n const voiceMedia = (prepared ?? []).filter(isVoiceLikeAttachment).map((att) => ({\n uri: att.uri,\n mimeType: att.mimeType,\n name: att.name,\n }));\n pushVisible({\n type: 'user_transcript',\n text: transcriptParts.join('\\n\\n'),\n media: voiceMedia,\n });\n }\n\n const armAbort = () => {\n if (abortHandled) {\n return;\n }\n abortHandled = true;\n userAborted = true;\n void abortEmbeddedRun(sessionKey);\n queue.close();\n };\n if (signal) {\n if (signal.aborted) {\n armAbort();\n return;\n }\n signal.addEventListener('abort', armAbort, { once: true });\n }\n\n const slash = await tryRunSlashCommand(\n deps,\n {\n sessionKey,\n channel,\n chatId,\n senderId: context.senderId,\n isGroup: context.isGroup,\n inboundMetadata: context.metadata,\n },\n mergedUserText,\n { skipResetCommands: resetTriggeredAtInit },\n );\n if (slash.matched) {\n ranSlashCommand = true;\n slashCommandMetadata = slash.metadata;\n const text = slash.aggregatedText.trim();\n if (text) {\n webchatSlashReceipt = text;\n pushAssistantReceipt(queue, text, input.runId);\n } else if (channel === 'webchat') {\n webchatSlashReceipt =\n 'Command finished with no assistant text. If you used `/goal`, a follow-up turn may still be scheduled automatically.';\n pushAssistantReceipt(queue, webchatSlashReceipt, input.runId);\n }\n const workflowRun = slash.metadata?.workflowRun;\n if (workflowRun && typeof workflowRun === 'object') {\n queue.push({\n type: 'workflow_run_started',\n runId: input.runId,\n payload: { workflowRun },\n });\n }\n return;\n }\n\n const textForAgent = mergedUserText.trimStart().startsWith('/skill:')\n ? deps.agentManager.expandSkillUserText(mergedUserText)\n : mergedUserText;\n const userMessage = await deps.buildTranscriptUserMessage(textForAgent, prepared, sessionKey);\n let sourceEnrichedUserMessage: AgentMessage = userMessage;\n let sourceImages: ImageContent[] | undefined;\n if (deps.sourceContextResolver) {\n const metadata = await deps.sessionStore.getMetadata(sessionKey).catch(() => null);\n const sourceBinding = metadata?.customData && typeof metadata.customData === 'object'\n ? (metadata.customData as Record<string, unknown>).sourceBinding\n : undefined;\n if (isSessionSourceBinding(sourceBinding)) {\n const sourceContext = await deps.sourceContextResolver(sourceBinding, sessionKey);\n sourceEnrichedUserMessage = injectSourceContextIntoUserMessage(userMessage, sourceContext);\n sourceImages = sourceContext?.images;\n }\n }\n\n if (channel === 'webchat') {\n pushVisible({\n type: 'user_message',\n timestamp: userMessage.timestamp ?? Date.now(),\n content: readAgentMessageContent(userMessage),\n media: userMessage.media,\n });\n if (textForAgent.trim()) {\n deps.enqueueProvisionalSessionTitle?.(sessionKey, textForAgent);\n }\n }\n\n const pendingUserMessage = userMessage as TranscriptUserMessage;\n setPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n\n try {\n const result = await runDirectAgentTurn(\n {\n sessionStore: deps.sessionStore,\n agentManager: deps.agentManager,\n modelManager: deps.modelManager,\n config: deps.getConfig(),\n },\n {\n sessionKey,\n userMessage: sourceEnrichedUserMessage,\n abortSignal: signal,\n sourceImages,\n runId: input.runId,\n onEvent: (embeddedEvent) => {\n const event = { ...embeddedEvent };\n if (event.type === 'error' && typeof event.content === 'string') {\n event.content = formatStreamError(event.content);\n }\n pushVisible(event);\n },\n },\n );\n\n if (result.lastAssistantText) {\n deps.onTurnComplete?.(sessionKey, result.lastAssistantText);\n }\n if (!result.ok && result.errorMessage && !abortHandled) {\n pushVisible({ type: 'error', content: formatStreamError(result.errorMessage) });\n }\n } finally {\n clearPendingTranscriptUserMessage(sessionKey, pendingUserMessage);\n }\n } catch (err) {\n if (!abortHandled) {\n const em = err instanceof Error ? err.message : String(err);\n pushVisible({ type: 'error', content: formatStreamError(em) });\n }\n } finally {\n queue.close();\n }\n })();\n\n try {\n for await (const event of queue) {\n yield event;\n }\n await taskPromise;\n\n if (channel === 'webchat' && ranSlashCommand) {\n try {\n const userMsg = {\n role: 'user' as const,\n content: [{ type: 'text' as const, text: mergedUserText }],\n timestamp: Date.now(),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, userMsg);\n if (webchatSlashReceipt?.trim()) {\n const assistantMsg = {\n role: 'assistant' as const,\n content: [{ type: 'text' as const, text: webchatSlashReceipt.trim() }],\n timestamp: Date.now(),\n ...(slashCommandMetadata && Object.keys(slashCommandMetadata).length > 0\n ? { metadata: slashCommandMetadata }\n : {}),\n } as AgentMessage;\n await deps.sessionStore.appendTranscriptMessage(sessionKey, assistantMsg);\n }\n deps.reloadWebchatTranscript?.(sessionKey);\n } catch (err) {\n deps.log.warn({ err, sessionKey }, 'Failed to persist webchat slash command receipt');\n }\n }\n\n if (!userAborted) {\n const ttsAudioEvent = await deps.maybeEmitWebchatTts(sessionKey, inboundVoice);\n if (ttsAudioEvent) {\n yield ttsAudioEvent;\n }\n }\n\n deps.recordPersistentGoalStreamOutcome?.(sessionKey, { skipPersistentGoalPostTurn: ranSlashCommand });\n } finally {\n if (channel === 'webchat') {\n deps.unregisterWebchatSsePublisher(sessionKey);\n }\n deps.endDirectRequestContext();\n }\n}\n"],"mappings":"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"}
@@ -52,10 +52,14 @@ async function reconcileManagedDreamingCronJobs(cron, effectiveConfig) {
52
52
  kind: "agentTurn",
53
53
  message: spec.token
54
54
  };
55
+ const desiredSchedule = {
56
+ kind: "cron",
57
+ expr: spec.schedule,
58
+ ...dreaming.timezone ? { tz: dreaming.timezone } : {}
59
+ };
55
60
  if (phaseJobs.length === 0) {
56
- await cron.addJob(spec.schedule, {
61
+ await cron.addJob(desiredSchedule, {
57
62
  name: spec.cronName,
58
- timezone: dreaming.timezone,
59
63
  sessionTarget: "isolated",
60
64
  payload: desiredPayload,
61
65
  enabled: true
@@ -65,9 +69,8 @@ async function reconcileManagedDreamingCronJobs(cron, effectiveConfig) {
65
69
  const primary = phaseJobs[0];
66
70
  for (const dup of phaseJobs.slice(1)) await cron.removeJob(dup.id).catch(() => {});
67
71
  const payloadMessage = primary.payload?.kind === "agentTurn" ? primary.payload.message : primary.payload?.text;
68
- if (primary.schedule !== spec.schedule || (dreaming.timezone ?? null) !== (primary.timezone ?? null) || primary.sessionTarget !== "isolated" || payloadMessage !== spec.token || primary.enabled !== true || primary.name !== spec.cronName) await cron.updateJob(primary.id, {
69
- schedule: spec.schedule,
70
- timezone: dreaming.timezone ?? void 0,
72
+ if (JSON.stringify(primary.schedule) !== JSON.stringify(desiredSchedule) || primary.sessionTarget !== "isolated" || payloadMessage !== spec.token || primary.enabled !== true || primary.name !== spec.cronName) await cron.updateJob(primary.id, {
73
+ schedule: desiredSchedule,
71
74
  sessionTarget: "isolated",
72
75
  name: spec.cronName,
73
76
  payload: desiredPayload,
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-dreaming-cron.js","names":[],"sources":["../../../../src/agent/service/reconcile-dreaming-cron.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { JobWithNextRun } from '../../cron/types.js';\nimport {\n DREAMING_SWEEP_TOKEN,\n DREAMING_LIGHT_CRON_NAME,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_CRON_NAME,\n DREAMING_REM_CRON_NAME,\n DREAMING_REM_SWEEP_TOKEN,\n} from '../memory/dreaming/constants.js';\nimport { resolveDreamingConfig } from '../memory/dreaming/config.js';\n\nconst DREAMING_SWEEP_TOKENS = new Set<string>([\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_SWEEP_TOKEN,\n DREAMING_REM_SWEEP_TOKEN,\n]);\n\nfunction dreamingSweepTokenFromJob(job: JobWithNextRun): string | undefined {\n if (job.payload?.kind !== 'agentTurn') {\n return undefined;\n }\n const msg = job.payload.message;\n return typeof msg === 'string' && DREAMING_SWEEP_TOKENS.has(msg) ? msg : undefined;\n}\n\n/**\n * Reconcile managed Dreaming cron jobs against the current effective config.\n */\nexport async function reconcileManagedDreamingCronJobs(\n cron: CronService,\n effectiveConfig: Config | undefined,\n): Promise<void> {\n const dreaming = resolveDreamingConfig(effectiveConfig);\n const jobs = await cron.listJobs();\n /** Match by sweep token — job names omit `[managed-by=…]`, so name-only matching never saw these jobs and re-added them every reconcile. */\n const managed = jobs.filter((job) => dreamingSweepTokenFromJob(job) !== undefined);\n\n const phaseSpecs: Array<{\n cronName: string;\n token: string;\n schedule: string;\n phaseEnabled: boolean;\n }> = [\n {\n cronName: DREAMING_LIGHT_CRON_NAME,\n token: DREAMING_LIGHT_SWEEP_TOKEN,\n schedule: dreaming.phases.light.cron,\n phaseEnabled: dreaming.phases.light.enabled,\n },\n {\n cronName: DREAMING_CRON_NAME,\n token: DREAMING_SWEEP_TOKEN,\n schedule: dreaming.phases.deep.cron,\n phaseEnabled: dreaming.phases.deep.enabled,\n },\n {\n cronName: DREAMING_REM_CRON_NAME,\n token: DREAMING_REM_SWEEP_TOKEN,\n schedule: dreaming.phases.rem.cron,\n phaseEnabled: dreaming.phases.rem.enabled,\n },\n ];\n\n if (!dreaming.enabled) {\n for (const job of managed) {\n await cron.removeJob(job.id).catch(() => {});\n }\n return;\n }\n\n for (const spec of phaseSpecs) {\n const phaseJobs = managed.filter((job) => dreamingSweepTokenFromJob(job) === spec.token);\n\n if (!spec.phaseEnabled) {\n for (const job of phaseJobs) {\n await cron.removeJob(job.id).catch(() => {});\n }\n continue;\n }\n\n const desiredPayload = { kind: 'agentTurn' as const, message: spec.token };\n\n if (phaseJobs.length === 0) {\n await cron.addJob(spec.schedule, {\n name: spec.cronName,\n timezone: dreaming.timezone,\n sessionTarget: 'isolated' as const,\n payload: desiredPayload,\n enabled: true,\n } as any);\n continue;\n }\n\n const primary = phaseJobs[0]!;\n for (const dup of phaseJobs.slice(1)) {\n await cron.removeJob(dup.id).catch(() => {});\n }\n\n const payloadMessage =\n primary.payload?.kind === 'agentTurn'\n ? primary.payload.message\n : (primary.payload as any)?.text;\n const needsUpdate =\n primary.schedule !== spec.schedule ||\n (dreaming.timezone ?? null) !== (primary.timezone ?? null) ||\n primary.sessionTarget !== 'isolated' ||\n payloadMessage !== spec.token ||\n primary.enabled !== true ||\n primary.name !== spec.cronName;\n\n if (needsUpdate) {\n await cron.updateJob(primary.id, {\n schedule: spec.schedule,\n timezone: dreaming.timezone ?? undefined,\n sessionTarget: 'isolated',\n name: spec.cronName,\n payload: desiredPayload,\n enabled: true,\n } as any);\n }\n }\n}\n"],"mappings":";;;AAaA,MAAM,wBAAwB,IAAI,IAAY;CAC5C;CACA;CACA;CACD,CAAC;AAEF,SAAS,0BAA0B,KAAyC;AAC1E,KAAI,IAAI,SAAS,SAAS,YACxB;CAEF,MAAM,MAAM,IAAI,QAAQ;AACxB,QAAO,OAAO,QAAQ,YAAY,sBAAsB,IAAI,IAAI,GAAG,MAAM,KAAA;;;;;AAM3E,eAAsB,iCACpB,MACA,iBACe;CACf,MAAM,WAAW,sBAAsB,gBAAgB;;CAGvD,MAAM,WAAU,MAFG,KAAK,UAAU,EAEb,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAA,EAAU;CAElF,MAAM,aAKD;EACH;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,MAAM;GAChC,cAAc,SAAS,OAAO,MAAM;GACrC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,KAAK;GAC/B,cAAc,SAAS,OAAO,KAAK;GACpC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,IAAI;GAC9B,cAAc,SAAS,OAAO,IAAI;GACnC;EACF;AAED,KAAI,CAAC,SAAS,SAAS;AACrB,OAAK,MAAM,OAAO,QAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;AAGF,MAAK,MAAM,QAAQ,YAAY;EAC7B,MAAM,YAAY,QAAQ,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAK,MAAM;AAExF,MAAI,CAAC,KAAK,cAAc;AACtB,QAAK,MAAM,OAAO,UAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;EAGF,MAAM,iBAAiB;GAAE,MAAM;GAAsB,SAAS,KAAK;GAAO;AAE1E,MAAI,UAAU,WAAW,GAAG;AAC1B,SAAM,KAAK,OAAO,KAAK,UAAU;IAC/B,MAAM,KAAK;IACX,UAAU,SAAS;IACnB,eAAe;IACf,SAAS;IACT,SAAS;IACV,CAAQ;AACT;;EAGF,MAAM,UAAU,UAAU;AAC1B,OAAK,MAAM,OAAO,UAAU,MAAM,EAAE,CAClC,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;EAG9C,MAAM,iBACJ,QAAQ,SAAS,SAAS,cACtB,QAAQ,QAAQ,UACf,QAAQ,SAAiB;AAShC,MAPE,QAAQ,aAAa,KAAK,aACzB,SAAS,YAAY,WAAW,QAAQ,YAAY,SACrD,QAAQ,kBAAkB,cAC1B,mBAAmB,KAAK,SACxB,QAAQ,YAAY,QACpB,QAAQ,SAAS,KAAK,SAGtB,OAAM,KAAK,UAAU,QAAQ,IAAI;GAC/B,UAAU,KAAK;GACf,UAAU,SAAS,YAAY,KAAA;GAC/B,eAAe;GACf,MAAM,KAAK;GACX,SAAS;GACT,SAAS;GACV,CAAQ"}
1
+ {"version":3,"file":"reconcile-dreaming-cron.js","names":[],"sources":["../../../../src/agent/service/reconcile-dreaming-cron.ts"],"sourcesContent":["import type { Config } from '../../config/schema.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { JobData } from '../../cron/types.js';\nimport {\n DREAMING_SWEEP_TOKEN,\n DREAMING_LIGHT_CRON_NAME,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_CRON_NAME,\n DREAMING_REM_CRON_NAME,\n DREAMING_REM_SWEEP_TOKEN,\n} from '../memory/dreaming/constants.js';\nimport { resolveDreamingConfig } from '../memory/dreaming/config.js';\n\nconst DREAMING_SWEEP_TOKENS = new Set<string>([\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_SWEEP_TOKEN,\n DREAMING_REM_SWEEP_TOKEN,\n]);\n\nfunction dreamingSweepTokenFromJob(job: JobData): string | undefined {\n if (job.payload?.kind !== 'agentTurn') {\n return undefined;\n }\n const msg = job.payload.message;\n return typeof msg === 'string' && DREAMING_SWEEP_TOKENS.has(msg) ? msg : undefined;\n}\n\n/**\n * Reconcile managed Dreaming cron jobs against the current effective config.\n */\nexport async function reconcileManagedDreamingCronJobs(\n cron: CronService,\n effectiveConfig: Config | undefined,\n): Promise<void> {\n const dreaming = resolveDreamingConfig(effectiveConfig);\n const jobs = await cron.listJobs();\n /** Match by sweep token — job names omit `[managed-by=…]`, so name-only matching never saw these jobs and re-added them every reconcile. */\n const managed = jobs.filter((job) => dreamingSweepTokenFromJob(job) !== undefined);\n\n const phaseSpecs: Array<{\n cronName: string;\n token: string;\n schedule: string;\n phaseEnabled: boolean;\n }> = [\n {\n cronName: DREAMING_LIGHT_CRON_NAME,\n token: DREAMING_LIGHT_SWEEP_TOKEN,\n schedule: dreaming.phases.light.cron,\n phaseEnabled: dreaming.phases.light.enabled,\n },\n {\n cronName: DREAMING_CRON_NAME,\n token: DREAMING_SWEEP_TOKEN,\n schedule: dreaming.phases.deep.cron,\n phaseEnabled: dreaming.phases.deep.enabled,\n },\n {\n cronName: DREAMING_REM_CRON_NAME,\n token: DREAMING_REM_SWEEP_TOKEN,\n schedule: dreaming.phases.rem.cron,\n phaseEnabled: dreaming.phases.rem.enabled,\n },\n ];\n\n if (!dreaming.enabled) {\n for (const job of managed) {\n await cron.removeJob(job.id).catch(() => {});\n }\n return;\n }\n\n for (const spec of phaseSpecs) {\n const phaseJobs = managed.filter((job) => dreamingSweepTokenFromJob(job) === spec.token);\n\n if (!spec.phaseEnabled) {\n for (const job of phaseJobs) {\n await cron.removeJob(job.id).catch(() => {});\n }\n continue;\n }\n\n const desiredPayload = { kind: 'agentTurn' as const, message: spec.token };\n const desiredSchedule = {\n kind: 'cron' as const,\n expr: spec.schedule,\n ...(dreaming.timezone ? { tz: dreaming.timezone } : {}),\n };\n\n if (phaseJobs.length === 0) {\n await cron.addJob(desiredSchedule, {\n name: spec.cronName,\n sessionTarget: 'isolated' as const,\n payload: desiredPayload,\n enabled: true,\n } as any);\n continue;\n }\n\n const primary = phaseJobs[0]!;\n for (const dup of phaseJobs.slice(1)) {\n await cron.removeJob(dup.id).catch(() => {});\n }\n\n const payloadMessage =\n primary.payload?.kind === 'agentTurn'\n ? primary.payload.message\n : (primary.payload as any)?.text;\n const needsUpdate =\n JSON.stringify(primary.schedule) !== JSON.stringify(desiredSchedule) ||\n primary.sessionTarget !== 'isolated' ||\n payloadMessage !== spec.token ||\n primary.enabled !== true ||\n primary.name !== spec.cronName;\n\n if (needsUpdate) {\n await cron.updateJob(primary.id, {\n schedule: desiredSchedule,\n sessionTarget: 'isolated',\n name: spec.cronName,\n payload: desiredPayload,\n enabled: true,\n } as any);\n }\n }\n}\n"],"mappings":";;;AAaA,MAAM,wBAAwB,IAAI,IAAY;CAC5C;CACA;CACA;CACD,CAAC;AAEF,SAAS,0BAA0B,KAAkC;AACnE,KAAI,IAAI,SAAS,SAAS,YACxB;CAEF,MAAM,MAAM,IAAI,QAAQ;AACxB,QAAO,OAAO,QAAQ,YAAY,sBAAsB,IAAI,IAAI,GAAG,MAAM,KAAA;;;;;AAM3E,eAAsB,iCACpB,MACA,iBACe;CACf,MAAM,WAAW,sBAAsB,gBAAgB;;CAGvD,MAAM,WAAU,MAFG,KAAK,UAAU,EAEb,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAA,EAAU;CAElF,MAAM,aAKD;EACH;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,MAAM;GAChC,cAAc,SAAS,OAAO,MAAM;GACrC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,KAAK;GAC/B,cAAc,SAAS,OAAO,KAAK;GACpC;EACD;GACE,UAAU;GACV,OAAO;GACP,UAAU,SAAS,OAAO,IAAI;GAC9B,cAAc,SAAS,OAAO,IAAI;GACnC;EACF;AAED,KAAI,CAAC,SAAS,SAAS;AACrB,OAAK,MAAM,OAAO,QAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;AAGF,MAAK,MAAM,QAAQ,YAAY;EAC7B,MAAM,YAAY,QAAQ,QAAQ,QAAQ,0BAA0B,IAAI,KAAK,KAAK,MAAM;AAExF,MAAI,CAAC,KAAK,cAAc;AACtB,QAAK,MAAM,OAAO,UAChB,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;AAE9C;;EAGF,MAAM,iBAAiB;GAAE,MAAM;GAAsB,SAAS,KAAK;GAAO;EAC1E,MAAM,kBAAkB;GACtB,MAAM;GACN,MAAM,KAAK;GACX,GAAI,SAAS,WAAW,EAAE,IAAI,SAAS,UAAU,GAAG,EAAE;GACvD;AAED,MAAI,UAAU,WAAW,GAAG;AAC1B,SAAM,KAAK,OAAO,iBAAiB;IACjC,MAAM,KAAK;IACX,eAAe;IACf,SAAS;IACT,SAAS;IACV,CAAQ;AACT;;EAGF,MAAM,UAAU,UAAU;AAC1B,OAAK,MAAM,OAAO,UAAU,MAAM,EAAE,CAClC,OAAM,KAAK,UAAU,IAAI,GAAG,CAAC,YAAY,GAAG;EAG9C,MAAM,iBACJ,QAAQ,SAAS,SAAS,cACtB,QAAQ,QAAQ,UACf,QAAQ,SAAiB;AAQhC,MANE,KAAK,UAAU,QAAQ,SAAS,KAAK,KAAK,UAAU,gBAAgB,IACpE,QAAQ,kBAAkB,cAC1B,mBAAmB,KAAK,SACxB,QAAQ,YAAY,QACpB,QAAQ,SAAS,KAAK,SAGtB,OAAM,KAAK,UAAU,QAAQ,IAAI;GAC/B,UAAU;GACV,eAAe;GACf,MAAM,KAAK;GACX,SAAS;GACT,SAAS;GACV,CAAQ"}
@@ -5,7 +5,7 @@ import { SessionStore } from '../session/index.js';
5
5
  import { OutboundCoordinator } from './messaging/index.js';
6
6
  import { TurnDispatcher } from './inbound/turn-dispatcher.js';
7
7
  import { SessionConfigService, SessionHydrator, SessionInspector } from './session/index.js';
8
- import { type AgentSkillAvailabilityPayload, type SkillCatalogEntry } from './agent-manager.js';
8
+ import { type AgentSkillAvailabilityPayload, type SkillCatalogEntry, type SkillCatalogSnapshot } from './agent-manager.js';
9
9
  import type { SkillMarkdownPreviewPayload } from './skills/types.js';
10
10
  import type { AgentServiceConfig, StreamHandle } from './service.types.js';
11
11
  import { PersistentGoalService } from './goals/persistent-goal-service.js';
@@ -109,6 +109,7 @@ export declare class AgentService {
109
109
  */
110
110
  applyAgentDefaultsFromConfig(config: Config): void;
111
111
  getSkillCatalog(): SkillCatalogEntry[];
112
+ getSkillCatalogSnapshot(): SkillCatalogSnapshot;
112
113
  getAgentSkillAvailability(agentId: string): AgentSkillAvailabilityPayload;
113
114
  getSkillMarkdownSource(skillName: string): SkillMarkdownPreviewPayload | null;
114
115
  refreshSkillsAfterDiskChange(): void;
@@ -1,10 +1,11 @@
1
- import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
2
- import { applyConfigOverrides } from "../config/runtime-overrides.js";
3
1
  import { init_agent_scope, resolveAgentHomeDir, resolveAgentProfileDir, resolveDefaultAgentId } from "./agent-scope.js";
4
- import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
5
2
  import { createLogger } from "../utils/logger/index.js";
6
3
  import { init_logger } from "../utils/logger.js";
4
+ import { getAgentDefaultModelRef, init_schema } from "../config/schema.js";
5
+ import { applyConfigOverrides } from "../config/runtime-overrides.js";
6
+ import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../config/agent-profile.js";
7
7
  import { extractTextContent } from "./context/workspace.js";
8
+ import { parseNoteAttachmentTarget } from "../notes/attachment-ref.js";
8
9
  import { getWorkflowProgressBroker } from "./workflow/progress-broker.js";
9
10
  import { onSessionTranscriptUpdate } from "../session/transcript-events.js";
10
11
  import "./workflow/index.js";
@@ -60,8 +61,9 @@ import { parseOutboundSessionKey } from "./service/parse-outbound-session-key.js
60
61
  import { cleanTrailingErrors } from "./memory/message-sanitizer.js";
61
62
  import { MemoryFlushService } from "./memory/memory-flush.js";
62
63
  import { tryApplySessionTranscriptHygiene } from "./transcript/transcript-hygiene.js";
63
- import { join } from "node:path";
64
64
  import { existsSync, readFileSync } from "node:fs";
65
+ import { readFile } from "node:fs/promises";
66
+ import { join } from "node:path";
65
67
  //#region src/agent/service.ts
66
68
  init_schema();
67
69
  init_logger();
@@ -229,7 +231,8 @@ var AgentService = class {
229
231
  verboseLevel: config.verboseLevel,
230
232
  gatewayClarify: config.gatewayClarify,
231
233
  getCronService: config.getCronService,
232
- getWorkflowRunService: config.getWorkflowRunService
234
+ getWorkflowRunService: config.getWorkflowRunService,
235
+ onSkillsUpdated: config.onSkillsUpdated
233
236
  });
234
237
  this.agentEventHandler = new AgentEventHandler({
235
238
  progressManager: this.progressManager,
@@ -284,6 +287,7 @@ var AgentService = class {
284
287
  sessionStore: this.sessionStore,
285
288
  sessionConfigStore: this.sessionConfigStore,
286
289
  getPersistentGoalApisForCommand: (routing) => this.persistentGoals.buildApisForRouting(routing),
290
+ getWorkflowRunService: config.getWorkflowRunService,
287
291
  applySessionThinkingLevel: (sessionKey, level) => {
288
292
  this.agentManager.setThinkingLevel(sessionKey, level);
289
293
  },
@@ -297,6 +301,7 @@ var AgentService = class {
297
301
  await this.streamManager.abort();
298
302
  this.agentOrchestrator.abort(sessionKey);
299
303
  },
304
+ reloadSkills: () => this.refreshSkillsAfterDiskChange(),
300
305
  compactSession: (sessionKey, options) => this.sessionInspector.compact(sessionKey, options),
301
306
  btwQuery: (sessionKey, question) => this.sessionInspector.btwQuery(sessionKey, question),
302
307
  getSessionContextReport: (sessionKey, mode) => this.sessionInspector.report(sessionKey, mode)
@@ -310,6 +315,7 @@ var AgentService = class {
310
315
  getConfig: () => this.effectiveAppConfig(),
311
316
  getResolvedWorkspaceForSession: (sk) => this.agentManager.getResolvedWorkspaceForSession(sk),
312
317
  onSessionMetadataUpdated: this.onSessionMetadataUpdated,
318
+ onGoalStatusUpdated: config.onGoalStatusUpdated,
313
319
  notifyWebchatTranscriptAppend: (sk, text) => this.turnDispatcher.notifyWebchatTranscriptAppend(sk, text)
314
320
  });
315
321
  this.sessionConfig = new SessionConfigService({
@@ -508,6 +514,9 @@ var AgentService = class {
508
514
  getSkillCatalog() {
509
515
  return this.agentManager.getSkillCatalog();
510
516
  }
517
+ getSkillCatalogSnapshot() {
518
+ return this.agentManager.getSkillCatalogSnapshot();
519
+ }
511
520
  getAgentSkillAvailability(agentId) {
512
521
  return this.agentManager.getAgentSkillAvailability(agentId);
513
522
  }
@@ -680,7 +689,22 @@ var AgentService = class {
680
689
  * Persist inbound file attachments to the global media store.
681
690
  */
682
691
  async prepareInboundAttachments(_sessionKey, attachments) {
683
- return persistInboundAttachments(attachments);
692
+ return persistInboundAttachments(attachments, { resolveUri: async (uri) => {
693
+ const target = parseNoteAttachmentTarget(uri);
694
+ if (!target) return null;
695
+ const notesService = this.notesServiceInstance;
696
+ if (!notesService) return null;
697
+ const located = await notesService.getAttachmentPath(target.noteId, target.attachmentId);
698
+ if (!located) return null;
699
+ const buffer = await readFile(located.filePath);
700
+ return {
701
+ buffer,
702
+ path: located.filePath,
703
+ mimeType: located.mimeType,
704
+ name: located.fileName,
705
+ size: buffer.byteLength
706
+ };
707
+ } });
684
708
  }
685
709
  endDirectRequestContext() {
686
710
  this.feedbackCoordinator.clearContext();