@canhta/dsh-autopilot 0.1.0-alpha.1
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/AGENTS.md +41 -0
- package/CONTEXT.md +39 -0
- package/LICENSE +21 -0
- package/README.md +95 -0
- package/cordis.patch.yml +13 -0
- package/deploy/dsh-autopilot.service +26 -0
- package/docs/CONTRIBUTING.md +60 -0
- package/docs/README.md +34 -0
- package/docs/agents/domain.md +7 -0
- package/docs/agents/issue-tracker.md +21 -0
- package/docs/agents/triage-labels.md +13 -0
- package/docs/assets/banner.png +0 -0
- package/docs/deployment.md +138 -0
- package/docs/engineering.md +43 -0
- package/docs/specs/execution.md +65 -0
- package/docs/specs/integrations.md +89 -0
- package/docs/specs/lifecycle.md +81 -0
- package/docs/specs/operations.md +89 -0
- package/docs/specs/plugin.md +49 -0
- package/docs/specs/providers.md +62 -0
- package/docs/specs/scope.md +35 -0
- package/docs/specs/ui-components.md +96 -0
- package/docs/specs/web-ui.md +64 -0
- package/lib/admission/cancellation-control.d.ts +11 -0
- package/lib/admission/cancellation-control.js +72 -0
- package/lib/admission/cancellation-control.js.map +1 -0
- package/lib/admission/candidates.d.ts +2 -0
- package/lib/admission/candidates.js +23 -0
- package/lib/admission/candidates.js.map +1 -0
- package/lib/admission/composition-claim.d.ts +10 -0
- package/lib/admission/composition-claim.js +13 -0
- package/lib/admission/composition-claim.js.map +1 -0
- package/lib/admission/constants.d.ts +12 -0
- package/lib/admission/constants.js +13 -0
- package/lib/admission/constants.js.map +1 -0
- package/lib/admission/deliveries.d.ts +6 -0
- package/lib/admission/deliveries.js +175 -0
- package/lib/admission/deliveries.js.map +1 -0
- package/lib/admission/delivery-control.d.ts +28 -0
- package/lib/admission/delivery-control.js +294 -0
- package/lib/admission/delivery-control.js.map +1 -0
- package/lib/admission/execution-control.d.ts +29 -0
- package/lib/admission/execution-control.js +177 -0
- package/lib/admission/execution-control.js.map +1 -0
- package/lib/admission/index.d.ts +4 -0
- package/lib/admission/index.js +4 -0
- package/lib/admission/index.js.map +1 -0
- package/lib/admission/model.d.ts +296 -0
- package/lib/admission/model.js +13 -0
- package/lib/admission/model.js.map +1 -0
- package/lib/admission/pause-control.d.ts +44 -0
- package/lib/admission/pause-control.js +220 -0
- package/lib/admission/pause-control.js.map +1 -0
- package/lib/admission/policy.d.ts +39 -0
- package/lib/admission/policy.js +238 -0
- package/lib/admission/policy.js.map +1 -0
- package/lib/admission/ports.d.ts +13 -0
- package/lib/admission/ports.js +2 -0
- package/lib/admission/ports.js.map +1 -0
- package/lib/admission/publication-control.d.ts +16 -0
- package/lib/admission/publication-control.js +153 -0
- package/lib/admission/publication-control.js.map +1 -0
- package/lib/admission/reconciler.d.ts +7 -0
- package/lib/admission/reconciler.js +121 -0
- package/lib/admission/reconciler.js.map +1 -0
- package/lib/admission/resume-control.d.ts +27 -0
- package/lib/admission/resume-control.js +213 -0
- package/lib/admission/resume-control.js.map +1 -0
- package/lib/admission/run-fence.d.ts +11 -0
- package/lib/admission/run-fence.js +49 -0
- package/lib/admission/run-fence.js.map +1 -0
- package/lib/admission/service.d.ts +130 -0
- package/lib/admission/service.js +415 -0
- package/lib/admission/service.js.map +1 -0
- package/lib/admission/state-domain.d.ts +11 -0
- package/lib/admission/state-domain.js +33 -0
- package/lib/admission/state-domain.js.map +1 -0
- package/lib/admission/state-integrity.d.ts +19 -0
- package/lib/admission/state-integrity.js +102 -0
- package/lib/admission/state-integrity.js.map +1 -0
- package/lib/admission/state-migration.d.ts +4 -0
- package/lib/admission/state-migration.js +46 -0
- package/lib/admission/state-migration.js.map +1 -0
- package/lib/admission/state.d.ts +4524 -0
- package/lib/admission/state.js +394 -0
- package/lib/admission/state.js.map +1 -0
- package/lib/admission.d.ts +1 -0
- package/lib/admission.js +2 -0
- package/lib/admission.js.map +1 -0
- package/lib/client-types/client/OperationsAtoms.d.ts +30 -0
- package/lib/client-types/client/OperationsPanel.d.ts +34 -0
- package/lib/client-types/client/RunsView.d.ts +14 -0
- package/lib/client-types/client/SettingsCapabilitySections.d.ts +16 -0
- package/lib/client-types/client/SettingsPanel.d.ts +40 -0
- package/lib/client-types/client/SettingsPolicySections.d.ts +13 -0
- package/lib/client-types/client/SettingsProviderSection.d.ts +21 -0
- package/lib/client-types/client/SummaryView.d.ts +10 -0
- package/lib/client-types/client/WorktreesView.d.ts +9 -0
- package/lib/client-types/client/index.d.ts +9 -0
- package/lib/client-types/client/locales/en.d.ts +154 -0
- package/lib/client-types/client/locales/index.d.ts +9 -0
- package/lib/client-types/client/locales/zh.d.ts +155 -0
- package/lib/client-types/client/settings-draft.d.ts +29 -0
- package/lib/client-types/client/state.d.ts +63 -0
- package/lib/client-types/code-host/index.d.ts +2 -0
- package/lib/client-types/code-host/model.d.ts +118 -0
- package/lib/client-types/code-host/registry.d.ts +23 -0
- package/lib/client-types/code-host/validation.d.ts +51 -0
- package/lib/client-types/code-host.d.ts +2 -0
- package/lib/client-types/config/index.d.ts +2 -0
- package/lib/client-types/config/settings.d.ts +51 -0
- package/lib/client-types/config.d.ts +2 -0
- package/lib/client-types/notification/index.d.ts +2 -0
- package/lib/client-types/notification/model.d.ts +57 -0
- package/lib/client-types/notification/registry.d.ts +16 -0
- package/lib/client-types/notification.d.ts +2 -0
- package/lib/client-types/providers/generation-registry.d.ts +20 -0
- package/lib/client-types/remote.d.ts +65 -0
- package/lib/client-types/tracker/index.d.ts +2 -0
- package/lib/client-types/tracker/model.d.ts +222 -0
- package/lib/client-types/tracker/registry.d.ts +49 -0
- package/lib/client-types/tracker/validation.d.ts +60 -0
- package/lib/client-types/tracker.d.ts +2 -0
- package/lib/client-types/web/contract.d.ts +958 -0
- package/lib/client.js +7961 -0
- package/lib/client.js.map +1 -0
- package/lib/code-host/index.d.ts +2 -0
- package/lib/code-host/index.js +3 -0
- package/lib/code-host/index.js.map +1 -0
- package/lib/code-host/model.d.ts +118 -0
- package/lib/code-host/model.js +23 -0
- package/lib/code-host/model.js.map +1 -0
- package/lib/code-host/registry.d.ts +23 -0
- package/lib/code-host/registry.js +90 -0
- package/lib/code-host/registry.js.map +1 -0
- package/lib/code-host/validation.d.ts +51 -0
- package/lib/code-host/validation.js +30 -0
- package/lib/code-host/validation.js.map +1 -0
- package/lib/code-host.d.ts +2 -0
- package/lib/code-host.js +3 -0
- package/lib/code-host.js.map +1 -0
- package/lib/config/index.d.ts +2 -0
- package/lib/config/index.js +3 -0
- package/lib/config/index.js.map +1 -0
- package/lib/config/settings.d.ts +51 -0
- package/lib/config/settings.js +195 -0
- package/lib/config/settings.js.map +1 -0
- package/lib/config.d.ts +2 -0
- package/lib/config.js +3 -0
- package/lib/config.js.map +1 -0
- package/lib/delivery/index.d.ts +1 -0
- package/lib/delivery/index.js +2 -0
- package/lib/delivery/index.js.map +1 -0
- package/lib/delivery/service.d.ts +29 -0
- package/lib/delivery/service.js +140 -0
- package/lib/delivery/service.js.map +1 -0
- package/lib/delivery.d.ts +2 -0
- package/lib/delivery.js +3 -0
- package/lib/delivery.js.map +1 -0
- package/lib/dispatch/composition.d.ts +18 -0
- package/lib/dispatch/composition.js +109 -0
- package/lib/dispatch/composition.js.map +1 -0
- package/lib/dispatch/contract.d.ts +2 -0
- package/lib/dispatch/contract.js +2 -0
- package/lib/dispatch/contract.js.map +1 -0
- package/lib/dispatch/execute.d.ts +10 -0
- package/lib/dispatch/execute.js +138 -0
- package/lib/dispatch/execute.js.map +1 -0
- package/lib/dispatch/execution-state.d.ts +12 -0
- package/lib/dispatch/execution-state.js +24 -0
- package/lib/dispatch/execution-state.js.map +1 -0
- package/lib/dispatch/git.d.ts +5 -0
- package/lib/dispatch/git.js +95 -0
- package/lib/dispatch/git.js.map +1 -0
- package/lib/dispatch/index.d.ts +2 -0
- package/lib/dispatch/index.js +2 -0
- package/lib/dispatch/index.js.map +1 -0
- package/lib/dispatch/report.d.ts +11 -0
- package/lib/dispatch/report.js +141 -0
- package/lib/dispatch/report.js.map +1 -0
- package/lib/dispatch/resume.d.ts +17 -0
- package/lib/dispatch/resume.js +89 -0
- package/lib/dispatch/resume.js.map +1 -0
- package/lib/dispatch/service.d.ts +56 -0
- package/lib/dispatch/service.js +231 -0
- package/lib/dispatch/service.js.map +1 -0
- package/lib/dispatch/usage.d.ts +10 -0
- package/lib/dispatch/usage.js +47 -0
- package/lib/dispatch/usage.js.map +1 -0
- package/lib/dispatch.d.ts +2 -0
- package/lib/dispatch.js +3 -0
- package/lib/dispatch.js.map +1 -0
- package/lib/github-code-host.d.ts +1 -0
- package/lib/github-code-host.js +2 -0
- package/lib/github-code-host.js.map +1 -0
- package/lib/github-issues.d.ts +1 -0
- package/lib/github-issues.js +2 -0
- package/lib/github-issues.js.map +1 -0
- package/lib/index.d.ts +21 -0
- package/lib/index.js +48 -0
- package/lib/index.js.map +1 -0
- package/lib/ingress.d.ts +2 -0
- package/lib/ingress.js +3 -0
- package/lib/ingress.js.map +1 -0
- package/lib/jira.d.ts +1 -0
- package/lib/jira.js +2 -0
- package/lib/jira.js.map +1 -0
- package/lib/mcp/contracts.d.ts +21 -0
- package/lib/mcp/contracts.js +33 -0
- package/lib/mcp/contracts.js.map +1 -0
- package/lib/mcp/cursor.d.ts +10 -0
- package/lib/mcp/cursor.js +68 -0
- package/lib/mcp/cursor.js.map +1 -0
- package/lib/mcp/definition.d.ts +8 -0
- package/lib/mcp/definition.js +43 -0
- package/lib/mcp/definition.js.map +1 -0
- package/lib/mcp/index.d.ts +6 -0
- package/lib/mcp/index.js +7 -0
- package/lib/mcp/index.js.map +1 -0
- package/lib/mcp/json.d.ts +4 -0
- package/lib/mcp/json.js +20 -0
- package/lib/mcp/json.js.map +1 -0
- package/lib/mcp/mount.d.ts +17 -0
- package/lib/mcp/mount.js +79 -0
- package/lib/mcp/mount.js.map +1 -0
- package/lib/mcp/read-tools.d.ts +27 -0
- package/lib/mcp/read-tools.js +149 -0
- package/lib/mcp/read-tools.js.map +1 -0
- package/lib/notification/index.d.ts +2 -0
- package/lib/notification/index.js +3 -0
- package/lib/notification/index.js.map +1 -0
- package/lib/notification/model.d.ts +57 -0
- package/lib/notification/model.js +20 -0
- package/lib/notification/model.js.map +1 -0
- package/lib/notification/registry.d.ts +16 -0
- package/lib/notification/registry.js +67 -0
- package/lib/notification/registry.js.map +1 -0
- package/lib/notification.d.ts +2 -0
- package/lib/notification.js +3 -0
- package/lib/notification.js.map +1 -0
- package/lib/ntfy-notification.d.ts +1 -0
- package/lib/ntfy-notification.js +2 -0
- package/lib/ntfy-notification.js.map +1 -0
- package/lib/operations/cleanup-inspector.d.ts +16 -0
- package/lib/operations/cleanup-inspector.js +132 -0
- package/lib/operations/cleanup-inspector.js.map +1 -0
- package/lib/operations/cleanup.d.ts +25 -0
- package/lib/operations/cleanup.js +151 -0
- package/lib/operations/cleanup.js.map +1 -0
- package/lib/operations/disposition.d.ts +46 -0
- package/lib/operations/disposition.js +89 -0
- package/lib/operations/disposition.js.map +1 -0
- package/lib/operations/health.d.ts +6 -0
- package/lib/operations/health.js +41 -0
- package/lib/operations/health.js.map +1 -0
- package/lib/operations/index.d.ts +6 -0
- package/lib/operations/index.js +7 -0
- package/lib/operations/index.js.map +1 -0
- package/lib/operations/inspection.d.ts +35 -0
- package/lib/operations/inspection.js +183 -0
- package/lib/operations/inspection.js.map +1 -0
- package/lib/operations/model.d.ts +77 -0
- package/lib/operations/model.js +2 -0
- package/lib/operations/model.js.map +1 -0
- package/lib/operations/recovery.d.ts +11 -0
- package/lib/operations/recovery.js +101 -0
- package/lib/operations/recovery.js.map +1 -0
- package/lib/operations/retention.d.ts +28 -0
- package/lib/operations/retention.js +105 -0
- package/lib/operations/retention.js.map +1 -0
- package/lib/operations/runtime-owner.d.ts +54 -0
- package/lib/operations/runtime-owner.js +281 -0
- package/lib/operations/runtime-owner.js.map +1 -0
- package/lib/operations/service.d.ts +55 -0
- package/lib/operations/service.js +154 -0
- package/lib/operations/service.js.map +1 -0
- package/lib/operations/state.d.ts +79 -0
- package/lib/operations/state.js +51 -0
- package/lib/operations/state.js.map +1 -0
- package/lib/operations/storage-composition.d.ts +16 -0
- package/lib/operations/storage-composition.js +61 -0
- package/lib/operations/storage-composition.js.map +1 -0
- package/lib/operations/store.d.ts +16 -0
- package/lib/operations/store.js +84 -0
- package/lib/operations/store.js.map +1 -0
- package/lib/operations.d.ts +2 -0
- package/lib/operations.js +3 -0
- package/lib/operations.js.map +1 -0
- package/lib/providers/generation-registry.d.ts +20 -0
- package/lib/providers/generation-registry.js +72 -0
- package/lib/providers/generation-registry.js.map +1 -0
- package/lib/providers/github-code-host/contracts.d.ts +224 -0
- package/lib/providers/github-code-host/contracts.js +144 -0
- package/lib/providers/github-code-host/contracts.js.map +1 -0
- package/lib/providers/github-code-host/index.d.ts +2 -0
- package/lib/providers/github-code-host/index.js +2 -0
- package/lib/providers/github-code-host/index.js.map +1 -0
- package/lib/providers/github-code-host/provider.d.ts +5 -0
- package/lib/providers/github-code-host/provider.js +289 -0
- package/lib/providers/github-code-host/provider.js.map +1 -0
- package/lib/providers/github-code-host/schemas.d.ts +81 -0
- package/lib/providers/github-code-host/schemas.js +39 -0
- package/lib/providers/github-code-host/schemas.js.map +1 -0
- package/lib/providers/github-code-host/settings.d.ts +16 -0
- package/lib/providers/github-code-host/settings.js +65 -0
- package/lib/providers/github-code-host/settings.js.map +1 -0
- package/lib/providers/github-issues/contracts.d.ts +151 -0
- package/lib/providers/github-issues/contracts.js +141 -0
- package/lib/providers/github-issues/contracts.js.map +1 -0
- package/lib/providers/github-issues/index.d.ts +1 -0
- package/lib/providers/github-issues/index.js +2 -0
- package/lib/providers/github-issues/index.js.map +1 -0
- package/lib/providers/github-issues/ingress.d.ts +8 -0
- package/lib/providers/github-issues/ingress.js +80 -0
- package/lib/providers/github-issues/ingress.js.map +1 -0
- package/lib/providers/github-issues/normalization.d.ts +11 -0
- package/lib/providers/github-issues/normalization.js +115 -0
- package/lib/providers/github-issues/normalization.js.map +1 -0
- package/lib/providers/github-issues/provider.d.ts +6 -0
- package/lib/providers/github-issues/provider.js +235 -0
- package/lib/providers/github-issues/provider.js.map +1 -0
- package/lib/providers/github-issues/schemas.d.ts +123 -0
- package/lib/providers/github-issues/schemas.js +58 -0
- package/lib/providers/github-issues/schemas.js.map +1 -0
- package/lib/providers/github-issues/settings.d.ts +27 -0
- package/lib/providers/github-issues/settings.js +154 -0
- package/lib/providers/github-issues/settings.js.map +1 -0
- package/lib/providers/jira/contracts.d.ts +193 -0
- package/lib/providers/jira/contracts.js +133 -0
- package/lib/providers/jira/contracts.js.map +1 -0
- package/lib/providers/jira/index.d.ts +1 -0
- package/lib/providers/jira/index.js +2 -0
- package/lib/providers/jira/index.js.map +1 -0
- package/lib/providers/jira/ingress.d.ts +4 -0
- package/lib/providers/jira/ingress.js +60 -0
- package/lib/providers/jira/ingress.js.map +1 -0
- package/lib/providers/jira/normalization.d.ts +8 -0
- package/lib/providers/jira/normalization.js +121 -0
- package/lib/providers/jira/normalization.js.map +1 -0
- package/lib/providers/jira/provider.d.ts +6 -0
- package/lib/providers/jira/provider.js +317 -0
- package/lib/providers/jira/provider.js.map +1 -0
- package/lib/providers/jira/schemas.d.ts +134 -0
- package/lib/providers/jira/schemas.js +76 -0
- package/lib/providers/jira/schemas.js.map +1 -0
- package/lib/providers/jira/settings.d.ts +32 -0
- package/lib/providers/jira/settings.js +163 -0
- package/lib/providers/jira/settings.js.map +1 -0
- package/lib/providers/notification-http.d.ts +13 -0
- package/lib/providers/notification-http.js +136 -0
- package/lib/providers/notification-http.js.map +1 -0
- package/lib/providers/ntfy-notification/index.d.ts +2 -0
- package/lib/providers/ntfy-notification/index.js +2 -0
- package/lib/providers/ntfy-notification/index.js.map +1 -0
- package/lib/providers/ntfy-notification/provider.d.ts +4 -0
- package/lib/providers/ntfy-notification/provider.js +89 -0
- package/lib/providers/ntfy-notification/provider.js.map +1 -0
- package/lib/providers/ntfy-notification/settings.d.ts +12 -0
- package/lib/providers/ntfy-notification/settings.js +34 -0
- package/lib/providers/ntfy-notification/settings.js.map +1 -0
- package/lib/providers/webhook-notification/index.d.ts +2 -0
- package/lib/providers/webhook-notification/index.js +2 -0
- package/lib/providers/webhook-notification/index.js.map +1 -0
- package/lib/providers/webhook-notification/provider.d.ts +4 -0
- package/lib/providers/webhook-notification/provider.js +57 -0
- package/lib/providers/webhook-notification/provider.js.map +1 -0
- package/lib/providers/webhook-notification/settings.d.ts +11 -0
- package/lib/providers/webhook-notification/settings.js +31 -0
- package/lib/providers/webhook-notification/settings.js.map +1 -0
- package/lib/publication/git.d.ts +7 -0
- package/lib/publication/git.js +154 -0
- package/lib/publication/git.js.map +1 -0
- package/lib/publication/index.d.ts +1 -0
- package/lib/publication/index.js +2 -0
- package/lib/publication/index.js.map +1 -0
- package/lib/publication/service.d.ts +27 -0
- package/lib/publication/service.js +166 -0
- package/lib/publication/service.js.map +1 -0
- package/lib/publication.d.ts +2 -0
- package/lib/publication.js +3 -0
- package/lib/publication.js.map +1 -0
- package/lib/reconciliation/index.d.ts +3 -0
- package/lib/reconciliation/index.js +4 -0
- package/lib/reconciliation/index.js.map +1 -0
- package/lib/reconciliation/ingress.d.ts +21 -0
- package/lib/reconciliation/ingress.js +168 -0
- package/lib/reconciliation/ingress.js.map +1 -0
- package/lib/reconciliation/service.d.ts +75 -0
- package/lib/reconciliation/service.js +228 -0
- package/lib/reconciliation/service.js.map +1 -0
- package/lib/reconciliation.d.ts +2 -0
- package/lib/reconciliation.js +3 -0
- package/lib/reconciliation.js.map +1 -0
- package/lib/remote.d.ts +65 -0
- package/lib/remote.js +135 -0
- package/lib/remote.js.map +1 -0
- package/lib/tracker/index.d.ts +2 -0
- package/lib/tracker/index.js +3 -0
- package/lib/tracker/index.js.map +1 -0
- package/lib/tracker/model.d.ts +222 -0
- package/lib/tracker/model.js +66 -0
- package/lib/tracker/model.js.map +1 -0
- package/lib/tracker/registry.d.ts +49 -0
- package/lib/tracker/registry.js +213 -0
- package/lib/tracker/registry.js.map +1 -0
- package/lib/tracker/validation.d.ts +60 -0
- package/lib/tracker/validation.js +52 -0
- package/lib/tracker/validation.js.map +1 -0
- package/lib/tracker.d.ts +2 -0
- package/lib/tracker.js +3 -0
- package/lib/tracker.js.map +1 -0
- package/lib/typert.d.ts +1 -0
- package/lib/typert.js +2 -0
- package/lib/typert.js.map +1 -0
- package/lib/web/commands.d.ts +18 -0
- package/lib/web/commands.js +231 -0
- package/lib/web/commands.js.map +1 -0
- package/lib/web/contract.d.ts +958 -0
- package/lib/web/contract.js +230 -0
- package/lib/web/contract.js.map +1 -0
- package/lib/web/contributions.d.ts +41 -0
- package/lib/web/contributions.js +61 -0
- package/lib/web/contributions.js.map +1 -0
- package/lib/web/integrations.d.ts +13 -0
- package/lib/web/integrations.js +95 -0
- package/lib/web/integrations.js.map +1 -0
- package/lib/web/projection.d.ts +10 -0
- package/lib/web/projection.js +192 -0
- package/lib/web/projection.js.map +1 -0
- package/lib/web/service.d.ts +31 -0
- package/lib/web/service.js +141 -0
- package/lib/web/service.js.map +1 -0
- package/lib/web.d.ts +5 -0
- package/lib/web.js +6 -0
- package/lib/web.js.map +1 -0
- package/lib/webhook-notification.d.ts +1 -0
- package/lib/webhook-notification.js +2 -0
- package/lib/webhook-notification.js.map +1 -0
- package/lib/workflow/index.d.ts +1 -0
- package/lib/workflow/index.js +2 -0
- package/lib/workflow/index.js.map +1 -0
- package/lib/workflow/service.d.ts +31 -0
- package/lib/workflow/service.js +220 -0
- package/lib/workflow/service.js.map +1 -0
- package/lib/workflow.d.ts +2 -0
- package/lib/workflow.js +3 -0
- package/lib/workflow.js.map +1 -0
- package/package.json +276 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
3
|
+
import s from '@deepseek-ai/schemastery';
|
|
4
|
+
import { TrackerProviderError } from '../../tracker.js';
|
|
5
|
+
const protectedSettingKeys = [
|
|
6
|
+
'mcpServerName',
|
|
7
|
+
'cloudId',
|
|
8
|
+
'projectId',
|
|
9
|
+
'integrationAccountId',
|
|
10
|
+
'readyLabel',
|
|
11
|
+
'priorityRanks',
|
|
12
|
+
'doneStatusIds',
|
|
13
|
+
'blockingLinkTypeIds',
|
|
14
|
+
'dependencyDirection',
|
|
15
|
+
'automationAccountIds',
|
|
16
|
+
'trustedHumanAccountIds',
|
|
17
|
+
'queuedLabel',
|
|
18
|
+
'implementingLabel',
|
|
19
|
+
'pausedLabel',
|
|
20
|
+
'blockedLabel',
|
|
21
|
+
'failedLabel',
|
|
22
|
+
'completedLabel',
|
|
23
|
+
'reviewTransitionId',
|
|
24
|
+
'reviewStatusId',
|
|
25
|
+
];
|
|
26
|
+
/** Whether a Settings edit would reinterpret an existing Jira run or delivery intent. */
|
|
27
|
+
export function changesJiraBinding(current, next) {
|
|
28
|
+
return protectedSettingKeys.some((key) => !isDeepStrictEqual(current[key], next[key]));
|
|
29
|
+
}
|
|
30
|
+
export const jiraSettingsSchema = s.object({
|
|
31
|
+
mcpServerName: s.string().default('atlassian'),
|
|
32
|
+
cloudId: s.string().default(''),
|
|
33
|
+
projectId: s.string().default(''),
|
|
34
|
+
integrationAccountId: s.string().default(''),
|
|
35
|
+
webhookSecretRef: s.string().default('DSH_AUTOPILOT_JIRA_WEBHOOK_SECRET'),
|
|
36
|
+
readyLabel: s.string().default('ready-for-agent'),
|
|
37
|
+
pageSize: s.number().min(1).max(100).default(50),
|
|
38
|
+
maxPagesPerTraversal: s.number().min(1).max(1_000).default(100),
|
|
39
|
+
maxItemsPerTraversal: s.number().min(1).max(10_000).default(10_000),
|
|
40
|
+
priorityRanks: s.dict(s.number().min(0)).default({}),
|
|
41
|
+
doneStatusIds: s.array(s.string()).default([]),
|
|
42
|
+
blockingLinkTypeIds: s.array(s.string()).default([]),
|
|
43
|
+
dependencyDirection: s.union(['inward', 'outward']).default('inward'),
|
|
44
|
+
automationAccountIds: s.array(s.string()).default([]),
|
|
45
|
+
trustedHumanAccountIds: s.array(s.string()).default([]),
|
|
46
|
+
queuedLabel: s.string().default('agent-queued'),
|
|
47
|
+
implementingLabel: s.string().default('agent-implementing'),
|
|
48
|
+
pausedLabel: s.string().default('agent-paused'),
|
|
49
|
+
blockedLabel: s.string().default('agent-blocked'),
|
|
50
|
+
failedLabel: s.string().default('agent-failed'),
|
|
51
|
+
completedLabel: s.string().default('agent-completed'),
|
|
52
|
+
reviewTransitionId: s.string().default(''),
|
|
53
|
+
reviewStatusId: s.string().default(''),
|
|
54
|
+
});
|
|
55
|
+
export function validateStoredSettings(config) {
|
|
56
|
+
if (!Number.isInteger(config.pageSize) || config.pageSize < 1 || config.pageSize > 100) {
|
|
57
|
+
throw new TypeError('Jira page size must be an integer from 1 through 100');
|
|
58
|
+
}
|
|
59
|
+
if (!Number.isInteger(config.maxPagesPerTraversal) ||
|
|
60
|
+
config.maxPagesPerTraversal < 1 ||
|
|
61
|
+
config.maxPagesPerTraversal > 1_000) {
|
|
62
|
+
throw new TypeError('Jira maximum pages must be an integer from 1 through 1000');
|
|
63
|
+
}
|
|
64
|
+
if (!Number.isInteger(config.maxItemsPerTraversal) ||
|
|
65
|
+
config.maxItemsPerTraversal < 1 ||
|
|
66
|
+
config.maxItemsPerTraversal > 10_000) {
|
|
67
|
+
throw new TypeError('Jira maximum items must be an integer from 1 through 10000');
|
|
68
|
+
}
|
|
69
|
+
if (!/^[A-Za-z0-9_-]{1,32}$/.test(config.mcpServerName))
|
|
70
|
+
throw new TypeError('Jira MCP server name is invalid');
|
|
71
|
+
if (config.integrationAccountId.length > 256)
|
|
72
|
+
throw new TypeError('Jira integration account id is too long');
|
|
73
|
+
if (config.readyLabel !== '' && !/^[^,\s]{1,255}$/.test(config.readyLabel)) {
|
|
74
|
+
throw new TypeError('Jira ready label is invalid');
|
|
75
|
+
}
|
|
76
|
+
const projectionLabels = [
|
|
77
|
+
config.readyLabel,
|
|
78
|
+
config.queuedLabel,
|
|
79
|
+
config.implementingLabel,
|
|
80
|
+
config.pausedLabel,
|
|
81
|
+
config.blockedLabel,
|
|
82
|
+
config.failedLabel,
|
|
83
|
+
config.completedLabel,
|
|
84
|
+
];
|
|
85
|
+
if (projectionLabels.some((label) => !/^[^,\s]{1,255}$/.test(label)) ||
|
|
86
|
+
new Set(projectionLabels).size !== projectionLabels.length) {
|
|
87
|
+
throw new TypeError('Jira projection labels must be valid and unique');
|
|
88
|
+
}
|
|
89
|
+
for (const [name, value] of [
|
|
90
|
+
['review transition', config.reviewTransitionId],
|
|
91
|
+
['review status', config.reviewStatusId],
|
|
92
|
+
]) {
|
|
93
|
+
if (value !== '' && (value.length > 256 || !/^[A-Za-z0-9_-]+$/.test(value))) {
|
|
94
|
+
throw new TypeError(`Jira ${name} id is invalid`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (Object.keys(config.priorityRanks).length > 256)
|
|
98
|
+
throw new TypeError('Jira priority mapping is too large');
|
|
99
|
+
for (const rank of Object.values(config.priorityRanks)) {
|
|
100
|
+
if (!Number.isInteger(rank) || rank < 0)
|
|
101
|
+
throw new TypeError('Jira priority ranks must be non-negative integers');
|
|
102
|
+
}
|
|
103
|
+
for (const [name, values] of [
|
|
104
|
+
['done status', config.doneStatusIds],
|
|
105
|
+
['blocking link type', config.blockingLinkTypeIds],
|
|
106
|
+
['automation account', config.automationAccountIds],
|
|
107
|
+
['trusted human account', config.trustedHumanAccountIds],
|
|
108
|
+
]) {
|
|
109
|
+
if (values.length > 256 || values.some((value) => value.length === 0 || value.length > 256)) {
|
|
110
|
+
throw new TypeError(`Jira ${name} mapping is invalid`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (config.cloudId !== '' && !/^[a-zA-Z0-9-]{1,128}$/.test(config.cloudId)) {
|
|
114
|
+
throw new TypeError('Jira cloud id is invalid');
|
|
115
|
+
}
|
|
116
|
+
if (config.projectId !== '' && !/^[1-9][0-9]{0,19}$/.test(config.projectId)) {
|
|
117
|
+
throw new TypeError('Jira project id is invalid');
|
|
118
|
+
}
|
|
119
|
+
if (config.webhookSecretRef !== '')
|
|
120
|
+
credentialRef(config.webhookSecretRef);
|
|
121
|
+
}
|
|
122
|
+
export function requireIngressConfiguredSettings(config) {
|
|
123
|
+
if (config.cloudId === '' || config.webhookSecretRef === '') {
|
|
124
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira webhook settings are incomplete');
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
validateStoredSettings(config);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira webhook settings are invalid');
|
|
131
|
+
}
|
|
132
|
+
return config;
|
|
133
|
+
}
|
|
134
|
+
export function requireConfiguredSettings(config) {
|
|
135
|
+
const missing = ['mcpServerName', 'cloudId', 'projectId', 'integrationAccountId', 'readyLabel'].filter((field) => config[field] === '');
|
|
136
|
+
if (missing.length > 0) {
|
|
137
|
+
throw new TrackerProviderError('invalid-configuration', `Jira settings are incomplete: ${missing.join(', ')}`);
|
|
138
|
+
}
|
|
139
|
+
if (config.blockingLinkTypeIds.length === 0) {
|
|
140
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira blocking-link mapping is required');
|
|
141
|
+
}
|
|
142
|
+
if (config.doneStatusIds.length === 0) {
|
|
143
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira completed-status mapping is required');
|
|
144
|
+
}
|
|
145
|
+
if (config.trustedHumanAccountIds.length === 0) {
|
|
146
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira trusted-human mapping is required');
|
|
147
|
+
}
|
|
148
|
+
if (config.reviewTransitionId === '' || config.reviewStatusId === '') {
|
|
149
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira review transition and status mappings are required');
|
|
150
|
+
}
|
|
151
|
+
const automationIds = new Set([config.integrationAccountId, ...config.automationAccountIds]);
|
|
152
|
+
if (config.trustedHumanAccountIds.some((accountId) => automationIds.has(accountId))) {
|
|
153
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira automation and trusted-human account mappings must be disjoint');
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
validateStoredSettings(config);
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
throw new TrackerProviderError('invalid-configuration', 'Jira settings are invalid');
|
|
160
|
+
}
|
|
161
|
+
return config;
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/providers/jira/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AA4BvD,MAAM,oBAAoB,GAAG;IAC3B,eAAe;IACf,SAAS;IACT,WAAW;IACX,sBAAsB;IACtB,YAAY;IACZ,eAAe;IACf,eAAe;IACf,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,wBAAwB;IACxB,aAAa;IACb,mBAAmB;IACnB,aAAa;IACb,cAAc;IACd,aAAa;IACb,gBAAgB;IAChB,oBAAoB;IACpB,gBAAgB;CACkC,CAAA;AAEpD,yFAAyF;AACzF,MAAM,UAAU,kBAAkB,CAAC,OAAqB,EAAE,IAAkB;IAC1E,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AACxF,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAoB,CAAC,CAAC,MAAM,CAAC;IAC1D,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACjC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC5C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC;IACzE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;IACjD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAChD,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IAC/D,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACnE,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9C,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACpD,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC9E,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrD,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACvD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/C,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC;IAC3D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC;IAC/C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;IACrD,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CACvC,CAAC,CAAA;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAAoB;IACzD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC;QACvF,MAAM,IAAI,SAAS,CAAC,sDAAsD,CAAC,CAAA;IAC7E,CAAC;IACD,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,oBAAoB,CAAC;QAC9C,MAAM,CAAC,oBAAoB,GAAG,CAAC;QAC/B,MAAM,CAAC,oBAAoB,GAAG,KAAK,EACnC,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,2DAA2D,CAAC,CAAA;IAClF,CAAC;IACD,IACE,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,oBAAoB,CAAC;QAC9C,MAAM,CAAC,oBAAoB,GAAG,CAAC;QAC/B,MAAM,CAAC,oBAAoB,GAAG,MAAM,EACpC,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,4DAA4D,CAAC,CAAA;IACnF,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAA;IAC/G,IAAI,MAAM,CAAC,oBAAoB,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAA;IAC5G,IAAI,MAAM,CAAC,UAAU,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,gBAAgB,GAAG;QACvB,MAAM,CAAC,UAAU;QACjB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,iBAAiB;QACxB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,YAAY;QACnB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,cAAc;KACtB,CAAA;IACD,IACE,gBAAgB,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChE,IAAI,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,MAAM,EAC1D,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAA;IACxE,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI;QAC1B,CAAC,mBAAmB,EAAE,MAAM,CAAC,kBAAkB,CAAC;QAChD,CAAC,eAAe,EAAE,MAAM,CAAC,cAAc,CAAC;KAChC,EAAE,CAAC;QACX,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5E,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,gBAAgB,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAA;IAC7G,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAA;IACnH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI;QAC3B,CAAC,aAAa,EAAE,MAAM,CAAC,aAAa,CAAC;QACrC,CAAC,oBAAoB,EAAE,MAAM,CAAC,mBAAmB,CAAC;QAClD,CAAC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB,CAAC;QACnD,CAAC,uBAAuB,EAAE,MAAM,CAAC,sBAAsB,CAAC;KAChD,EAAE,CAAC;QACX,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;YAC5F,MAAM,IAAI,SAAS,CAAC,QAAQ,IAAI,qBAAqB,CAAC,CAAA;QACxD,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAA;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,EAAE,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,SAAS,CAAC,4BAA4B,CAAC,CAAA;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,KAAK,EAAE;QAAE,aAAa,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAA;AAC5E,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,MAAoB;IACnE,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE,IAAI,MAAM,CAAC,gBAAgB,KAAK,EAAE,EAAE,CAAC;QAC5D,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,sCAAsC,CAAC,CAAA;IACjG,CAAC;IACD,IAAI,CAAC;QACH,sBAAsB,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,mCAAmC,CAAC,CAAA;IAC9F,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAoB;IAC5D,MAAM,OAAO,GAAG,CAAC,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,sBAAsB,EAAE,YAAY,CAAC,CAAC,MAAM,CACpG,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAA2B,CAAC,KAAK,EAAE,CACtD,CAAA;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChH,CAAC;IACD,IAAI,MAAM,CAAC,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,wCAAwC,CAAC,CAAA;IACnG,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,2CAA2C,CAAC,CAAA;IACtG,CAAC;IACD,IAAI,MAAM,CAAC,sBAAsB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,wCAAwC,CAAC,CAAA;IACnG,CAAC;IACD,IAAI,MAAM,CAAC,kBAAkB,KAAK,EAAE,IAAI,MAAM,CAAC,cAAc,KAAK,EAAE,EAAE,CAAC;QACrE,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,yDAAyD,CAAC,CAAA;IACpH,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,oBAAoB,EAAE,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAA;IAC5F,IAAI,MAAM,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACpF,MAAM,IAAI,oBAAoB,CAC5B,uBAAuB,EACvB,qEAAqE,CACtE,CAAA;IACH,CAAC;IACD,IAAI,CAAC;QACH,sBAAsB,CAAC,MAAM,CAAC,CAAA;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,oBAAoB,CAAC,uBAAuB,EAAE,2BAA2B,CAAC,CAAA;IACtF,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import { type NotificationReceipt } from '../notification.js';
|
|
3
|
+
export interface HttpNotificationDestination {
|
|
4
|
+
readonly url: string;
|
|
5
|
+
readonly authorizationCredentialRef: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function validateDestinationUrl(value: string, subject: string): void;
|
|
8
|
+
export declare function authorizationHeader(ctx: Context, reference: string): Promise<Record<'authorization', string> | Record<string, never>>;
|
|
9
|
+
export declare function postNotification(destination: HttpNotificationDestination, body: string, headers: Record<string, string>, timeoutMs: number, signal: AbortSignal, responseBody: 'ignore' | 'bounded'): Promise<{
|
|
10
|
+
response: Response;
|
|
11
|
+
text: string;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function acknowledgedReceipt(prefix: string, eventId: string, response: Response): NotificationReceipt;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
2
|
+
import { NotificationProviderError } from '../notification.js';
|
|
3
|
+
const MAX_RESPONSE_BYTES = 64 * 1024;
|
|
4
|
+
export function validateDestinationUrl(value, subject) {
|
|
5
|
+
let url;
|
|
6
|
+
try {
|
|
7
|
+
url = new URL(value);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
throw new TypeError(`${subject} must be an absolute URL`);
|
|
11
|
+
}
|
|
12
|
+
if (url.protocol !== 'https:' || url.username !== '' || url.password !== '' || url.hash !== '') {
|
|
13
|
+
throw new TypeError(`${subject} must use HTTPS without embedded credentials or a fragment`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function authorizationHeader(ctx, reference) {
|
|
17
|
+
if (reference === '')
|
|
18
|
+
return {};
|
|
19
|
+
const resolved = await ctx.credentials.resolve(credentialRef(reference));
|
|
20
|
+
if (resolved === undefined) {
|
|
21
|
+
throw new NotificationProviderError('authentication', 'notification authorization credential is unavailable');
|
|
22
|
+
}
|
|
23
|
+
return { authorization: `Bearer ${resolved.value}` };
|
|
24
|
+
}
|
|
25
|
+
export async function postNotification(destination, body, headers, timeoutMs, signal, responseBody) {
|
|
26
|
+
signal.throwIfAborted();
|
|
27
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
28
|
+
const combined = AbortSignal.any([signal, timeout]);
|
|
29
|
+
let response;
|
|
30
|
+
try {
|
|
31
|
+
response = await fetch(destination.url, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers,
|
|
34
|
+
body,
|
|
35
|
+
redirect: 'error',
|
|
36
|
+
signal: combined,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
signal.throwIfAborted();
|
|
41
|
+
if (timeout.aborted) {
|
|
42
|
+
throw new NotificationProviderError('ambiguous-acknowledgement', 'notification request timed out after dispatch');
|
|
43
|
+
}
|
|
44
|
+
throw new NotificationProviderError('transient', 'notification destination could not be reached');
|
|
45
|
+
}
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
void response.body?.cancel().catch(() => undefined);
|
|
48
|
+
throwResponseError(response);
|
|
49
|
+
}
|
|
50
|
+
if (responseBody === 'ignore') {
|
|
51
|
+
void response.body?.cancel().catch(() => undefined);
|
|
52
|
+
return { response, text: '' };
|
|
53
|
+
}
|
|
54
|
+
let text;
|
|
55
|
+
try {
|
|
56
|
+
text = await boundedResponseText(response, combined);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
signal.throwIfAborted();
|
|
60
|
+
if (timeout.aborted) {
|
|
61
|
+
throw new NotificationProviderError('ambiguous-acknowledgement', 'notification acknowledgement timed out after response headers');
|
|
62
|
+
}
|
|
63
|
+
if (error instanceof NotificationProviderError)
|
|
64
|
+
throw error;
|
|
65
|
+
throw new NotificationProviderError('transient', 'notification response could not be read');
|
|
66
|
+
}
|
|
67
|
+
return { response, text };
|
|
68
|
+
}
|
|
69
|
+
function throwResponseError(response) {
|
|
70
|
+
const retryAfterMs = retryDelay(response.headers.get('retry-after'));
|
|
71
|
+
if (response.status === 401)
|
|
72
|
+
throw new NotificationProviderError('authentication', 'notification authentication failed');
|
|
73
|
+
if (response.status === 403)
|
|
74
|
+
throw new NotificationProviderError('permission', 'notification permission was denied');
|
|
75
|
+
if (response.status === 429) {
|
|
76
|
+
throw new NotificationProviderError('rate-limit', 'notification destination rate limited delivery', retryAfterMs);
|
|
77
|
+
}
|
|
78
|
+
if (response.status >= 500) {
|
|
79
|
+
throw new NotificationProviderError('transient', 'notification destination was temporarily unavailable', retryAfterMs);
|
|
80
|
+
}
|
|
81
|
+
throw new NotificationProviderError('permanent-rejection', 'notification destination rejected the event');
|
|
82
|
+
}
|
|
83
|
+
export function acknowledgedReceipt(prefix, eventId, response) {
|
|
84
|
+
const externalId = response.headers.get('x-request-id')?.trim();
|
|
85
|
+
return {
|
|
86
|
+
receiptId: `${prefix}:${externalId === undefined || externalId === '' ? eventId : externalId}`.slice(0, 512),
|
|
87
|
+
receivedAt: new Date().toISOString(),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
async function boundedResponseText(response, signal) {
|
|
91
|
+
const declared = response.headers.get('content-length');
|
|
92
|
+
if (declared !== null && (!/^\d+$/.test(declared) || Number(declared) > MAX_RESPONSE_BYTES)) {
|
|
93
|
+
await response.body?.cancel();
|
|
94
|
+
throw new NotificationProviderError('invalid-response', 'notification response exceeded its safety bound');
|
|
95
|
+
}
|
|
96
|
+
if (response.body === null)
|
|
97
|
+
return '';
|
|
98
|
+
const reader = response.body.getReader();
|
|
99
|
+
const chunks = [];
|
|
100
|
+
let size = 0;
|
|
101
|
+
try {
|
|
102
|
+
while (true) {
|
|
103
|
+
signal.throwIfAborted();
|
|
104
|
+
const result = await reader.read();
|
|
105
|
+
if (result.done)
|
|
106
|
+
break;
|
|
107
|
+
size += result.value.byteLength;
|
|
108
|
+
if (size > MAX_RESPONSE_BYTES) {
|
|
109
|
+
await reader.cancel();
|
|
110
|
+
throw new NotificationProviderError('invalid-response', 'notification response exceeded its safety bound');
|
|
111
|
+
}
|
|
112
|
+
chunks.push(result.value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
reader.releaseLock();
|
|
117
|
+
}
|
|
118
|
+
const bytes = new Uint8Array(size);
|
|
119
|
+
let offset = 0;
|
|
120
|
+
for (const chunk of chunks) {
|
|
121
|
+
bytes.set(chunk, offset);
|
|
122
|
+
offset += chunk.byteLength;
|
|
123
|
+
}
|
|
124
|
+
return new TextDecoder().decode(bytes);
|
|
125
|
+
}
|
|
126
|
+
function retryDelay(value) {
|
|
127
|
+
if (value === null)
|
|
128
|
+
return undefined;
|
|
129
|
+
if (/^\d+$/.test(value))
|
|
130
|
+
return Math.min(Number(value) * 1_000, 60 * 60 * 1_000);
|
|
131
|
+
const timestamp = Date.parse(value);
|
|
132
|
+
if (Number.isNaN(timestamp))
|
|
133
|
+
return undefined;
|
|
134
|
+
return Math.max(1_000, Math.min(timestamp - Date.now(), 60 * 60 * 1_000));
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=notification-http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-http.js","sourceRoot":"","sources":["../../src/providers/notification-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/ntfy-notification/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { NOTIFICATION_INTERFACE_VERSION, NotificationProviderError, notificationProviderId, } from '../../notification.js';
|
|
4
|
+
import { authorizationHeader, postNotification } from '../notification-http.js';
|
|
5
|
+
import { ntfyNotificationSettingsSchema, validateNtfySettings } from './settings.js';
|
|
6
|
+
const responseSchema = z.object({ id: z.string().min(1).max(256), time: z.number().int().nonnegative() });
|
|
7
|
+
export const name = 'dsh-autopilot-ntfy-notification';
|
|
8
|
+
export const inject = ['notifications', 'settings', 'credentials'];
|
|
9
|
+
export async function apply(ctx) {
|
|
10
|
+
const settings = ctx.settings.register('dsh-autopilot-ntfy-notification', ntfyNotificationSettingsSchema, {
|
|
11
|
+
validate: validateNtfySettings,
|
|
12
|
+
});
|
|
13
|
+
await ctx.effect(async () => {
|
|
14
|
+
let snapshot = structuredClone(settings.get());
|
|
15
|
+
let dispose = ctx.notifications.register(createNtfyProvider(ctx, snapshot));
|
|
16
|
+
let queue = Promise.resolve();
|
|
17
|
+
const stop = settings.watch((next) => {
|
|
18
|
+
if (isDeepStrictEqual(snapshot, next))
|
|
19
|
+
return;
|
|
20
|
+
queue = queue.then(async () => {
|
|
21
|
+
await dispose();
|
|
22
|
+
snapshot = structuredClone(next);
|
|
23
|
+
dispose = ctx.notifications.register(createNtfyProvider(ctx, snapshot));
|
|
24
|
+
});
|
|
25
|
+
return queue;
|
|
26
|
+
});
|
|
27
|
+
return async () => {
|
|
28
|
+
stop();
|
|
29
|
+
await queue;
|
|
30
|
+
await dispose();
|
|
31
|
+
};
|
|
32
|
+
}, 'dsh-autopilot-ntfy-notification.provider');
|
|
33
|
+
}
|
|
34
|
+
function createNtfyProvider(ctx, config) {
|
|
35
|
+
validateNtfySettings(config);
|
|
36
|
+
return {
|
|
37
|
+
id: notificationProviderId('ntfy'),
|
|
38
|
+
interfaceVersion: NOTIFICATION_INTERFACE_VERSION,
|
|
39
|
+
displayName: 'ntfy',
|
|
40
|
+
configurationNamespace: 'dsh-autopilot-ntfy-notification',
|
|
41
|
+
reconcile: () => Promise.resolve(undefined),
|
|
42
|
+
async deliver({ destinationId, event, signal }) {
|
|
43
|
+
const destination = config.destinations.find((candidate) => candidate.id === destinationId);
|
|
44
|
+
if (destination === undefined) {
|
|
45
|
+
throw new NotificationProviderError('invalid-configuration', 'ntfy destination is not configured');
|
|
46
|
+
}
|
|
47
|
+
const auth = await authorizationHeader(ctx, destination.tokenCredentialRef);
|
|
48
|
+
signal.throwIfAborted();
|
|
49
|
+
const { text } = await postNotification({ url: destination.serverUrl, authorizationCredentialRef: destination.tokenCredentialRef }, JSON.stringify({
|
|
50
|
+
topic: destination.topic,
|
|
51
|
+
title: `${event.displayKey}: ${event.type}`,
|
|
52
|
+
message: ntfyMessage(event),
|
|
53
|
+
click: event.pullRequestUrl ?? event.runUrl,
|
|
54
|
+
actions: [{ action: 'view', label: 'Open run', url: event.runUrl }],
|
|
55
|
+
}), { 'content-type': 'application/json', 'x-autopilot-event-id': event.eventId, ...auth }, config.timeoutMs, signal, 'bounded');
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = responseSchema.parse(JSON.parse(text));
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
throw new NotificationProviderError('invalid-response', 'ntfy returned an invalid acknowledgement');
|
|
62
|
+
}
|
|
63
|
+
const receivedAt = new Date(parsed.time * 1_000);
|
|
64
|
+
if (Number.isNaN(receivedAt.getTime())) {
|
|
65
|
+
throw new NotificationProviderError('invalid-response', 'ntfy returned an invalid acknowledgement time');
|
|
66
|
+
}
|
|
67
|
+
return { receiptId: `ntfy:${parsed.id}`, receivedAt: receivedAt.toISOString() };
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function ntfyMessage(event) {
|
|
72
|
+
const lines = [
|
|
73
|
+
`Autopilot notification v${String(event.version)}`,
|
|
74
|
+
event.summary,
|
|
75
|
+
`Event: ${event.eventId}`,
|
|
76
|
+
`Run: ${event.runId} ${event.runUrl}`,
|
|
77
|
+
`Issue: ${event.issueIdentity} (${event.displayKey}) ${event.issueUrl}`,
|
|
78
|
+
`Type: ${event.type}`,
|
|
79
|
+
...(event.actionNeeded === undefined ? [] : [`Action needed: ${event.actionNeeded}`]),
|
|
80
|
+
...(event.pullRequestUrl === undefined ? [] : [`Pull request: ${event.pullRequestUrl}`]),
|
|
81
|
+
`Usage: ${event.usage.kind}${event.usage.tokens === undefined ? '' : ` ${String(event.usage.tokens)} tokens`}`,
|
|
82
|
+
];
|
|
83
|
+
const message = lines.join('\n');
|
|
84
|
+
if (new TextEncoder().encode(message).byteLength > 4_096) {
|
|
85
|
+
throw new NotificationProviderError('permanent-rejection', 'ntfy notification exceeds its payload bound');
|
|
86
|
+
}
|
|
87
|
+
return message;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/providers/ntfy-notification/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import s from '@deepseek-ai/schemastery';
|
|
2
|
+
export interface NtfyNotificationSettings {
|
|
3
|
+
destinations: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
serverUrl: string;
|
|
6
|
+
topic: string;
|
|
7
|
+
tokenCredentialRef: string;
|
|
8
|
+
}>;
|
|
9
|
+
timeoutMs: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const ntfyNotificationSettingsSchema: s<NtfyNotificationSettings>;
|
|
12
|
+
export declare function validateNtfySettings(config: NtfyNotificationSettings): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
2
|
+
import s from '@deepseek-ai/schemastery';
|
|
3
|
+
import { notificationDestinationId } from '../../notification.js';
|
|
4
|
+
import { validateDestinationUrl } from '../notification-http.js';
|
|
5
|
+
export const ntfyNotificationSettingsSchema = s.object({
|
|
6
|
+
destinations: s
|
|
7
|
+
.array(s.object({
|
|
8
|
+
id: s.string().required(),
|
|
9
|
+
serverUrl: s.string().required(),
|
|
10
|
+
topic: s.string().required(),
|
|
11
|
+
tokenCredentialRef: s.string().default(''),
|
|
12
|
+
}))
|
|
13
|
+
.default([]),
|
|
14
|
+
timeoutMs: s.number().min(1_000).max(30_000).default(10_000),
|
|
15
|
+
});
|
|
16
|
+
export function validateNtfySettings(config) {
|
|
17
|
+
if (!Number.isInteger(config.timeoutMs))
|
|
18
|
+
throw new TypeError('ntfy timeout must be an integer');
|
|
19
|
+
if (config.destinations.length > 32)
|
|
20
|
+
throw new TypeError('ntfy destinations exceed the configured bound');
|
|
21
|
+
const ids = new Set();
|
|
22
|
+
for (const destination of config.destinations) {
|
|
23
|
+
notificationDestinationId(destination.id);
|
|
24
|
+
if (ids.has(destination.id))
|
|
25
|
+
throw new TypeError('ntfy destination ids must be unique');
|
|
26
|
+
ids.add(destination.id);
|
|
27
|
+
validateDestinationUrl(destination.serverUrl, 'ntfy server URL');
|
|
28
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(destination.topic))
|
|
29
|
+
throw new TypeError('ntfy topic is invalid');
|
|
30
|
+
if (destination.tokenCredentialRef !== '')
|
|
31
|
+
credentialRef(destination.tokenCredentialRef);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/providers/ntfy-notification/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAOhE,MAAM,CAAC,MAAM,8BAA8B,GAAgC,CAAC,CAAC,MAAM,CAAC;IAClF,YAAY,EAAE,CAAC;SACZ,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;QACP,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KAC3C,CAAC,CACH;SACA,OAAO,CAAC,EAAE,CAAC;IACd,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;CAC7D,CAAC,CAAA;AAEF,MAAM,UAAU,oBAAoB,CAAC,MAAgC;IACnE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,iCAAiC,CAAC,CAAA;IAC/F,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAA;IACzG,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QAC9C,yBAAyB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QACzC,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAA;QACvF,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QACvB,sBAAsB,CAAC,WAAW,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAA;QAChE,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,CAAC,CAAA;QAClG,IAAI,WAAW,CAAC,kBAAkB,KAAK,EAAE;YAAE,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAA;IAC1F,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/providers/webhook-notification/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
2
|
+
import { NOTIFICATION_INTERFACE_VERSION, NotificationProviderError, notificationProviderId, } from '../../notification.js';
|
|
3
|
+
import { acknowledgedReceipt, authorizationHeader, postNotification } from '../notification-http.js';
|
|
4
|
+
import { validateWebhookSettings, webhookNotificationSettingsSchema, } from './settings.js';
|
|
5
|
+
export const name = 'dsh-autopilot-webhook-notification';
|
|
6
|
+
export const inject = ['notifications', 'settings', 'credentials'];
|
|
7
|
+
export async function apply(ctx) {
|
|
8
|
+
const settings = ctx.settings.register('dsh-autopilot-webhook-notification', webhookNotificationSettingsSchema, {
|
|
9
|
+
validate: validateWebhookSettings,
|
|
10
|
+
});
|
|
11
|
+
await ctx.effect(async () => {
|
|
12
|
+
let snapshot = structuredClone(settings.get());
|
|
13
|
+
let dispose = ctx.notifications.register(createWebhookProvider(ctx, snapshot));
|
|
14
|
+
let queue = Promise.resolve();
|
|
15
|
+
const stop = settings.watch((next) => {
|
|
16
|
+
if (isDeepStrictEqual(snapshot, next))
|
|
17
|
+
return;
|
|
18
|
+
queue = queue.then(async () => {
|
|
19
|
+
await dispose();
|
|
20
|
+
snapshot = structuredClone(next);
|
|
21
|
+
dispose = ctx.notifications.register(createWebhookProvider(ctx, snapshot));
|
|
22
|
+
});
|
|
23
|
+
return queue;
|
|
24
|
+
});
|
|
25
|
+
return async () => {
|
|
26
|
+
stop();
|
|
27
|
+
await queue;
|
|
28
|
+
await dispose();
|
|
29
|
+
};
|
|
30
|
+
}, 'dsh-autopilot-webhook-notification.provider');
|
|
31
|
+
}
|
|
32
|
+
function createWebhookProvider(ctx, config) {
|
|
33
|
+
validateWebhookSettings(config);
|
|
34
|
+
return {
|
|
35
|
+
id: notificationProviderId('webhook'),
|
|
36
|
+
interfaceVersion: NOTIFICATION_INTERFACE_VERSION,
|
|
37
|
+
displayName: 'Generic webhook',
|
|
38
|
+
configurationNamespace: 'dsh-autopilot-webhook-notification',
|
|
39
|
+
reconcile: () => Promise.resolve(undefined),
|
|
40
|
+
async deliver({ destinationId, event, signal }) {
|
|
41
|
+
const destination = config.destinations.find((candidate) => candidate.id === destinationId);
|
|
42
|
+
if (destination === undefined) {
|
|
43
|
+
throw new NotificationProviderError('invalid-configuration', 'webhook destination is not configured');
|
|
44
|
+
}
|
|
45
|
+
const auth = await authorizationHeader(ctx, destination.authorizationCredentialRef);
|
|
46
|
+
signal.throwIfAborted();
|
|
47
|
+
const { response } = await postNotification(destination, JSON.stringify(event), {
|
|
48
|
+
'content-type': 'application/json',
|
|
49
|
+
'x-autopilot-event-id': event.eventId,
|
|
50
|
+
'idempotency-key': event.eventId,
|
|
51
|
+
...auth,
|
|
52
|
+
}, config.timeoutMs, signal, 'ignore');
|
|
53
|
+
return acknowledgedReceipt('webhook', event.eventId, response);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/providers/webhook-notification/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import s from '@deepseek-ai/schemastery';
|
|
2
|
+
export interface WebhookNotificationSettings {
|
|
3
|
+
destinations: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
url: string;
|
|
6
|
+
authorizationCredentialRef: string;
|
|
7
|
+
}>;
|
|
8
|
+
timeoutMs: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const webhookNotificationSettingsSchema: s<WebhookNotificationSettings>;
|
|
11
|
+
export declare function validateWebhookSettings(config: WebhookNotificationSettings): void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { credentialRef } from '@deepseek-ai/dsh-credentials';
|
|
2
|
+
import s from '@deepseek-ai/schemastery';
|
|
3
|
+
import { notificationDestinationId } from '../../notification.js';
|
|
4
|
+
import { validateDestinationUrl } from '../notification-http.js';
|
|
5
|
+
export const webhookNotificationSettingsSchema = s.object({
|
|
6
|
+
destinations: s
|
|
7
|
+
.array(s.object({
|
|
8
|
+
id: s.string().required(),
|
|
9
|
+
url: s.string().required(),
|
|
10
|
+
authorizationCredentialRef: s.string().default(''),
|
|
11
|
+
}))
|
|
12
|
+
.default([]),
|
|
13
|
+
timeoutMs: s.number().min(1_000).max(30_000).default(10_000),
|
|
14
|
+
});
|
|
15
|
+
export function validateWebhookSettings(config) {
|
|
16
|
+
if (!Number.isInteger(config.timeoutMs))
|
|
17
|
+
throw new TypeError('webhook timeout must be an integer');
|
|
18
|
+
if (config.destinations.length > 32)
|
|
19
|
+
throw new TypeError('webhook destinations exceed the configured bound');
|
|
20
|
+
const ids = new Set();
|
|
21
|
+
for (const destination of config.destinations) {
|
|
22
|
+
notificationDestinationId(destination.id);
|
|
23
|
+
if (ids.has(destination.id))
|
|
24
|
+
throw new TypeError('webhook destination ids must be unique');
|
|
25
|
+
ids.add(destination.id);
|
|
26
|
+
validateDestinationUrl(destination.url, 'webhook destination URL');
|
|
27
|
+
if (destination.authorizationCredentialRef !== '')
|
|
28
|
+
credentialRef(destination.authorizationCredentialRef);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=settings.js.map
|