@xopcai/xopc 0.0.159 → 0.0.160

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 (195) 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/{action-boundary-settings-panel-CaRK2vIy.js → action-boundary-settings-panel-CY3sizqC.js} +1 -1
  4. package/dist/gateway/static/root/assets/{activity-store-C-57rvkX.js → activity-store-3Cso_2qm.js} +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BeVf03hx.js → agent-avatar-dicebear-B_27aaZQ.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-B1l3iii6.js +2 -0
  7. package/dist/gateway/static/root/assets/{api-BjcBIV2O.js → api-BbzB57CJ.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BG2ulMYw.js → app-management-settings-panel-DfmyWcyh.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-0Kjenr2T.js → appearance-settings-B2v0c-K-.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-DaNFLsp0.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-ChiNnH1e.js → archive-plugin-DL5Lnx0C.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-pbBlQR-g.js → attachment-load-InuP-ZjQ.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automation-suggestion-card-CTZDOyDy.js → automation-suggestion-card-CahGuh7B.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-Cd0gMx6p.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BeZGzpGF.js → binary-plugins-CdOTGYVu.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BnDmhN5Z.js → block-editor-D6ShK1S-.js} +3 -3
  17. package/dist/gateway/static/root/assets/browser-settings-page-BmUYDL2Z.js +8 -0
  18. package/dist/gateway/static/root/assets/{capability-presets-api-Ii36j_7v.js → capability-presets-api-BzoLm52Z.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-Cl3dw4yh.js → capability-presets-settings-panel-CE7mrWtS.js} +2 -2
  20. package/dist/gateway/static/root/assets/{channel-recipient-api-CFqrSi5K.js → channel-recipient-api-DbgydMjl.js} +1 -1
  21. package/dist/gateway/static/root/assets/channels-settings-D1_gcAHK.js +1 -0
  22. package/dist/gateway/static/root/assets/channels-status-swr-Cqfqv59m.js +1 -0
  23. package/dist/gateway/static/root/assets/{connector-logo-CiLxuZ8S.js → connector-logo-C3bJC9nt.js} +1 -1
  24. package/dist/gateway/static/root/assets/connectors-page-CaLBi6Na.js +2 -0
  25. package/dist/gateway/static/root/assets/desktop-pet-settings-BrHVvbBw.js +1 -0
  26. package/dist/gateway/static/root/assets/desktop-pet-sprite-CFd1jGLJ.js +1 -0
  27. package/dist/gateway/static/root/assets/desktop-pet-wacrnJJ1.js +1 -0
  28. package/dist/gateway/static/root/assets/{directory-picker-path-field-CC2VL5Mc.js → directory-picker-path-field-BPI969w-.js} +1 -1
  29. package/dist/gateway/static/root/assets/{dreaming-settings-KY7ZfVsy.js → dreaming-settings-iw6QXD45.js} +3 -3
  30. package/dist/gateway/static/root/assets/{extension-debug-page-C8KBeucs.js → extension-debug-page-rCHyhEr6.js} +1 -1
  31. package/dist/gateway/static/root/assets/{extension-page-CV-5Kcyk.js → extension-page-C4gQsAPt.js} +1 -1
  32. package/dist/gateway/static/root/assets/{extension-settings-page-DvUtDrAu.js → extension-settings-page-DB_3eik7.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-config-api-DXfVeJLc.js → gateway-config-api-Cdt38iF2.js} +1 -1
  34. package/dist/gateway/static/root/assets/gateway-settings-DM4BgyGw.js +1 -0
  35. package/dist/gateway/static/root/assets/{gateway-startup-retry-cxQ94qMm.js → gateway-startup-retry-ChRFNjj_.js} +1 -1
  36. package/dist/gateway/static/root/assets/goal-create-dialog-BQamcEmF.js +1 -0
  37. package/dist/gateway/static/root/assets/goal-detail-page-DZUQ0Lf1.js +4 -0
  38. package/dist/gateway/static/root/assets/{goals-config-api-P8VhLqYF.js → goals-config-api-RvljeEm6.js} +1 -1
  39. package/dist/gateway/static/root/assets/goals-page-BtxVD27C.js +2 -0
  40. package/dist/gateway/static/root/assets/{goals-settings-DHXyaH_O.js → goals-settings-DMGV4S4L.js} +1 -1
  41. package/dist/gateway/static/root/assets/{heartbeat-settings-CNckP_Dv.js → heartbeat-settings-B8r5EXc5.js} +1 -1
  42. package/dist/gateway/static/root/assets/index-CHKe7nwC.js +197 -0
  43. package/dist/gateway/static/root/assets/index-CXhfUIjh.css +1 -0
  44. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-jXmv1RVX.js → keyboard-shortcuts-settings-1-LYibQ4.js} +1 -1
  45. package/dist/gateway/static/root/assets/local-app-workbench-page-CTTfyFe3.js +2 -0
  46. package/dist/gateway/static/root/assets/{local-apps-page-Cs5LKjtc.js → local-apps-page-CC4vtUUI.js} +1 -1
  47. package/dist/gateway/static/root/assets/{locale-store-C_M71MK9.js → locale-store-CPbGB_6l.js} +1 -1
  48. package/dist/gateway/static/root/assets/logs-page-Bn_taxBV.js +7 -0
  49. package/dist/gateway/static/root/assets/{markdown-split-BFqeSNte.js → markdown-split-CprEIf8A.js} +1 -1
  50. package/dist/gateway/static/root/assets/{media-plugins-Cc8379gq.js → media-plugins-BXt_Sj2O.js} +1 -1
  51. package/dist/gateway/static/root/assets/{messages-BuT0SR1R.js → messages-DDsiqdJS.js} +4 -4
  52. package/dist/gateway/static/root/assets/models-hub-panel-DJReXRP9.js +2 -0
  53. package/dist/gateway/static/root/assets/{notes-page-DlGU4ipo.js → notes-page-Wf5-eyyM.js} +1 -1
  54. package/dist/gateway/static/root/assets/notes-workbench-BbdjzYzs.js +4 -0
  55. package/dist/gateway/static/root/assets/{page-tabs-kFOswGlG.js → page-tabs-dtpK_4Fs.js} +1 -1
  56. package/dist/gateway/static/root/assets/{preview-open-alternatives-CvjuvABg.js → preview-open-alternatives-DijtEVxG.js} +1 -1
  57. package/dist/gateway/static/root/assets/project-detail-page-BwG8SOzI.js +1 -0
  58. package/dist/gateway/static/root/assets/projects-page-nUlyUtxh.js +1 -0
  59. package/dist/gateway/static/root/assets/remote-access-hub-rf7bjije.js +1 -0
  60. package/dist/gateway/static/root/assets/{save-bar-controls-DwrD7ODx.js → save-bar-controls-qhDisdqY.js} +1 -1
  61. package/dist/gateway/static/root/assets/{schedule-field-Ba4WzTmE.js → schedule-field-AhJ50NoT.js} +1 -1
  62. package/dist/gateway/static/root/assets/{schema-form-DvydL8eF.js → schema-form-AuJg2CXU.js} +1 -1
  63. package/dist/gateway/static/root/assets/sessions-page-CSoHUe38.js +1 -0
  64. package/dist/gateway/static/root/assets/settings-advanced-gate-Db976IEa.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-collapsible-section-LaQqGGej.js → settings-collapsible-section-D5ganr_X.js} +1 -1
  66. package/dist/gateway/static/root/assets/{settings-form-section-DruI__qO.js → settings-form-section-Db3cKRsg.js} +1 -1
  67. package/dist/gateway/static/root/assets/{settings-loading-skeleton-UvA-eDhF.js → settings-loading-skeleton-D05YKT2x.js} +1 -1
  68. package/dist/gateway/static/root/assets/{settings-page-5oCGSebm.js → settings-page-DYfXmfTx.js} +1 -1
  69. package/dist/gateway/static/root/assets/{settings-page-layout-DG-XMIPu.js → settings-page-layout-Cv_Cu4I5.js} +1 -1
  70. package/dist/gateway/static/root/assets/setup-status-panel-wBWOFpvw.js +1 -0
  71. package/dist/gateway/static/root/assets/{share-preview-page-FLVeTrRt.js → share-preview-page-CYkZVuse.js} +1 -1
  72. package/dist/gateway/static/root/assets/shares-settings-BAMma1-P.js +1 -0
  73. package/dist/gateway/static/root/assets/skill-reload-api-TWxFFWxM.js +1 -0
  74. package/dist/gateway/static/root/assets/skills-page-Ca2RA29R.js +2 -0
  75. package/dist/gateway/static/root/assets/{system-settings-panel-CeK93xVi.js → system-settings-panel-C1Ng5bXh.js} +1 -1
  76. package/dist/gateway/static/root/assets/{theme-store-C8ohIHhw.js → theme-store-LMHIDR9n.js} +1 -1
  77. package/dist/gateway/static/root/assets/{typed-models-lib-D1Lr2gG0.js → typed-models-lib-Ch2Bdm_5.js} +1 -1
  78. package/dist/gateway/static/root/assets/{use-channel-catalog-BWzou5ar.js → use-channel-catalog-CZnaMOeL.js} +1 -1
  79. package/dist/gateway/static/root/assets/user-context-page-CTumZa0y.js +1 -0
  80. package/dist/gateway/static/root/assets/voice-api-key-field-DdlMxeqO.js +1 -0
  81. package/dist/gateway/static/root/assets/work-discovery-page-CcfZhdBi.js +1 -0
  82. package/dist/gateway/static/root/assets/work-item-detail-page--wxLw1p_.js +1 -0
  83. package/dist/gateway/static/root/assets/work-page-DyS0XBpV.js +1 -0
  84. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Bynqe4kV.js → workflow-run-setup-panel-BFk8TvTw.js} +2 -2
  85. package/dist/gateway/static/root/assets/workflows-page-CVVJd4gy.js +11 -0
  86. package/dist/gateway/static/root/index.html +7 -7
  87. package/dist/package.js +1 -1
  88. package/dist/src/automations/service/action-executor.js +1 -1
  89. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  90. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  91. package/dist/src/gateway/chat-stream/mapper.js +43 -7
  92. package/dist/src/gateway/hono/routes/home.js +15 -2
  93. package/dist/src/gateway/hono/routes/work-discovery.js +451 -0
  94. package/dist/src/gateway/service.d.ts +2 -0
  95. package/dist/src/gateway/service.js +27 -2
  96. package/dist/src/mobile/notification-service.js +1 -0
  97. package/dist/src/pets/factory.js +23 -26
  98. package/dist/src/pets/manifest.d.ts +2 -1
  99. package/dist/src/pets/manifest.js +15 -8
  100. package/dist/src/pets/validator.js +8 -3
  101. package/dist/src/proactive/calendar-signals.d.ts +4 -0
  102. package/dist/src/proactive/calendar-signals.js +120 -0
  103. package/dist/src/proactive/focus-service.d.ts +62 -0
  104. package/dist/src/proactive/focus-service.js +173 -0
  105. package/dist/src/proactive/index.d.ts +7 -0
  106. package/dist/src/proactive/index.js +7 -0
  107. package/dist/src/proactive/insight-repository.d.ts +19 -0
  108. package/dist/src/proactive/insight-repository.js +106 -0
  109. package/dist/src/proactive/run-processor.d.ts +19 -0
  110. package/dist/src/proactive/run-processor.js +125 -0
  111. package/dist/src/proactive/trial-expiry-reconciler.d.ts +5 -0
  112. package/dist/src/proactive/trial-expiry-reconciler.js +30 -0
  113. package/dist/src/proactive/types.d.ts +64 -0
  114. package/dist/src/proactive/types.js +1 -0
  115. package/dist/src/proactive/watch-repository.d.ts +28 -0
  116. package/dist/src/proactive/watch-repository.js +129 -0
  117. package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
  118. package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
  119. package/dist/src/storage/sqlite/migrations/047_work_discovery_sources.sql +16 -0
  120. package/dist/src/storage/sqlite/migrations/048_work_understanding_investigations.sql +40 -0
  121. package/dist/src/storage/sqlite/migrations/049_work_understanding_threads.sql +52 -0
  122. package/dist/src/storage/sqlite/migrations/050_work_discovery_source_refreshes.sql +15 -0
  123. package/dist/src/storage/sqlite/migrations/051_focus_watches.sql +26 -0
  124. package/dist/src/storage/sqlite/migrations/052_proactive_insights.sql +25 -0
  125. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  126. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  127. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  128. package/dist/src/storage/sqlite/schema.js +1 -1
  129. package/dist/src/work-discovery/analyzer.d.ts +12 -1
  130. package/dist/src/work-discovery/analyzer.js +126 -7
  131. package/dist/src/work-discovery/candidate-discovery.d.ts +17 -0
  132. package/dist/src/work-discovery/candidate-discovery.js +279 -0
  133. package/dist/src/work-discovery/evaluation.d.ts +11 -0
  134. package/dist/src/work-discovery/evaluation.js +17 -0
  135. package/dist/src/work-discovery/governance.d.ts +25 -0
  136. package/dist/src/work-discovery/governance.js +96 -0
  137. package/dist/src/work-discovery/incremental-repository.d.ts +13 -0
  138. package/dist/src/work-discovery/incremental-repository.js +55 -0
  139. package/dist/src/work-discovery/incremental.d.ts +2 -0
  140. package/dist/src/work-discovery/incremental.js +7 -0
  141. package/dist/src/work-discovery/index.d.ts +10 -0
  142. package/dist/src/work-discovery/index.js +13 -3
  143. package/dist/src/work-discovery/investigation-repository.d.ts +16 -0
  144. package/dist/src/work-discovery/investigation-repository.js +122 -0
  145. package/dist/src/work-discovery/investigator.d.ts +55 -0
  146. package/dist/src/work-discovery/investigator.js +358 -0
  147. package/dist/src/work-discovery/probe.d.ts +22 -0
  148. package/dist/src/work-discovery/probe.js +88 -1
  149. package/dist/src/work-discovery/service.d.ts +110 -1
  150. package/dist/src/work-discovery/service.js +578 -8
  151. package/dist/src/work-discovery/source-repository.d.ts +13 -0
  152. package/dist/src/work-discovery/source-repository.js +72 -0
  153. package/dist/src/work-discovery/thread-repository.d.ts +34 -0
  154. package/dist/src/work-discovery/thread-repository.js +112 -0
  155. package/dist/src/work-discovery/thread-service.d.ts +8 -0
  156. package/dist/src/work-discovery/thread-service.js +104 -0
  157. package/dist/src/work-discovery/types.d.ts +145 -0
  158. package/package.json +1 -1
  159. package/skills/creative/hatch-pet/SKILL.md +2 -2
  160. package/dist/gateway/static/root/assets/agents-P05C4A-3.js +0 -2
  161. package/dist/gateway/static/root/assets/apps-page-DANGrBpN.js +0 -1
  162. package/dist/gateway/static/root/assets/automations-page-BXfGL_cm.js +0 -6
  163. package/dist/gateway/static/root/assets/browser-settings-page-534luV0B.js +0 -8
  164. package/dist/gateway/static/root/assets/channels-settings-M91zFJVi.js +0 -1
  165. package/dist/gateway/static/root/assets/channels-status-swr-vooEF4lG.js +0 -1
  166. package/dist/gateway/static/root/assets/connectors-page-CV5UulW6.js +0 -2
  167. package/dist/gateway/static/root/assets/desktop-pet-Cil2eSpW.js +0 -1
  168. package/dist/gateway/static/root/assets/desktop-pet-settings-DwsC6l5F.js +0 -1
  169. package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +0 -1
  170. package/dist/gateway/static/root/assets/gateway-settings-BpJ0v56l.js +0 -1
  171. package/dist/gateway/static/root/assets/goal-create-dialog-lMHD-2CX.js +0 -1
  172. package/dist/gateway/static/root/assets/goal-detail-page-yPmF-G7b.js +0 -4
  173. package/dist/gateway/static/root/assets/goals-page-BHTCKobG.js +0 -2
  174. package/dist/gateway/static/root/assets/index-BgZhEOkN.css +0 -1
  175. package/dist/gateway/static/root/assets/index-BuqGh2SW.js +0 -193
  176. package/dist/gateway/static/root/assets/local-app-workbench-page-zpp_wciE.js +0 -2
  177. package/dist/gateway/static/root/assets/logs-page-B4CRYqYR.js +0 -7
  178. package/dist/gateway/static/root/assets/models-hub-panel-1hdoAoB_.js +0 -2
  179. package/dist/gateway/static/root/assets/notes-workbench-DQEAZTA5.js +0 -4
  180. package/dist/gateway/static/root/assets/project-detail-page-Bp9bC7A6.js +0 -1
  181. package/dist/gateway/static/root/assets/projects-page-RNorFXTw.js +0 -1
  182. package/dist/gateway/static/root/assets/remote-access-hub-BqRTcM_6.js +0 -1
  183. package/dist/gateway/static/root/assets/sessions-page-B2EfW1cm.js +0 -1
  184. package/dist/gateway/static/root/assets/settings-advanced-gate-CklL85T4.js +0 -1
  185. package/dist/gateway/static/root/assets/setup-status-panel-D3my1HgB.js +0 -1
  186. package/dist/gateway/static/root/assets/shares-settings-DVxgjrsP.js +0 -1
  187. package/dist/gateway/static/root/assets/skill-reload-api-Bcu58ZaF.js +0 -1
  188. package/dist/gateway/static/root/assets/skills-page-CDd-84FE.js +0 -2
  189. package/dist/gateway/static/root/assets/sliding-segmented-uWmrxE3P.js +0 -1
  190. package/dist/gateway/static/root/assets/user-context-page-1OyJnTyR.js +0 -1
  191. package/dist/gateway/static/root/assets/voice-api-key-field-B2ncRwHS.js +0 -1
  192. package/dist/gateway/static/root/assets/work-discovery-page-BZlY4PZL.js +0 -1
  193. package/dist/gateway/static/root/assets/work-item-detail-page-DPXMrneY.js +0 -1
  194. package/dist/gateway/static/root/assets/work-page-CTERoqyv.js +0 -1
  195. package/dist/gateway/static/root/assets/workflows-page-CLgsnqFQ.js +0 -11
