@xopcai/xopc 0.0.197 → 0.0.200

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 (244) 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-BwmdJ5pv.js → activity-store-DYVN1hRp.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C5st7lt5.js → agent-avatar-dicebear-eMarz29u.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-DeLW-454.js +68 -0
  6. package/dist/gateway/static/root/assets/{api-BM1hNzjw.js → api-B8mzbAle.js} +1 -1
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-yfb68wq9.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-B8SPknFM.js +1 -0
  9. package/dist/gateway/static/root/assets/apps-page-Bmor22Ny.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-qL07mwnY.js → archive-plugin-DmYRiOP3.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CqSobpdi.js → attachment-load-D66JvcPi.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-page-Q4e8m11h.js +6 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-DBRPyLYE.js → binary-plugins-ChIsZArT.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-6wG1LU7t.js → block-editor-Ck-k_d0Z.js} +4 -4
  15. package/dist/gateway/static/root/assets/browser-settings-page--uVL73Sb.js +8 -0
  16. package/dist/gateway/static/root/assets/browser-workflow-inputs-_ndaecsf.js +1 -0
  17. package/dist/gateway/static/root/assets/{browser-workflows-page-BEu3E0et.js → browser-workflows-page-BC5jm1zL.js} +2 -2
  18. package/dist/gateway/static/root/assets/button-CSEbl4zT.js +1 -0
  19. package/dist/gateway/static/root/assets/capabilities-settings-panel-DXpf3QYN.js +7 -0
  20. package/dist/gateway/static/root/assets/{capability-presets-api-BoOzFotX.js → capability-presets-api-Dy1jZJKs.js} +1 -1
  21. package/dist/gateway/static/root/assets/capability-presets-settings-panel-NAjCsrTi.js +3 -0
  22. package/dist/gateway/static/root/assets/{channel-recipient-api-_8IiTxRB.js → channel-recipient-api-D-9qiuio.js} +1 -1
  23. package/dist/gateway/static/root/assets/channels-settings-CiWUo7jW.js +1 -0
  24. package/dist/gateway/static/root/assets/channels-status-swr-B4Rbh3bM.js +1 -0
  25. package/dist/gateway/static/root/assets/connectors-api-5xiCRVUS.js +1 -0
  26. package/dist/gateway/static/root/assets/connectors-page-DOwlMseU.js +2 -0
  27. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +1 -0
  28. package/dist/gateway/static/root/assets/cron-expression-B3PebXKZ.js +2 -0
  29. package/dist/gateway/static/root/assets/date-picker-C1Vke7Xn.js +1 -0
  30. package/dist/gateway/static/root/assets/dependency-picker-FrQ0tsBC.js +1 -0
  31. package/dist/gateway/static/root/assets/{desktop-pet-CsLR4pWB.js → desktop-pet-CPBAzNJi.js} +1 -1
  32. package/dist/gateway/static/root/assets/desktop-pet-settings-D6s3glDP.js +1 -0
  33. package/dist/gateway/static/root/assets/directory-picker-path-field-CbNQ7QQS.js +1 -0
  34. package/dist/gateway/static/root/assets/dist-BPoKqzeH.js +1 -0
  35. package/dist/gateway/static/root/assets/dist-DY4Af0fY.js +1 -0
  36. package/dist/gateway/static/root/assets/{extension-debug-page-CD73euAM.js → extension-debug-page-dTK14hUv.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-page-DAKjpNwd.js → extension-page-Cpdj1Kip.js} +1 -1
  38. package/dist/gateway/static/root/assets/extension-settings-page-iNHUZGd5.js +1 -0
  39. package/dist/gateway/static/root/assets/external-link-DjqjBmc3.js +1 -0
  40. package/dist/gateway/static/root/assets/form-field-width-DJw_jULe.js +1 -0
  41. package/dist/gateway/static/root/assets/gateway-config-api-SvMvWqMM.js +1 -0
  42. package/dist/gateway/static/root/assets/gateway-config-swr-jB0hAhWO.js +1 -0
  43. package/dist/gateway/static/root/assets/gateway-settings-BilR3dGZ.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-startup-retry--2njcDpC.js → gateway-startup-retry-C-fRlHCL.js} +1 -1
  45. package/dist/gateway/static/root/assets/globe-DSSGFWFn.js +1 -0
  46. package/dist/gateway/static/root/assets/heartbeat-settings-zK40dcQ5.js +1 -0
  47. package/dist/gateway/static/root/assets/home-page-NyXy5MLr.js +3 -0
  48. package/dist/gateway/static/root/assets/index-Bp8I_eX4.css +1 -0
  49. package/dist/gateway/static/root/assets/index-CCK8zdlS.js +152 -0
  50. package/dist/gateway/static/root/assets/interaction-BmQogeqz.js +1 -0
  51. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-HMhxgOuD.js → keyboard-shortcuts-settings-nKzsroud.js} +1 -1
  52. package/dist/gateway/static/root/assets/loader-circle-CifKLtgG.js +1 -0
  53. package/dist/gateway/static/root/assets/local-app-workbench-page-Ds3sPXTh.js +2 -0
  54. package/dist/gateway/static/root/assets/local-apps-page-DV1s_FYh.js +1 -0
  55. package/dist/gateway/static/root/assets/{locale-store-Bjvw7jtg.js → locale-store-xULEcFVs.js} +1 -1
  56. package/dist/gateway/static/root/assets/logs-page-Biz4eA02.js +2 -0
  57. package/dist/gateway/static/root/assets/management-settings-D7KjYgHu.js +1 -0
  58. package/dist/gateway/static/root/assets/{markdown-split-DvVBewS4.js → markdown-split-CTYbpkrd.js} +1 -1
  59. package/dist/gateway/static/root/assets/{media-plugins-YVj7NVzD.js → media-plugins-BXYnaiZ6.js} +1 -1
  60. package/dist/gateway/static/root/assets/messages-3qRsLZuX.js +3 -0
  61. package/dist/gateway/static/root/assets/{notes-page-BDzuL2I9.js → notes-page-CWWVXpw5.js} +1 -1
  62. package/dist/gateway/static/root/assets/notes-workbench-DnBkQihH.js +4 -0
  63. package/dist/gateway/static/root/assets/page-tabs-BaEQMYm_.js +1 -0
  64. package/dist/gateway/static/root/assets/popover-select-BzdnTy3h.js +1 -0
  65. package/dist/gateway/static/root/assets/preview-open-alternatives-pimQAkeI.js +1 -0
  66. package/dist/gateway/static/root/assets/{product-open-page-Bwx_CQht.js → product-open-page-BoYSS_YR.js} +1 -1
  67. package/dist/gateway/static/root/assets/project-detail-page-ZO7t1UkB.js +1 -0
  68. package/dist/gateway/static/root/assets/projects-page-By-vq41g.js +1 -0
  69. package/dist/gateway/static/root/assets/remote-access-hub-C0C_Y9d0.js +1 -0
  70. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Fe05Nus6.js → runtime-tools-settings-panel-DT8flaX1.js} +4 -4
  71. package/dist/gateway/static/root/assets/schema-form-DabEP-UI.js +1 -0
  72. package/dist/gateway/static/root/assets/sessions-page-BNlVwUzV.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-advanced-gate-CxYBQDaM.js +1 -0
  74. package/dist/gateway/static/root/assets/settings-form-draft-Dy10ldo8.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-form-section-DCsfZAtC.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-loading-skeleton-BRE_-7Da.js → settings-loading-skeleton-Dac6Yd0T.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-C1zxCpqB.js → settings-page-BDoYoEar.js} +1 -1
  78. package/dist/gateway/static/root/assets/settings-page-layout-BRQNel6r.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-shell-dialog-layer-BU3UuiJr.js +1 -0
  80. package/dist/gateway/static/root/assets/setup-status-panel-DWijJ1rw.js +1 -0
  81. package/dist/gateway/static/root/assets/share-preview-page-ie9I2_7h.js +2 -0
  82. package/dist/gateway/static/root/assets/shares-settings-DU9VrJLf.js +1 -0
  83. package/dist/gateway/static/root/assets/skill-reload-api-C5RaIvoE.js +1 -0
  84. package/dist/gateway/static/root/assets/skills-page-N0YhaR5S.js +2 -0
  85. package/dist/gateway/static/root/assets/{skills-page.utils-CYwFWTso.js → skills-page.utils-C639DLXr.js} +1 -1
  86. package/dist/gateway/static/root/assets/system-settings-panel-CpshpQtC.js +1 -0
  87. package/dist/gateway/static/root/assets/task-detail-page-DsTocYkK.js +1 -0
  88. package/dist/gateway/static/root/assets/{theme-store-DtxpMC5S.js → theme-store-CHQRiuCF.js} +1 -1
  89. package/dist/gateway/static/root/assets/tool-activity-R8V9l6nk.js +1 -0
  90. package/dist/gateway/static/root/assets/typed-models-lib-q5-Vfqd8.js +1 -0
  91. package/dist/gateway/static/root/assets/use-autosave-ms6rDy59.js +1 -0
  92. package/dist/gateway/static/root/assets/user-context-page-BUxIemwy.js +1 -0
  93. package/dist/gateway/static/root/assets/voice-api-key-field-CObrQWh2.js +1 -0
  94. package/dist/gateway/static/root/assets/work-discovery-overlay-BBxrnEFt.js +1 -0
  95. package/dist/gateway/static/root/assets/work-discovery-page-DN3l-HW3.js +1 -0
  96. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DqIb1oBB.js → workflow-run-setup-panel-BxXhe3IV.js} +2 -2
  97. package/dist/gateway/static/root/assets/workflows-page-BCHkjd1i.js +5 -0
  98. package/dist/gateway/static/root/assets/working-directory-picker-modal-D-IgcHPp.js +1 -0
  99. package/dist/gateway/static/root/index.html +23 -8
  100. package/dist/package.js +1 -1
  101. package/dist/packages/gateway-contract/src/tasks.js +103 -9
  102. package/dist/src/agent/agent-manager.d.ts +1 -0
  103. package/dist/src/agent/agent-manager.js +1 -0
  104. package/dist/src/agent/context/execution-scope.js +3 -1
  105. package/dist/src/agent/service.js +1 -0
  106. package/dist/src/agent/service.types.d.ts +1 -0
  107. package/dist/src/agent/tasks/task-judge-service.d.ts +1 -1
  108. package/dist/src/agent/tasks/task-judge-service.js +3 -2
  109. package/dist/src/agent/tools/factory.d.ts +2 -0
  110. package/dist/src/agent/tools/factory.js +2 -1
  111. package/dist/src/agent/tools/xopc-use-tool.d.ts +1 -0
  112. package/dist/src/agent/tools/xopc-use-tool.js +69 -9
  113. package/dist/src/automations/domain/validation.d.ts +40 -12
  114. package/dist/src/automations/draft/automation-draft-validator.d.ts +4 -4
  115. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  116. package/dist/src/config/rules.js +2 -2
  117. package/dist/src/gateway/hono/app.d.ts +2 -0
  118. package/dist/src/gateway/hono/app.js +10 -3
  119. package/dist/src/gateway/hono/middleware/strict-rate-limit.d.ts +4 -0
  120. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +8 -1
  121. package/dist/src/gateway/hono/routes/agent-stream.js +2 -74
  122. package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -1
  123. package/dist/src/gateway/hono/routes/config.js +9 -0
  124. package/dist/src/gateway/hono/routes/deps.d.ts +1 -0
  125. package/dist/src/gateway/hono/routes/projects.js +55 -0
  126. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +62 -0
  127. package/dist/src/gateway/hono/routes/session-input-handler.js +82 -0
  128. package/dist/src/gateway/hono/routes/tasks.js +272 -20
  129. package/dist/src/gateway/host.d.ts +9 -1
  130. package/dist/src/gateway/host.js +22 -5
  131. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  132. package/dist/src/gateway/rate-limit/buckets.js +12 -0
  133. package/dist/src/gateway/runtime-config.js +6 -5
  134. package/dist/src/gateway/security/audit.js +0 -7
  135. package/dist/src/gateway/server.js +4 -1
  136. package/dist/src/gateway/service/task-conversation-query-service.d.ts +58 -0
  137. package/dist/src/gateway/service/task-conversation-query-service.js +84 -0
  138. package/dist/src/gateway/service.d.ts +11 -0
  139. package/dist/src/gateway/service.js +75 -38
  140. package/dist/src/proactive/actions/service.d.ts +2 -0
  141. package/dist/src/proactive/actions/service.js +80 -0
  142. package/dist/src/proactive/execution/insight.js +20 -0
  143. package/dist/src/proactive/execution/repository.js +8 -2
  144. package/dist/src/proactive/execution/types.d.ts +14 -0
  145. package/dist/src/proactive/inbox/repository.js +59 -9
  146. package/dist/src/proactive/inbox/service.d.ts +2 -2
  147. package/dist/src/proactive/inbox/service.js +7 -2
  148. package/dist/src/proactive/inbox/types.d.ts +14 -0
  149. package/dist/src/proactive/inbox/worker.js +2 -0
  150. package/dist/src/proactive/scenarios/prompt-composer.js +2 -2
  151. package/dist/src/projects/project-agent.js +1 -1
  152. package/dist/src/storage/sqlite/migrations/118_task_board_rank.sql +6 -0
  153. package/dist/src/storage/sqlite/migrations/119_proactive_disposition.sql +13 -0
  154. package/dist/src/storage/sqlite/migrations/120_task_conversation.sql +112 -0
  155. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  156. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  157. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  158. package/dist/src/storage/sqlite/schema.js +1 -1
  159. package/dist/src/tasks/execution-context.js +8 -4
  160. package/dist/src/tasks/home-query-service.d.ts +5 -0
  161. package/dist/src/tasks/home-query-service.js +7 -2
  162. package/dist/src/tasks/index.d.ts +3 -0
  163. package/dist/src/tasks/index.js +6 -3
  164. package/dist/src/tasks/project-monitoring-service.d.ts +9 -0
  165. package/dist/src/tasks/project-monitoring-service.js +41 -3
  166. package/dist/src/tasks/project-operating-view-service.d.ts +1 -2
  167. package/dist/src/tasks/project-operating-view-service.js +26 -23
  168. package/dist/src/tasks/task-application-service.js +107 -21
  169. package/dist/src/tasks/task-change-events.d.ts +13 -0
  170. package/dist/src/tasks/task-change-events.js +29 -0
  171. package/dist/src/tasks/task-context-assembler.js +9 -4
  172. package/dist/src/tasks/task-context-repository.d.ts +0 -6
  173. package/dist/src/tasks/task-context-repository.js +0 -4
  174. package/dist/src/tasks/task-conversation-repository.d.ts +71 -0
  175. package/dist/src/tasks/task-conversation-repository.js +194 -0
  176. package/dist/src/tasks/task-handoff-service.d.ts +31 -0
  177. package/dist/src/tasks/task-handoff-service.js +143 -0
  178. package/dist/src/tasks/task-read-model-projector.js +3 -6
  179. package/dist/src/tasks/task-repository.d.ts +7 -2
  180. package/dist/src/tasks/task-repository.js +31 -15
  181. package/dist/src/tasks/task-run-coordinator.js +3 -1
  182. package/dist/src/tunnel/enable-lan-pairing.js +15 -26
  183. package/dist/src/tunnel/pair-context.js +1 -1
  184. package/dist/src/tunnel/pair-url.js +1 -1
  185. package/dist/src/tunnel/tunnel-qr.d.ts +0 -7
  186. package/dist/src/tunnel/tunnel-qr.js +2 -19
  187. package/dist/src/workflows/service/workflow-run-service.js +4 -2
  188. package/package.json +5 -3
  189. package/dist/gateway/static/root/assets/agents-Baxfj44y.js +0 -68
  190. package/dist/gateway/static/root/assets/app-management-settings-panel-S8LhoD6G.js +0 -1
  191. package/dist/gateway/static/root/assets/appearance-settings-D8Cd5vDP.js +0 -1
  192. package/dist/gateway/static/root/assets/apps-page-0uCxKyE5.js +0 -1
  193. package/dist/gateway/static/root/assets/automations-page-XyDat125.js +0 -6
  194. package/dist/gateway/static/root/assets/browser-settings-page-CrYNMR4w.js +0 -8
  195. package/dist/gateway/static/root/assets/browser-workflow-inputs-Abil4puY.js +0 -1
  196. package/dist/gateway/static/root/assets/capabilities-settings-panel-CvMcDhGf.js +0 -7
  197. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CHJDY-Ih.js +0 -3
  198. package/dist/gateway/static/root/assets/channels-settings-Ds9BJbcY.js +0 -1
  199. package/dist/gateway/static/root/assets/channels-status-swr-DPaJSYX_.js +0 -1
  200. package/dist/gateway/static/root/assets/connectors-api-CgWjgPSI.js +0 -1
  201. package/dist/gateway/static/root/assets/connectors-page-NUs-Zf7F.js +0 -2
  202. package/dist/gateway/static/root/assets/cron-expression-ZdDBAoqA.js +0 -2
  203. package/dist/gateway/static/root/assets/dependency-picker-BGeB1jpn.js +0 -1
  204. package/dist/gateway/static/root/assets/desktop-pet-settings-CCjT1bdo.js +0 -1
  205. package/dist/gateway/static/root/assets/directory-picker-path-field-C-Te1QN3.js +0 -1
  206. package/dist/gateway/static/root/assets/extension-settings-page-BLSNdlgd.js +0 -1
  207. package/dist/gateway/static/root/assets/gateway-config-api-CQrf0k3D.js +0 -1
  208. package/dist/gateway/static/root/assets/gateway-settings-CvgH8IJI.js +0 -1
  209. package/dist/gateway/static/root/assets/heartbeat-settings-SPpnqbjl.js +0 -1
  210. package/dist/gateway/static/root/assets/home-page-BFoD6047.js +0 -3
  211. package/dist/gateway/static/root/assets/index-84ys9u-K.js +0 -152
  212. package/dist/gateway/static/root/assets/index-D-srnucP.css +0 -1
  213. package/dist/gateway/static/root/assets/local-app-workbench-page-D5uL2_Fd.js +0 -2
  214. package/dist/gateway/static/root/assets/local-apps-page-DIWkFa3g.js +0 -1
  215. package/dist/gateway/static/root/assets/logs-page--6v8qq6y.js +0 -2
  216. package/dist/gateway/static/root/assets/management-settings-DtEuS-kR.js +0 -1
  217. package/dist/gateway/static/root/assets/messages-DQ5X6cXp.js +0 -3
  218. package/dist/gateway/static/root/assets/notes-workbench-IdjuNXvH.js +0 -4
  219. package/dist/gateway/static/root/assets/page-tabs-7bSEWfSX.js +0 -1
  220. package/dist/gateway/static/root/assets/preview-open-alternatives-tgLbHgcV.js +0 -1
  221. package/dist/gateway/static/root/assets/project-detail-page-DnJXSuM4.js +0 -1
  222. package/dist/gateway/static/root/assets/projects-page-DckZKlBI.js +0 -1
  223. package/dist/gateway/static/root/assets/remote-access-hub-CfbUHBUH.js +0 -1
  224. package/dist/gateway/static/root/assets/schema-form-CFfyC4CB.js +0 -1
  225. package/dist/gateway/static/root/assets/sessions-page-BCfCh4My.js +0 -1
  226. package/dist/gateway/static/root/assets/settings-advanced-gate-Cbi4FvzO.js +0 -1
  227. package/dist/gateway/static/root/assets/settings-form-section-gEnEYT_3.js +0 -1
  228. package/dist/gateway/static/root/assets/settings-page-layout-CRpXF_05.js +0 -1
  229. package/dist/gateway/static/root/assets/setup-status-panel-BcHdpmFf.js +0 -1
  230. package/dist/gateway/static/root/assets/share-preview-page-DU8L68A5.js +0 -2
  231. package/dist/gateway/static/root/assets/shares-settings-kjTqH9yY.js +0 -1
  232. package/dist/gateway/static/root/assets/skill-reload-api-QAGpwzIM.js +0 -1
  233. package/dist/gateway/static/root/assets/skills-page-lE1-YRdK.js +0 -2
  234. package/dist/gateway/static/root/assets/system-settings-panel-CVDsiPKn.js +0 -1
  235. package/dist/gateway/static/root/assets/task-detail-page-DsM13-cy.js +0 -1
  236. package/dist/gateway/static/root/assets/typed-models-lib-DelyYgoc.js +0 -1
  237. package/dist/gateway/static/root/assets/use-autosave-C50Mq5yQ.js +0 -1
  238. package/dist/gateway/static/root/assets/user-context-page-D-VEOt2A.js +0 -1
  239. package/dist/gateway/static/root/assets/voice-api-key-field-DYfgTe3Y.js +0 -1
  240. package/dist/gateway/static/root/assets/work-discovery-overlay-DPbujsp3.js +0 -1
  241. package/dist/gateway/static/root/assets/work-discovery-page-D77opady.js +0 -1
  242. package/dist/gateway/static/root/assets/workflows-page-B9-PLmlX.js +0 -5
  243. package/dist/src/gateway/ensure-network-cors.d.ts +0 -3
  244. package/dist/src/gateway/ensure-network-cors.js +0 -23
