@xopcai/xopc 0.0.332 → 0.0.334
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-DocRzRlS.js → auth-Cjj5SuoT.js} +49 -39
- package/dist/browser-ext/dist/background.js +1 -1
- package/dist/browser-ext/dist/sidepanel.html +1 -1
- package/dist/browser-ext/dist/sidepanel.js +240 -36
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/{agent-avatar-dicebear-C2wg3xC_.js → agent-avatar-dicebear-B73q7mlz.js} +1 -1
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-B9L2YIXz.js +1 -0
- package/dist/gateway/static/root/assets/{agent-plugin-dialog-BeNnu1Ts.js → agent-plugin-dialog-COOjsvea.js} +1 -1
- package/dist/gateway/static/root/assets/agents-CCj1JnLu.js +70 -0
- package/dist/gateway/static/root/assets/agents-admin-api-Cuqi5xZn.js +2 -0
- package/dist/gateway/static/root/assets/{app-link-C6gA5Nck.js → app-link-DRL0YnPs.js} +1 -1
- package/dist/gateway/static/root/assets/{app-management-settings-panel-etFSkfzl.js → app-management-settings-panel-CckioKud.js} +1 -1
- package/dist/gateway/static/root/assets/{appearance-settings-DKmU2VAP.js → appearance-settings-DDiPIr_Q.js} +1 -1
- package/dist/gateway/static/root/assets/apps-page-Azqy8vfo.js +1 -0
- package/dist/gateway/static/root/assets/{archive-plugin-D0z_Fr2G.js → archive-plugin-Dtyr0RhX.js} +1 -1
- package/dist/gateway/static/root/assets/attachment-load-qjPpQzYY.js +1 -0
- package/dist/gateway/static/root/assets/attachment-utils-core-BIOUBrpT.js +1 -0
- package/dist/gateway/static/root/assets/{automations-page-B7_C-p66.js → automations-page-g3SrFkTC.js} +1 -1
- package/dist/gateway/static/root/assets/automations-workspace-B0nW2nZD.js +7 -0
- package/dist/gateway/static/root/assets/binary-plugins-BwKQVxsU.js +2 -0
- package/dist/gateway/static/root/assets/{block-editor-ChWW8Z9L.js → block-editor-DD9d5pCt.js} +29 -29
- package/dist/gateway/static/root/assets/{browser-automation-inputs-C5s1yHOu.js → browser-automation-inputs-D2gNdS3e.js} +1 -1
- package/dist/gateway/static/root/assets/{browser-automations-page-BV00BXRb.js → browser-automations-page-BKqqJR7P.js} +2 -2
- package/dist/gateway/static/root/assets/{browser-settings-page-xwTmuZjS.js → browser-settings-page-BZH9bZbk.js} +2 -2
- package/dist/gateway/static/root/assets/capabilities-CHk4RZl4.js +1 -0
- package/dist/gateway/static/root/assets/capabilities-page-CfWaVH-6.js +2 -0
- package/dist/gateway/static/root/assets/capabilities-settings-panel-C5FcWsSe.js +8 -0
- package/dist/gateway/static/root/assets/capability-header-actions-Bd66yEOa.js +1 -0
- package/dist/gateway/static/root/assets/channels-DIU5Gq4o.js +1 -0
- package/dist/gateway/static/root/assets/{chat-terminal-dock-C41mXCAi.js → chat-terminal-dock-B0nPDJyj.js} +2 -2
- package/dist/gateway/static/root/assets/{computer-settings-page-BJkqok2G.js → computer-settings-page-D7PxxaoG.js} +1 -1
- package/dist/gateway/static/root/assets/{connector-service-page-BKCZMmwm.js → connector-service-page-BZH4SeQg.js} +1 -1
- package/dist/gateway/static/root/assets/connectors-page-BC81R_fz.js +2 -0
- package/dist/gateway/static/root/assets/{turn-outcome-D0SnyZ3Z.js → constants-Co2_smKQ.js} +1 -1
- package/dist/gateway/static/root/assets/date-picker-CDEVYjXI.js +1 -0
- package/dist/gateway/static/root/assets/{dependency-picker-CqADAHZp.js → dependency-picker-AInmpSwC.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-Bab-iWED.js → desktop-pet-Sjgnlq8M.js} +1 -1
- package/dist/gateway/static/root/assets/{desktop-pet-settings-BqgzLOdi.js → desktop-pet-settings-BWn0rrhr.js} +1 -1
- package/dist/gateway/static/root/assets/{device-pairing-wizard-DFg7FDPf.js → device-pairing-wizard-BtW837_d.js} +1 -1
- package/dist/gateway/static/root/assets/{directory-picker-path-field-hqJ9sFCR.js → directory-picker-path-field-2CpmDx_D.js} +1 -1
- package/dist/gateway/static/root/assets/dist-CKkafhaS.js +1 -0
- package/dist/gateway/static/root/assets/dist-io9jFpN72.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-DX3PFhRE.js → extension-debug-page-WWJFj9Z5.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-DkREdHLs.js → extension-page-DL00dFRr.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-wF-HNTM-.js → extension-settings-page-CN-agjPk.js} +1 -1
- package/dist/gateway/static/root/assets/{files-BK6enEvD.js → files-Bw4SBGdM.js} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-cR-tz7-Q.js → gateway-config-swr-CgIjCxM8.js} +1 -1
- package/dist/gateway/static/root/assets/gateway-realtime-Ciq4c7KT.js +1 -0
- package/dist/gateway/static/root/assets/gateway-realtime-store-BHeHN26R.js +1 -0
- package/dist/gateway/static/root/assets/gateway-settings-4oD6fhAm.js +1 -0
- package/dist/gateway/static/root/assets/{gateway-startup-retry-6jLRcQsu.js → gateway-startup-retry-i-1lTrwY.js} +1 -1
- package/dist/gateway/static/root/assets/home-page-nEpyJUBY.js +1 -0
- package/dist/gateway/static/root/assets/{image-generation-api-CSSkwsyC.js → image-generation-api-gilc-u7M.js} +1 -1
- package/dist/gateway/static/root/assets/{imports-page-B80Cv043.js → imports-page-BivdeiQ5.js} +1 -1
- package/dist/gateway/static/root/assets/index-BioG1pRD.js +106 -0
- package/dist/gateway/static/root/assets/index-DbLEkdNg.css +1 -0
- package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-BgoFaTwv.js → keyboard-shortcuts-settings-B_8AJTFr.js} +1 -1
- package/dist/gateway/static/root/assets/local-app-workbench-page-CRtZQrmz.js +1 -0
- package/dist/gateway/static/root/assets/{local-apps-page-HO6OQlQT.js → local-apps-page-DclxpoqR.js} +1 -1
- package/dist/gateway/static/root/assets/{local-apps-Bpja8nC6.js → local-apps-yys1VChX.js} +1 -1
- package/dist/gateway/static/root/assets/local-session-drafts-DkolHmyp.js +1 -0
- package/dist/gateway/static/root/assets/{locale-store-wNXWkWu5.js → locale-store-BY30D6tg.js} +1 -1
- package/dist/gateway/static/root/assets/logs-page-DX8TxkRl.js +2 -0
- package/dist/gateway/static/root/assets/management-settings-5WFufZ4g.js +1 -0
- package/dist/gateway/static/root/assets/{markdown-view-DlT9KqwF.js → markdown-view-DYJnwlDr.js} +1 -1
- package/dist/gateway/static/root/assets/media-plugins-DlJDvwLK.js +1 -0
- package/dist/gateway/static/root/assets/messages-_6IXbP2u.js +3 -0
- package/dist/gateway/static/root/assets/note-detail-panel-GF5Q9Fqy.js +5 -0
- package/dist/gateway/static/root/assets/notes-page-E8o4_Ty9.js +8 -0
- package/dist/gateway/static/root/assets/page-context-capture-button-CiCmfRTw.js +1 -0
- package/dist/gateway/static/root/assets/{page-tabs-vqI30Yrg.js → page-tabs-Cwp3fGVM.js} +1 -1
- package/dist/gateway/static/root/assets/popover-select-0p9PIHRy.js +1 -0
- package/dist/gateway/static/root/assets/{preview-open-alternatives-B-mwPBJW.js → preview-open-alternatives-DJ5xqGeu.js} +1 -1
- package/dist/gateway/static/root/assets/{product-delivery-bv3z8Xkh.js → product-delivery-BAks11S4.js} +1 -1
- package/dist/gateway/static/root/assets/{product-open-page-D--sj_uN.js → product-open-page-CcGwNePw.js} +1 -1
- package/dist/gateway/static/root/assets/project-detail-page-6hhRBkmC.js +1 -0
- package/dist/gateway/static/root/assets/projects-page-DUOzRaFI.js +1 -0
- package/dist/gateway/static/root/assets/{registry-api-BIpltJ47.js → registry-api-BvVx0G1o.js} +1 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BWpWUXiE.js +1 -0
- package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-CAnb0PNY.js → runtime-tools-settings-panel-C6eDCNHz.js} +2 -2
- package/dist/gateway/static/root/assets/scenes-page-pF7Lmqnk.js +2 -0
- package/dist/gateway/static/root/assets/{schema-form-BKj6wIMb.js → schema-form-D8W8q_ez.js} +1 -1
- package/dist/gateway/static/root/assets/{schemas-88fK3zzl.js → schemas-CObaziC7.js} +3 -3
- package/dist/gateway/static/root/assets/session-api-BAyUr97V.js +1 -0
- package/dist/gateway/static/root/assets/session-manager-BAy2sR2Q.js +16 -0
- package/dist/gateway/static/root/assets/sessions-page-BDKDqqf9.js +1 -0
- package/dist/gateway/static/root/assets/settings-advanced-gate-C9cJWlAq.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-78ycUHfv.js → settings-form-section-B0cAj0nq.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-BOdxIVzo.js → settings-page-DZVVTFxs.js} +1 -1
- package/dist/gateway/static/root/assets/setup-status-panel-DZCPVx9c.js +1 -0
- package/dist/gateway/static/root/assets/share-preview-page-BkPNyV8c.js +2 -0
- package/dist/gateway/static/root/assets/shares-settings-Bqlv5JBi.js +1 -0
- package/dist/gateway/static/root/assets/{skill-api-CiBGQ0Jg.js → skill-api-C0dufzQC.js} +1 -1
- package/dist/gateway/static/root/assets/skill-reload-api-3JF2OTBz.js +1 -0
- package/dist/gateway/static/root/assets/skills-page-DB4lR4om.js +2 -0
- package/dist/gateway/static/root/assets/{system-settings-panel-CyJUeREH.js → system-settings-panel-xjrlhdUz.js} +1 -1
- package/dist/gateway/static/root/assets/task-detail-page-CB6M7wSs.js +1 -0
- package/dist/gateway/static/root/assets/{tasks-CDR_RVbQ.js → tasks-QQJXsiER.js} +1 -1
- package/dist/gateway/static/root/assets/{tunnel-api-Day9zhKi.js → tunnel-api--68MQEWM.js} +1 -1
- package/dist/gateway/static/root/assets/usage-page-OLZ00eqD.js +1 -0
- package/dist/gateway/static/root/assets/{use-autosave-Bj9hC6ML.js → use-autosave-DsnHYpTv.js} +1 -1
- package/dist/gateway/static/root/assets/user-model-page-CoePFpHD.js +2 -0
- package/dist/gateway/static/root/assets/{voice-api-key-field-fWRD6B8r.js → voice-api-key-field-CvIXutQp.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-config-api-ujEySjyc.js → voice-config-api-Bwy3Al3J.js} +1 -1
- package/dist/gateway/static/root/assets/{work-discovery-overlay-CnxdvIk8.js → work-discovery-overlay-By5_7MLR.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-run-setup-panel-DlWNN1VA.js → workflow-run-setup-panel-HSMDxDXV.js} +2 -2
- package/dist/gateway/static/root/assets/workflows-page-DElQ47Da.js +6 -0
- package/dist/gateway/static/root/index.html +27 -21
- package/dist/package.js +1 -1
- package/dist/packages/gateway-contract/src/automations.js +44 -14
- package/dist/packages/gateway-contract/src/capabilities.js +120 -10
- package/dist/packages/gateway-contract/src/index.js +8 -2
- package/dist/packages/gateway-contract/src/scenes.js +7 -6
- package/dist/packages/gateway-contract/src/session-command-rejection.js +19 -0
- package/dist/packages/gateway-contract/src/session-input-command.js +109 -0
- package/dist/packages/gateway-contract/src/sessions.js +2 -7
- package/dist/packages/gateway-contract/src/usage.js +6 -0
- package/dist/src/agent/agent-manager.js +15 -9
- package/dist/src/agent/background-review/run-background-review.js +8 -3
- package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
- package/dist/src/agent/embedded/model-runtime.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -1
- package/dist/src/agent/embedded/run-turn.js +7 -1
- package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
- package/dist/src/agent/external-tools/gateway-tools.d.ts +2 -1
- package/dist/src/agent/external-tools/gateway-tools.js +45 -11
- package/dist/src/agent/external-tools/index.js +1 -1
- package/dist/src/agent/image/tool-model-config.js +2 -2
- package/dist/src/agent/image/understanding/pi-ai-provider.js +1 -1
- package/dist/src/agent/memory/compaction.js +4 -0
- package/dist/src/agent/service/btw-query.js +8 -2
- package/dist/src/agent/service/process-direct-streaming.js +4 -2
- package/dist/src/agent/service.js +5 -5
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/filesystem-watcher.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +2 -2
- package/dist/src/agent/skills/marketplace/adapters/store/adapter.js +1 -1
- package/dist/src/agent/skills/marketplace/adapters/store/store-api-client.js +1 -1
- package/dist/src/agent/tasks/task-judge-service.js +7 -3
- package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
- package/dist/src/agent/tool-manuals/xopc-use.js +5 -4
- package/dist/src/agent/tools/automation-tool.d.ts +4 -1
- package/dist/src/agent/tools/automation-tool.js +42 -4
- package/dist/src/agent/tools/session-search-tool.js +1 -1
- package/dist/src/agent/tools/web-extract.js +1 -1
- package/dist/src/agent/tools/xopc-use-tool.js +50 -9
- package/dist/src/agent-catalog/capabilities.js +2 -2
- package/dist/src/ai-assist/text-assist.js +6 -2
- package/dist/src/auth/credentials.js +1 -1
- package/dist/src/auth/oauth-provider-lock.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/automations/api/routes.js +65 -0
- package/dist/src/automations/capabilities/drafts.js +1 -1
- package/dist/src/automations/capabilities/read.js +24 -0
- package/dist/src/automations/capabilities/write.d.ts +52 -14
- package/dist/src/automations/capabilities/write.js +52 -3
- package/dist/src/automations/delivery/delivery-router.d.ts +50 -0
- package/dist/src/automations/delivery/delivery-router.js +318 -0
- package/dist/src/automations/delivery/index.d.ts +1 -0
- package/dist/src/automations/delivery/index.js +2 -0
- package/dist/src/automations/domain/defaults.d.ts +0 -1
- package/dist/src/automations/domain/defaults.js +1 -1
- package/dist/src/automations/domain/index.js +2 -2
- package/dist/src/automations/domain/types.d.ts +158 -7
- package/dist/src/automations/domain/validation.d.ts +104 -22
- package/dist/src/automations/domain/validation.js +66 -13
- package/dist/src/automations/draft/automation-draft-prompt.js +3 -4
- package/dist/src/automations/draft/automation-draft-service.js +6 -0
- package/dist/src/automations/draft/automation-draft-validator.d.ts +22 -3
- package/dist/src/automations/draft/automation-draft-validator.js +4 -4
- package/dist/src/automations/events/event-catalog.d.ts +14 -0
- package/dist/src/automations/events/event-catalog.js +117 -0
- package/dist/src/automations/events/event-dispatcher.d.ts +27 -0
- package/dist/src/automations/events/event-dispatcher.js +140 -0
- package/dist/src/automations/events/event-repository.d.ts +59 -0
- package/dist/src/automations/events/event-repository.js +361 -0
- package/dist/src/automations/events/index.d.ts +3 -0
- package/dist/src/automations/events/index.js +4 -0
- package/dist/src/automations/index.d.ts +3 -1
- package/dist/src/automations/index.js +9 -3
- package/dist/src/automations/service/action-executor.d.ts +20 -1
- package/dist/src/automations/service/action-executor.js +80 -40
- package/dist/src/automations/service/automation-service.d.ts +21 -4
- package/dist/src/automations/service/automation-service.js +150 -100
- package/dist/src/automations/storage/automation-repository.js +4 -5
- package/dist/src/automations/storage/automation-run-repository.d.ts +1 -0
- package/dist/src/automations/storage/automation-run-repository.js +26 -1
- package/dist/src/automations/storage/index.js +2 -2
- package/dist/src/automations/webhook-secrets.d.ts +1 -0
- package/dist/src/automations/webhook-secrets.js +16 -0
- package/dist/src/bootstrap/application-state.js +1 -1
- package/dist/src/capabilities/runtime/dispatcher.js +1 -1
- package/dist/src/capabilities/runtime/product.js +1 -1
- package/dist/src/capabilities/store-connector.d.ts +17 -1
- package/dist/src/capabilities/store-connector.js +69 -3
- package/dist/src/channels/attachments/voice-stt-webchat.js +1 -1
- package/dist/src/chat-commands/agent-edit.js +1 -1
- package/dist/src/chat-commands/builtins/config.js +1 -1
- package/dist/src/cli/commands/agent.js +1 -1
- package/dist/src/cli/commands/agents.js +1 -1
- package/dist/src/cli/commands/connectors.js +4 -3
- package/dist/src/cli/commands/doctor/checks/automation-integrity.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/automation-integrity.js +55 -0
- package/dist/src/cli/commands/doctor/checks/database-relations.d.ts +2 -0
- package/dist/src/cli/commands/doctor/checks/database-relations.js +81 -0
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +2 -2
- package/dist/src/cli/commands/doctor/flow.js +5 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/models.js +1 -1
- package/dist/src/cli/commands/onboard/model.js +2 -2
- package/dist/src/cli/commands/skills.js +1 -1
- package/dist/src/cli/utils/init-workspace-core.js +1 -1
- package/dist/src/computer/runtime.js +1 -1
- package/dist/src/config/index.js +5 -5
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/schema.js +1 -1
- package/dist/src/connectors/approval-resume.js +1 -1
- package/dist/src/connectors/cli/authorization.d.ts +1 -1
- package/dist/src/connectors/cli/store.d.ts +1 -1
- package/dist/src/connectors/cli/store.js +1 -1
- package/dist/src/connectors/composio-backends.js +14 -4
- package/dist/src/connectors/composio-managed-events.d.ts +5 -2
- package/dist/src/connectors/composio-managed-events.js +4 -1
- package/dist/src/connectors/connection-candidates.js +53 -15
- package/dist/src/connectors/connection-capabilities.js +5 -1
- package/dist/src/connectors/connection-recovery-service.d.ts +2 -1
- package/dist/src/connectors/connection-recovery-service.js +89 -4
- package/dist/src/discussions/analyzer.js +4 -4
- package/dist/src/execution-environments/local-worktree-manager.js +10 -1
- package/dist/src/execution-environments/session-environment-service.d.ts +3 -0
- package/dist/src/execution-environments/session-environment-service.js +28 -4
- package/dist/src/extensions/agent-plugins/validation.js +1 -1
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/file-path-classifier.js +1 -1
- package/dist/src/gateway/home-intelligence-automation-reconciler.js +4 -1
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/routes/agent-stream.js +6 -2
- package/dist/src/gateway/hono/routes/browser-session.js +4 -2
- package/dist/src/gateway/hono/routes/capabilities.js +1 -1
- package/dist/src/gateway/hono/routes/commands-skills.js +9 -2
- package/dist/src/gateway/hono/routes/config-patch/misc.js +2 -2
- package/dist/src/gateway/hono/routes/connection-waits.js +3 -2
- package/dist/src/gateway/hono/routes/files.js +3 -0
- package/dist/src/gateway/hono/routes/lazy-bundles.js +14 -1
- package/dist/src/gateway/hono/routes/models.js +17 -1
- package/dist/src/gateway/hono/routes/notes.js +2 -4
- package/dist/src/gateway/hono/routes/projects.js +2 -2
- package/dist/src/gateway/hono/routes/public-gateway.js +93 -3
- package/dist/src/gateway/hono/routes/scenes.js +57 -41
- package/dist/src/gateway/hono/routes/session-command-handler.d.ts +5 -0
- package/dist/src/gateway/hono/routes/session-command-handler.js +189 -0
- package/dist/src/gateway/hono/routes/session-input-handler.d.ts +14 -2
- package/dist/src/gateway/hono/routes/session-input-handler.js +2 -2
- package/dist/src/gateway/hono/routes/sessions.js +15 -168
- package/dist/src/gateway/hono/routes/tasks.js +1 -1
- package/dist/src/gateway/hono/routes/tui.js +2 -1
- package/dist/src/gateway/hono/routes/usage.d.ts +3 -0
- package/dist/src/gateway/hono/routes/usage.js +61 -0
- package/dist/src/gateway/hono/routes/voice.js +10 -1
- package/dist/src/gateway/image-generation-setup.js +2 -2
- package/dist/src/gateway/lock.js +1 -1
- package/dist/src/gateway/memory-maintenance-automation-reconciler.js +5 -2
- package/dist/src/gateway/resolve-webchat-session-key.d.ts +1 -1
- package/dist/src/gateway/resolve-webchat-session-key.js +2 -2
- package/dist/src/gateway/scenes/host.js +27 -14
- package/dist/src/gateway/scenes/slackThreadSource.d.ts +2 -2
- package/dist/src/gateway/security/gateway-scopes.js +1 -0
- package/dist/src/gateway/service/active-execution.d.ts +19 -0
- package/dist/src/gateway/service/active-execution.js +16 -0
- package/dist/src/gateway/service/agent-runner.d.ts +4 -0
- package/dist/src/gateway/service/agent-runner.js +19 -1
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service/run-gateway-agent.d.ts +2 -0
- package/dist/src/gateway/service/run-gateway-agent.js +10 -2
- package/dist/src/gateway/service/session-command-service.d.ts +34 -0
- package/dist/src/gateway/service/session-command-service.js +81 -0
- package/dist/src/gateway/service/session-input-coordinator.d.ts +21 -0
- package/dist/src/gateway/service/session-input-coordinator.js +41 -0
- package/dist/src/gateway/service/session-preparation-worker.d.ts +15 -0
- package/dist/src/gateway/service/session-preparation-worker.js +125 -0
- package/dist/src/gateway/service/sessions-api.d.ts +13 -0
- package/dist/src/gateway/service/sessions-api.js +23 -0
- package/dist/src/gateway/service.d.ts +30 -3
- package/dist/src/gateway/service.js +89 -79
- package/dist/src/gateway/side-chat/promotion-service.js +0 -1
- package/dist/src/gateway/side-chat/run-service.js +10 -7
- package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
- package/dist/src/home-intelligence/generator.js +5 -2
- package/dist/src/infra/domain-outbox-dispatcher.d.ts +0 -3
- package/dist/src/infra/domain-outbox-dispatcher.js +15 -7
- package/dist/src/local-apps/service.js +2 -2
- package/dist/src/mcp/channel-bridge.js +12 -2
- package/dist/src/notes/capabilities/read.js +2 -2
- package/dist/src/notes/service.d.ts +4 -1
- package/dist/src/notes/service.js +13 -11
- package/dist/src/projects/project-service.js +1 -2
- package/dist/src/projects/project-skill-service.js +2 -2
- package/dist/src/providers/auth-runtime/resolve-auth.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-call.d.ts +3 -2
- package/dist/src/providers/model-call.js +30 -5
- package/dist/src/providers/model-catalog-persistence.js +1 -1
- package/dist/src/providers/register-runtime-providers.js +1 -1
- package/dist/src/scenes/activationAdapter.d.ts +19 -0
- package/dist/src/scenes/activationAdapter.js +1 -0
- package/dist/src/scenes/agentExecutor.js +3 -10
- package/dist/src/scenes/contracts.d.ts +3 -9
- package/dist/src/scenes/contracts.js +1 -0
- package/dist/src/scenes/execution.d.ts +9 -3
- package/dist/src/scenes/execution.js +12 -11
- package/dist/src/scenes/httpServices.d.ts +5 -2
- package/dist/src/scenes/mailContext.d.ts +4 -0
- package/dist/src/scenes/mailContext.js +9 -0
- package/dist/src/scenes/maintenance.js +1 -5
- package/dist/src/scenes/metrics.d.ts +0 -6
- package/dist/src/scenes/metrics.js +0 -11
- package/dist/src/scenes/registry.d.ts +11 -0
- package/dist/src/scenes/registry.js +28 -0
- package/dist/src/scenes/repository.d.ts +6 -3
- package/dist/src/scenes/repository.js +43 -5
- package/dist/src/scenes/service.d.ts +2 -1
- package/dist/src/scenes/service.js +9 -7
- package/dist/src/scenes/taskFollowUp/contracts.d.ts +37 -7
- package/dist/src/scenes/taskFollowUp/contracts.js +36 -17
- package/dist/src/scenes/taskFollowUp/service.d.ts +35 -7
- package/dist/src/scenes/taskFollowUp/service.js +86 -28
- package/dist/src/scenes/templates.d.ts +2 -2
- package/dist/src/scenes/userNotes.d.ts +3 -0
- package/dist/src/scenes/userNotes.js +6 -0
- package/dist/src/session/client-history.d.ts +3 -0
- package/dist/src/session/client-history.js +10 -5
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/resolve-session.js +4 -3
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.d.ts +1 -0
- package/dist/src/session/store.js +3 -3
- package/dist/src/storage/sqlite/ai-usage-repository.d.ts +137 -0
- package/dist/src/storage/sqlite/ai-usage-repository.js +175 -0
- package/dist/src/storage/sqlite/connector-account-repository.js +7 -5
- package/dist/src/storage/sqlite/connector-repository.js +36 -34
- package/dist/src/storage/sqlite/index.d.ts +2 -2
- package/dist/src/storage/sqlite/index.js +3 -3
- package/dist/src/storage/sqlite/migrations/209_automation_event_hub.sql +48 -0
- package/dist/src/storage/sqlite/migrations/210_remove_legacy_automation_timeout.sql +14 -0
- package/dist/src/storage/sqlite/migrations/211_automation_result_deliveries.sql +16 -0
- package/dist/src/storage/sqlite/migrations/212_automation_delivery_policy.sql +30 -0
- package/dist/src/storage/sqlite/migrations/213_automation_reliability_contract.sql +188 -0
- package/dist/src/storage/sqlite/migrations/214_ai_usage_ledger.sql +41 -0
- package/dist/src/storage/sqlite/migrations/215_scene_execution_adapters.sql +6 -0
- package/dist/src/storage/sqlite/migrations/216_remove_scene_model_usage.sql +1 -0
- package/dist/src/storage/sqlite/migrations/217_remove_legacy_memory_tables.sql +4 -0
- package/dist/src/storage/sqlite/migrations/218_core_relation_indexes.sql +26 -0
- package/dist/src/storage/sqlite/migrations/219_json_contracts.sql +123 -0
- package/dist/src/storage/sqlite/migrations/220_normalize_timestamps.sql +339 -0
- package/dist/src/storage/sqlite/migrations/221_ai_usage_retention_index.sql +2 -0
- package/dist/src/storage/sqlite/migrations/222_session_config_authority.sql +13 -0
- package/dist/src/storage/sqlite/migrations/223_session_creation_receipts.sql +59 -0
- package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
- package/dist/src/storage/sqlite/migrations/runner.js +4 -4
- package/dist/src/storage/sqlite/row-mappers.d.ts +3 -7
- package/dist/src/storage/sqlite/row-mappers.js +6 -6
- package/dist/src/storage/sqlite/scenes-schema.d.ts +1 -1
- package/dist/src/storage/sqlite/scenes-schema.js +0 -1
- package/dist/src/storage/sqlite/schema.js +1 -1
- package/dist/src/storage/sqlite/schema.sql +0 -52
- package/dist/src/storage/sqlite/schemas/scenes.sql +0 -7
- package/dist/src/storage/sqlite/session-creation-repository.d.ts +50 -0
- package/dist/src/storage/sqlite/session-creation-repository.js +166 -0
- package/dist/src/storage/sqlite/session-input-repository.d.ts +12 -2
- package/dist/src/storage/sqlite/session-input-repository.js +25 -2
- package/dist/src/storage/sqlite/session-read-repository.d.ts +1 -1
- package/dist/src/storage/sqlite/session-read-repository.js +0 -1
- package/dist/src/storage/sqlite/session-repository.d.ts +0 -4
- package/dist/src/storage/sqlite/session-repository.js +8 -18
- package/dist/src/storage/sqlite/timestamps.d.ts +4 -0
- package/dist/src/storage/sqlite/timestamps.js +20 -0
- package/dist/src/storage/sqlite/transcript-repository.d.ts +1 -0
- package/dist/src/storage/sqlite/transcript-repository.js +23 -15
- package/dist/src/storage/sqlite/user-trust-repository.js +4 -2
- package/dist/src/tasks/capabilities/read.js +2 -2
- package/dist/src/tasks/capabilities/write.d.ts +1 -1
- package/dist/src/tasks/home-query-service.js +3 -3
- package/dist/src/tasks/task-contract-planner.js +1 -1
- package/dist/src/tui/backends/embedded-backend.d.ts +5 -0
- package/dist/src/tui/backends/embedded-backend.js +266 -20
- package/dist/src/tui/backends/embedded-drafts.d.ts +22 -0
- package/dist/src/tui/backends/embedded-drafts.js +53 -0
- package/dist/src/tui/backends/gateway-realtime-backend.d.ts +10 -0
- package/dist/src/tui/backends/gateway-realtime-backend.js +214 -33
- package/dist/src/tui/tui-backend.d.ts +1 -1
- package/dist/src/tui/tui-chat-input-state.d.ts +1 -0
- package/dist/src/tui/tui-commands.js +1 -1
- package/dist/src/tui/tui-session-format.js +0 -1
- package/dist/src/tui/tui-startup-resources.d.ts +1 -0
- package/dist/src/tui/tui-startup-resources.js +2 -2
- package/dist/src/tui/tui-types.d.ts +0 -1
- package/dist/src/tui/tui.js +69 -29
- package/dist/src/usage/cost.d.ts +4 -0
- package/dist/src/usage/cost.js +28 -0
- package/dist/src/usage/recorder.d.ts +13 -0
- package/dist/src/usage/recorder.js +117 -0
- package/dist/src/usage/scenario-registry.d.ts +8 -0
- package/dist/src/usage/scenario-registry.js +117 -0
- package/dist/src/usage/types.d.ts +55 -0
- package/dist/src/usage/types.js +1 -0
- package/dist/src/voice/realtime/persona-context.js +1 -1
- package/dist/src/voice/tts/summarize.js +1 -1
- package/dist/src/work-discovery/analyzer.js +2 -2
- package/dist/src/work-discovery/investigator.js +1 -1
- package/dist/src/work-discovery/service.js +3 -6
- package/dist/src/workflows/service/workflow-run-service.js +16 -3
- package/package.json +3 -3
- package/dist/gateway/static/root/assets/agent-defaults-settings-panel-Se1Z72VG.js +0 -1
- package/dist/gateway/static/root/assets/agents-udIitwV8.js +0 -70
- package/dist/gateway/static/root/assets/apps-page-DVNySL58.js +0 -1
- package/dist/gateway/static/root/assets/attachment-load-DNCDbeOX.js +0 -1
- package/dist/gateway/static/root/assets/automations-workspace-BMgJvdcv.js +0 -7
- package/dist/gateway/static/root/assets/binary-plugins-BYn2hScX.js +0 -2
- package/dist/gateway/static/root/assets/capabilities-CHA-sTAZ.js +0 -1
- package/dist/gateway/static/root/assets/capabilities-page-v0WkhV5o.js +0 -2
- package/dist/gateway/static/root/assets/capabilities-settings-panel-DefBGjhV.js +0 -8
- package/dist/gateway/static/root/assets/capability-header-actions-vmx35sbu.js +0 -1
- package/dist/gateway/static/root/assets/channels-Eo4ONF5X.js +0 -1
- package/dist/gateway/static/root/assets/connectors-page-DZYgogQw.js +0 -2
- package/dist/gateway/static/root/assets/conversation-identity-Cw0n9uzK.js +0 -1
- package/dist/gateway/static/root/assets/date-picker-CrOV4Ynd.js +0 -1
- package/dist/gateway/static/root/assets/dist-3h6cXXhT.js +0 -1
- package/dist/gateway/static/root/assets/dist-Che_jiQF.js +0 -1
- package/dist/gateway/static/root/assets/gateway-settings-Du-Dos9O.js +0 -1
- package/dist/gateway/static/root/assets/home-page-D7YoMHq4.js +0 -1
- package/dist/gateway/static/root/assets/index-BEw0xrde.css +0 -1
- package/dist/gateway/static/root/assets/index-DalslRUx.js +0 -121
- package/dist/gateway/static/root/assets/local-app-workbench-page-BKL5UZAj.js +0 -1
- package/dist/gateway/static/root/assets/logs-page-CjzR9Rpj.js +0 -2
- package/dist/gateway/static/root/assets/management-settings-Dk_gTJb9.js +0 -1
- package/dist/gateway/static/root/assets/media-plugins-Dlj6TD3M.js +0 -1
- package/dist/gateway/static/root/assets/messages-fmf0dnr4.js +0 -3
- package/dist/gateway/static/root/assets/note-detail-panel-BebJPjjk.js +0 -5
- package/dist/gateway/static/root/assets/notes-page-CmS_hvz8.js +0 -8
- package/dist/gateway/static/root/assets/page-context-capture-button-BArPtqp5.js +0 -1
- package/dist/gateway/static/root/assets/popover-select-DcsFzD_i.js +0 -1
- package/dist/gateway/static/root/assets/project-detail-page-BFUdtWXF.js +0 -1
- package/dist/gateway/static/root/assets/projects-page-DBsBwAQ6.js +0 -1
- package/dist/gateway/static/root/assets/remote-access-hub-BurdDY0m.js +0 -1
- package/dist/gateway/static/root/assets/scenes-page-Cj8xtr5t.js +0 -2
- package/dist/gateway/static/root/assets/sessions-page-BCsjgkCs.js +0 -1
- package/dist/gateway/static/root/assets/settings-advanced-gate-BLL7csOJ.js +0 -1
- package/dist/gateway/static/root/assets/setup-status-panel-CbKHBjrU.js +0 -1
- package/dist/gateway/static/root/assets/share-preview-page-DyLfktib.js +0 -2
- package/dist/gateway/static/root/assets/shares-settings-BzvSNouj.js +0 -1
- package/dist/gateway/static/root/assets/skill-reload-api-BHnru0F5.js +0 -1
- package/dist/gateway/static/root/assets/skills-page-C35VKjhb.js +0 -2
- package/dist/gateway/static/root/assets/task-detail-page-Bd1_Fguk.js +0 -1
- package/dist/gateway/static/root/assets/user-model-page-DuYzuR1T.js +0 -2
- package/dist/gateway/static/root/assets/workflows-page-B45YDiEw.js +0 -6
- package/dist/src/automations/product-events.d.ts +0 -5
- package/dist/src/automations/product-events.js +0 -19
- package/dist/src/tui/tui-empty-session-cleanup.d.ts +0 -9
- package/dist/src/tui/tui-empty-session-cleanup.js +0 -19
- /package/dist/gateway/static/root/assets/{dist-CI_fqRk-.js → dist-CI_fqRk-2.js} +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createLogger } from "../../utils/logger/index.js";
|
|
2
|
+
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
4
|
+
import { getAutomation } from "../storage/automation-repository.js";
|
|
5
|
+
import "../storage/index.js";
|
|
6
|
+
import { claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, releaseAutomationEventDelivery, releaseAutomationEventProjection, skipAutomationEventDelivery } from "./event-repository.js";
|
|
7
|
+
import { randomUUID } from "node:crypto";
|
|
8
|
+
//#region src/automations/events/event-dispatcher.ts
|
|
9
|
+
init_transaction();
|
|
10
|
+
init_logger();
|
|
11
|
+
const log = createLogger("AutomationEventDispatcher");
|
|
12
|
+
const DELIVERY_SCAN_BUDGET = 500;
|
|
13
|
+
var AutomationEventDispatcher = class {
|
|
14
|
+
timer;
|
|
15
|
+
active;
|
|
16
|
+
stopping = false;
|
|
17
|
+
owner = `automation-event:${process.pid}:${randomUUID()}`;
|
|
18
|
+
abortController = new AbortController();
|
|
19
|
+
constructor(automationService, options = {}) {
|
|
20
|
+
this.automationService = automationService;
|
|
21
|
+
this.options = options;
|
|
22
|
+
}
|
|
23
|
+
start() {
|
|
24
|
+
if (this.timer) return;
|
|
25
|
+
this.stopping = false;
|
|
26
|
+
reconcileAutomationEventDeliveries();
|
|
27
|
+
this.dispatch();
|
|
28
|
+
this.timer = setInterval(() => void this.dispatch(), this.options.intervalMs ?? 1e3);
|
|
29
|
+
this.timer.unref?.();
|
|
30
|
+
}
|
|
31
|
+
async stop() {
|
|
32
|
+
this.stopping = true;
|
|
33
|
+
if (this.timer) clearInterval(this.timer);
|
|
34
|
+
this.timer = void 0;
|
|
35
|
+
this.abortController.abort(/* @__PURE__ */ new Error("Automation event dispatcher stopped"));
|
|
36
|
+
await this.active?.catch(() => void 0);
|
|
37
|
+
}
|
|
38
|
+
dispatch() {
|
|
39
|
+
if (this.stopping) return Promise.resolve(0);
|
|
40
|
+
this.active ??= this.runDispatch().finally(() => {
|
|
41
|
+
this.active = void 0;
|
|
42
|
+
});
|
|
43
|
+
return this.active;
|
|
44
|
+
}
|
|
45
|
+
runCompleted(run) {
|
|
46
|
+
completeAutomationEventDelivery(run.id, run.status);
|
|
47
|
+
if (!this.stopping) this.dispatch();
|
|
48
|
+
}
|
|
49
|
+
async runDispatch() {
|
|
50
|
+
await this.projectEvents();
|
|
51
|
+
const availableSlots = this.automationService.availableRunSlots();
|
|
52
|
+
if (availableSlots <= 0 || this.stopping) return 0;
|
|
53
|
+
let queued = 0;
|
|
54
|
+
const deliveries = claimAutomationEventDeliveries(this.owner, DELIVERY_SCAN_BUDGET);
|
|
55
|
+
for (const [index, delivery] of deliveries.entries()) {
|
|
56
|
+
if (queued >= availableSlots || this.stopping) {
|
|
57
|
+
for (const remaining of deliveries.slice(index)) releaseAutomationEventDelivery(remaining.event.id, remaining.automationId, this.owner, 0);
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
const automation = getAutomation(delivery.automationId);
|
|
61
|
+
if (!automation || !automation.enabled) {
|
|
62
|
+
skipAutomationEventDelivery(delivery.event.id, delivery.automationId, "Automation is unavailable", this.owner);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (automation.state.runningRunId) {
|
|
66
|
+
releaseAutomationEventDelivery(delivery.event.id, automation.id, this.owner);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const run = runSqliteWriteTransaction(() => {
|
|
71
|
+
const next = this.automationService.queueRunAtomically(automation.id, {
|
|
72
|
+
manual: false,
|
|
73
|
+
event: delivery.event
|
|
74
|
+
});
|
|
75
|
+
markAutomationEventDeliveryQueued(delivery.event.id, automation.id, next.id, this.owner);
|
|
76
|
+
return next;
|
|
77
|
+
});
|
|
78
|
+
this.automationService.dispatchQueuedRun(run.id);
|
|
79
|
+
queued += 1;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error instanceof Error && error.name === "AutomationAlreadyRunningError") {
|
|
82
|
+
releaseAutomationEventDelivery(delivery.event.id, automation.id, this.owner);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const status = deferAutomationEventDelivery(delivery.event.id, automation.id, this.owner, error);
|
|
86
|
+
if (status === "dead_letter") this.options.onDeadLetter?.({
|
|
87
|
+
phase: "event_delivery",
|
|
88
|
+
eventId: delivery.event.id,
|
|
89
|
+
automationId: automation.id,
|
|
90
|
+
error: error instanceof Error ? error.message : String(error)
|
|
91
|
+
});
|
|
92
|
+
log.warn({
|
|
93
|
+
err: error,
|
|
94
|
+
eventId: delivery.event.id,
|
|
95
|
+
automationId: automation.id,
|
|
96
|
+
status
|
|
97
|
+
}, status === "dead_letter" ? "Automation event delivery moved to dead letter" : "Automation event delivery will retry");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return queued;
|
|
101
|
+
}
|
|
102
|
+
async projectEvents() {
|
|
103
|
+
for (const expired of expireAutomationEventProjectionLeases()) {
|
|
104
|
+
this.options.onDeadLetter?.({
|
|
105
|
+
phase: "event_projection",
|
|
106
|
+
...expired
|
|
107
|
+
});
|
|
108
|
+
log.warn(expired, "Automation event projection moved to dead letter after lease expiry");
|
|
109
|
+
}
|
|
110
|
+
for (const event of claimAutomationEventsForProjection(this.owner)) {
|
|
111
|
+
if (this.stopping) {
|
|
112
|
+
releaseAutomationEventProjection(event.id, this.owner);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
await this.options.onEvent?.(event, this.abortController.signal);
|
|
117
|
+
completeAutomationEventProjection(event.id, this.owner);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (this.stopping || this.abortController.signal.aborted) {
|
|
120
|
+
releaseAutomationEventProjection(event.id, this.owner);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const status = failAutomationEventProjection(event.id, this.owner, error);
|
|
124
|
+
if (status === "dead_letter") this.options.onDeadLetter?.({
|
|
125
|
+
phase: "event_projection",
|
|
126
|
+
eventId: event.id,
|
|
127
|
+
error: error instanceof Error ? error.message : String(error)
|
|
128
|
+
});
|
|
129
|
+
log.warn({
|
|
130
|
+
err: error,
|
|
131
|
+
eventId: event.id,
|
|
132
|
+
eventType: event.type,
|
|
133
|
+
status
|
|
134
|
+
}, status === "dead_letter" ? "Automation event projection moved to dead letter" : "Automation event projection will retry");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
export { AutomationEventDispatcher };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { AutomationEvent, AutomationEventDeliveryStatus, AutomationEventEnvelope, AutomationEventProjectionStatus, AutomationEventRecord, AutomationRunStatus } from '../domain/types.js';
|
|
2
|
+
export interface ClaimedAutomationEventDelivery {
|
|
3
|
+
event: AutomationEventEnvelope;
|
|
4
|
+
automationId: string;
|
|
5
|
+
attempts: number;
|
|
6
|
+
owner: string;
|
|
7
|
+
}
|
|
8
|
+
export interface AutomationEventIngestResult {
|
|
9
|
+
event: AutomationEventEnvelope;
|
|
10
|
+
created: boolean;
|
|
11
|
+
deliveryCount: number;
|
|
12
|
+
}
|
|
13
|
+
export interface AutomationEventIngestOptions {
|
|
14
|
+
targetAutomationIds?: string[];
|
|
15
|
+
}
|
|
16
|
+
export interface AutomationEventPublisher {
|
|
17
|
+
publish(input: AutomationEvent, options?: AutomationEventIngestOptions): AutomationEventIngestResult;
|
|
18
|
+
}
|
|
19
|
+
export declare function ingestAutomationEvent(input: AutomationEvent, options?: AutomationEventIngestOptions): AutomationEventIngestResult;
|
|
20
|
+
export declare const automationEventPublisher: AutomationEventPublisher;
|
|
21
|
+
export declare function listAutomationEvents(input?: {
|
|
22
|
+
type?: string;
|
|
23
|
+
source?: string;
|
|
24
|
+
subjectKind?: string;
|
|
25
|
+
subjectId?: string;
|
|
26
|
+
limit?: number;
|
|
27
|
+
newestFirst?: boolean;
|
|
28
|
+
}): AutomationEventEnvelope[];
|
|
29
|
+
export declare function listAutomationEventRecords(input?: {
|
|
30
|
+
type?: string;
|
|
31
|
+
source?: string;
|
|
32
|
+
limit?: number;
|
|
33
|
+
}): AutomationEventRecord[];
|
|
34
|
+
export declare function claimAutomationEventsForProjection(owner: string, limit?: number, leaseMs?: number): AutomationEventEnvelope[];
|
|
35
|
+
export declare function expireAutomationEventProjectionLeases(): Array<{
|
|
36
|
+
eventId: string;
|
|
37
|
+
error: string;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function completeAutomationEventProjection(eventId: string, owner: string): void;
|
|
40
|
+
export declare function releaseAutomationEventProjection(eventId: string, owner: string): void;
|
|
41
|
+
export declare function failAutomationEventProjection(eventId: string, owner: string, error: unknown): AutomationEventProjectionStatus;
|
|
42
|
+
export declare function claimAutomationEventDeliveries(owner: string, limit: number, leaseMs?: number): ClaimedAutomationEventDelivery[];
|
|
43
|
+
export declare function releaseAutomationEventDelivery(eventId: string, automationId: string, owner: string, delayMs?: number): void;
|
|
44
|
+
export declare function getAutomationEventDeliveryRunId(eventId: string, automationId: string): string | null;
|
|
45
|
+
export declare function getAutomationEventForRun(runId: string): AutomationEventEnvelope | null;
|
|
46
|
+
export declare function markAutomationEventDeliveryQueued(eventId: string, automationId: string, runId: string, owner?: string): void;
|
|
47
|
+
export declare function deferAutomationEventDelivery(eventId: string, automationId: string, owner: string, error: unknown): AutomationEventDeliveryStatus;
|
|
48
|
+
export declare function skipAutomationEventDelivery(eventId: string, automationId: string, reason: string, owner?: string): void;
|
|
49
|
+
export declare function completeAutomationEventDelivery(runId: string, runStatus: AutomationRunStatus): void;
|
|
50
|
+
export declare function reconcileAutomationEventDeliveries(): number;
|
|
51
|
+
export declare function replayAutomationEvent(eventId: string): boolean;
|
|
52
|
+
export declare function getAutomationEventQueueMetrics(): {
|
|
53
|
+
pending: number;
|
|
54
|
+
oldestPendingAgeMs: number;
|
|
55
|
+
projectionDeadLetters: number;
|
|
56
|
+
pendingDeliveries: number;
|
|
57
|
+
deliveryDeadLetters: number;
|
|
58
|
+
activeLeases: number;
|
|
59
|
+
};
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { getSqliteDatabase, init_transaction, runSqliteWriteTransaction } from "../../storage/sqlite/transaction.js";
|
|
2
|
+
import { getAutomation, listAutomations } from "../storage/automation-repository.js";
|
|
3
|
+
import "../storage/index.js";
|
|
4
|
+
import { validateCatalogedBusinessEvent } from "./event-catalog.js";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
//#region src/automations/events/event-repository.ts
|
|
7
|
+
init_transaction();
|
|
8
|
+
const MAX_PAYLOAD_BYTES = 256 * 1024;
|
|
9
|
+
const MAX_ATTEMPTS = 5;
|
|
10
|
+
const RETRY_DELAYS_MS = [
|
|
11
|
+
1e3,
|
|
12
|
+
5e3,
|
|
13
|
+
3e4,
|
|
14
|
+
2 * 6e4,
|
|
15
|
+
10 * 6e4
|
|
16
|
+
];
|
|
17
|
+
function stableStringify(value) {
|
|
18
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
19
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
20
|
+
const record = value;
|
|
21
|
+
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(record[key])}`).join(",")}}`;
|
|
22
|
+
}
|
|
23
|
+
function sameEventIdentity(existing, candidate, input) {
|
|
24
|
+
return existing.id === candidate.id && existing.type === candidate.type && existing.source === candidate.source && existing.schemaVersion === candidate.schemaVersion && existing.subject?.kind === candidate.subject?.kind && existing.subject?.id === candidate.subject?.id && (input.occurredAtMs === void 0 || existing.occurredAtMs === candidate.occurredAtMs) && (input.correlationId === void 0 || existing.correlationId === candidate.correlationId) && (input.causationId === void 0 || existing.causationId === candidate.causationId) && (input.rootEventId === void 0 || existing.rootEventId === candidate.rootEventId) && (input.chainDepth === void 0 || existing.chainDepth === candidate.chainDepth) && existing.dedupeKey === candidate.dedupeKey && existing.trust === candidate.trust && stableStringify(existing.payload) === stableStringify(candidate.payload);
|
|
25
|
+
}
|
|
26
|
+
function matchesEvent(trigger, event) {
|
|
27
|
+
if (trigger.eventType !== event.type) return false;
|
|
28
|
+
if (trigger.source && trigger.source !== event.source) return false;
|
|
29
|
+
if (!trigger.payloadMatch) return true;
|
|
30
|
+
return Object.entries(trigger.payloadMatch).every(([key, expected]) => Object.is(event.payload[key], expected));
|
|
31
|
+
}
|
|
32
|
+
function rowToEvent(row) {
|
|
33
|
+
return {
|
|
34
|
+
id: row.event_id,
|
|
35
|
+
type: row.event_type,
|
|
36
|
+
schemaVersion: row.schema_version,
|
|
37
|
+
source: row.source,
|
|
38
|
+
...row.subject_kind && row.subject_id ? { subject: {
|
|
39
|
+
kind: row.subject_kind,
|
|
40
|
+
id: row.subject_id
|
|
41
|
+
} } : {},
|
|
42
|
+
occurredAtMs: row.occurred_at_ms,
|
|
43
|
+
ingestedAtMs: row.ingested_at_ms,
|
|
44
|
+
correlationId: row.correlation_id,
|
|
45
|
+
...row.causation_id ? { causationId: row.causation_id } : {},
|
|
46
|
+
rootEventId: row.root_event_id,
|
|
47
|
+
chainDepth: row.chain_depth,
|
|
48
|
+
...row.dedupe_key ? { dedupeKey: row.dedupe_key } : {},
|
|
49
|
+
trust: row.trust,
|
|
50
|
+
payload: JSON.parse(row.payload_json)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function readEventByIdentity(input) {
|
|
54
|
+
const db = getSqliteDatabase();
|
|
55
|
+
const row = input.dedupeKey ? db.prepare("SELECT * FROM automation_events WHERE event_id = ? OR (source = ? AND dedupe_key = ?) LIMIT 1").get(input.id, input.source, input.dedupeKey) : db.prepare("SELECT * FROM automation_events WHERE event_id = ?").get(input.id);
|
|
56
|
+
return row ? rowToEvent(row) : null;
|
|
57
|
+
}
|
|
58
|
+
function ingestAutomationEvent(input, options = {}) {
|
|
59
|
+
if (!input.type.trim()) throw new Error("Automation event type is required");
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
const id = input.id?.trim() || randomUUID();
|
|
62
|
+
const source = input.source?.trim() || "xopc";
|
|
63
|
+
const event = {
|
|
64
|
+
...input,
|
|
65
|
+
id,
|
|
66
|
+
type: input.type.trim(),
|
|
67
|
+
source,
|
|
68
|
+
schemaVersion: input.schemaVersion ?? 1,
|
|
69
|
+
occurredAtMs: input.occurredAtMs ?? now,
|
|
70
|
+
ingestedAtMs: now,
|
|
71
|
+
correlationId: input.correlationId?.trim() || id,
|
|
72
|
+
rootEventId: input.rootEventId?.trim() || id,
|
|
73
|
+
chainDepth: input.chainDepth ?? 0,
|
|
74
|
+
trust: input.trust ?? (source.startsWith("composio") ? "connector" : "system"),
|
|
75
|
+
payload: input.payload ?? {}
|
|
76
|
+
};
|
|
77
|
+
if (!Number.isInteger(event.schemaVersion) || event.schemaVersion < 1) throw new Error("Invalid event schema version");
|
|
78
|
+
if (!Number.isInteger(event.chainDepth) || event.chainDepth < 0 || event.chainDepth > 32) throw new Error("Invalid event chain depth");
|
|
79
|
+
const payloadJson = JSON.stringify(event.payload);
|
|
80
|
+
if (Buffer.byteLength(payloadJson) > MAX_PAYLOAD_BYTES) throw new Error(`Automation event payload exceeds ${MAX_PAYLOAD_BYTES} bytes`);
|
|
81
|
+
validateCatalogedBusinessEvent(event);
|
|
82
|
+
return runSqliteWriteTransaction((db) => {
|
|
83
|
+
if (!(db.prepare(`INSERT OR IGNORE INTO automation_events (
|
|
84
|
+
event_id, event_type, schema_version, source, subject_kind, subject_id,
|
|
85
|
+
occurred_at_ms, ingested_at_ms, correlation_id, causation_id, root_event_id,
|
|
86
|
+
chain_depth, dedupe_key, trust, payload_json, projection_next_attempt_at_ms
|
|
87
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(event.id, event.type, event.schemaVersion, event.source, event.subject?.kind ?? null, event.subject?.id ?? null, event.occurredAtMs, event.ingestedAtMs, event.correlationId, event.causationId ?? null, event.rootEventId, event.chainDepth, event.dedupeKey ?? null, event.trust, payloadJson, now).changes > 0)) {
|
|
88
|
+
const existing = readEventByIdentity({
|
|
89
|
+
id: event.id,
|
|
90
|
+
source: event.source,
|
|
91
|
+
dedupeKey: event.dedupeKey
|
|
92
|
+
});
|
|
93
|
+
if (!existing) throw new Error("Automation event identity conflict");
|
|
94
|
+
if (!sameEventIdentity(existing, event, input)) throw new Error("Automation event identity reused with different content");
|
|
95
|
+
return {
|
|
96
|
+
event: existing,
|
|
97
|
+
created: false,
|
|
98
|
+
deliveryCount: Number(db.prepare("SELECT count(*) AS count FROM automation_event_deliveries WHERE event_id = ?").get(existing.id)?.count ?? 0)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const automations = options.targetAutomationIds ? options.targetAutomationIds.map(getAutomation).filter((automation) => Boolean(automation?.enabled)) : listAutomations().filter((automation) => automation.enabled && automation.trigger.kind === "event" && matchesEvent(automation.trigger, event));
|
|
102
|
+
const insertDelivery = db.prepare(`INSERT INTO automation_event_deliveries (
|
|
103
|
+
event_id, automation_id, status, attempts, next_attempt_at_ms, created_at_ms, updated_at_ms
|
|
104
|
+
) VALUES (?, ?, 'pending', 0, ?, ?, ?)`);
|
|
105
|
+
for (const automation of automations) insertDelivery.run(event.id, automation.id, now, now, now);
|
|
106
|
+
return {
|
|
107
|
+
event,
|
|
108
|
+
created: true,
|
|
109
|
+
deliveryCount: automations.length
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const automationEventPublisher = { publish: ingestAutomationEvent };
|
|
114
|
+
function listAutomationEvents(input = {}) {
|
|
115
|
+
const clauses = [];
|
|
116
|
+
const params = [];
|
|
117
|
+
if (input.type) {
|
|
118
|
+
clauses.push("event_type = ?");
|
|
119
|
+
params.push(input.type);
|
|
120
|
+
}
|
|
121
|
+
if (input.source) {
|
|
122
|
+
clauses.push("source = ?");
|
|
123
|
+
params.push(input.source);
|
|
124
|
+
}
|
|
125
|
+
if (input.subjectKind) {
|
|
126
|
+
clauses.push("subject_kind = ?");
|
|
127
|
+
params.push(input.subjectKind);
|
|
128
|
+
}
|
|
129
|
+
if (input.subjectId) {
|
|
130
|
+
clauses.push("subject_id = ?");
|
|
131
|
+
params.push(input.subjectId);
|
|
132
|
+
}
|
|
133
|
+
params.push(Math.max(1, Math.min(500, Math.floor(input.limit ?? 100))));
|
|
134
|
+
return getSqliteDatabase().prepare(`SELECT * FROM automation_events
|
|
135
|
+
${clauses.length ? `WHERE ${clauses.join(" AND ")}` : ""}
|
|
136
|
+
ORDER BY ingested_at_ms ${input.newestFirst ? "DESC" : "ASC"}, rowid ${input.newestFirst ? "DESC" : "ASC"} LIMIT ?`).all(...params).map(rowToEvent);
|
|
137
|
+
}
|
|
138
|
+
function listAutomationEventRecords(input = {}) {
|
|
139
|
+
const events = listAutomationEvents({
|
|
140
|
+
...input,
|
|
141
|
+
newestFirst: true
|
|
142
|
+
});
|
|
143
|
+
const db = getSqliteDatabase();
|
|
144
|
+
const readEventState = db.prepare(`SELECT projection_status, projection_attempts, projection_error
|
|
145
|
+
FROM automation_events WHERE event_id = ?`);
|
|
146
|
+
const readDeliveries = db.prepare(`SELECT automation_id, status, run_id, attempts, last_error
|
|
147
|
+
FROM automation_event_deliveries WHERE event_id = ? ORDER BY automation_id`);
|
|
148
|
+
return events.map((event) => {
|
|
149
|
+
const state = readEventState.get(event.id);
|
|
150
|
+
const deliveries = readDeliveries.all(event.id);
|
|
151
|
+
return {
|
|
152
|
+
event,
|
|
153
|
+
projectionStatus: state.projection_status,
|
|
154
|
+
projectionAttempts: state.projection_attempts,
|
|
155
|
+
projectionError: state.projection_error ?? void 0,
|
|
156
|
+
deliveries: deliveries.map((delivery) => ({
|
|
157
|
+
automationId: delivery.automation_id,
|
|
158
|
+
status: delivery.status,
|
|
159
|
+
runId: delivery.run_id ?? void 0,
|
|
160
|
+
attempts: delivery.attempts,
|
|
161
|
+
lastError: delivery.last_error ?? void 0
|
|
162
|
+
}))
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function claimAutomationEventsForProjection(owner, limit = 100, leaseMs = 3e4) {
|
|
167
|
+
const now = Date.now();
|
|
168
|
+
return runSqliteWriteTransaction((db) => {
|
|
169
|
+
const candidates = db.prepare(`SELECT * FROM automation_events WHERE
|
|
170
|
+
(projection_status IN ('pending', 'retrying') AND projection_next_attempt_at_ms <= ?)
|
|
171
|
+
OR (projection_status = 'projecting' AND projection_lease_until_ms <= ?)
|
|
172
|
+
ORDER BY ingested_at_ms, event_id LIMIT ?`).all(now, now, Math.max(1, Math.min(500, limit)));
|
|
173
|
+
const claimed = [];
|
|
174
|
+
const statement = db.prepare(`UPDATE automation_events
|
|
175
|
+
SET projection_status = 'projecting', projection_attempts = projection_attempts + 1,
|
|
176
|
+
projection_owner = ?, projection_lease_until_ms = ?
|
|
177
|
+
WHERE event_id = ? AND (
|
|
178
|
+
(projection_status IN ('pending', 'retrying') AND projection_next_attempt_at_ms <= ?)
|
|
179
|
+
OR (projection_status = 'projecting' AND projection_lease_until_ms <= ?)
|
|
180
|
+
)`);
|
|
181
|
+
for (const candidate of candidates) if (statement.run(owner, now + leaseMs, candidate.event_id, now, now).changes === 1) claimed.push(rowToEvent(candidate));
|
|
182
|
+
return claimed;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
function expireAutomationEventProjectionLeases() {
|
|
186
|
+
const now = Date.now();
|
|
187
|
+
return runSqliteWriteTransaction((db) => {
|
|
188
|
+
const candidates = db.prepare(`SELECT event_id FROM automation_events
|
|
189
|
+
WHERE projection_status = 'projecting' AND projection_lease_until_ms <= ? AND projection_attempts >= ?`).all(now, MAX_ATTEMPTS);
|
|
190
|
+
const expire = db.prepare(`UPDATE automation_events
|
|
191
|
+
SET projection_status = 'dead_letter', projection_error = 'Projection lease expired after maximum attempts',
|
|
192
|
+
projection_owner = NULL, projection_lease_until_ms = NULL
|
|
193
|
+
WHERE event_id = ? AND projection_status = 'projecting'
|
|
194
|
+
AND projection_lease_until_ms <= ? AND projection_attempts >= ?`);
|
|
195
|
+
const expired = [];
|
|
196
|
+
for (const candidate of candidates) if (expire.run(candidate.event_id, now, MAX_ATTEMPTS).changes === 1) expired.push({
|
|
197
|
+
eventId: candidate.event_id,
|
|
198
|
+
error: "Projection lease expired after maximum attempts"
|
|
199
|
+
});
|
|
200
|
+
return expired;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function completeAutomationEventProjection(eventId, owner) {
|
|
204
|
+
getSqliteDatabase().prepare(`UPDATE automation_events
|
|
205
|
+
SET projection_status = 'projected', projected_at_ms = ?, projection_error = NULL,
|
|
206
|
+
projection_owner = NULL, projection_lease_until_ms = NULL
|
|
207
|
+
WHERE event_id = ? AND projection_status = 'projecting' AND projection_owner = ?`).run(Date.now(), eventId, owner);
|
|
208
|
+
}
|
|
209
|
+
function releaseAutomationEventProjection(eventId, owner) {
|
|
210
|
+
getSqliteDatabase().prepare(`UPDATE automation_events
|
|
211
|
+
SET projection_status = 'retrying', projection_attempts = MAX(0, projection_attempts - 1),
|
|
212
|
+
projection_next_attempt_at_ms = ?, projection_owner = NULL, projection_lease_until_ms = NULL
|
|
213
|
+
WHERE event_id = ? AND projection_status = 'projecting' AND projection_owner = ?`).run(Date.now(), eventId, owner);
|
|
214
|
+
}
|
|
215
|
+
function failAutomationEventProjection(eventId, owner, error) {
|
|
216
|
+
const db = getSqliteDatabase();
|
|
217
|
+
const row = db.prepare("SELECT projection_attempts FROM automation_events WHERE event_id = ? AND projection_owner = ?").get(eventId, owner);
|
|
218
|
+
if (!row) return "retrying";
|
|
219
|
+
const status = row.projection_attempts >= MAX_ATTEMPTS ? "dead_letter" : "retrying";
|
|
220
|
+
const delay = RETRY_DELAYS_MS[Math.min(row.projection_attempts - 1, RETRY_DELAYS_MS.length - 1)];
|
|
221
|
+
db.prepare(`UPDATE automation_events SET projection_status = ?, projection_next_attempt_at_ms = ?,
|
|
222
|
+
projection_error = ?, projection_owner = NULL, projection_lease_until_ms = NULL
|
|
223
|
+
WHERE event_id = ? AND projection_status = 'projecting' AND projection_owner = ?`).run(status, Date.now() + delay, error instanceof Error ? error.message : String(error), eventId, owner);
|
|
224
|
+
return status;
|
|
225
|
+
}
|
|
226
|
+
function claimAutomationEventDeliveries(owner, limit, leaseMs = 3e4) {
|
|
227
|
+
if (limit <= 0) return [];
|
|
228
|
+
const now = Date.now();
|
|
229
|
+
return runSqliteWriteTransaction((db) => {
|
|
230
|
+
const rows = db.prepare(`SELECT e.*, d.automation_id, d.attempts
|
|
231
|
+
FROM automation_event_deliveries d
|
|
232
|
+
JOIN automation_events e ON e.event_id = d.event_id
|
|
233
|
+
LEFT JOIN automations a ON a.automation_id = d.automation_id
|
|
234
|
+
WHERE d.status IN ('pending', 'retrying') AND d.next_attempt_at_ms <= ?
|
|
235
|
+
AND (d.lease_until_ms IS NULL OR d.lease_until_ms <= ?)
|
|
236
|
+
ORDER BY CASE
|
|
237
|
+
WHEN a.enabled = 1 AND json_extract(a.state_json, '$.runningRunId') IS NULL THEN 0
|
|
238
|
+
WHEN a.automation_id IS NULL OR a.enabled = 0 THEN 1
|
|
239
|
+
ELSE 2
|
|
240
|
+
END, d.created_at_ms, d.event_id, d.automation_id LIMIT ?`).all(now, now, Math.min(500, Math.floor(limit)));
|
|
241
|
+
const claimed = [];
|
|
242
|
+
const statement = db.prepare(`UPDATE automation_event_deliveries SET lease_owner = ?, lease_until_ms = ?, updated_at_ms = ?
|
|
243
|
+
WHERE event_id = ? AND automation_id = ? AND status IN ('pending', 'retrying')
|
|
244
|
+
AND (lease_until_ms IS NULL OR lease_until_ms <= ?)`);
|
|
245
|
+
for (const row of rows) if (statement.run(owner, now + leaseMs, now, row.event_id, row.automation_id, now).changes === 1) claimed.push({
|
|
246
|
+
event: rowToEvent(row),
|
|
247
|
+
automationId: row.automation_id,
|
|
248
|
+
attempts: row.attempts,
|
|
249
|
+
owner
|
|
250
|
+
});
|
|
251
|
+
return claimed;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
function releaseAutomationEventDelivery(eventId, automationId, owner, delayMs = 1e3) {
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
getSqliteDatabase().prepare(`UPDATE automation_event_deliveries SET next_attempt_at_ms = ?,
|
|
257
|
+
lease_owner = NULL, lease_until_ms = NULL, updated_at_ms = ?
|
|
258
|
+
WHERE event_id = ? AND automation_id = ? AND lease_owner = ? AND status IN ('pending', 'retrying')`).run(now + delayMs, now, eventId, automationId, owner);
|
|
259
|
+
}
|
|
260
|
+
function getAutomationEventDeliveryRunId(eventId, automationId) {
|
|
261
|
+
return getSqliteDatabase().prepare(`SELECT run_id FROM automation_event_deliveries
|
|
262
|
+
WHERE event_id = ? AND automation_id = ?`).get(eventId, automationId)?.run_id ?? null;
|
|
263
|
+
}
|
|
264
|
+
function getAutomationEventForRun(runId) {
|
|
265
|
+
const row = getSqliteDatabase().prepare(`SELECT e.* FROM automation_event_deliveries d
|
|
266
|
+
JOIN automation_events e ON e.event_id = d.event_id WHERE d.run_id = ? LIMIT 1`).get(runId);
|
|
267
|
+
return row ? rowToEvent(row) : null;
|
|
268
|
+
}
|
|
269
|
+
function markAutomationEventDeliveryQueued(eventId, automationId, runId, owner) {
|
|
270
|
+
const ownerClause = owner ? "AND lease_owner = ?" : "";
|
|
271
|
+
const params = owner ? [
|
|
272
|
+
runId,
|
|
273
|
+
Date.now(),
|
|
274
|
+
eventId,
|
|
275
|
+
automationId,
|
|
276
|
+
owner
|
|
277
|
+
] : [
|
|
278
|
+
runId,
|
|
279
|
+
Date.now(),
|
|
280
|
+
eventId,
|
|
281
|
+
automationId
|
|
282
|
+
];
|
|
283
|
+
if (getSqliteDatabase().prepare(`UPDATE automation_event_deliveries
|
|
284
|
+
SET status = 'queued', run_id = ?, attempts = attempts + 1, updated_at_ms = ?, last_error = NULL,
|
|
285
|
+
lease_owner = NULL, lease_until_ms = NULL
|
|
286
|
+
WHERE event_id = ? AND automation_id = ? AND status IN ('pending', 'retrying') ${ownerClause}`).run(...params).changes !== 1) throw new Error("Automation event delivery was already claimed");
|
|
287
|
+
}
|
|
288
|
+
function deferAutomationEventDelivery(eventId, automationId, owner, error) {
|
|
289
|
+
const db = getSqliteDatabase();
|
|
290
|
+
const row = db.prepare(`SELECT attempts FROM automation_event_deliveries
|
|
291
|
+
WHERE event_id = ? AND automation_id = ? AND lease_owner = ?`).get(eventId, automationId, owner);
|
|
292
|
+
if (!row) return "retrying";
|
|
293
|
+
const attempts = row.attempts + 1;
|
|
294
|
+
const status = attempts >= MAX_ATTEMPTS ? "dead_letter" : "retrying";
|
|
295
|
+
const delay = RETRY_DELAYS_MS[Math.min(attempts - 1, RETRY_DELAYS_MS.length - 1)];
|
|
296
|
+
db.prepare(`UPDATE automation_event_deliveries SET status = ?, attempts = ?, next_attempt_at_ms = ?,
|
|
297
|
+
last_error = ?, lease_owner = NULL, lease_until_ms = NULL, updated_at_ms = ?
|
|
298
|
+
WHERE event_id = ? AND automation_id = ? AND lease_owner = ?`).run(status, attempts, Date.now() + delay, error instanceof Error ? error.message : String(error), Date.now(), eventId, automationId, owner);
|
|
299
|
+
return status;
|
|
300
|
+
}
|
|
301
|
+
function skipAutomationEventDelivery(eventId, automationId, reason, owner) {
|
|
302
|
+
const ownerClause = owner ? "AND lease_owner = ?" : "";
|
|
303
|
+
getSqliteDatabase().prepare(`UPDATE automation_event_deliveries SET status = 'skipped',
|
|
304
|
+
last_error = ?, lease_owner = NULL, lease_until_ms = NULL, updated_at_ms = ?
|
|
305
|
+
WHERE event_id = ? AND automation_id = ? AND status IN ('pending', 'retrying') ${ownerClause}`).run(reason, Date.now(), eventId, automationId, ...owner ? [owner] : []);
|
|
306
|
+
}
|
|
307
|
+
function completeAutomationEventDelivery(runId, runStatus) {
|
|
308
|
+
const status = runStatus === "succeeded" ? "completed" : runStatus === "cancelled" ? "cancelled" : "failed";
|
|
309
|
+
getSqliteDatabase().prepare(`UPDATE automation_event_deliveries SET status = ?, updated_at_ms = ?
|
|
310
|
+
WHERE run_id = ? AND status = 'queued'`).run(status, Date.now(), runId);
|
|
311
|
+
}
|
|
312
|
+
function reconcileAutomationEventDeliveries() {
|
|
313
|
+
const result = getSqliteDatabase().prepare(`UPDATE automation_event_deliveries
|
|
314
|
+
SET status = CASE
|
|
315
|
+
WHEN (SELECT status FROM automation_runs WHERE run_id = automation_event_deliveries.run_id) = 'succeeded' THEN 'completed'
|
|
316
|
+
WHEN (SELECT status FROM automation_runs WHERE run_id = automation_event_deliveries.run_id) = 'cancelled' THEN 'cancelled'
|
|
317
|
+
ELSE 'failed'
|
|
318
|
+
END, updated_at_ms = ?
|
|
319
|
+
WHERE status = 'queued' AND run_id IN (
|
|
320
|
+
SELECT run_id FROM automation_runs WHERE status IN ('succeeded', 'failed', 'cancelled', 'timeout')
|
|
321
|
+
)`).run(Date.now());
|
|
322
|
+
return Number(result.changes);
|
|
323
|
+
}
|
|
324
|
+
function replayAutomationEvent(eventId) {
|
|
325
|
+
return runSqliteWriteTransaction((db) => {
|
|
326
|
+
const now = Date.now();
|
|
327
|
+
const projection = db.prepare(`UPDATE automation_events SET projection_status = 'retrying',
|
|
328
|
+
projection_attempts = 0, projection_next_attempt_at_ms = ?, projection_error = NULL,
|
|
329
|
+
projection_owner = NULL, projection_lease_until_ms = NULL
|
|
330
|
+
WHERE event_id = ? AND projection_status = 'dead_letter'`).run(now, eventId).changes;
|
|
331
|
+
const deliveries = db.prepare(`UPDATE automation_event_deliveries SET status = 'retrying', attempts = 0,
|
|
332
|
+
next_attempt_at_ms = ?, last_error = NULL, lease_owner = NULL, lease_until_ms = NULL, updated_at_ms = ?
|
|
333
|
+
WHERE event_id = ? AND status = 'dead_letter'`).run(now, now, eventId).changes;
|
|
334
|
+
return Number(projection) + Number(deliveries) > 0;
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
function getAutomationEventQueueMetrics() {
|
|
338
|
+
const now = Date.now();
|
|
339
|
+
const event = getSqliteDatabase().prepare(`SELECT
|
|
340
|
+
SUM(CASE WHEN projection_status IN ('pending', 'projecting', 'retrying') THEN 1 ELSE 0 END) AS pending,
|
|
341
|
+
MIN(CASE WHEN projection_status IN ('pending', 'projecting', 'retrying') THEN ingested_at_ms END) AS oldest,
|
|
342
|
+
SUM(CASE WHEN projection_status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letters
|
|
343
|
+
FROM automation_events`).get();
|
|
344
|
+
const delivery = getSqliteDatabase().prepare(`SELECT
|
|
345
|
+
SUM(CASE WHEN status IN ('pending', 'retrying', 'queued') THEN 1 ELSE 0 END) AS pending,
|
|
346
|
+
SUM(CASE WHEN status = 'dead_letter' THEN 1 ELSE 0 END) AS dead_letters,
|
|
347
|
+
SUM(CASE WHEN lease_until_ms > ? THEN 1 ELSE 0 END) AS active_leases
|
|
348
|
+
FROM automation_event_deliveries`).get(now);
|
|
349
|
+
const projectionLeases = getSqliteDatabase().prepare(`SELECT COUNT(*) AS count FROM automation_events
|
|
350
|
+
WHERE projection_status = 'projecting' AND projection_lease_until_ms > ?`).get(now);
|
|
351
|
+
return {
|
|
352
|
+
pending: event.pending ?? 0,
|
|
353
|
+
oldestPendingAgeMs: event.oldest == null ? 0 : Math.max(0, now - event.oldest),
|
|
354
|
+
projectionDeadLetters: event.dead_letters ?? 0,
|
|
355
|
+
pendingDeliveries: delivery.pending ?? 0,
|
|
356
|
+
deliveryDeadLetters: delivery.dead_letters ?? 0,
|
|
357
|
+
activeLeases: (delivery.active_leases ?? 0) + projectionLeases.count
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
//#endregion
|
|
361
|
+
export { automationEventPublisher, claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomationEventQueueMetrics, ingestAutomationEvent, listAutomationEventRecords, listAutomationEvents, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, releaseAutomationEventDelivery, releaseAutomationEventProjection, replayAutomationEvent, skipAutomationEventDelivery };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { listBusinessEventDefinitions, registerBusinessEvent, validateCatalogedBusinessEvent } from "./event-catalog.js";
|
|
2
|
+
import { automationEventPublisher, claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomationEventQueueMetrics, ingestAutomationEvent, listAutomationEventRecords, listAutomationEvents, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, releaseAutomationEventDelivery, releaseAutomationEventProjection, replayAutomationEvent, skipAutomationEventDelivery } from "./event-repository.js";
|
|
3
|
+
import { AutomationEventDispatcher } from "./event-dispatcher.js";
|
|
4
|
+
export { AutomationEventDispatcher, automationEventPublisher, claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomationEventQueueMetrics, ingestAutomationEvent, listAutomationEventRecords, listAutomationEvents, listBusinessEventDefinitions, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, registerBusinessEvent, releaseAutomationEventDelivery, releaseAutomationEventProjection, replayAutomationEvent, skipAutomationEventDelivery, validateCatalogedBusinessEvent };
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AutomationActionSchema, AutomationDeliveryPolicySchema, AutomationManagementSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, UpdateAutomationSchema } from "./domain/validation.js";
|
|
2
|
+
import { listBusinessEventDefinitions, registerBusinessEvent, validateCatalogedBusinessEvent } from "./events/event-catalog.js";
|
|
3
|
+
import { automationEventPublisher, claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomationEventQueueMetrics, ingestAutomationEvent, listAutomationEventRecords, listAutomationEvents, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, releaseAutomationEventDelivery, releaseAutomationEventProjection, replayAutomationEvent, skipAutomationEventDelivery } from "./events/event-repository.js";
|
|
3
4
|
import { computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, timerDelayUntil } from "./domain/schedule.js";
|
|
4
5
|
import { DEFAULT_AUTOMATION_TIMEOUT_SECONDS, DEFAULT_BROWSER_AUTOMATION_TIMEOUT_SECONDS, defaultAutomationTimeoutSeconds, resolveAutomationTimeoutSeconds } from "./domain/defaults.js";
|
|
5
6
|
import { AutomationActionExecutor } from "./service/action-executor.js";
|
|
7
|
+
import { AutomationEventDispatcher } from "./events/event-dispatcher.js";
|
|
8
|
+
import "./events/index.js";
|
|
9
|
+
import { resolveAutomationWebhookSecret } from "./webhook-secrets.js";
|
|
10
|
+
import { AutomationDeliveryRouter, getAutomationResultDeliveryMetrics, listAutomationResultDeliveries, retryAutomationResultDelivery } from "./delivery/delivery-router.js";
|
|
11
|
+
import "./delivery/index.js";
|
|
6
12
|
import { AutomationAlreadyExistsError, AutomationAlreadyRunningError, AutomationService } from "./service/automation-service.js";
|
|
7
13
|
import "./domain/index.js";
|
|
8
14
|
import "./service/index.js";
|
|
9
|
-
export { AutomationActionExecutor, AutomationActionSchema, AutomationAlreadyExistsError, AutomationAlreadyRunningError, AutomationManagementSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationService, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, DEFAULT_AUTOMATION_TIMEOUT_SECONDS, DEFAULT_BROWSER_AUTOMATION_TIMEOUT_SECONDS, UpdateAutomationSchema, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, defaultAutomationTimeoutSeconds,
|
|
15
|
+
export { AutomationActionExecutor, AutomationActionSchema, AutomationAlreadyExistsError, AutomationAlreadyRunningError, AutomationDeliveryPolicySchema, AutomationDeliveryRouter, AutomationEventDispatcher, AutomationManagementSchema, AutomationReliabilitySchema, AutomationSafetyPolicySchema, AutomationScheduleSchema, AutomationSchema, AutomationService, AutomationStateSchema, AutomationTriggerSchema, CreateAutomationSchema, DEFAULT_AUTOMATION_TIMEOUT_SECONDS, DEFAULT_BROWSER_AUTOMATION_TIMEOUT_SECONDS, UpdateAutomationSchema, automationEventPublisher, claimAutomationEventDeliveries, claimAutomationEventsForProjection, completeAutomationEventDelivery, completeAutomationEventProjection, computeNextAutomationRunAtMs, computeNextScheduleRunAtMs, defaultAutomationTimeoutSeconds, deferAutomationEventDelivery, expireAutomationEventProjectionLeases, failAutomationEventProjection, getAutomationEventDeliveryRunId, getAutomationEventForRun, getAutomationEventQueueMetrics, getAutomationResultDeliveryMetrics, ingestAutomationEvent, listAutomationEventRecords, listAutomationEvents, listAutomationResultDeliveries, listBusinessEventDefinitions, markAutomationEventDeliveryQueued, reconcileAutomationEventDeliveries, registerBusinessEvent, releaseAutomationEventDelivery, releaseAutomationEventProjection, replayAutomationEvent, resolveAutomationTimeoutSeconds, resolveAutomationWebhookSecret, retryAutomationResultDelivery, skipAutomationEventDelivery, timerDelayUntil, validateCatalogedBusinessEvent };
|
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
import type { Automation, AutomationActionExecutionContext, AutomationActionExecutionHooks, AutomationActionTask, AutomationDeps, AutomationRun } from '../domain/types.js';
|
|
1
|
+
import type { Automation, AutomationAction, AutomationActionExecutionContext, AutomationActionExecutionHooks, AutomationActionTask, AutomationDeps, AutomationRetrySafety, AutomationRun } from '../domain/types.js';
|
|
2
|
+
type AutomationActionKind = AutomationAction['kind'];
|
|
3
|
+
type AutomationActionOf<K extends AutomationActionKind> = Extract<AutomationAction, {
|
|
4
|
+
kind: K;
|
|
5
|
+
}>;
|
|
6
|
+
interface AutomationExecutorInput {
|
|
7
|
+
automation: Automation;
|
|
8
|
+
run: AutomationRun;
|
|
9
|
+
signal: AbortSignal;
|
|
10
|
+
hooks: AutomationActionExecutionHooks;
|
|
11
|
+
deadlineAtMs: number;
|
|
12
|
+
context: AutomationActionExecutionContext;
|
|
13
|
+
}
|
|
2
14
|
export declare class AutomationActionExecutor {
|
|
3
15
|
private deps;
|
|
16
|
+
private readonly handlers;
|
|
17
|
+
constructor();
|
|
18
|
+
register<K extends AutomationActionKind>(kind: K, retrySafety: AutomationRetrySafety, handler: (input: AutomationExecutorInput, action: AutomationActionOf<K>) => Promise<AutomationActionTask>): void;
|
|
19
|
+
canRetry(kind: AutomationActionKind, error: unknown): boolean;
|
|
4
20
|
setDeps(deps: AutomationDeps): void;
|
|
5
21
|
execute(automation: Automation, run: AutomationRun, signal: AbortSignal, hooks?: AutomationActionExecutionHooks, context?: AutomationActionExecutionContext): Promise<AutomationActionTask>;
|
|
6
22
|
private executeWithoutTimeout;
|
|
23
|
+
private executeTaskCommand;
|
|
24
|
+
private executeSystemAction;
|
|
7
25
|
private executeBrowserAutomation;
|
|
8
26
|
private executeAgent;
|
|
9
27
|
private executeWorkflow;
|
|
10
28
|
}
|
|
29
|
+
export {};
|