@@ -1,6 +1,10 @@
1
1
  import { getAgentDefaultModelRef, init_schema } from "../../../config/schema.js";
2
2
  import { init_providers, resolveModel } from "../../../providers/index.js";
3
3
  import { isLocalModelBaseUrl } from "../../../providers/model-call.js";
4
+ import { listFocusCalendarSignals } from "../../../proactive/calendar-signals.js";
5
+ import { FocusService } from "../../../proactive/focus-service.js";
6
+ import { claimProactiveInsightApproval, getProactiveInsight, setProactiveInsightStatus } from "../../../proactive/insight-repository.js";
7
+ import "../../../proactive/index.js";
4
8
  import { previewWorkDiscoveryRoot } from "../../../work-discovery/probe.js";
5
9
  import { WorkDiscoveryService } from "../../../work-discovery/service.js";
6
10
  //#region src/gateway/hono/routes/work-discovery.ts
@@ -26,6 +30,7 @@ function stringField(body, field) {
26
30
  }
27
31
  function registerWorkDiscoveryRoutes(authenticated, deps) {
28
32
  const service = workDiscoveryService(deps);
33
+ const focuses = new FocusService(deps.service.automationServiceInstance);
29
34
  const limited = deps.strictRateLimitMiddleware;
30
35
  authenticated.get("/api/onboarding/work-discovery", (c) => c.json({
31
36
  enabled: service.isEnabled(),
@@ -77,6 +82,178 @@ function registerWorkDiscoveryRoutes(authenticated, deps) {
77
82
  }, 400);
78
83
  }
79
84
  });
