@xopcai/xopc 0.0.196 → 0.0.199

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 (258) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{activity-store-BwmdJ5pv.js → activity-store-DYVN1hRp.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B1oxPli_.js → agent-avatar-dicebear-Bt70bZjv.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-D19uNmJf.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-BM1hNzjw.js → api-B8mzbAle.js} +1 -1
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-B4x7JfL8.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-Dwdagf-Q.js +1 -0
  9. package/dist/gateway/static/root/assets/apps-page-DkTiesxe.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-BdE4Mati.js → archive-plugin-Cv0VXKLm.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CTzaQcLV.js → attachment-load-CgidKrXn.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-BR6qMOVr.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-B25zTNxl.js → binary-plugins-DN3CQgIq.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-Cdrf2awF.js → block-editor-BwkSl1F_.js} +46 -46
  15. package/dist/gateway/static/root/assets/browser-settings-page-CDFQWAxI.js +8 -0
  16. package/dist/gateway/static/root/assets/browser-workflow-inputs-_ndaecsf.js +1 -0
  17. package/dist/gateway/static/root/assets/{browser-workflows-page-Wx9FrbK-.js → browser-workflows-page-C_I31wLm.js} +2 -2
  18. package/dist/gateway/static/root/assets/button-CSEbl4zT.js +1 -0
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-D41mssOq.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-BoOzFotX.js → capability-presets-api-Dy1jZJKs.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BXgCyuu2.js +3 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-_8IiTxRB.js → channel-recipient-api-D-9qiuio.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-DV5BhAeu.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-B4Rbh3bM.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-api-5FEBYguL.js +1 -0
  26. package/dist/gateway/static/root/assets/connectors-page-C_qkEN0T.js +2 -0
  27. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +1 -0
  28. package/dist/gateway/static/root/assets/cron-expression-SEFx5rnr.js +2 -0
  29. package/dist/gateway/static/root/assets/date-picker-D4zCUQJL.js +1 -0
  30. package/dist/gateway/static/root/assets/dependency-picker-DpQAxS2k.js +1 -0
  31. package/dist/gateway/static/root/assets/{desktop-pet-BOb8sEhN.js → desktop-pet-B_5G3lQl.js} +1 -1
  32. package/dist/gateway/static/root/assets/desktop-pet-settings-ClEyoUJe.js +1 -0
  33. package/dist/gateway/static/root/assets/directory-picker-path-field-AsFWmOjG.js +1 -0
  34. package/dist/gateway/static/root/assets/dist-BPoKqzeH.js +1 -0
  35. package/dist/gateway/static/root/assets/dist-DY4Af0fY.js +1 -0
  36. package/dist/gateway/static/root/assets/{extension-debug-page-p83TmZFd.js → extension-debug-page-C22Y2o5l.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-DMQ3ovxA.js → extension-page-C61Ikawk.js} +1 -1
  38. package/dist/gateway/static/root/assets/extension-settings-page-WlWWcDFr.js +1 -0
  39. package/dist/gateway/static/root/assets/external-link-DjqjBmc3.js +1 -0
  40. package/dist/gateway/static/root/assets/form-field-width-DJw_jULe.js +1 -0
  41. package/dist/gateway/static/root/assets/gateway-config-api-ByIOMQdc.js +1 -0
  42. package/dist/gateway/static/root/assets/gateway-config-swr-jB0hAhWO.js +1 -0
  43. package/dist/gateway/static/root/assets/gateway-settings-CzzS9A17.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-startup-retry--2njcDpC.js → gateway-startup-retry-C-fRlHCL.js} +1 -1
  45. package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +1 -0
  46. package/dist/gateway/static/root/assets/heartbeat-settings-B4A_CXUL.js +1 -0
  47. package/dist/gateway/static/root/assets/home-page-FVGYYPWo.js +3 -0
  48. package/dist/gateway/static/root/assets/index-CGbKTCST.js +152 -0
  49. package/dist/gateway/static/root/assets/index-CR233S0Q.css +1 -0
  50. package/dist/gateway/static/root/assets/interaction-BmQogeqz.js +1 -0
  51. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BQb06_jl.js → keyboard-shortcuts-settings-BD_TFz0_.js} +1 -1
  52. package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +1 -0
  53. package/dist/gateway/static/root/assets/local-app-workbench-page-BNpkigNb.js +2 -0
  54. package/dist/gateway/static/root/assets/local-apps-page-BwbUeLfm.js +1 -0
  55. package/dist/gateway/static/root/assets/{locale-store-Bjvw7jtg.js → locale-store-xULEcFVs.js} +1 -1
  56. package/dist/gateway/static/root/assets/logs-page-DXP9OQQt.js +2 -0
  57. package/dist/gateway/static/root/assets/management-settings-CW2VpqtT.js +1 -0
  58. package/dist/gateway/static/root/assets/{markdown-split-Db-KrpOQ.js → markdown-split-B1M9KO16.js} +1 -1
  59. package/dist/gateway/static/root/assets/{media-plugins-CHN66qs0.js → media-plugins-B_QlNdqZ.js} +1 -1
  60. package/dist/gateway/static/root/assets/messages-3qRsLZuX.js +3 -0
  61. package/dist/gateway/static/root/assets/{notes-page-CJtKZM0P.js → notes-page-BTbD4GmH.js} +1 -1
  62. package/dist/gateway/static/root/assets/notes-workbench-JRiq7QDW.js +4 -0
  63. package/dist/gateway/static/root/assets/page-tabs-BaEQMYm_.js +1 -0
  64. package/dist/gateway/static/root/assets/popover-select-BzdnTy3h.js +1 -0
  65. package/dist/gateway/static/root/assets/preview-open-alternatives-CeqtArlZ.js +1 -0
  66. package/dist/gateway/static/root/assets/{product-open-page--RnCc9bb.js → product-open-page-DnalBZZs.js} +1 -1
  67. package/dist/gateway/static/root/assets/project-detail-page-CjWA13aE.js +1 -0
  68. package/dist/gateway/static/root/assets/projects-page-jsCkScbG.js +1 -0
  69. package/dist/gateway/static/root/assets/remote-access-hub-CGPJTEkM.js +1 -0
  70. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bg1W2__k.js → runtime-tools-settings-panel-cGkBEfg4.js} +4 -4
  71. package/dist/gateway/static/root/assets/schema-form-CmsrLlxu.js +1 -0
  72. package/dist/gateway/static/root/assets/sessions-page-BBHzziMd.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-2cGg8-9h.js +1 -0
  74. package/dist/gateway/static/root/assets/settings-form-draft-Dy10ldo8.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-form-section-DUWCbaMJ.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BS36Mjzz.js → settings-loading-skeleton-Bvy5rdMY.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-BDSd7F9Y.js → settings-page-cZSAwsRR.js} +1 -1
  78. package/dist/gateway/static/root/assets/settings-page-layout-BRQNel6r.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-shell-dialog-layer-BU3UuiJr.js +1 -0
  80. package/dist/gateway/static/root/assets/setup-status-panel-Cf06b66-.js +1 -0
  81. package/dist/gateway/static/root/assets/share-preview-page-BzA2NCAH.js +2 -0
  82. package/dist/gateway/static/root/assets/shares-settings-xlNKydYY.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-C5Xu93c_.js +1 -0
  84. package/dist/gateway/static/root/assets/skills-page-Bvde7_i5.js +2 -0
  85. package/dist/gateway/static/root/assets/{skills-page.utils-CnbJncdL.js → skills-page.utils-vXSqHR7g.js} +1 -1
  86. package/dist/gateway/static/root/assets/system-settings-panel-9cQGOGCK.js +1 -0
  87. package/dist/gateway/static/root/assets/task-detail-page-Bkno4tTe.js +1 -0
  88. package/dist/gateway/static/root/assets/{theme-store-DtxpMC5S.js → theme-store-CHQRiuCF.js} +1 -1
  89. package/dist/gateway/static/root/assets/tool-activity-R8V9l6nk.js +1 -0
  90. package/dist/gateway/static/root/assets/typed-models-lib-q5-Vfqd8.js +1 -0
  91. package/dist/gateway/static/root/assets/use-autosave-7XfKULPI.js +1 -0
  92. package/dist/gateway/static/root/assets/user-context-page-CZ9m9aC_.js +1 -0
  93. package/dist/gateway/static/root/assets/voice-api-key-field-DXr21v-3.js +1 -0
  94. package/dist/gateway/static/root/assets/work-discovery-overlay-CeG7g_DZ.js +1 -0
  95. package/dist/gateway/static/root/assets/work-discovery-page-CQWZD03N.js +1 -0
  96. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BEmugHfL.js → workflow-run-setup-panel-DSQQZP9T.js} +2 -2
  97. package/dist/gateway/static/root/assets/workflows-page-Cs-MXFJ1.js +5 -0
  98. package/dist/gateway/static/root/assets/working-directory-picker-modal-D-IgcHPp.js +1 -0
  99. package/dist/gateway/static/root/index.html +23 -8
  100. package/dist/package.js +1 -1
  101. package/dist/packages/gateway-contract/src/tasks.js +54 -2
  102. package/dist/src/agent/agent-manager.d.ts +1 -0
  103. package/dist/src/agent/agent-manager.js +1 -0
  104. package/dist/src/agent/embedded/execution-context.d.ts +2 -0
  105. package/dist/src/agent/embedded/execution-context.js +11 -0
  106. package/dist/src/agent/embedded/index.d.ts +3 -1
  107. package/dist/src/agent/embedded/index.js +5 -3
  108. package/dist/src/agent/embedded/run-turn.js +15 -9
  109. package/dist/src/agent/embedded/session-runner.d.ts +6 -11
  110. package/dist/src/agent/embedded/session-runner.js +25 -36
  111. package/dist/src/agent/embedded/transcript-runtime.d.ts +35 -0
  112. package/dist/src/agent/embedded/transcript-runtime.js +66 -0
  113. package/dist/src/agent/embedded/types.d.ts +3 -1
  114. package/dist/src/agent/service.d.ts +15 -0
  115. package/dist/src/agent/service.js +31 -0
  116. package/dist/src/agent/service.types.d.ts +1 -0
  117. package/dist/src/agent/tools/factory.d.ts +2 -0
  118. package/dist/src/agent/tools/factory.js +2 -1
  119. package/dist/src/agent/tools/xopc-use-tool.d.ts +1 -0
  120. package/dist/src/agent/tools/xopc-use-tool.js +56 -6
  121. package/dist/src/automations/domain/validation.d.ts +40 -0
  122. package/dist/src/automations/draft/automation-draft-validator.d.ts +4 -1
  123. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  124. package/dist/src/config/agent-profile.js +1 -1
  125. package/dist/src/config/rules.js +2 -2
  126. package/dist/src/gateway/agents-admin.js +1 -1
  127. package/dist/src/gateway/hono/app.d.ts +2 -0
  128. package/dist/src/gateway/hono/app.js +10 -3
  129. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
  130. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +8 -1
  131. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -1
  132. package/dist/src/gateway/hono/routes/config.js +9 -0
  133. package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
  134. package/dist/src/gateway/hono/routes/home.d.ts +1 -1
  135. package/dist/src/gateway/hono/routes/home.js +2 -2
  136. package/dist/src/gateway/hono/routes/index.js +2 -0
  137. package/dist/src/gateway/hono/routes/projects.js +67 -1
  138. package/dist/src/gateway/hono/routes/side-chats.d.ts +3 -0
  139. package/dist/src/gateway/hono/routes/side-chats.js +173 -0
  140. package/dist/src/gateway/hono/routes/tasks.js +112 -19
  141. package/dist/src/gateway/host.d.ts +9 -1
  142. package/dist/src/gateway/host.js +22 -5
  143. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  144. package/dist/src/gateway/rate-limit/buckets.js +12 -0
  145. package/dist/src/gateway/runtime-config.js +6 -5
  146. package/dist/src/gateway/security/audit.js +0 -7
  147. package/dist/src/gateway/server.js +4 -1
  148. package/dist/src/gateway/service/agent-runner.d.ts +4 -0
  149. package/dist/src/gateway/service/agent-runner.js +15 -1
  150. package/dist/src/gateway/service/run-gateway-agent.js +1 -1
  151. package/dist/src/gateway/service.d.ts +5 -0
  152. package/dist/src/gateway/service.js +38 -8
  153. package/dist/src/gateway/side-chat/context-snapshot.d.ts +11 -0
  154. package/dist/src/gateway/side-chat/context-snapshot.js +108 -0
  155. package/dist/src/gateway/side-chat/index.d.ts +5 -0
  156. package/dist/src/gateway/side-chat/index.js +4 -0
  157. package/dist/src/gateway/side-chat/manager.d.ts +45 -0
  158. package/dist/src/gateway/side-chat/manager.js +198 -0
  159. package/dist/src/gateway/side-chat/run-service.d.ts +22 -0
  160. package/dist/src/gateway/side-chat/run-service.js +110 -0
  161. package/dist/src/gateway/side-chat/types.d.ts +61 -0
  162. package/dist/src/gateway/side-chat/types.js +1 -0
  163. package/dist/src/proactive/actions/service.d.ts +2 -0
  164. package/dist/src/proactive/actions/service.js +80 -0
  165. package/dist/src/proactive/execution/insight.js +20 -0
  166. package/dist/src/proactive/execution/repository.js +8 -2
  167. package/dist/src/proactive/execution/types.d.ts +14 -0
  168. package/dist/src/proactive/inbox/repository.js +59 -9
  169. package/dist/src/proactive/inbox/service.d.ts +2 -2
  170. package/dist/src/proactive/inbox/service.js +7 -2
  171. package/dist/src/proactive/inbox/types.d.ts +14 -0
  172. package/dist/src/proactive/inbox/worker.js +2 -0
  173. package/dist/src/proactive/scenarios/prompt-composer.js +2 -2
  174. package/dist/src/routing/session-key-utils.d.ts +0 -1
  175. package/dist/src/routing/session-key-utils.js +1 -6
  176. package/dist/src/routing/session-key.js +2 -2
  177. package/dist/src/storage/sqlite/migrations/118_task_board_rank.sql +6 -0
  178. package/dist/src/storage/sqlite/migrations/119_proactive_disposition.sql +13 -0
  179. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  180. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  181. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  182. package/dist/src/storage/sqlite/schema.js +1 -1
  183. package/dist/src/tasks/home-query-service.d.ts +29 -0
  184. package/dist/src/tasks/home-query-service.js +291 -7
  185. package/dist/src/tasks/index.d.ts +1 -0
  186. package/dist/src/tasks/index.js +5 -4
  187. package/dist/src/tasks/project-monitoring-service.d.ts +9 -0
  188. package/dist/src/tasks/project-monitoring-service.js +41 -3
  189. package/dist/src/tasks/project-operating-view-service.d.ts +2 -2
  190. package/dist/src/tasks/project-operating-view-service.js +47 -21
  191. package/dist/src/tasks/task-application-service.js +99 -6
  192. package/dist/src/tasks/task-change-events.d.ts +13 -0
  193. package/dist/src/tasks/task-change-events.js +29 -0
  194. package/dist/src/tasks/task-read-model-projector.js +2 -1
  195. package/dist/src/tasks/task-repository.d.ts +7 -0
  196. package/dist/src/tasks/task-repository.js +29 -6
  197. package/dist/src/tunnel/enable-lan-pairing.js +15 -26
  198. package/dist/src/tunnel/pair-context.js +1 -1
  199. package/dist/src/tunnel/pair-url.js +1 -1
  200. package/dist/src/tunnel/tunnel-qr.d.ts +0 -7
  201. package/dist/src/tunnel/tunnel-qr.js +2 -19
  202. package/package.json +4 -2
  203. package/dist/gateway/static/root/assets/agents-VoFNMGL3.js +0 -68
  204. package/dist/gateway/static/root/assets/app-management-settings-panel-vmuJ_Z6i.js +0 -1
  205. package/dist/gateway/static/root/assets/appearance-settings-BMlEoe-G.js +0 -1
  206. package/dist/gateway/static/root/assets/apps-page-CsNB6mv_.js +0 -1
  207. package/dist/gateway/static/root/assets/automations-page-CW1YWgiX.js +0 -6
  208. package/dist/gateway/static/root/assets/browser-settings-page-BMTmGMM6.js +0 -8
  209. package/dist/gateway/static/root/assets/browser-workflow-inputs-BsmHy0ks.js +0 -1
  210. package/dist/gateway/static/root/assets/capabilities-settings-panel-C5l85__e.js +0 -7
  211. package/dist/gateway/static/root/assets/capability-presets-settings-panel-9T2KXAs1.js +0 -3
  212. package/dist/gateway/static/root/assets/channels-settings-DquD4BPQ.js +0 -1
  213. package/dist/gateway/static/root/assets/channels-status-swr-DPaJSYX_.js +0 -1
  214. package/dist/gateway/static/root/assets/connectors-api-BC-4ftOM.js +0 -1
  215. package/dist/gateway/static/root/assets/connectors-page-7zUxVHQg.js +0 -2
  216. package/dist/gateway/static/root/assets/cron-expression-BycQlU8Q.js +0 -2
  217. package/dist/gateway/static/root/assets/dependency-picker-BvYqHRz0.js +0 -1
  218. package/dist/gateway/static/root/assets/desktop-pet-settings-DStgPb82.js +0 -1
  219. package/dist/gateway/static/root/assets/directory-picker-path-field-DUUr9sq0.js +0 -1
  220. package/dist/gateway/static/root/assets/extension-settings-page-BcSKEU8s.js +0 -1
  221. package/dist/gateway/static/root/assets/gateway-config-api-C-MmtCc7.js +0 -1
  222. package/dist/gateway/static/root/assets/gateway-settings-CuaRDWbg.js +0 -1
  223. package/dist/gateway/static/root/assets/heartbeat-settings-Dm8TrfGa.js +0 -1
  224. package/dist/gateway/static/root/assets/home-page-BYhDbUvI.js +0 -3
  225. package/dist/gateway/static/root/assets/index-BzPwnXho.js +0 -150
  226. package/dist/gateway/static/root/assets/index-CFFYvilx.css +0 -1
  227. package/dist/gateway/static/root/assets/local-app-workbench-page-CHk4x0kR.js +0 -2
  228. package/dist/gateway/static/root/assets/local-apps-page-DQtsxjGs.js +0 -1
  229. package/dist/gateway/static/root/assets/logs-page-CDqIY72S.js +0 -2
  230. package/dist/gateway/static/root/assets/management-settings-D7itDEHl.js +0 -1
  231. package/dist/gateway/static/root/assets/messages-DQ5X6cXp.js +0 -3
  232. package/dist/gateway/static/root/assets/notes-workbench-epHGeKd5.js +0 -4
  233. package/dist/gateway/static/root/assets/page-tabs-HXweXqYE.js +0 -1
  234. package/dist/gateway/static/root/assets/preview-open-alternatives-Dob6Oe2l.js +0 -1
  235. package/dist/gateway/static/root/assets/project-detail-page-BxOD5-zj.js +0 -1
  236. package/dist/gateway/static/root/assets/projects-page-D-9AhrH5.js +0 -1
  237. package/dist/gateway/static/root/assets/remote-access-hub-CSUNXLKM.js +0 -1
  238. package/dist/gateway/static/root/assets/schema-form-BI4rVt3u.js +0 -1
  239. package/dist/gateway/static/root/assets/sessions-page-BxOUBMca.js +0 -1
  240. package/dist/gateway/static/root/assets/settings-advanced-gate-DAvTIbgw.js +0 -1
  241. package/dist/gateway/static/root/assets/settings-form-section-C7rzhi7x.js +0 -1
  242. package/dist/gateway/static/root/assets/settings-page-layout-CTMmZcwj.js +0 -1
  243. package/dist/gateway/static/root/assets/setup-status-panel-D1v-2Ci-.js +0 -1
  244. package/dist/gateway/static/root/assets/share-preview-page-BeCxg6eb.js +0 -2
  245. package/dist/gateway/static/root/assets/shares-settings-CXL1EldF.js +0 -1
  246. package/dist/gateway/static/root/assets/skill-reload-api-BxwkKgVw.js +0 -1
  247. package/dist/gateway/static/root/assets/skills-page-CyfjEM4D.js +0 -2
  248. package/dist/gateway/static/root/assets/system-settings-panel-CAv0Yk0Y.js +0 -1
  249. package/dist/gateway/static/root/assets/task-detail-page-DGTVJs_N.js +0 -1
  250. package/dist/gateway/static/root/assets/typed-models-lib-DomX3Szl.js +0 -1
  251. package/dist/gateway/static/root/assets/use-autosave-BLc4gfG0.js +0 -1
  252. package/dist/gateway/static/root/assets/user-context-page-C2kQENTK.js +0 -1
  253. package/dist/gateway/static/root/assets/voice-api-key-field-BijmpPjb.js +0 -1
  254. package/dist/gateway/static/root/assets/work-discovery-overlay-D7w2JFFq.js +0 -1
  255. package/dist/gateway/static/root/assets/work-discovery-page-XtoPgPUS.js +0 -1
  256. package/dist/gateway/static/root/assets/workflows-page-D_K2xOWq.js +0 -5
  257. package/dist/src/gateway/ensure-network-cors.d.ts +0 -3
  258. package/dist/src/gateway/ensure-network-cors.js +0 -23
