@xopcai/xopc 0.0.366 → 0.0.367

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 (252) 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-SVmnh__i.js → activity-store-Cuf3JFFJ.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CS9lg5h2.js → agent-avatar-dicebear-DyATPNTe.js} +1 -1
  5. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-gT9_j4tr.js +1 -0
  6. package/dist/gateway/static/root/assets/agent-plugin-dialog-CLXCJ6JN.js +1 -0
  7. package/dist/gateway/static/root/assets/agents-BAUfOMsq.js +66 -0
  8. package/dist/gateway/static/root/assets/{agents-admin-api-CVdFV-cU.js → agents-admin-api-D842OcNo.js} +1 -1
  9. package/dist/gateway/static/root/assets/app-link-4gpFbdsr.js +1 -0
  10. package/dist/gateway/static/root/assets/{app-management-settings-panel-CaxnUxvy.js → app-management-settings-panel-CoIFxQKH.js} +1 -1
  11. package/dist/gateway/static/root/assets/{appearance-settings-6NKquG3v.js → appearance-settings-DQr0o6Lm.js} +1 -1
  12. package/dist/gateway/static/root/assets/{apps-page-BoB3MbsB.js → apps-page-CltMV4Xp.js} +1 -1
  13. package/dist/gateway/static/root/assets/{archive-plugin-BWtLZtK1.js → archive-plugin-DT8Nio-r.js} +1 -1
  14. package/dist/gateway/static/root/assets/automation-display-DCkjVzA0.js +2 -0
  15. package/dist/gateway/static/root/assets/{automations-page-CNngHw2c.js → automations-page-BIfWS_3Y.js} +1 -1
  16. package/dist/gateway/static/root/assets/automations-workspace-BCGPjsdU.js +6 -0
  17. package/dist/gateway/static/root/assets/binary-plugins-7qs3qcW9.js +2 -0
  18. package/dist/gateway/static/root/assets/{block-editor-BhstSZNE.js → block-editor-BFPUlxJ6.js} +28 -28
  19. package/dist/gateway/static/root/assets/{browser-automation-inputs-B6sOBxVA.js → browser-automation-inputs-BUAIKIX0.js} +1 -1
  20. package/dist/gateway/static/root/assets/{browser-automations-page-HZAKkVVt.js → browser-automations-page-CSwu1U1F.js} +2 -2
  21. package/dist/gateway/static/root/assets/browser-settings-page-C1ReMNqX.js +3 -0
  22. package/dist/gateway/static/root/assets/capabilities-BzWFO_x_.js +1 -0
  23. package/dist/gateway/static/root/assets/{capabilities-CAIQmCrH.js → capabilities-K0Zb_lH0.js} +1 -1
  24. package/dist/gateway/static/root/assets/capabilities-page-BdTSqloI.js +2 -0
  25. package/dist/gateway/static/root/assets/{capabilities-settings-panel-BP2roWcM.js → capabilities-settings-panel-BUblBMZC.js} +4 -4
  26. package/dist/gateway/static/root/assets/{capability-header-actions-BA1M7RRP.js → capability-header-actions-AMn_vTNv.js} +1 -1
  27. package/dist/gateway/static/root/assets/channels-CXCf5qO6.js +1 -0
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-KS_yk1H7.js → chat-terminal-dock-C7nAROhF.js} +2 -2
  29. package/dist/gateway/static/root/assets/chevron-left-DqFhpbvK.js +1 -0
  30. package/dist/gateway/static/root/assets/computer-settings-page-B5SuSZ3G.js +1 -0
  31. package/dist/gateway/static/root/assets/{connector-service-page-CY_3H_l9.js → connector-service-page-CTx1B8wx.js} +1 -1
  32. package/dist/gateway/static/root/assets/connectors-page-DfnK1crf.js +2 -0
  33. package/dist/gateway/static/root/assets/date-formatters-CUZAyDEg.js +1 -0
  34. package/dist/gateway/static/root/assets/date-picker-Cx_xIKvN.js +1 -0
  35. package/dist/gateway/static/root/assets/{dependency-picker-CyNH4m20.js → dependency-picker-DYm96PDu.js} +1 -1
  36. package/dist/gateway/static/root/assets/{desktop-pet-BsZQsQ2_.js → desktop-pet-D90OzgeR.js} +1 -1
  37. package/dist/gateway/static/root/assets/{desktop-pet-settings-DMgkUy6g.js → desktop-pet-settings-CmdCecjm.js} +1 -1
  38. package/dist/gateway/static/root/assets/{device-pairing-wizard-JjbUN8y-.js → device-pairing-wizard-s2ogSa4l.js} +1 -1
  39. package/dist/gateway/static/root/assets/{directory-picker-path-field-CBTI3tKh.js → directory-picker-path-field-DZpaoeNa.js} +1 -1
  40. package/dist/gateway/static/root/assets/{extension-debug-page-C7nSpOKj.js → extension-debug-page-Bv6QE8kC.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-page-BYUjAvsZ.js → extension-page-CEsq71Cm.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-provider-DaLt3bC-.js → extension-provider-CX-sK0Tw.js} +1 -1
  43. package/dist/gateway/static/root/assets/{extension-settings-page-CRasspq0.js → extension-settings-page-UyOHF39P.js} +1 -1
  44. package/dist/gateway/static/root/assets/{fallback-models-BLJFYASE.js → fallback-models-CKv_Wqg8.js} +1 -1
  45. package/dist/gateway/static/root/assets/{gateway-config-swr-DIIzvDLQ.js → gateway-config-swr-Cjnkle5J.js} +1 -1
  46. package/dist/gateway/static/root/assets/{gateway-realtime-DD70L42G.js → gateway-realtime-DCCLdyQD.js} +1 -1
  47. package/dist/gateway/static/root/assets/gateway-realtime-store-C_Th8kGg.js +1 -0
  48. package/dist/gateway/static/root/assets/gateway-settings-CZ73IpbP.js +1 -0
  49. package/dist/gateway/static/root/assets/{gateway-startup-retry-D_EwU7-6.js → gateway-startup-retry-CXKmdVzN.js} +1 -1
  50. package/dist/gateway/static/root/assets/home-page-BQWq4kYi.js +2 -0
  51. package/dist/gateway/static/root/assets/{image-generation-api-BkK22JsL.js → image-generation-api-NLHzm4Nc.js} +1 -1
  52. package/dist/gateway/static/root/assets/{imports-page-YJKcTKKr.js → imports-page-C7qvlBTQ.js} +1 -1
  53. package/dist/gateway/static/root/assets/index-BQgqzhQj.js +106 -0
  54. package/dist/gateway/static/root/assets/index-COB4QIJp.css +1 -0
  55. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BG_kM_Rm.js → keyboard-shortcuts-settings-pkgFWJb-.js} +1 -1
  56. package/dist/gateway/static/root/assets/local-app-workbench-page-dMDhZXAi.js +1 -0
  57. package/dist/gateway/static/root/assets/{local-apps-page-jqthjcQO.js → local-apps-page-TpUAfOn2.js} +1 -1
  58. package/dist/gateway/static/root/assets/{local-session-drafts-C4et6msJ.js → local-session-drafts-Cvv7I0fw.js} +1 -1
  59. package/dist/gateway/static/root/assets/{locale-store-CvNO-hbt.js → locale-store-C8TMD2gn.js} +1 -1
  60. package/dist/gateway/static/root/assets/logs-page-B-Y9oZLh.js +2 -0
  61. package/dist/gateway/static/root/assets/management-settings-B2lzsw6X.js +1 -0
  62. package/dist/gateway/static/root/assets/markdown-view-Dse7rkio.js +201 -0
  63. package/dist/gateway/static/root/assets/{media-plugins-C25mOgs2.js → media-plugins-BZrnzaBM.js} +1 -1
  64. package/dist/gateway/static/root/assets/messages-Dy26npMy.js +3 -0
  65. package/dist/gateway/static/root/assets/models-hub-cache-B1C86nRp.js +1 -0
  66. package/dist/gateway/static/root/assets/note-detail-panel-DL__qP6U.js +5 -0
  67. package/dist/gateway/static/root/assets/{notes-api-CKLw9vjk.js → notes-api-DKiVeQKG.js} +1 -1
  68. package/dist/gateway/static/root/assets/notes-page-DTBbg9Hs.js +8 -0
  69. package/dist/gateway/static/root/assets/{oauth-api-CC5KkSgG.js → oauth-api-BwpzpRwC.js} +1 -1
  70. package/dist/gateway/static/root/assets/open-route-MyZ2sB9C.js +1 -0
  71. package/dist/gateway/static/root/assets/{page-context-capture-button-KX9mrcJW.js → page-context-capture-button-Cxzd4QPB.js} +1 -1
  72. package/dist/gateway/static/root/assets/personal-page-CzaTnHeD.js +1 -0
  73. package/dist/gateway/static/root/assets/product-open-page-D4hoEWiu.js +1 -0
  74. package/dist/gateway/static/root/assets/product-preview-content-aR38El2E.js +1 -0
  75. package/dist/gateway/static/root/assets/project-detail-page-D20QH4YB.js +1 -0
  76. package/dist/gateway/static/root/assets/projects-page-Bf3BIcT6.js +1 -0
  77. package/dist/gateway/static/root/assets/{registry-api-CiN49wvk.js → registry-api-AdnxowbH.js} +1 -1
  78. package/dist/gateway/static/root/assets/remote-access-hub-CKxqncqW.js +1 -0
  79. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-wZjlSBiM.js → runtime-tools-settings-panel-CBN3raz1.js} +1 -1
  80. package/dist/gateway/static/root/assets/scenes-page-Cv_5ozfX.js +2 -0
  81. package/dist/gateway/static/root/assets/{schema-form-CMB61TV1.js → schema-form-CxrMGsT9.js} +1 -1
  82. package/dist/gateway/static/root/assets/{send-session-input-jH6MQwdZ.js → send-session-input-CgOzhDZ0.js} +1 -1
  83. package/dist/gateway/static/root/assets/{session-api-CW2X7g_U.js → session-api-_HIN8or3.js} +1 -1
  84. package/dist/gateway/static/root/assets/session-manager-CzCto5zT.js +16 -0
  85. package/dist/gateway/static/root/assets/sessions-page-DZcu6NLJ.js +1 -0
  86. package/dist/gateway/static/root/assets/settings-advanced-gate-DazqeDQ7.js +1 -0
  87. package/dist/gateway/static/root/assets/{settings-page-Ch71KQjb.js → settings-page-D8Q3H3-o.js} +1 -1
  88. package/dist/gateway/static/root/assets/setup-status-panel-DvLMMiuS.js +1 -0
  89. package/dist/gateway/static/root/assets/{share-link-dialog-DCSmx-Rl.js → share-link-dialog-Dg5os066.js} +1 -1
  90. package/dist/gateway/static/root/assets/{share-preview-page-C93IM3QK.js → share-preview-page-DMvohAyr.js} +1 -1
  91. package/dist/gateway/static/root/assets/{shares-api-B4rLfG3l.js → shares-api-C96IO4qJ.js} +1 -1
  92. package/dist/gateway/static/root/assets/{shares-settings-C_6idV8e.js → shares-settings-CsDATuCw.js} +1 -1
  93. package/dist/gateway/static/root/assets/{skill-api-sKX8SSlQ.js → skill-api-C10ML0CH.js} +1 -1
  94. package/dist/gateway/static/root/assets/{skill-reload-api-Ro-s69NW.js → skill-reload-api-DNbJzSfB.js} +1 -1
  95. package/dist/gateway/static/root/assets/skills-page-DObMKvA6.js +2 -0
  96. package/dist/gateway/static/root/assets/{system-settings-panel-DIjaUlla.js → system-settings-panel-Bn3khdzb.js} +1 -1
  97. package/dist/gateway/static/root/assets/task-detail-page-BR2L1L8l.js +2 -0
  98. package/dist/gateway/static/root/assets/task-expandable-content-DL2Q2gre.js +1 -0
  99. package/dist/gateway/static/root/assets/{tasks-CH6KoBeY.js → tasks-DwKXgZ-I.js} +1 -1
  100. package/dist/gateway/static/root/assets/{theme-store-DbRLBHVY.js → theme-store-DQ6KJa4l.js} +1 -1
  101. package/dist/gateway/static/root/assets/{tracing-settings-page-IgY26AYH.js → tracing-settings-page-Ed8_GYUT.js} +1 -1
  102. package/dist/gateway/static/root/assets/{tunnel-api-CgARwbus.js → tunnel-api-D3X8jDwo.js} +1 -1
  103. package/dist/gateway/static/root/assets/{usage-page-CKju62Cm.js → usage-page-BqzRyyb9.js} +1 -1
  104. package/dist/gateway/static/root/assets/{use-autosave-C889OTsP.js → use-autosave-CRFefpzO.js} +1 -1
  105. package/dist/gateway/static/root/assets/use-composer-attachments-OLrvSjn5.js +2 -0
  106. package/dist/gateway/static/root/assets/{use-file-preview-expanded-BOpcSApw.js → use-file-preview-expanded-CJvzfQvw.js} +2 -2
  107. package/dist/gateway/static/root/assets/user-model-page-CG6wqIKP.js +2 -0
  108. package/dist/gateway/static/root/assets/{voice-api-key-field-evWflGY6.js → voice-api-key-field-R9zNWYR_.js} +1 -1
  109. package/dist/gateway/static/root/assets/{voice-config-api-CZoV2Lt4.js → voice-config-api-DLudE9Rc.js} +1 -1
  110. package/dist/gateway/static/root/assets/{work-discovery-overlay-B2-2F39_.js → work-discovery-overlay-DVmQrolV.js} +1 -1
  111. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-cOGM8Nug.js → workflow-run-setup-panel-DEkmuD3T.js} +2 -2
  112. package/dist/gateway/static/root/assets/workflows-page-pqCB3sh4.js +6 -0
  113. package/dist/gateway/static/root/assets/workspace-api-CdVUhyPo.js +2 -0
  114. package/dist/gateway/static/root/index.html +32 -30
  115. package/dist/package.js +1 -1
  116. package/dist/packages/gateway-contract/src/automations.js +1 -0
  117. package/dist/packages/gateway-contract/src/home.js +14 -0
  118. package/dist/packages/gateway-contract/src/index.js +2 -0
  119. package/dist/packages/gateway-contract/src/notifications.js +2 -1
  120. package/dist/packages/gateway-contract/src/personal-proactivity.js +139 -0
  121. package/dist/packages/image-providers/src/catalog.js +373 -0
  122. package/dist/packages/image-providers/src/execute.js +372 -0
  123. package/dist/packages/image-providers/src/http.js +94 -0
  124. package/dist/packages/image-providers/src/index.js +5 -0
  125. package/dist/packages/image-providers/src/types.d.ts +95 -0
  126. package/dist/packages/image-providers/src/validation.js +52 -0
  127. package/dist/src/agent/commands/command-registry.js +1 -1
  128. package/dist/src/agent/failover-error.d.ts +1 -1
  129. package/dist/src/agent/failover-error.js +7 -0
  130. package/dist/src/agent/image/generation/native-provider.d.ts +2 -0
  131. package/dist/src/agent/image/generation/native-provider.js +118 -0
  132. package/dist/src/agent/image/generation/openai-images-provider.d.ts +1 -1
  133. package/dist/src/agent/image/generation/openai-images-provider.js +48 -32
  134. package/dist/src/agent/image/generation/provider-registry.js +4 -13
  135. package/dist/src/agent/image/generation/providers/xopc-cloud.js +5 -34
  136. package/dist/src/agent/image/generation/runtime-types.d.ts +2 -4
  137. package/dist/src/agent/image/generation/runtime.js +28 -23
  138. package/dist/src/agent/image/generation/types.d.ts +3 -50
  139. package/dist/src/agent/image/generation/validation.d.ts +6 -0
  140. package/dist/src/agent/image/generation/validation.js +16 -0
  141. package/dist/src/agent/tools/factory.js +5 -0
  142. package/dist/src/agent/tools/image-generate-tool.js +5 -19
  143. package/dist/src/agent/tools/personal-attention-tool.d.ts +21 -0
  144. package/dist/src/agent/tools/personal-attention-tool.js +191 -0
  145. package/dist/src/automations/capabilities/write.d.ts +2 -0
  146. package/dist/src/automations/domain/types.d.ts +1 -1
  147. package/dist/src/automations/domain/validation.d.ts +4 -0
  148. package/dist/src/automations/domain/validation.js +1 -0
  149. package/dist/src/automations/draft/automation-draft-validator.d.ts +1 -1
  150. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  151. package/dist/src/cli/commands/models.js +3 -8
  152. package/dist/src/config/models-json.d.ts +170 -0
  153. package/dist/src/config/models-json.js +23 -8
  154. package/dist/src/files/file-service.d.ts +6 -0
  155. package/dist/src/files/file-service.js +38 -1
  156. package/dist/src/gateway/custom-image-providers.d.ts +34 -0
  157. package/dist/src/gateway/file-path-classifier.js +12 -3
  158. package/dist/src/gateway/hono/routes/files.js +13 -2
  159. package/dist/src/gateway/hono/routes/personal-agent.js +41 -0
  160. package/dist/src/gateway/service.d.ts +1 -0
  161. package/dist/src/gateway/service.js +50 -11
  162. package/dist/src/home-intelligence/host.js +2 -2
  163. package/dist/src/notifications/planner.js +32 -0
  164. package/dist/src/notifications/service.d.ts +2 -0
  165. package/dist/src/personal-agent/notifications.d.ts +4 -0
  166. package/dist/src/personal-agent/notifications.js +40 -0
  167. package/dist/src/personal-agent/policy.d.ts +1 -1
  168. package/dist/src/personal-agent/policy.js +2 -0
  169. package/dist/src/personal-agent/proactivity/automation.d.ts +3 -0
  170. package/dist/src/personal-agent/proactivity/automation.js +41 -0
  171. package/dist/src/personal-agent/proactivity/follow-up-request.d.ts +5 -0
  172. package/dist/src/personal-agent/proactivity/follow-up-request.js +44 -0
  173. package/dist/src/personal-agent/proactivity/repository.d.ts +128 -0
  174. package/dist/src/personal-agent/proactivity/repository.js +403 -0
  175. package/dist/src/personal-agent/proactivity/routes.d.ts +3 -0
  176. package/dist/src/personal-agent/proactivity/routes.js +182 -0
  177. package/dist/src/personal-agent/proactivity/service.d.ts +32 -0
  178. package/dist/src/personal-agent/proactivity/service.js +496 -0
  179. package/dist/src/personal-agent/prompts.js +13 -2
  180. package/dist/src/personal-agent/reply-composer.js +2 -2
  181. package/dist/src/personal-agent/unread.d.ts +10 -0
  182. package/dist/src/personal-agent/unread.js +43 -0
  183. package/dist/src/providers/env-keys.js +6 -0
  184. package/dist/src/providers/model-catalog-persistence.js +3 -22
  185. package/dist/src/providers/model-catalog-store.js +1 -8
  186. package/dist/src/providers/model-catalog-types.d.ts +1 -9
  187. package/dist/src/providers/xopc-cloud-model-source.js +4 -25
  188. package/dist/src/session/client-history.d.ts +2 -0
  189. package/dist/src/session/client-history.js +26 -0
  190. package/dist/src/session/session-context-for-llm.js +28 -0
  191. package/dist/src/storage/sqlite/migrations/236_personal_proactivity.sql +53 -0
  192. package/dist/src/storage/sqlite/migrations/237_personal_strategy_versions.sql +18 -0
  193. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  194. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  195. package/dist/src/storage/sqlite/schema.js +1 -1
  196. package/dist/src/tasks/home-query-service.js +27 -1
  197. package/dist/src/voice/platform-catalog.d.ts +1 -9
  198. package/package.json +4 -3
  199. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-CvUPtxS4.js +0 -1
  200. package/dist/gateway/static/root/assets/agent-plugin-dialog-1tRxDfjI.js +0 -1
  201. package/dist/gateway/static/root/assets/agents-gdT0whx9.js +0 -66
  202. package/dist/gateway/static/root/assets/app-link-DRL0YnPs.js +0 -1
  203. package/dist/gateway/static/root/assets/automations-workspace-BKHsdiQ8.js +0 -7
  204. package/dist/gateway/static/root/assets/binary-plugins-fIhH-wg6.js +0 -2
  205. package/dist/gateway/static/root/assets/browser-settings-page-D8IpVQI6.js +0 -3
  206. package/dist/gateway/static/root/assets/capabilities-C4grvUkw.js +0 -1
  207. package/dist/gateway/static/root/assets/capabilities-page-DK8FJRW4.js +0 -2
  208. package/dist/gateway/static/root/assets/channels-EQGCxr8W.js +0 -1
  209. package/dist/gateway/static/root/assets/computer-settings-page-CGBR0KFw.js +0 -1
  210. package/dist/gateway/static/root/assets/connectors-page-CUOL6JX0.js +0 -2
  211. package/dist/gateway/static/root/assets/date-picker-CDSZ-PWV.js +0 -1
  212. package/dist/gateway/static/root/assets/gateway-realtime-store-DeUVEPPE.js +0 -1
  213. package/dist/gateway/static/root/assets/gateway-settings-B9n5naCr.js +0 -1
  214. package/dist/gateway/static/root/assets/home-page-BP6qAgBt.js +0 -1
  215. package/dist/gateway/static/root/assets/index-6JNNrzCq.js +0 -106
  216. package/dist/gateway/static/root/assets/index-CbJNcWAn.css +0 -1
  217. package/dist/gateway/static/root/assets/local-app-workbench-page-lHi21M1T.js +0 -1
  218. package/dist/gateway/static/root/assets/logs-page-CH7W-dm5.js +0 -2
  219. package/dist/gateway/static/root/assets/management-settings-DVgI_KNm.js +0 -1
  220. package/dist/gateway/static/root/assets/markdown-view-DDJlD5jR.js +0 -201
  221. package/dist/gateway/static/root/assets/messages-pGa2qMzG.js +0 -3
  222. package/dist/gateway/static/root/assets/models-hub-cache-DzFiL4xV.js +0 -1
  223. package/dist/gateway/static/root/assets/note-detail-panel-kyX-n1db.js +0 -5
  224. package/dist/gateway/static/root/assets/notes-page-CLZygZlm.js +0 -8
  225. package/dist/gateway/static/root/assets/personal-page-DnXlcJNJ.js +0 -1
  226. package/dist/gateway/static/root/assets/product-open-page-D7pknlCh.js +0 -1
  227. package/dist/gateway/static/root/assets/project-detail-page-DhV9DPj8.js +0 -1
  228. package/dist/gateway/static/root/assets/projects-page-D181xkFw.js +0 -1
  229. package/dist/gateway/static/root/assets/remote-access-hub-CQnBARQW.js +0 -1
  230. package/dist/gateway/static/root/assets/scenes-page-DWt54veq.js +0 -2
  231. package/dist/gateway/static/root/assets/session-manager-BDpdi3lF.js +0 -16
  232. package/dist/gateway/static/root/assets/sessions-page-DPEdjUdR.js +0 -1
  233. package/dist/gateway/static/root/assets/settings-advanced-gate-B6WGnTLY.js +0 -1
  234. package/dist/gateway/static/root/assets/setup-status-panel-C7sLy8Hl.js +0 -1
  235. package/dist/gateway/static/root/assets/skills-page-TsrjLYcI.js +0 -2
  236. package/dist/gateway/static/root/assets/task-detail-page-B4Lby289.js +0 -2
  237. package/dist/gateway/static/root/assets/use-composer-attachments-Dlm9EFTO.js +0 -2
  238. package/dist/gateway/static/root/assets/user-model-page-CTkCLRhE.js +0 -2
  239. package/dist/gateway/static/root/assets/workflows-page-Csk8xrRk.js +0 -6
  240. package/dist/gateway/static/root/assets/workspace-api-B9M9ECTB.js +0 -2
  241. package/dist/src/agent/image/generation/normalization.d.ts +0 -38
  242. package/dist/src/agent/image/generation/normalization.js +0 -181
  243. package/dist/src/agent/image/generation/providers/dashscope.d.ts +0 -35
  244. package/dist/src/agent/image/generation/providers/dashscope.js +0 -257
  245. package/dist/src/agent/image/generation/providers/fal.d.ts +0 -15
  246. package/dist/src/agent/image/generation/providers/fal.js +0 -323
  247. package/dist/src/agent/image/generation/providers/google.d.ts +0 -16
  248. package/dist/src/agent/image/generation/providers/google.js +0 -244
  249. package/dist/src/agent/image/generation/providers/minimax.d.ts +0 -23
  250. package/dist/src/agent/image/generation/providers/minimax.js +0 -215
  251. package/dist/src/agent/image/generation/providers/openai.d.ts +0 -5
  252. package/dist/src/agent/image/generation/providers/openai.js +0 -134