85
+ authenticated.post("/api/work-discovery/candidates", limited, async (c) => {
86
+ if (!service.isEnabled()) return c.json({
87
+ ok: false,
88
+ error: "Work discovery is disabled"
89
+ }, 404);
90
+ try {
91
+ const candidates = await service.discoverCandidates(c.req.raw.signal);
92
+ return c.json({
93
+ ok: true,
94
+ candidates
95
+ });
96
+ } catch (error) {
97
+ return c.json({
98
+ ok: false,
99
+ error: error instanceof Error ? error.message : String(error)
100
+ }, 500);
101
+ }
102
+ });
103
+ authenticated.get("/api/work-discovery/sources/directories", (c) => c.json({
104
+ ok: true,
105
+ sources: service.listDirectorySources()
106
+ }));
107
+ authenticated.post("/api/work-discovery/sources/directories", limited, async (c) => {
108
+ const rootPath = stringField(await c.req.json().catch(() => null), "rootPath");
109
+ if (!rootPath) return c.json({
110
+ ok: false,
111
+ error: "Missing rootPath"
112
+ }, 400);
113
+ try {
114
+ const source = await service.grantDirectorySource(rootPath);
115
+ return c.json({
116
+ ok: true,
117
+ source
118
+ }, 201);
119
+ } catch (error) {
120
+ return c.json({
121
+ ok: false,
122
+ error: error instanceof Error ? error.message : String(error)
123
+ }, 400);
124
+ }
125
+ });
126
+ authenticated.delete("/api/work-discovery/sources/directories/:sourceId", limited, (c) => {
127
+ const source = service.revokeDirectorySource(c.req.param("sourceId"));
128
+ return source ? c.json({
129
+ ok: true,
130
+ source
131
+ }) : c.json({
132
+ ok: false,
133
+ error: "Source not found"
134
+ }, 404);
135
+ });
136
+ authenticated.post("/api/work-discovery/sources/directories/:sourceId/runs", limited, async (c) => {
137
+ const idempotencyKey = stringField(await c.req.json().catch(() => null), "idempotencyKey");
138
+ if (!idempotencyKey) return c.json({
139
+ ok: false,
140
+ error: "Missing idempotencyKey"
141
+ }, 400);
142
+ try {
143
+ const run = await service.rescanDirectorySource({
144
+ id: c.req.param("sourceId"),
145
+ idempotencyKey
146
+ });
147
+ return c.json({
148
+ ok: true,
149
+ run
150
+ }, 202);
151
+ } catch (error) {
152
+ return c.json({
153
+ ok: false,
154
+ error: error instanceof Error ? error.message : String(error)
155
+ }, 400);
156
+ }
157
+ });
158
+ authenticated.post("/api/work-discovery/sources/directories/check", limited, async (c) => {
159
+ return c.json({
160
+ ok: true,
161
+ checks: await service.checkDirectorySources()
162
+ });
163
+ });
164
+ authenticated.post("/api/work-discovery/sources/directories/:sourceId/refresh-if-changed", limited, async (c) => {
165
+ const idempotencyKey = stringField(await c.req.json().catch(() => null), "idempotencyKey");
166
+ if (!idempotencyKey) return c.json({
167
+ ok: false,
168
+ error: "Missing idempotencyKey"
169
+ }, 400);
170
+ try {
171
+ const result = await service.refreshDirectorySourceIfChanged({
172
+ id: c.req.param("sourceId"),
173
+ idempotencyKey
174
+ });
175
+ return c.json({
176
+ ok: true,
177
+ ...result
178
+ }, result.changed ? 202 : 200);
179
+ } catch (error) {
180
+ return c.json({
181
+ ok: false,
182
+ error: error instanceof Error ? error.message : String(error)
183
+ }, 400);
184
+ }
185
+ });
186
+ authenticated.post("/api/work-discovery/personal-context/import", limited, async (c) => {
187
+ if (!service.isEnabled()) return c.json({
188
+ ok: false,
189
+ error: "Work discovery is disabled"
190
+ }, 404);
191
+ const body = await c.req.json().catch(() => null);
192
+ const items = body && typeof body === "object" && Array.isArray(body.items) ? body.items.slice(0, 150) : [];
193
+ const runId = stringField(body, "runId");
194
+ if (!items.length) return c.json({
195
+ ok: false,
196
+ error: "No personal context was provided"
197
+ }, 400);
198
+ try {
199
+ const result = await service.importPersonalContext(items, c.req.raw.signal, runId || void 0);
200
+ return c.json({
201
+ ok: true,
202
+ ...result
203
+ }, 201);
204
+ } catch (error) {
205
+ return c.json({
206
+ ok: false,
207
+ error: error instanceof Error ? error.message : String(error)
208
+ }, 400);
209
+ }
210
+ });
211
+ authenticated.post("/api/work-discovery/personal-context/profile", limited, async (c) => {
212
+ const body = await c.req.json().catch(() => null);
213
+ const decisions = (body && typeof body === "object" && Array.isArray(body.decisions) ? body.decisions : []).flatMap((value) => {
214
+ if (!value || typeof value !== "object") return [];
215
+ const item = value;
216
+ const memoryRecordId = typeof item.memoryRecordId === "string" ? item.memoryRecordId.trim() : "";
217
+ const status = item.status === "accepted" || item.status === "edited" || item.status === "rejected" ? item.status : void 0;
218
+ if (!memoryRecordId || !status) return [];
219
+ return [{
220
+ memoryRecordId,
221
+ status,
222
+ ...typeof item.statement === "string" ? { statement: item.statement } : {}
223
+ }];
224
+ }).slice(0, 10);
225
+ if (!decisions.length) return c.json({
226
+ ok: false,
227
+ error: "At least one valid decision is required"
228
+ }, 400);
229
+ return c.json({
230
+ ok: true,
231
+ decisions: service.updatePersonalContextProfile({ decisions })
232
+ });
233
+ });
234
+ authenticated.post("/api/work-discovery/quick-runs", limited, async (c) => {
235
+ if (!service.isEnabled()) return c.json({
236
+ ok: false,
237
+ error: "Work discovery is disabled"
238
+ }, 404);
239
+ const idempotencyKey = stringField(await c.req.json().catch(() => null), "idempotencyKey");
240
+ if (!idempotencyKey) return c.json({
241
+ ok: false,
242
+ error: "Missing idempotencyKey"
243
+ }, 400);
244
+ try {
245
+ const run = await service.startQuickRun({ idempotencyKey });
246
+ return c.json({
247
+ ok: true,
248
+ run
249
+ }, 202);
250
+ } catch (error) {
251
+ return c.json({
252
+ ok: false,
253
+ error: error instanceof Error ? error.message : String(error)
254
+ }, 400);
255
+ }
256
+ });
80
257
  authenticated.post("/api/work-discovery/runs", limited, async (c) => {
81
258
  if (!service.isEnabled()) return c.json({
82
259
  ok: false,
@@ -117,6 +294,250 @@ function registerWorkDiscoveryRoutes(authenticated, deps) {
117
294
  error: "Run not found"
118
295
  }, 404);
119
296
  });
297
+ authenticated.get("/api/work-discovery/runs/:runId/investigation", (c) => {
298
+ const result = service.getInvestigation(c.req.param("runId"));
299
+ return result ? c.json({
300
+ ok: true,
301
+ ...result
302
+ }) : c.json({
303
+ ok: false,
304
+ error: "Investigation not found"
305
+ }, 404);
306
+ });
307
+ authenticated.get("/api/work-understanding/threads", (c) => {
308
+ const projectId = c.req.query("projectId")?.trim();
309
+ const limit = Number(c.req.query("limit"));
310
+ return c.json({
311
+ ok: true,
312
+ threads: service.listWorkThreads({
313
+ ...projectId ? { projectId } : {},
314
+ ...Number.isFinite(limit) ? { limit } : {}
315
+ })
316
+ });
317
+ });
318
+ authenticated.get("/api/work-understanding/metrics", (c) => c.json({
319
+ ok: true,
320
+ metrics: service.getUnderstandingMetrics()
321
+ }));
322
+ authenticated.get("/api/work-understanding/sources/:sourceId/lineage", (c) => {
323
+ const lineage = service.getSourceLineage(c.req.param("sourceId"));
324
+ return lineage ? c.json({
325
+ ok: true,
326
+ lineage
327
+ }) : c.json({
328
+ ok: false,
329
+ error: "Source not found"
330
+ }, 404);
331
+ });
332
+ authenticated.delete("/api/work-understanding/sources/:sourceId/derived-data", limited, (c) => {
333
+ const deleted = service.deleteSourceDerivedData(c.req.param("sourceId"));
334
+ return deleted ? c.json({
335
+ ok: true,
336
+ deleted
337
+ }) : c.json({
338
+ ok: false,
339
+ error: "Source not found"
340
+ }, 404);
341
+ });
342
+ authenticated.get("/api/work-understanding/threads/:threadId", (c) => {
343
+ const thread = service.getWorkThread(c.req.param("threadId"));
344
+ return thread ? c.json({
345
+ ok: true,
346
+ thread
347
+ }) : c.json({
348
+ ok: false,
349
+ error: "Work thread not found"
350
+ }, 404);
351
+ });
352
+ authenticated.patch("/api/work-understanding/threads/:threadId", limited, async (c) => {
353
+ const body = await c.req.json().catch(() => null);
354
+ const decision = stringField(body, "decision");
355
+ if (![
356
+ "confirmed",
357
+ "corrected",
358
+ "rejected",
359
+ "paused",
360
+ "completed"
361
+ ].includes(decision)) return c.json({
362
+ ok: false,
363
+ error: "Invalid work thread decision"
364
+ }, 400);
365
+ const thread = service.updateWorkThread({
366
+ id: c.req.param("threadId"),
367
+ decision,
368
+ ...stringField(body, "correctedTitle") ? { correctedTitle: stringField(body, "correctedTitle") } : {},
369
+ ...stringField(body, "correctedSummary") ? { correctedSummary: stringField(body, "correctedSummary") } : {}
370
+ });
371
+ return thread ? c.json({
372
+ ok: true,
373
+ thread
374
+ }) : c.json({
375
+ ok: false,
376
+ error: "Work thread not found"
377
+ }, 404);
378
+ });
379
+ authenticated.get("/api/focuses", (c) => {
380
+ return c.json({
381
+ ok: true,
382
+ focuses: focuses.list({ includeUnreviewed: c.req.query("includeUnreviewed") === "true" })
383
+ });
384
+ });
385
+ authenticated.post("/api/focuses/:focusId/confirm", limited, (c) => {
386
+ const focus = focuses.confirm(c.req.param("focusId"));
387
+ return focus ? c.json({
388
+ ok: true,
389
+ focus
390
+ }) : c.json({
391
+ ok: false,
392
+ error: "Focus not found"
393
+ }, 404);
394
+ });
395
+ authenticated.post("/api/focuses/:focusId/watches/trial", limited, async (c) => {
396
+ const requestedKind = stringField(await c.req.json().catch(() => null), "kind");
397
+ const kind = [
398
+ "progress",
399
+ "staleness",
400
+ "deadline",
401
+ "intelligence"
402
+ ].includes(requestedKind) ? requestedKind : void 0;
403
+ try {
404
+ const result = await focuses.activateTrial({
405
+ threadId: c.req.param("focusId"),
406
+ ...kind ? { kind } : {}
407
+ });
408
+ return c.json({
409
+ ok: true,
410
+ ...result
411
+ }, 201);
412
+ } catch (error) {
413
+ return c.json({
414
+ ok: false,
415
+ error: error instanceof Error ? error.message : String(error)
416
+ }, 400);
417
+ }
418
+ });
419
+ authenticated.post("/api/focuses/:focusId/watches/:watchId/pause", limited, async (c) => {
420
+ const watch = focuses.list({ includeUnreviewed: true }).find((item) => item.id === c.req.param("focusId"))?.watches.find((item) => item.id === c.req.param("watchId"));
421
+ if (!watch) return c.json({
422
+ ok: false,
423
+ error: "Watch not found"
424
+ }, 404);
425
+ const paused = await focuses.pauseWatch(watch.id);
426
+ return c.json({
427
+ ok: true,
428
+ watch: paused
429
+ });
430
+ });
431
+ authenticated.patch("/api/proactive/insights/:insightId", limited, async (c) => {
432
+ const requested = stringField(await c.req.json().catch(() => null), "status");
433
+ const status = requested === "read" || requested === "dismissed" ? requested : void 0;
434
+ if (!status) return c.json({
435
+ ok: false,
436
+ error: "Status must be read or dismissed"
437
+ }, 400);
438
+ const insight = setProactiveInsightStatus(c.req.param("insightId"), status, Date.now(), "unread");
439
+ if (!insight) return c.json({
440
+ ok: false,
441
+ error: "Insight was already handled or not found"
442
+ }, 409);
443
+ if (status === "dismissed") await focuses.recordInsightFeedback(insight.watchId, false);
444
+ return c.json({
445
+ ok: true,
446
+ insight
447
+ });
448
+ });
449
+ authenticated.post("/api/proactive/insights/:insightId/approve", limited, async (c) => {
450
+ const insight = getProactiveInsight(c.req.param("insightId"));
451
+ if (!insight) return c.json({
452
+ ok: false,
453
+ error: "Insight not found"
454
+ }, 404);
455
+ if (insight.status !== "unread") return c.json({
456
+ ok: false,
457
+ error: `Insight is ${insight.status}`
458
+ }, 409);
459
+ const focus = focuses.list({ includeUnreviewed: true }).find((item) => item.watches.some((watch) => watch.id === insight.watchId));
460
+ if (!focus) return c.json({
461
+ ok: false,
462
+ error: "Focus not found"
463
+ }, 404);
464
+ if (!claimProactiveInsightApproval(insight.id)) return c.json({
465
+ ok: false,
466
+ error: "Insight was already handled"
467
+ }, 409);
468
+ let automationId;
469
+ try {
470
+ const automation = await deps.service.automationServiceInstance.create({
471
+ name: `Investigate: ${insight.title}`.slice(0, 200),
472
+ description: `User-approved read-only proposal from proactive insight ${insight.id}.`,
473
+ ...focus.projectIds[0] ? { projectId: focus.projectIds[0] } : {},
474
+ trigger: { kind: "manual" },
475
+ action: {
476
+ kind: "agent",
477
+ instruction: [
478
+ "The user approved this evidence-backed proposal for read-only investigation and preparation.",
479
+ `Focus: ${focus.title}`,
480
+ `Observed change: ${insight.summary}`,
481
+ `Why it matters: ${insight.whyItMatters}`,
482
+ `Approved next step: ${insight.nextAction}`,
483
+ `Evidence: ${JSON.stringify(insight.evidence)}`,
484
+ "Investigate or prepare the requested material. Return a concise result with evidence. Do not modify files or external systems."
485
+ ].join("\n"),
486
+ timeoutSeconds: 300
487
+ },
488
+ safety: { mode: "suggest_only" },
489
+ afterRun: { kind: "none" },
490
+ reliability: {
491
+ timeoutSeconds: 300,
492
+ disableAfterConsecutiveFailures: 1
493
+ }
494
+ });
495
+ automationId = automation.id;
496
+ const run = await deps.service.automationServiceInstance.runNow(automation.id);
497
+ await focuses.recordInsightFeedback(insight.watchId, true);
498
+ return c.json({
499
+ ok: true,
500
+ automationId: automation.id,
501
+ runId: run.id
502
+ }, 202);
503
+ } catch (error) {
504
+ if (automationId) await deps.service.automationServiceInstance.remove(automationId);
505
+ setProactiveInsightStatus(insight.id, "unread", Date.now(), "approved");
506
+ return c.json({
507
+ ok: false,
508
+ error: error instanceof Error ? error.message : String(error)
509
+ }, 500);
510
+ }
511
+ });
512
+ authenticated.post("/api/focuses/:focusId/calendar/:signalId/prepare", limited, async (c) => {
513
+ const focus = focuses.list().find((item) => item.id === c.req.param("focusId"));
514
+ if (!focus) return c.json({
515
+ ok: false,
516
+ error: "Focus not found"
517
+ }, 404);
518
+ const signal = listFocusCalendarSignals([focus]).find((item) => item.id === c.req.param("signalId"));
519
+ if (!signal) return c.json({
520
+ ok: false,
521
+ error: "Calendar event not found"
522
+ }, 404);
523
+ const eventContext = `${signal.title} at ${new Date(signal.startsAt).toISOString()}`;
524
+ try {
525
+ const result = await focuses.activateTrial({
526
+ threadId: focus.id,
527
+ kind: "deadline",
528
+ eventContext
529
+ });
530
+ return c.json({
531
+ ok: true,
532
+ ...result
533
+ });
534
+ } catch (error) {
535
+ return c.json({
536
+ ok: false,
537
+ error: error instanceof Error ? error.message : String(error)
538
+ }, 500);
539
+ }
540
+ });
120
541
  authenticated.post("/api/work-discovery/runs/:runId/cancel", (c) => {
121
542
  const run = service.cancelRun(c.req.param("runId"));
122
543
  return run ? c.json({
@@ -169,6 +590,36 @@ function registerWorkDiscoveryRoutes(authenticated, deps) {
169
590
  }, 400);
170
591
  }
171
592
  });
593
+ authenticated.post("/api/work-discovery/runs/:runId/profile", limited, async (c) => {
594
+ const body = await c.req.json().catch(() => null);
595
+ const decisions = (body && typeof body === "object" && Array.isArray(body.decisions) ? body.decisions : []).flatMap((value) => {
596
+ if (!value || typeof value !== "object") return [];
597
+ const item = value;
598
+ const id = typeof item.id === "string" ? item.id.trim() : "";
599
+ const status = item.status === "accepted" || item.status === "edited" || item.status === "rejected" ? item.status : void 0;
600
+ if (!id || !status) return [];
601
+ return [{
602
+ id,
603
+ status,
604
+ ...typeof item.statement === "string" ? { statement: item.statement } : {}
605
+ }];
606
+ }).slice(0, 10);
607
+ if (!decisions.length) return c.json({
608
+ ok: false,
609
+ error: "At least one valid decision is required"
610
+ }, 400);
611
+ const run = service.updateProfileCandidates({
612
+ runId: c.req.param("runId"),
613
+ decisions
614
+ });
615
+ return run ? c.json({
616
+ ok: true,
617
+ run
618
+ }) : c.json({
619
+ ok: false,
620
+ error: "Profile candidates not found"
621
+ }, 404);
622
+ });
172
623
  authenticated.post("/api/work-discovery/runs/:runId/suggestions/:suggestionId/select", (c) => {
173
624
  return service.selectSuggestion(c.req.param("runId"), c.req.param("suggestionId")) ? c.json({ ok: true }) : c.json({
174
625
  ok: false,
@@ -61,6 +61,7 @@ export declare class GatewayService {
61
61
  private connectedKnowledgeCoordinator;
62
62
  private stopAutomationProductEventBridge;
63
63
  private stopSessionTranscriptAutomationEvents;
64
+ private stopFocusTrialExpiryReconciler;
64
65
  /**
65
66
  * Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,
66
67
  * `submitClarifyResponse`, clarify-bridge dispatch). Owns the
@@ -267,6 +268,7 @@ export declare class GatewayService {
267
268
  processDirect(content: string, sessionKey?: string): Promise<string>;
268
269
  subscribe(sessionId: string, listener: (event: ServiceEvent) => Promise<void> | void): () => void;
269
270
  emit(type: string, payload: unknown): void;
271
+ private handleAutomationRunCompleted;
270
272
  private startAutomationProductEventBridge;
271
273
  /** Replay events since `lastEventId` for SSE reconnection. */
272
274
  getEventsSince(sessionId: string, lastEventId: string): ServiceEvent[];
@@ -48,6 +48,10 @@ import { startConnectorMemorySyncCoordinator } from "../connectors/memory-sync-c
48
48
  import { startConnectorSupervisor } from "../connectors/supervisor.js";
49
49
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
50
50
  import { reconcileDreamingAutomations } from "./dreaming-automation-reconciler.js";
51
+ import { FocusService } from "../proactive/focus-service.js";
52
+ import { processFocusAutomationRun } from "../proactive/run-processor.js";
53
+ import { startTrialExpiryReconciler } from "../proactive/trial-expiry-reconciler.js";
54
+ import "../proactive/index.js";
51
55
  import { NotesStore } from "../notes/store.js";
52
56
  import { buildNoteAgentContext } from "../notes/agent-context.js";
53
57
  import { NotesService } from "../notes/service.js";
@@ -141,6 +145,7 @@ var GatewayService = class {
141
145
  connectedKnowledgeCoordinator = null;
142
146
  stopAutomationProductEventBridge = null;
143
147
  stopSessionTranscriptAutomationEvents = null;
148
+ stopFocusTrialExpiryReconciler = null;
144
149
  /**
145
150
  * Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,
146
151
  * `submitClarifyResponse`, clarify-bridge dispatch). Owns the
@@ -356,7 +361,7 @@ var GatewayService = class {
356
361
  getDefaultAgentId: () => getDefaultAgentId(this.config),
357
362
  getProjectWorkspaceRoot: (projectId) => this.projects.get(projectId)?.workspaceRoot,
358
363
  workflowRunService: this.createWorkflowRunService(),
359
- onRunCompleted: (run) => this.emit("automation.run.completed", { run })
364
+ onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
360
365
  });
361
366
  this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {
362
367
  const scheduleWhenIdle = () => {
@@ -666,7 +671,7 @@ var GatewayService = class {
666
671
  agentService: this.agentService,
667
672
  getDefaultAgentId: () => getDefaultAgentId(this.config),
668
673
  workflowRunService: this.createWorkflowRunService(),
669
- onRunCompleted: (run) => this.emit("automation.run.completed", { run })
674
+ onRunCompleted: (run) => this.handleAutomationRunCompleted(run)
670
675
  });
671
676
  this.startAutomationProductEventBridge();
672
677
  await trace.measure("workflows.reconcile", () => this.reconcileInterruptedWorkflowRuns());
@@ -679,6 +684,7 @@ var GatewayService = class {
679
684
  });
680
685
  await trace.measure("automations.initialize", () => this.automationService.initialize());
681
686
  await trace.measure("dreaming.reconcile", () => this.reconcileDreamingAutomations());
687
+ this.stopFocusTrialExpiryReconciler = startTrialExpiryReconciler(new FocusService(this.automationService));
682
688
  await this.notesService.initialize();
683
689
  this.ensureHeartbeatService().start(heartbeatRunnerConfigFromConfig(this.config));
684
690
  this.connectorSupervisor = startConnectorSupervisor({
@@ -834,6 +840,8 @@ var GatewayService = class {
834
840
  this.lastChannelConnectDeferMode = "auto";
835
841
  this.lastChannelConnectDeferSource = "off";
836
842
  await this.channelManager.stop();
843
+ await this.stopFocusTrialExpiryReconciler?.();
844
+ this.stopFocusTrialExpiryReconciler = null;
837
845
  await this.automationService.stop();
838
846
  this.stopAutomationProductEventBridge?.();
839
847
  this.stopAutomationProductEventBridge = null;
@@ -1234,6 +1242,23 @@ var GatewayService = class {
1234
1242
  this.createGoalNotificationService().handleGatewayEvent(type, payload);
1235
1243
  this.createMobileNotificationService().handleGatewayEvent(type, payload);
1236
1244
  }
1245
+ handleAutomationRunCompleted(run) {
1246
+ try {
1247
+ const proactive = processFocusAutomationRun(run);
1248
+ this.emit("automation.run.completed", {
1249
+ run,
1250
+ silent: proactive.handled
1251
+ });
1252
+ if (proactive.insight) this.emit("proactive.insight.created", { insight: proactive.insight });
1253
+ } catch (err) {
1254
+ log.warn({
1255
+ err,
1256
+ automationId: run.automationId,
1257
+ runId: run.id
1258
+ }, "Proactive result processing failed");
1259
+ this.emit("automation.run.completed", { run });
1260
+ }
1261
+ }
1237
1262
  startAutomationProductEventBridge() {
1238
1263
  this.stopAutomationProductEventBridge?.();
1239
1264
  this.stopSessionTranscriptAutomationEvents?.();
@@ -44,6 +44,7 @@ function goalEvent(payload) {
44
44
  }
45
45
  function automationEvent(payload) {
46
46
  if (!payload || typeof payload !== "object") return null;
47
+ if (payload.silent === true) return null;
47
48
  const run = payload.run;
48
49
  if (!run || run.status !== "failed" && run.status !== "timeout" && run.status !== "succeeded") return null;
49
50
  const type = run.status === "succeeded" ? "automation.completed" : "automation.failed";