@xopcai/xopc 0.0.268 → 0.0.269

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 (207) 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-Bhyy6ENz.js → activity-store-DcwCSY6s.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B9WObxjr.js → agent-avatar-dicebear-D0NBOWC4.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-J1YFNG26.js → agent-defaults-settings-panel-qKCezlBg.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-BMhnZKhP.js +1 -0
  7. package/dist/gateway/static/root/assets/{api-B2y7ZjZk.js → api-eaPO-mdr.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-Bbn9mDfL.js → app-management-settings-panel-E3xm2teY.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-Deo5EsIc.js → appearance-settings-CiZOjgls.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-DduJDWGY.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-CxJTU8MU.js → archive-plugin-D09yo_Hc.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-C71Cukgp.js → attachment-load-CNYb8Qru.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-_J7UZ55Q.js → automations-page-DsrfW5ii.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-X7hNHCjW.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-CX8fC8Zt.js → binary-plugins-OWlaGqlY.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-Ci9fjoQL.js → block-editor-CVND3M6r.js} +3 -3
  17. package/dist/gateway/static/root/assets/{browser-automation-inputs-s5I78Iko.js → browser-automation-inputs-D7IzVK_J.js} +1 -1
  18. package/dist/gateway/static/root/assets/{browser-automations-page-rDSx0ozx.js → browser-automations-page-CQ6cCpIv.js} +2 -2
  19. package/dist/gateway/static/root/assets/browser-settings-page-BZ7nK_pN.js +8 -0
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-BfKvJO1C.js +7 -0
  21. package/dist/gateway/static/root/assets/channels-settings-D1UDxJuA.js +1 -0
  22. package/dist/gateway/static/root/assets/{channels-status-swr-_OsWr_vS.js → channels-status-swr-D4JrgJKa.js} +1 -1
  23. package/dist/gateway/static/root/assets/{chat-terminal-dock-DMSl8KxS.js → chat-terminal-dock-BUjnhT7C.js} +2 -2
  24. package/dist/gateway/static/root/assets/connectors-page-C2nuqs_O.js +2 -0
  25. package/dist/gateway/static/root/assets/{cron-expression-BByq6Uh8.js → cron-expression-DlyRIyUn.js} +1 -1
  26. package/dist/gateway/static/root/assets/{date-picker-m6JZCUEW.js → date-picker-CU-ij_yE.js} +1 -1
  27. package/dist/gateway/static/root/assets/{dependency-picker-CwCAjbaJ.js → dependency-picker-Z6Nf0Wjq.js} +1 -1
  28. package/dist/gateway/static/root/assets/{desktop-pet-DSmeEREd.js → desktop-pet-C0F5Iqnc.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-MfKceMoe.js → desktop-pet-settings-Bj_W6HL1.js} +1 -1
  30. package/dist/gateway/static/root/assets/{extension-debug-page-CwvWy26h.js → extension-debug-page-Ba09EnAn.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-page-DLrbVBHM.js → extension-page-C88aGXJs.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-settings-page-BI6C4PM-.js → extension-settings-page-CMyt0A32.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-config-swr-OObCK8jM.js → gateway-config-swr-bjzk_4hn.js} +1 -1
  34. package/dist/gateway/static/root/assets/gateway-settings-ogv8ZbvG.js +1 -0
  35. package/dist/gateway/static/root/assets/{gateway-startup-retry-D_TxKN_A.js → gateway-startup-retry-DrbIzFyB.js} +1 -1
  36. package/dist/gateway/static/root/assets/{heartbeat-settings-CUl832Tb.js → heartbeat-settings-BnrMRKaZ.js} +1 -1
  37. package/dist/gateway/static/root/assets/home-page-CbcJCREd.js +1 -0
  38. package/dist/gateway/static/root/assets/{image-generation-api-fPU9yGsw.js → image-generation-api-CBWU9Ner.js} +1 -1
  39. package/dist/gateway/static/root/assets/index-7PZ6jmhy.css +2 -0
  40. package/dist/gateway/static/root/assets/{index-wKE8Q2FX.js → index-CfyyA9-g.js} +47 -47
  41. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-r4DCS19O.js → keyboard-shortcuts-settings-B8Z7kKQY.js} +1 -1
  42. package/dist/gateway/static/root/assets/local-app-workbench-page-D5XVZnK1.js +2 -0
  43. package/dist/gateway/static/root/assets/{local-apps-page-DkfCRLUh.js → local-apps-page-CLSfzkRp.js} +1 -1
  44. package/dist/gateway/static/root/assets/{locale-store-DFQX9kTl.js → locale-store-BQ2HKTWb.js} +1 -1
  45. package/dist/gateway/static/root/assets/logs-page-CWDU1AGN.js +2 -0
  46. package/dist/gateway/static/root/assets/{management-settings-Cfx4ATTa.js → management-settings-CuFNgQUy.js} +1 -1
  47. package/dist/gateway/static/root/assets/{markdown-view-D-5jHRWg.js → markdown-view-DIcfrLmG.js} +1 -1
  48. package/dist/gateway/static/root/assets/{media-plugins-DOLjWd3y.js → media-plugins-CSv6-xTA.js} +1 -1
  49. package/dist/gateway/static/root/assets/{messages-Dj8QuS6e.js → messages-BRjoarIr.js} +2 -2
  50. package/dist/gateway/static/root/assets/{mobile-pairing-wizard-BGW9joAb.js → mobile-pairing-wizard-C7d_ztgp.js} +1 -1
  51. package/dist/gateway/static/root/assets/note-detail-panel-D5JuBLyt.js +5 -0
  52. package/dist/gateway/static/root/assets/notes-page-C5-ccCi4.js +8 -0
  53. package/dist/gateway/static/root/assets/{page-tabs-_SGXMT2O.js → page-tabs-BfV-PQa5.js} +1 -1
  54. package/dist/gateway/static/root/assets/{preview-open-alternatives-lVetfCWk.js → preview-open-alternatives-DQS7NFpg.js} +1 -1
  55. package/dist/gateway/static/root/assets/proactive-page-fHjPigmx.js +1 -0
  56. package/dist/gateway/static/root/assets/{product-open-page-CIGLPFm7.js → product-open-page-BIhjZLKg.js} +1 -1
  57. package/dist/gateway/static/root/assets/project-detail-page-6v_khvEt.js +1 -0
  58. package/dist/gateway/static/root/assets/projects-page-CCy1aK4V.js +1 -0
  59. package/dist/gateway/static/root/assets/{registry-api-CsZLatKo.js → registry-api-CwveUfe8.js} +1 -1
  60. package/dist/gateway/static/root/assets/remote-access-hub-pkqKRnch.js +1 -0
  61. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BDqVrUEj.js → runtime-tools-settings-panel-DMQ0wpNg.js} +2 -2
  62. package/dist/gateway/static/root/assets/{schema-form-8RQgFJJO.js → schema-form-C91g2PRU.js} +1 -1
  63. package/dist/gateway/static/root/assets/sessions-page-Cr4E4cap.js +1 -0
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-D1JRDRyL.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-form-section-j4UjGM-f.js → settings-form-section-Cem6L49Y.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-page-lMi50B_s.js → settings-page-afDUxqlV.js} +1 -1
  67. package/dist/gateway/static/root/assets/{setup-status-panel-Dx4Fy3rU.js → setup-status-panel-Cc_iP_vv.js} +1 -1
  68. package/dist/gateway/static/root/assets/{share-preview-page-aSyKRH5y.js → share-preview-page-CVEVHksg.js} +1 -1
  69. package/dist/gateway/static/root/assets/shares-settings-BrMECMAB.js +1 -0
  70. package/dist/gateway/static/root/assets/skill-reload-api-DuqIDYjc.js +1 -0
  71. package/dist/gateway/static/root/assets/{skills-page-C2_CAvxW.js → skills-page-CNrq1W6C.js} +1 -1
  72. package/dist/gateway/static/root/assets/{skills-page.utils-B00e4Q30.js → skills-page.utils-D1wGfm22.js} +1 -1
  73. package/dist/gateway/static/root/assets/{system-settings-panel-CulAkrsV.js → system-settings-panel-BLE8PxWE.js} +1 -1
  74. package/dist/gateway/static/root/assets/task-detail-page-m0oXUKl2.js +1 -0
  75. package/dist/gateway/static/root/assets/{theme-store-zRT6vaZc.js → theme-store-BejLVjIT.js} +1 -1
  76. package/dist/gateway/static/root/assets/{tunnel-api-C01xgCWR.js → tunnel-api-Dur80zSQ.js} +1 -1
  77. package/dist/gateway/static/root/assets/{use-autosave-DfSJ3c2p.js → use-autosave-DmgEA8Qb.js} +1 -1
  78. package/dist/gateway/static/root/assets/user-model-page-Dl10D_5q.js +2 -0
  79. package/dist/gateway/static/root/assets/{voice-api-key-field-9v-miN8o.js → voice-api-key-field-sZ0J83SF.js} +1 -1
  80. package/dist/gateway/static/root/assets/{voice-config-api-DpJEu2RQ.js → voice-config-api-BEbz3avx.js} +1 -1
  81. package/dist/gateway/static/root/assets/{work-discovery-overlay-CREYgh-1.js → work-discovery-overlay-BXnAlbmO.js} +1 -1
  82. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BkwFey0a.js +3 -0
  83. package/dist/gateway/static/root/assets/workflows-page-CswgoIFU.js +6 -0
  84. package/dist/gateway/static/root/index.html +10 -10
  85. package/dist/gateway/static/root/notification-sw.js +15 -0
  86. package/dist/package.js +1 -1
  87. package/dist/packages/gateway-contract/src/notifications.js +15 -1
  88. package/dist/packages/gateway-contract/src/proactive.js +104 -0
  89. package/dist/packages/realtime-protocol/src/voice.js +2 -1
  90. package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
  91. package/dist/src/agent/workflow/subagent-runner.js +2 -2
  92. package/dist/src/cli/commands/connectors.js +1 -1
  93. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  94. package/dist/src/connectors/connected-source-ingestion.js +1 -1
  95. package/dist/src/connectors/connection-recovery-service.js +1 -1
  96. package/dist/src/connectors/health.js +1 -1
  97. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  98. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  99. package/dist/src/gateway/hono/routes/index.js +0 -2
  100. package/dist/src/gateway/hono/routes/lazy-bundles.js +12 -0
  101. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  102. package/dist/src/gateway/hono/routes/proactive-control.d.ts +3 -0
  103. package/dist/src/gateway/hono/routes/proactive-control.js +161 -0
  104. package/dist/src/gateway/hono/routes/proactive.d.ts +1 -1
  105. package/dist/src/gateway/hono/routes/proactive.js +12 -5
  106. package/dist/src/gateway/hono/routes/voice.js +1 -1
  107. package/dist/src/gateway/security/gateway-scopes.js +5 -0
  108. package/dist/src/gateway/service.d.ts +0 -1
  109. package/dist/src/gateway/service.js +24 -26
  110. package/dist/src/notifications/planner.js +4 -3
  111. package/dist/src/notifications/proactive-channel.d.ts +8 -0
  112. package/dist/src/notifications/proactive-channel.js +57 -0
  113. package/dist/src/notifications/proactive-policy.d.ts +3 -0
  114. package/dist/src/notifications/proactive-policy.js +32 -0
  115. package/dist/src/notifications/service.d.ts +78 -0
  116. package/dist/src/notifications/service.js +71 -13
  117. package/dist/src/notifications/store.d.ts +2 -0
  118. package/dist/src/notifications/store.js +8 -1
  119. package/dist/src/notifications/web-push.d.ts +19 -0
  120. package/dist/src/notifications/web-push.js +182 -0
  121. package/dist/src/proactive/actions/service.js +10 -2
  122. package/dist/src/proactive/actions/workflow.d.ts +15 -0
  123. package/dist/src/proactive/actions/workflow.js +88 -0
  124. package/dist/src/proactive/execution/agent-executor.d.ts +5 -0
  125. package/dist/src/proactive/execution/agent-executor.js +21 -0
  126. package/dist/src/proactive/execution/authorization.d.ts +3 -0
  127. package/dist/src/proactive/execution/authorization.js +23 -0
  128. package/dist/src/proactive/execution/context.js +2 -11
  129. package/dist/src/proactive/execution/insight.d.ts +7 -0
  130. package/dist/src/proactive/execution/insight.js +33 -2
  131. package/dist/src/proactive/execution/repository.d.ts +2 -0
  132. package/dist/src/proactive/execution/repository.js +38 -4
  133. package/dist/src/proactive/execution/types.d.ts +5 -0
  134. package/dist/src/proactive/execution/worker.js +38 -7
  135. package/dist/src/proactive/inbox/cards.d.ts +21 -0
  136. package/dist/src/proactive/inbox/cards.js +237 -0
  137. package/dist/src/proactive/inbox/delivery.d.ts +6 -0
  138. package/dist/src/proactive/inbox/delivery.js +52 -0
  139. package/dist/src/proactive/inbox/digest.d.ts +8 -0
  140. package/dist/src/proactive/inbox/digest.js +112 -0
  141. package/dist/src/proactive/inbox/lifecycle.d.ts +4 -0
  142. package/dist/src/proactive/inbox/lifecycle.js +58 -0
  143. package/dist/src/proactive/inbox/notification-policy.d.ts +1 -0
  144. package/dist/src/proactive/inbox/notification-policy.js +20 -0
  145. package/dist/src/proactive/inbox/repository.d.ts +1 -0
  146. package/dist/src/proactive/inbox/repository.js +68 -11
  147. package/dist/src/proactive/inbox/types.d.ts +9 -1
  148. package/dist/src/proactive/inbox/worker.js +9 -3
  149. package/dist/src/proactive/index.js +1 -1
  150. package/dist/src/proactive/maintenance.js +7 -0
  151. package/dist/src/proactive/metrics.d.ts +10 -0
  152. package/dist/src/proactive/metrics.js +27 -0
  153. package/dist/src/proactive/policy/presence.d.ts +2 -0
  154. package/dist/src/proactive/policy/presence.js +27 -0
  155. package/dist/src/proactive/policy/service.d.ts +53 -0
  156. package/dist/src/proactive/policy/service.js +122 -0
  157. package/dist/src/proactive/routing/matcher.js +3 -2
  158. package/dist/src/proactive/scenarios/control.d.ts +90 -0
  159. package/dist/src/proactive/scenarios/control.js +109 -0
  160. package/dist/src/proactive/scenarios/preview.d.ts +13 -0
  161. package/dist/src/proactive/scenarios/preview.js +81 -0
  162. package/dist/src/proactive/scenarios/prompt-composer.js +2 -2
  163. package/dist/src/proactive/scenarios/repository.js +5 -1
  164. package/dist/src/proactive/temporal/schedule.d.ts +3 -0
  165. package/dist/src/proactive/temporal/schedule.js +67 -0
  166. package/dist/src/proactive/temporal/worker.js +8 -4
  167. package/dist/src/storage/sqlite/migrations/159_proactive_controls.sql +68 -0
  168. package/dist/src/storage/sqlite/migrations/160_proactive_web_push.sql +27 -0
  169. package/dist/src/storage/sqlite/migrations/161_proactive_delivery_and_lifecycle.sql +51 -0
  170. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  171. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  172. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  173. package/dist/src/storage/sqlite/schema.js +1 -1
  174. package/dist/src/tui/tui-startup-resources.js +1 -1
  175. package/dist/src/voice/realtime/runtime.d.ts +2 -1
  176. package/dist/src/voice/realtime/runtime.js +21 -5
  177. package/dist/src/workflows/domain/run.d.ts +1 -0
  178. package/dist/src/workflows/index.js +2 -2
  179. package/dist/src/workflows/service/workflow-run-service.d.ts +3 -0
  180. package/dist/src/workflows/service/workflow-run-service.js +26 -5
  181. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  182. package/package.json +6 -4
  183. package/dist/gateway/static/root/assets/agents-BJuTIRPD.js +0 -1
  184. package/dist/gateway/static/root/assets/apps-page-Cz4d7ErX.js +0 -1
  185. package/dist/gateway/static/root/assets/automations-workspace-Bn8nwUOL.js +0 -6
  186. package/dist/gateway/static/root/assets/browser-settings-page-B9RA6x4x.js +0 -8
  187. package/dist/gateway/static/root/assets/capabilities-settings-panel-C1GUih8m.js +0 -7
  188. package/dist/gateway/static/root/assets/channels-settings-CEhVLJNa.js +0 -1
  189. package/dist/gateway/static/root/assets/connectors-page-IQAQDSmO.js +0 -2
  190. package/dist/gateway/static/root/assets/gateway-settings-B3H7Vfbh.js +0 -1
  191. package/dist/gateway/static/root/assets/home-page-CT4JL2jm.js +0 -1
  192. package/dist/gateway/static/root/assets/index-CRJrO4GI.css +0 -2
  193. package/dist/gateway/static/root/assets/local-app-workbench-page-qwLuir8A.js +0 -2
  194. package/dist/gateway/static/root/assets/logs-page-DrNaaPWc.js +0 -2
  195. package/dist/gateway/static/root/assets/note-detail-panel-Dbj5OvXE.js +0 -5
  196. package/dist/gateway/static/root/assets/notes-page-5hRB3WXc.js +0 -8
  197. package/dist/gateway/static/root/assets/project-detail-page-CblWLA8k.js +0 -1
  198. package/dist/gateway/static/root/assets/projects-page-CGk-kzqs.js +0 -1
  199. package/dist/gateway/static/root/assets/remote-access-hub-Du8PweyU.js +0 -1
  200. package/dist/gateway/static/root/assets/sessions-page-BFm94dJC.js +0 -1
  201. package/dist/gateway/static/root/assets/settings-advanced-gate-C0H-cToA.js +0 -1
  202. package/dist/gateway/static/root/assets/shares-settings-CqF9s0pl.js +0 -1
  203. package/dist/gateway/static/root/assets/skill-reload-api-BBL_ZUSC.js +0 -1
  204. package/dist/gateway/static/root/assets/task-detail-page-D1FmRFIn.js +0 -1
  205. package/dist/gateway/static/root/assets/user-model-page-BGC_5baJ.js +0 -2
  206. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BfCWdw8F.js +0 -3
  207. package/dist/gateway/static/root/assets/workflows-page-CvmKQkD0.js +0 -6
