@xopcai/xopc 0.0.173 → 0.0.175

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 (224) 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-ByVA0N5n.js → activity-store-CM6mQUS2.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CJ5HvqE7.js → agent-avatar-dicebear-eckyE9AY.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-D-OIB_r0.js +2 -0
  6. package/dist/gateway/static/root/assets/api-2SLLStKp.js +1 -0
  7. package/dist/gateway/static/root/assets/{api-BZtCKzg4.js → api-BfMRS6FX.js} +1 -1
  8. package/dist/gateway/static/root/assets/{app-management-settings-panel-B0oNNcFn.js → app-management-settings-panel-DYkzZQzZ.js} +1 -1
  9. package/dist/gateway/static/root/assets/{appearance-settings-DbIj4NQ1.js → appearance-settings-CDXXN57j.js} +1 -1
  10. package/dist/gateway/static/root/assets/apps-page-CuvFyvuu.js +1 -0
  11. package/dist/gateway/static/root/assets/{archive-plugin-BICLQFWJ.js → archive-plugin-k909a76t.js} +1 -1
  12. package/dist/gateway/static/root/assets/{attachment-load-DV3PteSU.js → attachment-load-CqNzyhdJ.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automation-suggestion-card-CZUImis0.js → automation-suggestion-card-snNG6u0v.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-page-DetGVTjI.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-D6zkab6N.js → binary-plugins-PfQ9ZHDF.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-zCzoQI-g.js → block-editor-Xrw-DnE_.js} +6 -6
  17. package/dist/gateway/static/root/assets/browser-settings-page-G92AdEnX.js +8 -0
  18. package/dist/gateway/static/root/assets/{browser-workflow-inputs-CY3X83xQ.js → browser-workflow-inputs-DJPF2lUY.js} +1 -1
  19. package/dist/gateway/static/root/assets/{browser-workflows-page-DDRtZLuM.js → browser-workflows-page-BoXs4pgc.js} +2 -2
  20. package/dist/gateway/static/root/assets/capabilities-settings-panel-nS_AMN1K.js +7 -0
  21. package/dist/gateway/static/root/assets/{capability-presets-api-pYLW6P7g.js → capability-presets-api-BgY-Ysmi.js} +1 -1
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DIO8ZNHW.js +1 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-DxyOH3BO.js → channel-recipient-api-D32T1EJM.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-4Im3vtnO.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-CMctpuqb.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-BgANwjt-.js → connector-logo-C-l8haIK.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-vL3SjHSc.js +2 -0
  28. package/dist/gateway/static/root/assets/copy-VueTIC2x.js +1 -0
  29. package/dist/gateway/static/root/assets/{desktop-pet-BPjQbPeA.js → desktop-pet-CwOI_Hei.js} +1 -1
  30. package/dist/gateway/static/root/assets/{desktop-pet-settings-8CaU1Mhm.js → desktop-pet-settings-Cldo_pA3.js} +1 -1
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-BtNRUvzM.js → directory-picker-path-field-CMASXbgJ.js} +1 -1
  32. package/dist/gateway/static/root/assets/dreaming-settings-BnMx02w0.js +3 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-DFjTfx6f.js → extension-debug-page-mUFs3ign.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-NyEYtWWg.js → extension-page-BsFBOZ5N.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-BynTCfgf.js → extension-settings-page-CTEoovnV.js} +1 -1
  36. package/dist/gateway/static/root/assets/focus-detail-page-CCaZthpU.js +1 -0
  37. package/dist/gateway/static/root/assets/{gateway-config-api-BzOWImvU.js → gateway-config-api-Bwx-EetD.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-DXepE_Jw.js → gateway-settings-CvgyqhR_.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-C2JXXtwg.js → gateway-startup-retry-C8f5KwkT.js} +1 -1
  40. package/dist/gateway/static/root/assets/{goal-create-dialog-ClOZyG52.js → goal-create-dialog-Bhynl9LN.js} +1 -1
  41. package/dist/gateway/static/root/assets/goal-detail-page-ChS2rU0w.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-CU3JR9MI.js → goals-config-api-CUnfbgHa.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-BAS_liXl.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-DSZguLEx.js → goals-settings-Bkk-tOcf.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-KRkYziEF.js → heartbeat-settings-D9Pldf5E.js} +1 -1
  46. package/dist/gateway/static/root/assets/{image-generation-api-Y-n6TaZ_.js → image-generation-api-D7aCMgOv.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-DJ5vdaHk.css +1 -0
  48. package/dist/gateway/static/root/assets/index-TnouSpay.js +212 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-CwrQv952.js → keyboard-shortcuts-settings-CBhtXhHb.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-HQeu_F1C.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-DtITcS4K.js → local-apps-page-BtJGF3M8.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-Ccv7tH8B.js → locale-store-DO-u1yS7.js} +1 -1
  53. package/dist/gateway/static/root/assets/logs-page-0lvwfLAA.js +7 -0
  54. package/dist/gateway/static/root/assets/{markdown-split-D1oZlq1m.js → markdown-split-BGPaeTch.js} +1 -1
  55. package/dist/gateway/static/root/assets/{media-plugins-BKz5V32t.js → media-plugins-C_Cx8v6u.js} +1 -1
  56. package/dist/gateway/static/root/assets/messages-BP8aQX-5.js +3 -0
  57. package/dist/gateway/static/root/assets/{notes-page-DLekBQPa.js → notes-page-CIYy5BKF.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-_FgNPlOx.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-pT4nLfqS.js → page-tabs-C2vsdfJO.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-OtAiaJm2.js → preview-open-alternatives-D_VT83bW.js} +1 -1
  61. package/dist/gateway/static/root/assets/{product-open-page-CfryBKD9.js → product-open-page-BNP9kZ3Q.js} +1 -1
  62. package/dist/gateway/static/root/assets/project-detail-page-MNi-3mZU.js +1 -0
  63. package/dist/gateway/static/root/assets/{projects-page-3ubcbqHr.js → projects-page-xx8nUKZO.js} +1 -1
  64. package/dist/gateway/static/root/assets/remote-access-hub-H5DSn2bR.js +1 -0
  65. package/dist/gateway/static/root/assets/{save-bar-controls-nP1SB3Lf.js → save-bar-controls-BJL6Xb-F.js} +1 -1
  66. package/dist/gateway/static/root/assets/{schedule-field-OEQTsUNz.js → schedule-field-CxCPSLbu.js} +1 -1
  67. package/dist/gateway/static/root/assets/{schema-form-DIcAa7CJ.js → schema-form-Cao1wGbk.js} +1 -1
  68. package/dist/gateway/static/root/assets/sessions-page-CMQsupwM.js +1 -0
  69. package/dist/gateway/static/root/assets/settings-advanced-gate-OBUdG6bV.js +1 -0
  70. package/dist/gateway/static/root/assets/{settings-form-section-BxNcTbYO.js → settings-form-section-9pgClEud.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-loading-skeleton-Dpdxu4sf.js → settings-loading-skeleton-CQz0gEUK.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-page-DwPeOm1c.js → settings-page-DgsMzZLm.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-layout-CqirFmMn.js → settings-page-layout-BhqupMfG.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-B7BsWxJt.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-D72gYeux.js → share-preview-page-CC4dQsQN.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-Bhz21P05.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-CBP-UB88.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-A0rNObNB.js +2 -0
  79. package/dist/gateway/static/root/assets/skills-page.utils-CF4AYPQg.js +1 -0
  80. package/dist/gateway/static/root/assets/{system-settings-panel-U0tBgW46.js → system-settings-panel-CzZHWI4u.js} +1 -1
  81. package/dist/gateway/static/root/assets/{theme-store-DCKDVPFF.js → theme-store-BZWNdSZC.js} +1 -1
  82. package/dist/gateway/static/root/assets/time-picker-BC922Mdg.js +1 -0
  83. package/dist/gateway/static/root/assets/{typed-models-lib-D0XCOCAM.js → typed-models-lib-C1S-B1pk.js} +1 -1
  84. package/dist/gateway/static/root/assets/{use-channel-catalog-mq_Inao2.js → use-channel-catalog-DTiLxcLF.js} +1 -1
  85. package/dist/gateway/static/root/assets/user-context-page-8XdpiAyP.js +1 -0
  86. package/dist/gateway/static/root/assets/{voice-api-key-field-CKaDitO6.js → voice-api-key-field-CtIYRNfI.js} +1 -1
  87. package/dist/gateway/static/root/assets/work-discovery-page-DBer86NF.js +1 -0
  88. package/dist/gateway/static/root/assets/work-item-detail-page-BUPyfYaq.js +1 -0
  89. package/dist/gateway/static/root/assets/work-page-G8phwwI1.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-s_kS_FYA.js → workflow-run-setup-panel-IKxqDAXw.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-CNls7g6v.js +11 -0
  92. package/dist/gateway/static/root/index.html +7 -7
  93. package/dist/package.js +1 -1
  94. package/dist/src/agent/agent-manager.js +1 -1
  95. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  96. package/dist/src/agent/service.js +1 -1
  97. package/dist/src/agent/skills/hub-pull.js +1 -1
  98. package/dist/src/agent/skills/index.d.ts +2 -0
  99. package/dist/src/agent/skills/index.js +14 -5
  100. package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
  101. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  102. package/dist/src/agent/skills/test-framework.js +1 -1
  103. package/dist/src/automations/domain/defaults.d.ts +1 -0
  104. package/dist/src/automations/domain/defaults.js +4 -0
  105. package/dist/src/automations/domain/index.d.ts +1 -0
  106. package/dist/src/automations/domain/index.js +2 -1
  107. package/dist/src/automations/index.js +2 -1
  108. package/dist/src/automations/service/action-executor.js +2 -2
  109. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  110. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  111. package/dist/src/cli/commands/skills.js +1 -1
  112. package/dist/src/config/agent-profile.js +1 -1
  113. package/dist/src/focuses/candidate-repository.d.ts +15 -0
  114. package/dist/src/focuses/candidate-repository.js +91 -0
  115. package/dist/src/focuses/index.d.ts +7 -0
  116. package/dist/src/focuses/index.js +7 -0
  117. package/dist/src/focuses/insight-repository.d.ts +22 -0
  118. package/dist/src/focuses/insight-repository.js +77 -0
  119. package/dist/src/focuses/prompts.d.ts +2 -0
  120. package/dist/src/focuses/prompts.js +18 -0
  121. package/dist/src/focuses/reconciler.d.ts +5 -0
  122. package/dist/src/focuses/reconciler.js +26 -0
  123. package/dist/src/focuses/repository.d.ts +61 -0
  124. package/dist/src/focuses/repository.js +214 -0
  125. package/dist/src/focuses/run-processor.d.ts +18 -0
  126. package/dist/src/focuses/run-processor.js +162 -0
  127. package/dist/src/focuses/service.d.ts +42 -0
  128. package/dist/src/focuses/service.js +241 -0
  129. package/dist/src/focuses/types.d.ts +89 -0
  130. package/dist/src/gateway/agents-admin.js +1 -1
  131. package/dist/src/gateway/heartbeat/service.js +1 -1
  132. package/dist/src/gateway/hono/routes/focuses.d.ts +3 -0
  133. package/dist/src/gateway/hono/routes/focuses.js +319 -0
  134. package/dist/src/gateway/hono/routes/home.d.ts +16 -3
  135. package/dist/src/gateway/hono/routes/home.js +113 -42
  136. package/dist/src/gateway/hono/routes/index.js +4 -0
  137. package/dist/src/gateway/hono/routes/local-apps.js +1 -1
  138. package/dist/src/gateway/hono/routes/project-skills.d.ts +3 -0
  139. package/dist/src/gateway/hono/routes/project-skills.js +119 -0
  140. package/dist/src/gateway/hono/routes/projects.js +2 -103
  141. package/dist/src/gateway/hono/routes/work-discovery.js +0 -239
  142. package/dist/src/gateway/service.d.ts +1 -1
  143. package/dist/src/gateway/service.js +17 -13
  144. package/dist/src/heartbeat/index.js +1 -1
  145. package/dist/src/infra/update-restart.js +1 -1
  146. package/dist/src/mcp/channel-bridge.js +1 -1
  147. package/dist/src/projects/index.d.ts +1 -0
  148. package/dist/src/projects/index.js +2 -1
  149. package/dist/src/projects/project-skill-service.d.ts +67 -0
  150. package/dist/src/projects/project-skill-service.js +131 -0
  151. package/dist/src/storage/sqlite/home-attention-repository.d.ts +3 -0
  152. package/dist/src/storage/sqlite/home-attention-repository.js +21 -0
  153. package/dist/src/storage/sqlite/index.d.ts +1 -0
  154. package/dist/src/storage/sqlite/index.js +2 -1
  155. package/dist/src/storage/sqlite/migrations/066_first_class_focuses.sql +126 -0
  156. package/dist/src/storage/sqlite/migrations/067_home_attention_acknowledgements.sql +9 -0
  157. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  158. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  159. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  160. package/dist/src/storage/sqlite/schema.js +1 -1
  161. package/dist/src/storage/sqlite/schema.sql +10 -0
  162. package/dist/src/tui/tui-startup-resources.js +1 -1
  163. package/dist/src/work-discovery/index.d.ts +0 -2
  164. package/dist/src/work-discovery/index.js +1 -3
  165. package/dist/src/work-discovery/service.d.ts +0 -30
  166. package/dist/src/work-discovery/service.js +1 -35
  167. package/dist/src/work-discovery/thread-service.d.ts +5 -0
  168. package/dist/src/work-discovery/thread-service.js +36 -88
  169. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  170. package/package.json +1 -1
  171. package/dist/gateway/static/root/assets/agents--TQ9jM_1.js +0 -2
  172. package/dist/gateway/static/root/assets/apps-page-BDsoZDEn.js +0 -1
  173. package/dist/gateway/static/root/assets/automations-page-CHrNcppN.js +0 -6
  174. package/dist/gateway/static/root/assets/browser-settings-page-BQoRuQzH.js +0 -8
  175. package/dist/gateway/static/root/assets/capabilities-settings-panel-BOcU0qeM.js +0 -7
  176. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CJ1F_hlX.js +0 -1
  177. package/dist/gateway/static/root/assets/channels-settings-C4vDwRil.js +0 -1
  178. package/dist/gateway/static/root/assets/channels-status-swr-B0Pgq5x2.js +0 -1
  179. package/dist/gateway/static/root/assets/connectors-page-D6JEqDEj.js +0 -2
  180. package/dist/gateway/static/root/assets/dreaming-settings-Byv-h8XZ.js +0 -3
  181. package/dist/gateway/static/root/assets/goal-detail-page-UbZB77De.js +0 -4
  182. package/dist/gateway/static/root/assets/goals-page-GMqV8Fwv.js +0 -2
  183. package/dist/gateway/static/root/assets/index-BCkNJ5cR.css +0 -1
  184. package/dist/gateway/static/root/assets/index-CAZ9343h.js +0 -212
  185. package/dist/gateway/static/root/assets/local-app-workbench-page-m5HEyrHT.js +0 -2
  186. package/dist/gateway/static/root/assets/logs-page-Bf_nk75f.js +0 -7
  187. package/dist/gateway/static/root/assets/messages-DWrg3c4K.js +0 -3
  188. package/dist/gateway/static/root/assets/notes-workbench-BTDmprHM.js +0 -4
  189. package/dist/gateway/static/root/assets/project-detail-page-C7kntu4H.js +0 -1
  190. package/dist/gateway/static/root/assets/remote-access-hub-DoUkN3ik.js +0 -1
  191. package/dist/gateway/static/root/assets/sessions-page-ElAAlZ-R.js +0 -1
  192. package/dist/gateway/static/root/assets/settings-advanced-gate-CQn_KBqr.js +0 -1
  193. package/dist/gateway/static/root/assets/setup-status-panel-DX_LdcTN.js +0 -1
  194. package/dist/gateway/static/root/assets/shares-settings-nSfe-5xK.js +0 -1
  195. package/dist/gateway/static/root/assets/skill-reload-api-1tYpZrJf.js +0 -1
  196. package/dist/gateway/static/root/assets/skills-page-BUJl8LJG.js +0 -2
  197. package/dist/gateway/static/root/assets/time-picker-BpiBF5-d.js +0 -1
  198. package/dist/gateway/static/root/assets/user-context-page-BOC6Hn19.js +0 -1
  199. package/dist/gateway/static/root/assets/work-discovery-page-DWGYp5yV.js +0 -1
  200. package/dist/gateway/static/root/assets/work-item-detail-page-CpeWcpSp.js +0 -1
  201. package/dist/gateway/static/root/assets/work-page-MsEKzmSt.js +0 -1
  202. package/dist/gateway/static/root/assets/workflows-page-ByhHaUHB.js +0 -11
  203. package/dist/src/proactive/calendar-signals.d.ts +0 -4
  204. package/dist/src/proactive/calendar-signals.js +0 -120
  205. package/dist/src/proactive/focus-service.d.ts +0 -62
  206. package/dist/src/proactive/focus-service.js +0 -173
  207. package/dist/src/proactive/index.d.ts +0 -7
  208. package/dist/src/proactive/index.js +0 -7
  209. package/dist/src/proactive/insight-repository.d.ts +0 -21
  210. package/dist/src/proactive/insight-repository.js +0 -109
  211. package/dist/src/proactive/run-processor.d.ts +0 -19
  212. package/dist/src/proactive/run-processor.js +0 -146
  213. package/dist/src/proactive/trial-expiry-reconciler.d.ts +0 -5
  214. package/dist/src/proactive/trial-expiry-reconciler.js +0 -30
  215. package/dist/src/proactive/types.d.ts +0 -66
  216. package/dist/src/proactive/value-score.d.ts +0 -13
  217. package/dist/src/proactive/value-score.js +0 -30
  218. package/dist/src/proactive/watch-repository.d.ts +0 -28
  219. package/dist/src/proactive/watch-repository.js +0 -129
  220. package/dist/src/work-discovery/governance.d.ts +0 -25
  221. package/dist/src/work-discovery/governance.js +0 -96
  222. package/dist/src/work-discovery/thread-repository.d.ts +0 -34
  223. package/dist/src/work-discovery/thread-repository.js +0 -112
  224. /package/dist/src/{proactive → focuses}/types.js +0 -0
@@ -1,7 +1,19 @@
1
1
  import type { Hono } from 'hono';
2
+ import { type HomeAttentionSubjectKind } from '../../../storage/sqlite/index.js';
2
3
  import type { AuthenticatedRouteDeps } from './deps.js';
3
- type HomeDecisionKind = 'work_item' | 'goal' | 'workflow_run' | 'automation_run' | 'connector_approval' | 'goal_evidence';
4
- type HomeDecisionReason = 'needs_input' | 'in_review' | 'blocked' | 'overdue' | 'due_soon' | 'run_failed' | 'approval_required';
4
+ type HomeDecisionKind = 'work_item' | 'goal' | 'connector_approval' | 'goal_evidence';
5
+ type HomeDecisionReason = 'needs_input' | 'in_review' | 'blocked' | 'overdue' | 'due_soon' | 'approval_required';
6
+ type HomeAttention = {
7
+ id: string;
8
+ kind: HomeAttentionSubjectKind;
9
+ runId: string;
10
+ title: string;
11
+ detail: string;
12
+ reason: 'run_failed' | 'run_timeout';
13
+ href: string;
14
+ updatedAt: number;
15
+ sessionKey?: string;
16
+ };
5
17
  type HomeDecision = {
6
18
  id: string;
7
19
  kind: HomeDecisionKind;
@@ -39,6 +51,7 @@ type HomeAutomation = {
39
51
  export declare function buildHomeBriefing(input: {
40
52
  locale?: string;
41
53
  decisions: HomeDecision[];
54
+ attention: HomeAttention[];
42
55
  activeWorkCount: number;
43
56
  activeWorkflowCount: number;
44
57
  activeGoalCount: number;
@@ -68,7 +81,7 @@ export declare function buildHomeBriefing(input: {
68
81
  * - recentSessions: last 5 active AI sessions (threads)
69
82
  * - activeAgent: default agent identity for this gateway
70
83
  * - gateway: readiness + public tunnel status
71
- * - workflowRuns: active / attention / recent workflow runs
84
+ * - workflowRuns: active and recent workflow runs
72
85
  * - upcomingAutomations: upcoming enabled automations
73
86
  * - recentAutomationRuns: latest automation executions
74
87
  */
@@ -1,12 +1,11 @@
1
+ import { acknowledgeHomeAttention, isHomeAttentionAcknowledged } from "../../../storage/sqlite/home-attention-repository.js";
1
2
  import { decideConnectorApproval, listConnectorApprovals } from "../../../storage/sqlite/connector-repository.js";
2
3
  import "../../../storage/sqlite/index.js";
3
4
  import { GoalService } from "../../../goals/goal-service.js";
4
5
  import "../../../goals/index.js";
6
+ import "../../../automations/domain/defaults.js";
7
+ import "../../../automations/index.js";
5
8
  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
9
  import { WorkItemService } from "../../../work-items/work-item-service.js";
11
10
  import "../../../work-items/index.js";
12
11
  import { getTunnelService } from "../../../tunnel/tunnel-service.js";
@@ -87,6 +86,19 @@ function toHomeAutomationRun(run) {
87
86
  workflowRunId: run.workflowRunId
88
87
  };
89
88
  }
89
+ function effectiveAutomationTimeoutSeconds(run, automation) {
90
+ return run.actionSnapshot.timeoutSeconds ?? automation?.reliability?.timeoutSeconds ?? 300;
91
+ }
92
+ function attentionDetail(kind, status, locale, timeoutSeconds) {
93
+ const isChinese = locale?.toLowerCase().startsWith("zh") ?? false;
94
+ if (status === "timeout") {
95
+ const seconds = timeoutSeconds ?? 300;
96
+ const duration = seconds % 60 === 0 ? `${seconds / 60} ${isChinese ? "分钟" : seconds === 60 ? "minute" : "minutes"}` : `${seconds} ${isChinese ? "秒" : seconds === 1 ? "second" : "seconds"}`;
97
+ return isChinese ? `运行超过 ${duration},系统已停止本次执行。` : `The run exceeded ${duration} and was stopped.`;
98
+ }
99
+ if (isChinese) return kind === "automation_run" ? "自动化未能完成,请查看详情后重试。" : "工作流未能完成,请查看详情后重试。";
100
+ return kind === "automation_run" ? "The automation did not complete. Review the details and retry." : "The workflow did not complete. Review the details and retry.";
101
+ }
90
102
  function decisionFromGoal(goal, projectName) {
91
103
  if (goal.status !== "needs_input" && goal.status !== "blocked") return null;
92
104
  return {
@@ -128,7 +140,8 @@ function decisionFromWorkItem(item, projectName, nowMs) {
128
140
  function buildHomeBriefing(input) {
129
141
  const isChinese = input.locale?.toLowerCase().startsWith("zh") ?? false;
130
142
  const movingCount = input.activeWorkCount + input.activeWorkflowCount + input.activeGoalCount;
131
- const summary = input.decisions.length > 0 ? isChinese ? `有 ${input.decisions.length} 件事等你决定;我正在继续推进 ${movingCount} 件工作。` : `${input.decisions.length} ${input.decisions.length === 1 ? "item needs" : "items need"} your decision; I’m continuing ${movingCount} in the background.` : movingCount > 0 ? isChinese ? `目前没有事情需要你处理;我正在继续推进 ${movingCount} 件工作。` : `Nothing needs you right now; I’m continuing ${movingCount} ${movingCount === 1 ? "item" : "items"} in the background.` : isChinese ? "今天还没有正在推进的事项。把想要的结果交给我,我会从这里开始。" : "Nothing is moving yet today. Hand me an outcome and I’ll take it from here.";
143
+ const attentionCount = input.decisions.length + input.attention.length;
144
+ const summary = attentionCount > 0 ? isChinese ? movingCount > 0 ? `有 ${attentionCount} 件事需要你处理;我正在继续推进 ${movingCount} 件工作。` : `有 ${attentionCount} 件事需要你处理。` : movingCount > 0 ? `${attentionCount} ${attentionCount === 1 ? "item needs" : "items need"} your attention; I’m continuing ${movingCount} in the background.` : `${attentionCount} ${attentionCount === 1 ? "item needs" : "items need"} your attention.` : movingCount > 0 ? isChinese ? `目前没有事情需要你处理;我正在继续推进 ${movingCount} 件工作。` : `Nothing needs you right now; I’m continuing ${movingCount} ${movingCount === 1 ? "item" : "items"} in the background.` : isChinese ? "今天还没有正在推进的事项。把想要的结果交给我,我会从这里开始。" : "Nothing is moving yet today. Hand me an outcome and I’ll take it from here.";
132
145
  return {
133
146
  generatedAt: input.nowMs,
134
147
  summary,
@@ -153,14 +166,13 @@ function buildHomeBriefing(input) {
153
166
  * - recentSessions: last 5 active AI sessions (threads)
154
167
  * - activeAgent: default agent identity for this gateway
155
168
  * - gateway: readiness + public tunnel status
156
- * - workflowRuns: active / attention / recent workflow runs
169
+ * - workflowRuns: active and recent workflow runs
157
170
  * - upcomingAutomations: upcoming enabled automations
158
171
  * - recentAutomationRuns: latest automation executions
159
172
  */
160
173
  function registerHomeRoutes(authenticated, deps) {
161
174
  const { service } = deps;
162
175
  const goals = new GoalService();
163
- const focuses = new FocusService(service.automationServiceInstance);
164
176
  authenticated.get("/api/home", async (c) => {
165
177
  const notes = service.notesServiceInstance;
166
178
  const sessions = service.sessions;
@@ -171,8 +183,7 @@ function registerHomeRoutes(authenticated, deps) {
171
183
  const health = service.getHealth();
172
184
  const workItems = new WorkItemService();
173
185
  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([
186
+ const [recentlyOpened, inbox, pendingTasks, recentSessions, workflowRuns, automations, automationRuns, projects, allWorkItems, activeGoals, connectorApprovals] = await Promise.all([
176
187
  notes.listNotes({
177
188
  sortBy: "lastOpenedAt",
178
189
  sortOrder: "desc",
@@ -189,9 +200,10 @@ function registerHomeRoutes(authenticated, deps) {
189
200
  limit: 10
190
201
  }),
191
202
  sessions.listSessions({
203
+ channel: "webchat",
192
204
  sortBy: "updatedAt",
193
205
  sortOrder: "desc",
194
- limit: 5
206
+ limit: 50
195
207
  }),
196
208
  workflowRunStore.listRunSummaries(20),
197
209
  service.automationServiceInstance.list(),
@@ -211,14 +223,15 @@ function registerHomeRoutes(authenticated, deps) {
211
223
  principalId: "local-owner",
212
224
  status: "pending",
213
225
  limit: 100
214
- })),
215
- Promise.resolve(listProactiveInsights({
216
- status: ["unread"],
217
- limit: 10
218
- })),
219
- Promise.resolve(listFocusCalendarSignals(focusViews, nowMs))
226
+ }))
220
227
  ]);
221
228
  const projectsById = new Map(projects.items.map((project) => [project.id, project]));
229
+ const workChats = recentSessions.items.filter((session) => (session.messageCount ?? 0) > 0).map((session) => ({
230
+ key: session.key,
231
+ name: session.name || "Conversation",
232
+ updatedAt: session.updatedAt,
233
+ active: sessions.getActiveRun(session.key).active
234
+ }));
222
235
  const activeWorkItems = allWorkItems.items.filter((item) => item.status !== "done" && item.status !== "cancelled").sort((left, right) => {
223
236
  return workItemAttentionRank(left, nowMs) - workItemAttentionRank(right, nowMs) || right.updatedAt - left.updatedAt;
224
237
  });
@@ -226,33 +239,14 @@ function registerHomeRoutes(authenticated, deps) {
226
239
  const currentWorkItems = activeWorkItems.slice(0, 30).map((item) => toHomeWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project"));
227
240
  const recentlyCompletedWorkItems = allWorkItems.items.filter((item) => item.status === "done").sort((left, right) => (right.completedAt ?? right.updatedAt) - (left.completedAt ?? left.updatedAt)).slice(0, 8).map((item) => toHomeWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project"));
228
241
  const activeWorkflowRuns = workflowRuns.filter((run) => run.status === "queued" || run.status === "running").slice(0, 5).map(toHomeWorkflowRun);
229
- const attentionWorkflowRuns = workflowRuns.filter((run) => run.status === "failed" || run.status === "timeout").slice(0, 5).map(toHomeWorkflowRun);
242
+ const failedWorkflowRuns = workflowRuns.filter((run) => run.status === "failed" || run.status === "timeout").slice(0, 5).map(toHomeWorkflowRun);
230
243
  const recentWorkflowRuns = workflowRuns.slice(0, 5).map(toHomeWorkflowRun);
231
244
  const upcomingAutomations = automations.map(toHomeAutomation).filter((automation) => Boolean(automation)).sort((a, b) => Date.parse(a.nextRunAt) - Date.parse(b.nextRunAt)).slice(0, 5);
232
245
  const latestAutomationRuns = [...automationRuns].sort((left, right) => right.createdAtMs - left.createdAtMs).filter((run, index, all) => all.findIndex((candidate) => candidate.automationId === run.automationId) === index);
246
+ const automationsById = new Map(automations.map((automation) => [automation.id, automation]));
233
247
  const decisions = [
234
248
  ...activeWorkItems.map((item) => decisionFromWorkItem(item, projectsById.get(item.projectId)?.name ?? "Project", nowMs)).filter((item) => Boolean(item)),
235
249
  ...activeGoals.map((goal) => decisionFromGoal(goal, goal.projectId ? projectsById.get(goal.projectId)?.name : void 0)).filter((item) => Boolean(item)),
236
- ...attentionWorkflowRuns.map((run) => ({
237
- id: `workflow:${run.id}`,
238
- kind: "workflow_run",
239
- title: run.title,
240
- detail: run.status,
241
- reason: "run_failed",
242
- urgency: "now",
243
- href: `/workflows?runId=${encodeURIComponent(run.id)}`,
244
- updatedAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs
245
- })),
246
- ...latestAutomationRuns.filter((run) => run.status === "failed" || run.status === "timeout").map((run) => ({
247
- id: `automation:${run.id}`,
248
- kind: "automation_run",
249
- title: run.automationName || run.automationId,
250
- detail: run.error || run.summary,
251
- reason: "run_failed",
252
- urgency: "now",
253
- href: "/automations",
254
- updatedAt: run.endedAtMs ?? run.startedAtMs ?? run.createdAtMs
255
- })),
256
250
  ...connectorApprovals.filter((approval) => Date.parse(approval.expiresAt) > nowMs).map((approval) => ({
257
251
  id: `connector-approval:${approval.id}`,
258
252
  kind: "connector_approval",
@@ -287,6 +281,28 @@ function registerHomeRoutes(authenticated, deps) {
287
281
  ].sort((left, right) => {
288
282
  return (left.urgency === "now" ? 0 : 1) - (right.urgency === "now" ? 0 : 1) || right.updatedAt - left.updatedAt;
289
283
  }).slice(0, 20);
284
+ const locale = c.req.query("locale");
285
+ const attention = [...failedWorkflowRuns.filter((run) => !isHomeAttentionAcknowledged("workflow_run", run.id)).map((run) => ({
286
+ id: `workflow_run:${run.id}`,
287
+ kind: "workflow_run",
288
+ runId: run.id,
289
+ title: run.title,
290
+ detail: attentionDetail("workflow_run", run.status === "timeout" ? "timeout" : "failed", locale),
291
+ reason: run.status === "timeout" ? "run_timeout" : "run_failed",
292
+ href: `/workflows?runId=${encodeURIComponent(run.id)}`,
293
+ updatedAt: run.completedAtMs ?? run.startedAtMs ?? run.createdAtMs,
294
+ sessionKey: run.sessionKey
295
+ })), ...latestAutomationRuns.filter((run) => run.status === "failed" || run.status === "timeout").filter((run) => !isHomeAttentionAcknowledged("automation_run", run.id)).map((run) => ({
296
+ id: `automation_run:${run.id}`,
297
+ kind: "automation_run",
298
+ runId: run.id,
299
+ title: run.automationName || run.automationId,
300
+ detail: attentionDetail("automation_run", run.status === "timeout" ? "timeout" : "failed", locale, effectiveAutomationTimeoutSeconds(run, automationsById.get(run.automationId))),
301
+ reason: run.status === "timeout" ? "run_timeout" : "run_failed",
302
+ href: `/automations?run=${encodeURIComponent(run.id)}`,
303
+ updatedAt: run.endedAtMs ?? run.startedAtMs ?? run.createdAtMs,
304
+ sessionKey: run.sessionKey
305
+ }))].sort((left, right) => right.updatedAt - left.updatedAt).slice(0, 10);
290
306
  const wins = [
291
307
  ...recentlyCompletedWorkItems.map((item) => ({
292
308
  id: `work:${item.id}`,
@@ -311,8 +327,9 @@ function registerHomeRoutes(authenticated, deps) {
311
327
  }))
312
328
  ].sort((left, right) => right.completedAt - left.completedAt);
313
329
  const briefing = buildHomeBriefing({
314
- locale: c.req.query("locale"),
330
+ locale,
315
331
  decisions,
332
+ attention,
316
333
  activeWorkCount: activeWorkItems.filter((item) => item.status === "in_progress").length,
317
334
  activeWorkflowCount: activeWorkflowRuns.length,
318
335
  activeGoalCount: activeGoals.filter((goal) => goal.status === "active").length,
@@ -325,7 +342,7 @@ function registerHomeRoutes(authenticated, deps) {
325
342
  inboxCount: inbox.total,
326
343
  pendingTasks: pendingTasks.items,
327
344
  pendingTaskCount: pendingTasks.total,
328
- recentSessions: recentSessions.items,
345
+ recentSessions: recentSessions.items.slice(0, 5),
329
346
  activeAgent: defaultAgent ? {
330
347
  id: defaultAgent.id,
331
348
  name: defaultAgent.name,
@@ -345,13 +362,15 @@ function registerHomeRoutes(authenticated, deps) {
345
362
  },
346
363
  workflowRuns: {
347
364
  active: activeWorkflowRuns,
348
- attention: attentionWorkflowRuns,
349
365
  recent: recentWorkflowRuns
350
366
  },
351
367
  briefing,
352
368
  decisions,
353
- proactiveInsights,
354
- calendarSignals,
369
+ attention,
370
+ chats: {
371
+ running: workChats.filter((chat) => chat.active),
372
+ recent: workChats.filter((chat) => !chat.active).slice(0, 8)
373
+ },
355
374
  work: {
356
375
  attentionCount: activeWorkItems.filter((item) => workItemAttentionRank(item, nowMs) < 3).length,
357
376
  overdueCount: activeWorkItems.filter((item) => item.dueAt != null && item.dueAt < nowMs).length,
@@ -414,6 +433,58 @@ function registerHomeRoutes(authenticated, deps) {
414
433
  error: "Unsupported decision kind"
415
434
  }, 400);
416
435
  });
436
+ authenticated.post("/api/home/attention/acknowledge", deps.strictRateLimitMiddleware, async (c) => {
437
+ const body = await c.req.json().catch(() => ({}));
438
+ const kind = body.kind === "automation_run" || body.kind === "workflow_run" ? body.kind : void 0;
439
+ const runId = typeof body.runId === "string" ? body.runId.trim() : "";
440
+ if (!kind || !runId) return c.json({
441
+ ok: false,
442
+ error: "kind and runId are required"
443
+ }, 400);
444
+ acknowledgeHomeAttention(kind, runId);
445
+ return c.json({
446
+ ok: true,
447
+ status: "acknowledged"
448
+ });
449
+ });
450
+ authenticated.post("/api/home/attention/retry", deps.strictRateLimitMiddleware, async (c) => {
451
+ const body = await c.req.json().catch(() => ({}));
452
+ const kind = body.kind === "automation_run" || body.kind === "workflow_run" ? body.kind : void 0;
453
+ const runId = typeof body.runId === "string" ? body.runId.trim() : "";
454
+ if (!kind || !runId) return c.json({
455
+ ok: false,
456
+ error: "kind and runId are required"
457
+ }, 400);
458
+ if (kind === "automation_run") try {
459
+ const run = await service.automationServiceInstance.rerunFromRun(runId);
460
+ acknowledgeHomeAttention(kind, runId);
461
+ return c.json({
462
+ ok: true,
463
+ runId: run.id
464
+ }, 202);
465
+ } catch (error) {
466
+ return c.json({
467
+ ok: false,
468
+ error: error instanceof Error ? error.message : "Failed to retry automation"
469
+ }, 400);
470
+ }
471
+ const agentId = (await listGatewayAgents(service.currentConfig)).defaultId;
472
+ const result = await service.createWorkflowRunService().retryWorkflowRun({
473
+ agentId,
474
+ runId
475
+ });
476
+ if (result.ok === false) return c.json({
477
+ ok: false,
478
+ error: result.message,
479
+ code: result.code
480
+ }, result.httpStatus);
481
+ acknowledgeHomeAttention(kind, runId);
482
+ return c.json({
483
+ ok: true,
484
+ runId: result.runId,
485
+ sessionKey: result.sessionKey
486
+ }, 202);
487
+ });
417
488
  }
418
489
  //#endregion
419
490
  export { buildHomeBriefing, registerHomeRoutes };
@@ -4,6 +4,7 @@ import { registerSessionsRoutes } from "./sessions.js";
4
4
  import { registerStatusRoutes } from "./status.js";
5
5
  import { registerMemoryRoutes } from "./memory.js";
6
6
  import { registerProjectsRoutes } from "./projects.js";
7
+ import { registerProjectSkillRoutes } from "./project-skills.js";
7
8
  import { registerSearchRoutes } from "./search.js";
8
9
  import { registerMobileRoutes } from "./mobile.js";
9
10
  import { registerTaskOutcomeRoutes } from "./task-outcomes.js";
@@ -11,6 +12,7 @@ import { registerInteractionStateRoutes } from "./interaction-state.js";
11
12
  import { registerComposerHistoryRoutes } from "./composer-history.js";
12
13
  import { registerLocalAppsRoutes } from "./local-apps.js";
13
14
  import { registerWorkDiscoveryRoutes } from "./work-discovery.js";
15
+ import { registerFocusRoutes } from "./focuses.js";
14
16
  import { mountAppLazyRoutePrefixes, registerAuthenticatedLazyRouteFallback } from "./lazy-fallback.js";
15
17
  //#region src/gateway/hono/routes/index.ts
16
18
  function registerCoreAuthenticatedRoutes(authenticated, deps) {
@@ -20,8 +22,10 @@ function registerCoreAuthenticatedRoutes(authenticated, deps) {
20
22
  registerMemoryRoutes(authenticated, deps);
21
23
  registerActivityRoutes(authenticated, deps);
22
24
  registerProjectsRoutes(authenticated, deps);
25
+ registerProjectSkillRoutes(authenticated, deps);
23
26
  registerLocalAppsRoutes(authenticated, deps);
24
27
  registerWorkDiscoveryRoutes(authenticated, deps);
28
+ registerFocusRoutes(authenticated, deps);
25
29
  registerSearchRoutes(authenticated, deps);
26
30
  registerMobileRoutes(authenticated, deps);
27
31
  registerTaskOutcomeRoutes(authenticated, deps);
@@ -1,6 +1,6 @@
1
1
  import { readLocalAppAcceptanceConfig } from "../../../local-apps/acceptance.js";
2
- import { LOCAL_APP_RUNTIME_BRIDGE_HASH, injectLocalAppRuntimeBridge } from "../../../local-apps/preview-runtime-bridge.js";
3
2
  import { extensionAssetMimeType } from "../lib/extension-assets.js";
3
+ import { LOCAL_APP_RUNTIME_BRIDGE_HASH, injectLocalAppRuntimeBridge } from "../../../local-apps/preview-runtime-bridge.js";
4
4
  import { relative, resolve } from "node:path";
5
5
  import { existsSync, readFileSync, statSync } from "node:fs";
6
6
  //#region src/gateway/hono/routes/local-apps.ts
@@ -0,0 +1,3 @@
1
+ import type { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerProjectSkillRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;
@@ -0,0 +1,119 @@
1
+ import { ProjectSkillError, ProjectSkillService } from "../../../projects/project-skill-service.js";
2
+ import "../../../projects/index.js";
3
+ //#region src/gateway/hono/routes/project-skills.ts
4
+ function projectSkills(deps) {
5
+ return new ProjectSkillService({
6
+ projects: deps.service.projects,
7
+ getConfig: () => deps.service.currentConfig,
8
+ refreshSkills: () => deps.service.agentService.refreshSkillsAfterDiskChange()
9
+ });
10
+ }
11
+ function errorResponse(c, error) {
12
+ if (error instanceof ProjectSkillError) return c.json({
13
+ ok: false,
14
+ code: error.code,
15
+ error: error.message
16
+ }, error.status);
17
+ return c.json({
18
+ ok: false,
19
+ code: "project_skill_operation_failed",
20
+ error: error instanceof Error ? error.message : String(error)
21
+ }, 400);
22
+ }
23
+ function registerProjectSkillRoutes(authenticated, deps) {
24
+ authenticated.get("/api/projects/:projectId/skills", (c) => {
25
+ try {
26
+ return c.json({
27
+ ok: true,
28
+ ...projectSkills(deps).list(c.req.param("projectId"))
29
+ });
30
+ } catch (error) {
31
+ return errorResponse(c, error);
32
+ }
33
+ });
34
+ authenticated.get("/api/projects/:projectId/skills/:skillId", (c) => {
35
+ try {
36
+ return c.json({
37
+ ok: true,
38
+ skill: projectSkills(deps).getContent(c.req.param("projectId"), c.req.param("skillId"))
39
+ });
40
+ } catch (error) {
41
+ return errorResponse(c, error);
42
+ }
43
+ });
44
+ authenticated.post("/api/projects/:projectId/skills/upload", async (c) => {
45
+ try {
46
+ const body = await c.req.parseBody();
47
+ const file = body.file;
48
+ if (!(file instanceof File)) return c.json({
49
+ ok: false,
50
+ error: "Skill zip file is required"
51
+ }, 400);
52
+ const skill = await projectSkills(deps).installZip(c.req.param("projectId"), Buffer.from(await file.arrayBuffer()), {
53
+ skillId: typeof body.skillId === "string" ? body.skillId : void 0,
54
+ overwrite: body.overwrite === "true"
55
+ });
56
+ return c.json({
57
+ ok: true,
58
+ skill
59
+ }, 201);
60
+ } catch (error) {
61
+ return errorResponse(c, error);
62
+ }
63
+ });
64
+ authenticated.post("/api/projects/:projectId/skills/marketplace/install", async (c) => {
65
+ try {
66
+ const body = await c.req.json();
67
+ const name = typeof body.name === "string" ? body.name.trim() : "";
68
+ if (!name) return c.json({
69
+ ok: false,
70
+ error: "Marketplace skill name is required"
71
+ }, 400);
72
+ const skill = await projectSkills(deps).installMarketplace(c.req.param("projectId"), {
73
+ name,
74
+ version: typeof body.version === "string" ? body.version : void 0,
75
+ provider: typeof body.provider === "string" ? body.provider : void 0,
76
+ overwrite: body.overwrite === true
77
+ });
78
+ return c.json({
79
+ ok: true,
80
+ skill
81
+ }, 201);
82
+ } catch (error) {
83
+ return errorResponse(c, error);
84
+ }
85
+ });
86
+ authenticated.post("/api/projects/:projectId/skills/source/install", async (c) => {
87
+ try {
88
+ const body = await c.req.json();
89
+ const source = typeof body.source === "string" ? body.source.trim() : "";
90
+ if (!source) return c.json({
91
+ ok: false,
92
+ error: "Skill source is required"
93
+ }, 400);
94
+ const skill = await projectSkills(deps).installSource(c.req.param("projectId"), {
95
+ source,
96
+ skillId: typeof body.skillId === "string" ? body.skillId : void 0,
97
+ ref: typeof body.ref === "string" ? body.ref : void 0,
98
+ subpath: typeof body.subpath === "string" ? body.subpath : void 0,
99
+ force: body.force === true
100
+ });
101
+ return c.json({
102
+ ok: true,
103
+ skill
104
+ }, 201);
105
+ } catch (error) {
106
+ return errorResponse(c, error);
107
+ }
108
+ });
109
+ authenticated.delete("/api/projects/:projectId/skills/:skillId", async (c) => {
110
+ try {
111
+ await projectSkills(deps).remove(c.req.param("projectId"), c.req.param("skillId"));
112
+ return c.json({ ok: true });
113
+ } catch (error) {
114
+ return errorResponse(c, error);
115
+ }
116
+ });
117
+ }
118
+ //#endregion
119
+ export { registerProjectSkillRoutes };
@@ -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();