@xopcai/xopc 0.0.269 → 0.0.272

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 (293) hide show
  1. package/dist/browser-ext/dist/assets/{auth-cwEj8rFb.js → auth-C1QI-uMG.js} +65 -14
  2. package/dist/browser-ext/dist/background.js +23 -2
  3. package/dist/browser-ext/dist/pairing-handoff.js +51 -0
  4. package/dist/browser-ext/dist/sidepanel.html +1 -1
  5. package/dist/browser-ext/dist/sidepanel.js +39 -27
  6. package/dist/browser-ext/manifest.json +12 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/gateway/static/root/assets/{activity-store-DcwCSY6s.js → activity-store-DffqjeqQ.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D0NBOWC4.js → agent-avatar-dicebear-Cwj4HCYY.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-6CLfLxVc.js +1 -0
  11. package/dist/gateway/static/root/assets/agents-B6mu64fY.js +1 -0
  12. package/dist/gateway/static/root/assets/{api-eaPO-mdr.js → api-CGLdye4i.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-E3xm2teY.js → app-management-settings-panel-BLujSbaw.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-CiZOjgls.js → appearance-settings-BXMcueb8.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-BEgy4hY3.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-D09yo_Hc.js → archive-plugin-D4bUampf.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-CNYb8Qru.js → attachment-load-CBGNA2Ys.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-DsrfW5ii.js → automations-page-dQyolNmy.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-DxRFrmrV.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-OWlaGqlY.js → binary-plugins-bbvp81h2.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-CVND3M6r.js → block-editor-C8e6Wri4.js} +3 -3
  22. package/dist/gateway/static/root/assets/{browser-automation-inputs-D7IzVK_J.js → browser-automation-inputs-oJWJtQa6.js} +1 -1
  23. package/dist/gateway/static/root/assets/{browser-automations-page-CQ6cCpIv.js → browser-automations-page-CAcJQSjN.js} +2 -2
  24. package/dist/gateway/static/root/assets/browser-settings-page-TLAlqcPo.js +8 -0
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-z-K_jrZz.js +8 -0
  26. package/dist/gateway/static/root/assets/channels-settings-Dzrk33aB.js +1 -0
  27. package/dist/gateway/static/root/assets/{channels-status-swr-D4JrgJKa.js → channels-status-swr-CfOPNnVr.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-BUjnhT7C.js → chat-terminal-dock-9ZOl92kh.js} +2 -2
  29. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
  30. package/dist/gateway/static/root/assets/connectors-page-B1dIoRNi.js +2 -0
  31. package/dist/gateway/static/root/assets/cron-expression-C26e13YU.js +2 -0
  32. package/dist/gateway/static/root/assets/date-picker-Dj6FRLF9.js +1 -0
  33. package/dist/gateway/static/root/assets/{dependency-picker-Z6Nf0Wjq.js → dependency-picker-D1q89tVc.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-C0F5Iqnc.js → desktop-pet-DfqZBvhp.js} +1 -1
  35. package/dist/gateway/static/root/assets/{desktop-pet-settings-Bj_W6HL1.js → desktop-pet-settings-HCEh2MOm.js} +1 -1
  36. package/dist/gateway/static/root/assets/device-pairing-wizard-CPth92s6.js +1 -0
  37. package/dist/gateway/static/root/assets/{extension-debug-page-Ba09EnAn.js → extension-debug-page-C8cAWVoK.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-C88aGXJs.js → extension-page-5N87Vaym.js} +1 -1
  39. package/dist/gateway/static/root/assets/extension-settings-page-D85SAUFP.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-bjzk_4hn.js → gateway-config-swr-BjsDnB_n.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-Dqx8PmcT.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-DrbIzFyB.js → gateway-startup-retry-BIf0eLWX.js} +1 -1
  43. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
  44. package/dist/gateway/static/root/assets/heartbeat-settings-BpDWGE1a.js +1 -0
  45. package/dist/gateway/static/root/assets/home-page-DJaqpC8-.js +1 -0
  46. package/dist/gateway/static/root/assets/{image-generation-api-CBWU9Ner.js → image-generation-api-1m8xTVS_.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-C6PmD0cK.js +74 -0
  48. package/dist/gateway/static/root/assets/index-DKy1Qn1_.css +2 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B8Z7kKQY.js → keyboard-shortcuts-settings-Byy8mCSq.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-l2AEiG2C.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-CLSfzkRp.js → local-apps-page-BPo0wBgM.js} +1 -1
  52. package/dist/gateway/static/root/assets/locale-store-CRNble2Z.js +1 -0
  53. package/dist/gateway/static/root/assets/logs-page-X5FdLlXK.js +2 -0
  54. package/dist/gateway/static/root/assets/management-settings-DT6NoIjm.js +1 -0
  55. package/dist/gateway/static/root/assets/{markdown-view-DIcfrLmG.js → markdown-view-AglreSOj.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-CSv6-xTA.js → media-plugins-Bzka9qXu.js} +1 -1
  57. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
  58. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
  59. package/dist/gateway/static/root/assets/{messages-BRjoarIr.js → messages-DH_HCgmw.js} +3 -3
  60. package/dist/gateway/static/root/assets/note-detail-panel-BUJPoaGZ.js +5 -0
  61. package/dist/gateway/static/root/assets/notes-page-BwFpWRuo.js +8 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-BfV-PQa5.js → page-tabs-Ys0p65Lt.js} +1 -1
  63. package/dist/gateway/static/root/assets/popover-select-Dz_Qis2R.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-DQS7NFpg.js → preview-open-alternatives-iknB5xEp.js} +1 -1
  65. package/dist/gateway/static/root/assets/proactive-card-BPZDgNNR.js +1 -0
  66. package/dist/gateway/static/root/assets/proactive-page-CxdZR-p2.js +1 -0
  67. package/dist/gateway/static/root/assets/{product-open-page-BIhjZLKg.js → product-open-page-W1o3f-kz.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-BU1RKAcy.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-z0X0tL8G.js +1 -0
  70. package/dist/gateway/static/root/assets/{registry-api-CwveUfe8.js → registry-api-DmYFpjsH.js} +1 -1
  71. package/dist/gateway/static/root/assets/remote-access-hub-NNTut2I8.js +1 -0
  72. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DMQ0wpNg.js → runtime-tools-settings-panel-DP1XyYO8.js} +1 -1
  73. package/dist/gateway/static/root/assets/{schema-form-C91g2PRU.js → schema-form-BMYKdzsH.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-B6SsHlz5.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-BQu8bAcN.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-Cem6L49Y.js → settings-form-section-2LGjz7bu.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-afDUxqlV.js → settings-page-7DjpC9_C.js} +1 -1
  78. package/dist/gateway/static/root/assets/setup-status-panel-Dj9jFWJt.js +1 -0
  79. package/dist/gateway/static/root/assets/{share-preview-page-CVEVHksg.js → share-preview-page-BxYdSi8c.js} +1 -1
  80. package/dist/gateway/static/root/assets/shares-settings-CMqE0KuK.js +1 -0
  81. package/dist/gateway/static/root/assets/skill-reload-api-BXqSJymN.js +1 -0
  82. package/dist/gateway/static/root/assets/{skills-page-CNrq1W6C.js → skills-page-DNEScMZH.js} +1 -1
  83. package/dist/gateway/static/root/assets/skills-page.utils-q88l65YU.js +1 -0
  84. package/dist/gateway/static/root/assets/{system-settings-panel-BLE8PxWE.js → system-settings-panel-8NIssGKj.js} +1 -1
  85. package/dist/gateway/static/root/assets/task-detail-page-L6dp9v2y.js +1 -0
  86. package/dist/gateway/static/root/assets/{theme-store-BejLVjIT.js → theme-store-BXZG3S25.js} +1 -1
  87. package/dist/gateway/static/root/assets/tunnel-api-CWsRPM84.js +1 -0
  88. package/dist/gateway/static/root/assets/{use-autosave-DmgEA8Qb.js → use-autosave-BwQuoTQU.js} +1 -1
  89. package/dist/gateway/static/root/assets/user-model-page-D4BucMrZ.js +2 -0
  90. package/dist/gateway/static/root/assets/{voice-api-key-field-sZ0J83SF.js → voice-api-key-field-Bd03Ic0s.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-config-api-BEbz3avx.js → voice-config-api-gggUp3u9.js} +1 -1
  92. package/dist/gateway/static/root/assets/{work-discovery-overlay-BXnAlbmO.js → work-discovery-overlay-DF8PR_pK.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BkwFey0a.js → workflow-run-setup-panel-BiAAWlir.js} +2 -2
  94. package/dist/gateway/static/root/assets/workflows-page-DryKUMfA.js +6 -0
  95. package/dist/gateway/static/root/index.html +15 -11
  96. package/dist/package.js +1 -1
  97. package/dist/packages/gateway-contract/src/device-pairing.js +2 -1
  98. package/dist/packages/gateway-contract/src/notifications.js +2 -2
  99. package/dist/packages/gateway-contract/src/proactive.js +22 -6
  100. package/dist/packages/gateway-contract/src/session-identity.js +37 -0
  101. package/dist/src/agent/memory/compaction-chunks.d.ts +18 -0
  102. package/dist/src/agent/memory/compaction-chunks.js +53 -0
  103. package/dist/src/agent/memory/compaction-request.d.ts +12 -0
  104. package/dist/src/agent/memory/compaction-request.js +72 -0
  105. package/dist/src/agent/memory/compaction.d.ts +3 -0
  106. package/dist/src/agent/memory/compaction.js +166 -118
  107. package/dist/src/agent/service.js +1 -0
  108. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  109. package/dist/src/agent/tool-manuals/xopc-use.js +19 -1
  110. package/dist/src/agent/tools/factory.js +1 -0
  111. package/dist/src/agent/tools/xopc-use-tool.d.ts +3 -2
  112. package/dist/src/agent/tools/xopc-use-tool.js +48 -4
  113. package/dist/src/browser/automations/schema.d.ts +1 -1
  114. package/dist/src/browser/automations/service.d.ts +1 -1
  115. package/dist/src/browser/native-messaging-host.js +3 -1
  116. package/dist/src/cli/commands/connectors.js +1 -1
  117. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  118. package/dist/src/cli/commands/tunnel.js +5 -0
  119. package/dist/src/connectors/connected-source-ingestion.js +1 -1
  120. package/dist/src/connectors/connected-source-normalizers.js +3 -0
  121. package/dist/src/connectors/connection-recovery-service.js +1 -1
  122. package/dist/src/connectors/health.js +1 -1
  123. package/dist/src/gateway/heartbeat/service.js +1 -1
  124. package/dist/src/gateway/hono/app.js +1 -0
  125. package/dist/src/gateway/hono/middleware/auth.d.ts +1 -2
  126. package/dist/src/gateway/hono/middleware/auth.js +49 -31
  127. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +11 -15
  128. package/dist/src/gateway/hono/routes/browser-session.d.ts +3 -0
  129. package/dist/src/gateway/hono/routes/browser-session.js +43 -0
  130. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  131. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  132. package/dist/src/gateway/hono/routes/devices.js +61 -96
  133. package/dist/src/gateway/hono/routes/exposure.js +3 -7
  134. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  135. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  136. package/dist/src/gateway/hono/routes/models.js +60 -1
  137. package/dist/src/gateway/hono/routes/notes.js +3 -7
  138. package/dist/src/gateway/hono/routes/proactive-control.js +31 -24
  139. package/dist/src/gateway/hono/routes/sessions.js +11 -0
  140. package/dist/src/gateway/hono/routes/shares.js +8 -20
  141. package/dist/src/gateway/hono/routes/site-shares.js +4 -8
  142. package/dist/src/gateway/hono/routes/tunnel.js +13 -13
  143. package/dist/src/gateway/image-generation-setup.d.ts +17 -0
  144. package/dist/src/gateway/image-generation-setup.js +30 -21
  145. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  146. package/dist/src/gateway/rate-limit/buckets.js +10 -0
  147. package/dist/src/gateway/runtime-config.js +2 -0
  148. package/dist/src/gateway/security/browser-session.d.ts +5 -0
  149. package/dist/src/gateway/security/browser-session.js +45 -0
  150. package/dist/src/gateway/security/gateway-principal.d.ts +1 -0
  151. package/dist/src/gateway/service.d.ts +1 -0
  152. package/dist/src/gateway/service.js +21 -11
  153. package/dist/src/heartbeat/index.js +1 -1
  154. package/dist/src/infra/rate-limit/keyed-store.d.ts +3 -0
  155. package/dist/src/infra/rate-limit/keyed-store.js +9 -2
  156. package/dist/src/notifications/web-push.js +1 -1
  157. package/dist/src/proactive/actions/service.js +4 -2
  158. package/dist/src/proactive/execution/authorization.d.ts +2 -0
  159. package/dist/src/proactive/execution/authorization.js +39 -1
  160. package/dist/src/proactive/execution/context.d.ts +4 -0
  161. package/dist/src/proactive/execution/context.js +51 -5
  162. package/dist/src/proactive/execution/insight.js +3 -1
  163. package/dist/src/proactive/execution/repository.js +15 -5
  164. package/dist/src/proactive/execution/types.d.ts +2 -0
  165. package/dist/src/proactive/execution/worker.js +7 -2
  166. package/dist/src/proactive/experience.d.ts +69 -0
  167. package/dist/src/proactive/experience.js +90 -0
  168. package/dist/src/proactive/follow-ups.d.ts +123 -0
  169. package/dist/src/proactive/follow-ups.js +169 -0
  170. package/dist/src/proactive/inbox/cards.js +35 -6
  171. package/dist/src/proactive/inbox/delivery.js +4 -2
  172. package/dist/src/proactive/inbox/digest.js +2 -2
  173. package/dist/src/proactive/inbox/lifecycle.js +4 -1
  174. package/dist/src/proactive/inbox/notification-policy.js +4 -2
  175. package/dist/src/proactive/inbox/repository.js +17 -11
  176. package/dist/src/proactive/inbox/types.d.ts +2 -0
  177. package/dist/src/proactive/inbox/worker.js +1 -1
  178. package/dist/src/proactive/index.js +2 -2
  179. package/dist/src/proactive/mail-thread.d.ts +13 -0
  180. package/dist/src/proactive/mail-thread.js +54 -0
  181. package/dist/src/proactive/policy/service.d.ts +3 -5
  182. package/dist/src/proactive/policy/service.js +3 -5
  183. package/dist/src/proactive/scenarios/control.d.ts +4 -7
  184. package/dist/src/proactive/scenarios/control.js +3 -4
  185. package/dist/src/proactive/scenarios/preview.js +1 -1
  186. package/dist/src/proactive/scenarios/prompt-composer.js +2 -0
  187. package/dist/src/proactive/service.js +1 -1
  188. package/dist/src/proactive/temporal/worker.d.ts +1 -0
  189. package/dist/src/proactive/temporal/worker.js +18 -4
  190. package/dist/src/realtime/runtime.d.ts +2 -1
  191. package/dist/src/realtime/runtime.js +9 -3
  192. package/dist/src/realtime/tickets.d.ts +1 -0
  193. package/dist/src/realtime/tickets.js +3 -0
  194. package/dist/src/session/store.d.ts +2 -0
  195. package/dist/src/session/store.js +17 -2
  196. package/dist/src/session/types.d.ts +2 -1
  197. package/dist/src/storage/sqlite/browser-session-repository.d.ts +17 -0
  198. package/dist/src/storage/sqlite/browser-session-repository.js +54 -0
  199. package/dist/src/storage/sqlite/device-pairing-approval.js +2 -1
  200. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +4 -10
  201. package/dist/src/storage/sqlite/device-pairing-repository.js +10 -62
  202. package/dist/src/storage/sqlite/index.d.ts +1 -1
  203. package/dist/src/storage/sqlite/index.js +2 -2
  204. package/dist/src/storage/sqlite/migrations/162_proactive_product.sql +7 -0
  205. package/dist/src/storage/sqlite/migrations/163_proactive_follow_ups.sql +29 -0
  206. package/dist/src/storage/sqlite/migrations/164_browser_sessions.sql +8 -0
  207. package/dist/src/storage/sqlite/migrations/165_device_pairing_target.sql +40 -0
  208. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  209. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  210. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  211. package/dist/src/storage/sqlite/schema.js +1 -1
  212. package/dist/src/storage/sqlite/session-identity-sql.d.ts +2 -0
  213. package/dist/src/storage/sqlite/session-identity-sql.js +18 -0
  214. package/dist/src/storage/sqlite/session-repository.js +26 -22
  215. package/dist/src/tasks/home-query-service.js +1 -1
  216. package/dist/src/tasks/index.js +4 -4
  217. package/dist/src/tui/tui-startup-resources.js +1 -1
  218. package/dist/src/tunnel/auth-policy.d.ts +3 -0
  219. package/dist/src/tunnel/auth-policy.js +8 -0
  220. package/dist/src/tunnel/broker-client.d.ts +5 -15
  221. package/dist/src/tunnel/broker-client.js +37 -49
  222. package/dist/src/tunnel/frpc-binary.d.ts +8 -6
  223. package/dist/src/tunnel/frpc-binary.js +76 -88
  224. package/dist/src/tunnel/frpc-config.d.ts +2 -1
  225. package/dist/src/tunnel/frpc-config.js +29 -12
  226. package/dist/src/tunnel/frpc-release.d.ts +27 -0
  227. package/dist/src/tunnel/frpc-release.js +30 -0
  228. package/dist/src/tunnel/gateway-lifecycle.js +8 -2
  229. package/dist/src/tunnel/index.js +2 -1
  230. package/dist/src/tunnel/registration-proof.d.ts +19 -0
  231. package/dist/src/tunnel/registration-proof.js +37 -0
  232. package/dist/src/tunnel/tunnel-persist.js +3 -1
  233. package/dist/src/tunnel/tunnel-service.d.ts +1 -0
  234. package/dist/src/tunnel/tunnel-service.js +35 -8
  235. package/dist/src/tunnel/tunnel-state.js +11 -5
  236. package/dist/src/tunnel/tunnel-types.d.ts +2 -0
  237. package/dist/src/tunnel/well-known.js +5 -1
  238. package/dist/src/user-context/config.js +2 -2
  239. package/dist/src/utils/logger/redact.js +4 -0
  240. package/dist/src/voice/dashscope/streaming-stt-session.js +1 -0
  241. package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +1 -0
  242. package/dist/src/voice/dashscope/streaming-tts-stream.js +8 -0
  243. package/dist/src/voice/realtime/agentBroker.js +1 -1
  244. package/dist/src/voice/realtime/agentEngine.js +1 -1
  245. package/dist/src/voice/realtime/pcm-output-gain.d.ts +2 -0
  246. package/dist/src/voice/realtime/pcm-output-gain.js +16 -0
  247. package/dist/src/voice/realtime/runtime.d.ts +1 -0
  248. package/dist/src/voice/realtime/runtime.js +21 -3
  249. package/dist/src/voice/realtime/runtime.types.d.ts +1 -0
  250. package/dist/src/workflows/service/workflow-run-service.js +3 -1
  251. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  252. package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
  253. package/package.json +4 -4
  254. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-qKCezlBg.js +0 -1
  255. package/dist/gateway/static/root/assets/agents-BMhnZKhP.js +0 -1
  256. package/dist/gateway/static/root/assets/apps-page-DduJDWGY.js +0 -1
  257. package/dist/gateway/static/root/assets/automations-workspace-X7hNHCjW.js +0 -6
  258. package/dist/gateway/static/root/assets/browser-settings-page-BZ7nK_pN.js +0 -8
  259. package/dist/gateway/static/root/assets/capabilities-settings-panel-BfKvJO1C.js +0 -7
  260. package/dist/gateway/static/root/assets/channels-settings-D1UDxJuA.js +0 -1
  261. package/dist/gateway/static/root/assets/connectors-page-C2nuqs_O.js +0 -2
  262. package/dist/gateway/static/root/assets/cron-expression-DlyRIyUn.js +0 -2
  263. package/dist/gateway/static/root/assets/date-picker-CU-ij_yE.js +0 -1
  264. package/dist/gateway/static/root/assets/extension-settings-page-CMyt0A32.js +0 -1
  265. package/dist/gateway/static/root/assets/gateway-settings-ogv8ZbvG.js +0 -1
  266. package/dist/gateway/static/root/assets/heartbeat-settings-BnrMRKaZ.js +0 -1
  267. package/dist/gateway/static/root/assets/home-page-CbcJCREd.js +0 -1
  268. package/dist/gateway/static/root/assets/index-7PZ6jmhy.css +0 -2
  269. package/dist/gateway/static/root/assets/index-CfyyA9-g.js +0 -74
  270. package/dist/gateway/static/root/assets/local-app-workbench-page-D5XVZnK1.js +0 -2
  271. package/dist/gateway/static/root/assets/locale-store-BQ2HKTWb.js +0 -1
  272. package/dist/gateway/static/root/assets/logs-page-CWDU1AGN.js +0 -2
  273. package/dist/gateway/static/root/assets/management-settings-CuFNgQUy.js +0 -1
  274. package/dist/gateway/static/root/assets/mobile-pairing-wizard-C7d_ztgp.js +0 -1
  275. package/dist/gateway/static/root/assets/note-detail-panel-D5JuBLyt.js +0 -5
  276. package/dist/gateway/static/root/assets/notes-page-C5-ccCi4.js +0 -8
  277. package/dist/gateway/static/root/assets/popover-select-CKBYnT3c.js +0 -1
  278. package/dist/gateway/static/root/assets/proactive-page-fHjPigmx.js +0 -1
  279. package/dist/gateway/static/root/assets/project-detail-page-6v_khvEt.js +0 -1
  280. package/dist/gateway/static/root/assets/projects-page-CCy1aK4V.js +0 -1
  281. package/dist/gateway/static/root/assets/remote-access-hub-pkqKRnch.js +0 -1
  282. package/dist/gateway/static/root/assets/sessions-page-Cr4E4cap.js +0 -1
  283. package/dist/gateway/static/root/assets/settings-advanced-gate-D1JRDRyL.js +0 -1
  284. package/dist/gateway/static/root/assets/setup-status-panel-Cc_iP_vv.js +0 -1
  285. package/dist/gateway/static/root/assets/shares-settings-BrMECMAB.js +0 -1
  286. package/dist/gateway/static/root/assets/skill-reload-api-DuqIDYjc.js +0 -1
  287. package/dist/gateway/static/root/assets/skills-page.utils-D1wGfm22.js +0 -1
  288. package/dist/gateway/static/root/assets/task-detail-page-m0oXUKl2.js +0 -1
  289. package/dist/gateway/static/root/assets/tunnel-api-Dur80zSQ.js +0 -1
  290. package/dist/gateway/static/root/assets/user-model-page-Dl10D_5q.js +0 -2
  291. package/dist/gateway/static/root/assets/workflows-page-CswgoIFU.js +0 -6
  292. package/dist/src/proactive/actions/workflow.d.ts +0 -15
  293. package/dist/src/proactive/actions/workflow.js +0 -88
