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
package/dist/stores/postgrest.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/** PostgREST query parameters that are operators/modifiers, not columns. */
|
|
2
|
+
const RESERVED_QUERY_KEYS = new Set([
|
|
3
|
+
'or',
|
|
4
|
+
'and',
|
|
5
|
+
'not',
|
|
6
|
+
'select',
|
|
7
|
+
'order',
|
|
8
|
+
'limit',
|
|
9
|
+
'offset',
|
|
10
|
+
'on_conflict',
|
|
11
|
+
'columns',
|
|
12
|
+
]);
|
|
13
|
+
/** A bare, safe column identifier: no operators, separators, or grouping. */
|
|
14
|
+
const SAFE_FIELD = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1
15
|
/**
|
|
2
16
|
* PostgREST-compatible store adapter.
|
|
3
17
|
* Works with Supabase, standalone PostgREST, or any PostgREST-compatible API.
|
|
@@ -16,26 +30,77 @@ export class PostgRESTStore {
|
|
|
16
30
|
baseUrl;
|
|
17
31
|
headers;
|
|
18
32
|
primaryKey;
|
|
33
|
+
timeoutMs;
|
|
19
34
|
constructor(options) {
|
|
20
35
|
this.options = options;
|
|
21
36
|
// Normalize URL (remove trailing slash)
|
|
22
37
|
const url = options.url.replace(/\/$/, '');
|
|
23
38
|
this.baseUrl = `${url}/${options.table}`;
|
|
24
39
|
this.primaryKey = options.primaryKey ?? 'id';
|
|
40
|
+
this.timeoutMs = options.timeoutMs ?? 30000;
|
|
25
41
|
this.headers = {
|
|
26
42
|
'Content-Type': 'application/json',
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
apikey: options.apiKey,
|
|
44
|
+
Authorization: `Bearer ${options.apiKey}`,
|
|
45
|
+
Prefer: 'return=representation',
|
|
30
46
|
};
|
|
31
47
|
if (options.schema) {
|
|
32
48
|
this.headers['Accept-Profile'] = options.schema;
|
|
33
49
|
this.headers['Content-Profile'] = options.schema;
|
|
34
50
|
}
|
|
35
51
|
}
|
|
52
|
+
/** fetch wrapper that aborts the request once {@link timeoutMs} elapses. */
|
|
53
|
+
async request(url, init) {
|
|
54
|
+
try {
|
|
55
|
+
return await fetch(url, { ...init, signal: AbortSignal.timeout(this.timeoutMs) });
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof DOMException && error.name === 'TimeoutError') {
|
|
59
|
+
throw new PostgRESTError(`Request timed out after ${this.timeoutMs}ms`, 0);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Reject a where-clause field unless it is a plain column identifier. This
|
|
66
|
+
* stops a key such as `or` or `id,or=(...)` from being concatenated into the
|
|
67
|
+
* query string and reinterpreted as a PostgREST operator.
|
|
68
|
+
*/
|
|
69
|
+
validateField(field) {
|
|
70
|
+
if (!SAFE_FIELD.test(field) || RESERVED_QUERY_KEYS.has(field.toLowerCase())) {
|
|
71
|
+
throw new PostgRESTError(`Unsafe filter field name: ${JSON.stringify(field)}`, 0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Render a where-clause value as a PostgREST operand. Strings containing
|
|
76
|
+
* reserved characters are wrapped in a quoted operand (with `"` and `\`
|
|
77
|
+
* escaped) so they can't be parsed as list/group syntax.
|
|
78
|
+
*/
|
|
79
|
+
formatFilterValue(value) {
|
|
80
|
+
if (value === null)
|
|
81
|
+
return 'is.null';
|
|
82
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
83
|
+
return `eq.${value}`;
|
|
84
|
+
if (typeof value === 'string') {
|
|
85
|
+
if (/[,.()"\\:]|\s/.test(value)) {
|
|
86
|
+
return `eq."${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
87
|
+
}
|
|
88
|
+
return `eq.${value}`;
|
|
89
|
+
}
|
|
90
|
+
// Complex values: JSON-encode, then quote as a string operand.
|
|
91
|
+
const json = JSON.stringify(value);
|
|
92
|
+
return `eq."${json.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
93
|
+
}
|
|
94
|
+
/** Append a validated, escaped where clause to the given params. */
|
|
95
|
+
applyWhere(params, where) {
|
|
96
|
+
for (const [field, value] of Object.entries(where)) {
|
|
97
|
+
this.validateField(field);
|
|
98
|
+
params.append(field, this.formatFilterValue(value));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
36
101
|
async get(key) {
|
|
37
102
|
const url = `${this.baseUrl}?${this.primaryKey}=eq.${encodeURIComponent(key)}&limit=1`;
|
|
38
|
-
const response = await
|
|
103
|
+
const response = await this.request(url, {
|
|
39
104
|
method: 'GET',
|
|
40
105
|
headers: this.headers,
|
|
41
106
|
});
|
|
@@ -48,11 +113,11 @@ export class PostgRESTStore {
|
|
|
48
113
|
async set(key, value) {
|
|
49
114
|
// Upsert using PostgREST's on_conflict resolution
|
|
50
115
|
const record = { ...value, [this.primaryKey]: key };
|
|
51
|
-
const response = await
|
|
116
|
+
const response = await this.request(this.baseUrl, {
|
|
52
117
|
method: 'POST',
|
|
53
118
|
headers: {
|
|
54
119
|
...this.headers,
|
|
55
|
-
|
|
120
|
+
Prefer: 'resolution=merge-duplicates,return=representation',
|
|
56
121
|
},
|
|
57
122
|
body: JSON.stringify(record),
|
|
58
123
|
});
|
|
@@ -63,7 +128,7 @@ export class PostgRESTStore {
|
|
|
63
128
|
}
|
|
64
129
|
async update(key, value) {
|
|
65
130
|
const url = `${this.baseUrl}?${this.primaryKey}=eq.${encodeURIComponent(key)}`;
|
|
66
|
-
const response = await
|
|
131
|
+
const response = await this.request(url, {
|
|
67
132
|
method: 'PATCH',
|
|
68
133
|
headers: this.headers,
|
|
69
134
|
body: JSON.stringify(value),
|
|
@@ -75,7 +140,7 @@ export class PostgRESTStore {
|
|
|
75
140
|
}
|
|
76
141
|
async delete(key) {
|
|
77
142
|
const url = `${this.baseUrl}?${this.primaryKey}=eq.${encodeURIComponent(key)}`;
|
|
78
|
-
const response = await
|
|
143
|
+
const response = await this.request(url, {
|
|
79
144
|
method: 'DELETE',
|
|
80
145
|
headers: this.headers,
|
|
81
146
|
});
|
|
@@ -88,21 +153,7 @@ export class PostgRESTStore {
|
|
|
88
153
|
const params = new URLSearchParams();
|
|
89
154
|
// Apply where clause
|
|
90
155
|
if (filter?.where) {
|
|
91
|
-
|
|
92
|
-
if (value === null) {
|
|
93
|
-
params.append(field, 'is.null');
|
|
94
|
-
}
|
|
95
|
-
else if (typeof value === 'string') {
|
|
96
|
-
params.append(field, `eq.${value}`);
|
|
97
|
-
}
|
|
98
|
-
else if (typeof value === 'number' || typeof value === 'boolean') {
|
|
99
|
-
params.append(field, `eq.${value}`);
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
// For complex values, try JSON
|
|
103
|
-
params.append(field, `eq.${JSON.stringify(value)}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
156
|
+
this.applyWhere(params, filter.where);
|
|
106
157
|
}
|
|
107
158
|
// Apply pagination
|
|
108
159
|
if (filter?.limit) {
|
|
@@ -113,7 +164,7 @@ export class PostgRESTStore {
|
|
|
113
164
|
}
|
|
114
165
|
const queryString = params.toString();
|
|
115
166
|
const url = queryString ? `${this.baseUrl}?${queryString}` : this.baseUrl;
|
|
116
|
-
const response = await
|
|
167
|
+
const response = await this.request(url, {
|
|
117
168
|
method: 'GET',
|
|
118
169
|
headers: this.headers,
|
|
119
170
|
});
|
|
@@ -124,10 +175,13 @@ export class PostgRESTStore {
|
|
|
124
175
|
return response.json();
|
|
125
176
|
}
|
|
126
177
|
async clear() {
|
|
178
|
+
if (!this.options.allowFullTableClear) {
|
|
179
|
+
throw new PostgRESTError('Refusing full-table delete: set allowFullTableClear to enable clear()', 0);
|
|
180
|
+
}
|
|
127
181
|
// Delete all records - PostgREST requires a filter, so we use a always-true condition
|
|
128
182
|
// This deletes where primary key is not null (i.e., all records)
|
|
129
183
|
const url = `${this.baseUrl}?${this.primaryKey}=not.is.null`;
|
|
130
|
-
const response = await
|
|
184
|
+
const response = await this.request(url, {
|
|
131
185
|
method: 'DELETE',
|
|
132
186
|
headers: this.headers,
|
|
133
187
|
});
|
|
@@ -142,11 +196,11 @@ export class PostgRESTStore {
|
|
|
142
196
|
async bulkInsert(records) {
|
|
143
197
|
if (records.length === 0)
|
|
144
198
|
return;
|
|
145
|
-
const response = await
|
|
199
|
+
const response = await this.request(this.baseUrl, {
|
|
146
200
|
method: 'POST',
|
|
147
201
|
headers: {
|
|
148
202
|
...this.headers,
|
|
149
|
-
|
|
203
|
+
Prefer: 'resolution=merge-duplicates',
|
|
150
204
|
},
|
|
151
205
|
body: JSON.stringify(records),
|
|
152
206
|
});
|
|
@@ -162,21 +216,14 @@ export class PostgRESTStore {
|
|
|
162
216
|
const params = new URLSearchParams();
|
|
163
217
|
params.append('select', 'count');
|
|
164
218
|
if (filter?.where) {
|
|
165
|
-
|
|
166
|
-
if (value === null) {
|
|
167
|
-
params.append(field, 'is.null');
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
params.append(field, `eq.${value}`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
219
|
+
this.applyWhere(params, filter.where);
|
|
173
220
|
}
|
|
174
221
|
const url = `${this.baseUrl}?${params.toString()}`;
|
|
175
|
-
const response = await
|
|
222
|
+
const response = await this.request(url, {
|
|
176
223
|
method: 'GET',
|
|
177
224
|
headers: {
|
|
178
225
|
...this.headers,
|
|
179
|
-
|
|
226
|
+
Prefer: 'count=exact',
|
|
180
227
|
},
|
|
181
228
|
});
|
|
182
229
|
if (!response.ok) {
|
package/dist/stores/types.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ---
|
|
3
|
+
* purpose: Store interface definitions - contract for all store adapters
|
|
4
|
+
* exports:
|
|
5
|
+
* - StoreAdapter - CRUD interface (get, set, update, delete, list, count)
|
|
6
|
+
* - StoreFilter - where/limit/offset for queries
|
|
7
|
+
* - StoreConfig - store type configuration
|
|
8
|
+
* related:
|
|
9
|
+
* - ./memory.ts, ./file.ts, ./postgrest.ts - implementations
|
|
10
|
+
* - ../interpreter/step-handlers/store-handler.ts - uses StoreAdapter
|
|
11
|
+
* ---
|
|
12
|
+
*/
|
|
1
13
|
export interface StoreAdapter {
|
|
2
14
|
get(key: string): Promise<Record<string, unknown> | null>;
|
|
3
15
|
set(key: string, value: Record<string, unknown>): Promise<void>;
|
|
@@ -6,6 +18,11 @@ export interface StoreAdapter {
|
|
|
6
18
|
key: string;
|
|
7
19
|
value: Record<string, unknown>;
|
|
8
20
|
}>): Promise<void>;
|
|
21
|
+
/** Bulk upsert multiple records at once - more efficient than individual updates */
|
|
22
|
+
bulkUpsert?(records: Array<{
|
|
23
|
+
key: string;
|
|
24
|
+
value: Record<string, unknown>;
|
|
25
|
+
}>): Promise<void>;
|
|
9
26
|
update(key: string, value: Partial<Record<string, unknown>>): Promise<void>;
|
|
10
27
|
delete(key: string): Promise<void>;
|
|
11
28
|
list(filter?: StoreFilter): Promise<Record<string, unknown>[]>;
|
package/dist/stores/types.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ---
|
|
3
|
+
* purpose: Store interface definitions - contract for all store adapters
|
|
4
|
+
* exports:
|
|
5
|
+
* - StoreAdapter - CRUD interface (get, set, update, delete, list, count)
|
|
6
|
+
* - StoreFilter - where/limit/offset for queries
|
|
7
|
+
* - StoreConfig - store type configuration
|
|
8
|
+
* related:
|
|
9
|
+
* - ./memory.ts, ./file.ts, ./postgrest.ts - implementations
|
|
10
|
+
* - ../interpreter/step-handlers/store-handler.ts - uses StoreAdapter
|
|
11
|
+
* ---
|
|
12
|
+
*/
|
|
1
13
|
/**
|
|
2
14
|
* Apply filter criteria to a list of records.
|
|
3
15
|
* Handles where clause, offset, and limit.
|
package/dist/sync/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type { SyncCheckpoint, SyncState, SinceResolution, SinceDateFormat
|
|
2
|
-
export { generateCheckpointKey, formatSinceDate, parseSinceDate, EPOCH
|
|
1
|
+
export type { SyncCheckpoint, SyncState, SinceResolution, SinceDateFormat } from './state.js';
|
|
2
|
+
export { generateCheckpointKey, formatSinceDate, parseSinceDate, EPOCH } from './state.js';
|
|
3
3
|
export type { SyncStore } from './store.js';
|
|
4
4
|
export { FileSyncStore, MemorySyncStore } from './store.js';
|
|
5
|
+
export { LogBackedSyncStore } from './log-store.js';
|
package/dist/sync/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { generateCheckpointKey, formatSinceDate, parseSinceDate, EPOCH
|
|
1
|
+
export { generateCheckpointKey, formatSinceDate, parseSinceDate, EPOCH } from './state.js';
|
|
2
2
|
export { FileSyncStore, MemorySyncStore } from './store.js';
|
|
3
|
+
export { LogBackedSyncStore } from './log-store.js';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log-backed sync store: incremental-sync checkpoints as a view over the
|
|
3
|
+
* execution log.
|
|
4
|
+
*
|
|
5
|
+
* In durable mode the execution log is the single source of truth — a sync's
|
|
6
|
+
* progress is recorded as a `checkpoint.advanced` event alongside everything
|
|
7
|
+
* else, so it survives a crash and resumes atomically with the run. This
|
|
8
|
+
* adapter reads `getLastSync`/checkpoint state back out of those events
|
|
9
|
+
* (newest-per-key, monotonic by `syncedAt`) instead of a separate sync file.
|
|
10
|
+
*
|
|
11
|
+
* Writes go through the log, not here: the executor appends `checkpoint.advanced`
|
|
12
|
+
* when a sync's fetched data is durably stored, so {@link recordSync} is a no-op.
|
|
13
|
+
*/
|
|
14
|
+
import type { ExecutionLogStore } from '../execution-log/index.js';
|
|
15
|
+
import type { SyncStore } from './store.js';
|
|
16
|
+
import type { SyncCheckpoint } from './state.js';
|
|
17
|
+
export declare class LogBackedSyncStore implements SyncStore {
|
|
18
|
+
private log;
|
|
19
|
+
private mission?;
|
|
20
|
+
constructor(log: ExecutionLogStore, mission?: string | undefined);
|
|
21
|
+
private checkpoint;
|
|
22
|
+
getLastSync(key: string): Promise<Date>;
|
|
23
|
+
getCheckpoint(key: string): Promise<SyncCheckpoint | null>;
|
|
24
|
+
list(): Promise<SyncCheckpoint[]>;
|
|
25
|
+
/** No-op: the log (via `checkpoint.advanced`) is the write path. */
|
|
26
|
+
recordSync(_checkpoint: SyncCheckpoint): Promise<void>;
|
|
27
|
+
/** Clearing a log-derived checkpoint isn't supported (the log is append-only). */
|
|
28
|
+
clear(): Promise<void>;
|
|
29
|
+
clearAll(): Promise<void>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { EPOCH } from './state.js';
|
|
2
|
+
export class LogBackedSyncStore {
|
|
3
|
+
log;
|
|
4
|
+
mission;
|
|
5
|
+
constructor(log, mission) {
|
|
6
|
+
this.log = log;
|
|
7
|
+
this.mission = mission;
|
|
8
|
+
}
|
|
9
|
+
async checkpoint(key) {
|
|
10
|
+
const records = await this.log.listCheckpoints(this.mission);
|
|
11
|
+
const record = records.find((r) => r.key === key);
|
|
12
|
+
if (!record)
|
|
13
|
+
return null;
|
|
14
|
+
return {
|
|
15
|
+
key: record.key,
|
|
16
|
+
syncedAt: new Date(record.syncedAt),
|
|
17
|
+
recordCount: record.recordCount,
|
|
18
|
+
cursor: record.cursor,
|
|
19
|
+
mission: record.mission,
|
|
20
|
+
executionId: record.executionId,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async getLastSync(key) {
|
|
24
|
+
return (await this.checkpoint(key))?.syncedAt ?? EPOCH;
|
|
25
|
+
}
|
|
26
|
+
async getCheckpoint(key) {
|
|
27
|
+
return this.checkpoint(key);
|
|
28
|
+
}
|
|
29
|
+
async list() {
|
|
30
|
+
const records = await this.log.listCheckpoints(this.mission);
|
|
31
|
+
return records.map((r) => ({
|
|
32
|
+
key: r.key,
|
|
33
|
+
syncedAt: new Date(r.syncedAt),
|
|
34
|
+
recordCount: r.recordCount,
|
|
35
|
+
cursor: r.cursor,
|
|
36
|
+
mission: r.mission,
|
|
37
|
+
executionId: r.executionId,
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
/** No-op: the log (via `checkpoint.advanced`) is the write path. */
|
|
41
|
+
async recordSync(_checkpoint) { }
|
|
42
|
+
/** Clearing a log-derived checkpoint isn't supported (the log is append-only). */
|
|
43
|
+
async clear() { }
|
|
44
|
+
async clearAll() { }
|
|
45
|
+
}
|
package/dist/sync/store.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { EPOCH } from './state.js';
|
|
3
|
-
import { ensureParentDirectory, writeJsonFile, readJsonFile, restoreDates
|
|
3
|
+
import { ensureParentDirectory, writeJsonFile, readJsonFile, restoreDates } from '../utils/file.js';
|
|
4
4
|
/**
|
|
5
5
|
* File-based sync store
|
|
6
6
|
* Stores sync state in .reqon-data/sync/{mission}.json
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Module - Time-travel debugging for Reqon
|
|
3
|
+
*
|
|
4
|
+
* Provides execution tracing, replay, and debugging capabilities:
|
|
5
|
+
* - TraceRecorder: Captures execution state at each step
|
|
6
|
+
* - TraceStore: Persists traces for later analysis
|
|
7
|
+
* - TraceReplayer: Navigates and inspects recorded traces
|
|
8
|
+
*/
|
|
9
|
+
export type { TraceSnapshot, StoreSnapshot, LoopContext, ExecutionTrace } from './state.js';
|
|
10
|
+
export { generateSnapshotId, createExecutionTrace, safeClone, truncateForTrace } from './state.js';
|
|
11
|
+
export type { TraceStore } from './store.js';
|
|
12
|
+
export { FileTraceStore, MemoryTraceStore } from './store.js';
|
|
13
|
+
export type { TraceRecorderConfig } from './recorder.js';
|
|
14
|
+
export { TraceRecorder, createTraceRecorder } from './recorder.js';
|
|
15
|
+
export type { ReplaySession, ReplayStepResult, TimelineEvent, VariableChange, SnapshotDiff, } from './replay.js';
|
|
16
|
+
export { TraceReplayer, createTraceReplayer } from './replay.js';
|
|
17
|
+
export type { LogTimelineEntry, LogTraceSummary } from './log-view.js';
|
|
18
|
+
export { LogTraceView, traceTimelineFromLog } from './log-view.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Module - Time-travel debugging for Reqon
|
|
3
|
+
*
|
|
4
|
+
* Provides execution tracing, replay, and debugging capabilities:
|
|
5
|
+
* - TraceRecorder: Captures execution state at each step
|
|
6
|
+
* - TraceStore: Persists traces for later analysis
|
|
7
|
+
* - TraceReplayer: Navigates and inspects recorded traces
|
|
8
|
+
*/
|
|
9
|
+
export { generateSnapshotId, createExecutionTrace, safeClone, truncateForTrace } from './state.js';
|
|
10
|
+
export { FileTraceStore, MemoryTraceStore } from './store.js';
|
|
11
|
+
export { TraceRecorder, createTraceRecorder } from './recorder.js';
|
|
12
|
+
export { TraceReplayer, createTraceReplayer } from './replay.js';
|
|
13
|
+
export { LogTraceView, traceTimelineFromLog } from './log-view.js';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace as a view over the execution log.
|
|
3
|
+
*
|
|
4
|
+
* Time-travel debugging and the audit trail fall straight out of the
|
|
5
|
+
* append-only log: the ordered sequence of events *is* the trace. This module
|
|
6
|
+
* derives a navigable timeline and a folded summary from `StoredEvent[]`, so a
|
|
7
|
+
* run's history is reconstructable from the log with no separate trace store.
|
|
8
|
+
*
|
|
9
|
+
* Scope: the log records the structural timeline (steps, effects, checkpoints,
|
|
10
|
+
* pauses, errors), which is what time-travel navigation and audit need. The
|
|
11
|
+
* richer variable-level snapshots remain the job of the opt-in {@link TraceRecorder}.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExecutionLogStore, StoredEvent, ExecutionEventType } from '../execution-log/index.js';
|
|
14
|
+
import { foldLog } from '../execution-log/index.js';
|
|
15
|
+
/** One step in the timeline view, derived from a single log event. */
|
|
16
|
+
export interface LogTimelineEntry {
|
|
17
|
+
/** Sequence within the execution (the time-travel cursor). */
|
|
18
|
+
seq: number;
|
|
19
|
+
/** Recorded wall-clock time (ISO 8601). */
|
|
20
|
+
at: string;
|
|
21
|
+
/** The underlying event type. */
|
|
22
|
+
type: ExecutionEventType;
|
|
23
|
+
/** Action name, for step events. */
|
|
24
|
+
action?: string;
|
|
25
|
+
/** Step identity, for step/effect events. */
|
|
26
|
+
step?: string;
|
|
27
|
+
/** Step kind (fetch, store, …), for step events. */
|
|
28
|
+
stepType?: string;
|
|
29
|
+
/** Attempt number, for step/effect events. */
|
|
30
|
+
attempt?: number;
|
|
31
|
+
/** Human-readable summary of this entry. */
|
|
32
|
+
detail?: string;
|
|
33
|
+
}
|
|
34
|
+
/** A folded summary of a run, for the trace overview. */
|
|
35
|
+
export interface LogTraceSummary {
|
|
36
|
+
status: ReturnType<typeof foldLog>['status'];
|
|
37
|
+
totalEvents: number;
|
|
38
|
+
stepsCompleted: number;
|
|
39
|
+
effectsApplied: number;
|
|
40
|
+
checkpoints: number;
|
|
41
|
+
pendingPauseId?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/** Build an ordered, navigable timeline from a run's log events. */
|
|
45
|
+
export declare function traceTimelineFromLog(events: StoredEvent[]): LogTimelineEntry[];
|
|
46
|
+
/**
|
|
47
|
+
* Navigable, log-backed trace for one execution: the timeline and a folded
|
|
48
|
+
* summary, read straight from the execution log.
|
|
49
|
+
*/
|
|
50
|
+
export declare class LogTraceView {
|
|
51
|
+
private log;
|
|
52
|
+
private executionId;
|
|
53
|
+
constructor(log: ExecutionLogStore, executionId: string);
|
|
54
|
+
events(): Promise<StoredEvent[]>;
|
|
55
|
+
timeline(): Promise<LogTimelineEntry[]>;
|
|
56
|
+
summary(): Promise<LogTraceSummary>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { foldLog } from '../execution-log/index.js';
|
|
2
|
+
function describe(event) {
|
|
3
|
+
switch (event.type) {
|
|
4
|
+
case 'mission.started':
|
|
5
|
+
return `mission ${event.mission} started`;
|
|
6
|
+
case 'step.started':
|
|
7
|
+
return `${event.action}: ${event.stepType} step started`;
|
|
8
|
+
case 'step.completed':
|
|
9
|
+
return `step ${event.stepId} completed`;
|
|
10
|
+
case 'effect.applied':
|
|
11
|
+
return `${event.effectType} effect applied`;
|
|
12
|
+
case 'checkpoint.advanced':
|
|
13
|
+
return `checkpoint ${event.key} -> ${event.syncedAt}`;
|
|
14
|
+
case 'pause.created':
|
|
15
|
+
return `paused (${event.pauseId})`;
|
|
16
|
+
case 'pause.resumed':
|
|
17
|
+
return `resumed by ${event.resumedBy}`;
|
|
18
|
+
case 'mission.completed':
|
|
19
|
+
return 'mission completed';
|
|
20
|
+
case 'mission.failed':
|
|
21
|
+
return `mission failed: ${event.error}`;
|
|
22
|
+
default:
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Build an ordered, navigable timeline from a run's log events. */
|
|
27
|
+
export function traceTimelineFromLog(events) {
|
|
28
|
+
return events.map((event) => {
|
|
29
|
+
const entry = {
|
|
30
|
+
seq: event.seq,
|
|
31
|
+
at: event.at,
|
|
32
|
+
type: event.type,
|
|
33
|
+
detail: describe(event),
|
|
34
|
+
};
|
|
35
|
+
if ('action' in event)
|
|
36
|
+
entry.action = event.action;
|
|
37
|
+
if ('stepId' in event)
|
|
38
|
+
entry.step = event.stepId;
|
|
39
|
+
if ('stepType' in event)
|
|
40
|
+
entry.stepType = event.stepType;
|
|
41
|
+
if ('attempt' in event)
|
|
42
|
+
entry.attempt = event.attempt;
|
|
43
|
+
return entry;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Navigable, log-backed trace for one execution: the timeline and a folded
|
|
48
|
+
* summary, read straight from the execution log.
|
|
49
|
+
*/
|
|
50
|
+
export class LogTraceView {
|
|
51
|
+
log;
|
|
52
|
+
executionId;
|
|
53
|
+
constructor(log, executionId) {
|
|
54
|
+
this.log = log;
|
|
55
|
+
this.executionId = executionId;
|
|
56
|
+
}
|
|
57
|
+
async events() {
|
|
58
|
+
return this.log.read(this.executionId);
|
|
59
|
+
}
|
|
60
|
+
async timeline() {
|
|
61
|
+
return traceTimelineFromLog(await this.events());
|
|
62
|
+
}
|
|
63
|
+
async summary() {
|
|
64
|
+
const events = await this.events();
|
|
65
|
+
const folded = foldLog(events);
|
|
66
|
+
return {
|
|
67
|
+
status: folded.status,
|
|
68
|
+
totalEvents: events.length,
|
|
69
|
+
stepsCompleted: folded.completedSteps.size,
|
|
70
|
+
effectsApplied: folded.appliedEffects.size,
|
|
71
|
+
checkpoints: folded.checkpoints.size,
|
|
72
|
+
pendingPauseId: folded.pendingPauseId,
|
|
73
|
+
error: folded.error,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Recorder - Captures execution state for time-travel debugging
|
|
3
|
+
*
|
|
4
|
+
* Used by the executor to record snapshots at each step,
|
|
5
|
+
* building a complete trace that can be replayed later.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExecutionContext } from '../interpreter/context.js';
|
|
8
|
+
import type { TraceStore } from './store.js';
|
|
9
|
+
import { type ExecutionTrace, type TraceSnapshot, type LoopContext } from './state.js';
|
|
10
|
+
export interface TraceRecorderConfig {
|
|
11
|
+
/** Execution ID (used as trace ID) */
|
|
12
|
+
executionId: string;
|
|
13
|
+
/** Mission name */
|
|
14
|
+
mission: string;
|
|
15
|
+
/** Trace mode */
|
|
16
|
+
mode: 'full' | 'minimal';
|
|
17
|
+
/** Store for persisting traces */
|
|
18
|
+
store: TraceStore;
|
|
19
|
+
/** Metadata to attach to trace */
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
/** Whether to stream snapshots (append as they happen) vs batch at end */
|
|
22
|
+
streaming?: boolean;
|
|
23
|
+
/** Max items to include in store samples */
|
|
24
|
+
maxStoreItems?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Records execution state for time-travel debugging
|
|
28
|
+
*/
|
|
29
|
+
export declare class TraceRecorder {
|
|
30
|
+
private config;
|
|
31
|
+
private trace;
|
|
32
|
+
private snapshotIndex;
|
|
33
|
+
private currentLoopContext?;
|
|
34
|
+
constructor(config: TraceRecorderConfig);
|
|
35
|
+
/**
|
|
36
|
+
* Record a snapshot before step execution
|
|
37
|
+
*/
|
|
38
|
+
recordBeforeStep(action: string, stepIndex: number, stepType: string, ctx: ExecutionContext): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Record a snapshot after step execution
|
|
41
|
+
*/
|
|
42
|
+
recordAfterStep(action: string, stepIndex: number, stepType: string, ctx: ExecutionContext, stepDuration: number, error?: string): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Set loop context for subsequent snapshots
|
|
45
|
+
*/
|
|
46
|
+
setLoopContext(context: LoopContext | undefined): void;
|
|
47
|
+
/**
|
|
48
|
+
* Finalize the trace (called when execution completes)
|
|
49
|
+
*/
|
|
50
|
+
finalize(success: boolean): Promise<ExecutionTrace>;
|
|
51
|
+
/**
|
|
52
|
+
* Get the current trace (without finalizing)
|
|
53
|
+
*/
|
|
54
|
+
getTrace(): ExecutionTrace;
|
|
55
|
+
/**
|
|
56
|
+
* Get a specific snapshot by index
|
|
57
|
+
*/
|
|
58
|
+
getSnapshot(index: number): TraceSnapshot | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Get the total number of snapshots recorded. In streaming mode the in-memory
|
|
61
|
+
* array is bounded (older snapshots live only on disk), so this reflects the
|
|
62
|
+
* true total rather than the retained window.
|
|
63
|
+
*/
|
|
64
|
+
getSnapshotCount(): number;
|
|
65
|
+
private createSnapshot;
|
|
66
|
+
private captureVariables;
|
|
67
|
+
private captureStores;
|
|
68
|
+
/** Cap on snapshots kept in memory while streaming (each is already on disk). */
|
|
69
|
+
private static readonly MAX_STREAMED_IN_MEMORY;
|
|
70
|
+
private addSnapshot;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a trace recorder for an execution
|
|
74
|
+
*/
|
|
75
|
+
export declare function createTraceRecorder(config: TraceRecorderConfig): TraceRecorder;
|