@xopcai/xopc 0.0.159 → 0.0.161

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 (215) 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-BIVBUiNT.js} +1 -1
  4. package/dist/gateway/static/root/assets/activity-store-o7GRljfD.js +1 -0
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BeVf03hx.js → agent-avatar-dicebear-9R3szLMc.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-_qbUaYbs.js +2 -0
  7. package/dist/gateway/static/root/assets/{api-BjcBIV2O.js → api-jSTqFMq9.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-BG2ulMYw.js → app-management-settings-panel-D81cyE76.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-0Kjenr2T.js → appearance-settings-Ct6bZQCV.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-0sPqD0FK.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-ChiNnH1e.js → archive-plugin-CfD7AZKn.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-pbBlQR-g.js → attachment-load-CP_Gaxt3.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automation-suggestion-card-CTZDOyDy.js → automation-suggestion-card-BGKM_NDZ.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-BxWBuBsE.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BeZGzpGF.js → binary-plugins-IPr2EVnS.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-BnDmhN5Z.js → block-editor-B6aHEGA6.js} +3 -3
  17. package/dist/gateway/static/root/assets/browser-settings-page-C499b9AH.js +8 -0
  18. package/dist/gateway/static/root/assets/{capability-presets-api-Ii36j_7v.js → capability-presets-api-CCX9-LjU.js} +1 -1
  19. package/dist/gateway/static/root/assets/{capability-presets-settings-panel-Cl3dw4yh.js → capability-presets-settings-panel-Dva9SiPK.js} +2 -2
  20. package/dist/gateway/static/root/assets/{channel-recipient-api-CFqrSi5K.js → channel-recipient-api-MmLMLDWf.js} +1 -1
  21. package/dist/gateway/static/root/assets/channels-settings-DNAU7u9o.js +1 -0
  22. package/dist/gateway/static/root/assets/channels-status-swr-CIOH7tgn.js +1 -0
  23. package/dist/gateway/static/root/assets/check-DUBLcKHA.js +1 -0
  24. package/dist/gateway/static/root/assets/circle-alert-BEjgurr2.js +1 -0
  25. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-CiLxuZ8S.js → connector-logo-BbjzIs87.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-TwiBp8vY.js +2 -0
  28. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +1 -0
  29. package/dist/gateway/static/root/assets/desktop-pet-CYH5ZSXy.js +1 -0
  30. package/dist/gateway/static/root/assets/desktop-pet-settings-DQLqGLc0.js +1 -0
  31. package/dist/gateway/static/root/assets/desktop-pet-sprite-DTqXSpqf.js +1 -0
  32. package/dist/gateway/static/root/assets/{directory-picker-path-field-CC2VL5Mc.js → directory-picker-path-field-ClsiXhmz.js} +1 -1
  33. package/dist/gateway/static/root/assets/{dreaming-settings-KY7ZfVsy.js → dreaming-settings-CjMPPdzg.js} +3 -3
  34. package/dist/gateway/static/root/assets/{extension-debug-page-C8KBeucs.js → extension-debug-page-57eizjhB.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-page-CV-5Kcyk.js → extension-page-CsbSb3u1.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-DvUtDrAu.js → extension-settings-page-DKA9-lyP.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-api-DXfVeJLc.js → gateway-config-api-DIPJuzBZ.js} +1 -1
  38. package/dist/gateway/static/root/assets/gateway-settings-CDLqAQY7.js +1 -0
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-cxQ94qMm.js → gateway-startup-retry-DrfSJtvT.js} +1 -1
  40. package/dist/gateway/static/root/assets/goal-create-dialog-Q3B0E-0s.js +1 -0
  41. package/dist/gateway/static/root/assets/goal-detail-page-C5VAK04G.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-P8VhLqYF.js → goals-config-api-lGC10UkU.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-BJb-5IYw.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-DHXyaH_O.js → goals-settings-BWq0pdrA.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-CNckP_Dv.js → heartbeat-settings-D4o8BJVv.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-CkUHH170.css +1 -0
  47. package/dist/gateway/static/root/assets/index-vq_cJZJC.js +199 -0
  48. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-jXmv1RVX.js → keyboard-shortcuts-settings-6T2QYehS.js} +1 -1
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-euH17Kvb.js +2 -0
  50. package/dist/gateway/static/root/assets/{local-apps-page-Cs5LKjtc.js → local-apps-page-DCjg2K9f.js} +1 -1
  51. package/dist/gateway/static/root/assets/{locale-store-C_M71MK9.js → locale-store-Dar-xqQr.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-CyYCBqym.js +7 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-BFqeSNte.js → markdown-split-rt1XO43g.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-Cc8379gq.js → media-plugins-Bwo8CJuh.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-CxySDn9d.js +5 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-DObxxjc9.js +2 -0
  57. package/dist/gateway/static/root/assets/{notes-page-DlGU4ipo.js → notes-page-Dp-pkX7d.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-CCb4RXcZ.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-kFOswGlG.js → page-tabs-CzZ4iKOb.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-CvjuvABg.js → preview-open-alternatives-3E_Qa-58.js} +1 -1
  61. package/dist/gateway/static/root/assets/product-delivery-BTRT9kCS.js +1 -0
  62. package/dist/gateway/static/root/assets/product-open-page-B2T48Sbt.js +1 -0
  63. package/dist/gateway/static/root/assets/project-detail-page-BvEcriRC.js +1 -0
  64. package/dist/gateway/static/root/assets/projects-page-B_e79MRJ.js +1 -0
  65. package/dist/gateway/static/root/assets/remote-access-hub-DGcqnYfR.js +1 -0
  66. package/dist/gateway/static/root/assets/{save-bar-controls-DwrD7ODx.js → save-bar-controls-CkeKasGm.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schedule-field-Ba4WzTmE.js → schedule-field-TkqUL3wm.js} +1 -1
  68. package/dist/gateway/static/root/assets/{schema-form-DvydL8eF.js → schema-form-DC-iU5IG.js} +1 -1
  69. package/dist/gateway/static/root/assets/sessions-page-DQZhrDJ8.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-BkdeN99Y.js +1 -0
  71. package/dist/gateway/static/root/assets/{settings-collapsible-section-LaQqGGej.js → settings-collapsible-section-Dpqth3oA.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-form-section-DruI__qO.js → settings-form-section-CNqF6IwY.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-loading-skeleton-UvA-eDhF.js → settings-loading-skeleton-DkvwitK_.js} +1 -1
  74. package/dist/gateway/static/root/assets/{settings-page-layout-DG-XMIPu.js → settings-page-layout-DWvNgISx.js} +1 -1
  75. package/dist/gateway/static/root/assets/{settings-page-5oCGSebm.js → settings-page-qPG7I2zd.js} +1 -1
  76. package/dist/gateway/static/root/assets/setup-status-panel-lwRAh9aw.js +1 -0
  77. package/dist/gateway/static/root/assets/{share-preview-page-FLVeTrRt.js → share-preview-page-DGpSPW-n.js} +1 -1
  78. package/dist/gateway/static/root/assets/shares-settings-BGj9IVUr.js +1 -0
  79. package/dist/gateway/static/root/assets/skill-reload-api-B2UBAs5U.js +1 -0
  80. package/dist/gateway/static/root/assets/skills-page-DdjzFZ8I.js +2 -0
  81. package/dist/gateway/static/root/assets/{system-settings-panel-CeK93xVi.js → system-settings-panel-8TxxSbUw.js} +1 -1
  82. package/dist/gateway/static/root/assets/{theme-store-C8ohIHhw.js → theme-store-B5FzMWOx.js} +1 -1
  83. package/dist/gateway/static/root/assets/{typed-models-lib-D1Lr2gG0.js → typed-models-lib-DEGtSA5h.js} +1 -1
  84. package/dist/gateway/static/root/assets/{use-channel-catalog-BWzou5ar.js → use-channel-catalog-BDU6FneG.js} +1 -1
  85. package/dist/gateway/static/root/assets/user-context-page-BTTZpAGV.js +1 -0
  86. package/dist/gateway/static/root/assets/voice-api-key-field-DuDQd-WU.js +1 -0
  87. package/dist/gateway/static/root/assets/work-discovery-page-BUVkVCsW.js +1 -0
  88. package/dist/gateway/static/root/assets/work-item-detail-page-DeEPPu4n.js +1 -0
  89. package/dist/gateway/static/root/assets/work-page-DQNUyTUq.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-Bynqe4kV.js → workflow-run-setup-panel-Cwi8Pz7n.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-BIy4wrzO.js +11 -0
  92. package/dist/gateway/static/root/index.html +12 -10
  93. package/dist/package.js +1 -1
  94. package/dist/src/automations/service/action-executor.js +1 -1
  95. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  96. package/dist/src/config/agent-profile.js +1 -1
  97. package/dist/src/gateway/agents-admin.js +1 -1
  98. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  99. package/dist/src/gateway/chat-stream/mapper.js +43 -7
  100. package/dist/src/gateway/hono/routes/home.js +15 -2
  101. package/dist/src/gateway/hono/routes/work-discovery.js +451 -0
  102. package/dist/src/gateway/hono/sse.d.ts +2 -0
  103. package/dist/src/gateway/hono/sse.js +10 -3
  104. package/dist/src/gateway/run-loop.js +17 -7
  105. package/dist/src/gateway/server.d.ts +1 -0
  106. package/dist/src/gateway/server.js +9 -0
  107. package/dist/src/gateway/service.d.ts +2 -0
  108. package/dist/src/gateway/service.js +27 -2
  109. package/dist/src/local-apps/preview-runtime-bridge.d.ts +1 -1
  110. package/dist/src/local-apps/preview-runtime-bridge.js +14 -11
  111. package/dist/src/mobile/notification-service.js +1 -0
  112. package/dist/src/pets/factory.js +23 -26
  113. package/dist/src/pets/manifest.d.ts +2 -1
  114. package/dist/src/pets/manifest.js +15 -8
  115. package/dist/src/pets/validator.js +8 -3
  116. package/dist/src/proactive/calendar-signals.d.ts +4 -0
  117. package/dist/src/proactive/calendar-signals.js +120 -0
  118. package/dist/src/proactive/focus-service.d.ts +62 -0
  119. package/dist/src/proactive/focus-service.js +173 -0
  120. package/dist/src/proactive/index.d.ts +7 -0
  121. package/dist/src/proactive/index.js +7 -0
  122. package/dist/src/proactive/insight-repository.d.ts +19 -0
  123. package/dist/src/proactive/insight-repository.js +106 -0
  124. package/dist/src/proactive/run-processor.d.ts +19 -0
  125. package/dist/src/proactive/run-processor.js +125 -0
  126. package/dist/src/proactive/trial-expiry-reconciler.d.ts +5 -0
  127. package/dist/src/proactive/trial-expiry-reconciler.js +30 -0
  128. package/dist/src/proactive/types.d.ts +64 -0
  129. package/dist/src/proactive/types.js +1 -0
  130. package/dist/src/proactive/watch-repository.d.ts +28 -0
  131. package/dist/src/proactive/watch-repository.js +129 -0
  132. package/dist/src/storage/sqlite/knowledge-repository.d.ts +1 -0
  133. package/dist/src/storage/sqlite/knowledge-repository.js +4 -0
  134. package/dist/src/storage/sqlite/migrations/047_work_discovery_sources.sql +16 -0
  135. package/dist/src/storage/sqlite/migrations/048_work_understanding_investigations.sql +40 -0
  136. package/dist/src/storage/sqlite/migrations/049_work_understanding_threads.sql +52 -0
  137. package/dist/src/storage/sqlite/migrations/050_work_discovery_source_refreshes.sql +15 -0
  138. package/dist/src/storage/sqlite/migrations/051_focus_watches.sql +26 -0
  139. package/dist/src/storage/sqlite/migrations/052_proactive_insights.sql +25 -0
  140. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  141. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  142. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  143. package/dist/src/storage/sqlite/schema.js +1 -1
  144. package/dist/src/work-discovery/analyzer.d.ts +12 -1
  145. package/dist/src/work-discovery/analyzer.js +126 -7
  146. package/dist/src/work-discovery/candidate-discovery.d.ts +17 -0
  147. package/dist/src/work-discovery/candidate-discovery.js +279 -0
  148. package/dist/src/work-discovery/evaluation.d.ts +11 -0
  149. package/dist/src/work-discovery/evaluation.js +17 -0
  150. package/dist/src/work-discovery/governance.d.ts +25 -0
  151. package/dist/src/work-discovery/governance.js +96 -0
  152. package/dist/src/work-discovery/incremental-repository.d.ts +13 -0
  153. package/dist/src/work-discovery/incremental-repository.js +55 -0
  154. package/dist/src/work-discovery/incremental.d.ts +2 -0
  155. package/dist/src/work-discovery/incremental.js +7 -0
  156. package/dist/src/work-discovery/index.d.ts +10 -0
  157. package/dist/src/work-discovery/index.js +13 -3
  158. package/dist/src/work-discovery/investigation-repository.d.ts +16 -0
  159. package/dist/src/work-discovery/investigation-repository.js +122 -0
  160. package/dist/src/work-discovery/investigator.d.ts +55 -0
  161. package/dist/src/work-discovery/investigator.js +358 -0
  162. package/dist/src/work-discovery/probe.d.ts +22 -0
  163. package/dist/src/work-discovery/probe.js +88 -1
  164. package/dist/src/work-discovery/service.d.ts +110 -1
  165. package/dist/src/work-discovery/service.js +578 -8
  166. package/dist/src/work-discovery/source-repository.d.ts +13 -0
  167. package/dist/src/work-discovery/source-repository.js +72 -0
  168. package/dist/src/work-discovery/thread-repository.d.ts +34 -0
  169. package/dist/src/work-discovery/thread-repository.js +112 -0
  170. package/dist/src/work-discovery/thread-service.d.ts +8 -0
  171. package/dist/src/work-discovery/thread-service.js +104 -0
  172. package/dist/src/work-discovery/types.d.ts +145 -0
  173. package/package.json +1 -1
  174. package/skills/creative/hatch-pet/SKILL.md +2 -2
  175. package/dist/gateway/static/root/assets/activity-store-C-57rvkX.js +0 -1
  176. package/dist/gateway/static/root/assets/agents-P05C4A-3.js +0 -2
  177. package/dist/gateway/static/root/assets/apps-page-DANGrBpN.js +0 -1
  178. package/dist/gateway/static/root/assets/automations-page-BXfGL_cm.js +0 -6
  179. package/dist/gateway/static/root/assets/browser-settings-page-534luV0B.js +0 -8
  180. package/dist/gateway/static/root/assets/channels-settings-M91zFJVi.js +0 -1
  181. package/dist/gateway/static/root/assets/channels-status-swr-vooEF4lG.js +0 -1
  182. package/dist/gateway/static/root/assets/check-BODqo66o.js +0 -1
  183. package/dist/gateway/static/root/assets/circle-alert-RzVebuX2.js +0 -1
  184. package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +0 -1
  185. package/dist/gateway/static/root/assets/connectors-page-CV5UulW6.js +0 -2
  186. package/dist/gateway/static/root/assets/desktop-pet-Cil2eSpW.js +0 -1
  187. package/dist/gateway/static/root/assets/desktop-pet-settings-DwsC6l5F.js +0 -1
  188. package/dist/gateway/static/root/assets/desktop-pet-sprite-DqZ6fbIj.js +0 -1
  189. package/dist/gateway/static/root/assets/gateway-settings-BpJ0v56l.js +0 -1
  190. package/dist/gateway/static/root/assets/goal-create-dialog-lMHD-2CX.js +0 -1
  191. package/dist/gateway/static/root/assets/goal-detail-page-yPmF-G7b.js +0 -4
  192. package/dist/gateway/static/root/assets/goals-page-BHTCKobG.js +0 -2
  193. package/dist/gateway/static/root/assets/index-BgZhEOkN.css +0 -1
  194. package/dist/gateway/static/root/assets/index-BuqGh2SW.js +0 -193
  195. package/dist/gateway/static/root/assets/local-app-workbench-page-zpp_wciE.js +0 -2
  196. package/dist/gateway/static/root/assets/logs-page-B4CRYqYR.js +0 -7
  197. package/dist/gateway/static/root/assets/messages-BuT0SR1R.js +0 -5
  198. package/dist/gateway/static/root/assets/models-hub-panel-1hdoAoB_.js +0 -2
  199. package/dist/gateway/static/root/assets/notes-workbench-DQEAZTA5.js +0 -4
  200. package/dist/gateway/static/root/assets/project-detail-page-Bp9bC7A6.js +0 -1
  201. package/dist/gateway/static/root/assets/projects-page-RNorFXTw.js +0 -1
  202. package/dist/gateway/static/root/assets/remote-access-hub-BqRTcM_6.js +0 -1
  203. package/dist/gateway/static/root/assets/sessions-page-B2EfW1cm.js +0 -1
  204. package/dist/gateway/static/root/assets/settings-advanced-gate-CklL85T4.js +0 -1
  205. package/dist/gateway/static/root/assets/setup-status-panel-D3my1HgB.js +0 -1
  206. package/dist/gateway/static/root/assets/shares-settings-DVxgjrsP.js +0 -1
  207. package/dist/gateway/static/root/assets/skill-reload-api-Bcu58ZaF.js +0 -1
  208. package/dist/gateway/static/root/assets/skills-page-CDd-84FE.js +0 -2
  209. package/dist/gateway/static/root/assets/sliding-segmented-uWmrxE3P.js +0 -1
  210. package/dist/gateway/static/root/assets/user-context-page-1OyJnTyR.js +0 -1
  211. package/dist/gateway/static/root/assets/voice-api-key-field-B2ncRwHS.js +0 -1
  212. package/dist/gateway/static/root/assets/work-discovery-page-BZlY4PZL.js +0 -1
  213. package/dist/gateway/static/root/assets/work-item-detail-page-DPXMrneY.js +0 -1
  214. package/dist/gateway/static/root/assets/work-page-CTERoqyv.js +0 -1
  215. package/dist/gateway/static/root/assets/workflows-page-CLgsnqFQ.js +0 -11
@@ -0,0 +1,173 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { GoalService } from "../goals/goal-service.js";
4
+ import "../goals/index.js";
5
+ import { addWorkUnderstandingThreadFeedback, getWorkUnderstandingThread, listWorkUnderstandingThreads } from "../work-discovery/thread-repository.js";
6
+ import { createFocusWatch, getFocusWatchByThreadAndKind, listFocusWatches, recordFocusWatchFeedback, restartFocusWatchTrial, setFocusWatchStatus } from "./watch-repository.js";
7
+ //#region src/proactive/focus-service.ts
8
+ init_logger();
9
+ const TRIAL_DURATION_MS = 7 * 864e5;
10
+ const DAILY_INTERVAL_MS = 1440 * 60 * 1e3;
11
+ const log = createLogger("FocusService");
12
+ function instructionForFocus(title, summary, kind, eventContext) {
13
+ const intent = kind === "progress" ? "Look for meaningful progress, blockers, and the most useful next step." : kind === "staleness" ? "Check whether this focus has stalled and identify the smallest credible unblock." : kind === "deadline" ? "Check upcoming deadlines or meetings and prepare only the material that is needed next." : "Search for external changes published since the previous daily check. Use primary sources when possible, include the publication date and canonical URL, reject generic background news, and explain the concrete impact on this focus.";
14
+ return [
15
+ "Maintain this user-confirmed focus in suggest-only mode.",
16
+ `Focus: ${title}`,
17
+ `Context: ${summary}`,
18
+ ...eventContext ? [`Upcoming event selected by the user: ${eventContext}`] : [],
19
+ intent,
20
+ "Inspect only evidence that changed since the previous daily check; use timestamps, history, status, or source revisions to establish the delta.",
21
+ "Use evidence available to the agent. Do not modify files, send messages, publish content, or claim progress without evidence.",
22
+ "Return JSON only, with no markdown.",
23
+ "If nothing materially changed: {\"meaningful\":false}.",
24
+ "Otherwise return {\"meaningful\":true,\"title\":\"short title\",\"summary\":\"what changed\",\"whyItMatters\":\"concrete impact\",\"nextAction\":\"one next action\",\"evidence\":[{\"label\":\"specific observed evidence\",\"source\":\"file, event, or canonical URL\",\"publishedAt\":\"ISO date when this is external news\"}]}.",
25
+ "A meaningful result requires at least one specific evidence item. Never invent evidence. Keep the entire JSON response under 2,000 characters."
26
+ ].join("\n");
27
+ }
28
+ var FocusService = class {
29
+ goals = new GoalService();
30
+ constructor(automations) {
31
+ this.automations = automations;
32
+ }
33
+ list(options = {}) {
34
+ const threads = listWorkUnderstandingThreads({ limit: 200 }).filter((thread) => options.includeUnreviewed || thread.userStatus === "confirmed" || thread.userStatus === "corrected");
35
+ const watches = listFocusWatches();
36
+ const goals = this.goals.list({
37
+ status: [
38
+ "active",
39
+ "blocked",
40
+ "needs_input",
41
+ "paused"
42
+ ],
43
+ limit: 200
44
+ });
45
+ return threads.map((thread) => {
46
+ const goal = goals.find((candidate) => candidate.projectId && thread.projectIds.includes(candidate.projectId));
47
+ return {
48
+ id: thread.id,
49
+ title: thread.title,
50
+ summary: thread.summary,
51
+ status: thread.status,
52
+ horizon: thread.horizon,
53
+ confidence: thread.confidence,
54
+ focusScore: thread.focusScore,
55
+ userStatus: thread.userStatus,
56
+ projectIds: thread.projectIds,
57
+ ...goal ? {
58
+ goalId: goal.id,
59
+ nextAction: goal.nextAction,
60
+ blockedReason: goal.blockedReason
61
+ } : {},
62
+ watches: watches.filter((watch) => watch.threadId === thread.id),
63
+ lastObservedAt: thread.lastObservedAt
64
+ };
65
+ });
66
+ }
67
+ confirm(id) {
68
+ const thread = addWorkUnderstandingThreadFeedback({
69
+ threadId: id,
70
+ decision: "confirmed"
71
+ });
72
+ return thread ? this.list({ includeUnreviewed: true }).find((focus) => focus.id === thread.id) ?? null : null;
73
+ }
74
+ async activateTrial(input) {
75
+ const kind = input.kind ?? "progress";
76
+ let thread = getWorkUnderstandingThread(input.threadId);
77
+ if (!thread || thread.userStatus === "rejected") throw new Error("Focus not found");
78
+ if (thread.userStatus === "unreviewed") thread = addWorkUnderstandingThreadFeedback({
79
+ threadId: thread.id,
80
+ decision: "confirmed"
81
+ });
82
+ if (!thread) throw new Error("Focus not found");
83
+ const existing = getFocusWatchByThreadAndKind(thread.id, kind);
84
+ if (existing) {
85
+ if (input.eventContext) await this.automations.update(existing.automationId, { action: {
86
+ kind: "agent",
87
+ instruction: instructionForFocus(thread.title, thread.summary, kind, input.eventContext),
88
+ timeoutSeconds: 300
89
+ } });
90
+ if (existing.status === "paused") {
91
+ await this.automations.resume(existing.automationId);
92
+ restartFocusWatchTrial(existing.id, Date.now() + TRIAL_DURATION_MS);
93
+ }
94
+ if (input.eventContext) this.automations.runNow(existing.automationId).catch((err) => {
95
+ log.warn({
96
+ err,
97
+ automationId: existing.automationId,
98
+ watchId: existing.id
99
+ }, "Focus event preparation run failed");
100
+ });
101
+ return {
102
+ focus: this.list({ includeUnreviewed: true }).find((item) => item.id === thread.id),
103
+ watch: getFocusWatchByThreadAndKind(thread.id, kind)
104
+ };
105
+ }
106
+ const automation = await this.automations.create({
107
+ name: `Keep moving: ${thread.title}`.slice(0, 200),
108
+ description: `Seven-day ${kind} watch for a user-confirmed focus.`,
109
+ ...thread.projectIds[0] ? { projectId: thread.projectIds[0] } : {},
110
+ trigger: {
111
+ kind: "schedule",
112
+ schedule: {
113
+ kind: "interval",
114
+ everyMs: DAILY_INTERVAL_MS
115
+ }
116
+ },
117
+ action: {
118
+ kind: "agent",
119
+ instruction: instructionForFocus(thread.title, thread.summary, kind, input.eventContext),
120
+ timeoutSeconds: 300
121
+ },
122
+ safety: { mode: "suggest_only" },
123
+ afterRun: { kind: "none" },
124
+ reliability: {
125
+ timeoutSeconds: 300,
126
+ disableAfterConsecutiveFailures: 3
127
+ }
128
+ });
129
+ const watch = createFocusWatch({
130
+ threadId: thread.id,
131
+ automationId: automation.id,
132
+ kind,
133
+ config: {
134
+ cadence: "daily",
135
+ notifyOnlyWhenMeaningful: true
136
+ },
137
+ trialEndsAt: Date.now() + TRIAL_DURATION_MS
138
+ });
139
+ this.automations.runNow(automation.id).catch((err) => {
140
+ log.warn({
141
+ err,
142
+ automationId: automation.id,
143
+ watchId: watch.id
144
+ }, "Initial focus watch run failed");
145
+ });
146
+ return {
147
+ focus: this.list({ includeUnreviewed: true }).find((item) => item.id === thread.id),
148
+ watch
149
+ };
150
+ }
151
+ async pauseWatch(id) {
152
+ const watch = listFocusWatches().find((item) => item.id === id);
153
+ if (!watch) return null;
154
+ await this.automations.pause(watch.automationId);
155
+ return setFocusWatchStatus(id, "paused");
156
+ }
157
+ async reconcileExpiredTrials(nowMs = Date.now()) {
158
+ const expired = listFocusWatches({ status: "active" }).filter((watch) => watch.trialEndsAt != null && watch.trialEndsAt <= nowMs);
159
+ for (const watch of expired) {
160
+ await this.automations.pause(watch.automationId);
161
+ setFocusWatchStatus(watch.id, "paused", nowMs);
162
+ }
163
+ return expired.length;
164
+ }
165
+ async recordInsightFeedback(watchId, useful) {
166
+ const result = recordFocusWatchFeedback(watchId, useful);
167
+ if (!result) return null;
168
+ if (!useful && result.consecutiveDismissed >= 3) return this.pauseWatch(watchId);
169
+ return result.watch;
170
+ }
171
+ };
172
+ //#endregion
173
+ export { FocusService };
@@ -0,0 +1,7 @@
1
+ export * from './types.js';
2
+ export * from './calendar-signals.js';
3
+ export * from './focus-service.js';
4
+ export * from './insight-repository.js';
5
+ export * from './run-processor.js';
6
+ export * from './trial-expiry-reconciler.js';
7
+ export * from './watch-repository.js';
@@ -0,0 +1,7 @@
1
+ import { buildFocusCalendarSignals, listFocusCalendarSignals } from "./calendar-signals.js";
2
+ import { createFocusWatch, getFocusWatchByAutomationId, getFocusWatchByThreadAndKind, listFocusWatches, recordFocusWatchFeedback, recordFocusWatchRun, restartFocusWatchTrial, setFocusWatchStatus } from "./watch-repository.js";
3
+ import { FocusService } from "./focus-service.js";
4
+ import { claimProactiveInsightApproval, createProactiveInsight, getProactiveInsight, listProactiveInsights, setProactiveInsightStatus } from "./insight-repository.js";
5
+ import { hasValidIntelligenceEvidence, parseFocusRunResult, processFocusAutomationRun } from "./run-processor.js";
6
+ import { startTrialExpiryReconciler } from "./trial-expiry-reconciler.js";
7
+ export { FocusService, buildFocusCalendarSignals, claimProactiveInsightApproval, createFocusWatch, createProactiveInsight, getFocusWatchByAutomationId, getFocusWatchByThreadAndKind, getProactiveInsight, hasValidIntelligenceEvidence, listFocusCalendarSignals, listFocusWatches, listProactiveInsights, parseFocusRunResult, processFocusAutomationRun, recordFocusWatchFeedback, recordFocusWatchRun, restartFocusWatchTrial, setFocusWatchStatus, setProactiveInsightStatus, startTrialExpiryReconciler };
@@ -0,0 +1,19 @@
1
+ import type { FocusWatchKind, ProactiveEvidence, ProactiveInsight, ProactiveInsightStatus } from './types.js';
2
+ export declare function getProactiveInsight(id: string): ProactiveInsight | null;
3
+ export declare function listProactiveInsights(options?: {
4
+ status?: ProactiveInsightStatus[];
5
+ limit?: number;
6
+ }): ProactiveInsight[];
7
+ export declare function createProactiveInsight(input: {
8
+ watchId: string;
9
+ runId: string;
10
+ kind: FocusWatchKind;
11
+ title: string;
12
+ summary: string;
13
+ whyItMatters: string;
14
+ nextAction: string;
15
+ evidence: ProactiveEvidence[];
16
+ nowMs?: number;
17
+ }): ProactiveInsight | null;
18
+ export declare function setProactiveInsightStatus(id: string, status: ProactiveInsightStatus, nowMs?: number, expectedStatus?: ProactiveInsightStatus): ProactiveInsight | null;
19
+ export declare function claimProactiveInsightApproval(id: string, nowMs?: number): ProactiveInsight | null;
@@ -0,0 +1,106 @@
1
+ import { requireXopcDatabase } from "../storage/sqlite/connection.js";
2
+ import { runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
3
+ import { createHash, randomUUID } from "node:crypto";
4
+ //#region src/proactive/insight-repository.ts
5
+ function insightFromRow(row) {
6
+ return {
7
+ id: row.insight_id,
8
+ watchId: row.watch_id,
9
+ runId: row.run_id,
10
+ kind: row.kind,
11
+ title: row.title,
12
+ summary: row.summary,
13
+ whyItMatters: row.why_it_matters,
14
+ nextAction: row.next_action,
15
+ evidence: JSON.parse(row.evidence_json),
16
+ status: row.status,
17
+ createdAt: row.created_at,
18
+ updatedAt: row.updated_at
19
+ };
20
+ }
21
+ function getProactiveInsight(id) {
22
+ const { db } = requireXopcDatabase();
23
+ const row = db.prepare("SELECT * FROM proactive_insights WHERE insight_id = ?").get(id);
24
+ return row ? insightFromRow(row) : null;
25
+ }
26
+ function listProactiveInsights(options = {}) {
27
+ const statuses = options.status ?? ["unread", "read"];
28
+ if (statuses.length === 0) return [];
29
+ const limit = Math.max(1, Math.min(100, options.limit ?? 20));
30
+ const { db } = requireXopcDatabase();
31
+ return db.prepare(`SELECT * FROM proactive_insights
32
+ WHERE status IN (${statuses.map(() => "?").join(", ")})
33
+ ORDER BY created_at DESC LIMIT ?`).all(...statuses, limit).map(insightFromRow);
34
+ }
35
+ function createProactiveInsight(input) {
36
+ const id = randomUUID();
37
+ const now = input.nowMs ?? Date.now();
38
+ const intelligenceUpdates = input.evidence.map((item) => [
39
+ canonicalSource(item.source),
40
+ canonicalPublishedAt(item.publishedAt),
41
+ normalizeIdentityText(item.label)
42
+ ]).filter(([source]) => Boolean(source)).toSorted((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
43
+ const fingerprint = input.kind === "intelligence" && intelligenceUpdates.length > 0 ? JSON.stringify({
44
+ kind: input.kind,
45
+ updates: intelligenceUpdates
46
+ }) : JSON.stringify({
47
+ kind: input.kind,
48
+ title: input.title.toLocaleLowerCase().trim(),
49
+ summary: input.summary.toLocaleLowerCase().trim(),
50
+ evidence: input.evidence.map((item) => [
51
+ item.label.toLocaleLowerCase().trim(),
52
+ canonicalSource(item.source),
53
+ item.publishedAt ?? ""
54
+ ])
55
+ });
56
+ const contentHash = createHash("sha256").update(fingerprint).digest("hex");
57
+ let created = false;
58
+ runSqliteWriteTransaction((db) => {
59
+ created = db.prepare(`INSERT OR IGNORE INTO proactive_insights (
60
+ insight_id, watch_id, run_id, kind, title, summary, why_it_matters,
61
+ next_action, evidence_json, content_hash, status, created_at, updated_at
62
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?)`).run(id, input.watchId, input.runId, input.kind, input.title, input.summary, input.whyItMatters, input.nextAction, JSON.stringify(input.evidence), contentHash, now, now).changes > 0;
63
+ });
64
+ return created ? listProactiveInsights({ limit: 100 }).find((item) => item.id === id) ?? null : null;
65
+ }
66
+ function canonicalPublishedAt(value) {
67
+ if (!value) return "";
68
+ const timestamp = Date.parse(value);
69
+ return Number.isFinite(timestamp) ? new Date(timestamp).toISOString() : value.trim();
70
+ }
71
+ function normalizeIdentityText(value) {
72
+ return value.trim().toLocaleLowerCase().replace(/\s+/g, " ");
73
+ }
74
+ function canonicalSource(source) {
75
+ const value = source?.trim();
76
+ if (!value) return "";
77
+ try {
78
+ const url = new URL(value);
79
+ url.hash = "";
80
+ for (const key of [...url.searchParams.keys()]) if (key.toLowerCase().startsWith("utm_") || key === "ref" || key === "source") url.searchParams.delete(key);
81
+ url.pathname = url.pathname.replace(/\/$/, "");
82
+ return url.toString().toLocaleLowerCase();
83
+ } catch {
84
+ return value.toLocaleLowerCase();
85
+ }
86
+ }
87
+ function setProactiveInsightStatus(id, status, nowMs = Date.now(), expectedStatus) {
88
+ let changed = false;
89
+ runSqliteWriteTransaction((db) => {
90
+ changed = db.prepare(`UPDATE proactive_insights SET status = ?, updated_at = ? WHERE insight_id = ?
91
+ ${expectedStatus ? "AND status = ?" : ""}`).run(status, nowMs, id, ...expectedStatus ? [expectedStatus] : []).changes > 0;
92
+ });
93
+ if (!changed) return null;
94
+ const { db } = requireXopcDatabase();
95
+ return insightFromRow(db.prepare("SELECT * FROM proactive_insights WHERE insight_id = ?").get(id));
96
+ }
97
+ function claimProactiveInsightApproval(id, nowMs = Date.now()) {
98
+ let claimed = false;
99
+ runSqliteWriteTransaction((db) => {
100
+ claimed = db.prepare(`UPDATE proactive_insights SET status = 'approved', updated_at = ?
101
+ WHERE insight_id = ? AND status = 'unread'`).run(nowMs, id).changes > 0;
102
+ });
103
+ return claimed ? getProactiveInsight(id) : null;
104
+ }
105
+ //#endregion
106
+ export { claimProactiveInsightApproval, createProactiveInsight, getProactiveInsight, listProactiveInsights, setProactiveInsightStatus };
@@ -0,0 +1,19 @@
1
+ import type { AutomationRun } from '../automations/index.js';
2
+ import type { ProactiveEvidence, ProactiveInsight } from './types.js';
3
+ interface MeaningfulResult {
4
+ meaningful: true;
5
+ title: string;
6
+ summary: string;
7
+ whyItMatters: string;
8
+ nextAction: string;
9
+ evidence: ProactiveEvidence[];
10
+ }
11
+ export declare function parseFocusRunResult(summary: string): MeaningfulResult | {
12
+ meaningful: false;
13
+ } | null;
14
+ export declare function hasValidIntelligenceEvidence(evidence: ProactiveEvidence[]): boolean;
15
+ export declare function processFocusAutomationRun(run: AutomationRun): {
16
+ handled: boolean;
17
+ insight?: ProactiveInsight;
18
+ };
19
+ export {};
@@ -0,0 +1,125 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { getFocusWatchByAutomationId, recordFocusWatchRun } from "./watch-repository.js";
4
+ import { createProactiveInsight } from "./insight-repository.js";
5
+ //#region src/proactive/run-processor.ts
6
+ init_logger();
7
+ const log = createLogger("ProactiveRunProcessor");
8
+ function nonEmptyString(value) {
9
+ return typeof value === "string" && value.trim() ? value.trim() : null;
10
+ }
11
+ function parseFocusRunResult(summary) {
12
+ const start = summary.indexOf("{");
13
+ const end = summary.lastIndexOf("}");
14
+ if (start < 0 || end <= start) return null;
15
+ let value;
16
+ try {
17
+ value = JSON.parse(summary.slice(start, end + 1));
18
+ } catch {
19
+ return null;
20
+ }
21
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
22
+ const result = value;
23
+ if (result.meaningful === false) return { meaningful: false };
24
+ if (result.meaningful !== true) return null;
25
+ const title = nonEmptyString(result.title);
26
+ const resultSummary = nonEmptyString(result.summary);
27
+ const whyItMatters = nonEmptyString(result.whyItMatters);
28
+ const nextAction = nonEmptyString(result.nextAction);
29
+ const evidence = Array.isArray(result.evidence) ? result.evidence.flatMap((item) => {
30
+ if (!item || typeof item !== "object" || Array.isArray(item)) return [];
31
+ const label = nonEmptyString(item.label);
32
+ const source = nonEmptyString(item.source);
33
+ const publishedAtValue = nonEmptyString(item.publishedAt);
34
+ const publishedAt = publishedAtValue && Number.isFinite(Date.parse(publishedAtValue)) ? new Date(publishedAtValue).toISOString() : null;
35
+ return label ? [{
36
+ label,
37
+ ...source ? { source } : {},
38
+ ...publishedAt ? { publishedAt } : {}
39
+ }] : [];
40
+ }).slice(0, 8) : [];
41
+ if (!title || !resultSummary || !whyItMatters || !nextAction || evidence.length === 0) return null;
42
+ return {
43
+ meaningful: true,
44
+ title,
45
+ summary: resultSummary,
46
+ whyItMatters,
47
+ nextAction,
48
+ evidence
49
+ };
50
+ }
51
+ function hasValidIntelligenceEvidence(evidence) {
52
+ return evidence.some((item) => {
53
+ if (!item.source || !item.publishedAt) return false;
54
+ try {
55
+ const url = new URL(item.source);
56
+ return (url.protocol === "https:" || url.protocol === "http:") && Number.isFinite(Date.parse(item.publishedAt));
57
+ } catch {
58
+ return false;
59
+ }
60
+ });
61
+ }
62
+ function processFocusAutomationRun(run) {
63
+ const watch = getFocusWatchByAutomationId(run.automationId);
64
+ if (!watch) return { handled: false };
65
+ if (run.status !== "succeeded" || !run.summary) {
66
+ recordFocusWatchRun({
67
+ id: watch.id,
68
+ runId: run.id,
69
+ outcome: "failed",
70
+ nowMs: run.endedAtMs
71
+ });
72
+ return { handled: true };
73
+ }
74
+ const result = parseFocusRunResult(run.summary);
75
+ if (!result) {
76
+ recordFocusWatchRun({
77
+ id: watch.id,
78
+ runId: run.id,
79
+ outcome: "failed",
80
+ nowMs: run.endedAtMs
81
+ });
82
+ log.warn({
83
+ automationId: run.automationId,
84
+ runId: run.id
85
+ }, "Focus watch returned an invalid result");
86
+ return { handled: true };
87
+ }
88
+ if (result.meaningful && watch.kind === "intelligence" && !hasValidIntelligenceEvidence(result.evidence)) {
89
+ recordFocusWatchRun({
90
+ id: watch.id,
91
+ runId: run.id,
92
+ outcome: "failed",
93
+ nowMs: run.endedAtMs
94
+ });
95
+ log.warn({
96
+ automationId: run.automationId,
97
+ runId: run.id
98
+ }, "Intelligence watch result lacked dated web evidence");
99
+ return { handled: true };
100
+ }
101
+ if (!recordFocusWatchRun({
102
+ id: watch.id,
103
+ runId: run.id,
104
+ outcome: result.meaningful ? "meaningful" : "empty",
105
+ nowMs: run.endedAtMs
106
+ })) return { handled: true };
107
+ if (!result.meaningful) return { handled: true };
108
+ const insight = createProactiveInsight({
109
+ watchId: watch.id,
110
+ runId: run.id,
111
+ kind: watch.kind,
112
+ title: result.title,
113
+ summary: result.summary,
114
+ whyItMatters: result.whyItMatters,
115
+ nextAction: result.nextAction,
116
+ evidence: result.evidence,
117
+ nowMs: run.endedAtMs
118
+ });
119
+ return insight ? {
120
+ handled: true,
121
+ insight
122
+ } : { handled: true };
123
+ }
124
+ //#endregion
125
+ export { hasValidIntelligenceEvidence, parseFocusRunResult, processFocusAutomationRun };
@@ -0,0 +1,5 @@
1
+ interface TrialExpiryService {
2
+ reconcileExpiredTrials(): Promise<number>;
3
+ }
4
+ export declare function startTrialExpiryReconciler(service: TrialExpiryService, intervalMs?: number): () => Promise<void>;
5
+ export {};
@@ -0,0 +1,30 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ //#region src/proactive/trial-expiry-reconciler.ts
4
+ init_logger();
5
+ const DEFAULT_RECONCILE_INTERVAL_MS = 6e4;
6
+ const log = createLogger("FocusTrialExpiry");
7
+ function startTrialExpiryReconciler(service, intervalMs = DEFAULT_RECONCILE_INTERVAL_MS) {
8
+ let stopped = false;
9
+ let pending = null;
10
+ const reconcile = () => {
11
+ if (stopped || pending) return;
12
+ pending = service.reconcileExpiredTrials().then((pausedCount) => {
13
+ if (pausedCount > 0) log.info({ pausedCount }, "Expired focus watch trials paused");
14
+ }).catch((err) => {
15
+ log.warn({ err }, "Focus watch trial expiry reconciliation failed");
16
+ }).finally(() => {
17
+ pending = null;
18
+ });
19
+ };
20
+ reconcile();
21
+ const timer = setInterval(reconcile, intervalMs);
22
+ timer.unref();
23
+ return async () => {
24
+ stopped = true;
25
+ clearInterval(timer);
26
+ await pending;
27
+ };
28
+ }
29
+ //#endregion
30
+ export { startTrialExpiryReconciler };
@@ -0,0 +1,64 @@
1
+ import type { WorkUnderstandingThread } from '../work-discovery/types.js';
2
+ export type FocusWatchKind = 'progress' | 'staleness' | 'deadline' | 'intelligence';
3
+ export type FocusWatchStatus = 'active' | 'paused';
4
+ export interface FocusWatch {
5
+ id: string;
6
+ threadId: string;
7
+ goalId?: string;
8
+ automationId: string;
9
+ kind: FocusWatchKind;
10
+ status: FocusWatchStatus;
11
+ config: Record<string, unknown>;
12
+ trialEndsAt?: number;
13
+ lastCursor?: string;
14
+ lastRunAt?: number;
15
+ lastUsefulResultAt?: number;
16
+ consecutiveEmptyRuns: number;
17
+ createdAt: number;
18
+ updatedAt: number;
19
+ }
20
+ export interface FocusView {
21
+ id: string;
22
+ title: string;
23
+ summary: string;
24
+ status: WorkUnderstandingThread['status'];
25
+ horizon: WorkUnderstandingThread['horizon'];
26
+ confidence: number;
27
+ focusScore: number;
28
+ userStatus: WorkUnderstandingThread['userStatus'];
29
+ projectIds: string[];
30
+ goalId?: string;
31
+ nextAction?: string;
32
+ blockedReason?: string;
33
+ watches: FocusWatch[];
34
+ lastObservedAt: number;
35
+ }
36
+ export type ProactiveInsightStatus = 'unread' | 'read' | 'approved' | 'dismissed';
37
+ export interface ProactiveEvidence {
38
+ label: string;
39
+ source?: string;
40
+ publishedAt?: string;
41
+ }
42
+ export interface ProactiveInsight {
43
+ id: string;
44
+ watchId: string;
45
+ runId: string;
46
+ kind: FocusWatchKind;
47
+ title: string;
48
+ summary: string;
49
+ whyItMatters: string;
50
+ nextAction: string;
51
+ evidence: ProactiveEvidence[];
52
+ status: ProactiveInsightStatus;
53
+ createdAt: number;
54
+ updatedAt: number;
55
+ }
56
+ export interface FocusCalendarSignal {
57
+ id: string;
58
+ focusId: string;
59
+ focusTitle: string;
60
+ title: string;
61
+ startsAt: number;
62
+ endsAt?: number;
63
+ sourceInstanceId: string;
64
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { FocusWatch, FocusWatchKind, FocusWatchStatus } from './types.js';
2
+ export declare function listFocusWatches(options?: {
3
+ threadId?: string;
4
+ status?: FocusWatchStatus;
5
+ }): FocusWatch[];
6
+ export declare function getFocusWatchByThreadAndKind(threadId: string, kind: FocusWatchKind): FocusWatch | null;
7
+ export declare function getFocusWatchByAutomationId(automationId: string): FocusWatch | null;
8
+ export declare function createFocusWatch(input: {
9
+ threadId: string;
10
+ goalId?: string;
11
+ automationId: string;
12
+ kind: FocusWatchKind;
13
+ config?: Record<string, unknown>;
14
+ trialEndsAt?: number;
15
+ nowMs?: number;
16
+ }): FocusWatch;
17
+ export declare function setFocusWatchStatus(id: string, status: FocusWatchStatus, nowMs?: number): FocusWatch | null;
18
+ export declare function restartFocusWatchTrial(id: string, trialEndsAt: number, nowMs?: number): FocusWatch | null;
19
+ export declare function recordFocusWatchRun(input: {
20
+ id: string;
21
+ runId: string;
22
+ outcome: 'meaningful' | 'empty' | 'failed';
23
+ nowMs?: number;
24
+ }): FocusWatch | null;
25
+ export declare function recordFocusWatchFeedback(id: string, useful: boolean, nowMs?: number): {
26
+ watch: FocusWatch;
27
+ consecutiveDismissed: number;
28
+ } | null;