@@ -0,0 +1,403 @@
1
+ import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
2
+ import { PersonalFeedbackSchema, PersonalProactivitySettingsSchema, PersonalStrategyRollbackSchema } from "../../../packages/gateway-contract/src/personal-proactivity.js";
3
+ import { init_src } from "../../../packages/gateway-contract/src/index.js";
4
+ import { createContextEvidence, init_context_evidence_repository } from "../../storage/sqlite/context-evidence-repository.js";
5
+ import { init_session_instance_repository, readCurrentTranscriptId } from "../../storage/sqlite/session-instance-repository.js";
6
+ import { getUserProfileSnapshot } from "../../user-model/profile.js";
7
+ import { getPersonalAgentByConversation } from "../repository.js";
8
+ import { DurableState } from "../../storage/sqlite/durable-state.js";
9
+ import { isExplicitFollowUp, requestedCheckTime } from "./follow-up-request.js";
10
+ import { createHash, randomUUID } from "node:crypto";
11
+ //#region src/personal-agent/proactivity/repository.ts
12
+ init_src();
13
+ init_context_evidence_repository();
14
+ init_transaction();
15
+ init_session_instance_repository();
16
+ function getProactivitySettings(ownerId) {
17
+ const saved = new DurableState("personal-proactivity", ownerId).get("settings");
18
+ const timezone = getUserProfileSnapshot().timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
19
+ return PersonalProactivitySettingsSchema.parse(saved ?? { timezone });
20
+ }
21
+ function patchProactivitySettings(ownerId, input) {
22
+ return runSqliteWriteTransaction(() => {
23
+ const current = getProactivitySettings(ownerId);
24
+ if (input.revision !== current.revision) throw new Error("Proactivity settings changed");
25
+ const next = PersonalProactivitySettingsSchema.parse({
26
+ ...input,
27
+ revision: current.revision + 1
28
+ });
29
+ new DurableState("personal-proactivity", ownerId).set("settings", next);
30
+ return next;
31
+ });
32
+ }
33
+ function localDay(now, timezone) {
34
+ return new Intl.DateTimeFormat("en-CA", {
35
+ timeZone: timezone,
36
+ year: "numeric",
37
+ month: "2-digit",
38
+ day: "2-digit"
39
+ }).format(now);
40
+ }
41
+ function isQuiet(now, settings) {
42
+ const hour = Number(new Intl.DateTimeFormat("en-GB", {
43
+ timeZone: settings.timezone,
44
+ hour: "2-digit",
45
+ hourCycle: "h23"
46
+ }).format(now));
47
+ const { quietStart: start, quietEnd: end } = settings;
48
+ return start === end ? false : start < end ? hour >= start && hour < end : hour >= start || hour < end;
49
+ }
50
+ function reserveModelCall(ownerId, now) {
51
+ return runSqliteWriteTransaction(() => {
52
+ const settings = getProactivitySettings(ownerId);
53
+ const state = new DurableState("personal-proactivity-budget", ownerId);
54
+ const key = localDay(now, settings.timezone);
55
+ const calls = state.get(key) ?? 0;
56
+ if (calls >= settings.dailyModelCalls) return false;
57
+ state.set(key, calls + 1);
58
+ for (const [old] of state.entries()) if (old !== key) state.delete(old);
59
+ return true;
60
+ });
61
+ }
62
+ function getAttention(id, ownerId) {
63
+ const row = getSqliteDatabase().prepare("SELECT * FROM personal_attention_threads WHERE id = ?").get(id);
64
+ return row && (!ownerId || row.owner_id === ownerId) ? row : void 0;
65
+ }
66
+ function listAttention(conversationId) {
67
+ return getSqliteDatabase().prepare("SELECT * FROM personal_attention_threads WHERE conversation_id = ? ORDER BY updated_at DESC LIMIT 30").all(conversationId);
68
+ }
69
+ function getAttentionSources(threadId, entryIds) {
70
+ if (entryIds && (!entryIds.length || entryIds.length > 12)) return [];
71
+ return getSqliteDatabase().prepare(`SELECT s.entry_id, s.transcript_id, s.conversation_id, t.payload_json, e.processing_policy
72
+ FROM personal_attention_sources s JOIN transcript_entries t ON t.entry_id = s.entry_id
73
+ JOIN context_evidence e ON e.evidence_id = s.evidence_id
74
+ JOIN sessions c ON c.conversation_id = s.conversation_id
75
+ WHERE s.thread_id = ? AND c.active_transcript_id = s.transcript_id AND t.role = 'user'
76
+ AND COALESCE(json_extract(t.payload_json, '$.metadata.hiddenFromClient'), 0) = 0
77
+ ${entryIds ? `AND s.entry_id IN (${entryIds.map(() => "?").join(",")})` : ""} ORDER BY t.seq DESC LIMIT 12`).all(threadId, ...entryIds ?? []).map((row) => ({
78
+ entryId: row.entry_id,
79
+ transcriptId: row.transcript_id,
80
+ conversationId: row.conversation_id,
81
+ excerpt: userText(JSON.parse(row.payload_json)).slice(0, 600),
82
+ processingPolicy: row.processing_policy,
83
+ version: createHash("sha256").update(row.payload_json).digest("hex")
84
+ }));
85
+ }
86
+ function userText(payload) {
87
+ if (typeof payload.content === "string") return payload.content;
88
+ return Array.isArray(payload.content) ? payload.content.map((part) => part?.type === "text" ? part.text : "").join("\n") : "";
89
+ }
90
+ function sourceFingerprint(sources) {
91
+ return createHash("sha256").update(JSON.stringify(sources)).digest("hex");
92
+ }
93
+ /** Only user transcript rows can establish attention; inferred attention never grants work authorization. */
94
+ function saveAttention(input, now = Date.now()) {
95
+ return runSqliteWriteTransaction((db) => {
96
+ const personal = getPersonalAgentByConversation(input.conversationId);
97
+ if (!personal || personal.state !== "ready") throw new Error("Personal Agent is unavailable");
98
+ const transcriptId = readCurrentTranscriptId(db, input.conversationId);
99
+ const subject = input.subject.trim().slice(0, 160);
100
+ if (!subject || !input.entryIds.length || input.entryIds.length > 12) throw new Error("Attention needs user evidence");
101
+ const sources = [...new Set(input.entryIds)].map((id) => {
102
+ const row = db.prepare("SELECT payload_json, created_at FROM transcript_entries WHERE entry_id = ? AND transcript_id = ? AND role = 'user' AND COALESCE(json_extract(payload_json, '$.metadata.hiddenFromClient'), 0) = 0").get(id, transcriptId);
103
+ if (!row) throw new Error("Attention source is unavailable");
104
+ const text = userText(JSON.parse(row.payload_json));
105
+ if (!text.trim()) throw new Error("Attention source is empty");
106
+ return {
107
+ id,
108
+ text,
109
+ observedAt: row.created_at
110
+ };
111
+ });
112
+ const explicitSource = sources.filter((source) => isExplicitFollowUp(source.text)).sort((a, b) => b.observedAt - a.observedAt)[0];
113
+ const explicit = input.explicit && Boolean(explicitSource);
114
+ if (input.explicit && !explicit) throw new Error("Follow-up requires an explicit user request");
115
+ if (!Number.isFinite(input.nextCheckAt)) throw new Error("Invalid attention time");
116
+ const existing = db.prepare("SELECT * FROM personal_attention_threads WHERE conversation_id = ? AND subject = ? COLLATE NOCASE LIMIT 1").get(input.conversationId, subject);
117
+ if (existing && [
118
+ "completed",
119
+ "expired",
120
+ "paused"
121
+ ].includes(existing.status)) return existing;
122
+ const id = existing?.id ?? randomUUID();
123
+ const settings = getProactivitySettings(personal.ownerId);
124
+ if (input.kind === "interest" && existing?.authority === "user_explicit") return existing;
125
+ const kind = existing && !(existing.kind === "interest" && explicit) ? existing.kind : input.kind;
126
+ if (kind === "interest" && (explicit || sources.some((source) => isExplicitFollowUp(source.text)))) throw new Error("Follow-up requests are not interest evidence");
127
+ const authority = existing?.authority === "user_explicit" || explicit ? "user_explicit" : "inferred";
128
+ const normalize = (text) => text.slice(0, 600).trim().replace(/\s+/g, " ").toLocaleLowerCase();
129
+ const oldCount = existing ? getAttentionSources(id).map((source) => normalize(source.excerpt)) : [];
130
+ const count = new Set([...oldCount, ...sources.map((source) => normalize(source.text))]).size;
131
+ if (kind === "interest") {
132
+ const evidence = interestSupport([...existing ? interestSources(existing.id) : [], ...sources.map((source) => ({
133
+ entryId: source.id,
134
+ excerpt: source.text,
135
+ observedAt: source.observedAt
136
+ }))], settings.timezone, now);
137
+ if (evidence.independentStatements < 2 || evidence.independentDays < 2) throw new Error("Interest needs independent user evidence across days");
138
+ }
139
+ const status = kind === "interest" ? "candidate" : authority === "user_explicit" || settings.mode === "balanced" && count >= 2 ? "active" : "candidate";
140
+ if (input.taskId && !db.prepare(`SELECT 1 FROM task_origin_links WHERE task_id = ? AND conversation_id = ?`).get(input.taskId, input.conversationId)) throw new Error("Task is not linked to this conversation");
141
+ if (input.projectId && !db.prepare("SELECT 1 FROM sessions WHERE conversation_id = ? AND project_id = ?").get(input.conversationId, input.projectId)) throw new Error("Project is not linked to this conversation");
142
+ const requestedAt = explicit && explicitSource ? requestedCheckTime(explicitSource.text, explicitSource.observedAt, settings.timezone) : void 0;
143
+ const nextAt = Math.max(now + 6e4, Math.min(requestedAt ?? input.nextCheckAt, now + 30 * 864e5));
144
+ const observedAt = Math.min(now, Math.max(...sources.map((source) => source.observedAt), existing?.last_meaningful_at ?? 0));
145
+ const expiresAt = observedAt + 30 * 864e5;
146
+ if (existing) db.prepare(`UPDATE personal_attention_threads SET summary = ?, authority = ?, status = ?, kind = ?,
147
+ task_id = COALESCE(?, task_id), project_id = COALESCE(?, project_id),
148
+ next_check_at = ?, expires_at = ?, last_meaningful_at = ?, revision = revision + 1, updated_at = ? WHERE id = ?`).run(input.summary.slice(0, 1600), authority, status, kind, input.taskId ?? null, input.projectId ?? null, kind === "interest" ? null : Math.min(nextAt, expiresAt), expiresAt, observedAt, now, id);
149
+ else db.prepare(`INSERT INTO personal_attention_threads
150
+ (id, owner_id, agent_id, conversation_id, subject, summary, kind, status, authority, task_id, project_id,
151
+ next_check_at, expires_at, last_meaningful_at, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(id, personal.ownerId, personal.agentId, input.conversationId, subject, input.summary.slice(0, 1600), kind, status, authority, input.taskId ?? null, input.projectId ?? null, kind === "interest" ? null : Math.min(nextAt, expiresAt), expiresAt, observedAt, now, now);
152
+ for (const source of sources) {
153
+ const evidence = createContextEvidence({
154
+ sourceType: "conversation",
155
+ sourceRef: `personal-attention:${source.id}`,
156
+ conversationId: input.conversationId,
157
+ messageId: source.id,
158
+ trustLevel: "owner",
159
+ observedAt: source.observedAt
160
+ });
161
+ db.prepare("INSERT OR IGNORE INTO personal_attention_sources(thread_id,evidence_id,entry_id,transcript_id,conversation_id) VALUES (?,?,?,?,?)").run(id, evidence.id, source.id, transcriptId, input.conversationId);
162
+ }
163
+ return getAttention(id);
164
+ });
165
+ }
166
+ function patchAttention(ownerId, id, revision, patch, now = Date.now()) {
167
+ return runSqliteWriteTransaction((db) => {
168
+ const current = getAttention(id, ownerId);
169
+ if (!current) throw new Error("Attention is unavailable");
170
+ if (current.revision !== revision) throw new Error("Attention changed");
171
+ const status = patch.status ?? current.status;
172
+ if (current.kind === "interest" && current.authority === "inferred" && ["active", "paused"].includes(status)) throw new Error("Interest discovery is silent; explicit follow-up is required");
173
+ db.prepare(`UPDATE personal_attention_threads SET status = ?, next_check_at = ?, pause_until = ?, revision = revision + 1, updated_at = ? WHERE id = ?`).run(status, patch.nextCheckAt === void 0 ? current.next_check_at : patch.nextCheckAt, status === "paused" ? patch.nextCheckAt ?? null : null, now, id);
174
+ db.prepare("UPDATE personal_wakeups SET status = 'cancelled' WHERE thread_id = ? AND status IN ('pending','evaluating')").run(id);
175
+ db.prepare("UPDATE personal_outreach SET state = 'cancelled' WHERE thread_id = ? AND state = 'ready'").run(id);
176
+ return getAttention(id);
177
+ });
178
+ }
179
+ function enqueueWakeup(thread, kind, identity, now = Date.now()) {
180
+ getSqliteDatabase().prepare(`INSERT OR IGNORE INTO personal_wakeups
181
+ (id,thread_id,dedupe_key,trigger_kind,source_event_id,thread_revision,not_before,expires_at,created_at) VALUES (?,?,?,?,?,?,?,?,?)`).run(randomUUID(), thread.id, `${thread.id}:${identity}`, kind, kind === "change" ? identity : null, thread.revision, now, Math.min(thread.expires_at, now + 864e5), now);
182
+ }
183
+ function enqueueDue(now = Date.now()) {
184
+ runSqliteWriteTransaction((db) => {
185
+ db.prepare("UPDATE personal_attention_threads SET status = 'expired', revision = revision + 1 WHERE expires_at <= ? AND status IN ('candidate','active','paused')").run(now);
186
+ db.prepare("UPDATE personal_attention_threads SET status = 'active', pause_until = NULL, revision = revision + 1 WHERE status = 'paused' AND pause_until <= ? AND expires_at > ?").run(now, now);
187
+ db.prepare(`UPDATE personal_attention_threads SET revision = revision + 1, next_check_at = ?
188
+ WHERE status = 'active' AND next_check_at <= ? AND EXISTS
189
+ (SELECT 1 FROM personal_wakeups w WHERE w.thread_id = personal_attention_threads.id
190
+ AND w.thread_revision = personal_attention_threads.revision AND w.expires_at <= ?
191
+ AND w.status IN ('pending','evaluating','cancelled','dead_letter'))`).run(now, now, now);
192
+ const threads = db.prepare("SELECT * FROM personal_attention_threads WHERE status = 'active' AND next_check_at <= ? ORDER BY next_check_at LIMIT 30").all(now);
193
+ for (const thread of threads) enqueueWakeup(thread, thread.authority === "user_explicit" ? "follow_up" : "discussion", `due:${thread.revision}:${thread.next_check_at}`, now);
194
+ db.prepare("UPDATE personal_wakeups SET status = 'cancelled' WHERE expires_at <= ? AND status IN ('pending','evaluating')").run(now);
195
+ });
196
+ }
197
+ function getOutreach(id, ownerId) {
198
+ return getSqliteDatabase().prepare(`SELECT o.* FROM personal_outreach o JOIN personal_attention_threads t ON t.id = o.thread_id
199
+ WHERE o.id = ? AND (? IS NULL OR t.owner_id = ?)`).get(id, ownerId ?? null, ownerId ?? null);
200
+ }
201
+ function provenanceDetail(ownerId, id) {
202
+ const outreach = getOutreach(id, ownerId);
203
+ if (!outreach || outreach.state !== "published") return void 0;
204
+ const thread = getAttention(outreach.thread_id, ownerId);
205
+ const snapshot = JSON.parse(outreach.provenance_json);
206
+ const currentSources = getAttentionSources(thread.id, snapshot.sourceIds);
207
+ const sources = sourceFingerprint(currentSources) === snapshot.fingerprint ? currentSources : [];
208
+ return {
209
+ provenance: snapshot.display,
210
+ thread: {
211
+ id: thread.id,
212
+ subject: sources.length ? thread.subject : "",
213
+ status: thread.status,
214
+ revision: thread.revision,
215
+ nextCheckAt: thread.next_check_at
216
+ },
217
+ whyNow: sources.length ? outreach.reason : "",
218
+ sourcesAvailable: sources.length > 0,
219
+ sources: sources.map(({ processingPolicy: _policy, version: _version, ...source }) => source),
220
+ strategy: strategyState(thread.id)
221
+ };
222
+ }
223
+ function recordFeedback(ownerId, id, raw, now = Date.now()) {
224
+ const input = PersonalFeedbackSchema.parse(raw);
225
+ runSqliteWriteTransaction((db) => {
226
+ const outreach = getOutreach(id, ownerId);
227
+ if (!outreach || outreach.state !== "published") throw new Error("Message is unavailable");
228
+ const previous = db.prepare("SELECT outreach_id, payload_json FROM personal_feedback WHERE owner_id = ? AND dedupe_key = ?").get(ownerId, input.idempotencyKey);
229
+ if (previous) {
230
+ if (previous.outreach_id !== id || previous.payload_json !== JSON.stringify(input)) throw new Error("Feedback key was already used");
231
+ return;
232
+ }
233
+ if (input.until && (input.until <= now || input.until > now + 30 * 864e5)) throw new Error("Invalid defer time");
234
+ const feedbackId = randomUUID();
235
+ db.prepare("INSERT INTO personal_feedback(id,outreach_id,thread_id,owner_id,kind,scope,payload_json,created_at,dedupe_key) VALUES (?,?,?,?,?,?,?,?,?)").run(feedbackId, id, outreach.thread_id, ownerId, input.kind, input.scope, JSON.stringify(input), now, input.idempotencyKey);
236
+ const thread = getAttention(outreach.thread_id, ownerId);
237
+ if ([
238
+ "stop",
239
+ "defer",
240
+ "adjust"
241
+ ].includes(input.kind) && input.scope === "thread") applyThreadFeedback(ownerId, thread.id, thread.revision, input, { feedbackId }, now);
242
+ });
243
+ }
244
+ function interestSources(threadId) {
245
+ return getAttentionSources(threadId).map((source) => ({
246
+ entryId: source.entryId,
247
+ excerpt: source.excerpt,
248
+ observedAt: Number(getSqliteDatabase().prepare("SELECT created_at FROM transcript_entries WHERE entry_id = ?").get(source.entryId).created_at)
249
+ }));
250
+ }
251
+ function interestSupport(sources, timezone, now) {
252
+ const independent = /* @__PURE__ */ new Map();
253
+ for (const source of sources) {
254
+ if (source.observedAt < now - 30 * 864e5 || source.observedAt > now) continue;
255
+ const normalized = source.excerpt.replace(/^\[[^\]]+\]\s*/u, "").slice(0, 500).trim().replace(/\s+/gu, " ").toLocaleLowerCase();
256
+ if (normalized && (!independent.has(normalized) || independent.get(normalized).observedAt < source.observedAt)) independent.set(normalized, source);
257
+ }
258
+ const independentStatements = independent.size;
259
+ const independentDays = new Set([...independent.values()].map((source) => localDay(source.observedAt, timezone))).size;
260
+ return {
261
+ independentStatements,
262
+ independentDays,
263
+ confidence: independentStatements === 0 ? 0 : Math.min(.85, Math.round((.25 + independentStatements * .08 + independentDays * .04) * 100) / 100)
264
+ };
265
+ }
266
+ function listInterestCandidates(conversationId, now = Date.now()) {
267
+ const personal = getPersonalAgentByConversation(conversationId);
268
+ if (!personal) return [];
269
+ const timezone = getProactivitySettings(personal.ownerId).timezone;
270
+ return listAttention(conversationId).filter((thread) => thread.kind === "interest").map((thread) => {
271
+ const sources = interestSources(thread.id);
272
+ return {
273
+ id: thread.id,
274
+ subject: thread.subject,
275
+ summary: thread.summary,
276
+ status: thread.expires_at <= now && thread.status === "candidate" ? "expired" : thread.status,
277
+ ...interestSupport(sources, timezone, now),
278
+ lastSupportedAt: thread.last_meaningful_at,
279
+ expiresAt: thread.expires_at,
280
+ sources: sources.map((source) => ({
281
+ ...source,
282
+ excerpt: source.excerpt.slice(0, 600)
283
+ }))
284
+ };
285
+ }).filter((candidate) => candidate.sources.length > 0);
286
+ }
287
+ function latestStrategy(threadId) {
288
+ return getSqliteDatabase().prepare("SELECT * FROM personal_strategy_versions WHERE thread_id = ? ORDER BY revision DESC LIMIT 1").get(threadId);
289
+ }
290
+ function preparationStrategy(threadId, now = Date.now()) {
291
+ const latest = latestStrategy(threadId);
292
+ if (latest) {
293
+ const preparation = JSON.parse(latest.after_json).preparation;
294
+ return preparation && preparation.reviewAt > now ? preparation.value : null;
295
+ }
296
+ return getSqliteDatabase().prepare("SELECT value FROM personal_adaptive_strategies WHERE thread_id = ? AND review_at > ? ORDER BY created_at DESC, rowid DESC LIMIT 1").get(threadId, now)?.value ?? null;
297
+ }
298
+ function strategyState(threadId, now = Date.now()) {
299
+ const versions = getSqliteDatabase().prepare("SELECT * FROM personal_strategy_versions WHERE thread_id = ? ORDER BY revision DESC LIMIT 5").all(threadId);
300
+ return {
301
+ preparation: preparationStrategy(threadId, now),
302
+ versions: versions.map((version) => ({
303
+ id: version.id,
304
+ revision: version.revision,
305
+ kind: version.kind,
306
+ createdAt: version.created_at,
307
+ preparation: JSON.parse(version.after_json).preparation?.value ?? null
308
+ }))
309
+ };
310
+ }
311
+ function strategySnapshot(thread, now) {
312
+ const latest = latestStrategy(thread.id);
313
+ const legacy = getSqliteDatabase().prepare("SELECT value,review_at FROM personal_adaptive_strategies WHERE thread_id = ? AND review_at > ? ORDER BY created_at DESC, rowid DESC LIMIT 1").get(thread.id, now);
314
+ const preparation = latest ? JSON.parse(latest.after_json).preparation : legacy ? {
315
+ value: legacy.value,
316
+ reviewAt: Number(legacy.review_at)
317
+ } : null;
318
+ return {
319
+ status: thread.status,
320
+ nextCheckAt: thread.next_check_at,
321
+ pauseUntil: thread.pause_until,
322
+ preparation: preparation && preparation.reviewAt > now ? preparation : null
323
+ };
324
+ }
325
+ function existingStrategyOperation(ownerId, key, input) {
326
+ const existing = getSqliteDatabase().prepare("SELECT * FROM personal_strategy_versions WHERE owner_id = ? AND dedupe_key = ?").get(ownerId, key);
327
+ if (existing && existing.input_json !== input) throw new Error("Strategy key was already used");
328
+ return existing;
329
+ }
330
+ function applyThreadFeedback(ownerId, threadId, revision, raw, source = {}, now = Date.now()) {
331
+ const input = PersonalFeedbackSchema.parse(raw);
332
+ if (input.scope !== "thread" || ![
333
+ "stop",
334
+ "defer",
335
+ "adjust"
336
+ ].includes(input.kind)) throw new Error("A lasting strategy requires explicit thread feedback");
337
+ return runSqliteWriteTransaction((db) => {
338
+ const operation = JSON.stringify({
339
+ threadId,
340
+ input
341
+ });
342
+ const key = `feedback:${input.idempotencyKey}`;
343
+ if (existingStrategyOperation(ownerId, key, operation)) return getAttention(threadId, ownerId);
344
+ const thread = getAttention(threadId, ownerId);
345
+ if (!thread || thread.revision !== revision) throw new Error("Attention changed");
346
+ if (input.kind !== "stop" && ["completed", "expired"].includes(thread.status)) throw new Error("Attention has ended");
347
+ if (input.until && (input.until <= now || input.until > now + 30 * 864e5)) throw new Error("Invalid defer time");
348
+ const before = strategySnapshot(thread, now);
349
+ const next = patchAttention(ownerId, threadId, revision, input.kind === "stop" ? { status: "completed" } : input.kind === "defer" ? {
350
+ status: "paused",
351
+ nextCheckAt: input.until
352
+ } : {}, now);
353
+ const after = strategySnapshot(next, now);
354
+ if (input.kind === "adjust") {
355
+ after.preparation = {
356
+ value: input.preparation,
357
+ reviewAt: now + 30 * 864e5
358
+ };
359
+ if (source.feedbackId) db.prepare("INSERT INTO personal_adaptive_strategies(id,thread_id,feedback_id,dimension,value,authority,revision,created_at,review_at) VALUES (?,?,?,?,?,?,?,?,?)").run(randomUUID(), threadId, source.feedbackId, "preparation", input.preparation, "explicit", next.revision, now, after.preparation.reviewAt);
360
+ }
361
+ db.prepare(`INSERT INTO personal_strategy_versions(id,owner_id,thread_id,revision,kind,before_json,after_json,input_json,source_entry_id,feedback_id,dedupe_key,created_at)
362
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`).run(randomUUID(), ownerId, threadId, next.revision, input.kind, JSON.stringify(before), JSON.stringify(after), operation, source.entryId ?? null, source.feedbackId ?? null, key, now);
363
+ return next;
364
+ });
365
+ }
366
+ function rollbackStrategy(ownerId, threadId, raw, sourceEntryId, now = Date.now()) {
367
+ const input = PersonalStrategyRollbackSchema.parse(raw);
368
+ return runSqliteWriteTransaction((db) => {
369
+ const operation = JSON.stringify({
370
+ threadId,
371
+ input
372
+ });
373
+ const key = `rollback:${input.idempotencyKey}`;
374
+ if (existingStrategyOperation(ownerId, key, operation)) return getAttention(threadId, ownerId);
375
+ const thread = getAttention(threadId, ownerId);
376
+ const version = latestStrategy(threadId);
377
+ if (!thread || thread.revision !== input.revision || !version || version.id !== input.versionId) throw new Error("Strategy changed; reload before undoing");
378
+ const before = strategySnapshot(thread, now);
379
+ const previous = JSON.parse(version.before_json);
380
+ const applied = JSON.parse(version.after_json);
381
+ const schedulingChanged = previous.status !== applied.status || previous.nextCheckAt !== applied.nextCheckAt || previous.pauseUntil !== applied.pauseUntil;
382
+ if (schedulingChanged && (before.status !== applied.status || before.nextCheckAt !== applied.nextCheckAt || before.pauseUntil !== applied.pauseUntil)) throw new Error("Strategy changed; newer scheduling must be preserved");
383
+ const restored = {
384
+ ...schedulingChanged ? previous : before,
385
+ preparation: previous.preparation
386
+ };
387
+ if (thread.expires_at <= now || !getAttentionSources(threadId).length) throw new Error("Attention sources have expired");
388
+ const next = patchAttention(ownerId, threadId, thread.revision, schedulingChanged ? {
389
+ status: restored.status === "paused" && restored.pauseUntil !== null && restored.pauseUntil <= now ? "active" : restored.status,
390
+ nextCheckAt: restored.nextCheckAt === null ? null : Math.max(now + 6e4, restored.nextCheckAt)
391
+ } : {}, now);
392
+ db.prepare(`INSERT INTO personal_strategy_versions(id,owner_id,thread_id,revision,kind,before_json,after_json,input_json,source_entry_id,restored_version_id,dedupe_key,created_at)
393
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`).run(randomUUID(), ownerId, threadId, next.revision, "rollback", JSON.stringify(before), JSON.stringify({
394
+ ...restored,
395
+ status: next.status,
396
+ nextCheckAt: next.next_check_at,
397
+ pauseUntil: next.pause_until
398
+ }), operation, sourceEntryId ?? null, version.id, key, now);
399
+ return next;
400
+ });
401
+ }
402
+ //#endregion
403
+ export { applyThreadFeedback, enqueueDue, enqueueWakeup, getAttention, getAttentionSources, getOutreach, getProactivitySettings, isQuiet, listAttention, listInterestCandidates, localDay, patchAttention, patchProactivitySettings, preparationStrategy, provenanceDetail, recordFeedback, reserveModelCall, rollbackStrategy, saveAttention, sourceFingerprint, strategyState, userText };
@@ -0,0 +1,3 @@
1
+ import type { Context, Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from '../../gateway/hono/routes/deps.js';
3
+ export declare function registerProactivityRoutes(app: Hono, deps: AuthenticatedRouteDeps, owner: (context: Context) => string | null): void;
@@ -0,0 +1,182 @@
1
+ import { PersonalFeedbackSchema, PersonalProactivitySettingsSchema, PersonalStrategyRollbackSchema } from "../../../packages/gateway-contract/src/personal-proactivity.js";
2
+ import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
+ import { resolveUserContextSessionAccess } from "../../user-context/access-policy.js";
4
+ import { getPersonalAgent } from "../repository.js";
5
+ import { getProactivitySettings, listInterestCandidates, patchAttention, patchProactivitySettings, provenanceDetail, recordFeedback, rollbackStrategy, strategyState } from "./repository.js";
6
+ import { z } from "zod";
7
+ //#region src/personal-agent/proactivity/routes.ts
8
+ init_src();
9
+ const AttentionPatch = z.object({
10
+ revision: z.number().int().positive(),
11
+ status: z.enum([
12
+ "active",
13
+ "paused",
14
+ "completed"
15
+ ]).optional(),
16
+ nextCheckAt: z.number().int().positive().optional()
17
+ }).strict();
18
+ const SettingsPatch = z.object({
19
+ revision: z.number().int().positive(),
20
+ mode: z.enum([
21
+ "off",
22
+ "follow_up",
23
+ "balanced"
24
+ ]).optional(),
25
+ timezone: z.string().max(100).optional(),
26
+ quietStart: z.number().int().min(0).max(23).optional(),
27
+ quietEnd: z.number().int().min(0).max(23).optional(),
28
+ dailyMessages: z.number().int().min(0).max(10).optional(),
29
+ dailyModelCalls: z.number().int().min(0).max(100).optional()
30
+ }).strict();
31
+ function registerProactivityRoutes(app, deps, owner) {
32
+ app.get("/api/personal-agent/proactivity", (c) => {
33
+ const ownerId = owner(c);
34
+ return ownerId ? c.json({
35
+ ok: true,
36
+ payload: getProactivitySettings(ownerId)
37
+ }) : c.json({
38
+ ok: false,
39
+ error: "Owner access is required"
40
+ }, 403);
41
+ });
42
+ app.get("/api/personal-agent/interests", (c) => {
43
+ const ownerId = owner(c);
44
+ if (!ownerId) return c.json({
45
+ ok: false,
46
+ error: "Owner access is required"
47
+ }, 403);
48
+ const personal = getPersonalAgent(ownerId);
49
+ if (!personal || !resolveUserContextSessionAccess(deps.service.currentConfig, personal.conversationId).userModel) return c.json({
50
+ ok: false,
51
+ error: "Interest access is unavailable"
52
+ }, 403);
53
+ return c.json({
54
+ ok: true,
55
+ payload: listInterestCandidates(personal.conversationId)
56
+ });
57
+ });
58
+ app.post("/api/personal-agent/attention/:threadId/strategy/rollback", deps.strictRateLimitMiddleware, async (c) => {
59
+ const ownerId = owner(c);
60
+ if (!ownerId) return c.json({
61
+ ok: false,
62
+ error: "Owner access is required"
63
+ }, 403);
64
+ const input = PersonalStrategyRollbackSchema.safeParse(await c.req.json().catch(() => null));
65
+ if (!input.success) return c.json({
66
+ ok: false,
67
+ error: "Invalid strategy rollback"
68
+ }, 400);
69
+ try {
70
+ const thread = rollbackStrategy(ownerId, c.req.param("threadId"), input.data);
71
+ return c.json({
72
+ ok: true,
73
+ payload: {
74
+ thread,
75
+ strategy: strategyState(thread.id)
76
+ }
77
+ });
78
+ } catch (error) {
79
+ return c.json({
80
+ ok: false,
81
+ error: error instanceof Error ? error.message : "Strategy changed"
82
+ }, 409);
83
+ }
84
+ });
85
+ app.patch("/api/personal-agent/proactivity", deps.strictRateLimitMiddleware, async (c) => {
86
+ const ownerId = owner(c);
87
+ if (!ownerId) return c.json({
88
+ ok: false,
89
+ error: "Owner access is required"
90
+ }, 403);
91
+ const input = SettingsPatch.safeParse(await c.req.json().catch(() => null));
92
+ if (!input.success) return c.json({
93
+ ok: false,
94
+ error: "Invalid proactivity settings"
95
+ }, 400);
96
+ const merged = PersonalProactivitySettingsSchema.safeParse({
97
+ ...getProactivitySettings(ownerId),
98
+ ...input.data
99
+ });
100
+ if (!merged.success) return c.json({
101
+ ok: false,
102
+ error: "Invalid proactivity settings"
103
+ }, 400);
104
+ try {
105
+ return c.json({
106
+ ok: true,
107
+ payload: patchProactivitySettings(ownerId, merged.data)
108
+ });
109
+ } catch {
110
+ return c.json({
111
+ ok: false,
112
+ error: "Settings changed; reload before saving"
113
+ }, 409);
114
+ }
115
+ });
116
+ app.get("/api/personal-agent/outreach/:outreachId/provenance", (c) => {
117
+ const ownerId = owner(c);
118
+ if (!ownerId) return c.json({
119
+ ok: false,
120
+ error: "Owner access is required"
121
+ }, 403);
122
+ const personal = getPersonalAgent(ownerId);
123
+ if (!personal || !resolveUserContextSessionAccess(deps.service.currentConfig, personal.conversationId).userModel) return c.json({
124
+ ok: false,
125
+ error: "Source access is unavailable"
126
+ }, 403);
127
+ const detail = provenanceDetail(ownerId, c.req.param("outreachId"));
128
+ return detail ? c.json({
129
+ ok: true,
130
+ payload: detail
131
+ }) : c.json({
132
+ ok: false,
133
+ error: "Message is unavailable"
134
+ }, 404);
135
+ });
136
+ app.post("/api/personal-agent/outreach/:outreachId/feedback", deps.strictRateLimitMiddleware, async (c) => {
137
+ const ownerId = owner(c);
138
+ if (!ownerId) return c.json({
139
+ ok: false,
140
+ error: "Owner access is required"
141
+ }, 403);
142
+ const input = PersonalFeedbackSchema.safeParse(await c.req.json().catch(() => null));
143
+ if (!input.success) return c.json({
144
+ ok: false,
145
+ error: "Invalid feedback"
146
+ }, 400);
147
+ try {
148
+ recordFeedback(ownerId, c.req.param("outreachId"), input.data);
149
+ return c.json({ ok: true });
150
+ } catch (error) {
151
+ return c.json({
152
+ ok: false,
153
+ error: error instanceof Error ? error.message : "Feedback failed"
154
+ }, 409);
155
+ }
156
+ });
157
+ app.patch("/api/personal-agent/attention/:threadId", deps.strictRateLimitMiddleware, async (c) => {
158
+ const ownerId = owner(c);
159
+ if (!ownerId) return c.json({
160
+ ok: false,
161
+ error: "Owner access is required"
162
+ }, 403);
163
+ const input = AttentionPatch.safeParse(await c.req.json().catch(() => null));
164
+ if (!input.success || input.data.nextCheckAt && (input.data.nextCheckAt <= Date.now() || input.data.nextCheckAt > Date.now() + 30 * 864e5)) return c.json({
165
+ ok: false,
166
+ error: "Invalid attention update"
167
+ }, 400);
168
+ try {
169
+ return c.json({
170
+ ok: true,
171
+ payload: patchAttention(ownerId, c.req.param("threadId"), input.data.revision, input.data)
172
+ });
173
+ } catch (error) {
174
+ return c.json({
175
+ ok: false,
176
+ error: error instanceof Error ? error.message : "Attention changed"
177
+ }, 409);
178
+ }
179
+ });
180
+ }
181
+ //#endregion
182
+ export { registerProactivityRoutes };
@@ -0,0 +1,32 @@
1
+ import type { Config } from '../../config/schema.js';
2
+ import type { AutomationEventEnvelope } from '../../automations/domain/types.js';
3
+ export interface ProactivityDeps {
4
+ getConfig: () => Config;
5
+ isAvailable: (conversationId: string) => boolean;
6
+ notify: (conversationId: string, outreachId: string) => void;
7
+ call?: (conversationId: string, operation: string, prompt: string, signal: AbortSignal) => Promise<string>;
8
+ now?: () => number;
9
+ }
10
+ export declare class PersonalProactivityService {
11
+ private readonly deps;
12
+ private running;
13
+ private stopped;
14
+ private controller?;
15
+ private readonly stopWaiters;
16
+ constructor(deps: ProactivityDeps);
17
+ private now;
18
+ private accessible;
19
+ private available;
20
+ private hasDeliveredTaskResult;
21
+ private call;
22
+ stop(): Promise<void>;
23
+ start(): void;
24
+ /** SQL-only admission; the bounded worker runs outside the scheduler transaction. */
25
+ tick(): void;
26
+ /** The durable automation projection retries this admission before acknowledging its event. */
27
+ ingestEvent(event: AutomationEventEnvelope): void;
28
+ drain(): Promise<void>;
29
+ private extract;
30
+ private evaluate;
31
+ private publish;
32
+ }