@@ -0,0 +1,110 @@
1
+ import { createLogger } from "../../utils/logger/index.js";
2
+ import { init_logger } from "../../utils/logger.js";
3
+ import { abortEmbeddedRun } from "../../agent/embedded/runs.js";
4
+ import { SideChatError } from "./manager.js";
5
+ import { ChatStreamMapper } from "../chat-stream/mapper.js";
6
+ import { randomUUID } from "node:crypto";
7
+ //#region src/gateway/side-chat/run-service.ts
8
+ init_logger();
9
+ const log = createLogger("Gateway:SideChatRun");
10
+ var SideChatRunService = class {
11
+ activeBySideChat = /* @__PURE__ */ new Map();
12
+ constructor(options) {
13
+ this.options = options;
14
+ }
15
+ submit(sideChatId, clientInstanceId, content) {
16
+ const text = content.trim();
17
+ if (!text) throw new SideChatError("content is required", "INVALID_REQUEST");
18
+ const sideChat = this.options.manager.get(sideChatId, clientInstanceId);
19
+ if (this.activeBySideChat.has(sideChatId)) throw new SideChatError("A side chat run is already active", "CONFLICT");
20
+ const run = {
21
+ sideChatId,
22
+ clientInstanceId,
23
+ executionSessionKey: this.options.manager.getRuntime(sideChatId, clientInstanceId).runtimeId,
24
+ runId: randomUUID(),
25
+ abortController: new AbortController()
26
+ };
27
+ this.activeBySideChat.set(sideChatId, run);
28
+ this.options.manager.setStatus(sideChatId, clientInstanceId, "running");
29
+ this.execute(run, text, sideChat.config).catch((err) => {
30
+ log.error({
31
+ err,
32
+ sideChatId,
33
+ runId: run.runId
34
+ }, "Side chat run cleanup failed");
35
+ });
36
+ return { runId: run.runId };
37
+ }
38
+ async abort(sideChatId, clientInstanceId, runId) {
39
+ this.options.manager.get(sideChatId, clientInstanceId);
40
+ const active = this.activeBySideChat.get(sideChatId);
41
+ if (!active || runId && active.runId !== runId) return false;
42
+ this.options.agentRunner.cancelClarificationForRun(active.runId);
43
+ active.abortController.abort();
44
+ await abortEmbeddedRun(active.executionSessionKey).catch(() => false);
45
+ return true;
46
+ }
47
+ async dispose(sideChatId, clientInstanceId) {
48
+ await this.abort(sideChatId, clientInstanceId).catch(() => false);
49
+ return this.options.manager.dispose(sideChatId, clientInstanceId);
50
+ }
51
+ submitClarification(sideChatId, clientInstanceId, requestId, answer) {
52
+ this.options.manager.get(sideChatId, clientInstanceId);
53
+ return this.options.agentRunner.submitClarifyResponse(requestId, answer);
54
+ }
55
+ async execute(run, content, config) {
56
+ const topic = `run:${run.runId}`;
57
+ const mapper = new ChatStreamMapper({
58
+ runId: run.runId,
59
+ sessionKey: run.sideChatId,
60
+ channel: "side-chat"
61
+ });
62
+ const publish = (event) => {
63
+ this.options.publishRealtime(topic, event.type, event);
64
+ };
65
+ const publishMapped = (event) => {
66
+ for (const mapped of mapper.map(event)) publish(mapped);
67
+ };
68
+ try {
69
+ for (const event of mapper.start()) publish(event);
70
+ publishMapped({
71
+ type: "user_message",
72
+ message: {
73
+ role: "user",
74
+ content,
75
+ timestamp: Date.now()
76
+ }
77
+ });
78
+ this.options.agentRunner.registerExternalWebchatRun(run.executionSessionKey, run.runId, (event) => publishMapped(event));
79
+ const result = await this.options.getAgentService().runEphemeralTurn({
80
+ executionSessionKey: run.executionSessionKey,
81
+ parentSessionKey: this.options.manager.get(run.sideChatId, run.clientInstanceId).parentSessionKey,
82
+ runId: run.runId,
83
+ content,
84
+ modelRef: config.modelRef,
85
+ thinkingLevel: config.thinkingLevel,
86
+ transcriptRuntime: this.options.manager.getRuntime(run.sideChatId, run.clientInstanceId),
87
+ abortSignal: run.abortController.signal,
88
+ onEvent: publishMapped
89
+ });
90
+ const cancelled = run.abortController.signal.aborted;
91
+ const status = cancelled ? "cancelled" : result.ok ? "success" : "error";
92
+ if (!result.ok && result.errorMessage) for (const event of mapper.error(result.errorMessage)) publish(event);
93
+ for (const event of mapper.end(status, cancelled ? "Interrupted" : result.errorMessage)) publish(event);
94
+ } catch (error) {
95
+ const message = error instanceof Error ? error.message : String(error);
96
+ for (const event of mapper.error(message)) publish(event);
97
+ for (const event of mapper.end("error", message)) publish(event);
98
+ } finally {
99
+ this.options.agentRunner.unregisterExternalWebchatRun(run.executionSessionKey, run.runId);
100
+ this.activeBySideChat.delete(run.sideChatId);
101
+ try {
102
+ this.options.manager.getMessages(run.sideChatId, run.clientInstanceId);
103
+ this.options.manager.setStatus(run.sideChatId, run.clientInstanceId, "idle");
104
+ } catch {}
105
+ this.options.completeRealtimeTopic(topic);
106
+ }
107
+ }
108
+ };
109
+ //#endregion
110
+ export { SideChatRunService };
@@ -0,0 +1,61 @@
1
+ import type { ThinkingLevel } from '@earendil-works/pi-agent-core';
2
+ export type SideChatStatus = 'idle' | 'running' | 'waiting-approval' | 'waiting-input' | 'closing';
3
+ export type SideChatSelection = {
4
+ id: string;
5
+ type: 'message';
6
+ messageId: string;
7
+ role: string;
8
+ content: string;
9
+ label?: string;
10
+ } | {
11
+ id: string;
12
+ type: 'text';
13
+ text: string;
14
+ sourceMessageId?: string;
15
+ label?: string;
16
+ } | {
17
+ id: string;
18
+ type: 'file-range';
19
+ path: string;
20
+ startLine: number;
21
+ endLine: number;
22
+ text: string;
23
+ contentHash?: string;
24
+ label?: string;
25
+ } | {
26
+ id: string;
27
+ type: 'diff';
28
+ diff: string;
29
+ path?: string;
30
+ label?: string;
31
+ };
32
+ export interface SideChatContextSnapshot {
33
+ parentSessionKey: string;
34
+ parentSessionId: string;
35
+ parentMessageCount: number;
36
+ createdAt: string;
37
+ selections: SideChatSelection[];
38
+ contentHash: string;
39
+ }
40
+ export interface SideChatConfig {
41
+ modelRef: string;
42
+ thinkingLevel?: ThinkingLevel;
43
+ }
44
+ export interface SideChatView {
45
+ id: string;
46
+ parentSessionKey: string;
47
+ clientInstanceId: string;
48
+ status: SideChatStatus;
49
+ createdAt: string;
50
+ lastActiveAt: string;
51
+ expiresAt: string;
52
+ messageCount: number;
53
+ context: SideChatContextSnapshot;
54
+ config: SideChatConfig;
55
+ }
56
+ export interface CreateSideChatInput {
57
+ parentSessionKey: string;
58
+ clientInstanceId: string;
59
+ selections?: SideChatSelection[];
60
+ config?: Partial<SideChatConfig>;
61
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function executePendingProactiveActions(now?: Date): number;
2
+ export declare function resolveProactiveActionDecision(inboxItemId: string, choice: string, now?: Date): void;
@@ -0,0 +1,80 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
2
+ import { TaskApplicationService } from "../../tasks/task-application-service.js";
3
+ //#region src/proactive/actions/service.ts
4
+ function projectIdFromAggregationKey(value) {
5
+ if (!value.startsWith("project:") || value.length === 8) throw new Error("Proactive action has no project scope");
6
+ return value.slice(8);
7
+ }
8
+ function executeClaimedAction(row, now = /* @__PURE__ */ new Date()) {
9
+ const action = JSON.parse(row.proposed_action_json);
10
+ try {
11
+ if (action.id !== "create_project_task") throw new Error(`Unsupported proactive action: ${action.id}`);
12
+ const result = new TaskApplicationService().create({
13
+ idempotencyKey: `proactive:${row.insight_id}:${action.id}`,
14
+ title: action.input.title,
15
+ projectId: projectIdFromAggregationKey(row.aggregation_key),
16
+ priority: "normal",
17
+ contract: {
18
+ objective: action.input.objective,
19
+ expectedOutputs: [],
20
+ acceptanceCriteria: [],
21
+ constraints: [],
22
+ approvalRequired: [],
23
+ assumptions: [],
24
+ risks: [],
25
+ acceptancePolicy: "manual",
26
+ outputDestinations: []
27
+ },
28
+ dependencies: [],
29
+ context: [],
30
+ authorityGrants: [],
31
+ activation: {
32
+ mode: "capture",
33
+ phase: "backlog"
34
+ }
35
+ }, {
36
+ kind: "system",
37
+ id: "proactive"
38
+ });
39
+ if (!result.ok) throw new Error(`Task creation failed: ${"reason" in result ? result.reason : "unknown"}`);
40
+ getSqliteDatabase().prepare(`UPDATE proactive_insights
41
+ SET action_status = 'completed', action_result_json = ?, action_error = NULL, action_updated_at = ?
42
+ WHERE insight_id = ? AND action_status = 'executing'`).run(JSON.stringify({ taskId: result.model.task.id }), now.toISOString(), row.insight_id);
43
+ } catch (error) {
44
+ getSqliteDatabase().prepare(`UPDATE proactive_insights
45
+ SET action_status = 'failed', action_error = ?, action_updated_at = ?
46
+ WHERE insight_id = ? AND action_status = 'executing'`).run(String(error instanceof Error ? error.message : error).slice(0, 2e3), now.toISOString(), row.insight_id);
47
+ }
48
+ }
49
+ function executePendingProactiveActions(now = /* @__PURE__ */ new Date()) {
50
+ const expired = (/* @__PURE__ */ new Date(now.getTime() - 5 * 6e4)).toISOString();
51
+ getSqliteDatabase().prepare(`UPDATE proactive_insights SET action_status = 'pending', action_updated_at = ?
52
+ WHERE action_status = 'executing' AND action_updated_at <= ?`).run(now.toISOString(), expired);
53
+ let executed = 0;
54
+ while (true) {
55
+ const row = runSqliteWriteTransaction((db) => {
56
+ const candidate = db.prepare(`SELECT x.insight_id, b.aggregation_key, x.proposed_action_json
57
+ FROM proactive_insights x
58
+ JOIN proactive_runs r ON r.run_id = x.run_id
59
+ JOIN proactive_signal_batches b ON b.batch_id = r.batch_id
60
+ WHERE x.action_status = 'pending' ORDER BY x.created_at LIMIT 1`).get();
61
+ if (!candidate) return void 0;
62
+ return db.prepare(`UPDATE proactive_insights SET action_status = 'executing', action_updated_at = ?
63
+ WHERE insight_id = ? AND action_status = 'pending'`).run(now.toISOString(), candidate.insight_id).changes === 1 ? candidate : void 0;
64
+ });
65
+ if (!row) return executed;
66
+ executeClaimedAction(row, now);
67
+ executed += 1;
68
+ }
69
+ }
70
+ function resolveProactiveActionDecision(inboxItemId, choice, now = /* @__PURE__ */ new Date()) {
71
+ const row = getSqliteDatabase().prepare(`SELECT x.insight_id, x.action_status
72
+ FROM proactive_inbox_items i JOIN proactive_insights x ON x.insight_id = i.insight_id
73
+ WHERE i.inbox_item_id = ?`).get(inboxItemId);
74
+ if (!row || row.action_status !== "approval_required") return;
75
+ getSqliteDatabase().prepare(`UPDATE proactive_insights SET action_status = ?, action_updated_at = ?
76
+ WHERE insight_id = ? AND action_status = 'approval_required'`).run(choice === "approve" ? "pending" : "rejected", now.toISOString(), row.insight_id);
77
+ if (choice === "approve") executePendingProactiveActions(now);
78
+ }
79
+ //#endregion
80
+ export { executePendingProactiveActions, resolveProactiveActionDecision };
@@ -30,6 +30,23 @@ function parseDecision(value) {
30
30
  options
31
31
  };
32
32
  }
