@xopcai/xopc 0.0.172 → 0.0.174

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 (223) 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-C3Y-bESI.js → activity-store-CyEDJeIt.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CPyev9P7.js → agent-avatar-dicebear-DF7Bol6I.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-BVxEFPQ5.js +2 -0
  6. package/dist/gateway/static/root/assets/{api-B7qEr_Rw.js → api-DYunqroX.js} +1 -1
  7. package/dist/gateway/static/root/assets/api-DwyUxpgY.js +1 -0
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-Br_9-7fs.js → app-management-settings-panel-B4xJyvDu.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-uyLcRPai.js → appearance-settings-B2PQxRiu.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-BtIgd82S.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-B19REnR5.js → archive-plugin-DWhBmmjD.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-DLWCC4Yi.js → attachment-load-BOpZfa_I.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automation-suggestion-card-ky5S5lly.js → automation-suggestion-card-Byu3I7Rs.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-CG_SCH5b.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-CtPEzLlo.js → binary-plugins-6AG1qatz.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-CQVR4Xij.js → block-editor-CJhrn98_.js} +5 -5
  17. package/dist/gateway/static/root/assets/browser-settings-page-CfLqPWZC.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CimCGbhq.js → browser-workflow-inputs-CBVb4mt9.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-DewuCw3p.js → browser-workflows-page-Cq4XUKbu.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-DCJmm6cR.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-B5RTs-Az.js → capability-presets-api-hbW4NAKO.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CnkAYvWI.js +1 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-Czu0YzIZ.js → channel-recipient-api-CzMjHb17.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-DtqqFpDn.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-C-5yHbc0.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-Di3gnR_D.js → connector-logo-B9Au6gMZ.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-CaHfs8YF.js +2 -0
  28. package/dist/gateway/static/root/assets/copy-VueTIC2x.js +1 -0
  29. package/dist/gateway/static/root/assets/desktop-pet-CvFMKYdb.js +1 -0
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-C3L6AI8_.js → desktop-pet-settings-CNff5TFb.js} +1 -1
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-Dvq4iG6P.js → directory-picker-path-field-Bf956uo-.js} +1 -1
  32. package/dist/gateway/static/root/assets/dreaming-settings-CHM8FE1g.js +3 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-BecQjU0J.js → extension-debug-page-ZqM_0eUs.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-BeVkPSm-.js → extension-page-D4hvXOMM.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-DMoo2mKx.js → extension-settings-page-GsqxaJjA.js} +1 -1
  36. package/dist/gateway/static/root/assets/focus-detail-page-CE6uwrl1.js +1 -0
  37. package/dist/gateway/static/root/assets/{gateway-config-api-Bthb3_6v.js → gateway-config-api-B4THmgnS.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-Bh8nPvJQ.js → gateway-settings-CPv-MxGE.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-D3USVm9D.js → gateway-startup-retry-MP3K71pP.js} +1 -1
  40. package/dist/gateway/static/root/assets/goal-create-dialog-DAeb82xP.js +1 -0
  41. package/dist/gateway/static/root/assets/goal-detail-page-CwLSp01r.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-C_2QWBtb.js → goals-config-api-DCcDuIjG.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-DvJQ6_4M.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-DhL643tc.js → goals-settings-o9QMXvNq.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-COVFwp7C.js → heartbeat-settings-DixwpXnH.js} +1 -1
  46. package/dist/gateway/static/root/assets/{image-generation-api-BNQlnwpU.js → image-generation-api-BOGH9FGi.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-CfXiRNN5.css +1 -0
  48. package/dist/gateway/static/root/assets/index-eyttVNS_.js +212 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DfdJRJVy.js → keyboard-shortcuts-settings-D4o4ZPF6.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-CPcfqn_A.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-BvCPOgoi.js → local-apps-page-GzMmpO7G.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-BP0vD37A.js → locale-store-CAuhEGCn.js} +1 -1
  53. package/dist/gateway/static/root/assets/logs-page-DXABWCZp.js +7 -0
  54. package/dist/gateway/static/root/assets/{markdown-split-YO1rDk9m.js → markdown-split-CIX8D1pv.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-CU_RRf-q.js → media-plugins-Bp3eIA45.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-BiBdO1-O.js +3 -0
  57. package/dist/gateway/static/root/assets/{notes-page-CeFiOK3S.js → notes-page-RVFiYAoO.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-DgJzZRX3.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-tiHmRJUA.js → page-tabs-BGAYH3Ef.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-CU6XgaCz.js → preview-open-alternatives-BM6pDkHp.js} +1 -1
  61. package/dist/gateway/static/root/assets/{product-open-page-Dn4_qor4.js → product-open-page-BiMetEmn.js} +1 -1
  62. package/dist/gateway/static/root/assets/project-detail-page-DF7F70Vg.js +1 -0
  63. package/dist/gateway/static/root/assets/projects-page-Cw3jyi5s.js +1 -0
  64. package/dist/gateway/static/root/assets/remote-access-hub-ChAJsaNY.js +1 -0
  65. package/dist/gateway/static/root/assets/{save-bar-controls-edDUIbXo.js → save-bar-controls-BdjV8MK5.js} +1 -1
  66. package/dist/gateway/static/root/assets/{schedule-field-DqJO_5Yb.js → schedule-field-ChlqXU46.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schema-form-CMh0jzy5.js → schema-form-DDKf5ZSH.js} +1 -1
  68. package/dist/gateway/static/root/assets/sessions-page-BxZIxt7z.js +1 -0
  69. package/dist/gateway/static/root/assets/settings-advanced-gate-DcDLS0xV.js +1 -0
  70. package/dist/gateway/static/root/assets/{settings-form-section-Bb0Bc3nJ.js → settings-form-section-CPG0KGVs.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-loading-skeleton-DQhADvz1.js → settings-loading-skeleton-DRSDHucM.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-page-b0M5HukN.js → settings-page-CeB7_xD0.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-layout-hvjtIjvh.js → settings-page-layout-BENrkwd0.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-4Xa9NA7v.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-rbeaOpTg.js → share-preview-page-DIzczJkG.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-BpN0o5Cf.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-DvF2UAaL.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-CGKXpNfy.js +2 -0
  79. package/dist/gateway/static/root/assets/{system-settings-panel-BHo_hgnL.js → system-settings-panel-Dp4d5Q1B.js} +1 -1
  80. package/dist/gateway/static/root/assets/{theme-store-C3KnnjcU.js → theme-store-CbGc1laW.js} +1 -1
  81. package/dist/gateway/static/root/assets/{time-picker-D-G-uwVJ.js → time-picker-BhgCeDuO.js} +1 -1
  82. package/dist/gateway/static/root/assets/{typed-models-lib-DtRnG-YI.js → typed-models-lib-DwPk3OPL.js} +1 -1
  83. package/dist/gateway/static/root/assets/{use-channel-catalog-CWWItX2g.js → use-channel-catalog-CXrEu2dw.js} +1 -1
  84. package/dist/gateway/static/root/assets/user-context-page-Dy_fKAK_.js +1 -0
  85. package/dist/gateway/static/root/assets/{voice-api-key-field-BTnltQHZ.js → voice-api-key-field-DFoA79LB.js} +1 -1
  86. package/dist/gateway/static/root/assets/work-discovery-page-BWkjb1NK.js +1 -0
  87. package/dist/gateway/static/root/assets/work-item-detail-page-DLBNFse5.js +1 -0
  88. package/dist/gateway/static/root/assets/work-page-Bn5RXMIE.js +1 -0
  89. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-D7vKChFZ.js → workflow-run-setup-panel-BuniGPO0.js} +2 -2
  90. package/dist/gateway/static/root/assets/workflows-page-_vFhRrAl.js +11 -0
  91. package/dist/gateway/static/root/index.html +7 -7
  92. package/dist/package.js +1 -1
  93. package/dist/src/agent/agent-manager.d.ts +3 -1
  94. package/dist/src/agent/agent-manager.js +4 -3
  95. package/dist/src/agent/capabilities/definitions.d.ts +2 -1
  96. package/dist/src/agent/capabilities/definitions.js +3 -1
  97. package/dist/src/agent/prompt/sections/tooling.js +4 -0
  98. package/dist/src/agent/service.d.ts +2 -1
  99. package/dist/src/agent/service.js +26 -0
  100. package/dist/src/agent/skills/hub-pull.js +1 -1
  101. package/dist/src/agent/skills/index.js +1 -1
  102. package/dist/src/agent/skills/install-target.js +1 -1
  103. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.d.ts +64 -0
  104. package/dist/src/agent/skills/marketplace/adapters/clawhub/adapter.js +27 -18
  105. package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +1 -1
  106. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
  107. package/dist/src/agent/skills/marketplace/search.d.ts +46 -0
  108. package/dist/src/agent/skills/marketplace/search.js +193 -0
  109. package/dist/src/agent/skills/skill-tool-gating.js +2 -1
  110. package/dist/src/agent/tools/delegate-tool.js +2 -0
  111. package/dist/src/agent/tools/factory.d.ts +4 -2
  112. package/dist/src/agent/tools/factory.js +11 -5
  113. package/dist/src/agent/tools/index.d.ts +2 -1
  114. package/dist/src/agent/tools/index.js +2 -1
  115. package/dist/src/agent/tools/skill-install-tool.d.ts +17 -0
  116. package/dist/src/agent/tools/skill-install-tool.js +76 -8
  117. package/dist/src/agent/tools/skills-marketplace-search-tool.d.ts +17 -0
  118. package/dist/src/agent/tools/skills-marketplace-search-tool.js +77 -0
  119. package/dist/src/browser/providers/cloakbrowser.js +1 -1
  120. package/dist/src/capabilities/store-connector.js +1 -1
  121. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  122. package/dist/src/config/agent-profile.js +1 -1
  123. package/dist/src/extensions/api.js +1 -1
  124. package/dist/src/extensions/install.js +1 -1
  125. package/dist/src/focuses/candidate-repository.d.ts +15 -0
  126. package/dist/src/focuses/candidate-repository.js +91 -0
  127. package/dist/src/focuses/index.d.ts +7 -0
  128. package/dist/src/focuses/index.js +7 -0
  129. package/dist/src/focuses/insight-repository.d.ts +22 -0
  130. package/dist/src/focuses/insight-repository.js +77 -0
  131. package/dist/src/focuses/prompts.d.ts +2 -0
  132. package/dist/src/focuses/prompts.js +18 -0
  133. package/dist/src/focuses/reconciler.d.ts +5 -0
  134. package/dist/src/focuses/reconciler.js +26 -0
  135. package/dist/src/focuses/repository.d.ts +61 -0
  136. package/dist/src/focuses/repository.js +214 -0
  137. package/dist/src/focuses/run-processor.d.ts +18 -0
  138. package/dist/src/focuses/run-processor.js +162 -0
  139. package/dist/src/focuses/service.d.ts +42 -0
  140. package/dist/src/focuses/service.js +241 -0
  141. package/dist/src/focuses/types.d.ts +89 -0
  142. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  143. package/dist/src/gateway/agent-builtin-tools.js +2 -0
  144. package/dist/src/gateway/agents-admin.js +1 -1
  145. package/dist/src/gateway/hono/routes/commands-skills.js +2 -2
  146. package/dist/src/gateway/hono/routes/focuses.d.ts +3 -0
  147. package/dist/src/gateway/hono/routes/focuses.js +319 -0
  148. package/dist/src/gateway/hono/routes/home.js +15 -17
  149. package/dist/src/gateway/hono/routes/index.js +2 -0
  150. package/dist/src/gateway/hono/routes/projects.js +2 -103
  151. package/dist/src/gateway/hono/routes/work-discovery.js +0 -239
  152. package/dist/src/gateway/service/marketplace-service.js +1 -1
  153. package/dist/src/gateway/service.d.ts +1 -1
  154. package/dist/src/gateway/service.js +15 -11
  155. package/dist/src/storage/sqlite/migrations/066_first_class_focuses.sql +126 -0
  156. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  157. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  158. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  159. package/dist/src/storage/sqlite/schema.js +1 -1
  160. package/dist/src/work-discovery/index.d.ts +0 -2
  161. package/dist/src/work-discovery/index.js +1 -3
  162. package/dist/src/work-discovery/service.d.ts +0 -30
  163. package/dist/src/work-discovery/service.js +1 -35
  164. package/dist/src/work-discovery/thread-service.d.ts +5 -0
  165. package/dist/src/work-discovery/thread-service.js +36 -88
  166. package/package.json +1 -1
  167. package/skills/tools/find-skills/SKILL.md +18 -428
  168. package/dist/gateway/static/root/assets/agents-Bf_kK2Ay.js +0 -2
  169. package/dist/gateway/static/root/assets/apps-page-DXFCP5-1.js +0 -1
  170. package/dist/gateway/static/root/assets/automations-page-D8pT1o2O.js +0 -6
  171. package/dist/gateway/static/root/assets/browser-settings-page-Bav_skKN.js +0 -8
  172. package/dist/gateway/static/root/assets/capabilities-settings-panel-BHaYYo9E.js +0 -7
  173. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BgchTh81.js +0 -1
  174. package/dist/gateway/static/root/assets/channels-settings-BP0e62wt.js +0 -1
  175. package/dist/gateway/static/root/assets/channels-status-swr-DBWKfeGe.js +0 -1
  176. package/dist/gateway/static/root/assets/connectors-page-CC5kh0de.js +0 -2
  177. package/dist/gateway/static/root/assets/desktop-pet-D-ZUNHhn.js +0 -1
  178. package/dist/gateway/static/root/assets/dreaming-settings-D9i54kWO.js +0 -3
  179. package/dist/gateway/static/root/assets/goal-create-dialog-Dp0AyDHI.js +0 -1
  180. package/dist/gateway/static/root/assets/goal-detail-page-CNt7nrdS.js +0 -4
  181. package/dist/gateway/static/root/assets/goals-page-Bm_NZFiZ.js +0 -2
  182. package/dist/gateway/static/root/assets/index-C_XSKOH6.css +0 -1
  183. package/dist/gateway/static/root/assets/index-DUasAutC.js +0 -212
  184. package/dist/gateway/static/root/assets/local-app-workbench-page-DZwkD1co.js +0 -2
  185. package/dist/gateway/static/root/assets/logs-page-dNL0Y1dA.js +0 -7
  186. package/dist/gateway/static/root/assets/messages-BWtP5TFz.js +0 -3
  187. package/dist/gateway/static/root/assets/notes-workbench-B8MKxpZb.js +0 -4
  188. package/dist/gateway/static/root/assets/project-detail-page-CWBuuX-S.js +0 -1
  189. package/dist/gateway/static/root/assets/projects-page-BJSsLsXH.js +0 -1
  190. package/dist/gateway/static/root/assets/remote-access-hub-DXJDb8vB.js +0 -1
  191. package/dist/gateway/static/root/assets/sessions-page-DeHpWgxM.js +0 -1
  192. package/dist/gateway/static/root/assets/settings-advanced-gate-Cf-TEYUd.js +0 -1
  193. package/dist/gateway/static/root/assets/setup-status-panel-BFyfed_g.js +0 -1
  194. package/dist/gateway/static/root/assets/shares-settings-CYnH9sTt.js +0 -1
  195. package/dist/gateway/static/root/assets/skill-reload-api-Cr8_m-jS.js +0 -1
  196. package/dist/gateway/static/root/assets/skills-page-Chtc1xDO.js +0 -2
  197. package/dist/gateway/static/root/assets/user-context-page-D7qMR26X.js +0 -1
  198. package/dist/gateway/static/root/assets/work-discovery-page-CpqFZze9.js +0 -1
  199. package/dist/gateway/static/root/assets/work-item-detail-page-t4dXpGC0.js +0 -1
  200. package/dist/gateway/static/root/assets/work-page-BXwDKiMZ.js +0 -1
  201. package/dist/gateway/static/root/assets/workflows-page-Bos9HyqT.js +0 -11
  202. package/dist/src/proactive/calendar-signals.d.ts +0 -4
  203. package/dist/src/proactive/calendar-signals.js +0 -120
  204. package/dist/src/proactive/focus-service.d.ts +0 -62
  205. package/dist/src/proactive/focus-service.js +0 -173
  206. package/dist/src/proactive/index.d.ts +0 -7
  207. package/dist/src/proactive/index.js +0 -7
  208. package/dist/src/proactive/insight-repository.d.ts +0 -21
  209. package/dist/src/proactive/insight-repository.js +0 -109
  210. package/dist/src/proactive/run-processor.d.ts +0 -19
  211. package/dist/src/proactive/run-processor.js +0 -146
  212. package/dist/src/proactive/trial-expiry-reconciler.d.ts +0 -5
  213. package/dist/src/proactive/trial-expiry-reconciler.js +0 -30
  214. package/dist/src/proactive/types.d.ts +0 -66
  215. package/dist/src/proactive/value-score.d.ts +0 -13
  216. package/dist/src/proactive/value-score.js +0 -30
  217. package/dist/src/proactive/watch-repository.d.ts +0 -28
  218. package/dist/src/proactive/watch-repository.js +0 -129
  219. package/dist/src/work-discovery/governance.d.ts +0 -25
  220. package/dist/src/work-discovery/governance.js +0 -96
  221. package/dist/src/work-discovery/thread-repository.d.ts +0 -34
  222. package/dist/src/work-discovery/thread-repository.js +0 -112
  223. /package/dist/src/{proactive → focuses}/types.js +0 -0
@@ -0,0 +1,319 @@
1
+ import { createFocusActivity, listFocusActivities } from "../../../focuses/repository.js";
2
+ import { acceptFocusCandidate, listFocusCandidates, setFocusCandidateStatus } from "../../../focuses/candidate-repository.js";
3
+ import { getFocusInsight, listFocusInsights, setFocusInsightStatus } from "../../../focuses/insight-repository.js";
4
+ import { FocusService } from "../../../focuses/service.js";
5
+ import "../../../focuses/index.js";
6
+ //#region src/gateway/hono/routes/focuses.ts
7
+ const FOCUS_STATUSES = [
8
+ "active",
9
+ "paused",
10
+ "completed"
11
+ ];
12
+ const MONITOR_KINDS = ["progress", "external_changes"];
13
+ function stringField(body, field) {
14
+ if (!body || typeof body !== "object") return "";
15
+ const value = body[field];
16
+ return typeof value === "string" ? value.trim() : "";
17
+ }
18
+ function stringArrayField(body, field) {
19
+ if (!body || typeof body !== "object") return void 0;
20
+ const value = body[field];
21
+ if (!Array.isArray(value)) return void 0;
22
+ return [...new Set(value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean))];
23
+ }
24
+ function registerFocusRoutes(authenticated, deps) {
25
+ const focuses = new FocusService(deps.service.automationServiceInstance);
26
+ const limited = deps.strictRateLimitMiddleware;
27
+ authenticated.get("/api/focuses", (c) => {
28
+ const requested = c.req.query("status")?.split(",").map((item) => item.trim()).filter(Boolean) ?? [];
29
+ const statuses = requested.length > 0 ? requested.filter((item) => FOCUS_STATUSES.includes(item)) : void 0;
30
+ if (requested.length > 0 && statuses?.length !== requested.length) return c.json({
31
+ ok: false,
32
+ error: "Invalid focus status"
33
+ }, 400);
34
+ return c.json({
35
+ ok: true,
36
+ focuses: focuses.list(statuses)
37
+ });
38
+ });
39
+ authenticated.post("/api/focuses", limited, async (c) => {
40
+ const body = await c.req.json().catch(() => null);
41
+ const title = stringField(body, "title");
42
+ if (!title) return c.json({
43
+ ok: false,
44
+ error: "Focus title is required"
45
+ }, 400);
46
+ const focus = focuses.create({
47
+ title,
48
+ summary: stringField(body, "summary"),
49
+ ...stringArrayField(body, "projectIds") ? { projectIds: stringArrayField(body, "projectIds") } : {},
50
+ ...stringField(body, "goalId") ? { goalId: stringField(body, "goalId") } : {}
51
+ });
52
+ deps.service.emit("focus.created", { focus });
53
+ return c.json({
54
+ ok: true,
55
+ focus
56
+ }, 201);
57
+ });
58
+ authenticated.get("/api/focuses/:focusId", (c) => {
59
+ const focus = focuses.get(c.req.param("focusId"));
60
+ return focus ? c.json({
61
+ ok: true,
62
+ focus
63
+ }) : c.json({
64
+ ok: false,
65
+ error: "Focus not found"
66
+ }, 404);
67
+ });
68
+ authenticated.patch("/api/focuses/:focusId", limited, async (c) => {
69
+ const body = await c.req.json().catch(() => null);
70
+ const requestedStatus = stringField(body, "status");
71
+ if (requestedStatus && !FOCUS_STATUSES.includes(requestedStatus)) return c.json({
72
+ ok: false,
73
+ error: "Invalid focus status"
74
+ }, 400);
75
+ try {
76
+ const title = stringField(body, "title");
77
+ const hasSummary = typeof body?.summary === "string";
78
+ const projectIds = stringArrayField(body, "projectIds");
79
+ let focus = Boolean(title || hasSummary || projectIds) ? focuses.update(c.req.param("focusId"), {
80
+ ...title ? { title } : {},
81
+ ...hasSummary ? { summary: stringField(body, "summary") } : {},
82
+ ...projectIds ? { projectIds } : {}
83
+ }) : focuses.get(c.req.param("focusId"));
84
+ if (focus && requestedStatus) focus = await focuses.setStatus(c.req.param("focusId"), requestedStatus);
85
+ if (!focus) return c.json({
86
+ ok: false,
87
+ error: "Focus not found"
88
+ }, 404);
89
+ deps.service.emit("focus.updated", { focus });
90
+ return c.json({
91
+ ok: true,
92
+ focus
93
+ });
94
+ } catch (error) {
95
+ return c.json({
96
+ ok: false,
97
+ error: error instanceof Error ? error.message : String(error)
98
+ }, 400);
99
+ }
100
+ });
101
+ authenticated.delete("/api/focuses/:focusId", limited, async (c) => {
102
+ try {
103
+ if (!await focuses.remove(c.req.param("focusId"))) return c.json({
104
+ ok: false,
105
+ error: "Focus not found"
106
+ }, 404);
107
+ deps.service.emit("focus.deleted", { focusId: c.req.param("focusId") });
108
+ return c.json({ ok: true });
109
+ } catch (error) {
110
+ return c.json({
111
+ ok: false,
112
+ error: error instanceof Error ? error.message : String(error)
113
+ }, 500);
114
+ }
115
+ });
116
+ authenticated.put("/api/focuses/:focusId/monitors/:kind", limited, async (c) => {
117
+ const kind = c.req.param("kind");
118
+ if (!MONITOR_KINDS.includes(kind)) return c.json({
119
+ ok: false,
120
+ error: "Invalid monitor kind"
121
+ }, 400);
122
+ const body = await c.req.json().catch(() => null);
123
+ const enabled = body && typeof body === "object" ? body.enabled : void 0;
124
+ if (typeof enabled !== "boolean") return c.json({
125
+ ok: false,
126
+ error: "enabled must be a boolean"
127
+ }, 400);
128
+ const everyMs = body && typeof body === "object" && body.cadence && typeof body.cadence === "object" ? Number(body.cadence.everyMs) : void 0;
129
+ try {
130
+ const result = await focuses.configureMonitor({
131
+ focusId: c.req.param("focusId"),
132
+ kind,
133
+ enabled,
134
+ ...Number.isFinite(everyMs) ? { cadence: {
135
+ kind: "interval",
136
+ everyMs
137
+ } } : {}
138
+ });
139
+ deps.service.emit("focus.monitor.updated", {
140
+ focusId: c.req.param("focusId"),
141
+ monitor: result.monitor
142
+ });
143
+ return c.json({
144
+ ok: true,
145
+ ...result
146
+ }, result.initialRunId ? 202 : 200);
147
+ } catch (error) {
148
+ return c.json({
149
+ ok: false,
150
+ error: error instanceof Error ? error.message : String(error)
151
+ }, 400);
152
+ }
153
+ });
154
+ authenticated.post("/api/focuses/:focusId/monitors/:kind/run", limited, async (c) => {
155
+ const kind = c.req.param("kind");
156
+ if (!MONITOR_KINDS.includes(kind)) return c.json({
157
+ ok: false,
158
+ error: "Invalid monitor kind"
159
+ }, 400);
160
+ try {
161
+ const run = await focuses.runMonitorNow(c.req.param("focusId"), kind);
162
+ deps.service.emit("focus.run.updated", {
163
+ focusId: c.req.param("focusId"),
164
+ kind,
165
+ run
166
+ });
167
+ return c.json({
168
+ ok: true,
169
+ run
170
+ }, 202);
171
+ } catch (error) {
172
+ return c.json({
173
+ ok: false,
174
+ error: error instanceof Error ? error.message : String(error)
175
+ }, 400);
176
+ }
177
+ });
178
+ authenticated.get("/api/focuses/:focusId/activities", (c) => c.json({
179
+ ok: true,
180
+ activities: listFocusActivities({
181
+ focusId: c.req.param("focusId"),
182
+ ...Number.isFinite(Number(c.req.query("before"))) ? { before: Number(c.req.query("before")) } : {},
183
+ ...Number.isFinite(Number(c.req.query("limit"))) ? { limit: Number(c.req.query("limit")) } : {}
184
+ })
185
+ }));
186
+ authenticated.get("/api/focuses/:focusId/insights", (c) => c.json({
187
+ ok: true,
188
+ insights: listFocusInsights({
189
+ focusId: c.req.param("focusId"),
190
+ limit: Number(c.req.query("limit")) || 20
191
+ })
192
+ }));
193
+ authenticated.post("/api/focuses/:focusId/insights/:insightId/dismiss", limited, (c) => {
194
+ const insight = getFocusInsight(c.req.param("insightId"));
195
+ if (!insight || insight.focusId !== c.req.param("focusId")) return c.json({
196
+ ok: false,
197
+ error: "Insight not found"
198
+ }, 404);
199
+ const updated = setFocusInsightStatus(insight.id, "dismissed", "unread");
200
+ if (!updated) return c.json({
201
+ ok: false,
202
+ error: "Insight was already handled"
203
+ }, 409);
204
+ createFocusActivity({
205
+ focusId: insight.focusId,
206
+ monitorId: insight.monitorId,
207
+ type: "insight_dismissed",
208
+ summary: insight.title,
209
+ details: { insightId: insight.id }
210
+ });
211
+ deps.service.emit("focus.insight.updated", { insight: updated });
212
+ return c.json({
213
+ ok: true,
214
+ insight: updated
215
+ });
216
+ });
217
+ authenticated.post("/api/focuses/:focusId/insights/:insightId/investigate", limited, async (c) => {
218
+ const insight = getFocusInsight(c.req.param("insightId"));
219
+ const focus = focuses.get(c.req.param("focusId"));
220
+ if (!insight || !focus || insight.focusId !== focus.id) return c.json({
221
+ ok: false,
222
+ error: "Insight not found"
223
+ }, 404);
224
+ const claimed = setFocusInsightStatus(insight.id, "approved", "unread");
225
+ if (!claimed) return c.json({
226
+ ok: false,
227
+ error: "Insight was already handled"
228
+ }, 409);
229
+ let automationId;
230
+ try {
231
+ const automation = await deps.service.automationServiceInstance.create({
232
+ name: `Investigate: ${insight.title}`.slice(0, 200),
233
+ description: `User-approved investigation for focus insight ${insight.id}.`,
234
+ ...focus.projectIds[0] ? { projectId: focus.projectIds[0] } : {},
235
+ trigger: { kind: "manual" },
236
+ action: {
237
+ kind: "agent",
238
+ instruction: [
239
+ "Investigate this user-approved focus insight in read-only mode.",
240
+ `Focus: ${focus.title}`,
241
+ `Observed change: ${insight.summary}`,
242
+ `Why it matters: ${insight.whyItMatters}`,
243
+ `Next step: ${insight.nextAction}`,
244
+ `Evidence: ${JSON.stringify(insight.evidence)}`,
245
+ "Return a concise result with evidence. Do not modify files or external systems."
246
+ ].join("\n"),
247
+ timeoutSeconds: 300
248
+ },
249
+ safety: { mode: "suggest_only" },
250
+ afterRun: { kind: "none" },
251
+ reliability: {
252
+ timeoutSeconds: 300,
253
+ disableAfterConsecutiveFailures: 1
254
+ }
255
+ });
256
+ automationId = automation.id;
257
+ const run = await deps.service.automationServiceInstance.runNow(automation.id);
258
+ createFocusActivity({
259
+ focusId: focus.id,
260
+ monitorId: insight.monitorId,
261
+ type: "insight_approved",
262
+ summary: insight.title,
263
+ details: {
264
+ insightId: insight.id,
265
+ automationId,
266
+ runId: run.id
267
+ }
268
+ });
269
+ deps.service.emit("focus.insight.updated", {
270
+ insight: claimed,
271
+ investigationRunId: run.id
272
+ });
273
+ return c.json({
274
+ ok: true,
275
+ insight: claimed,
276
+ automationId,
277
+ runId: run.id
278
+ }, 202);
279
+ } catch (error) {
280
+ if (automationId) await deps.service.automationServiceInstance.remove(automationId);
281
+ setFocusInsightStatus(insight.id, "unread", "approved");
282
+ return c.json({
283
+ ok: false,
284
+ error: error instanceof Error ? error.message : String(error)
285
+ }, 500);
286
+ }
287
+ });
288
+ authenticated.get("/api/focus-candidates", (c) => c.json({
289
+ ok: true,
290
+ candidates: listFocusCandidates()
291
+ }));
292
+ authenticated.post("/api/focus-candidates/:candidateId/accept", limited, (c) => {
293
+ const focus = acceptFocusCandidate(c.req.param("candidateId"));
294
+ if (!focus) return c.json({
295
+ ok: false,
296
+ error: "Focus candidate not found"
297
+ }, 404);
298
+ const detail = focuses.get(focus.id);
299
+ deps.service.emit("focus.created", { focus: detail });
300
+ return c.json({
301
+ ok: true,
302
+ focus: detail
303
+ }, 201);
304
+ });
305
+ authenticated.post("/api/focus-candidates/:candidateId/dismiss", limited, (c) => {
306
+ const candidate = setFocusCandidateStatus(c.req.param("candidateId"), "dismissed");
307
+ if (!candidate) return c.json({
308
+ ok: false,
309
+ error: "Focus candidate not found"
310
+ }, 404);
311
+ deps.service.emit("focus.candidate.updated", { candidate });
312
+ return c.json({
313
+ ok: true,
314
+ candidate
315
+ });
316
+ });
317
+ }
318
+ //#endregion
319
+ export { registerFocusRoutes };
@@ -3,10 +3,6 @@ import "../../../storage/sqlite/index.js";
3
3
  import { GoalService } from "../../../goals/goal-service.js";
