@xopcai/xopc 0.0.312 → 0.0.314

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 (497) hide show
  1. package/dist/browser-ext/dist/assets/{auth-C3yV1y_l.js → auth-DKo-NMUY.js} +18 -1
  2. package/dist/browser-ext/dist/background.js +68 -2
  3. package/dist/browser-ext/dist/sidepanel.html +1 -1
  4. package/dist/browser-ext/dist/sidepanel.js +1 -1
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  7. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  8. package/dist/extensions/telegram/src/plugin.js +2 -2
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BVIJMP8w.js → agent-avatar-dicebear-BFkjfurL.js} +1 -1
  11. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BdOZ6q8Z.js +1 -0
  12. package/dist/gateway/static/root/assets/{agents-D6g_SeWI.js → agents-CCcavsHq.js} +1 -1
  13. package/dist/gateway/static/root/assets/{api-_aHQA8bd.js → api-BYhRsTAc.js} +1 -1
  14. package/dist/gateway/static/root/assets/{app-link-CKueEVbT.js → app-link-nL8iPwEr.js} +1 -1
  15. package/dist/gateway/static/root/assets/{app-management-settings-panel-CLg_aXYG.js → app-management-settings-panel-B4kihr-A.js} +1 -1
  16. package/dist/gateway/static/root/assets/appearance-settings-N9sYmNOx.js +1 -0
  17. package/dist/gateway/static/root/assets/apps-page-BMcy10_s.js +1 -0
  18. package/dist/gateway/static/root/assets/{archive-plugin-CHO3heHX.js → archive-plugin-k_SuYWyV.js} +1 -1
  19. package/dist/gateway/static/root/assets/{attachment-load-BsmsBCI2.js → attachment-load-DRv5QWUK.js} +1 -1
  20. package/dist/gateway/static/root/assets/{automations-page-CftigJlf.js → automations-page-CkJV3DN0.js} +1 -1
  21. package/dist/gateway/static/root/assets/automations-workspace-BEa2doeR.js +7 -0
  22. package/dist/gateway/static/root/assets/{binary-plugins-CRCLWBo2.js → binary-plugins-Dg3h3TA7.js} +1 -1
  23. package/dist/gateway/static/root/assets/{block-editor-D0LDiOTT.js → block-editor-DVhdHntT.js} +29 -29
  24. package/dist/gateway/static/root/assets/{browser-automation-inputs-C611KRBx.js → browser-automation-inputs-BMRYUW8_.js} +1 -1
  25. package/dist/gateway/static/root/assets/{browser-automations-page-Djyv3vy-.js → browser-automations-page-Byv6-FY2.js} +2 -2
  26. package/dist/gateway/static/root/assets/browser-settings-page-DRCHGFpO.js +3 -0
  27. package/dist/gateway/static/root/assets/capabilities-D0S3DuAD.js +1 -0
  28. package/dist/gateway/static/root/assets/capabilities-settings-panel-mxRP0gl0.js +8 -0
  29. package/dist/gateway/static/root/assets/channels-settings-DBt_6GsB.js +1 -0
  30. package/dist/gateway/static/root/assets/{chat-terminal-dock-CIsKqdET.js → chat-terminal-dock-D4AHa51o.js} +2 -2
  31. package/dist/gateway/static/root/assets/{computer-settings-page-C0YL9J7m.js → computer-settings-page-eXPe500D.js} +1 -1
  32. package/dist/gateway/static/root/assets/connector-service-page-BQTFlq_k.js +1 -0
  33. package/dist/gateway/static/root/assets/connectors-page-BKeBWwcI.js +2 -0
  34. package/dist/gateway/static/root/assets/conversation-identity-Cw0n9uzK.js +1 -0
  35. package/dist/gateway/static/root/assets/{date-picker-CDsfv8R0.js → date-picker-7MtovynY.js} +1 -1
  36. package/dist/gateway/static/root/assets/{dependency-picker-DvhPj3CZ.js → dependency-picker-Bj_xkXID.js} +1 -1
  37. package/dist/gateway/static/root/assets/{desktop-pet-Cyg8XMpL.js → desktop-pet-CTmba9zH.js} +1 -1
  38. package/dist/gateway/static/root/assets/desktop-pet-settings-DNM_BlWN.js +1 -0
  39. package/dist/gateway/static/root/assets/device-pairing-wizard-C2XE0QhT.js +1 -0
  40. package/dist/gateway/static/root/assets/{extension-debug-page-D-AVJU3q.js → extension-debug-page-J_olaL7e.js} +1 -1
  41. package/dist/gateway/static/root/assets/{extension-page-DrFoQ9xt.js → extension-page-pK5RvqN8.js} +1 -1
  42. package/dist/gateway/static/root/assets/{extension-settings-page-DxWjESC1.js → extension-settings-page-BwroEN08.js} +1 -1
  43. package/dist/gateway/static/root/assets/files-BK6enEvD.js +1 -0
  44. package/dist/gateway/static/root/assets/{gateway-config-swr-DUDX42qY.js → gateway-config-swr-FuJTIg_a.js} +1 -1
  45. package/dist/gateway/static/root/assets/gateway-settings-CLLDp23J.js +1 -0
  46. package/dist/gateway/static/root/assets/{gateway-startup-retry-Cf8OxlvY.js → gateway-startup-retry-CKg_gu8_.js} +1 -1
  47. package/dist/gateway/static/root/assets/home-page-B5Epb1PH.js +1 -0
  48. package/dist/gateway/static/root/assets/{image-generation-api-D2YorS--.js → image-generation-api-Bo6NZ7zb.js} +1 -1
  49. package/dist/gateway/static/root/assets/{imports-page-BKucJlXI.js → imports-page-C8-hX8gS.js} +1 -1
  50. package/dist/gateway/static/root/assets/index-14F1yGJI.js +89 -0
  51. package/dist/gateway/static/root/assets/index-cB7rWIDY.css +1 -0
  52. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BxLXD-yU.js → keyboard-shortcuts-settings-BkBEjUZD.js} +1 -1
  53. package/dist/gateway/static/root/assets/local-app-workbench-page-6jC3vQpY.js +2 -0
  54. package/dist/gateway/static/root/assets/{local-apps-page-BAsQJQKJ.js → local-apps-page-CrbKIixo.js} +1 -1
  55. package/dist/gateway/static/root/assets/{locale-store-DA0Z5jM_.js → locale-store-CvGwNbml.js} +1 -1
  56. package/dist/gateway/static/root/assets/logs-page-DBHlZts9.js +2 -0
  57. package/dist/gateway/static/root/assets/management-settings-DsUWLu5m.js +1 -0
  58. package/dist/gateway/static/root/assets/{markdown-view-DYGPxPee.js → markdown-view-nXo5nrsv.js} +1 -1
  59. package/dist/gateway/static/root/assets/{media-plugins-CQtQzLyg.js → media-plugins-upxXJ-4l.js} +1 -1
  60. package/dist/gateway/static/root/assets/messages-B_AwRroN.js +3 -0
  61. package/dist/gateway/static/root/assets/note-detail-panel-0Q9TOtJG.js +5 -0
  62. package/dist/gateway/static/root/assets/notes-page-D0NmcwNw.js +8 -0
  63. package/dist/gateway/static/root/assets/page-context-capture-button-DUyA-K4L.js +1 -0
  64. package/dist/gateway/static/root/assets/{page-tabs-B6DjkyMM.js → page-tabs-Cl-NFPNr.js} +1 -1
  65. package/dist/gateway/static/root/assets/{preview-open-alternatives-Dn57uLhr.js → preview-open-alternatives-DX81PwJ3.js} +1 -1
  66. package/dist/gateway/static/root/assets/product-delivery-chCjIpvu.js +1 -0
  67. package/dist/gateway/static/root/assets/{product-open-page-H2YMk8TY.js → product-open-page-CrfIGwm8.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-BVfVrYmn.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-nM9a9XNS.js +1 -0
  70. package/dist/gateway/static/root/assets/{registry-api-C0DCx3wv.js → registry-api-CHxgohY0.js} +1 -1
  71. package/dist/gateway/static/root/assets/remote-access-hub-C8b_k88G.js +1 -0
  72. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-D3dLOW04.js +5 -0
  73. package/dist/gateway/static/root/assets/scenes-page-DEowreZV.js +2 -0
  74. package/dist/gateway/static/root/assets/{schema-form-CblI9WUA.js → schema-form-ZxuIvD2_.js} +1 -1
  75. package/dist/gateway/static/root/assets/schemas-88fK3zzl.js +64 -0
  76. package/dist/gateway/static/root/assets/sessions-page-B_nPhera.js +1 -0
  77. package/dist/gateway/static/root/assets/settings-advanced-gate-BqhIOuus.js +1 -0
  78. package/dist/gateway/static/root/assets/{settings-form-section-BAaVyxJH.js → settings-form-section-TZRfg4yo.js} +1 -1
  79. package/dist/gateway/static/root/assets/{settings-page-CKNPbm5q.js → settings-page-a8qcJpdZ.js} +1 -1
  80. package/dist/gateway/static/root/assets/{settings-page-layout-DqNCGKxQ.js → settings-page-layout-BfvlRT9q.js} +1 -1
  81. package/dist/gateway/static/root/assets/setup-status-panel-CRj5Ruqn.js +1 -0
  82. package/dist/gateway/static/root/assets/{share-preview-page-BzMfp_HM.js → share-preview-page-DCt1pTWB.js} +1 -1
  83. package/dist/gateway/static/root/assets/shares-settings-BNbXPk--.js +1 -0
  84. package/dist/gateway/static/root/assets/skill-reload-api-CNMCLbav.js +1 -0
  85. package/dist/gateway/static/root/assets/{skills-page-DIht92q6.js → skills-page-BIOcg44X.js} +1 -1
  86. package/dist/gateway/static/root/assets/{skills-page.utils-DLYRiEn3.js → skills-page.utils-CgZdzT4I.js} +1 -1
  87. package/dist/gateway/static/root/assets/{system-settings-panel-yYs4YgYk.js → system-settings-panel-_YaRncA6.js} +1 -1
  88. package/dist/gateway/static/root/assets/task-detail-page-CAcfAG-c.js +1 -0
  89. package/dist/gateway/static/root/assets/tasks-CDR_RVbQ.js +1 -0
  90. package/dist/gateway/static/root/assets/{tunnel-api-BasDYxvx.js → tunnel-api-uOupJOoS.js} +1 -1
  91. package/dist/gateway/static/root/assets/turn-outcome-D0SnyZ3Z.js +1 -0
  92. package/dist/gateway/static/root/assets/{use-autosave-CWAUHhcb.js → use-autosave-BezzHBLE.js} +1 -1
  93. package/dist/gateway/static/root/assets/user-model-page-BFFeneDq.js +2 -0
  94. package/dist/gateway/static/root/assets/{voice-api-key-field-Kc4UlxZs.js → voice-api-key-field-BmYifdwL.js} +1 -1
  95. package/dist/gateway/static/root/assets/{voice-config-api-DTyMdGOR.js → voice-config-api-D_5Q2_A3.js} +1 -1
  96. package/dist/gateway/static/root/assets/{work-discovery-overlay-BPC_c9dO.js → work-discovery-overlay-4DmyEckJ.js} +1 -1
  97. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DBTciOrq.js → workflow-run-setup-panel-DeZe8bTZ.js} +2 -2
  98. package/dist/gateway/static/root/assets/workflows-page-Sv4hEc6W.js +6 -0
  99. package/dist/gateway/static/root/index.html +16 -16
  100. package/dist/package.js +1 -1
  101. package/dist/packages/computer-control-contract/src/index.js +10 -1
  102. package/dist/packages/gateway-contract/src/app-context.js +55 -0
  103. package/dist/packages/gateway-contract/src/automations.js +16 -17
  104. package/dist/packages/gateway-contract/src/capabilities.js +1078 -0
  105. package/dist/packages/gateway-contract/src/extension-capabilities.js +26 -0
  106. package/dist/packages/gateway-contract/src/home.js +3 -3
  107. package/dist/packages/gateway-contract/src/index.js +8 -0
  108. package/dist/packages/gateway-contract/src/product-delivery.js +19 -4
  109. package/dist/packages/gateway-contract/src/scenes.js +199 -0
  110. package/dist/packages/gateway-contract/src/task-runs.js +8 -4
  111. package/dist/packages/gateway-contract/src/tasks.js +5 -4
  112. package/dist/packages/realtime-client/src/index.js +17 -4
  113. package/dist/src/agent/agent-manager.d.ts +1 -0
  114. package/dist/src/agent/agent-manager.js +1 -0
  115. package/dist/src/agent/child-agent-factory.d.ts +2 -0
  116. package/dist/src/agent/child-agent-factory.js +5 -0
  117. package/dist/src/agent/commands/approved-verification.d.ts +14 -0
  118. package/dist/src/agent/commands/approved-verification.js +48 -0
  119. package/dist/src/agent/context/execution-scope.js +2 -1
  120. package/dist/src/agent/context/project-context.js +2 -1
  121. package/dist/src/agent/external-tools/cliProvider.js +123 -75
  122. package/dist/src/agent/external-tools/composio-provider.d.ts +1 -1
  123. package/dist/src/agent/external-tools/composio-provider.js +70 -12
  124. package/dist/src/agent/external-tools/endpoint-provider.js +14 -1
  125. package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -0
  126. package/dist/src/agent/inbound/turn-dispatcher.js +2 -1
  127. package/dist/src/agent/memory/compaction-chunks.d.ts +6 -1
  128. package/dist/src/agent/memory/compaction-chunks.js +16 -3
  129. package/dist/src/agent/memory/compaction-ledger.d.ts +3 -1
  130. package/dist/src/agent/memory/compaction-ledger.js +31 -18
  131. package/dist/src/agent/memory/compaction-request.d.ts +2 -0
  132. package/dist/src/agent/memory/compaction-request.js +6 -1
  133. package/dist/src/agent/memory/compaction.d.ts +19 -1
  134. package/dist/src/agent/memory/compaction.js +112 -30
  135. package/dist/src/agent/service/process-direct-streaming.d.ts +3 -0
  136. package/dist/src/agent/service/process-direct-streaming.js +19 -10
  137. package/dist/src/agent/service.js +1 -0
  138. package/dist/src/agent/service.types.d.ts +1 -0
  139. package/dist/src/agent/skills/config.js +2 -0
  140. package/dist/src/agent/skills/format-skills-prompt.js +14 -1
  141. package/dist/src/agent/skills/index.js +16 -8
  142. package/dist/src/agent/skills/types.d.ts +1 -1
  143. package/dist/src/agent/source-context/app-context.d.ts +4 -0
  144. package/dist/src/agent/source-context/app-context.js +36 -0
  145. package/dist/src/agent/source-context/injector.js +1 -0
  146. package/dist/src/agent/source-context/types.d.ts +5 -1
  147. package/dist/src/agent/tasks/task-judge-service.js +2 -1
  148. package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
  149. package/dist/src/agent/tool-manuals/computer.js +1 -1
  150. package/dist/src/agent/tools/automation-tool.d.ts +12 -1
  151. package/dist/src/agent/tools/automation-tool.js +106 -32
  152. package/dist/src/agent/tools/factory.d.ts +1 -0
  153. package/dist/src/agent/tools/factory.js +6 -1
  154. package/dist/src/agent/tools/scoped-workspace-tools.d.ts +8 -0
  155. package/dist/src/agent/tools/scoped-workspace-tools.js +81 -0
  156. package/dist/src/agent/tools/xopc-use-tool.d.ts +6 -3
  157. package/dist/src/agent/tools/xopc-use-tool.js +997 -908
  158. package/dist/src/agent/workflow/subagent-runner.js +1 -0
  159. package/dist/src/agent-config/index.js +2 -2
  160. package/dist/src/agent-config/schema.d.ts +5 -0
  161. package/dist/src/agent-config/schema.js +14 -10
  162. package/dist/src/automations/api/routes.js +244 -164
  163. package/dist/src/automations/capabilities/drafts.d.ts +4 -0
  164. package/dist/src/automations/capabilities/drafts.js +95 -0
  165. package/dist/src/automations/capabilities/read.d.ts +4 -0
  166. package/dist/src/automations/capabilities/read.js +119 -0
  167. package/dist/src/automations/capabilities/write.d.ts +349 -0
  168. package/dist/src/automations/capabilities/write.js +172 -0
  169. package/dist/src/automations/domain/index.js +2 -2
  170. package/dist/src/automations/domain/validation.d.ts +77 -77
  171. package/dist/src/automations/domain/validation.js +9 -6
  172. package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
  173. package/dist/src/automations/index.js +6 -6
  174. package/dist/src/automations/service/automation-service.d.ts +31 -0
  175. package/dist/src/automations/service/automation-service.js +213 -75
  176. package/dist/src/automations/service/index.js +2 -2
  177. package/dist/src/automations/storage/automation-repository.d.ts +2 -0
  178. package/dist/src/automations/storage/automation-repository.js +9 -1
  179. package/dist/src/automations/storage/automation-run-repository.d.ts +4 -1
  180. package/dist/src/automations/storage/automation-run-repository.js +16 -3
  181. package/dist/src/automations/storage/index.js +3 -3
  182. package/dist/src/browser/automations/schema.d.ts +1 -1
  183. package/dist/src/browser/automations/service.d.ts +1 -1
  184. package/dist/src/browser/observation/format.js +4 -0
  185. package/dist/src/capabilities/adapters/http.d.ts +4 -0
  186. package/dist/src/capabilities/adapters/http.js +44 -0
  187. package/dist/src/capabilities/readiness/from-config.js +11 -7
  188. package/dist/src/capabilities/runtime/app-context.d.ts +3 -0
  189. package/dist/src/capabilities/runtime/app-context.js +72 -0
  190. package/dist/src/capabilities/runtime/atomic-operations.d.ts +11 -0
  191. package/dist/src/capabilities/runtime/atomic-operations.js +34 -0
  192. package/dist/src/capabilities/runtime/dispatcher.d.ts +67 -0
  193. package/dist/src/capabilities/runtime/dispatcher.js +170 -0
  194. package/dist/src/capabilities/runtime/errors.d.ts +6 -0
  195. package/dist/src/capabilities/runtime/errors.js +11 -0
  196. package/dist/src/capabilities/runtime/external-operations.d.ts +16 -0
  197. package/dist/src/capabilities/runtime/external-operations.js +92 -0
  198. package/dist/src/capabilities/runtime/product.d.ts +12 -0
  199. package/dist/src/capabilities/runtime/product.js +69 -0
  200. package/dist/src/capabilities/runtime/settings.d.ts +3 -0
  201. package/dist/src/capabilities/runtime/settings.js +27 -0
  202. package/dist/src/channels/index.js +2 -2
  203. package/dist/src/channels/manager.js +1 -1
  204. package/dist/src/cli/cli-log-level-preset.d.ts +2 -0
  205. package/dist/src/cli/cli-log-level-preset.js +4 -0
  206. package/dist/src/cli/command-catalog.js +4 -0
  207. package/dist/src/cli/command-loaders.js +1 -0
  208. package/dist/src/cli/command-manifest.js +4 -0
  209. package/dist/src/cli/commands/channels.js +1 -1
  210. package/dist/src/cli/commands/connectors.js +1 -1
  211. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  212. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  213. package/dist/src/cli/commands/mcp.d.ts +1 -0
  214. package/dist/src/cli/commands/mcp.js +51 -0
  215. package/dist/src/cli/commands/models.js +1 -1
  216. package/dist/src/cli/commands/onboard.js +1 -1
  217. package/dist/src/cli/commands/project.js +1 -1
  218. package/dist/src/computer/broker.d.ts +0 -1
  219. package/dist/src/computer/broker.js +4 -6
  220. package/dist/src/computer/evaluation-harness.d.ts +45 -0
  221. package/dist/src/computer/evaluation-harness.js +108 -0
  222. package/dist/src/computer/model-adapter.d.ts +37 -2
  223. package/dist/src/computer/model-adapter.js +333 -42
  224. package/dist/src/computer/model-policy.d.ts +4 -1
  225. package/dist/src/computer/model-policy.js +11 -3
  226. package/dist/src/computer/release-gate.d.ts +22 -0
  227. package/dist/src/computer/release-gate.js +19 -0
  228. package/dist/src/computer/runtime.js +14 -10
  229. package/dist/src/computer/task-state.d.ts +1 -0
  230. package/dist/src/computer/task-state.js +1 -0
  231. package/dist/src/config/models-json.d.ts +14 -8
  232. package/dist/src/config/models-json.js +1 -1
  233. package/dist/src/config/schema.d.ts +4 -0
  234. package/dist/src/config/schema.js +3 -9
  235. package/dist/src/connectors/composio-sessions.d.ts +4 -2
  236. package/dist/src/connectors/composio-sessions.js +10 -9
  237. package/dist/src/connectors/composio.js +10 -8
  238. package/dist/src/discussions/action-tasks.js +2 -1
  239. package/dist/src/discussions/recording.js +1 -1
  240. package/dist/src/execution-environments/local-worktree-manager.d.ts +1 -0
  241. package/dist/src/execution-environments/local-worktree-manager.js +13 -2
  242. package/dist/src/extensions/activation-context.js +3 -3
  243. package/dist/src/extensions/api.js +1 -1
  244. package/dist/src/extensions/normalize-manifest.js +6 -1
  245. package/dist/src/extensions/sdk/index.js +1 -1
  246. package/dist/src/extensions/sdk/media.js +1 -1
  247. package/dist/src/extensions/types/manifest.d.ts +3 -0
  248. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  249. package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
  250. package/dist/src/gateway/hono/middleware/scopes.js +1 -1
  251. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +5 -2
  252. package/dist/src/gateway/hono/routes/capability-operations.d.ts +3 -0
  253. package/dist/src/gateway/hono/routes/capability-operations.js +52 -0
  254. package/dist/src/gateway/hono/routes/lazy-bundles.js +16 -0
  255. package/dist/src/gateway/hono/routes/local-app-capabilities.d.ts +4 -0
  256. package/dist/src/gateway/hono/routes/local-app-capabilities.js +41 -0
  257. package/dist/src/gateway/hono/routes/local-apps.js +41 -9
  258. package/dist/src/gateway/hono/routes/models.js +2 -2
  259. package/dist/src/gateway/hono/routes/notes.js +215 -146
  260. package/dist/src/gateway/hono/routes/projects.js +217 -374
  261. package/dist/src/gateway/hono/routes/scenes.js +188 -75
  262. package/dist/src/gateway/hono/routes/session-input-handler.d.ts +60 -16
  263. package/dist/src/gateway/hono/routes/session-input-handler.js +43 -1
  264. package/dist/src/gateway/hono/routes/sessions.js +17 -0
  265. package/dist/src/gateway/hono/routes/status.js +1 -1
  266. package/dist/src/gateway/hono/routes/tasks.js +182 -326
  267. package/dist/src/gateway/hono/routes/user-model-refresh.js +1 -1
  268. package/dist/src/gateway/hono/routes/voice.js +4 -4
  269. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  270. package/dist/src/gateway/media-access.js +2 -1
  271. package/dist/src/gateway/mobile-privacy.js +2 -2
  272. package/dist/src/gateway/scenes/host.js +14 -3
  273. package/dist/src/gateway/scenes/mailContext.js +1 -1
  274. package/dist/src/gateway/scenes/slackThreadSource.d.ts +41 -0
  275. package/dist/src/gateway/scenes/slackThreadSource.js +168 -0
  276. package/dist/src/gateway/security/gateway-scopes.d.ts +1 -1
  277. package/dist/src/gateway/security/gateway-scopes.js +5 -0
  278. package/dist/src/gateway/service/app-context-access.d.ts +11 -0
  279. package/dist/src/gateway/service/app-context-access.js +70 -0
  280. package/dist/src/gateway/service/run-gateway-agent.js +11 -2
  281. package/dist/src/gateway/service/session-input-coordinator.js +54 -15
  282. package/dist/src/gateway/service/sessions-api.d.ts +1 -0
  283. package/dist/src/gateway/service/sessions-api.js +3 -0
  284. package/dist/src/gateway/service/task-conversation-query-service.d.ts +3 -1
  285. package/dist/src/gateway/service/task-conversation-query-service.js +32 -3
  286. package/dist/src/gateway/service.d.ts +3 -0
  287. package/dist/src/gateway/service.js +69 -15
  288. package/dist/src/gateway/session-context-summary.js +2 -1
  289. package/dist/src/{tasks/task-outbox-dispatcher.d.ts → infra/domain-outbox-dispatcher.d.ts} +2 -2
  290. package/dist/src/{tasks/task-outbox-dispatcher.js → infra/domain-outbox-dispatcher.js} +10 -9
  291. package/dist/src/infra/operation-context.d.ts +2 -0
  292. package/dist/src/infra/operation-context.js +16 -0
  293. package/dist/src/local-apps/capabilities/contracts.d.ts +2 -0
  294. package/dist/src/local-apps/capabilities/contracts.js +32 -0
  295. package/dist/src/local-apps/capabilities/read.d.ts +3 -0
  296. package/dist/src/local-apps/capabilities/read.js +48 -0
  297. package/dist/src/local-apps/capabilities/runtime.d.ts +16 -0
  298. package/dist/src/local-apps/capabilities/runtime.js +66 -0
  299. package/dist/src/local-apps/capabilities/write.d.ts +3 -0
  300. package/dist/src/local-apps/capabilities/write.js +35 -0
  301. package/dist/src/local-apps/release-lock.d.ts +2 -0
  302. package/dist/src/local-apps/release-lock.js +20 -0
  303. package/dist/src/local-apps/runtime-entry.d.ts +0 -2
  304. package/dist/src/local-apps/runtime-entry.js +1 -14
  305. package/dist/src/local-apps/scaffold.js +4 -1
  306. package/dist/src/local-apps/service.d.ts +24 -1
  307. package/dist/src/local-apps/service.js +186 -43
  308. package/dist/src/local-apps/store.js +0 -2
  309. package/dist/src/mcp/capability-server.d.ts +4 -0
  310. package/dist/src/mcp/capability-server.js +96 -0
  311. package/dist/src/mcp/channel-bridge.js +1 -1
  312. package/dist/src/mcp/gateway-http-client.d.ts +7 -0
  313. package/dist/src/mcp/gateway-http-client.js +27 -5
  314. package/dist/src/media-understanding/openai-compatible-audio.js +1 -1
  315. package/dist/src/notes/agent-context.js +1 -1
  316. package/dist/src/notes/capabilities/read.d.ts +3 -0
  317. package/dist/src/notes/capabilities/read.js +96 -0
  318. package/dist/src/notes/capabilities/write.d.ts +7 -0
  319. package/dist/src/notes/capabilities/write.js +152 -0
  320. package/dist/src/notes/index.js +1 -1
  321. package/dist/src/notes/service.d.ts +12 -4
  322. package/dist/src/notes/service.js +188 -175
  323. package/dist/src/notes/store.d.ts +14 -9
  324. package/dist/src/notes/store.js +81 -21
  325. package/dist/src/notifications/service.d.ts +1 -0
  326. package/dist/src/notifications/service.js +5 -0
  327. package/dist/src/platform/client.d.ts +1 -1
  328. package/dist/src/platform/contracts.d.ts +1 -1
  329. package/dist/src/projects/capabilities/read.d.ts +3 -0
  330. package/dist/src/projects/capabilities/read.js +81 -0
  331. package/dist/src/projects/capabilities/write.d.ts +9 -0
  332. package/dist/src/projects/capabilities/write.js +260 -0
  333. package/dist/src/projects/index.js +2 -2
  334. package/dist/src/projects/project-change-events.d.ts +2 -0
  335. package/dist/src/projects/project-change-events.js +18 -0
  336. package/dist/src/projects/project-service.d.ts +11 -0
  337. package/dist/src/projects/project-service.js +121 -42
  338. package/dist/src/projects/project-store.js +12 -2
  339. package/dist/src/projects/project-workspace-creation.d.ts +3 -0
  340. package/dist/src/projects/project-workspace-creation.js +45 -0
  341. package/dist/src/projects/workspace-project.js +6 -0
  342. package/dist/src/providers/model-catalog-types.d.ts +2 -1
  343. package/dist/src/providers/model-reference-auditor.js +4 -4
  344. package/dist/src/providers/model-supplements.js +13 -3
  345. package/dist/src/providers/presentation.js +3 -3
  346. package/dist/src/providers/xopc-cloud-model-source.js +4 -2
  347. package/dist/src/realtime/runtime.js +4 -0
  348. package/dist/src/scenes/capabilities/read.d.ts +3 -0
  349. package/dist/src/scenes/capabilities/read.js +187 -0
  350. package/dist/src/scenes/capabilities/write.d.ts +3 -0
  351. package/dist/src/scenes/capabilities/write.js +151 -0
  352. package/dist/src/scenes/contracts.d.ts +2 -105
  353. package/dist/src/scenes/contracts.js +3 -88
  354. package/dist/src/scenes/execution.d.ts +1 -1
  355. package/dist/src/scenes/httpServices.d.ts +2 -0
  356. package/dist/src/scenes/inbox.d.ts +1 -0
  357. package/dist/src/scenes/inbox.js +7 -7
  358. package/dist/src/scenes/preferences.d.ts +3 -24
  359. package/dist/src/scenes/preferences.js +8 -30
  360. package/dist/src/scenes/repository.d.ts +1 -0
  361. package/dist/src/scenes/repository.js +7 -3
  362. package/dist/src/scenes/resultNotifications.js +2 -2
  363. package/dist/src/scenes/schedule.d.ts +1 -8
  364. package/dist/src/scenes/schedule.js +3 -15
  365. package/dist/src/scenes/service.d.ts +6 -0
  366. package/dist/src/scenes/service.js +29 -25
  367. package/dist/src/scenes/taskFollowUp/agentExecutor.d.ts +36 -0
  368. package/dist/src/scenes/taskFollowUp/agentExecutor.js +149 -0
  369. package/dist/src/scenes/taskFollowUp/branchInventory.d.ts +38 -0
  370. package/dist/src/scenes/taskFollowUp/branchInventory.js +70 -0
  371. package/dist/src/scenes/taskFollowUp/contracts.d.ts +91 -0
  372. package/dist/src/scenes/taskFollowUp/contracts.js +100 -0
  373. package/dist/src/scenes/taskFollowUp/resources.d.ts +19 -0
  374. package/dist/src/scenes/taskFollowUp/resources.js +97 -0
  375. package/dist/src/scenes/taskFollowUp/service.d.ts +810 -0
  376. package/dist/src/scenes/taskFollowUp/service.js +710 -0
  377. package/dist/src/scenes/taskFollowUp/workspaceFingerprint.d.ts +2 -0
  378. package/dist/src/scenes/taskFollowUp/workspaceFingerprint.js +46 -0
  379. package/dist/src/scenes/templates.d.ts +2 -2
  380. package/dist/src/scenes/templates.js +1 -1
  381. package/dist/src/session/session-find.d.ts +17 -0
  382. package/dist/src/session/session-find.js +56 -0
  383. package/dist/src/session/store.d.ts +4 -0
  384. package/dist/src/session/store.js +43 -7
  385. package/dist/src/share/note-share-revocation.d.ts +3 -0
  386. package/dist/src/share/note-share-revocation.js +26 -0
  387. package/dist/src/storage/sqlite/migrations/190_scene_development.sql +37 -0
  388. package/dist/src/storage/sqlite/migrations/191_scene_task_follow_up.sql +27 -0
  389. package/dist/src/storage/sqlite/migrations/192_capability_operations.sql +20 -0
  390. package/dist/src/storage/sqlite/migrations/193_note_file_cleanup.sql +8 -0
  391. package/dist/src/storage/sqlite/migrations/194_capability_external_outcomes.sql +11 -0
  392. package/dist/src/storage/sqlite/migrations/195_automation_deleted_revisions.sql +4 -0
  393. package/dist/src/storage/sqlite/migrations/196_automation_run_requests.sql +23 -0
  394. package/dist/src/storage/sqlite/migrations/197_note_deletion_cleanup.sql +8 -0
  395. package/dist/src/storage/sqlite/migrations/198_project_workspace_creation.sql +7 -0
  396. package/dist/src/storage/sqlite/migrations/199_scene_resource_events.sql +488 -0
  397. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  398. package/dist/src/storage/sqlite/migrations/runner.js +6 -3
  399. package/dist/src/storage/sqlite/schema.js +1 -1
  400. package/dist/src/storage/sqlite/transaction.d.ts +5 -0
  401. package/dist/src/storage/sqlite/transaction.js +34 -3
  402. package/dist/src/tasks/capabilities/management.d.ts +195 -0
  403. package/dist/src/tasks/capabilities/management.js +111 -0
  404. package/dist/src/tasks/capabilities/read.d.ts +2 -0
  405. package/dist/src/tasks/capabilities/read.js +141 -0
  406. package/dist/src/tasks/capabilities/relations.d.ts +204 -0
  407. package/dist/src/tasks/capabilities/relations.js +140 -0
  408. package/dist/src/tasks/capabilities/runs.d.ts +2 -0
  409. package/dist/src/tasks/capabilities/runs.js +89 -0
  410. package/dist/src/tasks/capabilities/write.d.ts +207 -0
  411. package/dist/src/tasks/capabilities/write.js +107 -0
  412. package/dist/src/tasks/home-query-service.js +3 -2
  413. package/dist/src/tasks/index.d.ts +0 -1
  414. package/dist/src/tasks/index.js +9 -9
  415. package/dist/src/tasks/project-operating-view-service.js +2 -1
  416. package/dist/src/tasks/task-application-service.d.ts +1 -0
  417. package/dist/src/tasks/task-application-service.js +3 -2
  418. package/dist/src/tasks/task-change-events.js +5 -3
  419. package/dist/src/tasks/task-context-assembler.js +2 -1
  420. package/dist/src/tasks/task-deletion-service.js +2 -1
  421. package/dist/src/tasks/task-dependency-service.js +2 -1
  422. package/dist/src/tasks/task-handoff-service.js +2 -1
  423. package/dist/src/tasks/task-read-model-projector.js +2 -1
  424. package/dist/src/tasks/task-repository.d.ts +12 -7
  425. package/dist/src/tasks/task-repository.js +175 -154
  426. package/dist/src/tasks/task-run-coordinator.js +2 -1
  427. package/dist/src/tasks/task-run-dispatcher.js +2 -1
  428. package/dist/src/tasks/task-run-repository.d.ts +1 -0
  429. package/dist/src/tasks/task-run-repository.js +29 -14
  430. package/dist/src/tasks/task-signal-service.js +2 -1
  431. package/dist/src/tui/backends/embedded-backend.js +1 -1
  432. package/dist/src/tui/backends/gateway-realtime-backend.js +1 -1
  433. package/dist/src/tui/tui-commands.js +1 -1
  434. package/dist/src/user-context/config.d.ts +13 -0
  435. package/dist/src/user-context/config.js +2 -0
  436. package/dist/src/voice/platform-catalog.d.ts +1 -1
  437. package/dist/src/voice/realtime/runtime.js +3 -3
  438. package/dist/src/voice/stt/providers/alibaba-transcription.js +1 -1
  439. package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +1 -1
  440. package/dist/src/voice/tts/providers/xopc-cloud-speech.js +1 -1
  441. package/dist/src/work-discovery/incremental-repository.js +1 -1
  442. package/dist/src/work-discovery/index.js +1 -1
  443. package/dist/src/work-discovery/repository.d.ts +1 -1
  444. package/dist/src/work-discovery/repository.js +3 -2
  445. package/dist/src/work-discovery/service.d.ts +4 -0
  446. package/dist/src/work-discovery/service.js +36 -11
  447. package/dist/src/workflows/context/workflow-context.js +3 -2
  448. package/dist/src/workflows/service/workflow-run-service.js +2 -1
  449. package/package.json +6 -2
  450. package/skills/THIRD_PARTY_NOTICES.md +2 -2
  451. package/skills/documents/xlsx/SKILL.md +5 -0
  452. package/skills/engineering/build-xopc-local-app/SKILL.md +2 -0
  453. package/skills/tools/find-skills/SKILL.md +3 -0
  454. package/dist/gateway/static/root/assets/activity-store-DVUTs1fk.js +0 -1
  455. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-K3hTmu9d.js +0 -1
  456. package/dist/gateway/static/root/assets/appearance-settings-CU52MfIT.js +0 -1
  457. package/dist/gateway/static/root/assets/apps-page-ZpA1-6ad.js +0 -1
  458. package/dist/gateway/static/root/assets/automations-workspace-IEAxKRME.js +0 -7
  459. package/dist/gateway/static/root/assets/browser-settings-page-CU4VWsmX.js +0 -3
  460. package/dist/gateway/static/root/assets/capabilities-settings-panel-C9XQk3HL.js +0 -8
  461. package/dist/gateway/static/root/assets/channels-settings-Bqlhjooi.js +0 -1
  462. package/dist/gateway/static/root/assets/connector-service-page-BmH17JnO.js +0 -1
  463. package/dist/gateway/static/root/assets/connectors-page-zkx8Q-e6.js +0 -2
  464. package/dist/gateway/static/root/assets/desktop-pet-settings-CE4GOlMM.js +0 -1
  465. package/dist/gateway/static/root/assets/device-pairing-wizard-CdKJqnnw.js +0 -1
  466. package/dist/gateway/static/root/assets/files-Be5viEFY.js +0 -1
  467. package/dist/gateway/static/root/assets/gateway-realtime-CGOW0-b4.js +0 -1
  468. package/dist/gateway/static/root/assets/gateway-realtime-store-D4um_sV7.js +0 -1
  469. package/dist/gateway/static/root/assets/gateway-settings-CgXp2zq4.js +0 -1
  470. package/dist/gateway/static/root/assets/home-page-D6Idk732.js +0 -1
  471. package/dist/gateway/static/root/assets/index-1wIKA-kM.css +0 -1
  472. package/dist/gateway/static/root/assets/index-PFQHPGgi.js +0 -79
  473. package/dist/gateway/static/root/assets/local-app-workbench-page-BmAqTRb4.js +0 -2
  474. package/dist/gateway/static/root/assets/logs-page-ZjVYXXyM.js +0 -2
  475. package/dist/gateway/static/root/assets/management-settings-CSTkYVOZ.js +0 -1
  476. package/dist/gateway/static/root/assets/messages-4BtQKYlM.js +0 -3
  477. package/dist/gateway/static/root/assets/note-detail-panel-DuXCt-MM.js +0 -5
  478. package/dist/gateway/static/root/assets/notes-page-BjOgBVq5.js +0 -8
  479. package/dist/gateway/static/root/assets/product-delivery-CrAI8ZEa.js +0 -1
  480. package/dist/gateway/static/root/assets/project-detail-page-0zi4-i9X.js +0 -1
  481. package/dist/gateway/static/root/assets/projects-page-B18OxmJj.js +0 -1
  482. package/dist/gateway/static/root/assets/remote-access-hub-z-DxbuaE.js +0 -1
  483. package/dist/gateway/static/root/assets/runtime-tools-settings-panel-DGsBTbo6.js +0 -5
  484. package/dist/gateway/static/root/assets/scenes-page-Bgba03B_.js +0 -1
  485. package/dist/gateway/static/root/assets/schemas-BaskVM5g.js +0 -64
  486. package/dist/gateway/static/root/assets/sessions-page-B1t3bMsm.js +0 -1
  487. package/dist/gateway/static/root/assets/settings-advanced-gate-CBX0Ezhf.js +0 -1
  488. package/dist/gateway/static/root/assets/setup-status-panel-Bw71C2X3.js +0 -1
  489. package/dist/gateway/static/root/assets/shares-settings-BoVDQolc.js +0 -1
  490. package/dist/gateway/static/root/assets/skill-reload-api-DtTptpAt.js +0 -1
  491. package/dist/gateway/static/root/assets/task-detail-page-vgkiGo-D.js +0 -1
  492. package/dist/gateway/static/root/assets/theme-store-CegIlB8d.js +0 -1
  493. package/dist/gateway/static/root/assets/user-model-page-CAGafNfP.js +0 -2
  494. package/dist/gateway/static/root/assets/workflows-page-CSxHVs1p.js +0 -6
  495. package/skills/creative/algorithmic-art/SKILL.md +0 -44
  496. package/skills/creative/algorithmic-art/templates/generator-template.js +0 -27
  497. package/skills/creative/algorithmic-art/templates/viewer.html +0 -27