33
+ function parseProposedAction(value) {
34
+ if (value == null) return void 0;
35
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Insight proposedAction is invalid");
36
+ const row = value;
37
+ if (row.id !== "create_project_task" || row.risk !== "low") throw new Error("Insight proposedAction is not supported");
38
+ if (!row.input || typeof row.input !== "object" || Array.isArray(row.input)) throw new Error("Insight proposedAction input is invalid");
39
+ const input = row.input;
40
+ return {
41
+ id: "create_project_task",
42
+ risk: "low",
43
+ rationale: boundedText(row.rationale, "proposedAction rationale", 600),
44
+ input: {
45
+ title: boundedText(input.title, "proposedAction title", 160),
46
+ objective: boundedText(input.objective, "proposedAction objective", 1200)
47
+ }
48
+ };
49
+ }
33
50
  function parseInsightCandidate(raw, allowedEvidenceIds) {
34
51
  let value;
35
52
  try {
@@ -45,6 +62,8 @@ function parseInsightCandidate(raw, allowedEvidenceIds) {
45
62
  const evidenceIds = [...new Set(row.evidenceIds.map(String))];
46
63
  if (evidenceIds.some((id) => !allowedEvidenceIds.has(id))) throw new Error("Insight cites unknown evidence");
47
64
  const decision = parseDecision(row.decision);
65
+ const proposedAction = parseProposedAction(row.proposedAction);
66
+ if (proposedAction && (!decision || decision.options.length !== 2 || decision.options[0]?.id !== "approve" || decision.options[1]?.id !== "reject")) throw new Error("Insight proposedAction requires approve and reject decision options");
48
67
  return {
49
68
  title: boundedText(row.title, "title", 160),
50
69
  summary: boundedText(row.summary, "summary", 1200),
@@ -53,6 +72,7 @@ function parseInsightCandidate(raw, allowedEvidenceIds) {
53
72
  recommendation: boundedText(row.recommendation, "recommendation", 800),
54
73
  workDone: boundedText(row.workDone, "workDone", 800),
55
74
  ...decision ? { decision } : {},
75
+ ...proposedAction ? { proposedAction } : {},
56
76
  urgency: String(row.urgency),
57
77
  confidence: row.confidence,
58
78
  evidenceIds
@@ -96,9 +96,9 @@ function finishRun(input, now = /* @__PURE__ */ new Date()) {
96
96
  createdAt: nowIso
97
97
  };
98
98
  db.prepare(`INSERT INTO proactive_insights (insight_id, run_id, subscription_id, scenario_key, title, summary,
99
- why_now, impact, recommendation, work_done, decision_json, urgency, confidence, value_score,
99
+ why_now, impact, recommendation, work_done, decision_json, proposed_action_json, urgency, confidence, value_score,
100
100
  evidence_ids_json, content_fingerprint, created_at)
101
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(insight.id, insight.runId, insight.subscriptionId, insight.scenarioKey, insight.title, insight.summary, insight.whyNow, insight.impact, insight.recommendation, insight.workDone, insight.decision ? JSON.stringify(insight.decision) : null, insight.urgency, insight.confidence, insight.valueScore, JSON.stringify(insight.evidenceIds), fingerprint, insight.createdAt);
101
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(insight.id, insight.runId, insight.subscriptionId, insight.scenarioKey, insight.title, insight.summary, insight.whyNow, insight.impact, insight.recommendation, insight.workDone, insight.decision ? JSON.stringify(insight.decision) : null, insight.proposedAction ? JSON.stringify(insight.proposedAction) : null, insight.urgency, insight.confidence, insight.valueScore, JSON.stringify(insight.evidenceIds), fingerprint, insight.createdAt);
102
102
  return insight;
103
103
  });
104
104
  }
@@ -124,9 +124,15 @@ function listInsights(limit = 50) {
124
124
  recommendation: str(row, "recommendation"),
125
125
  workDone: str(row, "work_done"),
126
126
  ...row.decision_json ? { decision: JSON.parse(str(row, "decision_json")) } : {},
127
+ ...row.proposed_action_json ? { proposedAction: JSON.parse(str(row, "proposed_action_json")) } : {},
127
128
  urgency: str(row, "urgency"),
128
129
  confidence: Number(row.confidence),
129
130
  valueScore: Number(row.value_score),
131
+ ...row.disposition ? { disposition: str(row, "disposition") } : {},
132
+ ...row.disposition_reason ? { dispositionReason: str(row, "disposition_reason") } : {},
133
+ ...row.action_status ? { actionStatus: str(row, "action_status") } : {},
134
+ ...row.action_result_json ? { actionResult: JSON.parse(str(row, "action_result_json")) } : {},
135
+ ...row.action_error ? { actionError: str(row, "action_error") } : {},
130
136
  evidenceIds: JSON.parse(str(row, "evidence_ids_json")),
131
137
  createdAt: str(row, "created_at")
132
138
  }));
@@ -20,6 +20,15 @@ export interface InsightCandidate {
20
20
  consequence: string;
21
21
  }>;
22
22
  };
23
+ proposedAction?: {
24
+ id: 'create_project_task';
25
+ risk: 'low';
26
+ rationale: string;
27
+ input: {
28
+ title: string;
29
+ objective: string;
30
+ };
31
+ };
23
32
  urgency: 'low' | 'medium' | 'high' | 'critical';
24
33
  confidence: number;
25
34
  evidenceIds: string[];
@@ -30,6 +39,11 @@ export interface ProactiveInsight extends InsightCandidate {
30
39
  subscriptionId: string;
31
40
  scenarioKey: string;
32
41
  valueScore: number;
42
+ disposition?: 'record_silently' | 'show_in_work' | 'request_approval' | 'auto_execute';
43
+ dispositionReason?: string;
44
+ actionStatus?: 'not_authorized' | 'approval_required' | 'pending' | 'executing' | 'completed' | 'rejected' | 'failed';
45
+ actionResult?: Record<string, unknown>;
46
+ actionError?: string;
33
47
  createdAt: string;
34
48
  }
35
49
  export interface ProactiveAgentExecutor {
@@ -1,4 +1,5 @@
1
1
  import { getSqliteDatabase, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
2
+ import { decideProactiveDisposition, nextQuietHoursEnd, proactiveDispositionReason } from "../../tasks/project-monitoring-service.js";
2
3
  import { randomUUID } from "node:crypto";
3
4
  //#region src/proactive/inbox/repository.ts
4
5
  const s = (row, key) => String(row[key]);
@@ -20,6 +21,12 @@ function itemFromRow(row) {
20
21
  recommendation: s(row, "recommendation"),
21
22
  workDone: s(row, "work_done"),
22
23
  ...row.decision_json ? { decision: JSON.parse(s(row, "decision_json")) } : {},
24
+ ...row.proposed_action_json ? { proposedAction: JSON.parse(s(row, "proposed_action_json")) } : {},
25
+ disposition: s(row, "disposition"),
26
+ dispositionReason: s(row, "disposition_reason"),
27
+ ...row.action_status ? { actionStatus: s(row, "action_status") } : {},
28
+ ...row.action_result_json ? { actionResult: JSON.parse(s(row, "action_result_json")) } : {},
29
+ ...row.action_error ? { actionError: s(row, "action_error") } : {},
23
30
  urgency: s(row, "urgency"),
24
31
  confidence: Number(row.confidence),
25
32
  valueScore: Number(row.value_score),
@@ -28,27 +35,70 @@ function itemFromRow(row) {
28
35
  };
29
36
  }
30
37
  const SELECT_ITEM = `SELECT i.*, x.subscription_id, x.scenario_key, x.title, x.summary, x.why_now, x.impact, x.recommendation,
31
- x.work_done, x.decision_json, x.urgency, x.confidence, x.value_score, x.evidence_ids_json FROM proactive_inbox_items i
38
+ x.work_done, x.decision_json, x.proposed_action_json, x.disposition, x.disposition_reason,
39
+ x.action_status, x.action_result_json, x.action_error, x.urgency, x.confidence, x.value_score, x.evidence_ids_json FROM proactive_inbox_items i
32
40
  JOIN proactive_insights x ON x.insight_id = i.insight_id`;
33
41
  function projectInsightsToInbox(now = /* @__PURE__ */ new Date()) {
34
42
  return runSqliteWriteTransaction((db) => {
35
- const missing = db.prepare(`SELECT x.insight_id FROM proactive_insights x
43
+ const missing = db.prepare(`SELECT x.insight_id, x.confidence, x.value_score, x.decision_json,
44
+ x.proposed_action_json, b.aggregation_key, p.project_id, p.mode, p.quiet_hours_json,
45
+ p.allowed_actions_json, p.confidence_threshold FROM proactive_insights x
36
46
  JOIN proactive_runs r ON r.run_id = x.run_id
37
47
  JOIN proactive_signal_batches b ON b.batch_id = r.batch_id
38
48
  LEFT JOIN project_monitoring_policies p
39
49
  ON b.aggregation_key = 'project:' || p.project_id
40
- WHERE x.insight_id NOT IN (SELECT insight_id FROM proactive_inbox_items)
41
- AND (p.project_id IS NULL OR (p.mode != 'observe' AND x.confidence >= p.confidence_threshold))
42
- ORDER BY x.created_at`).all();
50
+ WHERE x.disposition IS NULL ORDER BY x.created_at`).all();
51
+ let projected = 0;
43
52
  for (const row of missing) {
44
- const id = randomUUID();
53
+ const aggregationKey = String(row.aggregation_key);
54
+ const projectId = aggregationKey.startsWith("project:") ? aggregationKey.slice(8) : void 0;
55
+ const policy = projectId ? row.project_id ? {
56
+ projectId,
57
+ mode: String(row.mode),
58
+ ...row.quiet_hours_json ? { quietHours: JSON.parse(String(row.quiet_hours_json)) } : {},
59
+ allowedActions: JSON.parse(String(row.allowed_actions_json)),
60
+ confidenceThreshold: Number(row.confidence_threshold),
61
+ scenarios: [],
62
+ configured: true
63
+ } : {
64
+ projectId,
65
+ mode: "observe",
66
+ allowedActions: [],
67
+ confidenceThreshold: .75,
68
+ scenarios: [],
69
+ configured: false
70
+ } : {
71
+ projectId: "",
72
+ mode: "ask_before_action",
73
+ allowedActions: [],
74
+ confidenceThreshold: 0,
75
+ scenarios: [],
76
+ configured: false
77
+ };
78
+ const action = row.proposed_action_json ? JSON.parse(String(row.proposed_action_json)) : void 0;
79
+ const dispositionInput = {
80
+ confidence: Number(row.confidence),
81
+ valueScore: Number(row.value_score),
82
+ risk: action?.risk ?? "low",
83
+ ...action ? { actionId: action.id } : {},
84
+ requiresApproval: !action && Boolean(row.decision_json)
85
+ };
86
+ const disposition = action && !projectId ? "show_in_work" : decideProactiveDisposition(policy, dispositionInput);
87
+ const reason = action && !projectId ? "Proposed project action cannot run outside a project scope" : proactiveDispositionReason(policy, dispositionInput, disposition);
88
+ const actionStatus = action ? disposition === "auto_execute" ? "pending" : disposition === "request_approval" ? "approval_required" : disposition === "show_in_work" ? "not_authorized" : null : null;
45
89
  const nowIso = now.toISOString();
90
+ db.prepare(`UPDATE proactive_insights SET disposition = ?, disposition_reason = ?, action_status = ?,
91
+ disposition_at = ?, action_updated_at = ? WHERE insight_id = ? AND disposition IS NULL`).run(disposition, reason, actionStatus, nowIso, actionStatus ? nowIso : null, String(row.insight_id));
92
+ if (disposition === "record_silently") continue;
93
+ const id = randomUUID();
46
94
  db.prepare(`INSERT INTO proactive_inbox_items (inbox_item_id, insight_id, status, created_at, updated_at)
47
- VALUES (?, ?, 'unread', ?, ?)`).run(id, row.insight_id, nowIso, nowIso);
95
+ VALUES (?, ?, 'unread', ?, ?)`).run(id, String(row.insight_id), nowIso, nowIso);
96
+ const nextAttemptAt = nextQuietHoursEnd(policy.quietHours, now)?.toISOString() ?? nowIso;
48
97
  db.prepare(`INSERT INTO proactive_delivery_outbox (delivery_id, inbox_item_id, status, attempt, next_attempt_at, created_at, updated_at)
49
- VALUES (?, ?, 'pending', 0, ?, ?, ?)`).run(randomUUID(), id, nowIso, nowIso, nowIso);
98
+ VALUES (?, ?, 'pending', 0, ?, ?, ?)`).run(randomUUID(), id, nextAttemptAt, nowIso, nowIso);
99
+ projected += 1;
50
100
  }
51
- return missing.length;
101
+ return projected;
52
102
  });
53
103
  }
54
104
  function wakeSnoozedItems(now = /* @__PURE__ */ new Date()) {
@@ -1,11 +1,11 @@
1
- import { listInbox, projectInsightsToInbox, recordDecision, recordFeedback, wakeSnoozedItems } from './repository.js';
1
+ import { listInbox, projectInsightsToInbox, recordFeedback, wakeSnoozedItems } from './repository.js';
2
2
  import type { InboxStatus } from './types.js';
3
3
  export declare class ProactiveInboxService {
4
4
  list: typeof listInbox;
5
5
  project: typeof projectInsightsToInbox;
6
6
  wakeSnoozed: typeof wakeSnoozedItems;
7
- decide: typeof recordDecision;
8
7
  feedback: typeof recordFeedback;
8
+ decide(id: string, choice: string, note?: string): import("./types.js").InboxItem;
9
9
  instruct(id: string, instruction: string): {
10
10
  revisionId: string;
11
11
  };
@@ -1,12 +1,17 @@
1
1
  import { publishInstructionFeedback } from "../scenarios/repository.js";
2
- import { getInboxSubscriptionId, listInbox, projectInsightsToInbox, recordDecision, recordFeedback, transitionInboxItem, wakeSnoozedItems } from "./repository.js";
2
+ import { resolveProactiveActionDecision } from "../actions/service.js";
3
+ import { getInboxItem, getInboxSubscriptionId, listInbox, projectInsightsToInbox, recordDecision, recordFeedback, transitionInboxItem, wakeSnoozedItems } from "./repository.js";
3
4
  //#region src/proactive/inbox/service.ts
4
5
  var ProactiveInboxService = class {
5
6
  list = listInbox;
6
7
  project = projectInsightsToInbox;
7
8
  wakeSnoozed = wakeSnoozedItems;
8
- decide = recordDecision;
9
9
  feedback = recordFeedback;
10
+ decide(id, choice, note = "") {
11
+ const item = recordDecision(id, choice, note);
12
+ resolveProactiveActionDecision(id, choice);
13
+ return getInboxItem(id) ?? item;
14
+ }
10
15
  instruct(id, instruction) {
11
16
  return { revisionId: publishInstructionFeedback({
12
17
  subscriptionId: getInboxSubscriptionId(id),
@@ -23,6 +23,20 @@ export interface InboxItem {
23
23
  consequence: string;
24
24
  }>;
25
25
  };
26
+ proposedAction?: {
27
+ id: 'create_project_task';
28
+ risk: 'low';
29
+ rationale: string;
30
+ input: {
31
+ title: string;
32
+ objective: string;
33
+ };
34
+ };
35
+ disposition: 'show_in_work' | 'request_approval' | 'auto_execute';
36
+ dispositionReason: string;
37
+ actionStatus?: 'not_authorized' | 'approval_required' | 'pending' | 'executing' | 'completed' | 'rejected' | 'failed';
38
+ actionResult?: Record<string, unknown>;
39
+ actionError?: string;
26
40
  urgency: 'low' | 'medium' | 'high' | 'critical';
27
41
  confidence: number;
28
42
  valueScore: number;
@@ -1,5 +1,6 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { executePendingProactiveActions } from "../actions/service.js";
3
4
  import { claimDelivery, finishDelivery, projectInsightsToInbox, recoverExpiredDeliveries, wakeSnoozedItems } from "./repository.js";
4
5
  //#region src/proactive/inbox/worker.ts
5
6
  init_logger();
@@ -28,6 +29,7 @@ var ProactiveInboxWorker = class {
28
29
  this.running = true;
29
30
  try {
30
31
  projectInsightsToInbox();
32
+ executePendingProactiveActions();
31
33
  wakeSnoozedItems();
32
34
  recoverExpiredDeliveries();
33
35
  const claim = claimDelivery();
@@ -5,8 +5,8 @@ Use only supplied evidence identifiers. Separate observations from inferences.
5
5
  Do not invent dates, owners, dependencies, impact, or actions.
6
6
  Return only the protected output schema.`;
7
7
  const OUTPUT_CONTRACT = `Return JSON only with these fields:
8
- {"title":"...","summary":"...","whyNow":"...","impact":"...","workDone":"What you investigated or ruled out","recommendation":"...","decision":{"question":"The exact user decision","options":[{"id":"stable-id","label":"short choice","consequence":"likely consequence"}]},"urgency":"low|medium|high|critical","confidence":0.0,"evidenceIds":["event-id"]}
9
- Use decision only when the user must choose; otherwise set decision to null. Provide 2-3 mutually exclusive options. If evidence does not support a timely and actionable insight, return the same shape with urgency "low" and confidence below 0.65. Never add unknown fields.`;
8
+ {"title":"...","summary":"...","whyNow":"...","impact":"...","workDone":"What you investigated or ruled out","recommendation":"...","decision":{"question":"The exact user decision","options":[{"id":"stable-id","label":"short choice","consequence":"likely consequence"}]},"proposedAction":{"id":"create_project_task","risk":"low","rationale":"why this is safe and useful","input":{"title":"...","objective":"..."}},"urgency":"low|medium|high|critical","confidence":0.0,"evidenceIds":["event-id"]}
9
+ Use proposedAction only when the evidence clearly supports creating a follow-up task in the current project; otherwise set it to null. A proposed action must include exactly two decision options in this order: approve, reject. Use decision without proposedAction only when the user must choose; otherwise set decision to null. Provide 2-3 mutually exclusive options. If evidence does not support a timely and actionable insight, return the same shape with urgency "low" and confidence below 0.65. Never add unknown fields.`;
10
10
  function composeScenarioPrompt(input) {
11
11
  const parts = {
12
12
  platformSafety: PLATFORM_SAFETY,
@@ -14,7 +14,6 @@ export type RawSessionConversationRef = {
14
14
  };
15
15
  /** Parse `agent:{agentId}:{rest}` session keys (OpenClaw canonical form). */
16
16
  export declare function parseAgentSessionKey(sessionKey: string | undefined | null): ParsedAgentSessionKey | null;
17
- export declare function isCronRunSessionKey(sessionKey: string | undefined | null): boolean;
18
17
  export declare function isCronSessionKey(sessionKey: string | undefined | null): boolean;
19
18
  export declare function isSubagentSessionKey(sessionKey: string | undefined | null): boolean;
20
19
  export declare function getSubagentDepth(sessionKey: string | undefined | null): number;
@@ -16,11 +16,6 @@ function parseAgentSessionKey(sessionKey) {
16
16
  rest
17
17
  };
18
18
  }
19
- function isCronRunSessionKey(sessionKey) {
20
- const parsed = parseAgentSessionKey(sessionKey);
21
- if (!parsed) return false;
22
- return /^cron:[^:]+:run:[^:]+$/.test(parsed.rest);
23
- }
24
19
  function isCronSessionKey(sessionKey) {
25
20
  const parsed = parseAgentSessionKey(sessionKey);
26
21
  if (!parsed) return false;
@@ -87,4 +82,4 @@ var init_session_key_utils = __esmMin((() => {
87
82
  }));
88
83
  //#endregion
89
84
  init_session_key_utils();
90
- export { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey };
85
+ export { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey };
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
2
  import { DEFAULT_ACCOUNT_ID, normalizeAccountId, normalizeOptionalAccountId } from "./account-id.js";
3
- import { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey } from "./session-key-utils.js";
3
+ import { getSubagentDepth, init_session_key_utils, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseThreadSessionSuffix, resolveThreadParentSessionKey } from "./session-key-utils.js";
4
4
  import { DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, classifySessionKeyShape, defaultMainSessionKey, init_agent_session_key, isValidAgentId, normalizeAgentId, normalizeMainKey, normalizeSessionKey, resolveAgentIdFromSessionKey, resolveThreadSessionKeys, sanitizeAgentId, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey } from "./agent-session-key.js";
5
5
  //#region src/routing/session-key.ts
6
6
  function sanitizeSegment(value, options) {
@@ -188,4 +188,4 @@ var init_session_key = __esmMin((() => {
188
188
  }));
189
189
  //#endregion
190
190
  init_session_key();
191
- export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, buildSessionKey, buildSubagentSessionKey, classifySessionKeyShape, defaultMainSessionKey, getParentSessionKey, getSubagentDepth, init_session_key, isAcpSessionKey, isCronRunSessionKey, isCronSessionKey, isSubagentSessionKey, isValidAgentId, isValidSegment, normalizeAccountId, normalizeAgentId, normalizeMainKey, normalizeOptionalAccountId, normalizeSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseSessionKey, parseThreadSessionSuffix, resolveAgentIdFromSessionKey, resolveThreadParentSessionKey, resolveThreadSessionKeys, sanitizeAgentId, sanitizeSegment, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey };
191
+ export { DEFAULT_ACCOUNT_ID, DEFAULT_AGENT_ID, DEFAULT_MAIN_KEY, assertAgentSessionKey, buildAgentMainSessionKey, buildAgentPeerSessionKey, buildGroupHistoryKey, buildSessionKey, buildSubagentSessionKey, classifySessionKeyShape, defaultMainSessionKey, getParentSessionKey, getSubagentDepth, init_session_key, isAcpSessionKey, isCronSessionKey, isSubagentSessionKey, isValidAgentId, isValidSegment, normalizeAccountId, normalizeAgentId, normalizeMainKey, normalizeOptionalAccountId, normalizeSessionKey, parseAgentSessionKey, parseRawSessionConversationRef, parseSessionKey, parseThreadSessionSuffix, resolveAgentIdFromSessionKey, resolveThreadParentSessionKey, resolveThreadSessionKeys, sanitizeAgentId, sanitizeSegment, scopedHeartbeatWakeOptions, toAgentRequestSessionKey, toAgentStoreSessionKey };
@@ -0,0 +1,6 @@
1
+ ALTER TABLE tasks ADD COLUMN board_rank INTEGER NOT NULL DEFAULT 0;
2
+
3
+ UPDATE tasks SET board_rank = created_at;
4
+
5
+ CREATE INDEX idx_tasks_project_phase_rank
6
+ ON tasks(project_id, phase, board_rank, created_at);
@@ -0,0 +1,13 @@
1
+ ALTER TABLE proactive_insights ADD COLUMN proposed_action_json TEXT;
2
+ ALTER TABLE proactive_insights ADD COLUMN disposition TEXT
3
+ CHECK (disposition IN ('record_silently', 'show_in_work', 'request_approval', 'auto_execute'));
4
+ ALTER TABLE proactive_insights ADD COLUMN disposition_reason TEXT;
5
+ ALTER TABLE proactive_insights ADD COLUMN action_status TEXT
6
+ CHECK (action_status IN ('not_authorized', 'approval_required', 'pending', 'executing', 'completed', 'rejected', 'failed'));
7
+ ALTER TABLE proactive_insights ADD COLUMN action_result_json TEXT;
8
+ ALTER TABLE proactive_insights ADD COLUMN action_error TEXT;
9
+ ALTER TABLE proactive_insights ADD COLUMN disposition_at TEXT;
10
+ ALTER TABLE proactive_insights ADD COLUMN action_updated_at TEXT;
11
+
12
+ CREATE INDEX idx_proactive_insights_action_status
13
+ ON proactive_insights(action_status, created_at);
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 117;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 119;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -12,7 +12,7 @@ const log = createLogger("Sqlite:Migrations");
12
12
  /** Baseline schema version applied from schema.sql on first open. */
13
13
  const XOPC_DB_BASELINE_SCHEMA_VERSION = 11;
14
14
  /** Latest schema version this release supports (increment when adding migrations). */
15
- const XOPC_DB_SCHEMA_VERSION = 117;
15
+ const XOPC_DB_SCHEMA_VERSION = 119;
16
16
  const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
17
17
  function backupBeforeTaskCutover(db, databasePath) {
18
18
  db.exec("PRAGMA wal_checkpoint(FULL)");
@@ -57,7 +57,7 @@ function applySingleMigration(db, migration) {
57
57
  * Each step runs in its own transaction and updates schema_meta on success.
58
58
  */
59
59
  function applyPendingMigrations(db, options = {}) {
60
- const targetVersion = options.targetVersion ?? 117;
60
+ const targetVersion = options.targetVersion ?? 119;
61
61
  let currentVersion = readSchemaVersion(db);
62
62
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
63
63
  if (currentVersion >= targetVersion) return currentVersion;
@@ -94,7 +94,7 @@ function applyPendingMigrations(db, options = {}) {
94
94
  }
95
95
  /** Inspect schema version without mutating the database. */
96
96
  function inspectSchemaMigrationStatus(db, options = {}) {
97
- const appVersion = options.targetVersion ?? 117;
97
+ const appVersion = options.targetVersion ?? 119;
98
98
  const dbVersion = readSchemaVersion(db);
99
99
  if (dbVersion > appVersion) return {
100
100
  dbVersion,