@xopcai/xopc 0.0.403 → 0.0.405

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 (212) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/feishu/src/transport/socket-mode/monitor.js +1 -1
  3. package/dist/extensions/feishu/src/transport/webhook/monitor.js +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BibqpRFi.js → agent-avatar-dicebear-wc__VG7A.js} +1 -1
  6. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-DRgnm9A5.js +1 -0
  7. package/dist/gateway/static/root/assets/{agents-admin-api-DvSe10zu.js → agents-admin-api-D6XzhsQy.js} +1 -1
  8. package/dist/gateway/static/root/assets/agents-sIMLDv80.js +77 -0
  9. package/dist/gateway/static/root/assets/{app-management-settings-panel-cRzpsDIP.js → app-management-settings-panel-DnQKk3ql.js} +1 -1
  10. package/dist/gateway/static/root/assets/{appearance-settings-BKnQuWtS.js → appearance-settings-CoL67S5e.js} +1 -1
  11. package/dist/gateway/static/root/assets/apps-page-CRAr0xnF.js +1 -0
  12. package/dist/gateway/static/root/assets/{archive-plugin-Duhsr1eD.js → archive-plugin-CgKj53U1.js} +1 -1
  13. package/dist/gateway/static/root/assets/{automations-page-OfEhd4vL.js → automations-page-Cr_WMoqc.js} +1 -1
  14. package/dist/gateway/static/root/assets/automations-workspace-BGpO47Sw.js +6 -0
  15. package/dist/gateway/static/root/assets/{binary-plugins-BDsjWsNb.js → binary-plugins-C_h3FTTz.js} +1 -1
  16. package/dist/gateway/static/root/assets/{block-editor-D_wE8D8_.js → block-editor-lnkSRbxE.js} +40 -40
  17. package/dist/gateway/static/root/assets/{browser-automation-inputs-DlqyI0ez.js → browser-automation-inputs-FsIEAlnO.js} +1 -1
  18. package/dist/gateway/static/root/assets/browser-automations-page-Dwhk5TFz.js +3 -0
  19. package/dist/gateway/static/root/assets/browser-settings-page-B1Mfsw2n.js +3 -0
  20. package/dist/gateway/static/root/assets/{capabilities-glv1DeRI.js → capabilities-Dl3LttAm.js} +1 -1
  21. package/dist/gateway/static/root/assets/{capabilities-page-CYWBkGj0.js → capabilities-page-lfNS8DDp.js} +2 -2
  22. package/dist/gateway/static/root/assets/capabilities-settings-panel-DLL614DS.js +8 -0
  23. package/dist/gateway/static/root/assets/{capability-header-actions-DCxxOLIt.js → capability-header-actions-wTmkMFS8.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-W60IrDrt.js +1 -0
  25. package/dist/gateway/static/root/assets/{chat-terminal-dock-B0g-YEQo.js → chat-terminal-dock-DJjZ0p_B.js} +2 -2
  26. package/dist/gateway/static/root/assets/{computer-settings-page-DNI0SuC-.js → computer-settings-page-BYYgEEdX.js} +1 -1
  27. package/dist/gateway/static/root/assets/{connector-service-page-CDR35YqB.js → connector-service-page-DavOiSs1.js} +1 -1
  28. package/dist/gateway/static/root/assets/connectors-page-BUTj6vNY.js +1 -0
  29. package/dist/gateway/static/root/assets/{date-picker-B88pKWvd.js → date-picker-cGUcobcp.js} +1 -1
  30. package/dist/gateway/static/root/assets/{dependency-picker-ChpYlt2j.js → dependency-picker-BvEoPDqz.js} +1 -1
  31. package/dist/gateway/static/root/assets/{desktop-pet-17hqnL87.js → desktop-pet-DL330r9w.js} +1 -1
  32. package/dist/gateway/static/root/assets/{desktop-pet-settings-3jN8S9Zu.js → desktop-pet-settings-BkBrKnpR.js} +1 -1
  33. package/dist/gateway/static/root/assets/{device-pairing-wizard-DIcqqq97.js → device-pairing-wizard-BYUl_dNS.js} +1 -1
  34. package/dist/gateway/static/root/assets/{directory-picker-path-field-CFBLUC-2.js → directory-picker-path-field-Bq5EumS7.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-debug-page-CRjY1QeU.js → extension-debug-page-BcNqrM44.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-page-or5zrKc7.js → extension-page-BIOXclKZ.js} +1 -1
  37. package/dist/gateway/static/root/assets/{extension-settings-page-X8kI665r.js → extension-settings-page-BdLmNW7c.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-config-swr-DAir1JsW.js → gateway-config-swr-BvuySoCX.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-realtime-dE0XrVAT.js → gateway-realtime-SBtdXzco.js} +1 -1
  40. package/dist/gateway/static/root/assets/gateway-realtime-store-dKq2fm2X.js +1 -0
  41. package/dist/gateway/static/root/assets/gateway-settings-C1vgqKYa.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-CqyGHM2M.js → gateway-startup-retry-CEpuztYK.js} +1 -1
  43. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-CL6ZYfP_.js → highlighted-body-KQOG7T2V-BJBmXHUI.js} +1 -1
  44. package/dist/gateway/static/root/assets/home-page-Cd4MHgKf.js +2 -0
  45. package/dist/gateway/static/root/assets/{image-generation-api-DPcsBPX7.js → image-generation-api-vO5_70v-.js} +1 -1
  46. package/dist/gateway/static/root/assets/{imports-page-Cpuq7Ri0.js → imports-page-xvg0vgTo.js} +1 -1
  47. package/dist/gateway/static/root/assets/{index-CzkAd5Su.js → index-DdJ_djQt.js} +116 -116
  48. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BIoPfzm1.js → keyboard-shortcuts-settings-D-jHSG1c.js} +1 -1
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-ER7_0M_4.js +1 -0
  50. package/dist/gateway/static/root/assets/{local-apps-page-Dutmy_H3.js → local-apps-page-DQOK34TS.js} +1 -1
  51. package/dist/gateway/static/root/assets/{local-session-drafts-fhip41-L.js → local-session-drafts-DhJjHCfQ.js} +1 -1
  52. package/dist/gateway/static/root/assets/{locale-store-Jnhw2WMv.js → locale-store-D5h-Ha6-.js} +1 -1
  53. package/dist/gateway/static/root/assets/logs-page-_v_abG4D.js +2 -0
  54. package/dist/gateway/static/root/assets/management-settings-CWojbrEe.js +1 -0
  55. package/dist/gateway/static/root/assets/{markdown-view-B58RypQ4.js → markdown-view-CthsQiiO.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-Brwr53z1.js → media-plugins-4_OqZkJo.js} +1 -1
  57. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-BXiiOI72.js +1 -0
  58. package/dist/gateway/static/root/assets/{messages-DBvKzlCl.js → messages-Bwv-AOYl.js} +2 -2
  59. package/dist/gateway/static/root/assets/note-detail-panel-tHYUDAgB.js +5 -0
  60. package/dist/gateway/static/root/assets/note-image-lightbox-DwVH-T8-.js +1 -0
  61. package/dist/gateway/static/root/assets/notes-page-BQqxqB3t.js +8 -0
  62. package/dist/gateway/static/root/assets/{page-context-capture-button-CTMrt6Ws.js → page-context-capture-button-DkFhXsZj.js} +1 -1
  63. package/dist/gateway/static/root/assets/personal-page-DyKbVh4z.js +1 -0
  64. package/dist/gateway/static/root/assets/plugin-details-dialog-CVbHabgS.js +1 -0
  65. package/dist/gateway/static/root/assets/plugin-presentation-BfVM-8kL.js +1 -0
  66. package/dist/gateway/static/root/assets/{preview-open-alternatives-DCffBrFR.js → preview-open-alternatives-Bz7-AqIY.js} +1 -1
  67. package/dist/gateway/static/root/assets/{product-open-page--caaVC81.js → product-open-page-uAU6q84_.js} +1 -1
  68. package/dist/gateway/static/root/assets/{product-preview-content-B2pgfzxA.js → product-preview-content-DsPKx_gw.js} +1 -1
  69. package/dist/gateway/static/root/assets/project-detail-page-BpUxpCUt.js +1 -0
  70. package/dist/gateway/static/root/assets/projects-page-BWrQ05az.js +1 -0
  71. package/dist/gateway/static/root/assets/{registry-api-BbUEMGcj.js → registry-api-Bf0hVPNV.js} +1 -1
  72. package/dist/gateway/static/root/assets/{remote-access-hub-Crf01UPK.js → remote-access-hub-D4k7snPU.js} +1 -1
  73. package/dist/gateway/static/root/assets/{runtime-tools-api-D0xtCTXr.js → runtime-tools-api-ByH1meP7.js} +1 -1
  74. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-Bo_vaiIq.js → runtime-tools-settings-panel-D2VV6nm2.js} +1 -1
  75. package/dist/gateway/static/root/assets/{schema-form-BXk8w1q-.js → schema-form-gO0zayZd.js} +1 -1
  76. package/dist/gateway/static/root/assets/{session-api-CAKgrbgz.js → session-api-fVuszA_P.js} +1 -1
  77. package/dist/gateway/static/root/assets/{session-manager-D_N7qha7.js → session-manager-BMEW_eS_.js} +2 -2
  78. package/dist/gateway/static/root/assets/sessions-page-DPrI8ql2.js +1 -0
  79. package/dist/gateway/static/root/assets/settings-advanced-gate-BYXPsUzS.js +1 -0
  80. package/dist/gateway/static/root/assets/{settings-form-section-COwDGhbe.js → settings-form-section-CihKQYlF.js} +1 -1
  81. package/dist/gateway/static/root/assets/{settings-page-CV_QX35m.js → settings-page-BYP_I9AF.js} +1 -1
  82. package/dist/gateway/static/root/assets/setup-status-panel-BWVb5uxa.js +1 -0
  83. package/dist/gateway/static/root/assets/{share-preview-page-BsRSJVHV.js → share-preview-page-Dg0mhito.js} +1 -1
  84. package/dist/gateway/static/root/assets/shares-settings-q0E4FYlf.js +1 -0
  85. package/dist/gateway/static/root/assets/{skill-api-W7NoRL_J.js → skill-api-CrNz0Fi0.js} +1 -1
  86. package/dist/gateway/static/root/assets/skill-reload-api-BNCLOlJs.js +1 -0
  87. package/dist/gateway/static/root/assets/skills-page-CYwH8kim.js +2 -0
  88. package/dist/gateway/static/root/assets/{style-CXJD5Nzd.js → style-CuYP4CAT.js} +1 -1
  89. package/dist/gateway/static/root/assets/{system-settings-panel-DrdONDJA.js → system-settings-panel-DGFMkic_.js} +1 -1
  90. package/dist/gateway/static/root/assets/task-detail-page-CTqBd0eY.js +2 -0
  91. package/dist/gateway/static/root/assets/{task-expandable-content-HdEeV_0-.js → task-expandable-content-BoGtWYbk.js} +1 -1
  92. package/dist/gateway/static/root/assets/{tasks-PuIUgF9L.js → tasks-B4bZpO6O.js} +1 -1
  93. package/dist/gateway/static/root/assets/tracing-settings-page-0CvZ40sA.js +1 -0
  94. package/dist/gateway/static/root/assets/{tunnel-api-Ce4mYarE.js → tunnel-api-CnLkQQGi.js} +1 -1
  95. package/dist/gateway/static/root/assets/usage-page-BInqKKdE.js +1 -0
  96. package/dist/gateway/static/root/assets/{use-autosave-BmbPOiQU.js → use-autosave-0dTfTmCk.js} +1 -1
  97. package/dist/gateway/static/root/assets/user-model-page-3Dr0YRDG.js +2 -0
  98. package/dist/gateway/static/root/assets/{voice-api-key-field-DqLKXIfy.js → voice-api-key-field-BpOvEhu7.js} +1 -1
  99. package/dist/gateway/static/root/assets/{voice-config-api-T3nM4buh.js → voice-config-api-CRjdZdJF.js} +1 -1
  100. package/dist/gateway/static/root/assets/{work-discovery-overlay-oUsUigJS.js → work-discovery-overlay-Br-XaBAW.js} +1 -1
  101. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-C3oU639v.js → workflow-run-setup-panel-B8E6qBkL.js} +2 -2
  102. package/dist/gateway/static/root/assets/workflows-page-CqC45_Fd.js +6 -0
  103. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-DQNlWhsN.js → xopc-cloud-account-card-BARP73BX.js} +1 -1
  104. package/dist/gateway/static/root/index.html +15 -15
  105. package/dist/package.js +1 -1
  106. package/dist/packages/gateway-contract/src/tasks.js +27 -8
  107. package/dist/src/agent/agent-manager.js +1 -1
  108. package/dist/src/agent/background-review/run-background-review.js +1 -1
  109. package/dist/src/agent/external-tools/cliProvider.js +2 -2
  110. package/dist/src/agent/external-tools/composio-provider.js +2 -2
  111. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  112. package/dist/src/agent/service.js +1 -1
  113. package/dist/src/agent/skills/index.js +1 -1
  114. package/dist/src/agent/skills/managed-store.js +1 -1
  115. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  116. package/dist/src/agent/tools/personal-read-tool.js +1 -1
  117. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  118. package/dist/src/agent-catalog/capabilities.js +2 -2
  119. package/dist/src/agent-catalog/migrations/legacy-config-cutover.js +1 -1
  120. package/dist/src/agent-catalog/repository.js +1 -1
  121. package/dist/src/automations/capabilities/drafts.js +1 -1
  122. package/dist/src/automations/capabilities/write.d.ts +14 -0
  123. package/dist/src/automations/domain/validation.d.ts +28 -0
  124. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -1
  125. package/dist/src/bootstrap/application-state.js +1 -1
  126. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  127. package/dist/src/capabilities/runtime/dispatcher.js +1 -1
  128. package/dist/src/capabilities/runtime/product.js +1 -1
  129. package/dist/src/cli/commands/agents.js +1 -1
  130. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  131. package/dist/src/cli/commands/models.js +1 -1
  132. package/dist/src/cli/commands/onboard/model.js +1 -1
  133. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  134. package/dist/src/config/agent-profile.js +1 -1
  135. package/dist/src/execution-environments/local-worktree-manager.js +1 -1
  136. package/dist/src/extensions/agent-plugins/skill-catalog.js +1 -1
  137. package/dist/src/extensions/agent-plugins/validation.js +1 -1
  138. package/dist/src/gateway/agents-admin.js +2 -2
  139. package/dist/src/gateway/auth.d.ts +2 -0
  140. package/dist/src/gateway/auth.js +13 -4
  141. package/dist/src/gateway/hono/routes/agents.js +1 -1
  142. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  143. package/dist/src/gateway/hono/routes/notes.js +2 -2
  144. package/dist/src/gateway/hono/routes/projects.js +2 -2
  145. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  146. package/dist/src/gateway/hono/routes/tasks.js +3 -2
  147. package/dist/src/gateway/image-generation-setup.js +1 -1
  148. package/dist/src/gateway/security/audit.js +3 -3
  149. package/dist/src/gateway/service/run-gateway-agent.js +1 -0
  150. package/dist/src/gateway/service.js +4 -4
  151. package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
  152. package/dist/src/home-intelligence/host.js +2 -2
  153. package/dist/src/imports/importService.js +1 -1
  154. package/dist/src/local-apps/service.js +1 -1
  155. package/dist/src/personal-agent/service.js +1 -1
  156. package/dist/src/providers/prompt-cache-lifecycle.d.ts +1 -1
  157. package/dist/src/providers/prompt-cache-lifecycle.js +1 -1
  158. package/dist/src/runtime-tools/archive.js +1 -1
  159. package/dist/src/storage/sqlite/migrations/258_task_phase_changes.sql +20 -0
  160. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  161. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  162. package/dist/src/storage/sqlite/schema.js +1 -1
  163. package/dist/src/tasks/capabilities/read.js +3 -2
  164. package/dist/src/tasks/capabilities/write.js +3 -3
  165. package/dist/src/tasks/task-application-service.d.ts +2 -1
  166. package/dist/src/tasks/task-application-service.js +80 -12
  167. package/dist/src/tasks/task-collaboration-delivery.js +2 -1
  168. package/dist/src/tasks/task-context-assembler.js +2 -1
  169. package/dist/src/tasks/task-read-model-projector.js +13 -5
  170. package/dist/src/tasks/task-repository.d.ts +11 -1
  171. package/dist/src/tasks/task-repository.js +42 -7
  172. package/dist/src/tasks/task-run-coordinator.d.ts +2 -0
  173. package/dist/src/tasks/task-run-coordinator.js +26 -17
  174. package/dist/src/tasks/task-run-repository.js +5 -2
  175. package/dist/src/tui/backends/embedded-backend.js +1 -1
  176. package/dist/src/voice/realtime/persona-context.js +1 -1
  177. package/package.json +3 -3
  178. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Dj5XE9fO.js +0 -1
  179. package/dist/gateway/static/root/assets/agents-HpKwxi9M.js +0 -77
  180. package/dist/gateway/static/root/assets/apps-page-B_4AiHMy.js +0 -1
  181. package/dist/gateway/static/root/assets/automations-workspace-DyNAy5A1.js +0 -6
  182. package/dist/gateway/static/root/assets/browser-automations-page-BlSVIXB6.js +0 -3
  183. package/dist/gateway/static/root/assets/browser-settings-page-BuGBM-PJ.js +0 -3
  184. package/dist/gateway/static/root/assets/capabilities-settings-panel-CWoM2AZn.js +0 -8
  185. package/dist/gateway/static/root/assets/channels-DEB1AYkM.js +0 -1
  186. package/dist/gateway/static/root/assets/connectors-page-CW2vHnSK.js +0 -1
  187. package/dist/gateway/static/root/assets/gateway-realtime-store-CPlVuu0d.js +0 -1
  188. package/dist/gateway/static/root/assets/gateway-settings-BT6ZMqA4.js +0 -1
  189. package/dist/gateway/static/root/assets/home-page-MxealTDk.js +0 -2
  190. package/dist/gateway/static/root/assets/local-app-workbench-page-CvY6c0zW.js +0 -1
  191. package/dist/gateway/static/root/assets/logs-page-DFNUn-Lf.js +0 -2
  192. package/dist/gateway/static/root/assets/management-settings--LHmsgjW.js +0 -1
  193. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-CosDs4aI.js +0 -1
  194. package/dist/gateway/static/root/assets/note-detail-panel-1k-swf3p.js +0 -5
  195. package/dist/gateway/static/root/assets/note-image-lightbox-BYNLO2pt.js +0 -1
  196. package/dist/gateway/static/root/assets/notes-page-B1ADIBKj.js +0 -8
  197. package/dist/gateway/static/root/assets/personal-page-MhVNCcRA.js +0 -1
  198. package/dist/gateway/static/root/assets/plugin-details-dialog-BAPTOn3F.js +0 -1
  199. package/dist/gateway/static/root/assets/plugin-presentation-D-o-0IeU.js +0 -1
  200. package/dist/gateway/static/root/assets/project-detail-page-Cm4cR-TZ.js +0 -1
  201. package/dist/gateway/static/root/assets/projects-page-DPR6478A.js +0 -1
  202. package/dist/gateway/static/root/assets/sessions-page-DcAxjdZi.js +0 -1
  203. package/dist/gateway/static/root/assets/settings-advanced-gate-DLLcp7l0.js +0 -1
  204. package/dist/gateway/static/root/assets/setup-status-panel-BvAAETqm.js +0 -1
  205. package/dist/gateway/static/root/assets/shares-settings-Cm0iaWqX.js +0 -1
  206. package/dist/gateway/static/root/assets/skill-reload-api-DNp30a6A.js +0 -1
  207. package/dist/gateway/static/root/assets/skills-page-dHlURgRl.js +0 -2
  208. package/dist/gateway/static/root/assets/task-detail-page-C7zXj_B9.js +0 -2
  209. package/dist/gateway/static/root/assets/tracing-settings-page-CXI5s3V-.js +0 -1
  210. package/dist/gateway/static/root/assets/usage-page-yt14VUPq.js +0 -1
  211. package/dist/gateway/static/root/assets/user-model-page-ne3A7X7a.js +0 -2
  212. package/dist/gateway/static/root/assets/workflows-page-szPvZMys.js +0 -6