@@ -0,0 +1,104 @@
1
+ import { z } from "zod";
2
+ //#region packages/gateway-contract/src/proactive.ts
3
+ const ProactiveLevelSchema = z.enum([
4
+ "off",
5
+ "quiet",
6
+ "balanced",
7
+ "active"
8
+ ]);
9
+ const ProactiveTimezoneSchema = z.string().min(1).max(100).refine((value) => {
10
+ try {
11
+ new Intl.DateTimeFormat("en", { timeZone: value });
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ }, "Invalid timezone");
17
+ const ProactivePreferencesSchema = z.object({
18
+ level: ProactiveLevelSchema.default("balanced"),
19
+ timezone: ProactiveTimezoneSchema.default("Asia/Shanghai"),
20
+ quietStartHour: z.number().int().min(0).max(23).default(22),
21
+ quietEndHour: z.number().int().min(0).max(23).default(8),
22
+ dailyNotificationLimit: z.number().int().min(0).max(30).default(3),
23
+ digestEnabled: z.boolean().default(false),
24
+ digestHour: z.number().int().min(0).max(23).default(18),
25
+ digestMinute: z.number().int().min(0).max(59).default(0),
26
+ preferredChannel: z.enum([
27
+ "all",
28
+ "auto",
29
+ "browser",
30
+ "mobile",
31
+ "telegram"
32
+ ]).default("all"),
33
+ suppressWhileViewing: z.boolean().default(true),
34
+ telegram: z.object({
35
+ chatId: z.string().regex(/^-?[0-9]{1,20}$/),
36
+ accountId: z.string().min(1).max(100).optional(),
37
+ publicUrl: z.url().refine((value) => {
38
+ const url = new URL(value);
39
+ return url.protocol === "https:" && !url.username && !url.password && !url.search && !url.hash;
40
+ }, "Use an HTTPS console URL without credentials or query parameters")
41
+ }).nullable().default(null),
42
+ pausedUntil: z.iso.datetime().nullable().default(null),
43
+ revision: z.number().int().nonnegative().default(0)
44
+ });
45
+ const ProactivePreferencesUpdateSchema = z.object({
46
+ level: ProactivePreferencesSchema.shape.level.removeDefault().optional(),
47
+ timezone: ProactivePreferencesSchema.shape.timezone.removeDefault().optional(),
48
+ quietStartHour: ProactivePreferencesSchema.shape.quietStartHour.removeDefault().optional(),
49
+ quietEndHour: ProactivePreferencesSchema.shape.quietEndHour.removeDefault().optional(),
50
+ dailyNotificationLimit: ProactivePreferencesSchema.shape.dailyNotificationLimit.removeDefault().optional(),
51
+ digestEnabled: ProactivePreferencesSchema.shape.digestEnabled.removeDefault().optional(),
52
+ digestHour: ProactivePreferencesSchema.shape.digestHour.removeDefault().optional(),
53
+ digestMinute: ProactivePreferencesSchema.shape.digestMinute.removeDefault().optional(),
54
+ preferredChannel: ProactivePreferencesSchema.shape.preferredChannel.removeDefault().optional(),
55
+ suppressWhileViewing: ProactivePreferencesSchema.shape.suppressWhileViewing.removeDefault().optional(),
56
+ telegram: ProactivePreferencesSchema.shape.telegram.removeDefault().optional(),
57
+ pausedUntil: ProactivePreferencesSchema.shape.pausedUntil.removeDefault().optional(),
58
+ expectedRevision: z.number().int().nonnegative()
59
+ }).strict();
60
+ const ProactiveSubscriptionSettingsSchema = z.object({
61
+ level: ProactiveLevelSchema.nullable().default(null),
62
+ delivery: z.enum([
63
+ "inbox",
64
+ "important",
65
+ "digest"
66
+ ]).default("important"),
67
+ preparationWorkflowId: z.string().min(1).max(160).nullable().default(null),
68
+ scanIntervalMinutes: z.number().int().min(15).max(10080).nullable().default(null),
69
+ userInstructions: z.string().max(12e3).default("")
70
+ });
71
+ const ProactiveSubscriptionCreateSchema = ProactiveSubscriptionSettingsSchema.extend({
72
+ scenarioKey: z.string().min(1).max(100),
73
+ scopeKind: z.enum(["workspace", "project"]),
74
+ scopeId: z.string().min(1).max(200),
75
+ enabled: z.boolean().default(true)
76
+ }).strict();
77
+ const ProactiveSubscriptionUpdateSchema = z.object({
78
+ level: ProactiveSubscriptionSettingsSchema.shape.level.removeDefault().optional(),
79
+ delivery: ProactiveSubscriptionSettingsSchema.shape.delivery.removeDefault().optional(),
80
+ preparationWorkflowId: ProactiveSubscriptionSettingsSchema.shape.preparationWorkflowId.removeDefault().optional(),
81
+ scanIntervalMinutes: ProactiveSubscriptionSettingsSchema.shape.scanIntervalMinutes.removeDefault().optional(),
82
+ userInstructions: ProactiveSubscriptionSettingsSchema.shape.userInstructions.removeDefault().optional(),
83
+ enabled: z.boolean().optional(),
84
+ expectedRevision: z.number().int().nonnegative()
85
+ }).strict();
86
+ const ProactiveCardActionSchema = z.object({
87
+ actionId: z.enum([
88
+ "read",
89
+ "resolve",
90
+ "snooze",
91
+ "decide",
92
+ "less",
93
+ "pause",
94
+ "useful",
95
+ "not_useful",
96
+ "retry"
97
+ ]),
98
+ expectedRevision: z.number().int().positive(),
99
+ idempotencyKey: z.string().min(8).max(128),
100
+ choice: z.string().min(1).max(200).optional(),
101
+ snoozedUntil: z.iso.datetime().optional()
102
+ }).strict();
103
+ //#endregion
104
+ export { ProactiveCardActionSchema, ProactivePreferencesSchema, ProactivePreferencesUpdateSchema, ProactiveSubscriptionCreateSchema, ProactiveSubscriptionSettingsSchema, ProactiveSubscriptionUpdateSchema };
@@ -1,6 +1,7 @@
1
1
  import "./voice-audio.js";
2
2
  import { z } from "zod";
3
3
  const VOICE_REALTIME_WS_PATH = "/api/voice/realtime/v3/ws";
4
+ const VOICE_REALTIME_PROXY_WS_PATH = "/api/realtime/v1/ws?transport=voice-v3";
4
5
  const VOICE_REALTIME_MAX_BINARY_FRAME_BYTES = 64 * 1024;
5
6
  const VOICE_REALTIME_START_TIMEOUT_MS = 1e4;
6
7
  const VOICE_REALTIME_HEARTBEAT_INTERVAL_MS = 15e3;
@@ -258,4 +259,4 @@ function parseVoiceClientJsonFrame(text) {
258
259
  return JSON.parse(text);
259
260
  }
260
261
  //#endregion
261
- export { VOICE_REALTIME_HEARTBEAT_INTERVAL_MS, VOICE_REALTIME_MAX_BINARY_FRAME_BYTES, VOICE_REALTIME_START_TIMEOUT_MS, VOICE_REALTIME_WS_PATH, createVoiceSessionRequestSchema, parseVoiceClientJsonFrame, parseVoiceClientMessage };
262
+ export { VOICE_REALTIME_HEARTBEAT_INTERVAL_MS, VOICE_REALTIME_MAX_BINARY_FRAME_BYTES, VOICE_REALTIME_PROXY_WS_PATH, VOICE_REALTIME_START_TIMEOUT_MS, VOICE_REALTIME_WS_PATH, createVoiceSessionRequestSchema, parseVoiceClientJsonFrame, parseVoiceClientMessage };
@@ -42,3 +42,4 @@ export declare class DelegateSubagentRunner implements SubagentRunner {
42
42
  run<T = string>(prompt: string, opts: SubagentRunOptions<T>): Promise<T | null>;
43
43
  private preparePersistentSubagentSession;
44
44
  }
45
+ export declare function resolveAllowedToolNames(requested: string[] | undefined, wantStructured: boolean): string[];
@@ -129,7 +129,7 @@ var DelegateSubagentRunner = class {
129
129
  }
130
130
  };
