@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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { CapabilityError } from "../runtime/errors.js";
|
|
4
|
+
import "../runtime/dispatcher.js";
|
|
5
|
+
import { getGatewayPrincipal } from "../../gateway/security/gateway-principal.js";
|
|
6
|
+
//#region src/capabilities/adapters/http.ts
|
|
7
|
+
init_logger();
|
|
8
|
+
const log = createLogger("Capabilities:Http");
|
|
9
|
+
function capabilityHttpContext(c) {
|
|
10
|
+
const principal = getGatewayPrincipal(c);
|
|
11
|
+
return {
|
|
12
|
+
principalId: principal.principalId,
|
|
13
|
+
surface: "http",
|
|
14
|
+
scopes: principal.scopes,
|
|
15
|
+
actor: {
|
|
16
|
+
kind: "user",
|
|
17
|
+
id: principal.principalId
|
|
18
|
+
},
|
|
19
|
+
authorize: () => true,
|
|
20
|
+
signal: c.req.raw.signal
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function capabilityHttpError(c, error) {
|
|
24
|
+
const code = error instanceof CapabilityError ? error.code : "INTERNAL";
|
|
25
|
+
if (code === "INTERNAL") log.error({
|
|
26
|
+
err: error,
|
|
27
|
+
path: c.req.path,
|
|
28
|
+
phase: "invoke"
|
|
29
|
+
}, "Capability execution failed");
|
|
30
|
+
const status = code === "INVALID_INPUT" ? 400 : code === "FORBIDDEN" ? 403 : code === "NOT_FOUND" ? 404 : [
|
|
31
|
+
"CONTRACT_CHANGED",
|
|
32
|
+
"REVISION_CONFLICT",
|
|
33
|
+
"IN_PROGRESS",
|
|
34
|
+
"OUTCOME_UNKNOWN"
|
|
35
|
+
].includes(code) ? 409 : code === "UNAVAILABLE" ? 503 : code === "CANCELLED" ? 409 : 500;
|
|
36
|
+
return c.json({
|
|
37
|
+
ok: false,
|
|
38
|
+
code,
|
|
39
|
+
error: error instanceof CapabilityError ? error.message : "Capability execution failed",
|
|
40
|
+
...error instanceof CapabilityError && error.operationId ? { operationId: error.operationId } : {}
|
|
41
|
+
}, status);
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { capabilityHttpContext, capabilityHttpError };
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { getAgentDefaultImageGenerationModelConfig, getAgentDefaultImageModelConfig, init_schema, parseModelRef } from "../../config/schema.js";
|
|
2
|
-
import { init_model_policy, isComputerModel } from "../../computer/model-policy.js";
|
|
2
|
+
import { init_model_policy, isComputerModel, isDedicatedComputerProfile } from "../../computer/model-policy.js";
|
|
3
3
|
import { getModelCatalogStore, init_model_catalog_store } from "../../providers/model-catalog-store.js";
|
|
4
4
|
import { init_providers, isProviderConfiguredSync, resolveModel } from "../../providers/index.js";
|
|
5
5
|
import { compareCatalogModels } from "../../providers/model-catalog-ranking.js";
|
|
6
6
|
import { DEFAULT_LOCAL_VOICE_MODEL_ID, hasInstalledLocalVoiceModel } from "../../voice/local/models.js";
|
|
7
7
|
import { planCapabilities } from "./planner.js";
|
|
8
8
|
//#region src/capabilities/readiness/from-config.ts
|
|
9
|
+
init_model_policy();
|
|
9
10
|
init_schema();
|
|
10
11
|
init_model_catalog_store();
|
|
11
12
|
init_providers();
|
|
12
|
-
init_model_policy();
|
|
13
13
|
function buildCapabilityPlansForConfig(config, options = {}) {
|
|
14
14
|
const catalog = options.catalog ?? getModelCatalogStore().load();
|
|
15
15
|
const cloud = catalog.sources["xopc-cloud"];
|
|
@@ -114,11 +114,15 @@ function cloudCandidates(capability, models, authorized, basePriority = 0, recom
|
|
|
114
114
|
function matchesCapability(model, capability) {
|
|
115
115
|
if (model.availability !== "available") return false;
|
|
116
116
|
switch (capability) {
|
|
117
|
-
case "vision": return model.kind === "language" && model.input.includes("image") && !model.computerUse;
|
|
118
|
-
case "computer-use":
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
case "vision": return model.kind === "language" && model.input.includes("image") && !isDedicatedComputerProfile(model.computerUse?.profile);
|
|
118
|
+
case "computer-use":
|
|
119
|
+
if (!model.computerUse) return false;
|
|
120
|
+
if (model.computerUse.profile === "openai-responses-computer-v1" && !model.operations.includes("responses")) return false;
|
|
121
|
+
if (model.computerUse.profile !== "openai-responses-computer-v1" && !model.operations.includes("chat.completions")) return false;
|
|
122
|
+
return isComputerModel({
|
|
123
|
+
...model,
|
|
124
|
+
api: model.computerUse.profile === "openai-responses-computer-v1" ? "openai-responses" : "openai-completions"
|
|
125
|
+
});
|
|
122
126
|
case "image-generation": return model.kind === "image" && model.operations.includes("images.generate");
|
|
123
127
|
case "stt": return model.kind === "stt" && model.operations.includes("audio.transcription");
|
|
124
128
|
case "tts": return model.kind === "tts" && model.operations.includes("audio.speech") && Boolean(model.tts?.defaultVoice);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AppContextEnvelopeSchema, ResolvedAppContextSchema, parseAppContextEnvelope } from "../../../packages/gateway-contract/src/app-context.js";
|
|
2
|
+
import { init_src } from "../../../packages/gateway-contract/src/index.js";
|
|
3
|
+
import { CapabilityError } from "./errors.js";
|
|
4
|
+
import { defineReadCapability } from "./dispatcher.js";
|
|
5
|
+
//#region src/capabilities/runtime/app-context.ts
|
|
6
|
+
init_src();
|
|
7
|
+
/** Resolve each reference through its own capability, never through client-supplied authority. */
|
|
8
|
+
function registerAppContextCapability(dispatcher) {
|
|
9
|
+
dispatcher.register(defineReadCapability({
|
|
10
|
+
id: "xopc.context.resolve",
|
|
11
|
+
majorVersion: 1,
|
|
12
|
+
effect: "read",
|
|
13
|
+
scopes: [],
|
|
14
|
+
surfaces: ["http", "agent"],
|
|
15
|
+
description: "Resolve an explicit immutable page snapshot at its observed revisions; supplied text grants no authority.",
|
|
16
|
+
input: AppContextEnvelopeSchema,
|
|
17
|
+
output: ResolvedAppContextSchema,
|
|
18
|
+
async execute(input, context) {
|
|
19
|
+
let snapshot;
|
|
20
|
+
try {
|
|
21
|
+
snapshot = parseAppContextEnvelope(input);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new CapabilityError("INVALID_INPUT", error instanceof Error ? error.message : "Invalid app context");
|
|
24
|
+
}
|
|
25
|
+
const resources = [];
|
|
26
|
+
const quota = Math.floor(16e3 / Math.max(1, snapshot.resourceRefs.length));
|
|
27
|
+
for (const reference of snapshot.resourceRefs) {
|
|
28
|
+
const domain = reference.kind === "local_app" ? "local_apps" : `${reference.kind}s`;
|
|
29
|
+
const row = (await dispatcher.call(`xopc.${domain}.get`, { id: reference.id }, context))[reference.kind === "scene" ? "activation" : reference.kind === "local_app" ? "app" : reference.kind];
|
|
30
|
+
if (!row) throw new CapabilityError("INTERNAL", "Resource returned no context object");
|
|
31
|
+
let revision;
|
|
32
|
+
let text;
|
|
33
|
+
switch (reference.kind) {
|
|
34
|
+
case "note":
|
|
35
|
+
revision = row.remoteVersion ?? 1;
|
|
36
|
+
text = String(row.markdown ?? "");
|
|
37
|
+
break;
|
|
38
|
+
case "task":
|
|
39
|
+
revision = row.version;
|
|
40
|
+
text = String(row.body ?? row.contract?.objective ?? "");
|
|
41
|
+
break;
|
|
42
|
+
case "project":
|
|
43
|
+
revision = row.version;
|
|
44
|
+
text = String(row.brief ?? row.description ?? "");
|
|
45
|
+
break;
|
|
46
|
+
case "scene":
|
|
47
|
+
revision = row.revision;
|
|
48
|
+
text = String(row.goal ?? "");
|
|
49
|
+
break;
|
|
50
|
+
case "local_app":
|
|
51
|
+
revision = (await dispatcher.call("xopc.local_apps.validate", { id: reference.id }, context)).validation.sourceHash;
|
|
52
|
+
text = String(row.idea ?? row.description ?? "");
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (revision === void 0 || String(revision) !== reference.revision) throw new CapabilityError("REVISION_CONFLICT", "A page resource changed; capture its current revision again");
|
|
56
|
+
resources.push({
|
|
57
|
+
reference,
|
|
58
|
+
title: String(row.title ?? row.name ?? (reference.kind === "scene" ? row.goal : void 0) ?? reference.id),
|
|
59
|
+
text: text.slice(0, quota),
|
|
60
|
+
truncated: text.length > quota
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
snapshot,
|
|
65
|
+
resources,
|
|
66
|
+
selectionTrust: "user-supplied"
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { registerAppContextCapability };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class OperationConflictError extends Error {
|
|
2
|
+
}
|
|
3
|
+
/** Only synchronous, same-database effects belong here. No leases or retries are needed under SQLite's write lock. */
|
|
4
|
+
export declare function executeAtomicOperation(input: {
|
|
5
|
+
principalId: string;
|
|
6
|
+
capabilityId: string;
|
|
7
|
+
idempotencyKey: string;
|
|
8
|
+
requestDigest: string;
|
|
9
|
+
descriptorDigest: string;
|
|
10
|
+
surface: string;
|
|
11
|
+
}, execute: (operationId: string) => unknown): unknown;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { init_operation_context, withOperation } from "../../infra/operation-context.js";
|
|
2
|
+
import { init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/capabilities/runtime/atomic-operations.ts
|
|
5
|
+
init_transaction();
|
|
6
|
+
init_operation_context();
|
|
7
|
+
var OperationConflictError = class extends Error {};
|
|
8
|
+
/** Only synchronous, same-database effects belong here. No leases or retries are needed under SQLite's write lock. */
|
|
9
|
+
function executeAtomicOperation(input, execute) {
|
|
10
|
+
return runSqliteWriteTransaction((db) => {
|
|
11
|
+
const existing = db.prepare(`SELECT operation_id, request_digest, descriptor_digest, result_json, state, recovery_mode
|
|
12
|
+
FROM capability_operations WHERE principal_id = ? AND capability_id = ? AND idempotency_key = ?`).get(input.principalId, input.capabilityId, input.idempotencyKey);
|
|
13
|
+
if (existing && (existing.request_digest !== input.requestDigest || existing.descriptor_digest !== input.descriptorDigest || existing.state !== "succeeded" || existing.recovery_mode !== "atomic")) throw new OperationConflictError("Idempotency key already identifies a different operation");
|
|
14
|
+
const operationId = existing?.operation_id ?? randomUUID();
|
|
15
|
+
const now = Date.now();
|
|
16
|
+
let result;
|
|
17
|
+
if (existing) result = JSON.parse(existing.result_json);
|
|
18
|
+
else {
|
|
19
|
+
result = withOperation(operationId, () => execute(operationId));
|
|
20
|
+
if (result && typeof result.then === "function") throw new Error("Atomic capability handlers must be synchronous");
|
|
21
|
+
const serialized = JSON.stringify(result);
|
|
22
|
+
if (serialized === void 0) throw new Error("Atomic capability result must be JSON");
|
|
23
|
+
db.prepare(`INSERT INTO capability_operations
|
|
24
|
+
(operation_id, principal_id, capability_id, idempotency_key, request_digest, descriptor_digest, result_json, created_at)
|
|
25
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(operationId, input.principalId, input.capabilityId, input.idempotencyKey, input.requestDigest, input.descriptorDigest, serialized, now);
|
|
26
|
+
result = JSON.parse(serialized);
|
|
27
|
+
}
|
|
28
|
+
db.prepare(`INSERT INTO capability_invocations (invocation_id, operation_id, surface, replayed, created_at)
|
|
29
|
+
VALUES (?, ?, ?, ?, ?)`).run(randomUUID(), operationId, input.surface, existing ? 1 : 0, now);
|
|
30
|
+
return result;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { OperationConflictError, executeAtomicOperation };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ActorRef, CapabilityDescriptor, CapabilitySurface, GatewayScope } from '@xopcai/gateway-contract';
|
|
3
|
+
export { CapabilityError } from './errors.js';
|
|
4
|
+
/** Constructed by a trusted entry point, never parsed from tool or HTTP input. */
|
|
5
|
+
export interface CapabilityContext {
|
|
6
|
+
principalId: string;
|
|
7
|
+
surface: CapabilitySurface;
|
|
8
|
+
scopes: readonly GatewayScope[];
|
|
9
|
+
allowedCapabilities?: readonly string[];
|
|
10
|
+
authorize: (id: string, input: unknown) => boolean | Promise<boolean>;
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
/** Synchronous lease/grant guard immediately before domain execution or receipt replay. */
|
|
13
|
+
assertCurrent?: () => void;
|
|
14
|
+
actor?: ActorRef;
|
|
15
|
+
}
|
|
16
|
+
export interface ReadCapability<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> {
|
|
17
|
+
id: string;
|
|
18
|
+
majorVersion: number;
|
|
19
|
+
description: string;
|
|
20
|
+
effect: 'read';
|
|
21
|
+
surfaces: readonly CapabilitySurface[];
|
|
22
|
+
scopes: readonly GatewayScope[];
|
|
23
|
+
input: I;
|
|
24
|
+
output: O;
|
|
25
|
+
execute: (input: z.output<I>, context: CapabilityContext) => z.input<O> | Promise<z.input<O>>;
|
|
26
|
+
}
|
|
27
|
+
export declare function defineReadCapability<I extends z.ZodType, O extends z.ZodType>(definition: ReadCapability<I, O>): ReadCapability<I, O>;
|
|
28
|
+
export interface AtomicCapability<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> extends Omit<ReadCapability<I, O>, 'effect' | 'execute'> {
|
|
29
|
+
effect: 'local-write';
|
|
30
|
+
/** Bind receipts to trusted domain ownership that is not supplied in the public input. */
|
|
31
|
+
requestScope?: (context: CapabilityContext) => string;
|
|
32
|
+
/** Read-only asynchronous validation, skipped for committed receipt replay. Never perform effects here. */
|
|
33
|
+
prepare?: (input: z.output<I>, context: CapabilityContext) => void | Promise<void>;
|
|
34
|
+
execute: (input: z.output<I>, context: CapabilityContext & {
|
|
35
|
+
operationId: string;
|
|
36
|
+
idempotencyKey: string;
|
|
37
|
+
}) => z.input<O>;
|
|
38
|
+
afterCommit?: (result: z.output<O>, input: z.output<I>) => void | Promise<void>;
|
|
39
|
+
}
|
|
40
|
+
export declare function defineAtomicCapability<I extends z.ZodType, O extends z.ZodType>(definition: AtomicCapability<I, O>): AtomicCapability<I, O>;
|
|
41
|
+
export interface ExternalCapability<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> extends Omit<ReadCapability<I, O>, 'effect' | 'execute'> {
|
|
42
|
+
effect: 'external-write';
|
|
43
|
+
recovery: 'manual' | 'provider-idempotent';
|
|
44
|
+
requestScope?: (context: CapabilityContext) => string;
|
|
45
|
+
/** Provider-idempotent implementations must send operationId as the provider key. */
|
|
46
|
+
execute: (input: z.output<I>, context: CapabilityContext & {
|
|
47
|
+
operationId: string;
|
|
48
|
+
idempotencyKey: string;
|
|
49
|
+
}) => Promise<z.input<O>>;
|
|
50
|
+
}
|
|
51
|
+
export declare function defineExternalCapability<I extends z.ZodType, O extends z.ZodType>(definition: ExternalCapability<I, O>): ExternalCapability<I, O>;
|
|
52
|
+
type CapabilityDefinition<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType> = ReadCapability<I, O> | AtomicCapability<I, O> | ExternalCapability<I, O>;
|
|
53
|
+
/** Stable JSON encoding for contract digests; rejects non-JSON values. */
|
|
54
|
+
export declare function canonicalCapabilityJson(value: unknown): string;
|
|
55
|
+
export declare class CapabilityDispatcher {
|
|
56
|
+
private readonly entries;
|
|
57
|
+
register<I extends z.ZodType, O extends z.ZodType>(definition: CapabilityDefinition<I, O>): void;
|
|
58
|
+
private visible;
|
|
59
|
+
list(context: CapabilityContext): CapabilityDescriptor[];
|
|
60
|
+
describe(id: string, context: CapabilityContext): CapabilityDescriptor;
|
|
61
|
+
call(id: string, input: unknown, context: CapabilityContext, expected?: {
|
|
62
|
+
majorVersion: number;
|
|
63
|
+
descriptorDigest: string;
|
|
64
|
+
idempotencyKey?: string;
|
|
65
|
+
}): Promise<unknown>;
|
|
66
|
+
private validateResult;
|
|
67
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { SqliteCommitEffectError, init_transaction } from "../../storage/sqlite/transaction.js";
|
|
2
|
+
import { CapabilityError } from "./errors.js";
|
|
3
|
+
import { executeExternalOperation } from "./external-operations.js";
|
|
4
|
+
import { OperationConflictError, executeAtomicOperation } from "./atomic-operations.js";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
//#region src/capabilities/runtime/dispatcher.ts
|
|
8
|
+
init_transaction();
|
|
9
|
+
function defineReadCapability(definition) {
|
|
10
|
+
return definition;
|
|
11
|
+
}
|
|
12
|
+
function defineAtomicCapability(definition) {
|
|
13
|
+
return definition;
|
|
14
|
+
}
|
|
15
|
+
function defineExternalCapability(definition) {
|
|
16
|
+
return definition;
|
|
17
|
+
}
|
|
18
|
+
/** Stable JSON encoding for contract digests; rejects non-JSON values. */
|
|
19
|
+
function canonicalCapabilityJson(value) {
|
|
20
|
+
const parsed = z.json().parse(value);
|
|
21
|
+
const encode = (item) => {
|
|
22
|
+
if (Array.isArray(item)) return `[${item.map(encode).join(",")}]`;
|
|
23
|
+
if (item && typeof item === "object") return `{${Object.keys(item).sort().map((key) => `${JSON.stringify(key)}:${encode(item[key])}`).join(",")}}`;
|
|
24
|
+
return JSON.stringify(item);
|
|
25
|
+
};
|
|
26
|
+
return encode(parsed);
|
|
27
|
+
}
|
|
28
|
+
var CapabilityDispatcher = class {
|
|
29
|
+
entries = /* @__PURE__ */ new Map();
|
|
30
|
+
register(definition) {
|
|
31
|
+
if (!/^(xopc|extension)\.[a-zA-Z0-9_.-]+$/.test(definition.id) || !Number.isSafeInteger(definition.majorVersion) || definition.majorVersion < 1) throw new Error("Invalid capability identity");
|
|
32
|
+
if (this.entries.has(definition.id)) throw new Error(`Duplicate capability: ${definition.id}`);
|
|
33
|
+
const descriptor = {
|
|
34
|
+
id: definition.id,
|
|
35
|
+
majorVersion: definition.majorVersion,
|
|
36
|
+
description: definition.description,
|
|
37
|
+
effect: definition.effect,
|
|
38
|
+
surfaces: [...definition.surfaces],
|
|
39
|
+
inputSchema: z.toJSONSchema(definition.input, { io: "input" }),
|
|
40
|
+
outputSchema: z.toJSONSchema(definition.output, { io: "output" })
|
|
41
|
+
};
|
|
42
|
+
const descriptorDigest = createHash("sha256").update(canonicalCapabilityJson({
|
|
43
|
+
...descriptor,
|
|
44
|
+
scopes: definition.scopes,
|
|
45
|
+
...definition.effect === "external-write" ? { recovery: definition.recovery } : {}
|
|
46
|
+
})).digest("hex");
|
|
47
|
+
this.entries.set(definition.id, {
|
|
48
|
+
definition: {
|
|
49
|
+
...definition,
|
|
50
|
+
scopes: [...definition.scopes],
|
|
51
|
+
surfaces: [...definition.surfaces]
|
|
52
|
+
},
|
|
53
|
+
descriptor: {
|
|
54
|
+
...descriptor,
|
|
55
|
+
descriptorDigest
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
visible(definition, context) {
|
|
60
|
+
return Boolean(context.principalId) && definition.surfaces.includes(context.surface) && (!context.allowedCapabilities || context.allowedCapabilities.includes(definition.id)) && definition.scopes.every((scope) => context.scopes.includes("gateway.admin") || context.scopes.includes(scope));
|
|
61
|
+
}
|
|
62
|
+
list(context) {
|
|
63
|
+
return [...this.entries.values()].filter((entry) => this.visible(entry.definition, context)).map((entry) => structuredClone(entry.descriptor));
|
|
64
|
+
}
|
|
65
|
+
describe(id, context) {
|
|
66
|
+
const entry = this.entries.get(id);
|
|
67
|
+
if (!entry || !this.visible(entry.definition, context)) throw new CapabilityError("NOT_FOUND", "Capability not available");
|
|
68
|
+
return structuredClone(entry.descriptor);
|
|
69
|
+
}
|
|
70
|
+
async call(id, input, context, expected) {
|
|
71
|
+
const descriptor = this.describe(id, context);
|
|
72
|
+
if (expected && (expected.majorVersion !== descriptor.majorVersion || expected.descriptorDigest !== descriptor.descriptorDigest)) throw new CapabilityError("CONTRACT_CHANGED", "Capability contract changed; describe it again");
|
|
73
|
+
const { definition } = this.entries.get(id);
|
|
74
|
+
const parsed = definition.input.safeParse(input);
|
|
75
|
+
if (!parsed.success) throw new CapabilityError("INVALID_INPUT", parsed.error.message);
|
|
76
|
+
if (!await context.authorize(id, parsed.data)) throw new CapabilityError("FORBIDDEN", "Capability resource access denied");
|
|
77
|
+
context.assertCurrent?.();
|
|
78
|
+
if (context.signal?.aborted) throw new CapabilityError("CANCELLED", "Capability call cancelled");
|
|
79
|
+
if (definition.effect === "external-write") {
|
|
80
|
+
const key = expected?.idempotencyKey;
|
|
81
|
+
if (!key?.trim() || key.length > 200) throw new CapabilityError("INVALID_INPUT", "A stable idempotencyKey is required");
|
|
82
|
+
const normalizedInput = JSON.parse(JSON.stringify(parsed.data));
|
|
83
|
+
const identity = definition.requestScope ? {
|
|
84
|
+
input: normalizedInput,
|
|
85
|
+
scope: definition.requestScope(context)
|
|
86
|
+
} : normalizedInput;
|
|
87
|
+
return executeExternalOperation({
|
|
88
|
+
principalId: context.principalId,
|
|
89
|
+
capabilityId: id,
|
|
90
|
+
idempotencyKey: key,
|
|
91
|
+
requestDigest: createHash("sha256").update(canonicalCapabilityJson(identity)).digest("hex"),
|
|
92
|
+
descriptorDigest: descriptor.descriptorDigest,
|
|
93
|
+
surface: context.surface,
|
|
94
|
+
recovery: definition.recovery
|
|
95
|
+
}, (operationId) => definition.execute(parsed.data, {
|
|
96
|
+
...context,
|
|
97
|
+
operationId,
|
|
98
|
+
idempotencyKey: key
|
|
99
|
+
}), (result) => this.validateResult(definition, result));
|
|
100
|
+
}
|
|
101
|
+
if (definition.effect === "local-write") {
|
|
102
|
+
const key = expected?.idempotencyKey;
|
|
103
|
+
if (!key?.trim() || key.length > 200) throw new CapabilityError("INVALID_INPUT", "A stable idempotencyKey is required");
|
|
104
|
+
try {
|
|
105
|
+
const normalizedInput = JSON.parse(JSON.stringify(parsed.data));
|
|
106
|
+
const scope = definition.requestScope?.(context);
|
|
107
|
+
const requestIdentity = definition.requestScope ? {
|
|
108
|
+
input: normalizedInput,
|
|
109
|
+
scope
|
|
110
|
+
} : normalizedInput;
|
|
111
|
+
const preparationRequired = Symbol("preparationRequired");
|
|
112
|
+
let prepared = !definition.prepare;
|
|
113
|
+
const execute = () => {
|
|
114
|
+
context.assertCurrent?.();
|
|
115
|
+
return executeAtomicOperation({
|
|
116
|
+
principalId: context.principalId,
|
|
117
|
+
capabilityId: id,
|
|
118
|
+
idempotencyKey: key,
|
|
119
|
+
requestDigest: createHash("sha256").update(canonicalCapabilityJson(requestIdentity)).digest("hex"),
|
|
120
|
+
descriptorDigest: descriptor.descriptorDigest,
|
|
121
|
+
surface: context.surface
|
|
122
|
+
}, (operationId) => {
|
|
123
|
+
if (!prepared) throw preparationRequired;
|
|
124
|
+
const output = definition.execute(parsed.data, {
|
|
125
|
+
...context,
|
|
126
|
+
operationId,
|
|
127
|
+
idempotencyKey: key
|
|
128
|
+
});
|
|
129
|
+
if (output && typeof output.then === "function") throw new Error("Atomic capability handlers must be synchronous");
|
|
130
|
+
return this.validateResult(definition, output);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
let result;
|
|
134
|
+
try {
|
|
135
|
+
result = execute();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (error !== preparationRequired) throw error;
|
|
138
|
+
await definition.prepare(parsed.data, context);
|
|
139
|
+
if (!await context.authorize(id, parsed.data)) throw new CapabilityError("FORBIDDEN", "Capability resource access denied");
|
|
140
|
+
if (context.signal?.aborted) throw new CapabilityError("CANCELLED", "Capability call cancelled");
|
|
141
|
+
if (definition.requestScope?.(context) !== scope) throw new CapabilityError("REVISION_CONFLICT", "Capability ownership changed during preparation");
|
|
142
|
+
prepared = true;
|
|
143
|
+
result = execute();
|
|
144
|
+
}
|
|
145
|
+
await definition.afterCommit?.(result, parsed.data);
|
|
146
|
+
return result;
|
|
147
|
+
} catch (error) {
|
|
148
|
+
if (error instanceof OperationConflictError) throw new CapabilityError("REVISION_CONFLICT", error.message);
|
|
149
|
+
if (error instanceof SqliteCommitEffectError) {
|
|
150
|
+
const pending = new CapabilityError("UNAVAILABLE", "Operation committed; post-commit work is pending. Retry the same idempotencyKey.");
|
|
151
|
+
pending.cause = error;
|
|
152
|
+
throw pending;
|
|
153
|
+
}
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return this.validateResult(definition, await definition.execute(parsed.data, context));
|
|
158
|
+
}
|
|
159
|
+
validateResult(definition, result) {
|
|
160
|
+
const validated = definition.output.safeParse(result);
|
|
161
|
+
if (!validated.success) {
|
|
162
|
+
const error = new CapabilityError("INTERNAL", "Capability returned an invalid result");
|
|
163
|
+
error.cause = validated.error;
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
return validated.data;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
//#endregion
|
|
170
|
+
export { CapabilityDispatcher, CapabilityError, canonicalCapabilityJson, defineAtomicCapability, defineExternalCapability, defineReadCapability };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CapabilityErrorCode } from '@xopcai/gateway-contract';
|
|
2
|
+
export declare class CapabilityError extends Error {
|
|
3
|
+
readonly code: CapabilityErrorCode;
|
|
4
|
+
readonly operationId?: string;
|
|
5
|
+
constructor(code: CapabilityErrorCode, message: string, operationId?: string);
|
|
6
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/capabilities/runtime/errors.ts
|
|
2
|
+
var CapabilityError = class extends Error {
|
|
3
|
+
constructor(code, message, operationId) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.operationId = operationId;
|
|
7
|
+
this.name = "CapabilityError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { CapabilityError };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Use only when the provider can prove that no effect was applied. Network errors are not proof. */
|
|
2
|
+
export declare class ExternalEffectNotAppliedError extends Error {
|
|
3
|
+
}
|
|
4
|
+
export interface ExternalOperationInput {
|
|
5
|
+
principalId: string;
|
|
6
|
+
capabilityId: string;
|
|
7
|
+
idempotencyKey: string;
|
|
8
|
+
requestDigest: string;
|
|
9
|
+
descriptorDigest: string;
|
|
10
|
+
surface: string;
|
|
11
|
+
recovery: 'manual' | 'provider-idempotent';
|
|
12
|
+
leaseMs?: number;
|
|
13
|
+
now?: () => number;
|
|
14
|
+
}
|
|
15
|
+
/** The callback must use operationId as the provider key when declaring provider-idempotent recovery. */
|
|
16
|
+
export declare function executeExternalOperation<T>(input: ExternalOperationInput, execute: (operationId: string) => Promise<T>, validate?: (result: T) => T): Promise<T>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
2
|
+
import { CapabilityError } from "./errors.js";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
//#region src/capabilities/runtime/external-operations.ts
|
|
5
|
+
init_transaction();
|
|
6
|
+
/** Use only when the provider can prove that no effect was applied. Network errors are not proof. */
|
|
7
|
+
var ExternalEffectNotAppliedError = class extends Error {};
|
|
8
|
+
/** The callback must use operationId as the provider key when declaring provider-idempotent recovery. */
|
|
9
|
+
async function executeExternalOperation(input, execute, validate) {
|
|
10
|
+
if (!input.principalId || !input.idempotencyKey.trim() || input.idempotencyKey.length > 200) throw new CapabilityError("INVALID_INPUT", "External operation identity is required");
|
|
11
|
+
if (input.leaseMs !== void 0 && !Number.isFinite(input.leaseMs)) throw new CapabilityError("INVALID_INPUT", "Lease duration must be finite");
|
|
12
|
+
const now = input.now ?? Date.now;
|
|
13
|
+
const invocationId = randomUUID();
|
|
14
|
+
const claim = runSqliteWriteTransaction((db) => {
|
|
15
|
+
const row = db.prepare(`SELECT operation_id, request_digest, descriptor_digest, state, result_json, generation, lease_expires_at, recovery_mode
|
|
16
|
+
FROM capability_operations WHERE principal_id = ? AND capability_id = ? AND idempotency_key = ?`).get(input.principalId, input.capabilityId, input.idempotencyKey);
|
|
17
|
+
if (row && (row.request_digest !== input.requestDigest || row.descriptor_digest !== input.descriptorDigest || row.recovery_mode !== input.recovery)) throw new CapabilityError("REVISION_CONFLICT", "Operation parameters or contract changed", row.operation_id);
|
|
18
|
+
if (row?.state === "succeeded") {
|
|
19
|
+
db.prepare(`INSERT INTO capability_invocations
|
|
20
|
+
(invocation_id, operation_id, surface, replayed, created_at, finished_at) VALUES (?, ?, ?, 1, ?, ?)`).run(invocationId, row.operation_id, input.surface, now(), now());
|
|
21
|
+
return {
|
|
22
|
+
replay: true,
|
|
23
|
+
result: JSON.parse(row.result_json),
|
|
24
|
+
operationId: row.operation_id,
|
|
25
|
+
generation: row.generation
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (row?.state === "failed") throw new CapabilityError("UNAVAILABLE", "Previous attempt was rejected without applying an effect; use a new intent to retry", row.operation_id);
|
|
29
|
+
if (row?.state === "running" && (row.lease_expires_at ?? 0) > now()) throw new CapabilityError("IN_PROGRESS", "The same external operation is still running", row.operation_id);
|
|
30
|
+
if (row && input.recovery === "manual") return {
|
|
31
|
+
unknown: true,
|
|
32
|
+
operationId: row.operation_id,
|
|
33
|
+
generation: row.generation
|
|
34
|
+
};
|
|
35
|
+
const operationId = row?.operation_id ?? randomUUID();
|
|
36
|
+
const generation = (row?.generation ?? 0) + 1;
|
|
37
|
+
const expires = now() + Math.max(1e3, Math.min(input.leaseMs ?? 12e4, 36e5));
|
|
38
|
+
if (row) {
|
|
39
|
+
db.prepare(`UPDATE capability_operations SET state = 'running', generation = ?, lease_expires_at = ?
|
|
40
|
+
WHERE operation_id = ?`).run(generation, expires, operationId);
|
|
41
|
+
db.prepare(`UPDATE capability_invocations SET state = 'unknown', finished_at = ?
|
|
42
|
+
WHERE operation_id = ? AND state = 'running'`).run(now(), operationId);
|
|
43
|
+
} else db.prepare(`INSERT INTO capability_operations
|
|
44
|
+
(operation_id, principal_id, capability_id, idempotency_key, request_digest, descriptor_digest,
|
|
45
|
+
result_json, created_at, state, generation, lease_expires_at, recovery_mode) VALUES (?, ?, ?, ?, ?, ?, 'null', ?, 'running', ?, ?, ?)`).run(operationId, input.principalId, input.capabilityId, input.idempotencyKey, input.requestDigest, input.descriptorDigest, now(), generation, expires, input.recovery);
|
|
46
|
+
db.prepare(`INSERT INTO capability_invocations
|
|
47
|
+
(invocation_id, operation_id, surface, replayed, created_at, state) VALUES (?, ?, ?, 0, ?, 'running')`).run(invocationId, operationId, input.surface, now());
|
|
48
|
+
return {
|
|
49
|
+
operationId,
|
|
50
|
+
generation
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
if ("replay" in claim) return claim.result;
|
|
54
|
+
if ("unknown" in claim) {
|
|
55
|
+
runSqliteWriteTransaction((db) => {
|
|
56
|
+
db.prepare(`UPDATE capability_operations SET state = 'unknown'
|
|
57
|
+
WHERE operation_id = ? AND generation = ? AND state = 'running'`).run(claim.operationId, claim.generation);
|
|
58
|
+
db.prepare(`UPDATE capability_invocations SET state = 'unknown', finished_at = ?
|
|
59
|
+
WHERE operation_id = ? AND state = 'running'`).run(now(), claim.operationId);
|
|
60
|
+
});
|
|
61
|
+
throw new CapabilityError("OUTCOME_UNKNOWN", "External outcome is unknown; verify it before issuing another write", claim.operationId);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const raw = await execute(claim.operationId);
|
|
65
|
+
const evidence = JSON.stringify(raw);
|
|
66
|
+
if (evidence !== void 0) getSqliteDatabase().prepare(`UPDATE capability_operations SET evidence_json = ?
|
|
67
|
+
WHERE operation_id = ? AND generation = ?`).run(evidence, claim.operationId, claim.generation);
|
|
68
|
+
const result = validate ? validate(raw) : raw;
|
|
69
|
+
const json = JSON.stringify(result);
|
|
70
|
+
if (json === void 0) throw new Error("External result must be JSON");
|
|
71
|
+
if (!runSqliteWriteTransaction((db) => {
|
|
72
|
+
const changed = db.prepare(`UPDATE capability_operations SET state = 'succeeded', result_json = ?, lease_expires_at = NULL
|
|
73
|
+
WHERE operation_id = ? AND generation = ? AND state IN ('running', 'unknown')`).run(json, claim.operationId, claim.generation).changes;
|
|
74
|
+
if (changed) db.prepare(`UPDATE capability_invocations SET state = 'succeeded', finished_at = ? WHERE invocation_id = ?`).run(now(), invocationId);
|
|
75
|
+
return changed;
|
|
76
|
+
})) throw new CapabilityError("OUTCOME_UNKNOWN", "A newer recovery attempt owns this operation", claim.operationId);
|
|
77
|
+
return JSON.parse(json);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
const state = error instanceof ExternalEffectNotAppliedError ? "failed" : "unknown";
|
|
80
|
+
runSqliteWriteTransaction((db) => {
|
|
81
|
+
db.prepare(`UPDATE capability_operations SET state = ?, lease_expires_at = NULL
|
|
82
|
+
WHERE operation_id = ? AND generation = ? AND state = 'running'`).run(state, claim.operationId, claim.generation);
|
|
83
|
+
db.prepare(`UPDATE capability_invocations SET state = ?, finished_at = ? WHERE invocation_id = ? AND state = 'running'`).run(state, now(), invocationId);
|
|
84
|
+
});
|
|
85
|
+
const rejection = error instanceof ExternalEffectNotAppliedError && error.cause instanceof CapabilityError ? error.cause : void 0;
|
|
86
|
+
const failure = new CapabilityError(rejection?.code ?? (state === "failed" ? "UNAVAILABLE" : "OUTCOME_UNKNOWN"), rejection?.message ?? (state === "failed" ? "Provider confirmed no effect was applied" : "External outcome is unknown; do not resend with a new key without verification"), claim.operationId);
|
|
87
|
+
failure.cause = error;
|
|
88
|
+
throw failure;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { ExternalEffectNotAppliedError, executeExternalOperation };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NotesService } from '../../notes/service.js';
|
|
2
|
+
import type { LocalAppService } from '../../local-apps/service.js';
|
|
3
|
+
import { type ProjectWriteCapabilityDeps } from '../../projects/capabilities/write.js';
|
|
4
|
+
import type { AutomationService } from '../../automations/service/automation-service.js';
|
|
5
|
+
import { type TaskWriteCapabilityDeps } from '../../tasks/capabilities/write.js';
|
|
6
|
+
import { CapabilityDispatcher, type CapabilityContext } from './dispatcher.js';
|
|
7
|
+
import type { SceneAccess } from '../../scenes/httpServices.js';
|
|
8
|
+
export declare function createProductDispatcher(getNotes?: () => NotesService | undefined, taskWrites?: TaskWriteCapabilityDeps & ProjectWriteCapabilityDeps & {
|
|
9
|
+
getAutomations?: () => AutomationService | undefined;
|
|
10
|
+
getLocalApps?: () => LocalAppService | undefined;
|
|
11
|
+
getSceneAccess?: (context: CapabilityContext) => SceneAccess | undefined;
|
|
12
|
+
}): CapabilityDispatcher;
|