@@ -1,11 +1,11 @@
1
1
  import { normalizeAgentId } from "../agent-catalog/id.js";
2
2
  import { AgentCatalogRepository, init_repository } from "../agent-catalog/repository.js";
3
3
  import { init_agent_scope } from "../agent/agent-scope.js";
4
- import { AgentCatalogService } from "../agent-catalog/service.js";
5
4
  import { ConfigSchema, init_schema } from "../config/schema.js";
6
5
  import { resolveEffectiveAgentConfigForAgent } from "../config/agent-profile.js";
7
6
  import { fetchWithTimeoutGuarded } from "../media-shared/http/provider-http.js";
8
7
  import "../media-shared/http/index.js";
8
+ import { AgentCatalogService } from "../agent-catalog/service.js";
9
9
  import { getImageGenerationProvider, listImageGenerationProvidersSummary } from "../agent/image/generation/provider-registry.js";
10
10
  //#region src/gateway/image-generation-setup.ts
11
11
  init_repository();
@@ -90,12 +90,12 @@ function collectGatewayConfigFindings(params) {
90
90
  detail: "Token consists of a single repeated character, making it trivially guessable.",
91
91
  remediation: "Generate a cryptographically random token: `openssl rand -hex 32`."
92
92
  });
93
- if (!process.env.XOPC_GATEWAY_TOKEN) findings.push({
93
+ if (params.auth.tokenSource === "generated") findings.push({
94
94
  checkId: "gateway.auth.auto_generated_token",
95
95
  severity: "info",
96
96
  title: "Gateway token was auto-generated",
97
- detail: "No explicit XOPC_GATEWAY_TOKEN set. The token was auto-generated and will change on each restart.",
98
- remediation: "Set XOPC_GATEWAY_TOKEN environment variable for a stable token."
97
+ detail: "Neither gateway.auth.token nor XOPC_GATEWAY_TOKEN is set. The token was auto-generated and will change on each restart.",
98
+ remediation: "Save gateway.auth.token in the configuration or set XOPC_GATEWAY_TOKEN for a stable token."
99
99
  });
100
100
  }
101
101
  if (params.corsOrigins?.includes("*")) findings.push({
@@ -103,6 +103,7 @@ async function* runGatewayAgent(deps, message, channel, chatId, origin, attachme
103
103
  taskRun = TaskRunCoordinator.start({
104
104
  runId: runOptions?.taskRunId ?? runId,
105
105
  context: executionContext,
106
+ inputOrigin: origin,
106
107
  fallbackObjective: message,
107
108
  timeoutMs: executionContext.taskId ? resolveAgentTurnTimeoutMs(deps.config, webchatConversationId) : void 0
108
109
  });
@@ -103,10 +103,6 @@ import { DiscussionSealer } from "../discussions/sealer.js";
103
103
  import "../discussions/index.js";
104
104
  import { EndpointToolRuntime } from "../endpoint-tools/runtime.js";
105
105
  import "../endpoint-tools/index.js";
106
- import { HomeCapabilityPreflightService } from "../home-intelligence/capability-preflight.js";
107
- import { HomeAdviceGenerator } from "../home-intelligence/generator.js";
108
- import { HomeIntelligenceHost } from "../home-intelligence/host.js";
109
- import { HomeSnapshotBuilder } from "../home-intelligence/snapshot.js";
110
106
  import { assertGatewayAuthConfigured, extractToken, resolveGatewayAuth, validateToken } from "./auth.js";
111
107
  import { prepareAutomationAgentSession } from "./automation-agent-session.js";
112
108
  import { stopTailscaleExposure } from "./tailscale-lifecycle.js";
@@ -167,6 +163,10 @@ import { TaskMainUpdateDecisionService } from "../tasks/task-main-update-decisio
167
163
  import { selectTaskMainUpdateAttempt, submitAndConfirmTaskMainUpdate } from "../tasks/task-main-update-input.js";
168
164
  import { checkAppContextAccess, prepareAppContext } from "./service/app-context-access.js";
169
165
  import { applyAutomaticVoiceLanguage, inferProductLanguageFromEnvironment, initializeVoiceDefaults } from "../voice/language-profile.js";
166
+ import { HomeAdviceGenerator } from "../home-intelligence/generator.js";
167
+ import { HomeIntelligenceHost } from "../home-intelligence/host.js";
168
+ import { HomeSnapshotBuilder } from "../home-intelligence/snapshot.js";
169
+ import { HomeCapabilityPreflightService } from "../home-intelligence/capability-preflight.js";
170
170
  import crypto from "node:crypto";
171
171
  //#region src/gateway/service.ts
172
172
  init_session_repository();
@@ -1,13 +1,13 @@
1
1
  import "../agent-config/schema.js";
2
2
  import { init_agent_config } from "../agent-config/index.js";
3
3
  import { AgentCatalogRepository, init_repository } from "../agent-catalog/repository.js";
4
- import { AgentCatalogService } from "../agent-catalog/service.js";
5
4
  import { ConfigSchema, init_schema } from "../config/schema.js";
6
5
  import { init_model_policy, isComputerModel, isDedicatedComputerProfile } from "../computer/model-policy.js";
7
6
  import { voiceSupportsMode } from "../../packages/realtime-protocol/src/voice-catalog.js";
8
7
  import { init_voice } from "../../packages/realtime-protocol/src/voice.js";
9
8
  import { getModelCatalogStore, init_model_catalog_store } from "../providers/model-catalog-store.js";
10
9
  import { compareCatalogModels } from "../providers/model-catalog-ranking.js";
10
+ import { AgentCatalogService } from "../agent-catalog/service.js";
11
11
  import { prepareUpdateGlobalDefaults } from "./global-defaults-admin.js";
12
12
  //#region src/gateway/xopc-cloud-capability-setup.ts
13
13
  init_voice();
@@ -1,10 +1,10 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { HomeAdviceBudgetExceededError, isHomeProseLocalized } from "./generator.js";
3
4
  import { homePatternKey } from "./strategy.js";
5
+ import { HomeAdvicePolicy } from "./policy.js";
4
6
  import { HomeIntelligenceRepository } from "./repository.js";
5
7
  import { HomeOpportunityApplicationService } from "./application-service.js";
6
- import { HomeAdvicePolicy } from "./policy.js";
7
- import { HomeAdviceBudgetExceededError, isHomeProseLocalized } from "./generator.js";
8
8
  import { buildHomeOpportunityNotification } from "./notification.js";
9
9
  import { createHash } from "node:crypto";
10
10
  //#region src/home-intelligence/host.ts
@@ -11,8 +11,8 @@ import { scanLocal } from "./scanner.js";
11
11
  import { dirname, join } from "node:path";
12
12
  import { existsSync, lstatSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
13
13
  import { randomUUID } from "node:crypto";
14
- import yaml from "js-yaml";
15
14
  import lockfile from "proper-lockfile";
15
+ import yaml from "js-yaml";
16
16
  //#region src/imports/importService.ts
17
17
  init_write_file_atomic();
18
18
  init_logger();
@@ -5,10 +5,10 @@ import { currentOperationId, init_operation_context } from "../infra/operation-c
5
5
  import { afterSqliteCommit, init_transaction, runSqliteWriteTransaction } from "../storage/sqlite/transaction.js";
6
6
  import { ExtensionCapabilityBindingsSchema, extensionCapabilityPermissions } from "../../packages/gateway-contract/src/extension-capabilities.js";
7
7
  import { init_src } from "../../packages/gateway-contract/src/index.js";
8
- import { CapabilityError } from "../capabilities/runtime/errors.js";
9
8
  import { init_paths, resolveExtensionsDir } from "../config/paths.js";
10
9
  import { slugifyProjectName } from "../projects/project-store.js";
11
10
  import { LocalAppStore } from "./store.js";
11
+ import { CapabilityError } from "../capabilities/runtime/errors.js";
12
12
  import { DomainOutboxDispatcher } from "../infra/domain-outbox-dispatcher.js";
13
13
  import { validateLocalAppCapabilityContracts } from "./capabilities/contracts.js";
14
14
  import { buildLocalAppFixGuidance } from "./fix-guidance.js";
@@ -4,13 +4,13 @@ import { init_config_repository, setSessionConfig } from "../storage/sqlite/conf
4
4
  import { ResponsePreferencesSchema } from "../agent-config/schema.js";
5
5
  import { init_agent_config } from "../agent-config/index.js";
6
6
  import { AgentCatalogRepository, init_repository } from "../agent-catalog/repository.js";
7
- import { AgentCatalogService } from "../agent-catalog/service.js";
8
7
  import { createConversation, init_conversation_repository } from "../storage/sqlite/conversation-repository.js";
9
8
  import { getAvailableModels, init_providers } from "../providers/index.js";
10
9
  import { DEFAULT_PERSONAL_PREFERENCES, getPersonalAgent, personalAgentId } from "./repository.js";
11
10
  import { PERSONAL_MAIN_TOOL_IDS, PERSONAL_READ_TOOL_ALIASES } from "./policy.js";
12
11
  import { getModelThinking } from "../providers/model-thinking.js";
13
12
  import { personalInstructions, upgradePersonalInstructions } from "./prompts.js";
13
+ import { AgentCatalogService } from "../agent-catalog/service.js";
14
14
  import { completePersonalOnboarding } from "./onboarding.js";
15
15
  import { z } from "zod";
16
16
  //#region src/personal-agent/service.ts
@@ -4,6 +4,6 @@ export declare function resolvePromptCacheTtlMs(model: Model<Api>, policy: Promp
4
4
  export declare function recordPromptCacheTouch(conversationId: string, model: Model<Api>, usage: {
5
5
  cacheRead?: number;
6
6
  cacheWrite?: number;
7
- }, now?: number): void;
7
+ } | null | undefined, now?: number): void;
8
8
  export declare function isPromptCacheExpired(conversationId: string, model: Model<Api>, policy: PromptCachePolicy, now?: number): boolean;
9
9
  export declare function clearPromptCacheTouches(): void;
@@ -9,7 +9,7 @@ function resolvePromptCacheTtlMs(model, policy) {
9
9
  return policy.lifetime === "long" ? 60 * 6e4 : 5 * 6e4;
10
10
  }
11
11
  function recordPromptCacheTouch(conversationId, model, usage, now = Date.now()) {
12
- if ((usage.cacheRead ?? 0) <= 0 && (usage.cacheWrite ?? 0) <= 0) return;
12
+ if ((usage?.cacheRead ?? 0) <= 0 && (usage?.cacheWrite ?? 0) <= 0) return;
13
13
  const key = scopeKey(conversationId, model);
14
14
  cacheTouchByScope.delete(key);
15
15
  cacheTouchByScope.set(key, now);
@@ -1,8 +1,8 @@
1
1
  import { RuntimeError } from "./errors.js";
2
2
  import { isAbsolute, join, posix, relative, resolve } from "node:path";
3
3
  import { spawn } from "node:child_process";
4
- import { lstat, mkdir, readdir, readlink, rename, rm, stat } from "node:fs/promises";
5
4
  import AdmZip from "adm-zip";
5
+ import { lstat, mkdir, readdir, readlink, rename, rm, stat } from "node:fs/promises";
6
6
  //#region src/runtime-tools/archive.ts
7
7
  const MAX_ARCHIVE_ENTRIES = 5e4;
8
8
  const MAX_TAR_OUTPUT_BYTES = 16 * 1024 * 1024;
@@ -0,0 +1,20 @@
1
+ ALTER TABLE tasks ADD COLUMN manual_phase_revision INTEGER NOT NULL DEFAULT 0;
2
+ ALTER TABLE tasks ADD COLUMN automatic_phase_revision INTEGER NOT NULL DEFAULT 0;
3
+ ALTER TABLE task_runs ADD COLUMN manual_phase_revision INTEGER NOT NULL DEFAULT 0;
4
+
5
+ CREATE TABLE task_phase_changes (
6
+ id TEXT PRIMARY KEY,
7
+ task_id TEXT NOT NULL REFERENCES tasks(task_id) ON DELETE CASCADE,
8
+ from_phase TEXT NOT NULL,
9
+ to_phase TEXT NOT NULL,
10
+ from_resolution TEXT,
11
+ to_resolution TEXT,
12
+ actor_json TEXT NOT NULL,
13
+ source TEXT NOT NULL,
14
+ operation_id TEXT,
15
+ run_id TEXT,
16
+ task_version INTEGER NOT NULL,
17
+ created_at INTEGER NOT NULL,
18
+ UNIQUE(task_id, task_version)
19
+ );
20
+ CREATE INDEX idx_task_phase_changes_task ON task_phase_changes(task_id, task_version);
@@ -3,7 +3,7 @@ import type { ApplyMigrationsOptions } from './types.js';
3
3
  /** Baseline schema version applied from schema.sql on first open. */
4
4
  export declare const XOPC_DB_BASELINE_SCHEMA_VERSION = 217;
5
5
  /** Latest schema version this release supports (increment when adding migrations). */
6
- export declare const XOPC_DB_SCHEMA_VERSION = 257;
6
+ export declare const XOPC_DB_SCHEMA_VERSION = 258;
7
7
  export declare function resolveMigrationsDir(override?: string): string;
8
8
  /**
9
9
  * Apply sequential SQL migrations from (currentVersion + 1) through targetVersion.
@@ -48,7 +48,7 @@ function applySingleMigration(db, migration) {
48
48
  function applyPendingMigrations(db, options = {}) {
49
49
  db.function("xopc_memory_search_text", { deterministic: true }, (value) => memorySearchText(String(value ?? "")));
50
50
  db.function("xopc_operation_id", () => currentOperationId() ?? null);
51
- const targetVersion = options.targetVersion ?? 257;
51
+ const targetVersion = options.targetVersion ?? 258;
52
52
  let currentVersion = readSchemaVersion(db);
53
53
  if (currentVersion > targetVersion) throw new DatabaseSchemaTooNewError(currentVersion, targetVersion);
54
54
  if (!options.migrationsDir && currentVersion < 217) throw new DatabaseSchemaTooOldError(currentVersion, 217);
@@ -65,7 +65,7 @@ function applyPendingMigrations(db, options = {}) {
65
65
  }
66
66
  /** Inspect schema version without mutating the database. */
67
67
  function inspectSchemaMigrationStatus(db, options = {}) {
68
- const appVersion = options.targetVersion ?? 257;
68
+ const appVersion = options.targetVersion ?? 258;
69
69
  const dbVersion = readSchemaVersion(db);
70
70
  if (dbVersion > appVersion) return {
71
71
  dbVersion,
@@ -105,7 +105,7 @@ var init_runner = __esmMin((() => {
105
105
  init_errors();
106
106
  log = createLogger("Sqlite:Migrations");
107
107
  XOPC_DB_BASELINE_SCHEMA_VERSION = 217;
108
- XOPC_DB_SCHEMA_VERSION = 257;
108
+ XOPC_DB_SCHEMA_VERSION = 258;
109
109
  }));
110
110
  //#endregion
111
111
  init_runner();
@@ -26,7 +26,7 @@ function ensureXopcDatabaseSchema(db) {
26
26
  bootstrapFreshDatabase(db);
27
27
  currentVersion = 217;
28
28
  }
29
- applyPendingMigrations(db, { targetVersion: 257 });
29
+ applyPendingMigrations(db, { targetVersion: 258 });
30
30
  }
31
31
  var init_schema = __esmMin((() => {
32
32
  init_sql_assets();
@@ -2,10 +2,10 @@ import { ProductReadContracts } from "../../../packages/gateway-contract/src/cap
2
2
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
3
  import { TaskRepository, init_task_repository } from "../task-repository.js";
4
4
  import { TaskRunRepository, init_task_run_repository } from "../task-run-repository.js";
5
- import { CapabilityError } from "../../capabilities/runtime/errors.js";
6
- import { defineReadCapability } from "../../capabilities/runtime/dispatcher.js";
7
5
  import { TaskReadModelProjector } from "../task-read-model-projector.js";
8
6
  import { TaskConversationRepository } from "../task-conversation-repository.js";
7
+ import { CapabilityError } from "../../capabilities/runtime/errors.js";
8
+ import { defineReadCapability } from "../../capabilities/runtime/dispatcher.js";
9
9
  import { TaskContextRepository } from "../task-context-repository.js";
10
10
  import { TaskDependencyService } from "../task-dependency-service.js";
11
11
  import { TaskCriterionReviewRepository } from "../task-criterion-review-repository.js";
@@ -105,6 +105,7 @@ function registerTaskReadCapabilities(dispatcher) {
105
105
  return {
106
106
  ok: true,
107
107
  ...projector.project(task),
108
+ phaseChanges: tasks.phaseChanges(id),
108
109
  waits: runs.listActiveWaits(id),
109
110
  runs: runs.listByTask(id),
110
111
  receipts: runs.listReceipts(id),
@@ -2,9 +2,9 @@ import { TaskCommandRequestSchema, TaskCreateRequestSchema, TaskDetailResponseSc
2
2
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
3
  import { TaskRepository, init_task_repository } from "../task-repository.js";
4
4
  import { TaskRunRepository, init_task_run_repository } from "../task-run-repository.js";
5
+ import { resolveTaskLocale } from "../task-language.js";
5
6
  import { CapabilityError } from "../../capabilities/runtime/errors.js";
6
7
  import { defineAtomicCapability } from "../../capabilities/runtime/dispatcher.js";
7
- import { resolveTaskLocale } from "../task-language.js";
8
8
  import { resolveProjectAgentId } from "../../projects/project-agent.js";
9
9
  import { resolveResponseLanguageForSession } from "../../agent/prompt/response-language.js";
10
10
  import { TaskApplicationService } from "../task-application-service.js";
@@ -101,14 +101,14 @@ function registerTaskWriteCapabilities(dispatcher, deps) {
101
101
  idempotencyKey: context.idempotencyKey,
102
102
  actor: context.actor
103
103
  });
104
- if (result.ok && input.command.type === "close" && input.command.resolution === "done") new TaskSignalService().dependencyClosed(input.taskId);
104
+ if (result.ok && result.model.task.phase === "closed" && result.model.task.resolution === "done") new TaskSignalService().dependencyClosed(input.taskId);
105
105
  return result;
106
106
  },
107
107
  async afterCommit(result, input) {
108
108
  if (!result.ok) return;
109
109
  const command = input.command;
110
110
  const denied = command.type === "resolve_wait" && command.resolution?.kind === "task_approval" && command.resolution.decision === "deny";
111
- if (command.type === "add_wait" && command.wait.kind === "paused" || command.type === "close" || denied) {
111
+ if (command.type === "add_wait" && command.wait.kind === "paused" || command.type === "close" && command.resolution !== "done" || denied) {
112
112
  const activeRun = new TaskRunRepository().getActiveRoot(input.taskId);
113
113
  if (activeRun?.conversationId && new TaskRepository().get(input.taskId)?.version === result.model.task.version) await deps.abortConversation?.(activeRun.conversationId);
114
114
  }
@@ -1,4 +1,4 @@
1
- import type { ActorRef, TaskCommand, TaskCreateRequest, TaskRunReceipt } from '@xopcai/gateway-contract';
1
+ import type { ActorRef, TaskCommand, TaskChangeSource, TaskCreateRequest, TaskRunReceipt } from '@xopcai/gateway-contract';
2
2
  import { type TaskReadModel } from './task-read-model-projector.js';
3
3
  import type { TurnContextRef } from '../agent/source-context/types.js';
4
4
  export type TaskApplicationResult = {
@@ -37,6 +37,7 @@ export declare class TaskApplicationService {
37
37
  command: TaskCommand;
38
38
  actor?: ActorRef;
39
39
  triggerContext?: Record<string, unknown>;
40
+ source?: TaskChangeSource;
40
41
  }): TaskApplicationResult;
41
42
  completeRun(input: {
42
43
  runId: string;
@@ -270,7 +270,10 @@ var TaskApplicationService = class {
270
270
  let current = task.phase === "closed" ? this.#tasks.setLifecycle({
271
271
  taskId: task.id,
272
272
  expectedVersion: task.version,
273
- phase: "ready"
273
+ phase: "ready",
274
+ actor,
275
+ source: "api",
276
+ operationId: input.idempotencyKey
274
277
  }) : task;
275
278
  const contract = task.contract;
276
279
  const originalBody = db.prepare("SELECT original_body FROM task_work_revisions WHERE task_id = ? AND original_body IS NOT NULL ORDER BY contract_version LIMIT 1").get(task.id);
@@ -305,6 +308,7 @@ var TaskApplicationService = class {
305
308
  VALUES (?, ?, ?, ?, ?, ?, (SELECT request_input_id FROM task_origin_links WHERE task_id = ?), ?, ?, ?, ?, ?)`).run(randomUUID(), task.id, current.latestContractVersion, baseline.deliveryId, input.baselineVersion, entry.id, task.id, input.idempotencyKey, hash, JSON.stringify(input.supersedesEntryIds ?? []), originalBody ? null : task.body ?? contract.objective, Date.now());
306
309
  db.prepare("UPDATE task_sessions SET status = 'superseded', ended_at = ? WHERE task_id = ? AND role = 'execution' AND status = 'active'").run(Date.now(), task.id);
307
310
  db.prepare("UPDATE task_conversation_state SET active_conversation_id = NULL, current_executor_agent_id = NULL, status = 'idle', updated_at = ? WHERE task_id = ?").run(Date.now(), task.id);
311
+ this.#tasks.authorizeAutomaticPhase(task.id);
308
312
  const allocation = new TaskAllocationRepository();
309
313
  const previous = allocation.get(task.id);
310
314
  if (previous) db.prepare(`UPDATE task_allocations SET id = ?, status = 'pending', attempts = 0, selected_agent_id = NULL,
@@ -350,18 +354,44 @@ var TaskApplicationService = class {
350
354
  ok: true,
351
355
  model
352
356
  };
357
+ if (actor.kind !== "user" && [
358
+ "move",
359
+ "mark_ready",
360
+ "request_review",
361
+ "close",
362
+ "reopen"
363
+ ].includes(input.command.type) && !this.#tasks.automaticStartAllowed(task.id)) return {
364
+ ok: false,
365
+ reason: "blocked",
366
+ model
367
+ };
353
368
  return runSqliteWriteTransaction((db) => {
369
+ const lifecycle = (phase, resolution) => this.lifecycle(task.id, task.version, phase, resolution, {
370
+ actor,
371
+ source: input.source ?? (actor.kind === "user" ? "api" : "runtime"),
372
+ operationId: input.idempotencyKey,
373
+ manual: actor.kind === "user",
374
+ runId: this.#runs.getActiveRoot(task.id)?.id
375
+ });
354
376
  let result;
355
377
  switch (input.command.type) {
356
378
  case "move":
357
- result = task.phase !== "closed" && task.phase !== input.command.phase && !this.#runs.getActiveRoot(task.id) && this.#runs.listActiveWaits(task.id).length === 0 ? this.lifecycle(task.id, task.version, input.command.phase) : {
379
+ if (actor.kind !== "user" && input.command.phase === "closed" && (input.command.resolution ?? "done") === "done" && (!new TaskCriterionReviewRepository().allPassed(task) || this.#runs.getActiveRoot(task.id) || this.#runs.listActiveWaits(task.id).length)) {
380
+ result = {
381
+ ok: false,
382
+ reason: "blocked",
383
+ model
384
+ };
385
+ break;
386
+ }
387
+ result = task.phase !== input.command.phase ? lifecycle(input.command.phase, input.command.phase === "closed" ? input.command.resolution ?? "done" : void 0) : {
358
388
  ok: false,
359
389
  reason: "invalid_transition",
360
390
  model
361
391
  };
362
392
  break;
363
393
  case "mark_ready":
364
- result = task.phase === "backlog" ? this.lifecycle(task.id, task.version, "ready") : {
394
+ result = task.phase === "backlog" ? lifecycle("ready") : {
365
395
  ok: false,
366
396
  reason: "invalid_transition",
367
397
  model
@@ -404,21 +434,21 @@ var TaskApplicationService = class {
404
434
  });
405
435
  break;
406
436
  case "request_review":
407
- result = task.phase === "active" && !this.#runs.getActiveRoot(task.id) && this.#runs.listActiveWaits(task.id).length === 0 ? this.lifecycle(task.id, task.version, "review") : {
437
+ result = task.phase === "active" && !this.#runs.getActiveRoot(task.id) && this.#runs.listActiveWaits(task.id).length === 0 ? lifecycle("review") : {
408
438
  ok: false,
409
439
  reason: "invalid_transition",
410
440
  model
411
441
  };
412
442
  break;
413
443
  case "close":
414
- result = input.command.resolution === "done" && (!new TaskCriterionReviewRepository().allPassed(task) || this.#runs.getActiveRoot(task.id) !== void 0 || this.#runs.listActiveWaits(task.id).length > 0) ? {
444
+ result = actor.kind !== "user" && input.command.resolution === "done" && (!new TaskCriterionReviewRepository().allPassed(task) || this.#runs.getActiveRoot(task.id) !== void 0 || this.#runs.listActiveWaits(task.id).length > 0) ? {
415
445
  ok: false,
416
446
  reason: "blocked",
417
447
  model
418
- } : this.lifecycle(task.id, task.version, "closed", input.command.resolution);
448
+ } : lifecycle("closed", input.command.resolution);
419
449
  break;
420
450
  case "reopen":
421
- result = task.phase === "closed" ? this.lifecycle(task.id, task.version, input.command.phase) : {
451
+ result = task.phase === "closed" ? lifecycle(input.command.phase) : {
422
452
  ok: false,
423
453
  reason: "invalid_transition",
424
454
  model
@@ -460,13 +490,21 @@ var TaskApplicationService = class {
460
490
  reason: "not_found",
461
491
  model
462
492
  };
463
- else if (wait.status !== "active" || task.phase === "closed" || wait.condition.type === "connection") result = {
493
+ else if (wait.status !== "active" || task.phase === "closed" && task.resolution !== "done" || wait.condition.type === "connection") result = {
464
494
  ok: false,
465
495
  reason: "invalid_transition",
466
496
  model
467
497
  };
468
498
  else {
469
499
  const response = input.command.resolution;
500
+ if (wait.kind === "approval" && response?.kind !== "task_approval" || wait.kind === "user_input" && response?.kind !== "user_answer") {
501
+ result = {
502
+ ok: false,
503
+ reason: "invalid_transition",
504
+ model
505
+ };
506
+ break;
507
+ }
470
508
  if (response?.kind === "task_approval") {
471
509
  if (actor.kind !== "user" || wait.kind !== "approval" || typeof wait.condition.capability !== "string" || response.decision !== "approve" && response.decision !== "deny") {
472
510
  result = {
@@ -537,7 +575,7 @@ var TaskApplicationService = class {
537
575
  resolution: input.command.resolution
538
576
  });
539
577
  const executor = TaskExecutorSelectionSchema.safeParse(wait.condition.executor);
540
- result = response?.kind === "task_approval" && executor.success && !this.#runs.getActiveRoot(task.id) && this.#runs.listActiveWaits(task.id).length === 0 ? this.start(task.id, task.version, executor.data, {
578
+ result = task.phase !== "closed" && response?.kind === "task_approval" && executor.success && !this.#runs.getActiveRoot(task.id) && this.#runs.listActiveWaits(task.id).length === 0 ? this.start(task.id, task.version, executor.data, {
541
579
  idempotencyKey: input.idempotencyKey,
542
580
  actor,
543
581
  correlationId: input.idempotencyKey
@@ -606,6 +644,8 @@ var TaskApplicationService = class {
606
644
  title: result.model.task.title
607
645
  },
608
646
  taskId: task.id,
647
+ actor,
648
+ source: input.source ?? (actor.kind === "user" ? "api" : "runtime"),
609
649
  from: task.phase,
610
650
  to: result.model.task.phase,
611
651
  resolution: result.model.task.resolution,
@@ -647,7 +687,7 @@ var TaskApplicationService = class {
647
687
  };
648
688
  const task = this.#tasks.require(run.taskId);
649
689
  const activeConversationId = new TaskConversationRepository().getState(task.id)?.activeConversationId;
650
- if (run.parentRunId || task.phase === "closed" || this.#runs.listActiveWaits(task.id).length > 0 || run.conversationId && activeConversationId && run.conversationId !== activeConversationId || run.contractVersion !== task.latestContractVersion) {
690
+ if (run.parentRunId || task.phase === "closed" && task.resolution !== "done" || this.#runs.listActiveWaits(task.id).length > 0 || run.conversationId && activeConversationId && run.conversationId !== activeConversationId || run.contractVersion !== task.latestContractVersion) {
651
691
  enqueueTaskChangedEvent(db, {
652
692
  taskId: task.id,
653
693
  projectId: task.projectId,
@@ -671,6 +711,19 @@ var TaskApplicationService = class {
671
711
  idempotencyKey: `task-run-receipt:${run.id}`
672
712
  });
673
713
  if (input.receipt.status === "succeeded" || input.receipt.status === "failed") new TaskResultDeliveryRepository().enqueue(run.id, input.receipt.summary, input.receipt.status, input.resultText);
714
+ if (!this.#tasks.runPhaseUnchanged(task.id, run.id) || task.phase === "closed") {
715
+ enqueueTaskChangedEvent(db, {
716
+ taskId: task.id,
717
+ projectId: task.projectId,
718
+ version: task.version,
719
+ changedFields: ["runs", "receipts"],
720
+ source: "runtime"
721
+ });
722
+ return {
723
+ ok: true,
724
+ model: this.#projector.project(task)
725
+ };
726
+ }
674
727
  if (input.receipt.status !== "succeeded") {
675
728
  const model = this.#projector.project(task);
676
729
  if (!input.suppressAttention) enqueueTaskAttentionRequiredEvent(db, {
@@ -705,6 +758,9 @@ var TaskApplicationService = class {
705
758
  const updated = this.#tasks.setLifecycle({
706
759
  taskId: task.id,
707
760
  expectedVersion: task.version,
761
+ actor: input.actor ?? { kind: "system" },
762
+ source: "runtime",
763
+ runId: run.id,
708
764
  phase,
709
765
  ...phase === "closed" ? { resolution: "done" } : {}
710
766
  });
@@ -715,6 +771,8 @@ var TaskApplicationService = class {
715
771
  title: updated.title
716
772
  },
717
773
  taskId: updated.id,
774
+ actor: input.actor ?? { kind: "system" },
775
+ source: "runtime",
718
776
  from: task.phase,
719
777
  to: updated.phase,
720
778
  resolution: updated.resolution,
@@ -750,6 +808,11 @@ var TaskApplicationService = class {
750
808
  ok: false,
751
809
  reason: "not_found"
752
810
  };
811
+ if (options.actor.kind !== "user" && !this.#tasks.automaticStartAllowed(taskId)) return {
812
+ ok: false,
813
+ reason: "blocked",
814
+ model: this.#projector.project(task)
815
+ };
753
816
  const allocation = new TaskAllocationRepository().get(taskId);
754
817
  if (allocation && allocation.status !== "assigned" && !(options.actor.kind === "system" && options.actor.id === "task-router")) return {
755
818
  ok: false,
@@ -805,6 +868,7 @@ var TaskApplicationService = class {
805
868
  model: this.#projector.get(taskId)
806
869
  };
807
870
  }
871
+ if (options.actor.kind === "user") this.#tasks.authorizeAutomaticPhase(taskId);
808
872
  const run = this.#runs.create({
809
873
  taskId,
810
874
  executorKind: executor.kind,
@@ -823,7 +887,10 @@ var TaskApplicationService = class {
823
887
  const active = task.phase === "active" ? task : this.#tasks.setLifecycle({
824
888
  taskId,
825
889
  expectedVersion: task.version,
826
- phase: "active"
890
+ phase: "active",
891
+ actor: options.actor,
892
+ source: "runtime",
893
+ runId: run.id
827
894
  });
828
895
  if (!active) throw new Error("Task changed while its run was being created");
829
896
  return {
@@ -832,8 +899,9 @@ var TaskApplicationService = class {
832
899
  runId: run.id
833
900
  };
834
901
  }
835
- lifecycle(taskId, expectedVersion, phase, resolution) {
902
+ lifecycle(taskId, expectedVersion, phase, resolution, metadata = {}) {
836
903
  const updated = this.#tasks.setLifecycle({
904
+ ...metadata,
837
905
  taskId,
838
906
  expectedVersion,
839
907
  phase,
@@ -25,7 +25,8 @@ var TaskCollaborationDelivery = class {
25
25
  for (const pending of this.#entries.pendingDeliveries(limit)) {
26
26
  const { entry, clientMessageId } = pending;
27
27
  const task = this.#tasks.get(entry.taskId);
28
- if (!task || task.phase === "closed") {
28
+ const answersExistingWait = entry.kind === "answer" && entry.causationId && this.#runs.listActiveWaits(entry.taskId).some((wait) => wait.condition.collaborationEntryId === entry.causationId);
29
+ if (!task || task.phase === "closed" && (task.resolution !== "done" || !answersExistingWait)) {
29
30
  this.#entries.markStale(entry.id);
30
31
  continue;
31
32
  }
@@ -28,8 +28,9 @@ function taskIdForSession(conversationId) {
28
28
  function getTaskExecutionBrief(taskId) {
29
29
  if (!isXopcDatabaseOpen()) return void 0;
30
30
  const task = new TaskRepository().get(taskId);
31
- if (!task?.contract || task.phase === "closed") return void 0;
31
+ if (!task?.contract) return void 0;
32
32
  const runs = new TaskRunRepository();
33
+ if (task.phase === "closed" && (task.resolution !== "done" || !runs.getActiveRoot(taskId))) return void 0;
33
34
  if (runs.listActiveWaits(taskId).some((wait) => wait.kind === "paused")) return void 0;
34
35
  const latestRun = runs.getLatestRoot(taskId);
35
36
  const latestReceipt = latestRun?.contractVersion === task.latestContractVersion ? runs.getReceipt(latestRun.id) : void 0;
@@ -76,7 +76,7 @@ var TaskReadModelProjector = class {
76
76
  task,
77
77
  allocation,
78
78
  operationalState: task.phase !== "closed" && !paused && !activeRun && waits.length === 0 && allocation ? allocating ? "allocating" : allocation.status === "blocked" ? "blocked" : allocation.status === "failed" ? "failed" : executionState : executionState,
79
- attention: task.phase === "closed" || paused ? [] : attention,
79
+ attention: task.phase === "closed" && (task.resolution !== "done" || waits.length === 0) || paused ? [] : attention,
80
80
  allowedCommands,
81
81
  ...revisionBaseline ? { revisionBaseline } : {}
82
82
  };
@@ -93,7 +93,7 @@ var TaskReadModelProjector = class {
93
93
  };
94
94
  }
95
95
  operationalState(input) {
96
- if (input.task.phase === "closed") return "idle";
96
+ if (input.task.phase === "closed" && (input.task.resolution !== "done" || !input.activeRun && input.waits.length === 0)) return "idle";
97
97
  if (input.waits.some((wait) => wait.kind === "paused")) return "waiting";
98
98
  if (input.activeRun?.status === "running") return "running";
99
99
  if (input.activeRun?.status === "verifying") return "verifying";
@@ -107,10 +107,18 @@ var TaskReadModelProjector = class {
107
107
  return "idle";
108
108
  }
109
109
  allowedCommands(task, activeRunStatus, hasWaits, paused) {
110
- if (task.phase === "closed") return ["reopen"];
111
- const commands = ["revise_contract", "close"];
110
+ if (task.phase === "closed") return [
111
+ "move",
112
+ "reopen",
113
+ ...activeRunStatus ? ["close"] : [],
114
+ ...task.resolution === "done" && hasWaits ? ["resolve_wait"] : []
115
+ ];
116
+ const commands = [
117
+ "move",
118
+ "revise_contract",
119
+ "close"
120
+ ];
112
121
  if (!paused) commands.push("add_wait");
113
- if (!activeRunStatus && !hasWaits) commands.unshift("move");
114
122
  if (hasWaits) commands.unshift("resolve_wait");
115
123
  if (task.phase === "backlog") commands.unshift("mark_ready");
116
124
  if (!activeRunStatus && !hasWaits && task.phase !== "backlog") commands.unshift("start");
@@ -1,4 +1,4 @@
1
- import type { ActorRef, Task, TaskAcceptancePolicy, TaskContract, TaskPhase, TaskPriority, TaskResolution } from '@xopcai/gateway-contract';
1
+ import type { ActorRef, Task, TaskAcceptancePolicy, TaskContract, TaskPhase, TaskPriority, TaskResolution, TaskPhaseChange, TaskChangeSource } from '@xopcai/gateway-contract';
2
2
  export type TaskExecutionSource = 'chat' | 'cli' | 'cron' | 'workflow' | 'channel' | 'api';
3
3
  export type TaskUiLocale = 'en' | 'zh';
4
4
  export type TaskAggregate = Task;
@@ -65,7 +65,17 @@ export declare class TaskRepository {
65
65
  phase: TaskPhase;
66
66
  resolution?: TaskResolution;
67
67
  now?: number;
68
+ actor?: ActorRef;
69
+ source?: TaskChangeSource;
70
+ operationId?: string;
71
+ runId?: string;
72
+ manual?: boolean;
68
73
  }): TaskAggregate | undefined;
74
+ phaseChanges(taskId: string): TaskPhaseChange[];
75
+ /** A new explicit execution authorizes automation for the current manual revision. */
76
+ authorizeAutomaticPhase(taskId: string): void;
77
+ automaticStartAllowed(taskId: string): boolean;
78
+ runPhaseUnchanged(taskId: string, runId: string): boolean;
69
79
  reorder(input: {
70
80
  taskId: string;
71
81
  expectedVersion: number;