131
131
  function resolveAllowedToolNames(requested, wantStructured) {
132
- const filtered = (requested && requested.length > 0 ? requested : [...DEFAULT_DELEGATE_TOOLS]).map((s) => String(s).trim()).filter((s) => s.length > 0).filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));
132
+ const filtered = (requested ?? [...DEFAULT_DELEGATE_TOOLS]).map((s) => String(s).trim()).filter((s) => s.length > 0).filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));
133
133
  if (wantStructured && !filtered.includes("structured_output")) filtered.push(STRUCTURED_OUTPUT_TOOL_NAME);
134
134
  return [...new Set(filtered)];
135
135
  }
@@ -195,4 +195,4 @@ function mapChildProgressEvent(event) {
195
195
  }
196
196
  }
197
197
  //#endregion
198
- export { DelegateSubagentRunner };
198
+ export { DelegateSubagentRunner, resolveAllowedToolNames };
@@ -1,6 +1,6 @@
1
1
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
2
- import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
3
2
  import { register } from "../registry.js";
3
+ import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../capabilities/store-connector.js";
4
4
  import { confirm } from "@inquirer/prompts";
5
5
  import { Command } from "commander";
6
6
  //#region src/cli/commands/connectors.ts
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v158).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v161).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -6,8 +6,8 @@ import { ComposioSessionsAdapter } from "./composio-sessions.js";
6
6
  import { decodeConnectedSourceCursor, encodeConnectedSourceCursor } from "./connected-source-cursor.js";
