reqon-dsl 0.2.0 → 0.4.0
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/CHANGELOG.md +7 -0
- package/README.md +45 -3
- package/dist/ast/nodes.d.ts +91 -4
- package/dist/ast/nodes.js +14 -0
- package/dist/auth/circuit-breaker.d.ts +11 -0
- package/dist/auth/circuit-breaker.js +90 -18
- package/dist/auth/credentials.d.ts +6 -1
- package/dist/auth/credentials.js +12 -4
- package/dist/auth/oauth2-provider.js +13 -3
- package/dist/auth/rate-limiter.d.ts +12 -1
- package/dist/auth/rate-limiter.js +39 -26
- package/dist/auth/token-store.js +8 -1
- package/dist/cli.d.ts +24 -1
- package/dist/cli.js +149 -10
- package/dist/config/constants.d.ts +152 -0
- package/dist/config/constants.js +139 -0
- package/dist/config/index.d.ts +4 -0
- package/dist/config/index.js +4 -0
- package/dist/control/index.d.ts +2 -0
- package/dist/control/index.js +1 -0
- package/dist/control/server.d.ts +105 -0
- package/dist/control/server.js +315 -0
- package/dist/control/types.d.ts +61 -0
- package/dist/control/types.js +7 -0
- package/dist/debug/cli-debugger.d.ts +17 -0
- package/dist/debug/cli-debugger.js +185 -0
- package/dist/debug/controller.d.ts +94 -0
- package/dist/debug/controller.js +45 -0
- package/dist/debug/index.d.ts +6 -0
- package/dist/debug/index.js +5 -0
- package/dist/errors/index.d.ts +67 -0
- package/dist/errors/index.js +89 -1
- package/dist/execution/index.d.ts +1 -1
- package/dist/execution/state.d.ts +24 -0
- package/dist/execution/store.js +2 -2
- package/dist/execution-log/events.d.ts +125 -0
- package/dist/execution-log/events.js +17 -0
- package/dist/execution-log/fold.d.ts +38 -0
- package/dist/execution-log/fold.js +54 -0
- package/dist/execution-log/index.d.ts +18 -0
- package/dist/execution-log/index.js +6 -0
- package/dist/execution-log/postgres-store.d.ts +36 -0
- package/dist/execution-log/postgres-store.js +108 -0
- package/dist/execution-log/resume.d.ts +11 -0
- package/dist/execution-log/resume.js +5 -0
- package/dist/execution-log/sqlite-store.d.ts +16 -0
- package/dist/execution-log/sqlite-store.js +101 -0
- package/dist/execution-log/store.d.ts +72 -0
- package/dist/execution-log/store.js +182 -0
- package/dist/index.d.ts +23 -2
- package/dist/index.js +35 -3
- package/dist/interpreter/context.d.ts +29 -0
- package/dist/interpreter/context.js +18 -0
- package/dist/interpreter/evaluator.d.ts +63 -1
- package/dist/interpreter/evaluator.js +219 -42
- package/dist/interpreter/executor.d.ts +132 -14
- package/dist/interpreter/executor.js +883 -178
- package/dist/interpreter/fetch-handler.d.ts +48 -1
- package/dist/interpreter/fetch-handler.js +216 -38
- package/dist/interpreter/http.d.ts +34 -0
- package/dist/interpreter/http.js +203 -28
- package/dist/interpreter/index.d.ts +5 -3
- package/dist/interpreter/index.js +4 -2
- package/dist/interpreter/pagination.d.ts +12 -3
- package/dist/interpreter/pagination.js +102 -32
- package/dist/interpreter/signals.d.ts +8 -0
- package/dist/interpreter/signals.js +12 -0
- package/dist/interpreter/source-manager.d.ts +75 -0
- package/dist/interpreter/source-manager.js +157 -0
- package/dist/interpreter/step-handlers/apply-handler.d.ts +29 -0
- package/dist/interpreter/step-handlers/apply-handler.js +79 -0
- package/dist/interpreter/step-handlers/for-handler.d.ts +16 -0
- package/dist/interpreter/step-handlers/for-handler.js +89 -7
- package/dist/interpreter/step-handlers/index.d.ts +4 -2
- package/dist/interpreter/step-handlers/index.js +4 -2
- package/dist/interpreter/step-handlers/match-handler.d.ts +9 -0
- package/dist/interpreter/step-handlers/match-handler.js +47 -17
- package/dist/interpreter/step-handlers/pause-handler.d.ts +52 -0
- package/dist/interpreter/step-handlers/pause-handler.js +87 -0
- package/dist/interpreter/step-handlers/store-handler.d.ts +17 -1
- package/dist/interpreter/step-handlers/store-handler.js +61 -20
- package/dist/interpreter/step-handlers/types.d.ts +3 -0
- package/dist/interpreter/step-handlers/validate-handler.d.ts +2 -1
- package/dist/interpreter/step-handlers/validate-handler.js +7 -2
- package/dist/interpreter/step-handlers/webhook-handler.d.ts +4 -0
- package/dist/interpreter/step-handlers/webhook-handler.js +31 -5
- package/dist/interpreter/store-manager.d.ts +46 -0
- package/dist/interpreter/store-manager.js +70 -0
- package/dist/lexer/index.d.ts +11 -4
- package/dist/lexer/index.js +11 -4
- package/dist/lexer/tokens.d.ts +17 -1
- package/dist/lexer/tokens.js +36 -0
- package/dist/loader/index.js +5 -8
- package/dist/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/sandbox.d.ts +41 -0
- package/dist/mcp/sandbox.js +76 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.js +504 -0
- package/dist/oas/index.d.ts +2 -0
- package/dist/oas/index.js +1 -0
- package/dist/oas/loader.d.ts +13 -1
- package/dist/oas/loader.js +25 -3
- package/dist/oas/mock-generator.d.ts +12 -0
- package/dist/oas/mock-generator.js +196 -0
- package/dist/oas/validator.js +45 -5
- package/dist/observability/events.d.ts +248 -0
- package/dist/observability/events.js +85 -0
- package/dist/observability/index.d.ts +15 -0
- package/dist/observability/index.js +12 -0
- package/dist/observability/logger.d.ts +106 -0
- package/dist/observability/logger.js +266 -0
- package/dist/observability/otel.d.ts +143 -0
- package/dist/observability/otel.js +421 -0
- package/dist/parser/action-parser.d.ts +105 -0
- package/dist/parser/action-parser.js +645 -0
- package/dist/parser/base.d.ts +7 -0
- package/dist/parser/base.js +11 -0
- package/dist/parser/expressions.d.ts +14 -0
- package/dist/parser/expressions.js +89 -6
- package/dist/parser/fetch-parser.d.ts +27 -0
- package/dist/parser/fetch-parser.js +280 -0
- package/dist/parser/index.d.ts +17 -0
- package/dist/parser/index.js +17 -0
- package/dist/parser/parser.d.ts +44 -46
- package/dist/parser/parser.js +122 -1070
- package/dist/parser/pipeline-parser.d.ts +12 -0
- package/dist/parser/pipeline-parser.js +52 -0
- package/dist/parser/schedule-parser.d.ts +7 -0
- package/dist/parser/schedule-parser.js +137 -0
- package/dist/parser/source-parser.d.ts +9 -0
- package/dist/parser/source-parser.js +151 -0
- package/dist/pause/index.d.ts +15 -0
- package/dist/pause/index.js +12 -0
- package/dist/pause/log-store.d.ts +33 -0
- package/dist/pause/log-store.js +98 -0
- package/dist/pause/manager.d.ts +130 -0
- package/dist/pause/manager.js +294 -0
- package/dist/pause/state.d.ts +93 -0
- package/dist/pause/state.js +103 -0
- package/dist/pause/store.d.ts +61 -0
- package/dist/pause/store.js +158 -0
- package/dist/plugin.d.ts +9 -12
- package/dist/plugin.js +10 -13
- package/dist/scheduler/cron-parser.d.ts +10 -3
- package/dist/scheduler/cron-parser.js +227 -48
- package/dist/scheduler/scheduler.js +56 -22
- package/dist/stores/factory.d.ts +7 -1
- package/dist/stores/factory.js +14 -3
- package/dist/stores/file.d.ts +26 -0
- package/dist/stores/file.js +67 -21
- package/dist/stores/index.d.ts +16 -1
- package/dist/stores/index.js +16 -1
- package/dist/stores/memory.d.ts +4 -0
- package/dist/stores/memory.js +8 -6
- package/dist/stores/postgrest.d.ts +28 -0
- package/dist/stores/postgrest.js +84 -37
- package/dist/stores/types.d.ts +17 -0
- package/dist/stores/types.js +12 -0
- package/dist/sync/index.d.ts +3 -2
- package/dist/sync/index.js +2 -1
- package/dist/sync/log-store.d.ts +30 -0
- package/dist/sync/log-store.js +45 -0
- package/dist/sync/store.js +1 -1
- package/dist/trace/index.d.ts +18 -0
- package/dist/trace/index.js +13 -0
- package/dist/trace/log-view.d.ts +57 -0
- package/dist/trace/log-view.js +76 -0
- package/dist/trace/recorder.d.ts +75 -0
- package/dist/trace/recorder.js +157 -0
- package/dist/trace/replay.d.ts +132 -0
- package/dist/trace/replay.js +264 -0
- package/dist/trace/state.d.ts +102 -0
- package/dist/trace/state.js +86 -0
- package/dist/trace/store.d.ts +75 -0
- package/dist/trace/store.js +250 -0
- package/dist/utils/deep-merge.d.ts +10 -0
- package/dist/utils/deep-merge.js +23 -0
- package/dist/utils/file.d.ts +13 -4
- package/dist/utils/file.js +70 -12
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/long-timeout.d.ts +19 -0
- package/dist/utils/long-timeout.js +33 -0
- package/dist/utils/path.d.ts +22 -1
- package/dist/utils/path.js +46 -1
- package/dist/utils/redact.d.ts +22 -0
- package/dist/utils/redact.js +42 -0
- package/dist/utils/type-guards.d.ts +58 -0
- package/dist/utils/type-guards.js +92 -0
- package/dist/webhook/server.d.ts +9 -0
- package/dist/webhook/server.js +122 -36
- package/dist/webhook/types.d.ts +9 -1
- package/package.json +76 -9
- package/.claude/settings.local.json +0 -31
- package/.claude/skills/api-integration.md +0 -125
- package/.claude/skills/database-schema.md +0 -51
- package/.claude/skills/dsl-design.md +0 -80
- package/.claude/skills/property-testing.md +0 -143
- package/.claude/skills/reqon/SKILL.md +0 -44
- package/.claude/skills/reqon/references/examples.md +0 -206
- package/.claude/skills/reqon/references/syntax.md +0 -263
- package/.claude/skills/vscode-extension.md +0 -113
- package/.github/dependabot.yml +0 -32
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/ci.yml +0 -174
- package/.github/workflows/release.yml +0 -73
- package/CLAUDE.md +0 -72
- package/CONTRIBUTING.md +0 -161
- package/TODO.md +0 -51
- package/dist/auth/auth.test.d.ts +0 -1
- package/dist/auth/auth.test.js +0 -255
- package/dist/errors/errors.test.d.ts +0 -1
- package/dist/errors/errors.test.js +0 -165
- package/dist/execution/execution.test.d.ts +0 -1
- package/dist/execution/execution.test.js +0 -246
- package/dist/integration.test.d.ts +0 -1
- package/dist/integration.test.js +0 -168
- package/dist/interpreter/evaluator.test.d.ts +0 -1
- package/dist/interpreter/evaluator.test.js +0 -512
- package/dist/interpreter/http.test.d.ts +0 -1
- package/dist/interpreter/http.test.js +0 -299
- package/dist/interpreter/progress.test.d.ts +0 -1
- package/dist/interpreter/progress.test.js +0 -216
- package/dist/interpreter/schema-matcher.test.d.ts +0 -1
- package/dist/interpreter/schema-matcher.test.js +0 -122
- package/dist/lexer/lexer.d.ts +0 -24
- package/dist/lexer/lexer.js +0 -264
- package/dist/lexer/lexer.test.d.ts +0 -1
- package/dist/lexer/lexer.test.js +0 -259
- package/dist/loader/loader.test.d.ts +0 -1
- package/dist/loader/loader.test.js +0 -287
- package/dist/oas/oas.test.d.ts +0 -1
- package/dist/oas/oas.test.js +0 -218
- package/dist/parser/expressions.test.d.ts +0 -1
- package/dist/parser/expressions.test.js +0 -378
- package/dist/parser/match.test.d.ts +0 -1
- package/dist/parser/match.test.js +0 -254
- package/dist/parser/parser.test.d.ts +0 -1
- package/dist/parser/parser.test.js +0 -333
- package/dist/parser/schedule.test.d.ts +0 -1
- package/dist/parser/schedule.test.js +0 -241
- package/dist/scheduler/cron-parser.test.d.ts +0 -1
- package/dist/scheduler/cron-parser.test.js +0 -188
- package/dist/stores/file.test.d.ts +0 -1
- package/dist/stores/file.test.js +0 -165
- package/dist/stores/memory.test.d.ts +0 -1
- package/dist/stores/memory.test.js +0 -157
- package/dist/stores/stores.test.d.ts +0 -1
- package/dist/stores/stores.test.js +0 -158
- package/dist/sync/sync.test.d.ts +0 -1
- package/dist/sync/sync.test.js +0 -221
- package/docusaurus/README.md +0 -41
- package/docusaurus/docs/advanced/execution-state.md +0 -283
- package/docusaurus/docs/advanced/extending-reqon.md +0 -388
- package/docusaurus/docs/advanced/multi-file-missions.md +0 -250
- package/docusaurus/docs/advanced/parallel-execution.md +0 -353
- package/docusaurus/docs/api-reference.md +0 -443
- package/docusaurus/docs/authentication/api-key.md +0 -339
- package/docusaurus/docs/authentication/basic.md +0 -276
- package/docusaurus/docs/authentication/bearer.md +0 -282
- package/docusaurus/docs/authentication/oauth2.md +0 -317
- package/docusaurus/docs/authentication/overview.md +0 -251
- package/docusaurus/docs/cli.md +0 -229
- package/docusaurus/docs/core-concepts/actions.md +0 -286
- package/docusaurus/docs/core-concepts/missions.md +0 -264
- package/docusaurus/docs/core-concepts/schemas.md +0 -353
- package/docusaurus/docs/core-concepts/sources.md +0 -339
- package/docusaurus/docs/core-concepts/stores.md +0 -332
- package/docusaurus/docs/dsl-syntax/expressions.md +0 -361
- package/docusaurus/docs/dsl-syntax/fetch.md +0 -293
- package/docusaurus/docs/dsl-syntax/for-loops.md +0 -324
- package/docusaurus/docs/dsl-syntax/map.md +0 -345
- package/docusaurus/docs/dsl-syntax/match.md +0 -387
- package/docusaurus/docs/dsl-syntax/pipelines.md +0 -397
- package/docusaurus/docs/dsl-syntax/validate.md +0 -401
- package/docusaurus/docs/error-handling/dead-letter-queues.md +0 -399
- package/docusaurus/docs/error-handling/flow-control.md +0 -337
- package/docusaurus/docs/error-handling/retry-strategies.md +0 -368
- package/docusaurus/docs/examples.md +0 -488
- package/docusaurus/docs/getting-started.md +0 -256
- package/docusaurus/docs/http/circuit-breaker.md +0 -401
- package/docusaurus/docs/http/incremental-sync.md +0 -394
- package/docusaurus/docs/http/pagination.md +0 -361
- package/docusaurus/docs/http/rate-limiting.md +0 -383
- package/docusaurus/docs/http/requests.md +0 -328
- package/docusaurus/docs/http/retry.md +0 -402
- package/docusaurus/docs/intro.md +0 -90
- package/docusaurus/docs/openapi/loading-specs.md +0 -305
- package/docusaurus/docs/openapi/operation-calls.md +0 -314
- package/docusaurus/docs/openapi/overview.md +0 -212
- package/docusaurus/docs/openapi/response-validation.md +0 -344
- package/docusaurus/docs/scheduling/cron.md +0 -305
- package/docusaurus/docs/scheduling/daemon-mode.md +0 -317
- package/docusaurus/docs/scheduling/intervals.md +0 -289
- package/docusaurus/docs/scheduling/overview.md +0 -231
- package/docusaurus/docs/stores/custom-adapters.md +0 -376
- package/docusaurus/docs/stores/file.md +0 -236
- package/docusaurus/docs/stores/memory.md +0 -193
- package/docusaurus/docs/stores/overview.md +0 -274
- package/docusaurus/docs/stores/postgrest.md +0 -316
- package/docusaurus/docusaurus.config.ts +0 -148
- package/docusaurus/package-lock.json +0 -18029
- package/docusaurus/package.json +0 -47
- package/docusaurus/sidebars.ts +0 -155
- package/docusaurus/src/components/HomepageFeatures/index.tsx +0 -105
- package/docusaurus/src/components/HomepageFeatures/styles.module.css +0 -12
- package/docusaurus/src/css/custom.css +0 -169
- package/docusaurus/src/pages/index.module.css +0 -48
- package/docusaurus/src/pages/index.tsx +0 -110
- package/docusaurus/src/pages/markdown-page.md +0 -7
- package/docusaurus/static/.nojekyll +0 -0
- package/docusaurus/static/img/docusaurus-social-card.jpg +0 -0
- package/docusaurus/static/img/docusaurus.png +0 -0
- package/docusaurus/static/img/favicon.ico +0 -0
- package/docusaurus/static/img/logo.svg +0 -10
- package/docusaurus/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docusaurus/static/img/undraw_docusaurus_react.svg +0 -170
- package/docusaurus/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docusaurus/tsconfig.json +0 -8
- package/examples/README.md +0 -112
- package/examples/error-handling/README.md +0 -150
- package/examples/error-handling/payment-processor.vague +0 -287
- package/examples/github-sync/README.md +0 -74
- package/examples/github-sync/fetch-issues.vague +0 -47
- package/examples/github-sync/fetch-prs.vague +0 -40
- package/examples/github-sync/mission.vague +0 -101
- package/examples/github-sync/normalize.vague +0 -70
- package/examples/jsonplaceholder/README.md +0 -28
- package/examples/jsonplaceholder/posts.vague +0 -48
- package/examples/petstore/README.md +0 -35
- package/examples/petstore/openapi.yaml +0 -97
- package/examples/petstore/sync.vague +0 -52
- package/examples/temporal-comparison/README.md +0 -297
- package/examples/temporal-comparison/reconciliation.vague +0 -355
- package/examples/temporal-comparison/temporal/activities/index.ts +0 -8
- package/examples/temporal-comparison/temporal/activities/shipstation.ts +0 -225
- package/examples/temporal-comparison/temporal/activities/shopify.ts +0 -257
- package/examples/temporal-comparison/temporal/activities/storage.ts +0 -198
- package/examples/temporal-comparison/temporal/activities/stripe.ts +0 -169
- package/examples/temporal-comparison/temporal/activities/validation.ts +0 -205
- package/examples/temporal-comparison/temporal/client/schedule.ts +0 -218
- package/examples/temporal-comparison/temporal/config/retry.ts +0 -63
- package/examples/temporal-comparison/temporal/types/index.ts +0 -129
- package/examples/temporal-comparison/temporal/workers/main.ts +0 -130
- package/examples/temporal-comparison/temporal/workflows/orderReconciliation.ts +0 -262
- package/examples/xero/README.md +0 -88
- package/examples/xero/invoices.vague +0 -189
- package/src/api-integration.test.ts +0 -954
- package/src/ast/index.ts +0 -1
- package/src/ast/nodes.ts +0 -310
- package/src/auth/auth.test.ts +0 -326
- package/src/auth/circuit-breaker.test.ts +0 -390
- package/src/auth/circuit-breaker.ts +0 -379
- package/src/auth/credentials.test.ts +0 -273
- package/src/auth/credentials.ts +0 -246
- package/src/auth/index.ts +0 -40
- package/src/auth/oauth2-provider.ts +0 -177
- package/src/auth/rate-limiter.ts +0 -459
- package/src/auth/token-store.ts +0 -177
- package/src/auth/types.ts +0 -159
- package/src/benchmark/e2e.bench.ts +0 -288
- package/src/benchmark/evaluator.bench.ts +0 -331
- package/src/benchmark/fixtures.ts +0 -295
- package/src/benchmark/index.ts +0 -108
- package/src/benchmark/lexer.bench.ts +0 -69
- package/src/benchmark/parser.bench.ts +0 -103
- package/src/benchmark/resilience.bench.ts +0 -193
- package/src/benchmark/store.bench.ts +0 -147
- package/src/benchmark/utils.ts +0 -230
- package/src/cli.ts +0 -313
- package/src/errors/errors.test.ts +0 -234
- package/src/errors/index.ts +0 -223
- package/src/execution/execution.test.ts +0 -307
- package/src/execution/index.ts +0 -21
- package/src/execution/state.ts +0 -207
- package/src/execution/store.ts +0 -188
- package/src/index.ts +0 -169
- package/src/integration.test.ts +0 -192
- package/src/interpreter/context.ts +0 -57
- package/src/interpreter/evaluator.test.ts +0 -796
- package/src/interpreter/evaluator.ts +0 -245
- package/src/interpreter/executor.ts +0 -946
- package/src/interpreter/fetch-handler.ts +0 -302
- package/src/interpreter/http.test.ts +0 -423
- package/src/interpreter/http.ts +0 -308
- package/src/interpreter/index.ts +0 -32
- package/src/interpreter/pagination.ts +0 -207
- package/src/interpreter/progress.test.ts +0 -276
- package/src/interpreter/schema-matcher.test.ts +0 -160
- package/src/interpreter/schema-matcher.ts +0 -168
- package/src/interpreter/signals.ts +0 -73
- package/src/interpreter/step-handlers/for-handler.ts +0 -65
- package/src/interpreter/step-handlers/index.ts +0 -17
- package/src/interpreter/step-handlers/map-handler.ts +0 -24
- package/src/interpreter/step-handlers/match-handler.ts +0 -101
- package/src/interpreter/step-handlers/store-handler.ts +0 -78
- package/src/interpreter/step-handlers/types.ts +0 -17
- package/src/interpreter/step-handlers/validate-handler.ts +0 -30
- package/src/interpreter/step-handlers/webhook-handler.ts +0 -142
- package/src/lexer/index.ts +0 -18
- package/src/lexer/lexer.test.ts +0 -316
- package/src/lexer/tokens.ts +0 -179
- package/src/loader/index.ts +0 -288
- package/src/loader/loader.test.ts +0 -360
- package/src/oas/index.ts +0 -4
- package/src/oas/loader.ts +0 -126
- package/src/oas/oas.test.ts +0 -254
- package/src/oas/validator.ts +0 -299
- package/src/parser/base.ts +0 -124
- package/src/parser/expressions.test.ts +0 -525
- package/src/parser/expressions.ts +0 -314
- package/src/parser/index.ts +0 -3
- package/src/parser/match.test.ts +0 -296
- package/src/parser/parser.test.ts +0 -739
- package/src/parser/parser.ts +0 -1469
- package/src/parser/schedule.test.ts +0 -287
- package/src/parser/webhook.test.ts +0 -248
- package/src/plugin.ts +0 -83
- package/src/scheduler/cron-parser.test.ts +0 -236
- package/src/scheduler/cron-parser.ts +0 -236
- package/src/scheduler/index.ts +0 -10
- package/src/scheduler/scheduler.ts +0 -443
- package/src/scheduler/types.ts +0 -71
- package/src/stores/factory.ts +0 -104
- package/src/stores/file.test.ts +0 -276
- package/src/stores/file.ts +0 -211
- package/src/stores/index.ts +0 -6
- package/src/stores/memory.test.ts +0 -238
- package/src/stores/memory.ts +0 -63
- package/src/stores/postgrest.test.ts +0 -488
- package/src/stores/postgrest.ts +0 -263
- package/src/stores/stores.test.ts +0 -197
- package/src/stores/types.ts +0 -58
- package/src/sync/index.ts +0 -16
- package/src/sync/state.ts +0 -126
- package/src/sync/store.ts +0 -139
- package/src/sync/sync.test.ts +0 -271
- package/src/utils/async.ts +0 -10
- package/src/utils/file.ts +0 -106
- package/src/utils/index.ts +0 -14
- package/src/utils/logger.ts +0 -53
- package/src/utils/path.ts +0 -47
- package/src/webhook/index.ts +0 -15
- package/src/webhook/server.test.ts +0 -253
- package/src/webhook/server.ts +0 -389
- package/src/webhook/store.ts +0 -239
- package/src/webhook/types.ts +0 -93
- package/tsconfig.json +0 -17
- package/vitest.config.ts +0 -39
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause Manager - Orchestrates resource-free long pauses
|
|
3
|
+
*
|
|
4
|
+
* Handles pause creation, monitoring, and resume coordination.
|
|
5
|
+
* Integrates with webhook server for webhook-based resume triggers.
|
|
6
|
+
*/
|
|
7
|
+
import { createPauseState, parseDuration, isPauseExpired, getRemainingTime, formatDuration, } from './state.js';
|
|
8
|
+
/**
|
|
9
|
+
* Manages resource-free long pauses
|
|
10
|
+
*/
|
|
11
|
+
export class PauseManager {
|
|
12
|
+
config;
|
|
13
|
+
pollTimer;
|
|
14
|
+
isRunning = false;
|
|
15
|
+
// Pause ids currently being resumed. Claimed synchronously before any await
|
|
16
|
+
// so a timeout poll and an inbound webhook can't both resume the same pause.
|
|
17
|
+
resuming = new Set();
|
|
18
|
+
// Prevents a slow resume cycle from overlapping the next poll tick.
|
|
19
|
+
isCheckingExpired = false;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a new pause and persist state
|
|
25
|
+
*/
|
|
26
|
+
async createPause(options) {
|
|
27
|
+
const duration = parseDuration(options.duration);
|
|
28
|
+
// Build resume trigger states
|
|
29
|
+
const resumeTriggers = [];
|
|
30
|
+
// Always include timeout by default
|
|
31
|
+
const triggers = options.resumeTriggers ?? [{ type: 'timeout' }];
|
|
32
|
+
const hasTimeout = triggers.some((t) => t.type === 'timeout');
|
|
33
|
+
if (!hasTimeout) {
|
|
34
|
+
triggers.push({ type: 'timeout' });
|
|
35
|
+
}
|
|
36
|
+
for (const trigger of triggers) {
|
|
37
|
+
if (trigger.type === 'timeout') {
|
|
38
|
+
resumeTriggers.push({ type: 'timeout', active: true });
|
|
39
|
+
}
|
|
40
|
+
else if (trigger.type === 'webhook') {
|
|
41
|
+
const triggerState = {
|
|
42
|
+
type: 'webhook',
|
|
43
|
+
path: trigger.path,
|
|
44
|
+
active: true,
|
|
45
|
+
};
|
|
46
|
+
// Register webhook if server available
|
|
47
|
+
if (this.config.webhookServer) {
|
|
48
|
+
const registration = await this.registerWebhookTrigger(options.executionId, trigger.path, duration);
|
|
49
|
+
triggerState.registrationId = registration.id;
|
|
50
|
+
}
|
|
51
|
+
resumeTriggers.push(triggerState);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Create pause state
|
|
55
|
+
const pause = createPauseState(options.executionId, options.mission, duration, options.checkpoint, resumeTriggers);
|
|
56
|
+
// Persist
|
|
57
|
+
await this.config.store.save(pause);
|
|
58
|
+
this.log(`Created pause ${pause.id} for ${formatDuration(duration)}`);
|
|
59
|
+
return pause;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resume a pause manually
|
|
63
|
+
*/
|
|
64
|
+
async resumeManually(pauseId) {
|
|
65
|
+
const pause = await this.config.store.load(pauseId);
|
|
66
|
+
if (!pause) {
|
|
67
|
+
throw new Error(`Pause not found: ${pauseId}`);
|
|
68
|
+
}
|
|
69
|
+
if (pause.status !== 'waiting') {
|
|
70
|
+
throw new Error(`Pause ${pauseId} is not waiting (status: ${pause.status})`);
|
|
71
|
+
}
|
|
72
|
+
const resumed = await this.markResumed(pause, 'manual');
|
|
73
|
+
if (!resumed) {
|
|
74
|
+
// Lost a race with another resume trigger; return the resolved state.
|
|
75
|
+
const current = await this.config.store.load(pauseId);
|
|
76
|
+
if (!current)
|
|
77
|
+
throw new Error(`Pause not found: ${pauseId}`);
|
|
78
|
+
return current;
|
|
79
|
+
}
|
|
80
|
+
return resumed;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resume a pause by execution ID
|
|
84
|
+
*/
|
|
85
|
+
async resumeByExecution(executionId) {
|
|
86
|
+
const pause = await this.config.store.loadByExecution(executionId);
|
|
87
|
+
if (!pause) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return this.resumeManually(pause.id);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Cancel a pause (without resuming execution)
|
|
94
|
+
*/
|
|
95
|
+
async cancelPause(pauseId) {
|
|
96
|
+
const pause = await this.config.store.load(pauseId);
|
|
97
|
+
if (!pause) {
|
|
98
|
+
throw new Error(`Pause not found: ${pauseId}`);
|
|
99
|
+
}
|
|
100
|
+
if (pause.status !== 'waiting') {
|
|
101
|
+
return; // Already not waiting
|
|
102
|
+
}
|
|
103
|
+
await this.config.store.update(pauseId, {
|
|
104
|
+
status: 'cancelled',
|
|
105
|
+
resumedAt: new Date(),
|
|
106
|
+
resumedBy: 'cancelled',
|
|
107
|
+
});
|
|
108
|
+
// Cleanup webhook registrations
|
|
109
|
+
await this.cleanupWebhooks(pause);
|
|
110
|
+
this.log(`Cancelled pause ${pauseId}`);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Handle webhook callback for a pause
|
|
114
|
+
*/
|
|
115
|
+
async handleWebhook(pauseId, payload) {
|
|
116
|
+
const pause = await this.config.store.load(pauseId);
|
|
117
|
+
if (!pause || pause.status !== 'waiting') {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
// Check if this pause has an active webhook trigger
|
|
121
|
+
const webhookTrigger = pause.resumeTriggers.find((t) => t.type === 'webhook' && t.active);
|
|
122
|
+
if (!webhookTrigger) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
// Mark resumed with webhook payload; false if another trigger won the race.
|
|
126
|
+
const resumed = await this.markResumed(pause, 'webhook', payload);
|
|
127
|
+
return resumed !== null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Start monitoring for expired pauses
|
|
131
|
+
*/
|
|
132
|
+
startMonitoring() {
|
|
133
|
+
if (this.isRunning)
|
|
134
|
+
return;
|
|
135
|
+
this.isRunning = true;
|
|
136
|
+
const interval = this.config.pollInterval ?? 60000; // Default: 1 minute
|
|
137
|
+
this.pollTimer = setInterval(async () => {
|
|
138
|
+
await this.checkExpiredPauses();
|
|
139
|
+
}, interval);
|
|
140
|
+
this.log(`Started pause monitoring (interval: ${formatDuration(interval)})`);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Stop monitoring
|
|
144
|
+
*/
|
|
145
|
+
stopMonitoring() {
|
|
146
|
+
if (this.pollTimer) {
|
|
147
|
+
clearInterval(this.pollTimer);
|
|
148
|
+
this.pollTimer = undefined;
|
|
149
|
+
}
|
|
150
|
+
this.isRunning = false;
|
|
151
|
+
this.log('Stopped pause monitoring');
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Check for and process expired pauses
|
|
155
|
+
*/
|
|
156
|
+
async checkExpiredPauses() {
|
|
157
|
+
// Overlap guard: if a prior cycle's resume callbacks are still running when
|
|
158
|
+
// the next poll fires, skip rather than reprocessing the same pauses.
|
|
159
|
+
if (this.isCheckingExpired)
|
|
160
|
+
return [];
|
|
161
|
+
this.isCheckingExpired = true;
|
|
162
|
+
try {
|
|
163
|
+
const expired = await this.config.store.findExpired();
|
|
164
|
+
const resumed = [];
|
|
165
|
+
for (const pause of expired) {
|
|
166
|
+
const updated = await this.markResumed(pause, 'timeout');
|
|
167
|
+
// null means another trigger already resumed this pause — skip it.
|
|
168
|
+
if (updated)
|
|
169
|
+
resumed.push(updated);
|
|
170
|
+
}
|
|
171
|
+
return resumed;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
this.isCheckingExpired = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get all active pauses
|
|
179
|
+
*/
|
|
180
|
+
async getActivePauses() {
|
|
181
|
+
return this.config.store.listActive();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get pause by ID
|
|
185
|
+
*/
|
|
186
|
+
async getPause(pauseId) {
|
|
187
|
+
return this.config.store.load(pauseId);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get pause status summary
|
|
191
|
+
*/
|
|
192
|
+
async getStatus() {
|
|
193
|
+
const active = await this.config.store.listActive();
|
|
194
|
+
const expired = active.filter((p) => isPauseExpired(p));
|
|
195
|
+
const waiting = active.filter((p) => !isPauseExpired(p));
|
|
196
|
+
return {
|
|
197
|
+
totalActive: active.length,
|
|
198
|
+
waiting: waiting.length,
|
|
199
|
+
expired: expired.length,
|
|
200
|
+
nextExpiration: waiting.length > 0
|
|
201
|
+
? waiting.reduce((min, p) => (p.expiresAt < min ? p.expiresAt : min), waiting[0].expiresAt)
|
|
202
|
+
: undefined,
|
|
203
|
+
pauses: active.map((p) => ({
|
|
204
|
+
id: p.id,
|
|
205
|
+
mission: p.mission,
|
|
206
|
+
executionId: p.executionId,
|
|
207
|
+
remaining: getRemainingTime(p),
|
|
208
|
+
remainingFormatted: formatDuration(getRemainingTime(p)),
|
|
209
|
+
})),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Transition a pause to `resumed` and fire `onResume` exactly once.
|
|
214
|
+
*
|
|
215
|
+
* Returns the resumed pause, or `null` if this call lost the race (another
|
|
216
|
+
* resume already claimed it, or it is no longer waiting). The claim on
|
|
217
|
+
* `this.resuming` is synchronous — taken before any `await` — so two
|
|
218
|
+
* concurrent callers (e.g. the timeout poller and an inbound webhook) can't
|
|
219
|
+
* both pass the status check and double-fire the side-effecting tail. The
|
|
220
|
+
* persisted-status re-check makes resume idempotent across poll cycles too.
|
|
221
|
+
*/
|
|
222
|
+
async markResumed(pause, resumedBy, webhookPayload) {
|
|
223
|
+
if (this.resuming.has(pause.id)) {
|
|
224
|
+
return null; // another resume is already in flight for this pause
|
|
225
|
+
}
|
|
226
|
+
this.resuming.add(pause.id);
|
|
227
|
+
try {
|
|
228
|
+
// Re-read the source of truth: a prior cycle may already have resumed it.
|
|
229
|
+
const current = await this.config.store.load(pause.id);
|
|
230
|
+
if (!current || current.status !== 'waiting') {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
const updates = {
|
|
234
|
+
status: 'resumed',
|
|
235
|
+
resumedAt: new Date(),
|
|
236
|
+
resumedBy,
|
|
237
|
+
};
|
|
238
|
+
if (webhookPayload !== undefined) {
|
|
239
|
+
updates.webhookPayload = webhookPayload;
|
|
240
|
+
}
|
|
241
|
+
await this.config.store.update(pause.id, updates);
|
|
242
|
+
// Cleanup webhook registrations
|
|
243
|
+
await this.cleanupWebhooks(current);
|
|
244
|
+
const updated = await this.config.store.load(pause.id);
|
|
245
|
+
if (!updated) {
|
|
246
|
+
throw new Error(`Failed to load updated pause: ${pause.id}`);
|
|
247
|
+
}
|
|
248
|
+
this.log(`Pause ${pause.id} resumed by ${resumedBy}`);
|
|
249
|
+
// Trigger callback (the side-effecting pipeline tail) exactly once.
|
|
250
|
+
if (this.config.onResume) {
|
|
251
|
+
await this.config.onResume(updated);
|
|
252
|
+
}
|
|
253
|
+
return updated;
|
|
254
|
+
}
|
|
255
|
+
finally {
|
|
256
|
+
this.resuming.delete(pause.id);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async registerWebhookTrigger(executionId, path, timeout) {
|
|
260
|
+
if (!this.config.webhookServer) {
|
|
261
|
+
throw new Error('Webhook server not configured for webhook triggers');
|
|
262
|
+
}
|
|
263
|
+
// Register a webhook listener that will call handleWebhook
|
|
264
|
+
const registration = await this.config.webhookServer.register(executionId, {
|
|
265
|
+
path,
|
|
266
|
+
timeout,
|
|
267
|
+
expectedEvents: 1,
|
|
268
|
+
});
|
|
269
|
+
return { id: registration.id };
|
|
270
|
+
}
|
|
271
|
+
async cleanupWebhooks(pause) {
|
|
272
|
+
if (!this.config.webhookServer)
|
|
273
|
+
return;
|
|
274
|
+
for (const trigger of pause.resumeTriggers) {
|
|
275
|
+
if (trigger.type === 'webhook' && trigger.registrationId) {
|
|
276
|
+
try {
|
|
277
|
+
await this.config.webhookServer.unregister(trigger.registrationId);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Ignore cleanup errors
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
log(message) {
|
|
286
|
+
this.config.log?.(`[PauseManager] ${message}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Create a pause manager
|
|
291
|
+
*/
|
|
292
|
+
export function createPauseManager(config) {
|
|
293
|
+
return new PauseManager(config);
|
|
294
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause State - Types for resource-free long pauses
|
|
3
|
+
*
|
|
4
|
+
* Supports pausing execution for extended periods (days/weeks)
|
|
5
|
+
* while persisting state and releasing resources.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Persisted pause state
|
|
9
|
+
*/
|
|
10
|
+
export interface PauseState {
|
|
11
|
+
/** Unique pause ID */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Execution ID this pause belongs to */
|
|
14
|
+
executionId: string;
|
|
15
|
+
/** Mission name */
|
|
16
|
+
mission: string;
|
|
17
|
+
/** When the pause started */
|
|
18
|
+
pausedAt: Date;
|
|
19
|
+
/** When the pause will expire (resume due to timeout) */
|
|
20
|
+
expiresAt: Date;
|
|
21
|
+
/** Original duration specified (in milliseconds) */
|
|
22
|
+
duration: number;
|
|
23
|
+
/** Current status */
|
|
24
|
+
status: 'waiting' | 'resumed' | 'expired' | 'cancelled';
|
|
25
|
+
/** How the pause was resumed (if resumed) */
|
|
26
|
+
resumedBy?: 'timeout' | 'webhook' | 'manual' | 'cancelled';
|
|
27
|
+
/** When resumed */
|
|
28
|
+
resumedAt?: Date;
|
|
29
|
+
/** Resume trigger configuration */
|
|
30
|
+
resumeTriggers: PauseResumeTriggerState[];
|
|
31
|
+
/** Checkpoint data for resuming execution */
|
|
32
|
+
checkpoint: PauseCheckpoint;
|
|
33
|
+
/** Webhook data if resumed by webhook */
|
|
34
|
+
webhookPayload?: unknown;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Resume trigger state
|
|
38
|
+
*/
|
|
39
|
+
export interface PauseResumeTriggerState {
|
|
40
|
+
type: 'timeout' | 'webhook';
|
|
41
|
+
/** For webhook: the registered path */
|
|
42
|
+
path?: string;
|
|
43
|
+
/** For webhook: registration ID */
|
|
44
|
+
registrationId?: string;
|
|
45
|
+
/** Whether this trigger is active */
|
|
46
|
+
active: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Checkpoint data for resuming after pause
|
|
50
|
+
*/
|
|
51
|
+
export interface PauseCheckpoint {
|
|
52
|
+
/** Stage index to resume from */
|
|
53
|
+
stageIndex: number;
|
|
54
|
+
/** Step index within action to resume from (after pause step) */
|
|
55
|
+
stepIndex: number;
|
|
56
|
+
/** Current action name */
|
|
57
|
+
action: string;
|
|
58
|
+
/** For loops: current item index */
|
|
59
|
+
itemIndex?: number;
|
|
60
|
+
/** Saved context variables */
|
|
61
|
+
variables: Record<string, unknown>;
|
|
62
|
+
/** Saved response value */
|
|
63
|
+
response?: unknown;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Generate a unique pause ID
|
|
67
|
+
*/
|
|
68
|
+
export declare function generatePauseId(executionId: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Parse duration string to milliseconds
|
|
71
|
+
* Supports: "7d", "1d", "12h", "30m", "45s", or raw milliseconds
|
|
72
|
+
*/
|
|
73
|
+
export declare function parseDuration(duration: string | number): number;
|
|
74
|
+
/**
|
|
75
|
+
* Format duration for display
|
|
76
|
+
*/
|
|
77
|
+
export declare function formatDuration(ms: number): string;
|
|
78
|
+
/**
|
|
79
|
+
* Create initial pause state
|
|
80
|
+
*/
|
|
81
|
+
export declare function createPauseState(executionId: string, mission: string, duration: number, checkpoint: PauseCheckpoint, resumeTriggers: PauseResumeTriggerState[]): PauseState;
|
|
82
|
+
/**
|
|
83
|
+
* Check if a pause has expired
|
|
84
|
+
*/
|
|
85
|
+
export declare function isPauseExpired(pause: PauseState): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Get remaining time for a pause (in milliseconds)
|
|
88
|
+
*/
|
|
89
|
+
export declare function getRemainingTime(pause: PauseState): number;
|
|
90
|
+
/**
|
|
91
|
+
* Get pause summary for display
|
|
92
|
+
*/
|
|
93
|
+
export declare function getPauseSummary(pause: PauseState): string;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause State - Types for resource-free long pauses
|
|
3
|
+
*
|
|
4
|
+
* Supports pausing execution for extended periods (days/weeks)
|
|
5
|
+
* while persisting state and releasing resources.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Generate a unique pause ID
|
|
9
|
+
*/
|
|
10
|
+
export function generatePauseId(executionId) {
|
|
11
|
+
const timestamp = Date.now().toString(36);
|
|
12
|
+
const random = Math.random().toString(36).substring(2, 6);
|
|
13
|
+
return `pause_${executionId}_${timestamp}_${random}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse duration string to milliseconds
|
|
17
|
+
* Supports: "7d", "1d", "12h", "30m", "45s", or raw milliseconds
|
|
18
|
+
*/
|
|
19
|
+
export function parseDuration(duration) {
|
|
20
|
+
if (typeof duration === 'number') {
|
|
21
|
+
return duration;
|
|
22
|
+
}
|
|
23
|
+
const match = duration.match(/^(\d+(?:\.\d+)?)\s*(d|h|m|s|ms)?$/i);
|
|
24
|
+
if (!match) {
|
|
25
|
+
throw new Error(`Invalid duration format: ${duration}. Use "7d", "12h", "30m", "45s", or milliseconds.`);
|
|
26
|
+
}
|
|
27
|
+
const value = parseFloat(match[1]);
|
|
28
|
+
const unit = (match[2] || 'ms').toLowerCase();
|
|
29
|
+
const multipliers = {
|
|
30
|
+
ms: 1,
|
|
31
|
+
s: 1000,
|
|
32
|
+
m: 60 * 1000,
|
|
33
|
+
h: 60 * 60 * 1000,
|
|
34
|
+
d: 24 * 60 * 60 * 1000,
|
|
35
|
+
};
|
|
36
|
+
const multiplier = multipliers[unit];
|
|
37
|
+
if (multiplier === undefined) {
|
|
38
|
+
throw new Error(`Unknown duration unit: ${unit}`);
|
|
39
|
+
}
|
|
40
|
+
return Math.round(value * multiplier);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Format duration for display
|
|
44
|
+
*/
|
|
45
|
+
export function formatDuration(ms) {
|
|
46
|
+
if (ms < 1000)
|
|
47
|
+
return `${ms}ms`;
|
|
48
|
+
if (ms < 60 * 1000)
|
|
49
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
50
|
+
if (ms < 60 * 60 * 1000)
|
|
51
|
+
return `${(ms / (60 * 1000)).toFixed(1)}m`;
|
|
52
|
+
if (ms < 24 * 60 * 60 * 1000)
|
|
53
|
+
return `${(ms / (60 * 60 * 1000)).toFixed(1)}h`;
|
|
54
|
+
return `${(ms / (24 * 60 * 60 * 1000)).toFixed(1)}d`;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create initial pause state
|
|
58
|
+
*/
|
|
59
|
+
export function createPauseState(executionId, mission, duration, checkpoint, resumeTriggers) {
|
|
60
|
+
const now = new Date();
|
|
61
|
+
return {
|
|
62
|
+
id: generatePauseId(executionId),
|
|
63
|
+
executionId,
|
|
64
|
+
mission,
|
|
65
|
+
pausedAt: now,
|
|
66
|
+
expiresAt: new Date(now.getTime() + duration),
|
|
67
|
+
duration,
|
|
68
|
+
status: 'waiting',
|
|
69
|
+
resumeTriggers,
|
|
70
|
+
checkpoint,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if a pause has expired
|
|
75
|
+
*/
|
|
76
|
+
export function isPauseExpired(pause) {
|
|
77
|
+
return pause.status === 'waiting' && new Date() >= pause.expiresAt;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get remaining time for a pause (in milliseconds)
|
|
81
|
+
*/
|
|
82
|
+
export function getRemainingTime(pause) {
|
|
83
|
+
if (pause.status !== 'waiting')
|
|
84
|
+
return 0;
|
|
85
|
+
const remaining = pause.expiresAt.getTime() - Date.now();
|
|
86
|
+
return Math.max(0, remaining);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get pause summary for display
|
|
90
|
+
*/
|
|
91
|
+
export function getPauseSummary(pause) {
|
|
92
|
+
const remaining = getRemainingTime(pause);
|
|
93
|
+
if (pause.status === 'resumed') {
|
|
94
|
+
return `Pause ${pause.id}: resumed by ${pause.resumedBy} at ${pause.resumedAt?.toISOString()}`;
|
|
95
|
+
}
|
|
96
|
+
if (pause.status === 'expired') {
|
|
97
|
+
return `Pause ${pause.id}: expired at ${pause.expiresAt.toISOString()}`;
|
|
98
|
+
}
|
|
99
|
+
if (pause.status === 'cancelled') {
|
|
100
|
+
return `Pause ${pause.id}: cancelled`;
|
|
101
|
+
}
|
|
102
|
+
return `Pause ${pause.id}: waiting (${formatDuration(remaining)} remaining)`;
|
|
103
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pause Store - Persistence for pause states
|
|
3
|
+
*
|
|
4
|
+
* Stores pause state for resource-free long pauses,
|
|
5
|
+
* enabling resumption after extended periods.
|
|
6
|
+
*/
|
|
7
|
+
import type { PauseState } from './state.js';
|
|
8
|
+
/**
|
|
9
|
+
* Pause store interface
|
|
10
|
+
*/
|
|
11
|
+
export interface PauseStore {
|
|
12
|
+
/** Save a pause state */
|
|
13
|
+
save(pause: PauseState): Promise<void>;
|
|
14
|
+
/** Load a pause by ID */
|
|
15
|
+
load(id: string): Promise<PauseState | null>;
|
|
16
|
+
/** Load pause by execution ID */
|
|
17
|
+
loadByExecution(executionId: string): Promise<PauseState | null>;
|
|
18
|
+
/** List all active (waiting) pauses */
|
|
19
|
+
listActive(): Promise<PauseState[]>;
|
|
20
|
+
/** List pauses for a mission */
|
|
21
|
+
listByMission(mission: string): Promise<PauseState[]>;
|
|
22
|
+
/** Delete a pause state */
|
|
23
|
+
delete(id: string): Promise<void>;
|
|
24
|
+
/** Find pauses that have expired but not yet processed */
|
|
25
|
+
findExpired(): Promise<PauseState[]>;
|
|
26
|
+
/** Update pause state (e.g., when resumed) */
|
|
27
|
+
update(id: string, updates: Partial<PauseState>): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* File-based pause store
|
|
31
|
+
*/
|
|
32
|
+
export declare class FilePauseStore implements PauseStore {
|
|
33
|
+
private baseDir;
|
|
34
|
+
private initialized;
|
|
35
|
+
constructor(baseDir?: string);
|
|
36
|
+
private getFilePath;
|
|
37
|
+
private deserialize;
|
|
38
|
+
save(pause: PauseState): Promise<void>;
|
|
39
|
+
load(id: string): Promise<PauseState | null>;
|
|
40
|
+
loadByExecution(executionId: string): Promise<PauseState | null>;
|
|
41
|
+
listActive(): Promise<PauseState[]>;
|
|
42
|
+
listByMission(mission: string): Promise<PauseState[]>;
|
|
43
|
+
delete(id: string): Promise<void>;
|
|
44
|
+
findExpired(): Promise<PauseState[]>;
|
|
45
|
+
update(id: string, updates: Partial<PauseState>): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* In-memory pause store (for testing)
|
|
49
|
+
*/
|
|
50
|
+
export declare class MemoryPauseStore implements PauseStore {
|
|
51
|
+
private pauses;
|
|
52
|
+
save(pause: PauseState): Promise<void>;
|
|
53
|
+
load(id: string): Promise<PauseState | null>;
|
|
54
|
+
loadByExecution(executionId: string): Promise<PauseState | null>;
|
|
55
|
+
listActive(): Promise<PauseState[]>;
|
|
56
|
+
listByMission(mission: string): Promise<PauseState[]>;
|
|
57
|
+
delete(id: string): Promise<void>;
|
|
58
|
+
findExpired(): Promise<PauseState[]>;
|
|
59
|
+
update(id: string, updates: Partial<PauseState>): Promise<void>;
|
|
60
|
+
clear(): void;
|
|
61
|
+
}
|