@@ -1,35 +1,34 @@
1
1
  import { runWithActivityContext } from "../../activity/context.js";
2
- import { init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
3
2
  import { TaskCommandSchema, TaskContextInputSchema } from "../../../packages/gateway-contract/src/tasks.js";
4
3
  import { appendProductDeliveryText } from "../../../packages/gateway-contract/src/product-delivery.js";
4
+ import { AutomationCancelOutputSchema, AutomationDeleteOutputSchema, AutomationMutationOutputSchema, AutomationReadAllInputSchema, AutomationReadAllOutputSchema, AutomationReadOutputSchema, AutomationRunMutationOutputSchema, CapabilityCallSchema, CapabilityResourceInputSchema, NoteDeleteOutputSchema, NoteGetOutputSchema, ProjectCreateInputSchema, ProjectDeleteInputSchema, ProjectDeleteOutputSchema, ProjectEditInputSchema, ProjectMilestoneCreateInputSchema, ProjectMilestoneDeleteInputSchema, ProjectMilestoneDeleteOutputSchema, ProjectMilestoneOutputSchema, ProjectMilestoneUpdateInputSchema, ProjectMutationOutputSchema, ProjectResolveWorkspaceInputSchema, ProjectResolveWorkspaceOutputSchema, ProjectSetPinnedInputSchema, ProjectUpdateCreateInputSchema, ProjectUpdateOutputSchema, SceneWriteContracts, TaskRunCancelInputSchema, TaskRunCancelOutputSchema, TaskRunFeedbackInputSchema, TaskRunFeedbackOutputSchema } from "../../../packages/gateway-contract/src/capabilities.js";
5
5
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
6
- import { enqueueTaskChangedEvent } from "../../tasks/task-change-events.js";
6
+ import { TaskRepository } from "../../tasks/task-repository.js";
7
7
  import { TaskRunRepository } from "../../tasks/task-run-repository.js";
8
8
  import { getSessionMetadata } from "../../storage/sqlite/session-read-repository.js";
9
9
  import "../../storage/sqlite/index.js";
10
- import { ObjectLinkService } from "../../activity/service.js";
11
10
  import "../../activity/index.js";
12
11
  import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
13
- import { TaskRepository } from "../../tasks/task-repository.js";
14
- import { TaskReadModelProjector } from "../../tasks/task-read-model-projector.js";
15
- import { isValidProjectAgentId, normalizeProjectAgentId, resolveProjectAgentId } from "../../projects/project-agent.js";
12
+ import { CapabilityError } from "../../capabilities/runtime/errors.js";
13
+ import "../../capabilities/runtime/dispatcher.js";
14
+ import { resolveProjectAgentId } from "../../projects/project-agent.js";
16
15
  import "../../projects/index.js";
17
- import { CreateAutomationSchema, UpdateAutomationSchema } from "../../automations/domain/validation.js";
18
- import "../../automations/index.js";
19
- import { TaskContextRepository } from "../../tasks/task-context-repository.js";
20
- import { TaskDependencyError, TaskDependencyService } from "../../tasks/task-dependency-service.js";
21
- import { TaskApplicationService } from "../../tasks/task-application-service.js";
22
- import { defineTaskContract } from "../../tasks/task-contract-definition.js";
23
16
  import { TaskDeletionService } from "../../tasks/task-deletion-service.js";
17
+ import { TaskDeleteOutputSchema } from "../../tasks/capabilities/management.js";
18
+ import { AutomationCreateCapabilityInputSchema, AutomationUpdatePatchSchema } from "../../automations/capabilities/write.js";
19
+ import { TaskMutationOutputSchema } from "../../tasks/capabilities/write.js";
20
+ import { createProductDispatcher } from "../../capabilities/runtime/product.js";
21
+ import { localAppCapabilities } from "../../local-apps/capabilities/runtime.js";
22
+ import { defineTaskContract } from "../../tasks/task-contract-definition.js";
24
23
  import "../../tasks/index.js";
25
24
  import { randomUUID } from "node:crypto";
26
25
  import { Type } from "@sinclair/typebox";
27
26
  //#region src/agent/tools/xopc-use-tool.ts
28
27
  init_src();
29
28
  init_resolve_route();
30
- init_transaction();
31
29
  const XopcUseToolSchema = Type.Object({
32
30
  mode: Type.Union([
31
+ Type.Literal("context"),
33
32
  Type.Literal("scene"),
34
33
  Type.Literal("project"),
35
34
  Type.Literal("automation"),
@@ -39,30 +38,10 @@ const XopcUseToolSchema = Type.Object({
39
38
  Type.Literal("local_app"),
40
39
  Type.Literal("settings")
41
40
  ]),
42
- command: Type.String({ description: "Object command. Scene commands: templates, list, get {id}, mail_accounts, mail_search {accountId, query}, mail_sources, read_notes {id}, preflight/start {templateKey, templateVersion, goal, scope, permissions}, configure {id, expectedRevision, goal, scope, permissions}, transition {id, expectedRevision, status: paused|active|completed|archived}, check {id}, notes {id, expectedRevision, content, validUntil?}, work_item {id, subjectId, accountId, dueAt}, update_work_item {workItemId, expectedRevision, dueAt?, status?}, schedule {id, triggerKey, expectedRevision, schedule}, results {id?}, feedback {presentationId, expectedRevision, rating}, mark_read {presentationId, read}, diagnostics, get_preferences, set_preferences {expectedRevision, ...preferences}. Start and check accept a stable requestId for retries. Scenes prepare read-only suggestions and drafts; never send mail. Only create a scene for work explicitly delegated by the user; inspect existing scenes first. Supports project list/get/create/update/resolve_workspace/list_milestones/create_milestone/update_milestone/list_updates/create_update, automation list/get/create/update/delete/run/pause/resume/history, note list/get/create/append/update/preview_edit/delete, task list/get/create/update_dependencies/add_context/remove_context/command/delete, task_run list/get/cancel, local_app list/get/create/validate, and settings open." }),
41
+ command: Type.String({ description: "Context resolve takes an explicit AppContextEnvelope; never guess a current page. Automation draft/repair_draft accept prompt/id, agentId?, language?, idempotencyKey?; simulate explains an automation without running it. Local_app record_acceptance records supplied checks and sourceHash, not proof that checks were executed. Project create accepts idempotencyKey; update/pin/unpin/delete accepts {projectId, expectedVersion?, idempotencyKey?}; stable retries require the original expectedVersion. Delete preserves workspace files and does not confirm external execution stopped. Project milestone writes support idempotencyKey; update_milestone/delete_milestone require original expectedRevision for stable retries, and create_update requires original expectedVersion. TaskRun cancel accepts idempotencyKey and expectedVersion, and does not confirm external execution stopped. Automation diagnostics: get_run/run_events {runId}, metrics {}, product_events {eventType, source?, payloadKey?, payloadValue?, limit?}; payload filters require both key and value. Automation also supports cancel/read {runId, idempotencyKey?} and read_all {projectId?, idempotencyKey?}; omitted projectId means all projects. Cancel acceptance is not confirmation of stopping. Object command. Scene commands: templates, list, get {id}, mail_accounts, mail_search {accountId, query}, mail_sources, read_notes {id}, preflight/start {templateKey, templateVersion, goal, scope, permissions}, configure {id, expectedRevision, goal, scope, permissions}, transition {id, expectedRevision, status: paused|active|completed|archived}, check {id}, notes {id, expectedRevision, content, validUntil?}, work_item {id, subjectId, accountId, dueAt}, update_work_item {workItemId, expectedRevision, dueAt?, status?}, schedule {id, triggerKey, expectedRevision, schedule}, results {id?}, feedback {presentationId, expectedRevision, rating}, mark_read {presentationId, read}, diagnostics, get_preferences, set_preferences {expectedRevision, ...preferences}. Start and check accept a stable requestId for retries. Scenes prepare read-only suggestions and drafts; never send mail. Only create a scene for work explicitly delegated by the user; inspect existing scenes first. Supports project list/get/create/update/resolve_workspace/list_milestones/create_milestone/update_milestone/list_updates/create_update, automation list/get/create/update/delete/run/rerun/pause/resume/history (rerun takes runId; run/rerun accept idempotencyKey), note list/get/project_summaries/history {noteId}/snapshot {noteId, timestamp}/create/append/update/preview_edit/delete, task list/get/create/update_dependencies/add_context/remove_context/command/delete, task_run list/get/cancel, local_app list/get/create/validate, and settings open." }),
43
42
  args: Type.Optional(Type.Record(Type.String(), Type.Any())),
44
43
  dryRun: Type.Optional(Type.Boolean({ description: "Validate and preview the action without mutating xopc state." }))
45
44
  });
46
- const PROJECT_STATUSES = new Set([
47
- "planned",
48
- "active",
49
- "paused",
50
- "completed",
51
- "cancelled",
52
- "archived"
53
- ]);
54
- const PROJECT_HEALTHS = new Set([
55
- "unknown",
56
- "on_track",
57
- "at_risk",
58
- "off_track"
59
- ]);
60
- const MILESTONE_STATUSES = new Set([
61
- "planned",
62
- "active",
63
- "completed",
64
- "cancelled"
65
- ]);
66
45
  const NOTE_KINDS = new Set([
67
46
  "thought",
68
47
  "todo",
@@ -78,13 +57,6 @@ const NOTE_STATUSES = new Set([
78
57
  "archived",
79
58
  "trashed"
80
59
  ]);
81
- const TASK_PHASES = new Set([
82
- "backlog",
83
- "ready",
84
- "active",
85
- "review",
86
- "closed"
87
- ]);
88
60
  const TASK_PRIORITIES = new Set([
89
61
  "low",
90
62
  "normal",
@@ -133,15 +105,6 @@ function optionalString(value) {
133
105
  if (value === null) return null;
134
106
  if (typeof value === "string") return value;
135
107
  }
136
- function boundedLimit(value, fallback = 20, max = 100) {
137
- const raw = typeof value === "number" ? value : typeof value === "string" ? Number(value) : fallback;
138
- if (!Number.isFinite(raw)) return fallback;
139
- return Math.max(1, Math.min(max, Math.floor(raw)));
140
- }
141
- function offset(value) {
142
- const raw = typeof value === "number" ? value : typeof value === "string" ? Number(value) : void 0;
143
- return raw !== void 0 && Number.isFinite(raw) ? Math.max(0, Math.floor(raw)) : void 0;
144
- }
145
108
  function enumValue(value, allowed) {
146
109
  return typeof value === "string" && allowed.has(value) ? value : void 0;
147
110
  }
@@ -156,10 +119,6 @@ function stringArray(value) {
156
119
  if (!Array.isArray(value)) return void 0;
157
120
  return value.filter((item) => typeof item === "string");
158
121
  }
159
- function nullableFiniteNumber(value) {
160
- if (value === null) return null;
161
- return finiteNumber(value);
162
- }
163
122
  function ensureArgs(input) {
164
123
  return input.args && typeof input.args === "object" && !Array.isArray(input.args) ? input.args : {};
165
124
  }
@@ -179,9 +138,65 @@ function deliverySummary(...values) {
179
138
  return value.length > 180 ? `${value.slice(0, 177)}…` : value;
180
139
  }
181
140
  function deliveryForXopcResult(mode, command, result, dryRun) {
182
- if (dryRun || command === "list" || command === "delete") return void 0;
141
+ if (dryRun || command === "delete") return void 0;
183
142
  const resultRecord = record(result);
184
143
  if (!resultRecord || resultRecord.ok === false) return void 0;
144
+ if (command === "list") {
145
+ const rows = resultRecord.items ?? resultRecord.activations ?? resultRecord.apps;
146
+ if (!Array.isArray(rows) || ![
147
+ "task",
148
+ "note",
149
+ "project",
150
+ "automation",
151
+ "scene",
152
+ "local_app"
153
+ ].includes(mode)) return void 0;
154
+ const field = mode === "scene" ? "activation" : mode === "local_app" ? "app" : mode;
155
+ const items = rows.slice(0, 50).flatMap((row) => {
156
+ const reference = deliveryForXopcResult(mode, "get", { [field]: row }, false)?.primary;
157
+ return reference ? [{
158
+ ...reference,
159
+ capabilities: ["open"]
160
+ }] : [];
161
+ });
162
+ return {
163
+ version: 1,
164
+ operation: "opened",
165
+ presentation: {
166
+ kind: "table",
167
+ items,
168
+ truncated: rows.length > 50 || Boolean(resultRecord.nextCursor) || typeof resultRecord.total === "number" && resultRecord.total > items.length
169
+ }
170
+ };
171
+ }
172
+ if (mode === "note" && command === "preview_edit") {
173
+ const patch = record(resultRecord.patch);
174
+ if (!patch || !Array.isArray(patch.operations)) return void 0;
175
+ let remaining = 16e3;
176
+ let truncated = patch.operations.length > 20;
177
+ const edits = patch.operations.slice(0, 20).flatMap((value) => {
178
+ const edit = record(value);
179
+ if (!edit || edit.type !== "replaceRange" || !Number.isSafeInteger(edit.from) || !Number.isSafeInteger(edit.to) || edit.from < 0 || edit.to < edit.from || typeof edit.markdown !== "string") return [];
180
+ const text = edit.markdown.slice(0, remaining);
181
+ truncated ||= text.length < edit.markdown.length;
182
+ remaining -= text.length;
183
+ return [{
184
+ from: edit.from,
185
+ to: edit.to,
186
+ text
187
+ }];
188
+ });
189
+ return {
190
+ version: 1,
191
+ operation: "opened",
192
+ presentation: {
193
+ kind: "diff",
194
+ title: String(patch.summary ?? "").slice(0, 2e3),
195
+ edits,
196
+ truncated
197
+ }
198
+ };
199
+ }
185
200
  let source;
186
201
  let primary;
187
202
  if (mode === "project") {
@@ -194,7 +209,7 @@ function deliveryForXopcResult(mode, command, result, dryRun) {
194
209
  title: deliveryText(source?.name) ?? "Project",
195
210
  summary: deliverySummary(source?.description, source?.brief),
196
211
  status: deliveryText(source?.status),
197
- revision: deliveryRevision(source?.updatedAt),
212
+ revision: deliveryRevision(source?.version),
198
213
  capabilities: [
199
214
  "open",
200
215
  "edit",
@@ -247,7 +262,7 @@ function deliveryForXopcResult(mode, command, result, dryRun) {
247
262
  title: deliveryText(source?.title) ?? "Untitled note",
248
263
  summary: deliverySummary(source?.markdown),
249
264
  status: deliveryText(source?.status),
250
- revision: deliveryRevision(source?.localVersion) ?? deliveryRevision(source?.updatedAt),
265
+ revision: deliveryRevision(source?.remoteVersion ?? 1),
251
266
  projectId: deliveryText(resultRecord.projectId),
252
267
  capabilities: [
253
268
  "open",
@@ -329,7 +344,7 @@ function deliveryForXopcResult(mode, command, result, dryRun) {
329
344
  if (!primary) return void 0;
330
345
  return {
331
346
  version: 1,
332
- operation: mode === "task" && deliveryText(resultRecord.runId) || mode === "automation" && command === "run" || mode === "scene" && command === "check" ? "started" : command === "create" || mode === "scene" && command === "start" ? "created" : command === "get" || command === "resolve_workspace" || mode === "settings" ? "opened" : command === "validate" ? "completed" : "updated",
347
+ operation: mode === "task" && deliveryText(resultRecord.runId) || mode === "automation" && (command === "run" || command === "rerun") || mode === "scene" && command === "check" ? "started" : command === "create" || mode === "scene" && command === "start" ? "created" : command === "get" || command === "resolve_workspace" || mode === "settings" ? "opened" : command === "validate" ? "completed" : "updated",
333
348
  primary
334
349
  };
335
350
  }
@@ -359,70 +374,50 @@ function optionalProjectWorkspaceRootArg(args) {
359
374
  if (args.workspacePath !== void 0) return optionalString(args.workspacePath);
360
375
  if (args.path !== void 0) return optionalString(args.path);
361
376
  }
362
- function validateDefaultAgentId(raw, config) {
363
- if (raw === null) return null;
364
- const normalized = normalizeProjectAgentId(trimString(raw));
365
- if (!normalized) return void 0;
366
- if (config && !isValidProjectAgentId(config, normalized)) throw new Error(`Default agent not found: ${normalized}`);
367
- return normalized;
368
- }
369
- async function handleProject(command, args, deps, dryRun) {
377
+ async function handleProject(command, args, deps, dryRun, capabilities) {
370
378
  const projects = deps.getProjectService?.();
371
379
  if (!projects) return {
372
380
  ok: false,
373
381
  error: "Project service is unavailable"
374
382
  };
375
- if (command === "list") return {
376
- ok: true,
377
- ...projects.list({
378
- status: enumValue(args.status, PROJECT_STATUSES),
379
- search: trimString(args.search),
380
- sortBy: enumValue(args.sortBy, new Set([
381
- "updatedAt",
382
- "createdAt",
383
- "name"
384
- ])),
385
- sortOrder: enumValue(args.sortOrder, new Set(["asc", "desc"])),
386
- limit: boundedLimit(args.limit),
387
- offset: offset(args.offset)
388
- })
389
- };
390
- if (command === "get") {
391
- const id = trimString(args.projectId) ?? trimString(args.id);
392
- if (!id) return {
393
- ok: false,
394
- error: "projectId is required"
395
- };
396
- const project = projects.getWithDetails(id);
397
- return project ? {
398
- ok: true,
399
- project
400
- } : {
401
- ok: false,
402
- error: `Project not found: ${id}`
403
- };
404
- }
405
383
  if (command === "resolve_workspace") {
406
- const workspacePath = projectWorkspaceRootArg(args);
407
- if (!workspacePath) return {
384
+ if (args.idempotencyKey !== void 0 && !trimString(args.idempotencyKey)) return {
408
385
  ok: false,
409
- error: "workspacePath is required"
410
- };
411
- const defaultAgentId = args.defaultAgentId !== void 0 ? validateDefaultAgentId(args.defaultAgentId, deps.getConfig?.()) ?? void 0 : void 0;
412
- const input = {
413
- workspacePath,
414
- agentId: trimString(args.agentId),
415
- defaultAgentId,
416
- autoCreate: args.autoCreate === true
386
+ error: "Invalid idempotencyKey"
417
387
  };
388
+ const input = ProjectResolveWorkspaceInputSchema.parse({
389
+ ...pickDefined(args, [
390
+ "agentId",
391
+ "defaultAgentId",
392
+ "projectKind",
393
+ "autoCreate",
394
+ "conversationId"
395
+ ]),
396
+ workspacePath: projectWorkspaceRootArg(args)
397
+ });
418
398
  if (dryRun) return {
419
399
  ok: true,
420
400
  dryRun: true,
421
401
  action: "resolve_project_workspace",
422
402
  input
423
403
  };
424
- const match = projects.resolveOrCreateForWorkspacePath(input);
425
- return match ? {
404
+ const caller = {
405
+ principalId: "agent:" + (deps.getCurrentAgentId?.() ?? "main"),
406
+ surface: "agent",
407
+ scopes: ["workspace.write"],
408
+ actor: {
409
+ kind: "agent",
410
+ id: deps.getCurrentAgentId?.()
411
+ },
412
+ authorize: deps.authorizeCapability ?? (() => true)
413
+ };
414
+ const operation = "xopc.projects.resolve_workspace";
415
+ const result = ProjectResolveWorkspaceOutputSchema.parse(await capabilities.call(operation, input, caller, {
416
+ ...capabilities.describe(operation, caller),
417
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
418
+ }));
419
+ const { ok: _ok, ...match } = result;
420
+ return result.project ? {
426
421
  ok: true,
427
422
  match
428
423
  } : {
@@ -430,335 +425,267 @@ async function handleProject(command, args, deps, dryRun) {
430
425
  error: "No project matched workspace path"
431
426
  };
432
427
  }
433
- if (command === "create") {
434
- const name = trimString(args.name);
435
- const workspaceRoot = projectWorkspaceRootArg(args);
436
- if (!name && !workspaceRoot) return {
437
- ok: false,
438
- error: "name or workspaceRoot is required"
439
- };
440
- const input = {
441
- name,
442
- description: trimString(args.description),
443
- defaultAgentId: validateDefaultAgentId(args.defaultAgentId, deps.getConfig?.()) ?? void 0,
444
- workspaceRoot,
445
- createWorkspaceRoot: args.createWorkspaceRoot === true,
446
- projectKind: trimString(args.projectKind),
447
- brief: trimString(args.brief),
448
- instructions: trimString(args.instructions),
449
- outcome: trimString(args.outcome),
450
- successCriteria: args.successCriteria === void 0 ? void 0 : stringArray(args.successCriteria),
451
- scope: args.scope === void 0 ? void 0 : record(args.scope),
452
- nonGoals: args.nonGoals === void 0 ? void 0 : stringArray(args.nonGoals),
453
- health: args.health === void 0 ? void 0 : enumValue(args.health, PROJECT_HEALTHS),
454
- ownerId: trimString(args.ownerId),
455
- targetAt: args.targetAt === void 0 ? void 0 : finiteNumber(args.targetAt)
456
- };
457
- if (args.successCriteria !== void 0 && !input.successCriteria) return {
458
- ok: false,
459
- error: "Invalid successCriteria"
460
- };
461
- if (args.scope !== void 0 && !input.scope) return {
462
- ok: false,
463
- error: "Invalid scope"
464
- };
465
- if (args.nonGoals !== void 0 && !input.nonGoals) return {
466
- ok: false,
467
- error: "Invalid nonGoals"
468
- };
469
- if (args.health !== void 0 && !input.health) return {
470
- ok: false,
471
- error: "Invalid project health"
472
- };
473
- if (args.targetAt !== void 0 && input.targetAt === void 0) return {
474
- ok: false,
475
- error: "Invalid targetAt"
476
- };
428
+ if (command === "create" || command === "update") {
429
+ const values = pickDefined(args, [
430
+ "name",
431
+ "description",
432
+ "defaultAgentId",
433
+ "createWorkspaceRoot",
434
+ "executionMode",
435
+ "brief",
436
+ "instructions",
437
+ "outcome",
438
+ "successCriteria",
439
+ "scope",
440
+ "nonGoals",
441
+ "health",
442
+ "ownerId",
443
+ "targetAt"
444
+ ]);
445
+ const workspaceRoot = command === "create" ? projectWorkspaceRootArg(args) : optionalProjectWorkspaceRootArg(args);
446
+ if (workspaceRoot !== void 0) values.workspaceRoot = workspaceRoot;
447
+ if (args.workspaceRoot !== void 0 && typeof args.workspaceRoot !== "string" && args.workspaceRoot !== null) values.workspaceRoot = args.workspaceRoot;
448
+ if (args.idempotencyKey !== void 0 && !trimString(args.idempotencyKey)) return {
449
+ ok: false,
450
+ error: "Invalid idempotencyKey"
451
+ };
452
+ let input;
453
+ if (command === "create") input = ProjectCreateInputSchema.parse({
454
+ ...values,
455
+ ...pickDefined(args, ["projectKind", "autoUnderstand"])
456
+ });
457
+ else {
458
+ const id = trimString(args.projectId) ?? trimString(args.id);
459
+ if (!id) return {
460
+ ok: false,
461
+ error: "projectId is required"
462
+ };
463
+ if (args.idempotencyKey !== void 0 && args.expectedVersion === void 0) return {
464
+ ok: false,
465
+ error: "Stable retries require the original expectedVersion"
466
+ };
467
+ const project = args.expectedVersion === void 0 ? projects.get(id) : void 0;
468
+ if (args.expectedVersion === void 0 && !project) return {
469
+ ok: false,
470
+ error: "Project not found"
471
+ };
472
+ input = ProjectEditInputSchema.parse({
473
+ id,
474
+ expectedVersion: args.expectedVersion === void 0 ? project?.version : args.expectedVersion,
475
+ patch: {
476
+ ...values,
477
+ ...pickDefined(args, ["status"])
478
+ }
479
+ });
480
+ }
477
481
  if (dryRun) return {
478
482
  ok: true,
479
483
  dryRun: true,
480
- action: "create_project",
484
+ action: `${command}_project`,
481
485
  input
482
486
  };
483
- return {
484
- ok: true,
485
- project: projects.create(input)
487
+ const caller = {
488
+ principalId: "agent:" + (deps.getCurrentAgentId?.() ?? "main"),
489
+ surface: "agent",
490
+ scopes: ["workspace.write"],
491
+ actor: {
492
+ kind: "agent",
493
+ id: deps.getCurrentAgentId?.()
494
+ },
495
+ authorize: deps.authorizeCapability ?? (() => true)
486
496
  };
497
+ const operation = "xopc.projects." + command;
498
+ return ProjectMutationOutputSchema.parse(await capabilities.call(operation, input, caller, {
499
+ ...capabilities.describe(operation, caller),
500
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
501
+ }));
487
502
  }
488
- if (command === "update") {
503
+ if (command === "pin" || command === "unpin" || command === "delete") {
489
504
  const id = trimString(args.projectId) ?? trimString(args.id);
490
505
  if (!id) return {
491
506
  ok: false,
492
507
  error: "projectId is required"
493
508
  };
494
- const workspaceRoot = optionalProjectWorkspaceRootArg(args);
495
- const patch = {
496
- ...args.name !== void 0 ? { name: trimString(args.name) ?? "" } : {},
497
- ...args.description !== void 0 ? { description: optionalString(args.description) } : {},
498
- ...args.status !== void 0 ? { status: enumValue(args.status, PROJECT_STATUSES) } : {},
499
- ...args.defaultAgentId !== void 0 ? { defaultAgentId: validateDefaultAgentId(args.defaultAgentId, deps.getConfig?.()) } : {},
500
- ...workspaceRoot !== void 0 ? { workspaceRoot } : {},
501
- ...args.createWorkspaceRoot === true ? { createWorkspaceRoot: true } : {},
502
- ...args.brief !== void 0 ? { brief: optionalString(args.brief) } : {},
503
- ...args.instructions !== void 0 ? { instructions: optionalString(args.instructions) } : {},
504
- ...args.outcome !== void 0 ? { outcome: optionalString(args.outcome) } : {},
505
- ...args.successCriteria !== void 0 ? { successCriteria: stringArray(args.successCriteria) } : {},
506
- ...args.scope !== void 0 ? { scope: record(args.scope) } : {},
507
- ...args.nonGoals !== void 0 ? { nonGoals: stringArray(args.nonGoals) } : {},
508
- ...args.health !== void 0 ? { health: enumValue(args.health, PROJECT_HEALTHS) } : {},
509
- ...args.ownerId !== void 0 ? { ownerId: optionalString(args.ownerId) } : {},
510
- ...args.targetAt !== void 0 ? { targetAt: nullableFiniteNumber(args.targetAt) } : {}
511
- };
512
- if (args.status !== void 0 && patch.status === void 0) return {
513
- ok: false,
514
- error: "Invalid project status"
515
- };
516
- if (args.successCriteria !== void 0 && patch.successCriteria === void 0) return {
517
- ok: false,
518
- error: "Invalid successCriteria"
519
- };
520
- if (args.scope !== void 0 && patch.scope === void 0) return {
509
+ if (args.idempotencyKey !== void 0 && !trimString(args.idempotencyKey)) return {
521
510
  ok: false,
522
- error: "Invalid scope"
511
+ error: "Invalid idempotencyKey"
523
512
  };
524
- if (args.nonGoals !== void 0 && patch.nonGoals === void 0) return {
513
+ if (args.idempotencyKey !== void 0 && args.expectedVersion === void 0) return {
525
514
  ok: false,
526
- error: "Invalid nonGoals"
515
+ error: "Stable retries require the original expectedVersion"
527
516
  };
528
- if (args.health !== void 0 && patch.health === void 0) return {
517
+ const project = args.expectedVersion === void 0 ? projects.get(id) : void 0;
518
+ if (args.expectedVersion === void 0 && !project) return {
529
519
  ok: false,
530
- error: "Invalid project health"
520
+ error: "Project not found"
531
521
  };
532
- if (args.targetAt !== void 0 && patch.targetAt === void 0) return {
533
- ok: false,
534
- error: "Invalid targetAt"
522
+ const common = {
523
+ id,
524
+ expectedVersion: args.expectedVersion === void 0 ? project?.version : args.expectedVersion
535
525
  };
526
+ const input = command === "delete" ? ProjectDeleteInputSchema.parse(common) : ProjectSetPinnedInputSchema.parse({
527
+ ...common,
528
+ pinned: command === "pin"
529
+ });
536
530
  if (dryRun) return {
537
531
  ok: true,
538
532
  dryRun: true,
539
- action: "update_project",
540
- projectId: id,
541
- patch
533
+ action: `${command}_project`,
534
+ input
542
535
  };
543
- return {
544
- ok: true,
545
- project: projects.update(id, patch)
536
+ const caller = {
537
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
538
+ surface: "agent",
539
+ scopes: ["workspace.write"],
540
+ actor: {
541
+ kind: "agent",
542
+ id: deps.getCurrentAgentId?.()
543
+ },
544
+ authorize: deps.authorizeCapability ?? (() => true)
546
545
  };
546
+ const operation = command === "delete" ? "xopc.projects.delete" : "xopc.projects.set_pinned";
547
+ const result = await capabilities.call(operation, input, caller, {
548
+ ...capabilities.describe(operation, caller),
549
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
550
+ });
551
+ return (command === "delete" ? ProjectDeleteOutputSchema : ProjectMutationOutputSchema).parse(result);
547
552
  }
548
- const projectId = trimString(args.projectId) ?? trimString(args.id);
549
- if (command === "list_milestones") {
553
+ if ([
554
+ "create_milestone",
555
+ "update_milestone",
556
+ "delete_milestone",
557
+ "create_update"
558
+ ].includes(command)) {
559
+ const projectId = trimString(args.projectId) ?? trimString(args.id);
550
560
  if (!projectId) return {
551
561
  ok: false,
552
562
  error: "projectId is required"
553
563
  };
554
- return {
555
- ok: true,
564
+ const operation = "xopc.projects." + command;
565
+ let input;
566
+ if (command === "create_milestone") input = ProjectMilestoneCreateInputSchema.parse({
556
567
  projectId,
557
- items: projects.listMilestones(projectId)
558
- };
559
- }
560
- if (command === "create_milestone") {
561
- if (!projectId) return {
562
- ok: false,
563
- error: "projectId is required"
564
- };
565
- const title = trimString(args.title);
566
- const status = args.status === void 0 ? void 0 : enumValue(args.status, MILESTONE_STATUSES);
567
- const targetAt = args.targetAt === void 0 ? void 0 : finiteNumber(args.targetAt);
568
- const sortOrder = args.sortOrder === void 0 ? void 0 : finiteNumber(args.sortOrder);
569
- if (!title) return {
570
- ok: false,
571
- error: "title is required"
572
- };
573
- if (args.status !== void 0 && !status) return {
574
- ok: false,
575
- error: "Invalid milestone status"
576
- };
577
- if (args.targetAt !== void 0 && targetAt === void 0) return {
578
- ok: false,
579
- error: "Invalid targetAt"
580
- };
581
- if (args.sortOrder !== void 0 && sortOrder === void 0) return {
582
- ok: false,
583
- error: "Invalid sortOrder"
584
- };
585
- const input = {
586
- title,
587
- description: trimString(args.description),
588
- status,
589
- targetAt,
590
- sortOrder
591
- };
568
+ ...pickDefined(args, [
569
+ "title",
570
+ "description",
571
+ "status",
572
+ "targetAt",
573
+ "sortOrder"
574
+ ])
575
+ });
576
+ else if (command === "create_update") {
577
+ if (args.idempotencyKey !== void 0 && args.expectedVersion === void 0) return {
578
+ ok: false,
579
+ error: "Stable retries require the original expectedVersion"
580
+ };
581
+ input = ProjectUpdateCreateInputSchema.parse({
582
+ projectId,
583
+ ...pickDefined(args, [
584
+ "health",
585
+ "summary",
586
+ "progress",
587
+ "risks",
588
+ "nextSteps"
589
+ ]),
590
+ expectedVersion: args.expectedVersion === void 0 ? projects.get(projectId)?.version : args.expectedVersion
591
+ });
592
+ } else {
593
+ const id = trimString(args.milestoneId);
594
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
595
+ ok: false,
596
+ error: "Stable retries require the original expectedRevision"
597
+ };
598
+ const common = {
599
+ projectId,
600
+ id,
601
+ expectedRevision: args.expectedRevision === void 0 ? projects.listMilestones(projectId).find((item) => item.id === id)?.updatedAt : args.expectedRevision
602
+ };
603
+ input = command === "delete_milestone" ? ProjectMilestoneDeleteInputSchema.parse(common) : ProjectMilestoneUpdateInputSchema.parse({
604
+ ...common,
605
+ patch: pickDefined(args, [
606
+ "title",
607
+ "description",
608
+ "status",
609
+ "targetAt",
610
+ "sortOrder"
611
+ ])
612
+ });
613
+ }
592
614
  if (dryRun) return {
593
615
  ok: true,
594
616
  dryRun: true,
595
- action: "create_project_milestone",
596
- projectId,
617
+ action: command,
597
618
  input
598
619
  };
599
- return {
600
- ok: true,
601
- milestone: projects.createMilestone(projectId, input),
602
- project: projects.get(projectId)
603
- };
604
- }
605
- if (command === "update_milestone") {
606
- if (!projectId) return {
607
- ok: false,
608
- error: "projectId is required"
609
- };
610
- const milestoneId = trimString(args.milestoneId);
611
- if (!milestoneId) return {
612
- ok: false,
613
- error: "milestoneId is required"
614
- };
615
- const patch = {
616
- ...args.title !== void 0 ? { title: trimString(args.title) ?? "" } : {},
617
- ...args.description !== void 0 ? { description: optionalString(args.description) } : {},
618
- ...args.status !== void 0 ? { status: enumValue(args.status, MILESTONE_STATUSES) } : {},
619
- ...args.targetAt !== void 0 ? { targetAt: nullableFiniteNumber(args.targetAt) } : {},
620
- ...args.sortOrder !== void 0 ? { sortOrder: finiteNumber(args.sortOrder) } : {}
621
- };
622
- if (args.status !== void 0 && patch.status === void 0) return {
623
- ok: false,
624
- error: "Invalid milestone status"
625
- };
626
- if (args.targetAt !== void 0 && patch.targetAt === void 0) return {
627
- ok: false,
628
- error: "Invalid targetAt"
629
- };
630
- if (args.sortOrder !== void 0 && patch.sortOrder === void 0) return {
631
- ok: false,
632
- error: "Invalid sortOrder"
633
- };
634
- if (dryRun) return {
635
- ok: true,
636
- dryRun: true,
637
- action: "update_project_milestone",
638
- projectId,
639
- milestoneId,
640
- patch
641
- };
642
- return {
643
- ok: true,
644
- milestone: projects.updateMilestone(projectId, milestoneId, patch),
645
- project: projects.get(projectId)
646
- };
647
- }
648
- if (command === "list_updates") {
649
- if (!projectId) return {
650
- ok: false,
651
- error: "projectId is required"
652
- };
653
- return {
654
- ok: true,
655
- projectId,
656
- items: projects.listUpdates(projectId, boundedLimit(args.limit))
657
- };
658
- }
659
- if (command === "create_update") {
660
- if (!projectId) return {
661
- ok: false,
662
- error: "projectId is required"
663
- };
664
- const health = enumValue(args.health, PROJECT_HEALTHS);
665
- const summary = trimString(args.summary);
666
- const progress = args.progress === void 0 ? void 0 : stringArray(args.progress);
667
- const risks = args.risks === void 0 ? void 0 : stringArray(args.risks);
668
- const nextSteps = args.nextSteps === void 0 ? void 0 : stringArray(args.nextSteps);
669
- if (!health) return {
670
- ok: false,
671
- error: "health is required"
672
- };
673
- if (!summary) return {
674
- ok: false,
675
- error: "summary is required"
676
- };
677
- if (args.progress !== void 0 && !progress) return {
678
- ok: false,
679
- error: "Invalid progress"
680
- };
681
- if (args.risks !== void 0 && !risks) return {
682
- ok: false,
683
- error: "Invalid risks"
684
- };
685
- if (args.nextSteps !== void 0 && !nextSteps) return {
686
- ok: false,
687
- error: "Invalid nextSteps"
688
- };
689
- const input = {
690
- health,
691
- summary,
692
- progress,
693
- risks,
694
- nextSteps,
620
+ const caller = {
621
+ principalId: "agent:" + (deps.getCurrentAgentId?.() ?? "main"),
622
+ surface: "agent",
623
+ scopes: ["workspace.write"],
695
624
  actor: {
696
625
  kind: "agent",
697
- agentId: deps.getCurrentAgentId?.(),
698
- conversationId: deps.getCurrentConversationId?.()
699
- }
700
- };
701
- if (dryRun) return {
702
- ok: true,
703
- dryRun: true,
704
- action: "create_project_update",
705
- projectId,
706
- input
707
- };
708
- return {
709
- ok: true,
710
- update: projects.createUpdate(projectId, input),
711
- project: projects.get(projectId)
626
+ id: deps.getCurrentAgentId?.()
627
+ },
628
+ authorize: deps.authorizeCapability ?? (() => true)
712
629
  };
630
+ const result = await capabilities.call(operation, input, caller, {
631
+ ...capabilities.describe(operation, caller),
632
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
633
+ });
634
+ return (command === "create_update" ? ProjectUpdateOutputSchema : command === "delete_milestone" ? ProjectMilestoneDeleteOutputSchema : ProjectMilestoneOutputSchema).parse(result);
713
635
  }
714
636
  return {
715
637
  ok: false,
716
638
  error: `Unsupported project command: ${command}`
717
639
  };
718
640
  }
719
- async function handleAutomation(command, args, deps, dryRun) {
641
+ async function handleAutomation(command, args, deps, dryRun, capabilities) {
720
642
  const automations = deps.getAutomationService?.();
721
643
  if (!automations) return {
722
644
  ok: false,
723
645
  error: "Automation service is unavailable"
724
646
  };
725
- if (command === "list") {
726
- const projectId = currentProjectId(args, deps);
727
- const projectError = automationProjectError(projectId, deps);
728
- if (projectError) return {
729
- ok: false,
730
- error: projectError
731
- };
732
- return {
733
- ok: true,
734
- items: await automations.list({ projectId }),
735
- ...projectId ? { projectId } : {}
736
- };
737
- }
738
- if (command === "get") {
739
- const id = trimString(args.automationId) ?? trimString(args.id);
740
- if (!id) return {
741
- ok: false,
742
- error: "automationId is required"
647
+ const invoke = async (operation, input) => {
648
+ const caller = {
649
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
650
+ surface: "agent",
651
+ scopes: ["automations.write"],
652
+ authorize: deps.authorizeCapability ?? (() => true)
743
653
  };
744
- const automation = await automations.get(id);
745
- return automation ? {
654
+ try {
655
+ return (operation === "xopc.automations.delete" ? AutomationDeleteOutputSchema : operation === "xopc.automations.cancel" ? AutomationCancelOutputSchema : operation === "xopc.automations.read" ? AutomationReadOutputSchema : operation === "xopc.automations.read_all" ? AutomationReadAllOutputSchema : operation === "xopc.automations.run" || operation === "xopc.automations.rerun" ? AutomationRunMutationOutputSchema : AutomationMutationOutputSchema).parse(await capabilities.call(operation, input, caller, {
656
+ ...capabilities.describe(operation, caller),
657
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
658
+ }));
659
+ } catch (error) {
660
+ if (error instanceof CapabilityError) return {
661
+ ok: false,
662
+ error: error.message,
663
+ code: error.code
664
+ };
665
+ throw error;
666
+ }
667
+ };
668
+ if (command === "cancel" || command === "read" || command === "read_all") {
669
+ const input = command === "read_all" ? AutomationReadAllInputSchema.parse({ projectId: trimString(args.projectId) }) : CapabilityResourceInputSchema.parse({ id: trimString(args.runId) ?? trimString(args.id) });
670
+ if (dryRun) return {
746
671
  ok: true,
747
- automation
748
- } : {
749
- ok: false,
750
- error: `Automation not found: ${id}`
672
+ dryRun: true,
673
+ action: command,
674
+ input
751
675
  };
676
+ return invoke(`xopc.automations.${command}`, input);
752
677
  }
753
678
  if (command === "create") {
754
679
  const source = automationPayload(args, "automation");
755
680
  const projectId = trimString(args.projectId) ?? trimString(source.projectId) ?? currentProjectId({}, deps);
756
- const projectError = automationProjectError(projectId, deps);
757
- if (projectError) return {
758
- ok: false,
759
- error: projectError
760
- };
761
- const input = CreateAutomationSchema.parse({
681
+ if (dryRun) {
682
+ const projectError = automationProjectError(projectId, deps);
683
+ if (projectError) return {
684
+ ok: false,
685
+ error: projectError
686
+ };
687
+ }
688
+ const input = AutomationCreateCapabilityInputSchema.parse({
762
689
  ...pickDefined(source, [
763
690
  "id",
764
691
  "name",
@@ -782,10 +709,10 @@ async function handleAutomation(command, args, deps, dryRun) {
782
709
  input,
783
710
  projectId
784
711
  };
712
+ const result = await invoke("xopc.automations.create", input);
785
713
  return {
786
- ok: true,
787
- automation: await automations.create(input),
788
- ...projectId ? { projectId } : {}
714
+ ...result,
715
+ ...result.ok && projectId ? { projectId } : {}
789
716
  };
790
717
  }
791
718
  if (command === "update") {
@@ -795,7 +722,7 @@ async function handleAutomation(command, args, deps, dryRun) {
795
722
  error: "automationId is required"
796
723
  };
797
724
  const source = automationPayload(args, "patch");
798
- const patch = UpdateAutomationSchema.parse(pickDefined(source, [
725
+ const patch = AutomationUpdatePatchSchema.parse(pickDefined(source, [
799
726
  "name",
800
727
  "description",
801
728
  "projectId",
@@ -809,11 +736,13 @@ async function handleAutomation(command, args, deps, dryRun) {
809
736
  "reliability",
810
737
  "state"
811
738
  ]));
812
- const projectError = automationProjectError(patch.projectId, deps);
813
- if (projectError) return {
814
- ok: false,
815
- error: projectError
816
- };
739
+ if (dryRun) {
740
+ const projectError = automationProjectError(patch.projectId, deps);
741
+ if (projectError) return {
742
+ ok: false,
743
+ error: projectError
744
+ };
745
+ }
817
746
  if (dryRun) return {
818
747
  ok: true,
819
748
  dryRun: true,
@@ -821,32 +750,34 @@ async function handleAutomation(command, args, deps, dryRun) {
821
750
  automationId: id,
822
751
  patch
823
752
  };
824
- const automation = await automations.update(id, patch);
825
- return automation ? {
826
- ok: true,
827
- automation
828
- } : {
753
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
754
+ ok: false,
755
+ error: "Idempotent automation changes require expectedRevision from the original read"
756
+ };
757
+ const expectedRevision = args.expectedRevision !== void 0 ? args.expectedRevision : (await automations.get(id))?.updatedAtMs;
758
+ if (expectedRevision === void 0) return {
829
759
  ok: false,
830
760
  error: `Automation not found: ${id}`
831
761
  };
762
+ return invoke("xopc.automations.update", {
763
+ id,
764
+ patch,
765
+ expectedRevision
766
+ });
832
767
  }
833
- if (command === "history") {
834
- const automationId = trimString(args.automationId) ?? trimString(args.id);
835
- const projectId = automationId ? void 0 : currentProjectId(args, deps);
836
- const projectError = automationProjectError(projectId, deps);
837
- if (projectError) return {
768
+ if (command === "rerun") {
769
+ const runId = trimString(args.runId) ?? trimString(args.id);
770
+ if (!runId) return {
838
771
  ok: false,
839
- error: projectError
772
+ error: "runId is required"
840
773
  };
841
- return {
774
+ if (dryRun) return {
842
775
  ok: true,
843
- items: await automations.listRuns({
844
- automationId,
845
- projectId,
846
- limit: boundedLimit(args.limit, 20, 50)
847
- }),
848
- ...projectId ? { projectId } : {}
776
+ dryRun: true,
777
+ action: "rerun_automation",
778
+ runId
849
779
  };
780
+ return invoke("xopc.automations.rerun", { id: runId });
850
781
  }
851
782
  if (![
852
783
  "delete",
@@ -862,10 +793,37 @@ async function handleAutomation(command, args, deps, dryRun) {
862
793
  ok: false,
863
794
  error: "automationId is required"
864
795
  };
865
- const current = await automations.get(id);
866
- if (!current) return {
867
- ok: false,
868
- error: `Automation not found: ${id}`
796
+ if (!dryRun && command === "run") return invoke("xopc.automations.run", { id });
797
+ if (!dryRun && command === "delete") {
798
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
799
+ ok: false,
800
+ error: "Idempotent deletion requires the original expectedRevision"
801
+ };
802
+ return invoke("xopc.automations.delete", {
803
+ id,
804
+ expectedRevision: args.expectedRevision !== void 0 ? args.expectedRevision : (await automations.get(id))?.updatedAtMs ?? null
805
+ });
806
+ }
807
+ if (!dryRun && (command === "pause" || command === "resume")) {
808
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
809
+ ok: false,
810
+ error: "Idempotent automation changes require expectedRevision from the original read"
811
+ };
812
+ const expectedRevision = args.expectedRevision !== void 0 ? args.expectedRevision : (await automations.get(id))?.updatedAtMs;
813
+ if (expectedRevision === void 0) return {
814
+ ok: false,
815
+ error: `Automation not found: ${id}`
816
+ };
817
+ return invoke("xopc.automations.set_enabled", {
818
+ id,
819
+ enabled: command === "resume",
820
+ expectedRevision
821
+ });
822
+ }
823
+ const current = await automations.get(id);
824
+ if (!current) return {
825
+ ok: false,
826
+ error: `Automation not found: ${id}`
869
827
  };
870
828
  if (dryRun) return {
871
829
  ok: true,
@@ -874,75 +832,33 @@ async function handleAutomation(command, args, deps, dryRun) {
874
832
  automationId: id,
875
833
  automation: current
876
834
  };
877
- if (command === "delete") return {
878
- ok: true,
879
- removed: await automations.remove(id),
880
- automation: current
881
- };
882
- if (command === "run") return {
883
- ok: true,
884
- automation: current,
885
- run: await automations.runNow(id)
886
- };
887
- if (command === "pause" || command === "resume") {
888
- const automation = command === "pause" ? await automations.pause(id) : await automations.resume(id);
889
- return automation ? {
890
- ok: true,
891
- automation
892
- } : {
893
- ok: false,
894
- error: `Automation not found: ${id}`
895
- };
896
- }
897
835
  return {
898
836
  ok: false,
899
837
  error: `Automation command failed: ${command}`
900
838
  };
901
839
  }
902
- async function handleNote(command, args, deps, dryRun) {
840
+ async function handleNote(command, args, deps, dryRun, capabilities) {
903
841
  const notes = deps.getNotesService?.();
904
842
  if (!notes) return {
905
843
  ok: false,
906
844
  error: "Notes service is unavailable"
907
845
  };
908
- if (command === "list") {
909
- const projectId = currentProjectId(args, deps);
910
- return {
911
- ok: true,
912
- ...await notes.listNotes({
913
- status: enumValue(args.status, NOTE_STATUSES),
914
- kind: enumValue(args.kind, NOTE_KINDS),
915
- tag: trimString(args.tag),
916
- projectId,
917
- search: trimString(args.search),
918
- pinned: typeof args.pinned === "boolean" ? args.pinned : void 0,
919
- limit: boundedLimit(args.limit),
920
- offset: offset(args.offset),
921
- sortBy: enumValue(args.sortBy, new Set([
922
- "createdAt",
923
- "updatedAt",
924
- "lastOpenedAt"
925
- ])),
926
- sortOrder: enumValue(args.sortOrder, new Set(["asc", "desc"]))
927
- }),
928
- ...projectId ? { projectId } : {}
929
- };
930
- }
931
- if (command === "get") {
932
- const id = trimString(args.noteId) ?? trimString(args.id);
933
- if (!id) return {
934
- ok: false,
935
- error: "noteId is required"
936
- };
937
- const note = await notes.getNote(id);
938
- return note ? {
939
- ok: true,
940
- note
941
- } : {
942
- ok: false,
943
- error: `Note not found: ${id}`
846
+ const invoke = async (operation, input) => {
847
+ const context = {
848
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
849
+ surface: "agent",
850
+ scopes: ["workspace.write"],
851
+ authorize: deps.authorizeCapability ?? (() => true),
852
+ actor: {
853
+ kind: "agent",
854
+ id: deps.getCurrentAgentId?.() ?? "main"
855
+ }
944
856
  };
945
- }
857
+ return NoteGetOutputSchema.parse(await capabilities.call(operation, input, context, {
858
+ ...capabilities.describe(operation, context),
859
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
860
+ }));
861
+ };
946
862
  if (command === "create") {
947
863
  const projectId = currentProjectId(args, deps);
948
864
  const projectService = projectId ? deps.getProjectService?.() : void 0;
@@ -971,21 +887,9 @@ async function handleNote(command, args, deps, dryRun) {
971
887
  input,
972
888
  projectId
973
889
  };
974
- const note = await notes.createNote(input);
975
- if (project) new ObjectLinkService().create({
976
- id: `note:${note.id}:project:${project.id}`,
977
- from: {
978
- kind: "note",
979
- id: note.id,
980
- title: note.title
981
- },
982
- to: {
983
- kind: "project",
984
- id: project.id,
985
- title: project.name
986
- },
987
- relation: "belongs_to",
988
- source: "user"
890
+ const { note } = await invoke("xopc.notes.create", {
891
+ ...input,
892
+ projectId
989
893
  });
990
894
  return {
991
895
  ok: true,
@@ -1013,34 +917,15 @@ async function handleNote(command, args, deps, dryRun) {
1013
917
  heading,
1014
918
  content
1015
919
  };
1016
- const note = await notes.appendTextToNote(id, content, heading);
1017
- return note ? {
920
+ const { note } = await invoke("xopc.notes.append", {
921
+ id,
922
+ content,
923
+ heading,
924
+ expectedRevision: args.expectedRevision
925
+ });
926
+ return {
1018
927
  ok: true,
1019
928
  note
1020
- } : {
1021
- ok: false,
1022
- error: `Note not found: ${id}`
1023
- };
1024
- }
1025
- if (command === "preview_edit") {
1026
- const id = trimString(args.noteId) ?? trimString(args.id);
1027
- const instruction = trimString(args.instruction);
1028
- if (!id) return {
1029
- ok: false,
1030
- error: "noteId is required"
1031
- };
1032
- if (!instruction) return {
1033
- ok: false,
1034
- error: "instruction is required"
1035
- };
1036
- const markdown = typeof args.markdown === "string" ? args.markdown : void 0;
1037
- const result = await notes.createAiEditPatch(id, instruction, markdown);
1038
- return result ? {
1039
- ok: true,
1040
- ...result
1041
- } : {
1042
- ok: false,
1043
- error: `Note not found: ${id}`
1044
929
  };
1045
930
  }
1046
931
  if (command === "update") {
@@ -1079,6 +964,10 @@ async function handleNote(command, args, deps, dryRun) {
1079
964
  ok: false,
1080
965
  error: "Invalid note status"
1081
966
  };
967
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
968
+ ok: false,
969
+ error: "Idempotent note updates require expectedRevision from the original read"
970
+ };
1082
971
  if (dryRun) return {
1083
972
  ok: true,
1084
973
  dryRun: true,
@@ -1086,14 +975,20 @@ async function handleNote(command, args, deps, dryRun) {
1086
975
  noteId: id,
1087
976
  patch
1088
977
  };
1089
- const note = await notes.updateNote(id, patch, "ai_edit");
1090
- return note ? {
1091
- ok: true,
1092
- note
1093
- } : {
978
+ const current = await notes.getNote(id);
979
+ if (!current) return {
1094
980
  ok: false,
1095
981
  error: `Note not found: ${id}`
1096
982
  };
983
+ const { note } = await invoke("xopc.notes.update", {
984
+ id,
985
+ patch,
986
+ expectedRevision: args.expectedRevision ?? current.remoteVersion ?? 1
987
+ });
988
+ return {
989
+ ok: true,
990
+ note
991
+ };
1097
992
  }
1098
993
  if (command === "delete") {
1099
994
  const id = trimString(args.noteId) ?? trimString(args.id);
@@ -1114,13 +1009,39 @@ async function handleNote(command, args, deps, dryRun) {
1114
1009
  error: `Note not found: ${id}`
1115
1010
  };
1116
1011
  }
1117
- return await notes.deleteNote(id) ? {
1118
- ok: true,
1119
- removed: true,
1120
- noteId: id
1121
- } : {
1012
+ if (args.idempotencyKey !== void 0 && args.expectedRevision === void 0) return {
1122
1013
  ok: false,
1123
- error: `Note not found: ${id}`
1014
+ error: "Stable retries require the original expectedRevision"
1015
+ };
1016
+ let expectedRevision = args.expectedRevision;
1017
+ if (expectedRevision === void 0) {
1018
+ const note = await notes.getNote(id);
1019
+ if (!note) return {
1020
+ ok: false,
1021
+ error: `Note not found: ${id}`
1022
+ };
1023
+ expectedRevision = note.remoteVersion ?? 1;
1024
+ }
1025
+ const caller = {
1026
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1027
+ surface: "agent",
1028
+ scopes: ["workspace.write"],
1029
+ authorize: deps.authorizeCapability ?? (() => true)
1030
+ };
1031
+ const operation = "xopc.notes.delete";
1032
+ const result = NoteDeleteOutputSchema.parse(await capabilities.call(operation, {
1033
+ id,
1034
+ expectedRevision,
1035
+ revokeShares: args.revokeShares
1036
+ }, caller, {
1037
+ ...capabilities.describe(operation, caller),
1038
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
1039
+ }));
1040
+ return {
1041
+ ok: true,
1042
+ removed: result.deleted,
1043
+ noteId: id,
1044
+ revokedShares: result.revokedShares
1124
1045
  };
1125
1046
  }
1126
1047
  return {
@@ -1128,77 +1049,46 @@ async function handleNote(command, args, deps, dryRun) {
1128
1049
  error: `Unsupported note command: ${command}`
1129
1050
  };
1130
1051
  }
1131
- async function handleTask(command, args, deps, dryRun) {
1052
+ async function handleTask(command, args, deps, dryRun, capabilities) {
1132
1053
  const tasks = new TaskRepository();
1133
- const dependencies = new TaskDependencyService();
1134
- const context = new TaskContextRepository();
1135
- const runs = new TaskRunRepository();
1136
- const projector = new TaskReadModelProjector();
1137
- const deletion = new TaskDeletionService(tasks, runs);
1138
- if (command === "list") {
1139
- const projectId = currentProjectId(args, deps);
1140
- const phase = enumValue(args.phase, TASK_PHASES);
1141
- const priority = enumValue(args.priority, TASK_PRIORITIES);
1142
- const search = trimString(args.search)?.toLocaleLowerCase();
1143
- const start = offset(args.offset) ?? 0;
1144
- const limit = boundedLimit(args.limit);
1145
- const matching = (projectId ? tasks.listByProject(projectId, 200) : tasks.list({ limit: 200 })).filter((task) => (!phase || task.phase === phase) && (!priority || task.priority === priority) && (!search || `${task.title}\n${task.contract?.objective ?? ""}`.toLocaleLowerCase().includes(search)));
1146
- return {
1147
- ok: true,
1148
- items: matching.slice(start, start + limit),
1149
- total: matching.length,
1150
- ...projectId ? { projectId } : {}
1054
+ const deletion = new TaskDeletionService(tasks, new TaskRunRepository());
1055
+ const invokeRelation = (operation, input) => {
1056
+ const caller = {
1057
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1058
+ surface: "agent",
1059
+ scopes: ["tasks.write"],
1060
+ actor: {
1061
+ kind: "agent",
1062
+ id: deps.getCurrentAgentId?.() ?? "main"
1063
+ },
1064
+ authorize: deps.authorizeCapability ?? (() => true)
1151
1065
  };
1152
- }
1153
- if (command === "get") {
1066
+ return capabilities.call(operation, input, caller, {
1067
+ ...capabilities.describe(operation, caller),
1068
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
1069
+ });
1070
+ };
1071
+ if (command === "delete") {
1154
1072
  const id = trimString(args.taskId) ?? trimString(args.id);
1155
1073
  if (!id) return {
1156
1074
  ok: false,
1157
1075
  error: "taskId is required"
1158
1076
  };
1159
- const task = tasks.get(id);
1160
- if (!task) return {
1161
- ok: false,
1162
- error: `Task not found: ${id}`
1163
- };
1164
- const model = projector.project(task);
1165
- return {
1077
+ const result = dryRun ? deletion.inspect(id) : TaskDeleteOutputSchema.parse(await invokeRelation("xopc.tasks.delete", {
1078
+ taskId: id,
1079
+ expectedVersion: args.expectedVersion
1080
+ }));
1081
+ if (result.ok === true) return dryRun ? {
1166
1082
  ok: true,
1167
- task,
1168
- model,
1169
- operationalState: model.operationalState,
1170
- attention: model.attention,
1171
- allowedCommands: model.allowedCommands,
1172
- dependencies: dependencies.listDependencies(id),
1173
- dependents: dependencies.listDependents(id),
1174
- context: context.list(id),
1175
- authorityGrants: context.listActiveGrants(id),
1176
- runs: runs.listByTask(id),
1177
- receipts: runs.listReceipts(id),
1178
- waits: runs.listActiveWaits(id)
1179
- };
1180
- }
1181
- if (command === "delete") {
1182
- const id = trimString(args.taskId) ?? trimString(args.id);
1183
- if (!id) return {
1184
- ok: false,
1185
- error: "taskId is required"
1083
+ dryRun: true,
1084
+ action: "delete_task",
1085
+ taskId: id,
1086
+ task: result.task
1087
+ } : {
1088
+ ok: true,
1089
+ removed: true,
1090
+ taskId: id
1186
1091
  };
1187
- const result = dryRun ? deletion.inspect(id) : deletion.delete(id);
1188
- if (result.ok === true) {
1189
- if (!dryRun) deps.dispatchTaskEvents?.();
1190
- return dryRun ? {
1191
- ok: true,
1192
- dryRun: true,
1193
- action: "delete_task",
1194
- taskId: id,
1195
- task: result.task
1196
- } : {
1197
- ok: true,
1198
- removed: true,
1199
- taskId: id
1200
- };
1201
- }
1202
1092
  return result.reason === "active_run" ? {
1203
1093
  ok: false,
1204
1094
  error: "Cancel the active TaskRun before deleting the Task",
@@ -1326,17 +1216,26 @@ async function handleTask(command, args, deps, dryRun) {
1326
1216
  input,
1327
1217
  dependsOnTaskIds
1328
1218
  };
1329
- const created = new TaskApplicationService().create(input, {
1330
- kind: "agent",
1331
- id: agentId
1332
- });
1219
+ const capabilityContext = {
1220
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1221
+ surface: "agent",
1222
+ scopes: ["tasks.write"],
1223
+ actor: {
1224
+ kind: "agent",
1225
+ id: deps.getCurrentAgentId?.() ?? "main"
1226
+ },
1227
+ authorize: deps.authorizeCapability ?? (() => true)
1228
+ };
1229
+ const { idempotencyKey, ...capabilityInput } = input;
1230
+ const created = TaskMutationOutputSchema.parse(await capabilities.call("xopc.tasks.create", capabilityInput, capabilityContext, {
1231
+ ...capabilities.describe("xopc.tasks.create", capabilityContext),
1232
+ idempotencyKey
1233
+ }));
1333
1234
  if (created.ok === false) return {
1334
1235
  ok: false,
1335
1236
  error: created.reason,
1336
1237
  ...created
1337
1238
  };
1338
- if (created.runId) deps.dispatchTaskRuns?.();
1339
- else deps.dispatchTaskEvents?.();
1340
1239
  return {
1341
1240
  ok: true,
1342
1241
  task: created.model.task,
@@ -1369,40 +1268,11 @@ async function handleTask(command, args, deps, dryRun) {
1369
1268
  expectedVersion,
1370
1269
  dependsOnTaskIds
1371
1270
  };
1372
- try {
1373
- const task = runSqliteWriteTransaction((db) => {
1374
- const changed = dependencies.replace({
1375
- taskId: id,
1376
- dependsOnTaskIds,
1377
- expectedVersion
1378
- });
1379
- enqueueTaskChangedEvent(db, {
1380
- taskId: changed.id,
1381
- projectId: changed.projectId,
1382
- version: changed.version,
1383
- changedFields: ["dependencies"],
1384
- actor: {
1385
- kind: "agent",
1386
- id: deps.getCurrentAgentId?.()
1387
- }
1388
- });
1389
- return changed;
1390
- });
1391
- deps.dispatchTaskEvents?.();
1392
- return {
1393
- ok: true,
1394
- task,
1395
- dependencies: dependencies.listDependencies(id),
1396
- dependents: dependencies.listDependents(id)
1397
- };
1398
- } catch (error) {
1399
- if (!(error instanceof TaskDependencyError)) throw error;
1400
- return {
1401
- ok: false,
1402
- error: error.message,
1403
- reason: error.code
1404
- };
1405
- }
1271
+ return invokeRelation("xopc.tasks.update_dependencies", {
1272
+ taskId: id,
1273
+ dependsOnTaskIds,
1274
+ expectedVersion
1275
+ });
1406
1276
  }
1407
1277
  if (command === "add_context") {
1408
1278
  const id = trimString(args.taskId) ?? trimString(args.id);
@@ -1441,24 +1311,11 @@ async function handleTask(command, args, deps, dryRun) {
1441
1311
  action: "add_task_context",
1442
1312
  input
1443
1313
  };
1444
- const task = tasks.require(id);
1445
- const edge = runSqliteWriteTransaction((db) => {
1446
- const created = context.add(input);
1447
- enqueueTaskChangedEvent(db, {
1448
- taskId: task.id,
1449
- projectId: task.projectId,
1450
- version: task.version,
1451
- changedFields: ["context"],
1452
- actor: input.createdBy
1453
- });
1454
- return created;
1314
+ return invokeRelation("xopc.tasks.add_context", {
1315
+ taskId: id,
1316
+ edge: parsed.data,
1317
+ expectedVersion: args.expectedVersion
1455
1318
  });
1456
- deps.dispatchTaskEvents?.();
1457
- return {
1458
- ok: true,
1459
- edge,
1460
- context: context.list(id)
1461
- };
1462
1319
  }
1463
1320
  if (command === "remove_context") {
1464
1321
  const id = trimString(args.taskId) ?? trimString(args.id);
@@ -1478,32 +1335,11 @@ async function handleTask(command, args, deps, dryRun) {
1478
1335
  taskId: id,
1479
1336
  edgeId
1480
1337
  };
1481
- const task = tasks.get(id);
1482
- const actor = {
1483
- kind: "agent",
1484
- id: deps.getCurrentAgentId?.()
1485
- };
1486
- const removed = task ? runSqliteWriteTransaction((db) => {
1487
- const didRemove = context.remove(id, edgeId);
1488
- if (didRemove) enqueueTaskChangedEvent(db, {
1489
- taskId: task.id,
1490
- projectId: task.projectId,
1491
- version: task.version,
1492
- changedFields: ["context"],
1493
- actor
1494
- });
1495
- return didRemove;
1496
- }) : false;
1497
- if (removed) deps.dispatchTaskEvents?.();
1498
- return removed ? {
1499
- ok: true,
1338
+ return invokeRelation("xopc.tasks.remove_context", {
1500
1339
  taskId: id,
1501
1340
  edgeId,
1502
- context: context.list(id)
1503
- } : {
1504
- ok: false,
1505
- error: `Task context edge not found: ${edgeId}`
1506
- };
1341
+ expectedVersion: args.expectedVersion
1342
+ });
1507
1343
  }
1508
1344
  if (command === "command") {
1509
1345
  const id = trimString(args.taskId) ?? trimString(args.id);
@@ -1542,24 +1378,30 @@ async function handleTask(command, args, deps, dryRun) {
1542
1378
  command: parsedCommand.data,
1543
1379
  expectedVersion
1544
1380
  };
1545
- const result = new TaskApplicationService().execute({
1546
- taskId: id,
1547
- idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID(),
1548
- expectedVersion,
1549
- command: parsedCommand.data,
1381
+ const capabilityContext = {
1382
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1383
+ surface: "agent",
1384
+ scopes: ["tasks.write"],
1550
1385
  actor: {
1551
1386
  kind: "agent",
1552
- id: deps.getCurrentAgentId?.()
1553
- }
1554
- });
1387
+ id: deps.getCurrentAgentId?.() ?? "main"
1388
+ },
1389
+ authorize: deps.authorizeCapability ?? (() => true)
1390
+ };
1391
+ const result = TaskMutationOutputSchema.parse(await capabilities.call("xopc.tasks.command", {
1392
+ taskId: id,
1393
+ expectedVersion,
1394
+ command: parsedCommand.data
1395
+ }, capabilityContext, {
1396
+ ...capabilities.describe("xopc.tasks.command", capabilityContext),
1397
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
1398
+ }));
1555
1399
  if (result.ok === false) return {
1556
1400
  ok: false,
1557
1401
  error: result.reason,
1558
1402
  command: parsedCommand.data,
1559
1403
  ...result
1560
1404
  };
1561
- if (result.runId) deps.dispatchTaskRuns?.();
1562
- else deps.dispatchTaskEvents?.();
1563
1405
  return {
1564
1406
  ok: true,
1565
1407
  task: result.model.task,
@@ -1573,109 +1415,77 @@ async function handleTask(command, args, deps, dryRun) {
1573
1415
  error: `Unsupported task command: ${command}`
1574
1416
  };
1575
1417
  }
1576
- async function handleTaskRun(command, args, dryRun, deps) {
1577
- const runs = new TaskRunRepository();
1578
- if (command === "list") {
1579
- const taskId = trimString(args.taskId);
1580
- if (!taskId) return {
1581
- ok: false,
1582
- error: "taskId is required"
1583
- };
1584
- const limit = boundedLimit(args.limit);
1585
- return {
1586
- ok: true,
1587
- taskId,
1588
- items: runs.listByTask(taskId).slice(0, limit),
1589
- receipts: runs.listReceipts(taskId, limit),
1590
- activeWaits: runs.listActiveWaits(taskId)
1591
- };
1592
- }
1593
- if (command === "get") {
1594
- const runId = trimString(args.runId) ?? trimString(args.id);
1595
- if (!runId) return {
1596
- ok: false,
1597
- error: "runId is required"
1598
- };
1599
- const run = runs.get(runId);
1600
- if (!run) return {
1601
- ok: false,
1602
- error: `TaskRun not found: ${runId}`
1603
- };
1604
- return {
1605
- ok: true,
1606
- run,
1607
- receipt: runs.getReceipt(runId),
1608
- events: runs.listEvents(runId),
1609
- activeWaits: runs.listActiveWaits(run.taskId)
1610
- };
1611
- }
1612
- if (command === "cancel") {
1613
- const runId = trimString(args.runId) ?? trimString(args.id);
1614
- const expectedVersion = finiteNumber(args.expectedVersion);
1615
- if (!runId) return {
1616
- ok: false,
1617
- error: "runId is required"
1618
- };
1619
- if (expectedVersion === void 0 || !Number.isInteger(expectedVersion) || expectedVersion < 1) return {
1620
- ok: false,
1621
- error: "expectedVersion is required"
1622
- };
1623
- const run = runs.get(runId);
1624
- if (!run) return {
1625
- ok: false,
1626
- error: `TaskRun not found: ${runId}`
1627
- };
1628
- if (run.version !== expectedVersion) return {
1629
- ok: false,
1630
- error: "TaskRun changed",
1631
- reason: "conflict",
1632
- run
1633
- };
1634
- const task = new TaskRepository().require(run.taskId);
1635
- const reason = trimString(args.reason) ?? "TaskRun cancelled by agent";
1418
+ async function handleTaskRun(command, args, dryRun, deps, capabilities) {
1419
+ if (command === "feedback") {
1420
+ const input = TaskRunFeedbackInputSchema.parse({
1421
+ id: args.runId ?? args.id,
1422
+ rating: args.rating,
1423
+ reason: args.reason
1424
+ });
1636
1425
  if (dryRun) return {
1637
1426
  ok: true,
1638
1427
  dryRun: true,
1639
- action: "cancel_task_run",
1640
- runId,
1641
- expectedVersion,
1642
- reason
1428
+ action: "task_run_feedback",
1429
+ input
1643
1430
  };
1644
- const result = new TaskApplicationService().completeRun({
1645
- runId,
1646
- expectedRunVersion: expectedVersion,
1431
+ const caller = {
1432
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1433
+ surface: "agent",
1434
+ scopes: ["tasks.write"],
1647
1435
  actor: {
1648
1436
  kind: "agent",
1649
1437
  id: deps.getCurrentAgentId?.()
1650
1438
  },
1651
- terminalCode: "cancelled_by_agent",
1652
- terminalMessage: reason,
1653
- receipt: {
1654
- status: "cancelled",
1655
- summary: reason,
1656
- changes: [],
1657
- evidence: [],
1658
- verification: {
1659
- status: "unverified",
1660
- checks: []
1661
- },
1662
- remainingWork: [task.contract?.objective ?? task.title],
1663
- needsUser: false,
1664
- completionVerdict: "not_achieved"
1665
- }
1666
- });
1667
- if (result.ok === false) return {
1668
- ok: false,
1669
- error: result.reason,
1670
- ...result
1439
+ authorize: deps.authorizeCapability ?? (() => true)
1671
1440
  };
1672
- deps.dispatchTaskEvents?.();
1673
- return {
1674
- ok: true,
1675
- run: runs.get(runId),
1676
- receipt: runs.getReceipt(runId),
1677
- model: result.model
1441
+ const operation = "xopc.task_runs.feedback";
1442
+ return TaskRunFeedbackOutputSchema.parse(await capabilities.call(operation, input, caller, {
1443
+ ...capabilities.describe(operation, caller),
1444
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
1445
+ }));
1446
+ }
1447
+ if (command === "cancel") {
1448
+ const input = TaskRunCancelInputSchema.parse({
1449
+ id: args.runId ?? args.id,
1450
+ expectedVersion: args.expectedVersion,
1451
+ reason: args.reason
1452
+ });
1453
+ if (dryRun) {
1454
+ const run = new TaskRunRepository().get(input.id);
1455
+ if (!run) return {
1456
+ ok: false,
1457
+ error: "TaskRun not found"
1458
+ };
1459
+ if (run.version !== input.expectedVersion) return {
1460
+ ok: false,
1461
+ error: "TaskRun changed",
1462
+ reason: "conflict",
1463
+ run
1464
+ };
1465
+ return {
1466
+ ok: true,
1467
+ dryRun: true,
1468
+ action: "cancel_task_run",
1469
+ runId: input.id,
1470
+ expectedVersion: input.expectedVersion,
1471
+ reason: input.reason
1472
+ };
1473
+ }
1474
+ const caller = {
1475
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1476
+ surface: "agent",
1477
+ scopes: ["tasks.write"],
1478
+ actor: {
1479
+ kind: "agent",
1480
+ id: deps.getCurrentAgentId?.()
1481
+ },
1482
+ authorize: deps.authorizeCapability ?? (() => true)
1678
1483
  };
1484
+ const operation = "xopc.task_runs.cancel";
1485
+ return TaskRunCancelOutputSchema.parse(await capabilities.call(operation, input, caller, {
1486
+ ...capabilities.describe(operation, caller),
1487
+ idempotencyKey: trimString(args.idempotencyKey) ?? randomUUID()
1488
+ }));
1679
1489
  }
1680
1490
  return {
1681
1491
  ok: false,
@@ -1688,25 +1498,6 @@ async function handleLocalApp(command, args, deps, dryRun) {
1688
1498
  ok: false,
1689
1499
  error: "Local app service is unavailable"
1690
1500
  };
1691
- if (command === "list") return {
1692
- ok: true,
1693
- apps: localApps.list()
1694
- };
1695
- const id = trimString(args.localAppId) ?? trimString(args.id);
1696
- if (command === "get") {
1697
- if (!id) return {
1698
- ok: false,
1699
- error: "localAppId is required"
1700
- };
1701
- const app = localApps.get(id);
1702
- return app ? {
1703
- ok: true,
1704
- app
1705
- } : {
1706
- ok: false,
1707
- error: `Local app not found: ${id}`
1708
- };
1709
- }
1710
1501
  if (command === "create") {
1711
1502
  const name = trimString(args.name);
1712
1503
  const idea = trimString(args.idea);
@@ -1734,57 +1525,31 @@ async function handleLocalApp(command, args, deps, dryRun) {
1734
1525
  app: localApps.create(input)
1735
1526
  };
1736
1527
  }
1737
- if (command === "validate") {
1738
- if (!id) return {
1739
- ok: false,
1740
- error: "localAppId is required"
1741
- };
1742
- const app = localApps.get(id);
1743
- if (!app) return {
1744
- ok: false,
1745
- error: `Local app not found: ${id}`
1746
- };
1747
- return {
1748
- ok: true,
1749
- app,
1750
- validation: localApps.validate(id)
1751
- };
1752
- }
1753
1528
  return {
1754
1529
  ok: false,
1755
1530
  error: `Unsupported local_app command: ${command}`
1756
1531
  };
1757
1532
  }
1758
- function handleSettings(command, args) {
1759
- if (command !== "open") return {
1760
- ok: false,
1761
- error: `Unsupported settings command: ${command}`
1762
- };
1763
- const section = trimString(args.section) ?? "overview";
1764
- if (!/^[a-z0-9][a-z0-9/_-]*$/i.test(section) || section.includes("..")) return {
1765
- ok: false,
1766
- error: "Invalid settings section"
1767
- };
1768
- return {
1769
- ok: true,
1770
- settings: {
1771
- section,
1772
- title: trimString(args.title) ?? "Settings",
1773
- summary: trimString(args.summary)
1774
- }
1775
- };
1776
- }
1777
1533
  function createXopcUseTool(deps) {
1534
+ const capabilities = createProductDispatcher(deps.getNotesService, {
1535
+ getConfig: deps.getConfig,
1536
+ getProjects: deps.getProjectService,
1537
+ getWorkDiscovery: deps.getWorkDiscovery,
1538
+ getLocalApps: deps.getLocalAppService,
1539
+ getSceneAccess: deps.getSceneAccess,
1540
+ getAutomations: deps.getAutomationService,
1541
+ wake: deps.dispatchTaskRuns || deps.dispatchTaskEvents ? (runId) => runId ? deps.dispatchTaskRuns?.() : deps.dispatchTaskEvents?.() : void 0
1542
+ });
1778
1543
  return {
1779
1544
  name: "xopc_use",
1780
1545
  label: "XOPC Use",
1781
- description: "Operate first-class xopc objects through one safe entry point. Use for scenes, projects, automations, notes, tasks, TaskRuns, local apps, and exact settings jump targets instead of editing storage files directly. For non-trivial object changes, load the built-in manual first with tool_manual({ tool: \"xopc_use\" }).",
1546
+ description: "Operate first-class xopc objects through one safe entry point. Local App capabilities takes extensionId and discovers already granted bindings. Local App invoke requires extensionId, the discovered manifestDigest, capabilityId and a pinned call {majorVersion, descriptorDigest, input, idempotencyKey for writes}. Never manufacture grants or change a retry key after an uncertain write. Use for scenes, projects, automations, notes, tasks, TaskRuns, local apps, and exact settings jump targets instead of editing storage files directly. For non-trivial object changes, load the built-in manual first with tool_manual({ tool: \"xopc_use\" }).",
1782
1547
  parameters: XopcUseToolSchema,
1783
1548
  mutatesWorkspace: true,
1784
1549
  mutationScope: "external",
1785
1550
  requiresExclusiveWorkspaceLock: true,
1786
1551
  finalGuardRelevant: true,
1787
- async execute(toolCallId, input) {
1552
+ async execute(toolCallId, input, signal) {
1788
1553
  const mode = input.mode;
1789
1554
  const command = input.command.trim();
1790
1555
  const dryRun = input.dryRun === true;
@@ -1795,6 +1560,405 @@ function createXopcUseTool(deps) {
1795
1560
  dryRun
1796
1561
  };
1797
1562
  if (!command) return errorText("command is required", details);
1563
+ if (mode === "local_app" && (command === "capabilities" || command === "invoke")) {
1564
+ const apps = deps.getLocalAppService?.();
1565
+ if (!apps) return errorText("Local app service is unavailable", details);
1566
+ if (typeof args.extensionId !== "string") return errorText("extensionId is required", details);
1567
+ const manifestDigest = command === "capabilities" ? apps.getUiGrant(args.extensionId).manifestDigest : args.manifestDigest;
1568
+ if (typeof manifestDigest !== "string") return errorText("A discovered manifestDigest is required", details);
1569
+ const caller = {
1570
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1571
+ surface: "agent",
1572
+ scopes: ["gateway.admin"],
1573
+ authorize: deps.authorizeCapability ?? (() => true),
1574
+ signal
1575
+ };
1576
+ const runtime = localAppCapabilities(apps, capabilities, args.extensionId, manifestDigest, caller);
1577
+ if (command === "capabilities") return okText({
1578
+ ...details,
1579
+ result: runtime.list()
1580
+ });
1581
+ if (dryRun) return errorText("Use capabilities to inspect the pinned contract; invoke does not execute in dryRun", details);
1582
+ if (typeof args.capabilityId !== "string") return errorText("capabilityId is required", details);
1583
+ const call = CapabilityCallSchema.parse(args.call);
1584
+ return okText({
1585
+ ...details,
1586
+ result: await runtime.call(args.capabilityId, call)
1587
+ });
1588
+ }
1589
+ if (mode === "context" && command === "resolve") {
1590
+ const caller = {
1591
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1592
+ surface: "agent",
1593
+ scopes: ["gateway.admin"],
1594
+ authorize: deps.authorizeCapability ?? (() => true),
1595
+ signal
1596
+ };
1597
+ return okText({
1598
+ ...details,
1599
+ result: await capabilities.call("xopc.context.resolve", args, caller)
1600
+ });
1601
+ }
1602
+ if (mode === "scene" && ([
1603
+ "configure",
1604
+ "check",
1605
+ "notes",
1606
+ "work_item",
1607
+ "update_work_item",
1608
+ "schedule",
1609
+ "set_preferences",
1610
+ "feedback",
1611
+ "mark_read",
1612
+ "transition"
1613
+ ].includes(command) || command === "start" && !dryRun)) {
1614
+ const operation = `xopc.scenes.${command}`;
1615
+ const { requestId, idempotencyKey, workItemId, presentationId, ...fields } = args;
1616
+ if (requestId !== void 0 && typeof requestId !== "string" || idempotencyKey !== void 0 && typeof idempotencyKey !== "string") return errorText("Request identity must be a string", details);
1617
+ const projectedInput = command === "update_work_item" ? {
1618
+ ...fields,
1619
+ id: workItemId ?? fields.id
1620
+ } : command === "feedback" || command === "mark_read" ? {
1621
+ ...fields,
1622
+ id: presentationId ?? fields.id
1623
+ } : fields;
1624
+ const parsed = SceneWriteContracts[operation].input.safeParse(projectedInput);
1625
+ if (!parsed.success) {
1626
+ const issue = parsed.error.issues[0];
1627
+ const field = issue?.path.join(".") || "input";
1628
+ const expected = issue?.code === "invalid_type" ? issue.expected : void 0;
1629
+ return errorText(expected ? `${field} must be ${/^[aeiou]/.test(expected) ? "an" : "a"} ${expected}` : issue?.message ?? "Invalid input", details);
1630
+ }
1631
+ if (dryRun) return okText({
1632
+ ...details,
1633
+ result: {
1634
+ preview: true,
1635
+ command,
1636
+ input: parsed.data
1637
+ }
1638
+ });
1639
+ const caller = {
1640
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1641
+ surface: "agent",
1642
+ scopes: ["gateway.admin"],
1643
+ authorize: deps.authorizeCapability ?? (() => true),
1644
+ signal
1645
+ };
1646
+ try {
1647
+ const result = await capabilities.call(operation, parsed.data, caller, {
1648
+ ...capabilities.describe(operation, caller),
1649
+ idempotencyKey: typeof idempotencyKey === "string" ? idempotencyKey : typeof requestId === "string" ? requestId : toolCallId
1650
+ });
1651
+ return okText({
1652
+ ...details,
1653
+ result,
1654
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1655
+ });
1656
+ } catch (error) {
1657
+ if (error instanceof CapabilityError) return errorText(error.message, details);
1658
+ throw error;
1659
+ }
1660
+ }
1661
+ if (mode === "scene" && ([
1662
+ "templates",
1663
+ "get_template",
1664
+ "list",
1665
+ "get",
1666
+ "read_notes",
1667
+ "list_runs",
1668
+ "list_schedules",
1669
+ "list_work_items",
1670
+ "get_preferences",
1671
+ "preflight",
1672
+ "mail_accounts",
1673
+ "mail_sources",
1674
+ "results",
1675
+ "get_presentation",
1676
+ "get_feedback",
1677
+ "digest_results",
1678
+ "metrics",
1679
+ "diagnostics"
1680
+ ].includes(command) || command === "start" && dryRun)) {
1681
+ const caller = {
1682
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1683
+ surface: "agent",
1684
+ scopes: ["gateway.admin"],
1685
+ authorize: deps.authorizeCapability ?? (() => true),
1686
+ signal
1687
+ };
1688
+ const { id: _id, requestId: _requestId, triggerKey: _triggerKey, ...preflightInput } = args;
1689
+ const result = await capabilities.call(`xopc.scenes.${command === "start" ? "preflight" : command}`, command === "start" || command === "preflight" ? preflightInput : command === "results" ? {
1690
+ ...preflightInput,
1691
+ activationId: args.activationId ?? args.id
1692
+ } : args, caller);
1693
+ return okText({
1694
+ ...details,
1695
+ result,
1696
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1697
+ });
1698
+ }
1699
+ if (mode === "settings" && command === "open") {
1700
+ const caller = {
1701
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1702
+ surface: "agent",
1703
+ scopes: ["gateway.status"],
1704
+ authorize: deps.authorizeCapability ?? (() => true),
1705
+ signal
1706
+ };
1707
+ const result = await capabilities.call("xopc.settings.open", args, caller);
1708
+ return okText({
1709
+ ...details,
1710
+ result,
1711
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1712
+ });
1713
+ }
1714
+ if (mode === "local_app" && (command === "get" || command === "list" || command === "validate")) {
1715
+ const caller = {
1716
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1717
+ surface: "agent",
1718
+ scopes: ["gateway.admin"],
1719
+ authorize: deps.authorizeCapability ?? (() => true),
1720
+ signal
1721
+ };
1722
+ const result = await capabilities.call(`xopc.local_apps.${command}`, command === "list" ? {} : { id: args.localAppId ?? args.id }, caller);
1723
+ if (command === "validate") Object.assign(result, await capabilities.call("xopc.local_apps.get", { id: args.localAppId ?? args.id }, caller));
1724
+ return okText({
1725
+ ...details,
1726
+ result: {
1727
+ ok: true,
1728
+ ...result
1729
+ },
1730
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1731
+ });
1732
+ }
1733
+ if (mode === "task" && command === "metrics") {
1734
+ const caller = {
1735
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1736
+ surface: "agent",
1737
+ scopes: ["tasks.read"],
1738
+ authorize: deps.authorizeCapability ?? (() => true),
1739
+ signal
1740
+ };
1741
+ return okText({
1742
+ ...details,
1743
+ result: await capabilities.call("xopc.tasks.metrics", {}, caller)
1744
+ });
1745
+ }
1746
+ if (mode === "local_app" && command === "record_acceptance") {
1747
+ const { idempotencyKey, localAppId, ...input } = args;
1748
+ if (idempotencyKey !== void 0 && typeof idempotencyKey !== "string") return errorText("idempotencyKey must be a string", details);
1749
+ const caller = {
1750
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1751
+ surface: "agent",
1752
+ scopes: ["gateway.admin"],
1753
+ authorize: deps.authorizeCapability ?? (() => true),
1754
+ signal
1755
+ };
1756
+ if (dryRun) return okText({
1757
+ ...details,
1758
+ result: {
1759
+ ok: true,
1760
+ dryRun: true,
1761
+ input
1762
+ }
1763
+ });
1764
+ const operation = "xopc.local_apps.record_acceptance";
1765
+ return okText({
1766
+ ...details,
1767
+ result: await capabilities.call(operation, {
1768
+ ...input,
1769
+ id: localAppId ?? input.id
1770
+ }, caller, {
1771
+ ...capabilities.describe(operation, caller),
1772
+ idempotencyKey: typeof idempotencyKey === "string" ? idempotencyKey : toolCallId
1773
+ })
1774
+ });
1775
+ }
1776
+ if (mode === "note" && [
1777
+ "project_summaries",
1778
+ "history",
1779
+ "snapshot",
1780
+ "preview_edit"
1781
+ ].includes(command)) {
1782
+ const projectedInput = command === "project_summaries" ? {} : {
1783
+ id: args.noteId ?? args.id,
1784
+ ...command === "snapshot" ? { timestamp: args.timestamp } : {},
1785
+ ...command === "preview_edit" ? {
1786
+ instruction: args.instruction,
1787
+ markdown: args.markdown
1788
+ } : {}
1789
+ };
1790
+ const caller = {
1791
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1792
+ surface: "agent",
1793
+ scopes: ["workspace.read"],
1794
+ authorize: deps.authorizeCapability ?? (() => true),
1795
+ signal
1796
+ };
1797
+ const result = await capabilities.call(`xopc.notes.${command}`, projectedInput, caller);
1798
+ return okText({
1799
+ ...details,
1800
+ result: command === "preview_edit" ? {
1801
+ ok: true,
1802
+ ...result
1803
+ } : result,
1804
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1805
+ });
1806
+ }
1807
+ if (mode === "automation" && [
1808
+ "get_run",
1809
+ "run_events",
1810
+ "metrics",
1811
+ "product_events"
1812
+ ].includes(command)) {
1813
+ const projectedInput = command === "metrics" ? {} : command === "product_events" ? {
1814
+ eventType: args.eventType,
1815
+ source: args.source,
1816
+ payloadKey: args.payloadKey,
1817
+ payloadValue: args.payloadValue,
1818
+ limit: args.limit
1819
+ } : { id: args.runId ?? args.id };
1820
+ const caller = {
1821
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1822
+ surface: "agent",
1823
+ scopes: ["automations.read"],
1824
+ authorize: deps.authorizeCapability ?? (() => true),
1825
+ signal
1826
+ };
1827
+ const result = await capabilities.call(`xopc.automations.${command}`, projectedInput, caller);
1828
+ return okText({
1829
+ ...details,
1830
+ result
1831
+ });
1832
+ }
1833
+ if (mode === "automation" && [
1834
+ "draft",
1835
+ "repair_draft",
1836
+ "simulate"
1837
+ ].includes(command)) {
1838
+ const operation = `xopc.automations.${command}`;
1839
+ const { idempotencyKey, ...input } = args;
1840
+ if (idempotencyKey !== void 0 && typeof idempotencyKey !== "string") return errorText("idempotencyKey must be a string", details);
1841
+ const caller = {
1842
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1843
+ surface: "agent",
1844
+ scopes: [command === "simulate" ? "automations.read" : "automations.write"],
1845
+ authorize: deps.authorizeCapability ?? (() => true),
1846
+ signal
1847
+ };
1848
+ if (dryRun && command !== "simulate") return okText({
1849
+ ...details,
1850
+ result: {
1851
+ ok: true,
1852
+ dryRun: true,
1853
+ input
1854
+ }
1855
+ });
1856
+ return okText({
1857
+ ...details,
1858
+ result: await capabilities.call(operation, input, caller, {
1859
+ ...capabilities.describe(operation, caller),
1860
+ idempotencyKey: typeof idempotencyKey === "string" ? idempotencyKey : toolCallId
1861
+ })
1862
+ });
1863
+ }
1864
+ if (mode === "automation" && [
1865
+ "get",
1866
+ "list",
1867
+ "history"
1868
+ ].includes(command)) {
1869
+ const id = trimString(args.automationId) ?? trimString(args.id);
1870
+ const projectId = command === "get" || command === "history" && id ? void 0 : currentProjectId(args, deps);
1871
+ const projectedInput = command === "get" ? { id } : command === "list" ? { projectId } : {
1872
+ automationId: id,
1873
+ projectId,
1874
+ limit: args.limit ?? 20
1875
+ };
1876
+ const caller = {
1877
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1878
+ surface: "agent",
1879
+ scopes: ["automations.read"],
1880
+ authorize: deps.authorizeCapability ?? (() => true),
1881
+ signal
1882
+ };
1883
+ const result = await capabilities.call(`xopc.automations.${command}`, projectedInput, caller);
1884
+ return okText({
1885
+ ...details,
1886
+ result,
1887
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1888
+ });
1889
+ }
1890
+ if (mode === "project" && [
1891
+ "get",
1892
+ "list",
1893
+ "list_milestones",
1894
+ "list_updates"
1895
+ ].includes(command)) {
1896
+ const id = args.projectId ?? args.id;
1897
+ const projectedInput = command === "list" ? Object.fromEntries(Object.entries(args).filter(([key]) => key !== "conversationId")) : {
1898
+ id,
1899
+ ...command === "list_updates" && args.limit !== void 0 ? { limit: args.limit } : {}
1900
+ };
1901
+ const context = {
1902
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1903
+ surface: "agent",
1904
+ scopes: ["workspace.read"],
1905
+ authorize: deps.authorizeCapability ?? (() => true),
1906
+ signal
1907
+ };
1908
+ const result = await capabilities.call(`xopc.projects.${command}`, projectedInput, context);
1909
+ return okText({
1910
+ ...details,
1911
+ result,
1912
+ delivery: deliveryForXopcResult(mode, command, result, dryRun)
1913
+ });
1914
+ }
1915
+ if ((mode === "note" || mode === "task" || mode === "task_run") && (command === "get" || command === "list")) {
1916
+ const id = mode === "note" ? args.noteId ?? args.id : mode === "task_run" ? args.runId ?? args.id : args.taskId ?? args.id;
1917
+ const projectId = mode === "task_run" ? void 0 : currentProjectId(args, deps);
1918
+ const capabilityId = `xopc.${mode === "note" ? "notes" : mode === "task_run" ? "task_runs" : "tasks"}.${command}`;
1919
+ const context = {
1920
+ principalId: `agent:${deps.getCurrentAgentId?.() ?? "main"}`,
1921
+ surface: "agent",
1922
+ scopes: ["workspace.read", "tasks.read"],
1923
+ allowedCapabilities: [
1924
+ "xopc.notes.get",
1925
+ "xopc.notes.list",
1926
+ "xopc.tasks.get",
1927
+ "xopc.tasks.list",
1928
+ "xopc.task_runs.get",
1929
+ "xopc.task_runs.list"
1930
+ ],
1931
+ authorize: deps.authorizeCapability ?? (() => true),
1932
+ signal
1933
+ };
1934
+ const input = command === "get" ? { id } : {
1935
+ ...Object.fromEntries(Object.entries(args).filter(([key]) => key !== "conversationId")),
1936
+ ...projectId ? { projectId } : {},
1937
+ limit: args.limit ?? 20
1938
+ };
1939
+ const result = await capabilities.call(capabilityId, input, context);
1940
+ const projected = mode === "task" && command === "list" ? {
1941
+ ...result,
1942
+ items: result.items.map((item) => item.task)
1943
+ } : mode === "task" && command === "get" ? {
1944
+ ...result,
1945
+ model: {
1946
+ task: result.task,
1947
+ operationalState: result.operationalState,
1948
+ attention: result.attention,
1949
+ allowedCommands: result.allowedCommands
1950
+ }
1951
+ } : result;
1952
+ return okText({
1953
+ ...details,
1954
+ result: {
1955
+ ok: true,
1956
+ ...projected,
1957
+ ...command === "list" && projectId ? { projectId } : {}
1958
+ },
1959
+ delivery: deliveryForXopcResult(mode, command, projected, dryRun)
1960
+ });
1961
+ }
1798
1962
  try {
1799
1963
  const conversationId = deps.getCurrentConversationId?.();
1800
1964
  const agentId = deps.getCurrentAgentId?.();
@@ -1812,7 +1976,7 @@ function createXopcUseTool(deps) {
1812
1976
  kind: "xopc_use",
1813
1977
  toolCallId
1814
1978
  }
1815
- }, async () => mode === "scene" ? await handleScene(command, args, deps, dryRun, toolCallId) : mode === "project" ? await handleProject(command, args, deps, dryRun) : mode === "automation" ? await handleAutomation(command, args, deps, dryRun) : mode === "note" ? await handleNote(command, args, deps, dryRun) : mode === "task" ? await handleTask(command, args, deps, dryRun) : mode === "task_run" ? await handleTaskRun(command, args, dryRun, deps) : mode === "local_app" ? await handleLocalApp(command, args, deps, dryRun) : mode === "settings" ? handleSettings(command, args) : {
1979
+ }, async () => mode === "scene" ? await handleScene(command, args, deps, dryRun) : mode === "project" ? await handleProject(command, args, deps, dryRun, capabilities) : mode === "automation" ? await handleAutomation(command, args, deps, dryRun, capabilities) : mode === "note" ? await handleNote(command, args, deps, dryRun, capabilities) : mode === "task" ? await handleTask(command, args, deps, dryRun, capabilities) : mode === "task_run" ? await handleTaskRun(command, args, dryRun, deps, capabilities) : mode === "local_app" ? await handleLocalApp(command, args, deps, dryRun) : {
1816
1980
  ok: false,
1817
1981
  error: `Unsupported mode: ${String(mode)}`
1818
1982
  });
@@ -1827,93 +1991,18 @@ function createXopcUseTool(deps) {
1827
1991
  }
1828
1992
  };
1829
1993
  }
1830
- async function handleScene(command, args, deps, dryRun, toolCallId) {
1994
+ async function handleScene(command, args, deps, dryRun) {
1995
+ if (command !== "mail_search") throw new Error("Unsupported scene command");
1831
1996
  const access = deps.getSceneAccess?.();
1832
1997
  if (!access) throw new Error("Scene service is unavailable");
1833
1998
  const { services, principal } = access;
1834
- const { id, requestId, triggerKey, ...input } = args;
1835
- const activationId = typeof id === "string" ? id : "";
1836
- const request = typeof requestId === "string" && requestId.trim() ? requestId : toolCallId;
1837
- if (command === "templates") return { templates: services.repository.listTemplates() };
1838
- if (command === "list") return { activations: services.repository.listActivations(principal) };
1839
- if (command === "get") return {
1840
- activation: services.repository.getActivation(principal, activationId),
1841
- runs: services.repository.listRuns(principal, activationId),
1842
- schedules: services.repository.listSchedules(principal, activationId)
1999
+ if (!services.mailDiscovery) throw new Error("Mail search is unavailable");
2000
+ if (dryRun) return {
2001
+ preview: true,
2002
+ command,
2003
+ input: args
1843
2004
  };
1844
- if (command === "mail_accounts") return { accounts: services.mailDiscovery?.listAccounts(principal) ?? [] };
1845
- if (command === "mail_search") {
1846
- if (!services.mailDiscovery) throw new Error("Mail search is unavailable");
1847
- if (dryRun) return {
1848
- preview: true,
1849
- command,
1850
- input
1851
- };
1852
- return { sources: await services.mailDiscovery.searchSources(principal, input, AbortSignal.timeout(15e3)) };
1853
- }
1854
- if (command === "read_notes") return { notes: services.repository.readNotes(principal, activationId) };
1855
- if (command === "mail_sources") return { sources: services.mail.listSources(principal) };
1856
- if (command === "results") return { outcomes: services.repository.listInbox(principal, 50, "", activationId || null) };
1857
- if (command === "diagnostics") return services.metrics.diagnostics(principal);
1858
- if (command === "get_preferences") return services.preferences.get(principal);
1859
- if (command === "preflight" || command === "start" && dryRun) return services.application.preflight(principal, input);
1860
- if (dryRun) {
1861
- if (command === "set_preferences") return {
1862
- preview: true,
1863
- command,
1864
- input: args
1865
- };
1866
- if (command === "update_work_item") return {
1867
- preview: true,
1868
- command,
1869
- workItemId: args.workItemId ?? id,
1870
- input
1871
- };
1872
- if (command === "feedback" || command === "mark_read") return {
1873
- preview: true,
1874
- command,
1875
- presentationId: args.presentationId ?? id,
1876
- input
1877
- };
1878
- services.repository.getActivation(principal, activationId);
1879
- return {
1880
- preview: true,
1881
- command,
1882
- activationId,
1883
- input
1884
- };
1885
- }
1886
- if (command === "start") return { activation: await services.application.start(principal, input, request) };
1887
- if (command === "configure") return { activation: services.application.configure(principal, activationId, input) };
1888
- if (command === "transition") return { activation: await services.application.transition(principal, activationId, input) };
1889
- if (command === "check") return { intentId: services.application.check(principal, activationId, request) };
1890
- if (command === "notes") return { revision: services.application.writeNotes(principal, activationId, input) };
1891
- if (command === "work_item") return { workItem: services.application.createWorkItem(principal, activationId, input) };
1892
- if (command === "update_work_item") {
1893
- const workItemId = typeof args.workItemId === "string" ? args.workItemId : activationId;
1894
- const { workItemId: _workItemId, ...workItemInput } = args;
1895
- return { workItem: services.application.updateWorkItem(principal, workItemId, workItemInput) };
1896
- }
1897
- if (command === "schedule") return { revision: services.application.setSchedule(principal, activationId, String(triggerKey ?? ""), input) };
1898
- if (command === "set_preferences") return services.preferences.update(principal, args);
1899
- if (command === "feedback") {
1900
- const presentationId = typeof args.presentationId === "string" ? args.presentationId : activationId;
1901
- if (!presentationId.trim()) throw new Error("presentationId is required");
1902
- const { presentationId: _presentationId, ...feedbackInput } = args;
1903
- return { revision: services.inbox.feedback(principal, presentationId, feedbackInput) };
1904
- }
1905
- if (command === "mark_read") {
1906
- const presentationId = typeof args.presentationId === "string" ? args.presentationId : activationId;
1907
- if (!presentationId.trim()) throw new Error("presentationId is required");
1908
- if (typeof args.read !== "boolean") throw new Error("read must be a boolean");
1909
- services.inbox.setRead(principal, presentationId, args.read);
1910
- return {
1911
- ok: true,
1912
- presentationId,
1913
- read: args.read
1914
- };
1915
- }
1916
- throw new Error("Unsupported scene command");
2005
+ return { sources: await services.mailDiscovery.searchSources(principal, args, AbortSignal.timeout(15e3)) };
1917
2006
  }
1918
2007
  //#endregion
1919
2008
  export { createXopcUseTool };