7
7
  import { scopeForComposioAction } from "./composio.js";
8
8
  import { getConnectorDefinition } from "./catalog.js";
9
- import { getConnectorInstance } from "./instances.js";
10
9
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
10
+ import { getConnectorInstance } from "./instances.js";
11
11
  import { KnowledgeIngestionService } from "../knowledge/ingestion-service.js";
12
12
  import { ConnectedKnowledgePipeline } from "../knowledge/connected-knowledge-pipeline.js";
13
13
  import { LocalFolderKnowledgeSourceAdapter } from "../knowledge/local-folder-adapter.js";
@@ -13,9 +13,9 @@ import { getConnectorDefinition } from "./catalog.js";
13
13
  import { capabilityActions, isToolInputSchema, missingConnectionCapabilities } from "./connection-capabilities.js";
14
14
  import { connectorPrincipalForSession } from "./principal.js";
15
15
  import { resolveConnectionCandidate } from "./connection-candidates.js";
16
+ import { persistConfigMutation } from "../config/config-mutation.js";
16
17
  import { listConnectorInstances } from "./instances.js";
17
18
  import { installConnector } from "./install.js";
18
- import { persistConfigMutation } from "../config/config-mutation.js";
19
19
  import { randomUUID } from "node:crypto";
20
20
  //#region src/connectors/connection-recovery-service.ts
