@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.
- package/dist/browser-ext/dist/assets/{auth-C3yV1y_l.js → auth-DKo-NMUY.js} +18 -1
- package/dist/browser-ext/dist/background.js +68 -2
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +2 -2
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BVIJMP8w.js → agent-avatar-dicebear-BFkjfurL.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-BdOZ6q8Z.js +1 -0
- package/dist/gateway/static/root/assets/{agents-D6g_SeWI.js → agents-CCcavsHq.js} +1 -1
- package/dist/gateway/static/root/assets/{api-_aHQA8bd.js → api-BYhRsTAc.js} +1 -1
- package/dist/gateway/static/root/assets/{app-link-CKueEVbT.js → app-link-nL8iPwEr.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-CLg_aXYG.js → app-management-settings-panel-B4kihr-A.js} +1 -1
- package/dist/gateway/static/root/assets/appearance-settings-N9sYmNOx.js +1 -0
- package/dist/gateway/static/root/assets/apps-page-BMcy10_s.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-CHO3heHX.js → archive-plugin-k_SuYWyV.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-load-BsmsBCI2.js → attachment-load-DRv5QWUK.js} +1 -1
- package/dist/gateway/static/root/assets/{automations-page-CftigJlf.js → automations-page-CkJV3DN0.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-BEa2doeR.js +7 -0
- package/dist/gateway/static/root/assets/{binary-plugins-CRCLWBo2.js → binary-plugins-Dg3h3TA7.js} +1 -1
- package/dist/gateway/static/root/assets/{block-editor-D0LDiOTT.js → block-editor-DVhdHntT.js} +29 -29
- package/dist/gateway/static/root/assets/{browser-automation-inputs-C611KRBx.js → browser-automation-inputs-BMRYUW8_.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-Djyv3vy-.js → browser-automations-page-Byv6-FY2.js} +2 -2
- package/dist/gateway/static/root/assets/browser-settings-page-DRCHGFpO.js +3 -0
- package/dist/gateway/static/root/assets/capabilities-D0S3DuAD.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-mxRP0gl0.js +8 -0
- package/dist/gateway/static/root/assets/channels-settings-DBt_6GsB.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-CIsKqdET.js → chat-terminal-dock-D4AHa51o.js} +2 -2
- package/dist/gateway/static/root/assets/{computer-settings-page-C0YL9J7m.js → computer-settings-page-eXPe500D.js} +1 -1
- package/dist/gateway/static/root/assets/connector-service-page-BQTFlq_k.js +1 -0
- package/dist/gateway/static/root/assets/connectors-page-BKeBWwcI.js +2 -0
- package/dist/gateway/static/root/assets/conversation-identity-Cw0n9uzK.js +1 -0
- package/dist/gateway/static/root/assets/{date-picker-CDsfv8R0.js → date-picker-7MtovynY.js} +1 -1
- package/dist/gateway/static/root/assets/{dependency-picker-DvhPj3CZ.js → dependency-picker-Bj_xkXID.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Cyg8XMpL.js → desktop-pet-CTmba9zH.js} +1 -1
- package/dist/gateway/static/root/assets/desktop-pet-settings-DNM_BlWN.js +1 -0
- package/dist/gateway/static/root/assets/device-pairing-wizard-C2XE0QhT.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-D-AVJU3q.js → extension-debug-page-J_olaL7e.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DrFoQ9xt.js → extension-page-pK5RvqN8.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DxWjESC1.js → extension-settings-page-BwroEN08.js} +1 -1
- package/dist/gateway/static/root/assets/files-BK6enEvD.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-config-swr-DUDX42qY.js → gateway-config-swr-FuJTIg_a.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-settings-CLLDp23J.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-Cf8OxlvY.js → gateway-startup-retry-CKg_gu8_.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-B5Epb1PH.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-D2YorS--.js → image-generation-api-Bo6NZ7zb.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-BKucJlXI.js → imports-page-C8-hX8gS.js} +1 -1
- package/dist/gateway/static/root/assets/index-14F1yGJI.js +89 -0
- package/dist/gateway/static/root/assets/index-cB7rWIDY.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BxLXD-yU.js → keyboard-shortcuts-settings-BkBEjUZD.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-6jC3vQpY.js +2 -0
- package/dist/gateway/static/root/assets/{local-apps-page-BAsQJQKJ.js → local-apps-page-CrbKIixo.js} +1 -1
- package/dist/gateway/static/root/assets/{locale-store-DA0Z5jM_.js → locale-store-CvGwNbml.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DBHlZts9.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-DsUWLu5m.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-DYGPxPee.js → markdown-view-nXo5nrsv.js} +1 -1
- package/dist/gateway/static/root/assets/{media-plugins-CQtQzLyg.js → media-plugins-upxXJ-4l.js} +1 -1
- package/dist/gateway/static/root/assets/messages-B_AwRroN.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-0Q9TOtJG.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-D0NmcwNw.js +8 -0
- package/dist/gateway/static/root/assets/page-context-capture-button-DUyA-K4L.js +1 -0
- package/dist/gateway/static/root/assets/{page-tabs-B6DjkyMM.js → page-tabs-Cl-NFPNr.js} +1 -1
- package/dist/gateway/static/root/assets/{preview-open-alternatives-Dn57uLhr.js → preview-open-alternatives-DX81PwJ3.js} +1 -1
- package/dist/gateway/static/root/assets/product-delivery-chCjIpvu.js +1 -0
- package/dist/gateway/static/root/assets/{product-open-page-H2YMk8TY.js → product-open-page-CrfIGwm8.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-BVfVrYmn.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-nM9a9XNS.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-C0DCx3wv.js → registry-api-CHxgohY0.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-C8b_k88G.js +1 -0
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-D3dLOW04.js +5 -0
- package/dist/gateway/static/root/assets/scenes-page-DEowreZV.js +2 -0
- package/dist/gateway/static/root/assets/{schema-form-CblI9WUA.js → schema-form-ZxuIvD2_.js} +1 -1
- package/dist/gateway/static/root/assets/schemas-88fK3zzl.js +64 -0
- package/dist/gateway/static/root/assets/sessions-page-B_nPhera.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-BqhIOuus.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-BAaVyxJH.js → settings-form-section-TZRfg4yo.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CKNPbm5q.js → settings-page-a8qcJpdZ.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-layout-DqNCGKxQ.js → settings-page-layout-BfvlRT9q.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CRj5Ruqn.js +1 -0
- package/dist/gateway/static/root/assets/{share-preview-page-BzMfp_HM.js → share-preview-page-DCt1pTWB.js} +1 -1
- package/dist/gateway/static/root/assets/shares-settings-BNbXPk--.js +1 -0
- package/dist/gateway/static/root/assets/skill-reload-api-CNMCLbav.js +1 -0
- package/dist/gateway/static/root/assets/{skills-page-DIht92q6.js → skills-page-BIOcg44X.js} +1 -1
- package/dist/gateway/static/root/assets/{skills-page.utils-DLYRiEn3.js → skills-page.utils-CgZdzT4I.js} +1 -1
- package/dist/gateway/static/root/assets/{system-settings-panel-yYs4YgYk.js → system-settings-panel-_YaRncA6.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-CAcfAG-c.js +1 -0
- package/dist/gateway/static/root/assets/tasks-CDR_RVbQ.js +1 -0
- package/dist/gateway/static/root/assets/{tunnel-api-BasDYxvx.js → tunnel-api-uOupJOoS.js} +1 -1
- package/dist/gateway/static/root/assets/turn-outcome-D0SnyZ3Z.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-CWAUHhcb.js → use-autosave-BezzHBLE.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-BFFeneDq.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-Kc4UlxZs.js → voice-api-key-field-BmYifdwL.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-DTyMdGOR.js → voice-config-api-D_5Q2_A3.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-BPC_c9dO.js → work-discovery-overlay-4DmyEckJ.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DBTciOrq.js → workflow-run-setup-panel-DeZe8bTZ.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-Sv4hEc6W.js +6 -0
- package/dist/gateway/static/root/index.html +16 -16
- package/dist/package.js +1 -1
- package/dist/packages/computer-control-contract/src/index.js +10 -1
- package/dist/packages/gateway-contract/src/app-context.js +55 -0
- package/dist/packages/gateway-contract/src/automations.js +16 -17
- package/dist/packages/gateway-contract/src/capabilities.js +1078 -0
- package/dist/packages/gateway-contract/src/extension-capabilities.js +26 -0
- package/dist/packages/gateway-contract/src/home.js +3 -3
- package/dist/packages/gateway-contract/src/index.js +8 -0
- package/dist/packages/gateway-contract/src/product-delivery.js +19 -4
- package/dist/packages/gateway-contract/src/scenes.js +199 -0
- package/dist/packages/gateway-contract/src/task-runs.js +8 -4
- package/dist/packages/gateway-contract/src/tasks.js +5 -4
- package/dist/packages/realtime-client/src/index.js +17 -4
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/child-agent-factory.d.ts +2 -0
- package/dist/src/agent/child-agent-factory.js +5 -0
- package/dist/src/agent/commands/approved-verification.d.ts +14 -0
- package/dist/src/agent/commands/approved-verification.js +48 -0
- package/dist/src/agent/context/execution-scope.js +2 -1
- package/dist/src/agent/context/project-context.js +2 -1
- package/dist/src/agent/external-tools/cliProvider.js +123 -75
- package/dist/src/agent/external-tools/composio-provider.d.ts +1 -1
- package/dist/src/agent/external-tools/composio-provider.js +70 -12
- package/dist/src/agent/external-tools/endpoint-provider.js +14 -1
- package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -0
- package/dist/src/agent/inbound/turn-dispatcher.js +2 -1
- package/dist/src/agent/memory/compaction-chunks.d.ts +6 -1
- package/dist/src/agent/memory/compaction-chunks.js +16 -3
- package/dist/src/agent/memory/compaction-ledger.d.ts +3 -1
- package/dist/src/agent/memory/compaction-ledger.js +31 -18
- package/dist/src/agent/memory/compaction-request.d.ts +2 -0
- package/dist/src/agent/memory/compaction-request.js +6 -1
- package/dist/src/agent/memory/compaction.d.ts +19 -1
- package/dist/src/agent/memory/compaction.js +112 -30
- package/dist/src/agent/service/process-direct-streaming.d.ts +3 -0
- package/dist/src/agent/service/process-direct-streaming.js +19 -10
- package/dist/src/agent/service.js +1 -0
- package/dist/src/agent/service.types.d.ts +1 -0
- package/dist/src/agent/skills/config.js +2 -0
- package/dist/src/agent/skills/format-skills-prompt.js +14 -1
- package/dist/src/agent/skills/index.js +16 -8
- package/dist/src/agent/skills/types.d.ts +1 -1
- package/dist/src/agent/source-context/app-context.d.ts +4 -0
- package/dist/src/agent/source-context/app-context.js +36 -0
- package/dist/src/agent/source-context/injector.js +1 -0
- package/dist/src/agent/source-context/types.d.ts +5 -1
- package/dist/src/agent/tasks/task-judge-service.js +2 -1
- package/dist/src/agent/tool-manuals/computer.d.ts +1 -1
- package/dist/src/agent/tool-manuals/computer.js +1 -1
- package/dist/src/agent/tools/automation-tool.d.ts +12 -1
- package/dist/src/agent/tools/automation-tool.js +106 -32
- package/dist/src/agent/tools/factory.d.ts +1 -0
- package/dist/src/agent/tools/factory.js +6 -1
- package/dist/src/agent/tools/scoped-workspace-tools.d.ts +8 -0
- package/dist/src/agent/tools/scoped-workspace-tools.js +81 -0
- package/dist/src/agent/tools/xopc-use-tool.d.ts +6 -3
- package/dist/src/agent/tools/xopc-use-tool.js +997 -908
- package/dist/src/agent/workflow/subagent-runner.js +1 -0
- package/dist/src/agent-config/index.js +2 -2
- package/dist/src/agent-config/schema.d.ts +5 -0
- package/dist/src/agent-config/schema.js +14 -10
- package/dist/src/automations/api/routes.js +244 -164
- package/dist/src/automations/capabilities/drafts.d.ts +4 -0
- package/dist/src/automations/capabilities/drafts.js +95 -0
- package/dist/src/automations/capabilities/read.d.ts +4 -0
- package/dist/src/automations/capabilities/read.js +119 -0
- package/dist/src/automations/capabilities/write.d.ts +349 -0
- package/dist/src/automations/capabilities/write.js +172 -0
- package/dist/src/automations/domain/index.js +2 -2
- package/dist/src/automations/domain/validation.d.ts +77 -77
- package/dist/src/automations/domain/validation.js +9 -6
- package/dist/src/automations/draft/automation-draft-validator.d.ts +2 -2
- package/dist/src/automations/index.js +6 -6
- package/dist/src/automations/service/automation-service.d.ts +31 -0
- package/dist/src/automations/service/automation-service.js +213 -75
- package/dist/src/automations/service/index.js +2 -2
- package/dist/src/automations/storage/automation-repository.d.ts +2 -0
- package/dist/src/automations/storage/automation-repository.js +9 -1
- package/dist/src/automations/storage/automation-run-repository.d.ts +4 -1
- package/dist/src/automations/storage/automation-run-repository.js +16 -3
- package/dist/src/automations/storage/index.js +3 -3
- package/dist/src/browser/automations/schema.d.ts +1 -1
- package/dist/src/browser/automations/service.d.ts +1 -1
- package/dist/src/browser/observation/format.js +4 -0
- package/dist/src/capabilities/adapters/http.d.ts +4 -0
- package/dist/src/capabilities/adapters/http.js +44 -0
- package/dist/src/capabilities/readiness/from-config.js +11 -7
- package/dist/src/capabilities/runtime/app-context.d.ts +3 -0
- package/dist/src/capabilities/runtime/app-context.js +72 -0
- package/dist/src/capabilities/runtime/atomic-operations.d.ts +11 -0
- package/dist/src/capabilities/runtime/atomic-operations.js +34 -0
- package/dist/src/capabilities/runtime/dispatcher.d.ts +67 -0
- package/dist/src/capabilities/runtime/dispatcher.js +170 -0
- package/dist/src/capabilities/runtime/errors.d.ts +6 -0
- package/dist/src/capabilities/runtime/errors.js +11 -0
- package/dist/src/capabilities/runtime/external-operations.d.ts +16 -0
- package/dist/src/capabilities/runtime/external-operations.js +92 -0
- package/dist/src/capabilities/runtime/product.d.ts +12 -0
- package/dist/src/capabilities/runtime/product.js +69 -0
- package/dist/src/capabilities/runtime/settings.d.ts +3 -0
- package/dist/src/capabilities/runtime/settings.js +27 -0
- package/dist/src/channels/index.js +2 -2
- package/dist/src/channels/manager.js +1 -1
- package/dist/src/cli/cli-log-level-preset.d.ts +2 -0
- package/dist/src/cli/cli-log-level-preset.js +4 -0
- package/dist/src/cli/command-catalog.js +4 -0
- package/dist/src/cli/command-loaders.js +1 -0
- package/dist/src/cli/command-manifest.js +4 -0
- package/dist/src/cli/commands/channels.js +1 -1
- package/dist/src/cli/commands/connectors.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/mcp.d.ts +1 -0
- package/dist/src/cli/commands/mcp.js +51 -0
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard.js +1 -1
- package/dist/src/cli/commands/project.js +1 -1
- package/dist/src/computer/broker.d.ts +0 -1
- package/dist/src/computer/broker.js +4 -6
- package/dist/src/computer/evaluation-harness.d.ts +45 -0
- package/dist/src/computer/evaluation-harness.js +108 -0
- package/dist/src/computer/model-adapter.d.ts +37 -2
- package/dist/src/computer/model-adapter.js +333 -42
- package/dist/src/computer/model-policy.d.ts +4 -1
- package/dist/src/computer/model-policy.js +11 -3
- package/dist/src/computer/release-gate.d.ts +22 -0
- package/dist/src/computer/release-gate.js +19 -0
- package/dist/src/computer/runtime.js +14 -10
- package/dist/src/computer/task-state.d.ts +1 -0
- package/dist/src/computer/task-state.js +1 -0
- package/dist/src/config/models-json.d.ts +14 -8
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.d.ts +4 -0
- package/dist/src/config/schema.js +3 -9
- package/dist/src/connectors/composio-sessions.d.ts +4 -2
- package/dist/src/connectors/composio-sessions.js +10 -9
- package/dist/src/connectors/composio.js +10 -8
- package/dist/src/discussions/action-tasks.js +2 -1
- package/dist/src/discussions/recording.js +1 -1
- package/dist/src/execution-environments/local-worktree-manager.d.ts +1 -0
- package/dist/src/execution-environments/local-worktree-manager.js +13 -2
- package/dist/src/extensions/activation-context.js +3 -3
- package/dist/src/extensions/api.js +1 -1
- package/dist/src/extensions/normalize-manifest.js +6 -1
- package/dist/src/extensions/sdk/index.js +1 -1
- package/dist/src/extensions/sdk/media.js +1 -1
- package/dist/src/extensions/types/manifest.d.ts +3 -0
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +1 -0
- package/dist/src/gateway/hono/middleware/scopes.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +5 -2
- package/dist/src/gateway/hono/routes/capability-operations.d.ts +3 -0
- package/dist/src/gateway/hono/routes/capability-operations.js +52 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +16 -0
- package/dist/src/gateway/hono/routes/local-app-capabilities.d.ts +4 -0
- package/dist/src/gateway/hono/routes/local-app-capabilities.js +41 -0
- package/dist/src/gateway/hono/routes/local-apps.js +41 -9
- package/dist/src/gateway/hono/routes/models.js +2 -2
- package/dist/src/gateway/hono/routes/notes.js +215 -146
- package/dist/src/gateway/hono/routes/projects.js +217 -374
- package/dist/src/gateway/hono/routes/scenes.js +188 -75
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +60 -16
- package/dist/src/gateway/hono/routes/session-input-handler.js +43 -1
- package/dist/src/gateway/hono/routes/sessions.js +17 -0
- package/dist/src/gateway/hono/routes/status.js +1 -1
- package/dist/src/gateway/hono/routes/tasks.js +182 -326
- package/dist/src/gateway/hono/routes/user-model-refresh.js +1 -1
- package/dist/src/gateway/hono/routes/voice.js +4 -4
- package/dist/src/gateway/hono/routes/workflows.js +1 -1
- package/dist/src/gateway/media-access.js +2 -1
- package/dist/src/gateway/mobile-privacy.js +2 -2
- package/dist/src/gateway/scenes/host.js +14 -3
- package/dist/src/gateway/scenes/mailContext.js +1 -1
- package/dist/src/gateway/scenes/slackThreadSource.d.ts +41 -0
- package/dist/src/gateway/scenes/slackThreadSource.js +168 -0
- package/dist/src/gateway/security/gateway-scopes.d.ts +1 -1
- package/dist/src/gateway/security/gateway-scopes.js +5 -0
- package/dist/src/gateway/service/app-context-access.d.ts +11 -0
- package/dist/src/gateway/service/app-context-access.js +70 -0
- package/dist/src/gateway/service/run-gateway-agent.js +11 -2
- package/dist/src/gateway/service/session-input-coordinator.js +54 -15
- package/dist/src/gateway/service/sessions-api.d.ts +1 -0
- package/dist/src/gateway/service/sessions-api.js +3 -0
- package/dist/src/gateway/service/task-conversation-query-service.d.ts +3 -1
- package/dist/src/gateway/service/task-conversation-query-service.js +32 -3
- package/dist/src/gateway/service.d.ts +3 -0
- package/dist/src/gateway/service.js +69 -15
- package/dist/src/gateway/session-context-summary.js +2 -1
- package/dist/src/{tasks/task-outbox-dispatcher.d.ts → infra/domain-outbox-dispatcher.d.ts} +2 -2
- package/dist/src/{tasks/task-outbox-dispatcher.js → infra/domain-outbox-dispatcher.js} +10 -9
- package/dist/src/infra/operation-context.d.ts +2 -0
- package/dist/src/infra/operation-context.js +16 -0
- package/dist/src/local-apps/capabilities/contracts.d.ts +2 -0
- package/dist/src/local-apps/capabilities/contracts.js +32 -0
- package/dist/src/local-apps/capabilities/read.d.ts +3 -0
- package/dist/src/local-apps/capabilities/read.js +48 -0
- package/dist/src/local-apps/capabilities/runtime.d.ts +16 -0
- package/dist/src/local-apps/capabilities/runtime.js +66 -0
- package/dist/src/local-apps/capabilities/write.d.ts +3 -0
- package/dist/src/local-apps/capabilities/write.js +35 -0
- package/dist/src/local-apps/release-lock.d.ts +2 -0
- package/dist/src/local-apps/release-lock.js +20 -0
- package/dist/src/local-apps/runtime-entry.d.ts +0 -2
- package/dist/src/local-apps/runtime-entry.js +1 -14
- package/dist/src/local-apps/scaffold.js +4 -1
- package/dist/src/local-apps/service.d.ts +24 -1
- package/dist/src/local-apps/service.js +186 -43
- package/dist/src/local-apps/store.js +0 -2
- package/dist/src/mcp/capability-server.d.ts +4 -0
- package/dist/src/mcp/capability-server.js +96 -0
- package/dist/src/mcp/channel-bridge.js +1 -1
- package/dist/src/mcp/gateway-http-client.d.ts +7 -0
- package/dist/src/mcp/gateway-http-client.js +27 -5
- package/dist/src/media-understanding/openai-compatible-audio.js +1 -1
- package/dist/src/notes/agent-context.js +1 -1
- package/dist/src/notes/capabilities/read.d.ts +3 -0
- package/dist/src/notes/capabilities/read.js +96 -0
- package/dist/src/notes/capabilities/write.d.ts +7 -0
- package/dist/src/notes/capabilities/write.js +152 -0
- package/dist/src/notes/index.js +1 -1
- package/dist/src/notes/service.d.ts +12 -4
- package/dist/src/notes/service.js +188 -175
- package/dist/src/notes/store.d.ts +14 -9
- package/dist/src/notes/store.js +81 -21
- package/dist/src/notifications/service.d.ts +1 -0
- package/dist/src/notifications/service.js +5 -0
- package/dist/src/platform/client.d.ts +1 -1
- package/dist/src/platform/contracts.d.ts +1 -1
- package/dist/src/projects/capabilities/read.d.ts +3 -0
- package/dist/src/projects/capabilities/read.js +81 -0
- package/dist/src/projects/capabilities/write.d.ts +9 -0
- package/dist/src/projects/capabilities/write.js +260 -0
- package/dist/src/projects/index.js +2 -2
- package/dist/src/projects/project-change-events.d.ts +2 -0
- package/dist/src/projects/project-change-events.js +18 -0
- package/dist/src/projects/project-service.d.ts +11 -0
- package/dist/src/projects/project-service.js +121 -42
- package/dist/src/projects/project-store.js +12 -2
- package/dist/src/projects/project-workspace-creation.d.ts +3 -0
- package/dist/src/projects/project-workspace-creation.js +45 -0
- package/dist/src/projects/workspace-project.js +6 -0
- package/dist/src/providers/model-catalog-types.d.ts +2 -1
- package/dist/src/providers/model-reference-auditor.js +4 -4
- package/dist/src/providers/model-supplements.js +13 -3
- package/dist/src/providers/presentation.js +3 -3
- package/dist/src/providers/xopc-cloud-model-source.js +4 -2
- package/dist/src/realtime/runtime.js +4 -0
- package/dist/src/scenes/capabilities/read.d.ts +3 -0
- package/dist/src/scenes/capabilities/read.js +187 -0
- package/dist/src/scenes/capabilities/write.d.ts +3 -0
- package/dist/src/scenes/capabilities/write.js +151 -0
- package/dist/src/scenes/contracts.d.ts +2 -105
- package/dist/src/scenes/contracts.js +3 -88
- package/dist/src/scenes/execution.d.ts +1 -1
- package/dist/src/scenes/httpServices.d.ts +2 -0
- package/dist/src/scenes/inbox.d.ts +1 -0
- package/dist/src/scenes/inbox.js +7 -7
- package/dist/src/scenes/preferences.d.ts +3 -24
- package/dist/src/scenes/preferences.js +8 -30
- package/dist/src/scenes/repository.d.ts +1 -0
- package/dist/src/scenes/repository.js +7 -3
- package/dist/src/scenes/resultNotifications.js +2 -2
- package/dist/src/scenes/schedule.d.ts +1 -8
- package/dist/src/scenes/schedule.js +3 -15
- package/dist/src/scenes/service.d.ts +6 -0
- package/dist/src/scenes/service.js +29 -25
- package/dist/src/scenes/taskFollowUp/agentExecutor.d.ts +36 -0
- package/dist/src/scenes/taskFollowUp/agentExecutor.js +149 -0
- package/dist/src/scenes/taskFollowUp/branchInventory.d.ts +38 -0
- package/dist/src/scenes/taskFollowUp/branchInventory.js +70 -0
- package/dist/src/scenes/taskFollowUp/contracts.d.ts +91 -0
- package/dist/src/scenes/taskFollowUp/contracts.js +100 -0
- package/dist/src/scenes/taskFollowUp/resources.d.ts +19 -0
- package/dist/src/scenes/taskFollowUp/resources.js +97 -0
- package/dist/src/scenes/taskFollowUp/service.d.ts +810 -0
- package/dist/src/scenes/taskFollowUp/service.js +710 -0
- package/dist/src/scenes/taskFollowUp/workspaceFingerprint.d.ts +2 -0
- package/dist/src/scenes/taskFollowUp/workspaceFingerprint.js +46 -0
- package/dist/src/scenes/templates.d.ts +2 -2
- package/dist/src/scenes/templates.js +1 -1
- package/dist/src/session/session-find.d.ts +17 -0
- package/dist/src/session/session-find.js +56 -0
- package/dist/src/session/store.d.ts +4 -0
- package/dist/src/session/store.js +43 -7
- package/dist/src/share/note-share-revocation.d.ts +3 -0
- package/dist/src/share/note-share-revocation.js +26 -0
- package/dist/src/storage/sqlite/migrations/190_scene_development.sql +37 -0
- package/dist/src/storage/sqlite/migrations/191_scene_task_follow_up.sql +27 -0
- package/dist/src/storage/sqlite/migrations/192_capability_operations.sql +20 -0
- package/dist/src/storage/sqlite/migrations/193_note_file_cleanup.sql +8 -0
- package/dist/src/storage/sqlite/migrations/194_capability_external_outcomes.sql +11 -0
- package/dist/src/storage/sqlite/migrations/195_automation_deleted_revisions.sql +4 -0
- package/dist/src/storage/sqlite/migrations/196_automation_run_requests.sql +23 -0
- package/dist/src/storage/sqlite/migrations/197_note_deletion_cleanup.sql +8 -0
- package/dist/src/storage/sqlite/migrations/198_project_workspace_creation.sql +7 -0
- package/dist/src/storage/sqlite/migrations/199_scene_resource_events.sql +488 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +6 -3
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/transaction.d.ts +5 -0
- package/dist/src/storage/sqlite/transaction.js +34 -3
- package/dist/src/tasks/capabilities/management.d.ts +195 -0
- package/dist/src/tasks/capabilities/management.js +111 -0
- package/dist/src/tasks/capabilities/read.d.ts +2 -0
- package/dist/src/tasks/capabilities/read.js +141 -0
- package/dist/src/tasks/capabilities/relations.d.ts +204 -0
- package/dist/src/tasks/capabilities/relations.js +140 -0
- package/dist/src/tasks/capabilities/runs.d.ts +2 -0
- package/dist/src/tasks/capabilities/runs.js +89 -0
- package/dist/src/tasks/capabilities/write.d.ts +207 -0
- package/dist/src/tasks/capabilities/write.js +107 -0
- package/dist/src/tasks/home-query-service.js +3 -2
- package/dist/src/tasks/index.d.ts +0 -1
- package/dist/src/tasks/index.js +9 -9
- package/dist/src/tasks/project-operating-view-service.js +2 -1
- package/dist/src/tasks/task-application-service.d.ts +1 -0
- package/dist/src/tasks/task-application-service.js +3 -2
- package/dist/src/tasks/task-change-events.js +5 -3
- package/dist/src/tasks/task-context-assembler.js +2 -1
- package/dist/src/tasks/task-deletion-service.js +2 -1
- package/dist/src/tasks/task-dependency-service.js +2 -1
- package/dist/src/tasks/task-handoff-service.js +2 -1
- package/dist/src/tasks/task-read-model-projector.js +2 -1
- package/dist/src/tasks/task-repository.d.ts +12 -7
- package/dist/src/tasks/task-repository.js +175 -154
- package/dist/src/tasks/task-run-coordinator.js +2 -1
- package/dist/src/tasks/task-run-dispatcher.js +2 -1
- package/dist/src/tasks/task-run-repository.d.ts +1 -0
- package/dist/src/tasks/task-run-repository.js +29 -14
- package/dist/src/tasks/task-signal-service.js +2 -1
- package/dist/src/tui/backends/embedded-backend.js +1 -1
- package/dist/src/tui/backends/gateway-realtime-backend.js +1 -1
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/user-context/config.d.ts +13 -0
- package/dist/src/user-context/config.js +2 -0
- package/dist/src/voice/platform-catalog.d.ts +1 -1
- package/dist/src/voice/realtime/runtime.js +3 -3
- package/dist/src/voice/stt/providers/alibaba-transcription.js +1 -1
- package/dist/src/voice/stt/providers/xopc-cloud-transcription.js +1 -1
- package/dist/src/voice/tts/providers/xopc-cloud-speech.js +1 -1
- package/dist/src/work-discovery/incremental-repository.js +1 -1
- package/dist/src/work-discovery/index.js +1 -1
- package/dist/src/work-discovery/repository.d.ts +1 -1
- package/dist/src/work-discovery/repository.js +3 -2
- package/dist/src/work-discovery/service.d.ts +4 -0
- package/dist/src/work-discovery/service.js +36 -11
- package/dist/src/workflows/context/workflow-context.js +3 -2
- package/dist/src/workflows/service/workflow-run-service.js +2 -1
- package/package.json +6 -2
- package/skills/THIRD_PARTY_NOTICES.md +2 -2
- package/skills/documents/xlsx/SKILL.md +5 -0
- package/skills/engineering/build-xopc-local-app/SKILL.md +2 -0
- package/skills/tools/find-skills/SKILL.md +3 -0
- package/dist/gateway/static/root/assets/activity-store-DVUTs1fk.js +0 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-K3hTmu9d.js +0 -1
- package/dist/gateway/static/root/assets/appearance-settings-CU52MfIT.js +0 -1
- package/dist/gateway/static/root/assets/apps-page-ZpA1-6ad.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-IEAxKRME.js +0 -7
- package/dist/gateway/static/root/assets/browser-settings-page-CU4VWsmX.js +0 -3
- package/dist/gateway/static/root/assets/capabilities-settings-panel-C9XQk3HL.js +0 -8
- package/dist/gateway/static/root/assets/channels-settings-Bqlhjooi.js +0 -1
- package/dist/gateway/static/root/assets/connector-service-page-BmH17JnO.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-zkx8Q-e6.js +0 -2
- package/dist/gateway/static/root/assets/desktop-pet-settings-CE4GOlMM.js +0 -1
- package/dist/gateway/static/root/assets/device-pairing-wizard-CdKJqnnw.js +0 -1
- package/dist/gateway/static/root/assets/files-Be5viEFY.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-CGOW0-b4.js +0 -1
- package/dist/gateway/static/root/assets/gateway-realtime-store-D4um_sV7.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-CgXp2zq4.js +0 -1
- package/dist/gateway/static/root/assets/home-page-D6Idk732.js +0 -1
- package/dist/gateway/static/root/assets/index-1wIKA-kM.css +0 -1
- package/dist/gateway/static/root/assets/index-PFQHPGgi.js +0 -79
- package/dist/gateway/static/root/assets/local-app-workbench-page-BmAqTRb4.js +0 -2
- package/dist/gateway/static/root/assets/logs-page-ZjVYXXyM.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-CSTkYVOZ.js +0 -1
- package/dist/gateway/static/root/assets/messages-4BtQKYlM.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-DuXCt-MM.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-BjOgBVq5.js +0 -8
- package/dist/gateway/static/root/assets/product-delivery-CrAI8ZEa.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-0zi4-i9X.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-B18OxmJj.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-z-DxbuaE.js +0 -1
- package/dist/gateway/static/root/assets/runtime-tools-settings-panel-DGsBTbo6.js +0 -5
- package/dist/gateway/static/root/assets/scenes-page-Bgba03B_.js +0 -1
- package/dist/gateway/static/root/assets/schemas-BaskVM5g.js +0 -64
- package/dist/gateway/static/root/assets/sessions-page-B1t3bMsm.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-CBX0Ezhf.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-Bw71C2X3.js +0 -1
- package/dist/gateway/static/root/assets/shares-settings-BoVDQolc.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-DtTptpAt.js +0 -1
- package/dist/gateway/static/root/assets/task-detail-page-vgkiGo-D.js +0 -1
- package/dist/gateway/static/root/assets/theme-store-CegIlB8d.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-CAGafNfP.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-CSxHVs1p.js +0 -6
- package/skills/creative/algorithmic-art/SKILL.md +0 -44
- package/skills/creative/algorithmic-art/templates/generator-template.js +0 -27
- 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 {
|
|
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 {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
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 === "
|
|
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?.
|
|
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?.
|
|
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
|
|
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
|
-
|
|
407
|
-
if (!workspacePath) return {
|
|
384
|
+
if (args.idempotencyKey !== void 0 && !trimString(args.idempotencyKey)) return {
|
|
408
385
|
ok: false,
|
|
409
|
-
error: "
|
|
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
|
|
425
|
-
|
|
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
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
};
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
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:
|
|
484
|
+
action: `${command}_project`,
|
|
481
485
|
input
|
|
482
486
|
};
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
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 === "
|
|
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
|
-
|
|
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
|
|
511
|
+
error: "Invalid idempotencyKey"
|
|
523
512
|
};
|
|
524
|
-
if (args.
|
|
513
|
+
if (args.idempotencyKey !== void 0 && args.expectedVersion === void 0) return {
|
|
525
514
|
ok: false,
|
|
526
|
-
error: "
|
|
515
|
+
error: "Stable retries require the original expectedVersion"
|
|
527
516
|
};
|
|
528
|
-
|
|
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: "
|
|
520
|
+
error: "Project not found"
|
|
531
521
|
};
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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:
|
|
540
|
-
|
|
541
|
-
patch
|
|
533
|
+
action: `${command}_project`,
|
|
534
|
+
input
|
|
542
535
|
};
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
549
|
-
|
|
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
|
-
|
|
555
|
-
|
|
564
|
+
const operation = "xopc.projects." + command;
|
|
565
|
+
let input;
|
|
566
|
+
if (command === "create_milestone") input = ProjectMilestoneCreateInputSchema.parse({
|
|
556
567
|
projectId,
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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:
|
|
596
|
-
projectId,
|
|
617
|
+
action: command,
|
|
597
618
|
input
|
|
598
619
|
};
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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
|
-
|
|
698
|
-
|
|
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
|
-
|
|
726
|
-
const
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
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
|
-
|
|
745
|
-
|
|
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
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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
|
-
|
|
787
|
-
|
|
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 =
|
|
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
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
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
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
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 === "
|
|
834
|
-
const
|
|
835
|
-
|
|
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:
|
|
772
|
+
error: "runId is required"
|
|
840
773
|
};
|
|
841
|
-
return {
|
|
774
|
+
if (dryRun) return {
|
|
842
775
|
ok: true,
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
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
|
-
|
|
866
|
-
if (!
|
|
867
|
-
|
|
868
|
-
|
|
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
|
-
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
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.
|
|
975
|
-
|
|
976
|
-
|
|
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.
|
|
1017
|
-
|
|
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
|
|
1090
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
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
|
-
|
|
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
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
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
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
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
|
|
1330
|
-
|
|
1331
|
-
|
|
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
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
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
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
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
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
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: "
|
|
1640
|
-
|
|
1641
|
-
expectedVersion,
|
|
1642
|
-
reason
|
|
1428
|
+
action: "task_run_feedback",
|
|
1429
|
+
input
|
|
1643
1430
|
};
|
|
1644
|
-
const
|
|
1645
|
-
|
|
1646
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1673
|
-
return {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
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
|
-
|
|
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 };
|