@@ -1,8 +1,9 @@
1
1
  import { getSqliteDatabase } from "../../storage/sqlite/transaction.js";
2
2
  import { getAssertionSlot, listUserAssertions } from "../../user-model/repository.js";
3
3
  import "../../user-model/index.js";
4
- import { getDiscussionCapture, getLatestDiscussionOrganization } from "../../discussions/repository.js";
5
4
  import { authorizedConnectedSource } from "./authorization.js";
5
+ import { authorizedMailThread, requireMailFollowUp } from "../follow-ups.js";
6
+ import { getDiscussionCapture, getLatestDiscussionOrganization } from "../../discussions/repository.js";
6
7
  import { wrapExternalContent } from "../../gateway/security/external-content.js";
7
8
  //#region src/proactive/execution/context.ts
8
9
  const MAX_EVENT_COUNT = 50;
@@ -27,7 +28,12 @@ function emptyContext() {
27
28
  };
28
29
  }
29
30
  function authorizedConnectedSourceItem(event, scenarioKey) {
30
- return authorizedConnectedSource(event.subject_id, event.workspace_id, scenarioKey, event.agent_id);
31
+ const item = authorizedConnectedSource(event.subject_id, event.workspace_id, scenarioKey, event.agent_id);
32
+ if (item && event.type === "connected_source.calendar_window.v1") {
33
+ const payload = JSON.parse(event.payload_json);
34
+ if (payload.meetingStartsAt !== item.occurredAt || payload.contentHash && payload.contentHash !== item.contentHash) return null;
35
+ }
36
+ return item;
31
37
  }