@@ -0,0 +1,143 @@
1
+ import { createLogger } from "../utils/logger/index.js";
2
+ import { init_logger } from "../utils/logger.js";
3
+ import { init_agent_scope, listAgentEntries, normalizeAgentId } from "../agent/agent-scope.js";
4
+ import { buildSessionKey, init_session_key, sanitizeSegment } from "../routing/session-key.js";
5
+ import { TaskRepository } from "./task-repository.js";
6
+ import { TaskConversationRepository } from "./task-conversation-repository.js";
7
+ import { TaskRunRepository } from "./task-run-repository.js";
8
+ import { TaskContextRepository } from "./task-context-repository.js";
9
+ //#region src/tasks/task-handoff-service.ts
10
+ init_agent_scope();
11
+ init_session_key();
12
+ init_logger();
13
+ const log = createLogger("TaskHandoff");
14
+ var TaskHandoffService = class {
15
+ #inflight = /* @__PURE__ */ new Map();
16
+ constructor(deps) {
17
+ this.deps = deps;
18
+ }
19
+ handoff(input) {
20
+ const previous = this.#inflight.get(input.taskId);
21
+ const pending = (previous ? previous.catch(() => void 0) : Promise.resolve()).then(() => this.performHandoff(input));
22
+ this.#inflight.set(input.taskId, pending);
23
+ pending.finally(() => {
24
+ if (this.#inflight.get(input.taskId) === pending) this.#inflight.delete(input.taskId);
25
+ });
26
+ return pending;
27
+ }
28
+ async performHandoff(input) {
29
+ const config = this.deps.getConfig();
30
+ const toAgentId = normalizeAgentId(input.toAgentId);
31
+ if (!listAgentEntries(config).find((entry) => entry.enabled !== false && normalizeAgentId(entry.id) === toAgentId)) throw new Error(`Agent not found: ${toAgentId}`);
32
+ const tasks = new TaskRepository();
33
+ const task = tasks.require(input.taskId);
34
+ const conversations = new TaskConversationRepository();
35
+ const duplicate = conversations.findHandoffByIdempotencyKey({
36
+ taskId: task.id,
37
+ expectedTaskVersion: input.expectedVersion,
38
+ toAgentId,
39
+ idempotencyKey: input.idempotencyKey
40
+ });
41
+ if (duplicate) {
42
+ await this.abortPreviousSession(duplicate.fromSessionKey);
43
+ return {
44
+ task,
45
+ conversation: conversations.requireState(task.id),
46
+ snapshot: duplicate,
47
+ ...duplicate.fromAgentId ? { fromAgentId: duplicate.fromAgentId } : {},
48
+ toAgentId,
49
+ activeSessionKey: duplicate.toSessionKey,
50
+ assignmentEpoch: duplicate.assignmentEpoch
51
+ };
52
+ }
53
+ if (task.version !== input.expectedVersion) throw new Error("Task changed");
54
+ const previousState = conversations.requireState(task.id);
55
+ if (previousState.currentExecutorAgentId === toAgentId) throw new Error("Executor is already active");
56
+ const assignmentEpoch = previousState.assignmentEpoch + 1;
57
+ const peerId = sanitizeSegment(`task-${task.id}-assignment-${assignmentEpoch}`);
58
+ const sessionKey = buildSessionKey({
59
+ agentId: toAgentId,
60
+ source: "webchat",
61
+ accountId: "default",
62
+ peerKind: "direct",
63
+ peerId
64
+ });
65
+ const runs = new TaskRunRepository();
66
+ const latestRun = runs.getLatestRoot(task.id);
67
+ const latestReceipt = latestRun ? runs.getReceipt(latestRun.id) : void 0;
68
+ const remainingCriteria = latestReceipt?.verification.checks.length ? latestReceipt.verification.checks.filter((check) => check.status !== "passed").map((check) => check.criterion) : task.contract?.acceptanceCriteria ?? [];
69
+ const payload = {
70
+ objective: task.contract?.objective ?? task.title,
71
+ expectedOutputs: task.contract?.expectedOutputs ?? [],
72
+ remainingCriteria,
73
+ constraints: task.contract?.constraints ?? [],
74
+ risks: task.contract?.risks ?? [],
75
+ approvalRequired: task.contract?.approvalRequired ?? [],
76
+ context: new TaskContextRepository().list(task.id),
77
+ ...latestReceipt ? {
78
+ latestReceipt,
79
+ completedWork: latestReceipt.changes,
80
+ remainingWork: latestReceipt.remainingWork
81
+ } : {}
82
+ };
83
+ await this.deps.sessionIndex.saveMessages(sessionKey, [], { metadata: {
84
+ sourceChannel: "webchat",
85
+ sourceChatId: `default:direct:${peerId}`,
86
+ sessionType: "chat",
87
+ routing: {
88
+ agentId: toAgentId,
89
+ source: "webchat",
90
+ accountId: "default",
91
+ peerKind: "direct",
92
+ peerId
93
+ },
94
+ projectId: task.projectId,
95
+ customData: {
96
+ origin: "task",
97
+ triggerKind: "user",
98
+ assignmentEpoch
99
+ }
100
+ } });
101
+ let completed;
102
+ try {
103
+ completed = conversations.completeHandoff({
104
+ taskId: task.id,
105
+ expectedTaskVersion: input.expectedVersion,
106
+ toSessionKey: sessionKey,
107
+ toAgentId,
108
+ idempotencyKey: input.idempotencyKey,
109
+ payload
110
+ });
111
+ } catch (error) {
112
+ await this.deps.sessionIndex.delete(sessionKey);
113
+ throw error;
114
+ }
115
+ const oldSessionKey = completed.snapshot.fromSessionKey;
116
+ await this.abortPreviousSession(oldSessionKey);
117
+ return {
118
+ task: tasks.require(task.id),
119
+ conversation: completed.state,
120
+ snapshot: completed.snapshot,
121
+ ...completed.snapshot.fromAgentId ? { fromAgentId: completed.snapshot.fromAgentId } : {},
122
+ toAgentId,
123
+ activeSessionKey: sessionKey,
124
+ assignmentEpoch: completed.state.assignmentEpoch
125
+ };
126
+ }
127
+ async abortPreviousSession(sessionKey) {
128
+ if (!sessionKey) return;
129
+ const activeRunId = this.deps.getActiveRunId(sessionKey);
130
+ if (!activeRunId) return;
131
+ try {
132
+ await this.deps.abortRun(activeRunId);
133
+ } catch (error) {
134
+ log.warn({
135
+ err: error,
136
+ sessionKey,
137
+ runId: activeRunId
138
+ }, "Previous task executor did not stop cleanly");
139
+ }
140
+ }
141
+ };
142
+ //#endregion
143
+ export { TaskHandoffService };
@@ -76,16 +76,13 @@ var TaskReadModelProjector = class {
76
76
  }
77
77
  allowedCommands(task, activeRunStatus, hasWaits) {
78
78
  if (task.phase === "closed") return ["reopen"];
79
- const commands = [
80
- "revise_contract",
81
- "delegate",
82
- "close"
83
- ];
79
+ const commands = ["revise_contract", "close"];
80
+ if (!activeRunStatus && !hasWaits) commands.unshift("move");
84
81
  if (hasWaits) commands.unshift("resolve_wait");
85
82
  else if (activeRunStatus === "running" || activeRunStatus === "verifying") commands.unshift("add_wait");
86
83
  if (task.phase === "backlog") commands.unshift("mark_ready");
87
84
  if (!activeRunStatus && !hasWaits && task.phase !== "backlog") commands.unshift("start");
88
- if (task.phase === "active") commands.push("request_review");
85
+ if (task.phase === "active" && !activeRunStatus) commands.push("request_review");
89
86
  return commands;
90
87
  }
91
88
  };