4
4
  import "../../../goals/index.js";
5
5
  import { listGatewayAgents } from "../../agents-admin.js";
6
- import { listFocusCalendarSignals } from "../../../proactive/calendar-signals.js";
7
- import { FocusService } from "../../../proactive/focus-service.js";
8
- import { listProactiveInsights } from "../../../proactive/insight-repository.js";
9
- import "../../../proactive/index.js";
10
6
  import { WorkItemService } from "../../../work-items/work-item-service.js";
11
7
  import "../../../work-items/index.js";
12
8
  import { getTunnelService } from "../../../tunnel/tunnel-service.js";
@@ -160,7 +156,6 @@ function buildHomeBriefing(input) {
160
156
  function registerHomeRoutes(authenticated, deps) {
161
157
  const { service } = deps;
162
158
  const goals = new GoalService();
163
- const focuses = new FocusService(service.automationServiceInstance);
164
159
  authenticated.get("/api/home", async (c) => {
165
160
  const notes = service.notesServiceInstance;
166
161
  const sessions = service.sessions;
@@ -171,8 +166,7 @@ function registerHomeRoutes(authenticated, deps) {
171
166
  const health = service.getHealth();
172
167
  const workItems = new WorkItemService();
173
168
  const nowMs = Date.now();
174
- const focusViews = focuses.list();
175
- const [recentlyOpened, inbox, pendingTasks, recentSessions, workflowRuns, automations, automationRuns, projects, allWorkItems, activeGoals, connectorApprovals, proactiveInsights, calendarSignals] = await Promise.all([
169
+ const [recentlyOpened, inbox, pendingTasks, recentSessions, workflowRuns, automations, automationRuns, projects, allWorkItems, activeGoals, connectorApprovals] = await Promise.all([
176
170
  notes.listNotes({
177
171
  sortBy: "lastOpenedAt",
178
172
  sortOrder: "desc",
@@ -189,9 +183,10 @@ function registerHomeRoutes(authenticated, deps) {
189
183
  limit: 10
190
184
  }),
191
185
  sessions.listSessions({
186
+ channel: "webchat",
192
187
  sortBy: "updatedAt",
193
188
  sortOrder: "desc",
194
- limit: 5
189
+ limit: 50
195
190
  }),
196
191
  workflowRunStore.listRunSummaries(20),
197
192
  service.automationServiceInstance.list(),
@@ -211,14 +206,15 @@ function registerHomeRoutes(authenticated, deps) {
211
206
  principalId: "local-owner",
212
207
  status: "pending",
213
208
  limit: 100
214
- })),
215
- Promise.resolve(listProactiveInsights({
216
- status: ["unread"],
217
- limit: 10
218
- })),
219
- Promise.resolve(listFocusCalendarSignals(focusViews, nowMs))
209
+ }))
220
210
  ]);
221
211
  const projectsById = new Map(projects.items.map((project) => [project.id, project]));
212
+ const workChats = recentSessions.items.filter((session) => (session.messageCount ?? 0) > 0).map((session) => ({
213
+ key: session.key,
214
+ name: session.name || "Conversation",
215
+ updatedAt: session.updatedAt,
216
+ active: sessions.getActiveRun(session.key).active
217
+ }));
222
218
  const activeWorkItems = allWorkItems.items.filter((item) => item.status !== "done" && item.status !== "cancelled").sort((left, right) => {
223
219
  return workItemAttentionRank(left, nowMs) - workItemAttentionRank(right, nowMs) || right.updatedAt - left.updatedAt;
224
220
  });
@@ -325,7 +321,7 @@ function registerHomeRoutes(authenticated, deps) {
325
321
  inboxCount: inbox.total,
326
322
  pendingTasks: pendingTasks.items,
327
323
  pendingTaskCount: pendingTasks.total,
328
- recentSessions: recentSessions.items,
324
+ recentSessions: recentSessions.items.slice(0, 5),
329
325
  activeAgent: defaultAgent ? {
330
326
  id: defaultAgent.id,
331
327
  name: defaultAgent.name,
@@ -350,8 +346,10 @@ function registerHomeRoutes(authenticated, deps) {
350
346
  },
351
347
  briefing,
352
348
  decisions,
353
- proactiveInsights,
354
- calendarSignals,
349
+ chats: {
350
+ running: workChats.filter((chat) => chat.active),
351
+ recent: workChats.filter((chat) => !chat.active).slice(0, 8)
352
+ },
355
353
  work: {
356
354
  attentionCount: activeWorkItems.filter((item) => workItemAttentionRank(item, nowMs) < 3).length,
357
355
  overdueCount: activeWorkItems.filter((item) => item.dueAt != null && item.dueAt < nowMs).length,
@@ -11,6 +11,7 @@ import { registerInteractionStateRoutes } from "./interaction-state.js";
11
11
  import { registerComposerHistoryRoutes } from "./composer-history.js";
12
12
  import { registerLocalAppsRoutes } from "./local-apps.js";
13
13
  import { registerWorkDiscoveryRoutes } from "./work-discovery.js";
14
+ import { registerFocusRoutes } from "./focuses.js";
14
15
  import { mountAppLazyRoutePrefixes, registerAuthenticatedLazyRouteFallback } from "./lazy-fallback.js";
15
16
  //#region src/gateway/hono/routes/index.ts
16
17
  function registerCoreAuthenticatedRoutes(authenticated, deps) {
@@ -22,6 +23,7 @@ function registerCoreAuthenticatedRoutes(authenticated, deps) {
22
23
  registerProjectsRoutes(authenticated, deps);
23
24
  registerLocalAppsRoutes(authenticated, deps);
24
25
  registerWorkDiscoveryRoutes(authenticated, deps);
26
+ registerFocusRoutes(authenticated, deps);
25
27
  registerSearchRoutes(authenticated, deps);
26
28
  registerMobileRoutes(authenticated, deps);
27
29
  registerTaskOutcomeRoutes(authenticated, deps);
@@ -1,4 +1,4 @@
1
- import { getSqliteDatabase, runSqliteWriteTransaction } from "../../../storage/sqlite/transaction.js";
1
+ import { getSqliteDatabase } from "../../../storage/sqlite/transaction.js";
2
2
  import { getSessionMetadata } from "../../../storage/sqlite/session-repository.js";
3
3
  import { loadTranscriptRowsForSession } from "../../../storage/sqlite/transcript-repository.js";
4
4
  import { listMemoryRecords, upsertMemoryRecord } from "../../../storage/sqlite/memory-records-repository.js";
@@ -7,8 +7,7 @@ import { ActivityService } from "../../../activity/service.js";
7
7
  import "../../../activity/index.js";
8
8
  import { buildSessionKey, init_session_key } from "../../../routing/session-key.js";
9
9
  import { resolveEffectiveAgentProfile } from "../../../config/agent-profile.js";
10
- import { GoalService, normalizeGoalUiLocale } from "../../../goals/goal-service.js";
11
- import { draftGoalContract } from "../../../goals/goal-contract-draft.js";
10
+ import { GoalService } from "../../../goals/goal-service.js";
12
11
  import "../../../goals/index.js";
13
12
  import { ProjectWorkspaceConflictError, ProjectWorkspaceMissingError } from "../../../projects/workspace-project.js";
14
13
  import { isValidProjectAgentId, normalizeProjectAgentId, resolveProjectAgentId } from "../../../projects/project-agent.js";
@@ -27,10 +26,6 @@ import { readFile, readdir, realpath, stat, writeFile } from "node:fs/promises";
27
26
  //#region src/gateway/hono/routes/projects.ts
28
27
  init_session_key();
29
28
  const log = createGatewayRouteLogger("Projects");
30
- const DELEGATED_OUTCOME_MAX_LENGTH = 12e3;
31
- function inferDelegatedWorkName(outcome) {
32
- return (outcome.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? outcome.trim()).replace(/^[#*\-\s]+/, "").replace(/[。.!!??]+$/, "").trim().slice(0, 72) || "Untitled work";
33
- }
34
29
  function parseProjectStatus(raw) {
35
30
  return raw === "active" || raw === "paused" || raw === "archived" ? raw : void 0;
36
31
  }
@@ -379,102 +374,6 @@ function registerProjectsRoutes(authenticated, deps) {
379
374
  const activity = new ActivityService();
380
375
  const goals = new GoalService();
381
376
  const workItems = new WorkItemService();
382
- authenticated.post("/api/projects/delegate", async (c) => {
383
- const body = await c.req.json().catch(() => ({}));
384
- const outcome = textField(body, "outcome")?.trim() ?? "";
385
- if (!outcome) return c.json({
386
- ok: false,
387
- error: "Missing outcome"
388
- }, 400);
389
- if (outcome.length > DELEGATED_OUTCOME_MAX_LENGTH) return c.json({
390
- ok: false,
391
- error: `Outcome exceeds ${DELEGATED_OUTCOME_MAX_LENGTH} characters`
392
- }, 400);
393
- const name = textField(body, "name")?.trim().slice(0, 72) || inferDelegatedWorkName(outcome);
394
- const uiLocale = normalizeGoalUiLocale(body.uiLocale);
395
- const defaultAgentId = inferSuggestedProjectDefaultAgentId({
396
- config: service.currentConfig,
397
- name,
398
- description: outcome,
399
- projectKind: "auto"
400
- });
401
- if (!isValidProjectAgentId(service.currentConfig, defaultAgentId)) return c.json({
402
- ok: false,
403
- error: "Default agent not found"
404
- }, 400);
405
- const contractDraft = await draftGoalContract({
406
- title: name,
407
- context: outcome,
408
- uiLocale,
409
- modelRef: service.currentConfig.goals?.judgeModelRef
410
- });
411
- let created;
412
- try {
413
- created = runSqliteWriteTransaction(() => {
414
- const project = service.projects.create({
415
- name,
416
- description: outcome,
417
- defaultAgentId,
418
- projectKind: "auto",
419
- brief: outcome
420
- });
421
- const goal = goals.create({
422
- title: name,
423
- description: outcome,
424
- agentId: defaultAgentId,
425
- priority: "normal",
426
- uiLocale,
427
- source: "api",
428
- projectId: project.id,
429
- contract: contractDraft.contract,
430
- config: service.currentConfig
431
- });
432
- const detailedGoal = goals.setContextMessage({
433
- goalId: goal.id,
434
- text: outcome
435
- });
436
- if (!detailedGoal) throw new Error("Goal context could not be saved");
437
- return {
438
- project,
439
- goal: detailedGoal
440
- };
441
- });
442
- } catch (error) {
443
- log.warn({
444
- err: error,
445
- phase: "delegate_create"
446
- }, `Delegated work could not be created: ${error instanceof Error ? error.message : String(error)}`);
447
- return c.json({
448
- ok: false,
449
- error: error instanceof Error ? error.message : String(error)
450
- }, 400);
451
- }
452
- let queued;
453
- let executionWarning;
454
- try {
455
- queued = service.enqueueGoalRun(created.goal.id, { source: "api" });
456
- } catch (error) {
457
- executionWarning = error instanceof Error ? error.message : String(error);
458
- log.warn({
459
- err: error,
460
- projectId: created.project.id,
461
- goalId: created.goal.id,
462
- phase: "delegate_enqueue"
463
- }, `Delegated work was saved but could not be queued: ${executionWarning}`);
464
- }
465
- return c.json({
466
- ok: true,
467
- project: enrichProjectWorkspace(service, created.project),
468
- goal: created.goal,
469
- contractGenerated: contractDraft.generated,
470
- contractWarning: contractDraft.warning,
471
- execution: {
472
- status: queued ? "queued" : "saved",
473
- queueItem: queued,
474
- warning: executionWarning
475
- }
476
- }, 201);
477
- });
478
377
  authenticated.post("/api/projects", async (c) => {
479
378
  const body = await c.req.json().catch(() => ({}));
480
379
  const name = textField(body, "name")?.trim();