32
38
  var EventBatchContextProvider = class {
33
39
  id = "event_batch";
@@ -53,11 +59,13 @@ var ConnectedSourceContextProvider = class {
53
59
  async collect(input) {
54
60
  const items = [];
55
61
  const snapshotItems = [];
62
+ const seen = /* @__PURE__ */ new Set();
56
63
  const evidenceIds = [];
57
64
  for (const event of eventRows(input.eventIds)) {
58
65
  if (!event.type.startsWith("connected_source.") || event.type.includes("_deleted.")) continue;
59
66
  const item = authorizedConnectedSourceItem(event, input.scenarioKey);
60
- if (!item) continue;
67
+ if (!item || seen.has(item.id)) continue;
68
+ seen.add(item.id);
61
69
  const evidenceId = `source-item:${item.id}`;
62
70
  const common = {
63
71
  evidenceId,
@@ -325,6 +333,43 @@ var DiscussionContextProvider = class {
325
333
  };
326
334
  }
327
335
  };
336
+ var MailFollowUpContextProvider = class {
337
+ id = "follow_up";
338
+ async collect(input) {
339
+ const event = eventRows(input.eventIds).findLast((row) => row.subject_kind === "mail_follow_up");
340
+ if (!event) return emptyContext();
341
+ const follow = requireMailFollowUp(event.workspace_id, event.subject_id);
342
+ const thread = authorizedMailThread(follow);
343
+ if (!thread || follow.status !== "watching") return emptyContext();
344
+ const common = {
345
+ followUpId: follow.id,
346
+ revision: follow.revision,
347
+ fingerprint: thread.fingerprint,
348
+ dueAt: follow.due_at,
349
+ deadlinePassed: Date.parse(follow.due_at) <= Date.now()
350
+ };
351
+ return {
352
+ content: {
353
+ ...common,
354
+ instructions: follow.instructions,
355
+ items: thread.items.map((item) => ({
356
+ evidenceId: `source-item:${item.id}`,
357
+ occurredAt: item.occurredAt,
358
+ content: wrapExternalContent(item.normalizedText?.slice(0, 4e3) ?? "", { source: "email" })
359
+ }))
360
+ },
361
+ snapshotContent: {
362
+ ...common,
363
+ items: thread.items.map((item) => ({
364
+ sourceItemId: item.id,
365
+ contentHash: item.contentHash,
366
+ occurredAt: item.occurredAt
367
+ }))
368
+ },
369
+ evidenceIds: thread.items.map((item) => `source-item:${item.id}`)
370
+ };
371
+ }
372
+ };
328
373
  var ContextProviderRegistry = class {
329
374
  constructor(providers = [
330
375
  new EventBatchContextProvider(),
@@ -334,7 +379,8 @@ var ContextProviderRegistry = class {
334
379
  new MeetingWorkspaceContextProvider(),
335
380
  new ProjectStateContextProvider(),
336
381
  new AutomationStateContextProvider(),
337
- new DiscussionContextProvider()
382
+ new DiscussionContextProvider(),
383
+ new MailFollowUpContextProvider()
338
384
  ]) {
339
385
  this.providers = providers;
340
386
  }
@@ -357,4 +403,4 @@ var ContextProviderRegistry = class {
357
403
  }
358
404
  };
359
405
  //#endregion
360
- export { AutomationStateContextProvider, ConnectedSourceContextProvider, ContextProviderRegistry, DiscussionContextProvider, EventBatchContextProvider, InternalObjectContextProvider, MeetingWorkspaceContextProvider, ProjectStateContextProvider, UserModelContextProvider };
406
+ export { AutomationStateContextProvider, ConnectedSourceContextProvider, ContextProviderRegistry, DiscussionContextProvider, EventBatchContextProvider, InternalObjectContextProvider, MailFollowUpContextProvider, MeetingWorkspaceContextProvider, ProjectStateContextProvider, UserModelContextProvider };
@@ -1,3 +1,4 @@
1
+ import { ProactiveArtifactSchema } from "../../../packages/gateway-contract/src/proactive.js";
1
2
  import { stripCodeFences } from "../../providers/model-response.js";
2
3
  //#region src/proactive/execution/insight.ts
3
4
  const URGENCY = new Set([
@@ -65,6 +66,7 @@ function parseInsightCandidate(raw, allowedEvidenceIds) {
65
66
  const proposedAction = parseProposedAction(row.proposedAction);
66
67
  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");
67
68
  return {
69
+ ...row.artifact != null ? { artifact: ProactiveArtifactSchema.parse(row.artifact) } : {},
68
70
  title: boundedText(row.title, "title", 160),
69
71
  summary: boundedText(row.summary, "summary", 1200),
70
72
  whyNow: boundedText(row.whyNow, "whyNow", 800),
@@ -91,7 +93,7 @@ function isValuableInsight(candidate, policy = {
91
93
  minConfidence: .65,
92
94
  minScore: .6
93
95
  }) {
94
- return candidate.confidence >= policy.minConfidence && candidate.urgency !== "low" && scoreInsight(candidate) >= policy.minScore;
96
+ return candidate.confidence >= policy.minConfidence && (candidate.urgency !== "low" || Boolean(candidate.artifact)) && scoreInsight(candidate) >= policy.minScore;
95
97
  }
96
98
  function parseAnalysisResult(raw, allowedEvidenceIds) {
97
99
  let value;
@@ -107,11 +107,19 @@ function finishRun(input, now = /* @__PURE__ */ new Date()) {
107
107
  JOIN proactive_events e ON e.event_id = be.event_id
108
108
  WHERE be.batch_id = ?
109
109
  ORDER BY e.subject_kind, e.subject_id`).all(input.run.batchId).map((row) => `${str(row, "subject_kind")}:${str(row, "subject_id")}`);
110
- const fingerprint = input.candidate ? createHash("sha256").update([...subjectScope, ...[
111
- input.candidate.title,
112
- input.candidate.summary,
113
- input.candidate.recommendation
114
- ].map((value) => value.trim().toLowerCase().replace(/\s+/g, " "))].join("\n")).digest("hex") : void 0;
110
+ const snapshot = db.prepare(`SELECT c.content_json FROM proactive_runs r JOIN proactive_context_snapshots c
111
+ ON c.snapshot_id = r.context_snapshot_id WHERE r.run_id = ?`).get(input.run.id);
112
+ const sourceVersions = snapshot ? JSON.parse(snapshot.content_json) : {};
113
+ const fingerprint = input.candidate ? createHash("sha256").update([
114
+ ...subjectScope,
115
+ JSON.stringify(input.candidate.artifact ?? null),
116
+ JSON.stringify(sourceVersions.connected_source ?? sourceVersions.project_state ?? sourceVersions.follow_up ?? null),
117
+ ...[
118
+ input.candidate.title,
119
+ input.candidate.summary,
120
+ input.candidate.recommendation
121
+ ].map((value) => value.trim().toLowerCase().replace(/\s+/g, " "))
122
+ ].join("\n")).digest("hex") : void 0;
115
123
  const duplicate = fingerprint ? db.prepare(`SELECT 1 FROM proactive_insights
116
124
  WHERE subscription_id = ? AND scenario_key = ? AND content_fingerprint = ? AND created_at >= ? LIMIT 1`).get(input.run.subscriptionId, input.run.scenarioKey, fingerprint, (/* @__PURE__ */ new Date(now.getTime() - (input.cooldownSeconds ?? 10080 * 60) * 1e3)).toISOString()) : void 0;
117
125
  const valuable = Boolean(input.candidate) && !duplicate;
@@ -141,6 +149,7 @@ function finishRun(input, now = /* @__PURE__ */ new Date()) {
141
149
  why_now, impact, recommendation, work_done, decision_json, proposed_action_json, urgency, confidence, value_score,
142
150
  evidence_ids_json, content_fingerprint, created_at)
143
151
  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);
152
+ if (insight.artifact) db.prepare("UPDATE proactive_insights SET artifact_json = ? WHERE insight_id = ?").run(JSON.stringify(insight.artifact), insight.id);
144
153
  return insight;
145
154
  });
146
155
  }
@@ -165,6 +174,7 @@ function listInsights(limit = 50) {
165
174
  impact: str(row, "impact"),
166
175
  recommendation: str(row, "recommendation"),
167
176
  workDone: str(row, "work_done"),
177
+ ...row.artifact_json ? { artifact: JSON.parse(str(row, "artifact_json")) } : {},
168
178
  ...row.decision_json ? { decision: JSON.parse(str(row, "decision_json")) } : {},
169
179
  ...row.proposed_action_json ? { proposedAction: JSON.parse(str(row, "proposed_action_json")) } : {},
170
180
  urgency: str(row, "urgency"),
@@ -1,3 +1,4 @@
1
+ import type { ProactiveArtifact } from '@xopcai/gateway-contract';
1
2
  export interface ContextSnapshot {
2
3
  id: string;
3
4
  batchId: string;
@@ -6,6 +7,7 @@ export interface ContextSnapshot {
6
7
  createdAt: string;
7
8
  }
8
9
  export interface InsightCandidate {
10
+ artifact?: ProactiveArtifact;
9
11
  title: string;
10
12
  summary: string;
11
13
  whyNow: string;
@@ -1,6 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
3
  import { getSqliteDatabase } from "../../storage/sqlite/transaction.js";
4
+ import { authorizedConnectedSource } from "./authorization.js";
4
5
  import { effectiveProactivePolicy } from "../policy/service.js";
5
6
  import { getPromptRevision, getScenario } from "../scenarios/repository.js";
6
7
  import { composeScenarioPrompt } from "../scenarios/prompt-composer.js";
@@ -9,6 +10,7 @@ import { ContextProviderRegistry } from "./context.js";
9
10
  import { attachSnapshot, claimNextRun, eventIdsForBatch, failRun, finishRun, saveSnapshot } from "./repository.js";
10
11
  import { isValuableInsight, parseAnalysisResult, scoreInsight } from "./insight.js";
11
12
  import { randomUUID } from "node:crypto";
13
+ import { isDeepStrictEqual } from "node:util";
12
14
  //#region src/proactive/execution/worker.ts
13
15
  init_logger();
14
16
  const log = createLogger("ProactiveWorker");
@@ -86,11 +88,14 @@ var ProactiveWorker = class {
86
88
  subscriptionId: run.subscriptionId
87
89
  });
88
90
  const revoked = context.evidenceIds.some((id) => !latestContext.evidenceIds.includes(id));
89
- const result = revoked ? {
91
+ const changed = !isDeepStrictEqual(context.snapshotContent ?? context.content, latestContext.snapshotContent ?? latestContext.content);
92
+ const unavailable = context.evidenceIds.some((id) => id.startsWith("source-item:") && !authorizedConnectedSource(id.slice(12), effectiveProactivePolicy(run.subscriptionId).workspaceId, run.scenarioKey));
93
+ const result = revoked || changed ? {
90
94
  result: "no_insight",
91
- reason: "source_unavailable"
95
+ reason: unavailable ? "source_unavailable" : "source_changed"
92
96
  } : parseAnalysisResult(output.text, new Set(latestContext.evidenceIds));
93
97
  const candidate = result.result === "insight" ? result.candidate : void 0;
98
+ if (run.scenarioKey === "communication_follow_up" && (candidate?.decision || candidate?.proposedAction)) throw new Error("Communication preparation must return a draft or update; actions require the conversation confirmation flow");
94
99
  const valueScore = candidate ? scoreInsight(candidate) : 0;
95
100
  const enabled = effectiveProactivePolicy(run.subscriptionId).enabled;
96
101
  const valuable = enabled && candidate && isValuableInsight(candidate, scenario.valuePolicy);
@@ -0,0 +1,69 @@
1
+ export declare function startDelegation(workspace: string, value: unknown): {
2
+ effectiveLevel: "off" | "active" | "quiet" | "balanced";
3
+ schedule: Record<string, import("node:sqlite").SQLOutputValue>;
4
+ revision: number;
5
+ level: "off" | "active" | "quiet" | "balanced";
6
+ delivery: "digest" | "inbox" | "important";
7
+ completedAt: string;
8
+ scanIntervalMinutes: number;
9
+ userInstructions: string;
10
+ id: string;
11
+ scenarioKey: string;
12
+ workspaceId: string;
13
+ scopeKind: "workspace" | "project";
14
+ scopeId: string;
15
+ enabled: boolean;
16
+ activePromptRevisionId?: string;
17
+ createdAt: string;
18
+ updatedAt: string;
19
+ };
20
+ /** Queue work in the existing worker; HTTP and conversation requests do not own model runs. */
21
+ export declare function checkDelegation(workspace: string, id: string): {
22
+ status: "queued";
23
+ };
24
+ export declare function delegationOverview(workspace: string): {
25
+ followUps: {
26
+ id: string;
27
+ subscriptionId: string;
28
+ instructions: string;
29
+ dueAt: string;
30
+ status: "completed" | "paused" | "watching";
31
+ revision: number;
32
+ lastCheckedAt: string;
33
+ sessionKey: string;
34
+ sourceAvailable: boolean;
35
+ enabled: boolean;
36
+ subject: string;
37
+ latestMessageAt: string;
38
+ latestDirection: string;
39
+ lastSyncedAt: string;
40
+ syncFailed: boolean;
41
+ }[];
42
+ needsDecision: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
43
+ prepared: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
44
+ updates: import("@xopcai/gateway-contract/src/proactive.js").ProactiveCard[];
45
+ delegations: {
46
+ effectiveEnabled: boolean;
47
+ project: Record<string, import("node:sqlite").SQLOutputValue>;
48
+ latestRun: Record<string, import("node:sqlite").SQLOutputValue>;
49
+ pending: boolean;
50
+ effectiveLevel: "off" | "active" | "quiet" | "balanced";
51
+ schedule: Record<string, import("node:sqlite").SQLOutputValue>;
52
+ revision: number;
53
+ level: "off" | "active" | "quiet" | "balanced";
54
+ delivery: "digest" | "inbox" | "important";
55
+ completedAt: string;
56
+ scanIntervalMinutes: number;
57
+ userInstructions: string;
58
+ id: string;
59
+ scenarioKey: string;
60
+ workspaceId: string;
61
+ scopeKind: "workspace" | "project";
62
+ scopeId: string;
63
+ enabled: boolean;
64
+ activePromptRevisionId?: string;
65
+ createdAt: string;
66
+ updatedAt: string;
67
+ }[];
68
+ };
69
+ export declare function completeDeliveredProjects(now?: Date): void;
@@ -0,0 +1,90 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ import { ProactiveConflict, effectiveProactivePolicy } from "./policy/service.js";
3
+ import { controlledSubscriptions, createControlledSubscription, requireSubscription, updateControlledSubscription } from "./scenarios/control.js";
4
+ import { ProactiveScenarioService } from "./scenarios/service.js";
5
+ import { ProactiveEventService } from "./service.js";
6
+ import { listMailFollowUps } from "./follow-ups.js";
7
+ import { getCard } from "./inbox/cards.js";
8
+ import { scanDueProjects } from "./temporal/schedule.js";
9
+ import { z } from "zod";
10
+ //#region src/proactive/experience.ts
11
+ const DelegateSchema = z.object({
12
+ scenarioKey: z.enum([
13
+ "project_delivery_risk",
14
+ "meeting_preparation",
15
+ "discussion_follow_up"
16
+ ]),
17
+ projectId: z.string().min(1).optional(),
18
+ instructions: z.string().trim().min(1).max(12e3)
19
+ }).strict();
20
+ function startDelegation(workspace, value) {
21
+ const input = DelegateSchema.parse(value);
22
+ if (input.scenarioKey === "project_delivery_risk" && !input.projectId) throw new Error("Choose a project");
23
+ if (input.scenarioKey !== "project_delivery_risk" && input.projectId) throw new Error("This service uses workspace sources");
24
+ const subscription = createControlledSubscription(workspace, {
25
+ scenarioKey: input.scenarioKey,
26
+ scopeKind: input.projectId ? "project" : "workspace",
27
+ scopeId: input.projectId ?? workspace,
28
+ userInstructions: input.instructions
29
+ });
30
+ if (input.projectId && effectiveProactivePolicy(subscription.id).enabled) checkDelegation(workspace, subscription.id);
31
+ return subscription;
32
+ }
33
+ /** Queue work in the existing worker; HTTP and conversation requests do not own model runs. */
34
+ function checkDelegation(workspace, id) {
35
+ const sub = requireSubscription(id, workspace);
36
+ if (!effectiveProactivePolicy(id).enabled) throw new Error("Resume this service before checking");
37
+ if (sub.scopeKind !== "project") throw new Error("This service checks when connected sources change");
38
+ return runSqliteWriteTransaction((db) => {
39
+ if (db.prepare("SELECT 1 FROM proactive_signal_batches WHERE subscription_id = ? AND status IN ('collecting', 'ready', 'processing')").get(id)) return { status: "queued" };
40
+ const last = db.prepare("SELECT MAX(started_at) AS at FROM proactive_runs WHERE subscription_id = ?").get(id);
41
+ if (last.at && Date.parse(last.at) > Date.now() - 6e4) throw new ProactiveConflict("A check just finished; try again in a minute");
42
+ db.prepare(`INSERT INTO proactive_schedule_state(subscription_id, next_due_at) VALUES (?, ?)
43
+ ON CONFLICT(subscription_id) DO UPDATE SET next_due_at = excluded.next_due_at, last_fingerprint = NULL`).run(id, (/* @__PURE__ */ new Date()).toISOString());
44
+ scanDueProjects(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
45
+ db.prepare("UPDATE proactive_signal_batches SET ready_at = ?, status = 'ready' WHERE subscription_id = ? AND status = 'collecting'").run((/* @__PURE__ */ new Date()).toISOString(), id);
46
+ return { status: "queued" };
47
+ });
48
+ }
49
+ function delegationOverview(workspace) {
50
+ const db = getSqliteDatabase();
51
+ const now = (/* @__PURE__ */ new Date()).toISOString();
52
+ const cards = db.prepare(`SELECT i.inbox_item_id FROM proactive_inbox_items i
53
+ JOIN proactive_insights x USING(insight_id) JOIN proactive_scenario_subscriptions s USING(subscription_id)
54
+ WHERE s.workspace_id = ? AND i.withdrawn_at IS NULL AND i.status IN ('unread', 'read')
55
+ AND (i.expires_at IS NULL OR i.expires_at > ?)
56
+ ORDER BY CASE WHEN x.action_status = 'approval_required' THEN 0 WHEN x.artifact_json IS NOT NULL THEN 1 ELSE 2 END,
57
+ x.value_score DESC, i.updated_at DESC LIMIT 100`).all(workspace, now).map((row) => getCard(row.inbox_item_id, workspace)).filter((card) => !["withdrawn", "expired"].includes(card.status));
58
+ return {
59
+ followUps: listMailFollowUps(workspace),
60
+ needsDecision: cards.filter((card) => card.decision && card.actionStatus !== "completed"),
61
+ prepared: cards.filter((card) => card.artifact && !card.decision),
62
+ updates: cards.filter((card) => !card.artifact && !card.decision),
63
+ delegations: controlledSubscriptions(workspace).map((sub) => ({
64
+ ...sub,
65
+ effectiveEnabled: effectiveProactivePolicy(sub.id).enabled,
66
+ project: sub.scopeKind === "project" ? db.prepare("SELECT name, status FROM projects WHERE project_id = ?").get(sub.scopeId) ?? null : null,
67
+ latestRun: db.prepare(`SELECT status, outcome_reason AS reason, completed_at AS completedAt, started_at AS startedAt, error_message AS error
68
+ FROM proactive_runs WHERE subscription_id = ? ORDER BY started_at DESC LIMIT 1`).get(sub.id) ?? null,
69
+ pending: Boolean(db.prepare("SELECT 1 FROM proactive_signal_batches WHERE subscription_id = ? AND status IN ('collecting', 'ready', 'processing')").get(sub.id))
70
+ }))
71
+ };
72
+ }
73
+ function completeDeliveredProjects(now = /* @__PURE__ */ new Date()) {
74
+ const db = getSqliteDatabase();
75
+ const rows = db.prepare(`SELECT s.subscription_id, s.workspace_id FROM proactive_scenario_subscriptions s
76
+ JOIN projects p ON p.project_id = s.scope_id WHERE s.scope_kind = 'project' AND s.enabled = 1
77
+ AND p.status IN ('completed', 'cancelled', 'archived')`).all();
78
+ for (const row of rows) {
79
+ const current = controlledSubscriptions(row.workspace_id).find((sub) => sub.id === row.subscription_id);
80
+ updateControlledSubscription(row.workspace_id, row.subscription_id, {
81
+ expectedRevision: current.revision,
82
+ enabled: false,
83
+ completedAt: now.toISOString()
84
+ });
85
+ db.prepare(`UPDATE proactive_inbox_items SET status = 'resolved', resolution = 'project_ended', updated_at = ?
86
+ WHERE insight_id IN (SELECT insight_id FROM proactive_insights WHERE subscription_id = ?) AND status <> 'resolved'`).run(now.toISOString(), row.subscription_id);
87
+ }
88
+ }
89
+ //#endregion
90
+ export { checkDelegation, completeDeliveredProjects, delegationOverview, startDelegation };
@@ -0,0 +1,123 @@
1
+ import { ProactiveEventService } from './service.js';
2
+ export declare const COMMUNICATION_SCENARIO = "communication_follow_up";
3
+ export type MailFollowUp = {
4
+ id: string;
5
+ subscription_id: string;
6
+ workspace_id: string;
7
+ source_item_id: string;
8
+ instructions: string;
9
+ due_at: string;
10
+ status: 'watching' | 'paused' | 'completed';
11
+ revision: number;
12
+ last_fingerprint: string | null;
13
+ last_checked_at: string | null;
14
+ session_key: string | null;
15
+ };
16
+ export declare function requireMailFollowUp(workspace: string, id: string): MailFollowUp;
17
+ export declare function authorizedMailThread(follow: MailFollowUp): {
18
+ origin: import("../knowledge/types.js").KnowledgeSourceItem;
19
+ items: import("../knowledge/types.js").KnowledgeSourceItem[];
20
+ threadKey: string;
21
+ fingerprint: string;
22
+ };
23
+ export declare function mailFollowUpView(follow: MailFollowUp): {
24
+ id: string;
25
+ subscriptionId: string;
26
+ instructions: string;
27
+ dueAt: string;
28
+ status: "completed" | "paused" | "watching";
29
+ revision: number;
30
+ lastCheckedAt: string;
31
+ sessionKey: string;
32
+ sourceAvailable: boolean;
33
+ enabled: boolean;
34
+ subject: string;
35
+ latestMessageAt: string;
36
+ latestDirection: string;
37
+ lastSyncedAt: string;
38
+ syncFailed: boolean;
39
+ };
40
+ export declare function listMailFollowUps(workspace: string): {
41
+ id: string;
42
+ subscriptionId: string;
43
+ instructions: string;
44
+ dueAt: string;
45
+ status: "completed" | "paused" | "watching";
46
+ revision: number;
47
+ lastCheckedAt: string;
48
+ sessionKey: string;
49
+ sourceAvailable: boolean;
50
+ enabled: boolean;
51
+ subject: string;
52
+ latestMessageAt: string;
53
+ latestDirection: string;
54
+ lastSyncedAt: string;
55
+ syncFailed: boolean;
56
+ }[];
57
+ export declare function mailFollowUpSources(workspace: string): {
58
+ id: string;
59
+ subject: string;
60
+ sender: string;
61
+ occurredAt: string;
62
+ accountLabel: string;
63
+ }[];
64
+ export declare function startMailFollowUp(workspace: string, value: unknown): {
65
+ id: string;
66
+ subscriptionId: string;
67
+ instructions: string;
68
+ dueAt: string;
69
+ status: "completed" | "paused" | "watching";
70
+ revision: number;
71
+ lastCheckedAt: string;
72
+ sessionKey: string;
73
+ sourceAvailable: boolean;
74
+ enabled: boolean;
75
+ subject: string;
76
+ latestMessageAt: string;
77
+ latestDirection: string;
78
+ lastSyncedAt: string;
79
+ syncFailed: boolean;
80
+ };
81
+ export declare function updateMailFollowUp(workspace: string, id: string, value: unknown): {
82
+ id: string;
83
+ subscriptionId: string;
84
+ instructions: string;
85
+ dueAt: string;
86
+ status: "completed" | "paused" | "watching";
87
+ revision: number;
88
+ lastCheckedAt: string;
89
+ sessionKey: string;
90
+ sourceAvailable: boolean;
91
+ enabled: boolean;
92
+ subject: string;
93
+ latestMessageAt: string;
94
+ latestDirection: string;
95
+ lastSyncedAt: string;
96
+ syncFailed: boolean;
97
+ };
98
+ /** Keep the existing chat and its exact connector confirmation flow as the write boundary. */
99
+ export declare function continueMailFollowUp(workspace: string, id: string, sessionKey: string): {
100
+ followUp: {
101
+ id: string;
102
+ subscriptionId: string;
103
+ instructions: string;
104
+ dueAt: string;
105
+ status: "completed" | "paused" | "watching";
106
+ revision: number;
107
+ lastCheckedAt: string;
108
+ sessionKey: string;
109
+ sourceAvailable: boolean;
110
+ enabled: boolean;
111
+ subject: string;
112
+ latestMessageAt: string;
113
+ latestDirection: string;
114
+ lastSyncedAt: string;
115
+ syncFailed: boolean;
116
+ };
117
+ connectionId: unknown;
118
+ sourceItemId: string;
119
+ threadId: string;
120
+ instruction: string;
121
+ };
122
+ /** Poll only delegated threads; unchanged threads and passed deadlines produce no repeat signals. */
123
+ export declare function scanMailFollowUps(events: ProactiveEventService, now?: Date): number;
@@ -0,0 +1,169 @@
1
+ import { getSqliteDatabase, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
2
+ import { listKnowledgeSourceItems } from "../storage/sqlite/knowledge-repository.js";
3
+ import { getConnectorConnection } from "../storage/sqlite/connector-repository.js";
4
+ import { emailFields, readMailThread } from "./mail-thread.js";
5
+ import { authorizedConnectedSource } from "./execution/authorization.js";
6
+ import { ProactiveConflict, effectiveProactivePolicy } from "./policy/service.js";
7
+ import { listSubscriptions } from "./scenarios/repository.js";
8
+ import { createControlledSubscription } from "./scenarios/control.js";
9
+ import { ProactiveScenarioService } from "./scenarios/service.js";
10
+ import { ProactiveEventService } from "./service.js";
11
+ import { randomUUID } from "node:crypto";
12
+ import { z } from "zod";
13
+ //#region src/proactive/follow-ups.ts
14
+ const COMMUNICATION_SCENARIO = "communication_follow_up";
15
+ const CreateSchema = z.object({
16
+ sourceItemId: z.string().min(1),
17
+ instructions: z.string().trim().min(1).max(12e3),
18
+ dueAt: z.string().datetime()
19
+ }).strict();
20
+ const UpdateSchema = z.object({
21
+ expectedRevision: z.number().int().positive(),
22
+ instructions: z.string().trim().min(1).max(12e3).optional(),
23
+ dueAt: z.string().datetime().optional(),
24
+ status: z.enum([
25
+ "watching",
26
+ "paused",
27
+ "completed"
28
+ ]).optional()
29
+ }).strict();
30
+ function requireMailFollowUp(workspace, id) {
31
+ const row = getSqliteDatabase().prepare("SELECT * FROM proactive_follow_ups WHERE id = ? AND workspace_id = ?").get(id, workspace);
32
+ if (!row) throw new Error("Follow-up not found");
33
+ return row;
34
+ }
35
+ function authorizedMailThread(follow) {
36
+ if (!authorizedConnectedSource(follow.source_item_id, follow.workspace_id, "communication_follow_up")) return null;
37
+ const thread = readMailThread(follow.source_item_id);
38
+ if (!thread || thread.items.some((item) => !authorizedConnectedSource(item.id, follow.workspace_id, "communication_follow_up") || item.metadata.connectionId !== thread.origin.metadata.connectionId)) return null;
39
+ return thread;
40
+ }
41
+ function mailFollowUpView(follow) {
42
+ const thread = authorizedMailThread(follow);
43
+ const latest = thread?.items.at(-1);
44
+ const sync = thread ? getSqliteDatabase().prepare("SELECT status, error, finished_at FROM knowledge_sync_runs WHERE source_instance_id = ? ORDER BY started_at DESC LIMIT 1").get(thread.origin.sourceInstanceId) : void 0;
45
+ return {
46
+ id: follow.id,
47
+ subscriptionId: follow.subscription_id,
48
+ instructions: follow.instructions,
49
+ dueAt: follow.due_at,
50
+ status: follow.status,
51
+ revision: follow.revision,
52
+ lastCheckedAt: follow.last_checked_at,
53
+ sessionKey: follow.session_key,
54
+ sourceAvailable: Boolean(thread),
55
+ enabled: effectiveProactivePolicy(follow.subscription_id).enabled,
56
+ subject: thread ? emailFields(thread.origin.normalizedText).subject ?? "Email follow-up" : null,
57
+ latestMessageAt: latest?.occurredAt ?? null,
58
+ latestDirection: latest ? emailFields(latest.normalizedText).labels?.includes("SENT") ? "sent" : emailFields(latest.normalizedText).labels?.includes("INBOX") ? "received" : "unknown" : null,
59
+ lastSyncedAt: sync?.finished_at ? new Date(sync.finished_at).toISOString() : null,
60
+ syncFailed: Boolean(sync?.error)
61
+ };
62
+ }
63
+ function listMailFollowUps(workspace) {
64
+ return getSqliteDatabase().prepare("SELECT * FROM proactive_follow_ups WHERE workspace_id = ? ORDER BY updated_at DESC").all(workspace).map(mailFollowUpView);
65
+ }
66
+ function mailFollowUpSources(workspace) {
67
+ const seen = /* @__PURE__ */ new Set();
68
+ return listKnowledgeSourceItems({
69
+ itemType: "email",
70
+ limit: 500
71
+ }).flatMap((item) => {
72
+ if (!authorizedConnectedSource(item.id, workspace, "communication_follow_up")) return [];
73
+ const thread = readMailThread(item.id);
74
+ if (!thread || seen.has(thread.threadKey)) return [];
75
+ seen.add(thread.threadKey);
76
+ const fields = emailFields(item.normalizedText);
77
+ const connection = getConnectorConnection(String(item.metadata.connectionId));
78
+ const account = connection?.alias ?? connection?.identity.email ?? connection?.identity.name;
79
+ return [{
80
+ id: item.id,
81
+ subject: fields.subject ?? "Email",
82
+ sender: fields.sender ?? "",
83
+ occurredAt: item.occurredAt,
84
+ accountLabel: typeof account === "string" ? account : "Connected email account"
85
+ }];
86
+ }).slice(0, 100);
87
+ }
88
+ function startMailFollowUp(workspace, value) {
89
+ const input = CreateSchema.parse(value);
90
+ if (Date.parse(input.dueAt) <= Date.now()) throw new Error("Choose a future follow-up time");
91
+ if (!authorizedConnectedSource(input.sourceItemId, workspace, "communication_follow_up")) throw new Error("Authorize this email account for proactive follow-up first");
92
+ const thread = readMailThread(input.sourceItemId);
93
+ if (!thread) throw new Error("This email has no available thread");
94
+ return runSqliteWriteTransaction((db) => {
95
+ if (db.prepare("SELECT 1 FROM proactive_follow_ups WHERE workspace_id = ? AND thread_key = ?").get(workspace, thread.threadKey)) throw new ProactiveConflict("This conversation is already delegated; update the existing follow-up");
96
+ const sub = listSubscriptions("communication_follow_up").find((item) => item.workspaceId === workspace) ?? createControlledSubscription(workspace, {
97
+ scenarioKey: "communication_follow_up",
98
+ scopeKind: "workspace",
99
+ scopeId: workspace
100
+ });
101
+ const id = randomUUID();
102
+ const now = (/* @__PURE__ */ new Date()).toISOString();
103
+ db.prepare(`INSERT INTO proactive_follow_ups(id, subscription_id, workspace_id, source_item_id, thread_key, instructions, due_at, created_at, updated_at)
104
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, sub.id, workspace, input.sourceItemId, thread.threadKey, input.instructions, input.dueAt, now, now);
105
+ scanMailFollowUps(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
106
+ return mailFollowUpView(requireMailFollowUp(workspace, id));
107
+ });
108
+ }
109
+ function updateMailFollowUp(workspace, id, value) {
110
+ const input = UpdateSchema.parse(value);
111
+ return runSqliteWriteTransaction((db) => {
112
+ const row = requireMailFollowUp(workspace, id);
113
+ if (row.revision !== input.expectedRevision) throw new ProactiveConflict("Follow-up changed; refresh before editing");
114
+ if (input.dueAt && Date.parse(input.dueAt) <= Date.now()) throw new Error("Choose a future follow-up time");
115
+ db.prepare(`UPDATE proactive_follow_ups SET instructions = ?, due_at = ?, status = ?, revision = revision + 1,
116
+ last_fingerprint = NULL, updated_at = ? WHERE id = ?`).run(input.instructions ?? row.instructions, input.dueAt ?? row.due_at, input.status ?? row.status, (/* @__PURE__ */ new Date()).toISOString(), id);
117
+ scanMailFollowUps(new ProactiveEventService(() => new ProactiveScenarioService().routes()));
118
+ return mailFollowUpView(requireMailFollowUp(workspace, id));
119
+ });
120
+ }
121
+ /** Keep the existing chat and its exact connector confirmation flow as the write boundary. */
122
+ function continueMailFollowUp(workspace, id, sessionKey) {
123
+ const follow = requireMailFollowUp(workspace, id);
124
+ const thread = authorizedMailThread(follow);
125
+ if (!thread || follow.status !== "watching" || !effectiveProactivePolicy(follow.subscription_id).enabled) throw new Error("Resume and authorize this follow-up before continuing");
126
+ getSqliteDatabase().prepare("UPDATE proactive_follow_ups SET session_key = ? WHERE id = ?").run(sessionKey, id);
127
+ return {
128
+ followUp: mailFollowUpView(requireMailFollowUp(workspace, id)),
129
+ connectionId: thread.origin.metadata.connectionId,
130
+ sourceItemId: thread.origin.id,
131
+ threadId: emailFields(thread.origin.normalizedText).threadId,
132
+ instruction: "Read the current card and latest thread using this exact connection. Review the recipients and complete draft with the user before sending through the connector approval flow. Never infer successful delivery from a draft or approval. Use provider results, then continue watching synchronized replies."
133
+ };
134
+ }
135
+ /** Poll only delegated threads; unchanged threads and passed deadlines produce no repeat signals. */
136
+ function scanMailFollowUps(events, now = /* @__PURE__ */ new Date()) {
137
+ const db = getSqliteDatabase();
138
+ let published = 0;
139
+ for (const follow of db.prepare("SELECT * FROM proactive_follow_ups WHERE status = 'watching'").all()) {
140
+ if (!effectiveProactivePolicy(follow.subscription_id, now).enabled) continue;
141
+ const thread = authorizedMailThread(follow);
142
+ if (!thread) continue;
143
+ const fingerprint = `${follow.revision}:${thread.fingerprint}:${Date.parse(follow.due_at) <= now.getTime() ? "due" : "waiting"}`;
144
+ if (fingerprint !== follow.last_fingerprint) {
145
+ if (events.publish({
146
+ type: "proactive.follow_up.v1",
147
+ schemaVersion: 1,
148
+ source: {
149
+ kind: "connector",
150
+ id: String(thread.origin.metadata.connectionId)
151
+ },
152
+ subject: {
153
+ kind: "mail_follow_up",
154
+ id: follow.id
155
+ },
156
+ actor: { kind: "system" },
157
+ scope: { workspaceId: follow.workspace_id },
158
+ occurredAt: now.toISOString(),
159
+ dedupeKey: `mail-follow-up:${follow.id}:${fingerprint}`,
160
+ sensitivity: "personal",
161
+ payload: { followUpId: follow.id }
162
+ }, now).inserted) published++;
163
+ }
164
+ db.prepare("UPDATE proactive_follow_ups SET last_fingerprint = ?, last_checked_at = ? WHERE id = ?").run(fingerprint, now.toISOString(), follow.id);
165
+ }
166
+ return published;
167
+ }
168
+ //#endregion
169
+ export { COMMUNICATION_SCENARIO, authorizedMailThread, continueMailFollowUp, listMailFollowUps, mailFollowUpSources, mailFollowUpView, requireMailFollowUp, scanMailFollowUps, startMailFollowUp, updateMailFollowUp };