@@ -34,11 +34,11 @@ export declare class TaskRepository {
34
34
  get(id: string): TaskAggregate | undefined;
35
35
  require(id: string): TaskAggregate;
36
36
  getByIdempotencyKey(key: string): TaskAggregate | undefined;
37
- getBySession(sessionKey: string): TaskAggregate | undefined;
38
37
  list(input?: {
39
38
  phase?: TaskPhase;
40
39
  projectId?: string;
41
40
  limit?: number;
41
+ order?: 'recent' | 'board';
42
42
  }): TaskAggregate[];
43
43
  listByProject(projectId: string, limit?: number): TaskAggregate[];
44
44
  getContract(taskId: string, version?: number): TaskContract | undefined;
@@ -52,7 +52,6 @@ export declare class TaskRepository {
52
52
  priority?: TaskPriority;
53
53
  dueAt?: number | null;
54
54
  ownerId?: string | null;
55
- delegateAgentId?: string | null;
56
55
  now?: number;
57
56
  }): TaskAggregate | undefined;
58
57
  setLifecycle(input: {
@@ -62,6 +61,12 @@ export declare class TaskRepository {
62
61
  resolution?: TaskResolution;
63
62
  now?: number;
64
63
  }): TaskAggregate | undefined;
64
+ reorder(input: {
65
+ taskId: string;
66
+ expectedVersion: number;
67
+ beforeTaskId?: string | null;
68
+ now?: number;
69
+ }): TaskAggregate | undefined;
65
70
  reviseContract(input: {
66
71
  taskId: string;
67
72
  objective: string;
@@ -38,6 +38,7 @@ function taskFromRow(row, contract) {
38
38
  source: row.source,
39
39
  ...row.locale ? { locale: row.locale } : {},
40
40
  latestContractVersion: row.latest_contract_version,
41
+ boardRank: row.board_rank,
41
42
  version: row.version,
42
43
  ...contract ? { contract } : {},
43
44
  createdAt: row.created_at,
@@ -54,11 +55,13 @@ var TaskRepository = class {
54
55
  const id = input.id ?? randomUUID();
55
56
  const now = input.now ?? Date.now();
56
57
  runSqliteWriteTransaction((db) => {
58
+ const phase = input.phase ?? "backlog";
59
+ const boardRank = Number(db.prepare("SELECT COALESCE(MAX(board_rank), 0) + 1024 AS board_rank FROM tasks WHERE project_id IS ? AND phase = ?").get(input.projectId ?? null, phase).board_rank);
57
60
  db.prepare(`INSERT INTO tasks (
58
61
  task_id, creation_idempotency_key, project_id, milestone_id, parent_task_id,
59
62
  title, body, phase, priority, due_at, owner_id, delegate_agent_id,
60
- source, locale, latest_contract_version, version, created_at, updated_at
61
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?)`).run(id, input.idempotencyKey ?? null, input.projectId ?? null, input.milestoneId ?? null, input.parentTaskId ?? null, title, input.body?.trim() || null, input.phase ?? "backlog", input.priority ?? "normal", input.dueAt ?? null, input.ownerId ?? null, input.delegateAgentId ?? null, input.source ?? "api", input.locale ?? null, now, now);
63
+ source, locale, latest_contract_version, board_rank, version, created_at, updated_at
64
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, 1, ?, ?)`).run(id, input.idempotencyKey ?? null, input.projectId ?? null, input.milestoneId ?? null, input.parentTaskId ?? null, title, input.body?.trim() || null, phase, input.priority ?? "normal", input.dueAt ?? null, input.ownerId ?? null, input.delegateAgentId ?? null, input.source ?? "api", input.locale ?? null, boardRank, now, now);
62
65
  this.insertContract(db, {
63
66
  taskId: id,
64
67
  version: 1,
@@ -90,13 +93,6 @@ var TaskRepository = class {
90
93
  const row = getSqliteDatabase().prepare("SELECT * FROM tasks WHERE creation_idempotency_key = ?").get(key);
91
94
  return row ? taskFromRow(row, this.getContract(row.task_id, row.latest_contract_version)) : void 0;
92
95
  }
93
- getBySession(sessionKey) {
94
- const row = getSqliteDatabase().prepare(`SELECT tasks.* FROM tasks
95
- JOIN task_sessions ON task_sessions.task_id = tasks.task_id
96
- WHERE task_sessions.session_key = ?
97
- ORDER BY task_sessions.created_at DESC LIMIT 1`).get(sessionKey);
98
- return row ? taskFromRow(row, this.getContract(row.task_id, row.latest_contract_version)) : void 0;
99
- }
100
96
  list(input = {}) {
101
97
  const clauses = [];
102
98
  const params = [];
@@ -111,12 +107,13 @@ var TaskRepository = class {
111
107
  const limit = Math.max(1, Math.min(200, Math.floor(input.limit ?? 50)));
112
108
  params.push(limit);
113
109
  return getSqliteDatabase().prepare(`SELECT * FROM tasks${clauses.length ? ` WHERE ${clauses.join(" AND ")}` : ""}
114
- ORDER BY updated_at DESC LIMIT ?`).all(...params).map((row) => taskFromRow(row, this.getContract(row.task_id, row.latest_contract_version)));
110
+ ORDER BY ${input.order === "board" ? "board_rank ASC, created_at ASC, task_id ASC" : "updated_at DESC"} LIMIT ?`).all(...params).map((row) => taskFromRow(row, this.getContract(row.task_id, row.latest_contract_version)));
115
111
  }
116
112
  listByProject(projectId, limit = 50) {
117
113
  return this.list({
118
114
  projectId,
119
- limit
115
+ limit,
116
+ order: "board"
120
117
  });
121
118
  }
122
119
  getContract(taskId, version) {
@@ -130,18 +127,37 @@ var TaskRepository = class {
130
127
  if (!title) throw new Error("Task title is required");
131
128
  const now = Math.max(patch.now ?? Date.now(), current.updatedAt + 1);
132
129
  return getSqliteDatabase().prepare(`UPDATE tasks SET title = ?, body = ?, project_id = ?, milestone_id = ?,
133
- parent_task_id = ?, priority = ?, due_at = ?, owner_id = ?, delegate_agent_id = ?,
130
+ parent_task_id = ?, priority = ?, due_at = ?, owner_id = ?,
134
131
  version = version + 1, updated_at = ?
135
- WHERE task_id = ? AND version = ?`).run(title, patch.body === void 0 ? current.body ?? null : patch.body?.trim() || null, patch.projectId === void 0 ? current.projectId ?? null : patch.projectId, patch.milestoneId === void 0 ? current.milestoneId ?? null : patch.milestoneId, patch.parentTaskId === void 0 ? current.parentTaskId ?? null : patch.parentTaskId, patch.priority ?? current.priority, patch.dueAt === void 0 ? current.dueAt ?? null : patch.dueAt, patch.ownerId === void 0 ? current.ownerId ?? null : patch.ownerId, patch.delegateAgentId === void 0 ? current.delegateAgentId ?? null : patch.delegateAgentId, now, taskId, patch.expectedVersion).changes === 0 ? void 0 : this.get(taskId);
132
+ WHERE task_id = ? AND version = ?`).run(title, patch.body === void 0 ? current.body ?? null : patch.body?.trim() || null, patch.projectId === void 0 ? current.projectId ?? null : patch.projectId, patch.milestoneId === void 0 ? current.milestoneId ?? null : patch.milestoneId, patch.parentTaskId === void 0 ? current.parentTaskId ?? null : patch.parentTaskId, patch.priority ?? current.priority, patch.dueAt === void 0 ? current.dueAt ?? null : patch.dueAt, patch.ownerId === void 0 ? current.ownerId ?? null : patch.ownerId, now, taskId, patch.expectedVersion).changes === 0 ? void 0 : this.get(taskId);
136
133
  }
137
134
  setLifecycle(input) {
138
135
  if (input.phase === "closed" !== Boolean(input.resolution)) throw new Error("Closed tasks require a resolution and open tasks cannot have one");
139
136
  const current = this.get(input.taskId);
140
137
  if (!current || current.version !== input.expectedVersion) return void 0;
141
138
  const now = Math.max(input.now ?? Date.now(), current.updatedAt + 1);
139
+ const boardRank = current.phase === input.phase ? current.boardRank : Number(getSqliteDatabase().prepare("SELECT COALESCE(MAX(board_rank), 0) + 1024 AS board_rank FROM tasks WHERE project_id IS ? AND phase = ?").get(current.projectId ?? null, input.phase).board_rank);
142
140
  return getSqliteDatabase().prepare(`UPDATE tasks SET phase = ?, resolution = ?, closed_at = ?,
143
- version = version + 1, updated_at = ?
144
- WHERE task_id = ? AND version = ?`).run(input.phase, input.resolution ?? null, input.phase === "closed" ? now : null, now, input.taskId, input.expectedVersion).changes === 0 ? void 0 : this.get(input.taskId);
141
+ board_rank = ?, version = version + 1, updated_at = ?
142
+ WHERE task_id = ? AND version = ?`).run(input.phase, input.resolution ?? null, input.phase === "closed" ? now : null, boardRank, now, input.taskId, input.expectedVersion).changes === 0 ? void 0 : this.get(input.taskId);
143
+ }
144
+ reorder(input) {
145
+ const current = this.get(input.taskId);
146
+ if (!current || current.version !== input.expectedVersion) return void 0;
147
+ const before = input.beforeTaskId ? this.get(input.beforeTaskId) : void 0;
148
+ if (input.beforeTaskId && (!before || before.id === current.id || before.projectId !== current.projectId || before.phase !== current.phase)) throw new Error("Board position target must be another task in the same project phase");
149
+ const now = Math.max(input.now ?? Date.now(), current.updatedAt + 1);
150
+ return runSqliteWriteTransaction((db) => {
151
+ const ids = db.prepare(`SELECT task_id FROM tasks
152
+ WHERE project_id IS ? AND phase = ? AND task_id <> ?
153
+ ORDER BY board_rank ASC, created_at ASC, task_id ASC`).all(current.projectId ?? null, current.phase, current.id).map((row) => row.task_id);
154
+ const insertAt = before ? ids.indexOf(before.id) : ids.length;
155
+ ids.splice(insertAt, 0, current.id);
156
+ const updateRank = db.prepare("UPDATE tasks SET board_rank = ? WHERE task_id = ?");
157
+ ids.forEach((id, index) => updateRank.run((index + 1) * 1024, id));
158
+ return db.prepare(`UPDATE tasks SET version = version + 1, updated_at = ?
159
+ WHERE task_id = ? AND version = ?`).run(now, current.id, current.version).changes === 0 ? void 0 : this.get(current.id);
160
+ });
145
161
  }
146
162
  reviseContract(input) {
147
163
  const current = this.get(input.taskId);
@@ -19,11 +19,13 @@ var TaskRunCoordinator = class TaskRunCoordinator {
19
19
  let run = runs.get(input.runId);
20
20
  if (!run) {
21
21
  if (runs.getActiveRoot(task.id)) return void 0;
22
+ const agentId = task.delegateAgentId ?? input.context.agentId;
23
+ if (!agentId) return void 0;
22
24
  run = runs.create({
23
25
  id: input.runId,
24
26
  taskId: task.id,
25
27
  executorKind: "agent",
26
- executorRef: { agentId: input.context.agentId ?? task.delegateAgentId ?? "main" },
28
+ executorRef: { agentId },
27
29
  trigger: { kind: input.context.triggerKind },
28
30
  correlationId: input.runId,
29
31
  idempotencyKey: input.runId,
@@ -1,39 +1,27 @@
1
- import { buildDefaultCorsOrigins } from "../gateway/host.js";
2
- import { isNetworkAccessibleBindHost, resolveGatewayBindMode, resolveGatewayEffectiveHost } from "../config/gateway-bind.js";
3
- import { enumerateLanGatewayCandidates } from "./tunnel-qr.js";
4
1
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../gateway/auth.js";
5
2
  import { assertGatewayRuntimeConfig } from "../gateway/runtime-config.js";
6
3
  //#region src/tunnel/enable-lan-pairing.ts
7
- function mergeCorsOriginsForLan(config, port, bindHost) {
8
- if (!config.gateway) return;
9
- const existing = new Set((config.gateway.corsOrigins ?? []).map((o) => o.trim()).filter(Boolean));
10
- for (const origin of buildDefaultCorsOrigins({
11
- port,
12
- bindHost
13
- })) existing.add(origin);
14
- for (const candidate of enumerateLanGatewayCandidates(port)) existing.add(candidate.url);
15
- config.gateway.corsOrigins = [...existing];
16
- }
17
4
  function applyLanPairingGatewayPatch(config) {
18
- const bindMode = resolveGatewayBindMode(config);
19
- const listenHost = resolveGatewayEffectiveHost(config);
20
- if (bindMode === "lan" && isNetworkAccessibleBindHost(listenHost)) return {
21
- ok: true,
22
- changed: false
23
- };
24
5
  if (!config.gateway) return {
25
6
  ok: false,
26
7
  message: "Gateway section missing from config"
27
8
  };
28
- config.gateway.bind = "lan";
29
- delete config.gateway.customBindHost;
30
- const port = config.gateway.port ?? 18790;
31
- mergeCorsOriginsForLan(config, port, resolveGatewayEffectiveHost(config));
9
+ const previousGateway = JSON.stringify(config.gateway);
10
+ const nextGateway = {
11
+ ...config.gateway,
12
+ bind: "lan"
13
+ };
14
+ delete nextGateway.customBindHost;
15
+ const candidate = {
16
+ ...config,
17
+ gateway: nextGateway
18
+ };
19
+ const port = nextGateway.port ?? 18790;
32
20
  try {
33
- const auth = resolveGatewayAuth({ authConfig: config.gateway.auth });
21
+ const auth = resolveGatewayAuth({ authConfig: candidate.gateway.auth });
34
22
  assertGatewayAuthConfigured(auth);
35
23
  assertGatewayRuntimeConfig({
36
- cfg: config,
24
+ cfg: candidate,
37
25
  auth,
38
26
  port
39
27
  });
@@ -43,9 +31,10 @@ function applyLanPairingGatewayPatch(config) {
43
31
  message: err instanceof Error ? err.message : String(err)
44
32
  };
45
33
  }
34
+ config.gateway = candidate.gateway;
46
35
  return {
47
36
  ok: true,
48
- changed: true
37
+ changed: previousGateway !== JSON.stringify(config.gateway)
49
38
  };
50
39
  }
51
40
  //#endregion
@@ -1,6 +1,6 @@
1
1
  import { init_public_url, normalizePublicUrlOrNull } from "../config/public-url.js";
2
+ import { enumerateLanGatewayCandidates } from "../gateway/host.js";
2
3
  import { isNetworkAccessibleBindHost, resolveGatewayBindMode, resolveGatewayEffectiveHost } from "../config/gateway-bind.js";
3
- import { enumerateLanGatewayCandidates } from "./tunnel-qr.js";
4
4
  import { buildMobileConnectUrlOrder } from "./pair-url.js";
5
5
  //#region src/tunnel/pair-context.ts
6
6
  init_public_url();
@@ -1,5 +1,5 @@
1
+ import { enumerateLanGatewayCandidates } from "../gateway/host.js";
1
2
  import { isNetworkAccessibleBindHost, resolveGatewayEffectiveHost } from "../config/gateway-bind.js";
2
- import { enumerateLanGatewayCandidates } from "./tunnel-qr.js";
3
3
  import net from "node:net";
4
4
  //#region src/tunnel/pair-url.ts
5
5
  /** Normalize a gateway root URL (no trailing slash, no path). */
@@ -1,11 +1,4 @@
1
1
  import type { TunnelQrPayload } from './tunnel-types.js';
2
- export type LanGatewayCandidate = {
3
- url: string;
4
- address: string;
5
- interfaceName: string;
6
- };
7
- /** Non-internal IPv4 addresses on this machine (independent of gateway bind mode). */
8
- export declare function enumerateLanGatewayCandidates(port: number): LanGatewayCandidate[];
9
2
  /** First non-internal IPv4 suitable for LAN QR (when gateway listens on 0.0.0.0). */
10
3
  export declare function resolveLanGatewayUrl(gatewayHost: string, gatewayPort: number): string | null;
11
4
  export declare function buildMobileConnectQrPayload(input: {
@@ -1,25 +1,8 @@
1
- import { networkInterfaces } from "node:os";
1
+ import { enumerateLanGatewayCandidates } from "../gateway/host.js";
2
2
  //#region src/tunnel/tunnel-qr.ts
3
3
  function trimBase(raw) {
4
4
  return raw.trim().replace(/\/+$/, "");
5
5
  }
6
- /** Non-internal IPv4 addresses on this machine (independent of gateway bind mode). */
7
- function enumerateLanGatewayCandidates(port) {
8
- const nets = networkInterfaces();
9
- const seen = /* @__PURE__ */ new Set();
10
- const out = [];
11
- for (const [interfaceName, addrs] of Object.entries(nets)) for (const addr of addrs ?? []) {
12
- if (addr.family !== "IPv4" || addr.internal) continue;
13
- if (seen.has(addr.address)) continue;
14
- seen.add(addr.address);
15
- out.push({
16
- address: addr.address,
17
- interfaceName,
18
- url: trimBase(`http://${addr.address}:${port}`)
19
- });
20
- }
21
- return out;
22
- }
23
6
  /** First non-internal IPv4 suitable for LAN QR (when gateway listens on 0.0.0.0). */
24
7
  function resolveLanGatewayUrl(gatewayHost, gatewayPort) {
25
8
  const host = gatewayHost.trim().toLowerCase();
@@ -43,4 +26,4 @@ function buildMobileConnectQrPayload(input) {
43
26
  };
44
27
  }
45
28
  //#endregion
46
- export { buildMobileConnectQrPayload, enumerateLanGatewayCandidates, resolveLanGatewayUrl };
29
+ export { buildMobileConnectQrPayload, resolveLanGatewayUrl };
@@ -2,6 +2,7 @@ import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-rou
2
2
  import { extractProfileAgentId, resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
3
3
  import { init_providers, resolveModel } from "../../providers/index.js";
4
4
  import { TaskRepository } from "../../tasks/task-repository.js";
5
+ import { TaskConversationRepository } from "../../tasks/task-conversation-repository.js";
5
6
  import { TaskRunRepository } from "../../tasks/task-run-repository.js";
6
7
  import { getProjectWorkspacePathForSession } from "../../projects/workspace.js";
7
8
  import { publishAutomationProductEvent } from "../../automations/product-events.js";
@@ -161,10 +162,11 @@ var WorkflowRunService = class {
161
162
  },
162
163
  sessionKey
163
164
  })) throw new Error("TaskRun changed before workflow execution started");
164
- context.linkSession({
165
+ new TaskConversationRepository().activateExecutionSession({
165
166
  taskId: task.id,
166
167
  sessionKey,
167
- role: "execution"
168
+ agentId: params.agentId,
169
+ runId: linkedTaskRun.id
168
170
  });
169
171
  }
170
172
  const source = normalizeWorkflowRunSourceForSession(params.source, sessionKey, params.parentSessionKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.197",
3
+ "version": "0.0.200",
4
4
  "description": "Local-first AI system that remembers context, coordinates AI, and sustains long-term progress.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -163,9 +163,9 @@
163
163
  "vitest": "4.1.5",
164
164
  "vue": "^3.5.35",
165
165
  "@xopcai/endpoint-tools-protocol": "0.0.0",
166
- "@xopcai/gateway-contract": "0.0.0",
167
166
  "@xopcai/realtime-protocol": "0.0.0",
168
- "@xopcai/realtime-client": "0.0.0"
167
+ "@xopcai/realtime-client": "0.0.0",
168
+ "@xopcai/gateway-contract": "0.0.0"
169
169
  },
170
170
  "scripts": {
171
171
  "assets:brand": "node scripts/generate-brand-assets.mjs",
@@ -190,6 +190,8 @@
190
190
  "mobile:test": "pnpm -C apps/mobile-expo test",
191
191
  "mobile:test:stream": "pnpm --filter @xopcai/agent-stream-client test",
192
192
  "mobile:release:patch": "bash scripts/apps/mobile-expo/release-patch.sh",
193
+ "mobile:configure:ios:github": "bash scripts/apps/mobile-expo/configure-ios-github-secrets.sh",
194
+ "mobile:release:ios:testflight": "bash scripts/apps/mobile-expo/release-ios-testflight.sh",
193
195
  "dev": "tsx src/cli/bin.ts",
194
196
  "dev:init": "sh -c 'mkdir -p \"$HOME/.xopc-dev\" && XOPC_STATE_DIR=\"$HOME/.xopc-dev\" XOPC_CONFIG_PATH=\"$HOME/.xopc-dev/xopc.json\" XOPC_CONFIG=\"$HOME/.xopc-dev/xopc.json\" XOPC_LOG_DIR=\"$HOME/.xopc-dev/logs\" XOPC_LOG_LEVEL=info tsx src/cli/bin.ts init \"$@\"' --",
195
197
  "dev:gateway": "sh -c 'mkdir -p \"$HOME/.xopc-dev\" && XOPC_STATE_DIR=\"$HOME/.xopc-dev\" XOPC_CONFIG_PATH=\"$HOME/.xopc-dev/xopc.json\" XOPC_CONFIG=\"$HOME/.xopc-dev/xopc.json\" XOPC_LOG_DIR=\"$HOME/.xopc-dev/logs\" XOPC_LOG_LEVEL=info tsx src/cli/bin.ts gateway \"$@\"' --",