21
21
  init_logger();
@@ -1,6 +1,6 @@
1
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
1
2
  import { materializeConnectorMcpServer } from "./materialize.js";
2
3
  import { getConnectorInstance } from "./instances.js";
3
- import { getWorkspacePath } from "../config/workspace-path-helpers.js";
4
4
  import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-gateway.js";
5
5
  //#region src/connectors/health.ts
6
6
  function classifyConnectorHealthError(error) {
@@ -1,5 +1,5 @@
1
- import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../../capabilities/store-connector.js";
2
1
  import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
2
+ import { getStoreConnectorInstallPlan, installStoreConnector, listStoreConnectors } from "../../../capabilities/store-connector.js";
3
3
  //#region src/gateway/hono/routes/capabilities.ts
4
4
  function errorMessage(error) {
5
5
  return error instanceof Error ? error.message : String(error);
@@ -12,10 +12,10 @@ import { createConnectorSetupSecretRequest, submitConnectorSetupSecret } from ".
12
12
  import { configureComposioApiKey, executeComposioTool, getComposioInstallationPolicy, getComposioToolkitAuthState, getComposioToolkitScope, inspectComposioConnectorHealth, listComposioConnections, listComposioTools, refreshComposioConnection, revokeComposioConnection, setComposioToolkitScope, updateComposioConnection, updateComposioInstallationPolicy } from "../../../connectors/composio.js";
13
13
  import { listConnectorProviders } from "../../../connectors/providers.js";
14
14
  import { getConnectorDefinition, listConnectorCatalog } from "../../../connectors/catalog.js";
15
+ import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
15
16
  import { recordConnectorHealthUsage } from "../../../connectors/usage.js";
16
17
  import { getConnectorInstance, getInstalledConnectorDefinition, listConnectorInstances } from "../../../connectors/instances.js";
17
18
  import { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig } from "../../../connectors/install.js";
18
- import { ConfigPersistenceError, persistConfigMutation } from "../../../config/config-mutation.js";
19
19
  import { getMcpOAuthManager } from "../../../agent/mcp/oauth/mcp-oauth-manager.js";
20
20
  import { startConnectorAuthorization } from "../../../connectors/auth-provider-registry.js";
21
21
  import { composioLogoResponse } from "../../../connectors/composio-logo.js";
@@ -20,7 +20,6 @@ import { registerLocalAppsRoutes } from "./local-apps.js";
20
20
  import { registerWorkDiscoveryRoutes } from "./work-discovery.js";
21
21
  import { registerContextSourceRoutes } from "./context-sources.js";
22
22
  import { registerTaskRoutes } from "./tasks.js";
23
- import { registerProactiveRoutes } from "./proactive.js";
24
23
  import { registerMobilePrivacyRoutes } from "./mobile-privacy.js";
25
24
  import { mountAppLazyRoutePrefixes, registerAuthenticatedLazyRouteFallback } from "./lazy-fallback.js";
26
25
  //#region src/gateway/hono/routes/index.ts
@@ -40,7 +39,6 @@ function registerCoreAuthenticatedRoutes(authenticated, deps) {
40
39
  registerWorkDiscoveryRoutes(authenticated, deps);
41
40
  registerContextSourceRoutes(authenticated, deps);
42
41
  registerTaskRoutes(authenticated, deps);
43
- registerProactiveRoutes(authenticated, deps);
44
42
  registerSearchRoutes(authenticated, deps);
45
43
  registerDevicePushRoutes(authenticated);
46
44
  registerNotificationRoutes(authenticated, deps);
@@ -3,6 +3,18 @@ function startsWithAny(path, prefixes) {
3
3
  return prefixes.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
4
4
  }
5
5
  const AUTHENTICATED_LAZY_ROUTE_BUNDLES = [
6
+ {
7
+ id: "proactive",
8
+ match: (path) => startsWithAny(path, [
9
+ "/api/proactive",
10
+ "/api/inbox/judgments",
11
+ "/api/internal/proactive"
12
+ ]),
13
+ load: async () => {
14
+ const { registerProactiveRoutes } = await import("./proactive.js");
15
+ return { register: registerProactiveRoutes };
16
+ }
17
+ },
6
18
  {
7
19
  id: "runtime-tools",
8
20
  match: (path) => startsWithAny(path, ["/api/runtime-tools"]),
@@ -1,7 +1,7 @@
1
1
  import { canonicalizeConfiguredMcpServer, normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
2
2
  import { loadMergedBundleMcpConfig } from "../../../agent/mcp/bundle-mcp-config.js";
3
- import { isManagedConnectorServer } from "../../../connectors/materialize.js";
4
3
  import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
4
+ import { isManagedConnectorServer } from "../../../connectors/materialize.js";
5
5
  import { getMcpOAuthManager } from "../../../agent/mcp/oauth/mcp-oauth-manager.js";
6
6
  import { listBundleMcpServerCapabilitiesForGateway, listBundleMcpServerToolsForGateway } from "../../../agent/mcp/bundle-mcp-gateway.js";
7
7
  //#region src/gateway/hono/routes/mcp.ts
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerProactiveControlRoutes(app: Hono, deps: AuthenticatedRouteDeps): void;
@@ -0,0 +1,161 @@
1
+ import { getSqliteDatabase } from "../../../storage/sqlite/transaction.js";
2
+ import { getDefaultAgentId, init_resolve_route } from "../../../routing/resolve-route.js";
3
+ import { resolveProjectAgentId } from "../../../projects/project-agent.js";
4
+ import "../../../projects/index.js";
5
+ import { ProactiveConflict, proactivePreferences, updateProactivePreferences } from "../../../proactive/policy/service.js";
6
+ import { recordProactivePresence } from "../../../proactive/policy/presence.js";
7
+ import { controlledSubscriptions, createControlledSubscription, requireSubscription, templateCatalog, updateControlledSubscription } from "../../../proactive/scenarios/control.js";
8
+ import { cardChanges, getCard, listCards, performCardAction } from "../../../proactive/inbox/cards.js";
9
+ import { digestCards } from "../../../proactive/inbox/digest.js";
10
+ import { acknowledgeBrowserProbe, listBrowserProbes, prepareBrowserPush, registerBrowserPush, testBrowserPush, unregisterBrowserPush } from "../../../notifications/web-push.js";
11
+ import { ReadonlyProactiveAgentExecutor } from "../../../proactive/execution/agent-executor.js";
12
+ import { proactiveMetrics } from "../../../proactive/metrics.js";
13
+ import { prepareCardWorkflow, workflowForCard } from "../../../proactive/actions/workflow.js";
14
+ import { previewSubscription } from "../../../proactive/scenarios/preview.js";
15
+ import { ZodError } from "zod";
16
+ //#region src/gateway/hono/routes/proactive-control.ts
17
+ init_resolve_route();
18
+ function registerProactiveControlRoutes(app, deps) {
19
+ app.onError((error, c) => c.json({
20
+ ok: false,
21
+ error: error instanceof ZodError ? "Invalid request" : error.message
22
+ }, error instanceof ProactiveConflict ? 409 : 400));
23
+ const workspace = () => deps.service.currentWorkspacePath;
24
+ for (const path of ["/api/proactive/*", "/api/inbox/judgments/*"]) app.use(path, async (c, next) => {
25
+ try {
26
+ const id = c.req.path.match(/^\/api\/inbox\/judgments\/([^/]+)/)?.[1];
27
+ if (id && id !== "changes") getCard(decodeURIComponent(id), workspace());
28
+ await next();
29
+ } catch (error) {
30
+ return c.json({
31
+ ok: false,
32
+ error: error instanceof ZodError ? "Invalid request" : error instanceof Error ? error.message : "Request failed"
33
+ }, error instanceof ProactiveConflict ? 409 : 400);
34
+ }
35
+ });
36
+ app.get("/api/proactive/web-push/probes", (c) => c.json({
37
+ ok: true,
38
+ probes: listBrowserProbes(workspace())
39
+ }));
40
+ app.post("/api/proactive/web-push/subscriptions/:id/test", deps.strictRateLimitMiddleware, async (c) => c.json({
41
+ ok: true,
42
+ ...await testBrowserPush(workspace(), c.req.param("id"))
43
+ }));
44
+ app.post("/api/proactive/web-push/probes/:id/opened", deps.strictRateLimitMiddleware, (c) => {
45
+ acknowledgeBrowserProbe(workspace(), c.req.param("id"));
46
+ return c.json({ ok: true });
47
+ });
48
+ app.post("/api/proactive/web-push/prepare", deps.strictRateLimitMiddleware, (c) => c.json({
49
+ ok: true,
50
+ ...prepareBrowserPush()
51
+ }));
52
+ app.post("/api/proactive/web-push/subscriptions", deps.strictRateLimitMiddleware, async (c) => c.json({
53
+ ok: true,
54
+ ...registerBrowserPush(workspace(), await c.req.json())
55
+ }, 201));
56
+ app.delete("/api/proactive/web-push/subscriptions/:id", deps.strictRateLimitMiddleware, (c) => {
57
+ unregisterBrowserPush(workspace(), c.req.param("id"));
58
+ return c.json({ ok: true });
59
+ });
60
+ app.get("/api/inbox/judgments/:itemId/workflow", async (c) => c.json({
61
+ ok: true,
62
+ workflow: await workflowForCard(c.req.param("itemId"), workspace(), deps.service.createWorkflowRunService())
63
+ }));
64
+ app.post("/api/inbox/judgments/:itemId/prepare", deps.strictRateLimitMiddleware, async (c) => {
65
+ const card = getCard(c.req.param("itemId"), workspace());
66
+ const sub = requireSubscription(card.subscriptionId, workspace());
67
+ const config = deps.service.currentConfig;
68
+ const agentId = sub.scopeKind === "project" ? resolveProjectAgentId({
69
+ config,
70
+ projects: deps.service.projects,
71
+ projectId: sub.scopeId
72
+ }) : getDefaultAgentId(config);
73
+ return c.json({
74
+ ok: true,
75
+ workflow: await prepareCardWorkflow(workspace(), card.id, await c.req.json(), agentId, deps.service.createWorkflowRunService())
76
+ }, 202);
77
+ });
78
+ app.post("/api/proactive/presence", deps.strictRateLimitMiddleware, async (c) => {
79
+ recordProactivePresence(workspace(), await c.req.json());
80
+ return c.json({ ok: true });
81
+ });
82
+ app.get("/api/proactive/metrics", (c) => c.json({
83
+ ok: true,
84
+ metrics: proactiveMetrics(workspace())
85
+ }));
86
+ app.get("/api/proactive/digests/:id", (c) => c.json({
87
+ ok: true,
88
+ cards: digestCards(c.req.param("id"), workspace())
89
+ }));
90
+ app.post("/api/proactive/subscriptions/:id/preview", deps.strictRateLimitMiddleware, async (c) => c.json({
91
+ ok: true,
92
+ ...await previewSubscription(workspace(), c.req.param("id"), new ReadonlyProactiveAgentExecutor(() => deps.service.getConfig()), c.req.raw.signal)
93
+ }));
94
+ app.get("/api/proactive/templates", (c) => c.json({
95
+ ok: true,
96
+ templates: templateCatalog(workspace())
97
+ }));
98
+ app.get("/api/proactive/preferences", (c) => c.json({
99
+ ok: true,
100
+ preferences: proactivePreferences(workspace())
101
+ }));
102
+ app.patch("/api/proactive/preferences", deps.strictRateLimitMiddleware, async (c) => c.json({
103
+ ok: true,
104
+ preferences: updateProactivePreferences(workspace(), await c.req.json())
105
+ }));
106
+ app.get("/api/proactive/subscriptions", (c) => c.json({
107
+ ok: true,
108
+ subscriptions: controlledSubscriptions(workspace())
109
+ }));
110
+ app.post("/api/proactive/subscriptions", deps.strictRateLimitMiddleware, async (c) => c.json({
111
+ ok: true,
112
+ subscription: createControlledSubscription(workspace(), await c.req.json())
113
+ }, 201));
114
+ app.patch("/api/proactive/subscriptions/:id", deps.strictRateLimitMiddleware, async (c) => c.json({
115
+ ok: true,
116
+ subscription: updateControlledSubscription(workspace(), c.req.param("id"), await c.req.json())
117
+ }));
118
+ app.get("/api/proactive/subscriptions/:id/runs", (c) => {
119
+ requireSubscription(c.req.param("id"), workspace());
120
+ return c.json({
121
+ ok: true,
122
+ runs: getSqliteDatabase().prepare(`SELECT run_id AS id, status, outcome_reason AS reason,
123
+ started_at AS startedAt, completed_at AS completedAt, error_message AS error FROM proactive_runs WHERE subscription_id = ? ORDER BY started_at DESC LIMIT 30`).all(c.req.param("id"))
124
+ });
125
+ });
126
+ app.get("/api/proactive/cards", (c) => c.json({
127
+ ok: true,
128
+ ...listCards(workspace(), {
129
+ status: c.req.query("status"),
130
+ before: c.req.query("before")
131
+ })
132
+ }));
133
+ app.get("/api/inbox/judgments/changes", (c) => {
134
+ const cursor = Number(c.req.query("cursor") ?? 0);
135
+ if (!Number.isSafeInteger(cursor) || cursor < 0) return c.json({
136
+ ok: false,
137
+ error: "Invalid cursor"
138
+ }, 400);
139
+ return c.json({
140
+ ok: true,
141
+ ...cardChanges(workspace(), cursor)
142
+ });
143
+ });
144
+ app.get("/api/inbox/judgments/:itemId", (c) => c.json({
145
+ ok: true,
146
+ card: getCard(c.req.param("itemId"), workspace())
147
+ }));
148
+ app.post("/api/inbox/judgments/:itemId/actions", deps.strictRateLimitMiddleware, async (c) => {
149
+ const card = performCardAction(c.req.param("itemId"), workspace(), await c.req.json());
150
+ deps.service.emit("proactive.card.changed", {
151
+ cardId: card.id,
152
+ revision: card.revision
153
+ });
154
+ return c.json({
155
+ ok: true,
156
+ card
157
+ });
158
+ });
159
+ }
160
+ //#endregion
161
+ export { registerProactiveControlRoutes };
@@ -1,4 +1,4 @@
1
1
  import type { Hono } from 'hono';
2
2
  import type { AuthenticatedRouteDeps } from './deps.js';
3
- /** User-facing judgment inbox plus internal diagnostics. There is intentionally no proactive control-panel API. */
3
+ /** Proactive controls, cards and internal diagnostics. */
4
4
  export declare function registerProactiveRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
@@ -1,10 +1,14 @@
1
+ import { getInboxItem } from "../../../proactive/inbox/repository.js";
2
+ import { listCards } from "../../../proactive/inbox/cards.js";
3
+ import { registerProactiveControlRoutes } from "./proactive-control.js";
1
4
  //#region src/gateway/hono/routes/proactive.ts
2
5
  function positiveInt(value, fallback) {
3
6
  const parsed = Number(value);
4
7
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
5
8
  }
6
- /** User-facing judgment inbox plus internal diagnostics. There is intentionally no proactive control-panel API. */
9
+ /** Proactive controls, cards and internal diagnostics. */
7
10
  function registerProactiveRoutes(authenticated, deps) {
11
+ registerProactiveControlRoutes(authenticated, deps);
8
12
  authenticated.get("/api/inbox/judgments", (c) => {
9
13
  const status = c.req.query("status");
10
14
  if (status && ![
@@ -16,12 +20,15 @@ function registerProactiveRoutes(authenticated, deps) {
16
20
  ok: false,
17
21
  error: "Invalid inbox status"
18
22
  }, 400);
23
+ const page = listCards(deps.service.currentWorkspacePath, {
24
+ status,
25
+ limit: positiveInt(c.req.query("limit"), 50),
26
+ before: c.req.query("before")
27
+ });
19
28
  return c.json({
20
29
  ok: true,
21
- items: deps.service.proactiveInbox.list({
22
- ...status ? { status } : {},
23
- limit: positiveInt(c.req.query("limit"), 50)
24
- })
30
+ ...page,
31
+ items: page.cards.map((card) => getInboxItem(card.id))
25
32
  });
26
33
  });
27
34
  authenticated.post("/api/inbox/judgments/:itemId/transition", deps.strictRateLimitMiddleware, async (c) => {
@@ -256,7 +256,7 @@ function registerVoiceRoutes(authenticated, deps) {
256
256
  }
257
257
  }, 400);
258
258
  const principal = getGatewayPrincipal(c);
259
- service.voiceRealtime.cancelSession(parsed.data.sessionId, parsed.data.ticket, principal.principalId);
259
+ await service.voiceRealtime.cancelSession(parsed.data.sessionId, parsed.data.ticket, principal.principalId);
260
260
  return c.json({ ok: true });
261
261
  });
262
262
  authenticated.post("/api/voice/language", strictRateLimitMiddleware, async (c) => {
@@ -63,6 +63,11 @@ function requiredGatewayScope(method, path) {
63
63
  if (path.startsWith("/api/agents") || path.startsWith("/api/models")) return methodScope(method, "agents.read", "gateway.admin");
64
64
  if (path.startsWith("/api/sessions") || path.startsWith("/api/side-chats")) return methodScope(method, "sessions.read", "sessions.write");
65
65
  if (path.startsWith("/api/tasks")) return methodScope(method, "tasks.read", "tasks.write");
66
+ if (method === "POST" && /^\/api\/proactive\/subscriptions\/[^/]+\/preview$/.test(path)) return "agents.run";
67
+ if (/^\/api\/inbox\/judgments\/[^/]+\/workflow$/.test(path)) return methodScope(method, "automations.read", "automations.write");
68
+ if (method === "POST" && /^\/api\/inbox\/judgments\/[^/]+\/prepare$/.test(path)) return "automations.write";
69
+ if (path.startsWith("/api/proactive/web-push")) return "notifications.self";
70
+ if (path === "/api/proactive" || path.startsWith("/api/proactive/")) return methodScope(method, "tasks.read", "tasks.write");
66
71
  if (path.startsWith("/api/home") || path.startsWith("/api/inbox")) return methodScope(method, "tasks.read", "tasks.write");
67
72
  if (path.startsWith("/api/automations") || path.startsWith("/api/automation-runs")) return methodScope(method, "automations.read", "automations.write");
68
73
  if (path.startsWith("/api/workflows")) return methodScope(method, "automations.read", "automations.write");
@@ -179,7 +179,6 @@ export declare class GatewayService {
179
179
  private schedulePostReadySidecars;
180
180
  private runPostReadySidecars;
181
181
  start(): Promise<void>;
182
- private ensureDefaultProactiveScenarioSubscriptions;
183
182
  /** Called when the HTTP listener is bound (before deferred channel work). */
184
183
  markHttpListening(): void;
185
184
  isGatewayReady(): boolean;
@@ -54,6 +54,12 @@ import { registerClarificationChannelRuntime } from "./clarify-runtime.js";
54
54
  import { ChannelManager } from "../channels/manager.js";
55
55
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
56
56
  import "../config/index.js";
57
+ import { DiscussionService } from "../discussions/service.js";
58
+ import { DiscussionOrganizer } from "../discussions/organizer.js";
59
+ import { DiscussionLiveWorker } from "../discussions/live-worker.js";
60
+ import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
61
+ import { DiscussionSealer } from "../discussions/sealer.js";
62
+ import "../discussions/index.js";
57
63
  import { ManagedComposioEventPoller } from "../connectors/composio-managed-events.js";
58
64
  import { startConnectedKnowledgeCoordinator } from "../knowledge/coordinator.js";
59
65
  import "../knowledge/index.js";
@@ -61,17 +67,13 @@ import { ConnectionRecoveryService } from "../connectors/connection-recovery-ser
61
67
  import { startConnectorLearningCoordinator } from "../connectors/learning-coordinator.js";
62
68
  import { ConnectedSourceChangePublisher } from "../connectors/source-change-publisher.js";
63
69
  import { startConnectorSupervisor } from "../connectors/supervisor.js";
64
- import { DiscussionService } from "../discussions/service.js";
65
- import { DiscussionOrganizer } from "../discussions/organizer.js";
66
- import { DiscussionLiveWorker } from "../discussions/live-worker.js";
67
- import { DiscussionOrganizerWorker } from "../discussions/organizer-worker.js";
68
- import { DiscussionSealer } from "../discussions/sealer.js";
69
- import "../discussions/index.js";
70
70
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
71
71
  import "../endpoint-tools/index.js";
72
72
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
73
73
  import { prepareAutomationAgentSession } from "./automation-agent-session.js";
74
74
  import { stopTailscaleExposure } from "./tailscale-lifecycle.js";
75
+ import { ProactiveInboxService } from "../proactive/inbox/service.js";
76
+ import { deliverProactiveCard } from "../proactive/inbox/delivery.js";
75
77
  import { buildVoiceMemoryContext } from "../voice/realtime/memory-context.js";
76
78
  import { buildVoicePersonaContext } from "../voice/realtime/persona-context.js";
77
79
  import { voiceMemoryBudget, voicePersonaBudget } from "../voice/realtime/conversation-context.js";
@@ -111,7 +113,6 @@ import { ReadonlyProactiveAgentExecutor } from "../proactive/execution/agent-exe
111
113
  import { listInsights } from "../proactive/execution/repository.js";
112
114
  import { ProactiveWorker } from "../proactive/execution/worker.js";
113
115
  import { ProactiveTemporalWorker } from "../proactive/temporal/worker.js";
114
- import { ProactiveInboxService } from "../proactive/inbox/service.js";
115
116
  import { ProactiveInboxWorker } from "../proactive/inbox/worker.js";
116
117
  import "../proactive/index.js";
117
118
  import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js";
@@ -317,7 +318,7 @@ var GatewayService = class {
317
318
  this.proactiveWorker = new ProactiveWorker(new ReadonlyProactiveAgentExecutor(() => this.config));
318
319
  this.proactiveTemporalWorker = new ProactiveTemporalWorker(this.proactive);
319
320
  this.proactiveInboxWorker = new ProactiveInboxWorker({ deliver: async ({ inboxItem }) => {
320
- this.emit("proactive.inbox.created", inboxItem);
321
+ return deliverProactiveCard(inboxItem, this.createNotificationService(), (type, payload) => this.realtime.broker.publish("gateway", type, payload));
321
322
  } });
322
323
  let bootstrapConfigChanged = initializeVoiceDefaults(this.config, inferProductLanguageFromEnvironment());
323
324
  const starterResult = ensureStarterAgentsInitialized(this.config);
@@ -680,7 +681,21 @@ var GatewayService = class {
680
681
  return this.taskRunDispatcher;
681
682
  }
682
683
  createNotificationService() {
683
- if (!this.notificationService) this.notificationService = new NotificationService({ publish: (type, payload) => this.realtime.broker.publish("gateway", type, payload) });
684
+ if (!this.notificationService) this.notificationService = new NotificationService({
685
+ publish: (type, payload) => this.realtime.broker.publish("gateway", type, payload),
686
+ sendChannel: async (target, text) => {
687
+ const outbound = this.channelManager.getPlugin("telegram")?.outbound;
688
+ if (!outbound?.sendText || !this.channelManager.getRunningChannels().includes("telegram")) throw new Error("Telegram is not connected");
689
+ const result = await outbound.sendText({
690
+ cfg: this.config,
691
+ to: target.chatId,
692
+ accountId: target.accountId,
693
+ text
694
+ });
695
+ if (!result.success) throw new Error("Telegram delivery failed");
696
+ return { messageId: result.messageId };
697
+ }
698
+ });
684
699
  return this.notificationService;
685
700
  }
686
701
  dispatchTaskRuns() {
@@ -921,7 +936,6 @@ var GatewayService = class {
921
936
  this.running = true;
922
937
  this.taskRunDispatchTimer = setInterval(() => this.dispatchTaskRuns(), 1e3);
923
938
  this.taskRunDispatchTimer.unref?.();
924
- this.ensureDefaultProactiveScenarioSubscriptions();
925
939
  this.proactiveWorker.start();
926
940
  this.proactiveTemporalWorker.start();
927
941
  this.proactiveInboxWorker.start();
@@ -1115,22 +1129,6 @@ var GatewayService = class {
1115
1129
  else trace.mark("service.started-awaiting-http");
1116
1130
  log.debug("Gateway service started");
1117
1131
  }
1118
- ensureDefaultProactiveScenarioSubscriptions() {
1119
- for (const scenarioKey of [
1120
- "automation_failure_impact",
1121
- "meeting_preparation",
1122
- "discussion_follow_up"
1123
- ]) {
1124
- if (this.proactiveScenarios.subscriptions(scenarioKey).some((subscription) => subscription.workspaceId === this.currentWorkspacePath)) continue;
1125
- this.proactiveScenarios.subscribe({
1126
- scenarioKey,
1127
- workspaceId: this.currentWorkspacePath,
1128
- scopeKind: "workspace",
1129
- scopeId: this.currentWorkspacePath,
1130
- enabled: true
1131
- });
1132
- }
1133
- }
1134
1132
  /** Called when the HTTP listener is bound (before deferred channel work). */
1135
1133
  markHttpListening() {
1136
1134
  this.readiness.markHttpListening();
@@ -122,7 +122,7 @@ function automationPlan(payload) {
122
122
  function proactivePlan(payload) {
123
123
  if (!payload || typeof payload !== "object") return null;
124
124
  const item = payload;
125
- if (typeof item.id !== "string" || typeof item.insightId !== "string" || typeof item.insight.title !== "string") return null;
125
+ if (typeof item.id !== "string" || typeof item.insightId !== "string" || typeof item.insight?.title !== "string") return null;
126
126
  const requiresDecision = item.insight.attentionKind === "decision";
127
127
  const highUrgency = item.insight.urgency === "high" || item.insight.urgency === "critical";
128
128
  if (item.insight.attentionKind === "receipt") return null;
@@ -130,7 +130,7 @@ function proactivePlan(payload) {
130
130
  const title = item.insight.title.trim().slice(0, 120);
131
131
  const summary = typeof item.insight.summary === "string" ? item.insight.summary.trim().slice(0, 180) : "";
132
132
  return {
133
- dedupeKey: `proactive.insight:${item.id}`,
133
+ dedupeKey: `proactive.insight:${item.id}${item.notificationRevision && item.notificationRevision > 1 ? `:${item.notificationRevision}` : ""}`,
134
134
  notification: {
135
135
  type: "proactive.insight",
136
136
  target: {
@@ -148,7 +148,8 @@ function proactivePlan(payload) {
148
148
  } } : {},
149
149
  payload: {
150
150
  inboxItemId: item.id,
151
- insightId: item.insightId
151
+ insightId: item.insightId,
152
+ notificationRevision: item.notificationRevision ?? 1
152
153
  }
153
154
  }
154
155
  };