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,157 @@
|
|
|
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 { createExecutionTrace, generateSnapshotId, safeClone, truncateForTrace, } from './state.js';
|
|
8
|
+
import { redactSecrets } from '../utils/redact.js';
|
|
9
|
+
/**
|
|
10
|
+
* Records execution state for time-travel debugging
|
|
11
|
+
*/
|
|
12
|
+
export class TraceRecorder {
|
|
13
|
+
config;
|
|
14
|
+
trace;
|
|
15
|
+
snapshotIndex = 0;
|
|
16
|
+
currentLoopContext;
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.trace = createExecutionTrace(config.executionId, config.mission, config.mode, config.metadata);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Record a snapshot before step execution
|
|
23
|
+
*/
|
|
24
|
+
async recordBeforeStep(action, stepIndex, stepType, ctx) {
|
|
25
|
+
const snapshot = this.createSnapshot(action, stepIndex, stepType, 'before', ctx);
|
|
26
|
+
await this.addSnapshot(snapshot);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Record a snapshot after step execution
|
|
30
|
+
*/
|
|
31
|
+
async recordAfterStep(action, stepIndex, stepType, ctx, stepDuration, error) {
|
|
32
|
+
const snapshot = this.createSnapshot(action, stepIndex, stepType, 'after', ctx);
|
|
33
|
+
snapshot.stepDuration = stepDuration;
|
|
34
|
+
snapshot.error = error;
|
|
35
|
+
await this.addSnapshot(snapshot);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set loop context for subsequent snapshots
|
|
39
|
+
*/
|
|
40
|
+
setLoopContext(context) {
|
|
41
|
+
this.currentLoopContext = context;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Finalize the trace (called when execution completes)
|
|
45
|
+
*/
|
|
46
|
+
async finalize(success) {
|
|
47
|
+
this.trace.completedAt = new Date();
|
|
48
|
+
this.trace.duration = this.trace.completedAt.getTime() - this.trace.startedAt.getTime();
|
|
49
|
+
this.trace.success = success;
|
|
50
|
+
// If not streaming, save entire trace at end
|
|
51
|
+
if (!this.config.streaming) {
|
|
52
|
+
await this.config.store.save(this.trace);
|
|
53
|
+
}
|
|
54
|
+
return this.trace;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the current trace (without finalizing)
|
|
58
|
+
*/
|
|
59
|
+
getTrace() {
|
|
60
|
+
return this.trace;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get a specific snapshot by index
|
|
64
|
+
*/
|
|
65
|
+
getSnapshot(index) {
|
|
66
|
+
return this.trace.snapshots[index];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the total number of snapshots recorded. In streaming mode the in-memory
|
|
70
|
+
* array is bounded (older snapshots live only on disk), so this reflects the
|
|
71
|
+
* true total rather than the retained window.
|
|
72
|
+
*/
|
|
73
|
+
getSnapshotCount() {
|
|
74
|
+
return this.snapshotIndex;
|
|
75
|
+
}
|
|
76
|
+
createSnapshot(action, stepIndex, stepType, phase, ctx) {
|
|
77
|
+
const index = this.snapshotIndex++;
|
|
78
|
+
// Capture variables from context chain. Trace files are diagnostic and
|
|
79
|
+
// persisted to disk, so redact credential-looking fields.
|
|
80
|
+
const variables = redactSecrets(this.captureVariables(ctx));
|
|
81
|
+
// Capture store states
|
|
82
|
+
const stores = this.captureStores(ctx);
|
|
83
|
+
// Capture response (truncated for large responses)
|
|
84
|
+
const response = this.config.mode === 'full'
|
|
85
|
+
? redactSecrets(truncateForTrace(safeClone(ctx.response)))
|
|
86
|
+
: undefined;
|
|
87
|
+
return {
|
|
88
|
+
id: generateSnapshotId(this.trace.id, index),
|
|
89
|
+
index,
|
|
90
|
+
timestamp: new Date(),
|
|
91
|
+
mission: this.trace.mission,
|
|
92
|
+
action,
|
|
93
|
+
stepIndex,
|
|
94
|
+
stepType,
|
|
95
|
+
phase,
|
|
96
|
+
variables,
|
|
97
|
+
response,
|
|
98
|
+
stores,
|
|
99
|
+
loopContext: this.currentLoopContext ? { ...this.currentLoopContext } : undefined,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
captureVariables(ctx) {
|
|
103
|
+
const variables = {};
|
|
104
|
+
let current = ctx;
|
|
105
|
+
while (current) {
|
|
106
|
+
for (const [key, value] of current.variables) {
|
|
107
|
+
if (!(key in variables)) {
|
|
108
|
+
// Clone and truncate for trace storage
|
|
109
|
+
variables[key] =
|
|
110
|
+
this.config.mode === 'full' ? truncateForTrace(safeClone(value)) : typeof value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
current = current.parent;
|
|
114
|
+
}
|
|
115
|
+
return variables;
|
|
116
|
+
}
|
|
117
|
+
captureStores(ctx) {
|
|
118
|
+
const stores = {};
|
|
119
|
+
const maxItems = this.config.maxStoreItems ?? 10;
|
|
120
|
+
for (const [name, _store] of ctx.stores) {
|
|
121
|
+
const storeType = ctx.storeTypes.get(name) ?? 'unknown';
|
|
122
|
+
// Note: Getting actual item count would require async call
|
|
123
|
+
// For now, we just record the type
|
|
124
|
+
stores[name] = {
|
|
125
|
+
type: storeType,
|
|
126
|
+
itemCount: -1, // Would need async to get actual count
|
|
127
|
+
sampleItems: this.config.mode === 'full' ? [] : undefined,
|
|
128
|
+
};
|
|
129
|
+
// In full mode, we could sample items if we had sync access
|
|
130
|
+
// For now, this is a placeholder for future enhancement
|
|
131
|
+
if (this.config.mode === 'full' && maxItems > 0) {
|
|
132
|
+
// TODO: Add async store sampling if needed
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return stores;
|
|
136
|
+
}
|
|
137
|
+
/** Cap on snapshots kept in memory while streaming (each is already on disk). */
|
|
138
|
+
static MAX_STREAMED_IN_MEMORY = 200;
|
|
139
|
+
async addSnapshot(snapshot) {
|
|
140
|
+
this.trace.snapshots.push(snapshot);
|
|
141
|
+
if (this.config.streaming) {
|
|
142
|
+
// Persisted immediately, so the in-memory copy is only a recent window for
|
|
143
|
+
// live inspection — bound it so a long run doesn't grow without limit.
|
|
144
|
+
await this.config.store.appendSnapshot(this.trace.id, snapshot);
|
|
145
|
+
const cap = TraceRecorder.MAX_STREAMED_IN_MEMORY;
|
|
146
|
+
if (this.trace.snapshots.length > cap) {
|
|
147
|
+
this.trace.snapshots.splice(0, this.trace.snapshots.length - cap);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create a trace recorder for an execution
|
|
154
|
+
*/
|
|
155
|
+
export function createTraceRecorder(config) {
|
|
156
|
+
return new TraceRecorder(config);
|
|
157
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Replay - Time-travel debugging for execution traces
|
|
3
|
+
*
|
|
4
|
+
* Allows stepping through recorded execution traces,
|
|
5
|
+
* inspecting state at each point, and comparing across runs.
|
|
6
|
+
*/
|
|
7
|
+
import type { TraceStore } from './store.js';
|
|
8
|
+
import type { ExecutionTrace, TraceSnapshot, LoopContext } from './state.js';
|
|
9
|
+
/**
|
|
10
|
+
* Replay session state
|
|
11
|
+
*/
|
|
12
|
+
export interface ReplaySession {
|
|
13
|
+
/** Trace being replayed */
|
|
14
|
+
trace: ExecutionTrace;
|
|
15
|
+
/** Current snapshot index */
|
|
16
|
+
currentIndex: number;
|
|
17
|
+
/** Total snapshots */
|
|
18
|
+
totalSnapshots: number;
|
|
19
|
+
/** Current snapshot */
|
|
20
|
+
currentSnapshot: TraceSnapshot | null;
|
|
21
|
+
/** Replay mode */
|
|
22
|
+
mode: 'paused' | 'stepping' | 'running';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Replay step result
|
|
26
|
+
*/
|
|
27
|
+
export interface ReplayStepResult {
|
|
28
|
+
/** The snapshot at this step */
|
|
29
|
+
snapshot: TraceSnapshot;
|
|
30
|
+
/** Whether there are more steps */
|
|
31
|
+
hasNext: boolean;
|
|
32
|
+
/** Whether there are previous steps */
|
|
33
|
+
hasPrevious: boolean;
|
|
34
|
+
/** Human-readable summary of this step */
|
|
35
|
+
summary: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Replay controller for navigating execution traces
|
|
39
|
+
*/
|
|
40
|
+
export declare class TraceReplayer {
|
|
41
|
+
private store;
|
|
42
|
+
private session;
|
|
43
|
+
constructor(store: TraceStore);
|
|
44
|
+
/**
|
|
45
|
+
* Load a trace and start a replay session
|
|
46
|
+
*/
|
|
47
|
+
loadTrace(traceId: string): Promise<ReplaySession>;
|
|
48
|
+
/**
|
|
49
|
+
* Load the latest trace for a mission
|
|
50
|
+
*/
|
|
51
|
+
loadLatest(mission: string): Promise<ReplaySession>;
|
|
52
|
+
/**
|
|
53
|
+
* Get current session state
|
|
54
|
+
*/
|
|
55
|
+
getSession(): ReplaySession | null;
|
|
56
|
+
/**
|
|
57
|
+
* Go to a specific step by index
|
|
58
|
+
*/
|
|
59
|
+
goToStep(index: number): Promise<ReplayStepResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Go to the next step
|
|
62
|
+
*/
|
|
63
|
+
next(): Promise<ReplayStepResult | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Go to the previous step
|
|
66
|
+
*/
|
|
67
|
+
previous(): Promise<ReplayStepResult | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Jump to the first step of an action
|
|
70
|
+
*/
|
|
71
|
+
goToAction(actionName: string): Promise<ReplayStepResult | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Jump to a step where a specific variable changed
|
|
74
|
+
*/
|
|
75
|
+
findVariableChange(variableName: string, fromIndex?: number): Promise<ReplayStepResult | null>;
|
|
76
|
+
/**
|
|
77
|
+
* Find steps where an error occurred
|
|
78
|
+
*/
|
|
79
|
+
findErrors(): number[];
|
|
80
|
+
/**
|
|
81
|
+
* Get all unique action names in the trace
|
|
82
|
+
*/
|
|
83
|
+
getActions(): string[];
|
|
84
|
+
/**
|
|
85
|
+
* Get execution timeline with key events
|
|
86
|
+
*/
|
|
87
|
+
getTimeline(): TimelineEvent[];
|
|
88
|
+
/**
|
|
89
|
+
* Compare two snapshots
|
|
90
|
+
*/
|
|
91
|
+
compareSnapshots(index1: number, index2: number): SnapshotDiff;
|
|
92
|
+
/**
|
|
93
|
+
* Export trace to JSON for external analysis
|
|
94
|
+
*/
|
|
95
|
+
exportTrace(): ExecutionTrace | null;
|
|
96
|
+
private formatStepResult;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Timeline event types
|
|
100
|
+
*/
|
|
101
|
+
export interface TimelineEvent {
|
|
102
|
+
type: 'action-start' | 'error' | 'loop-iteration' | 'checkpoint';
|
|
103
|
+
index: number;
|
|
104
|
+
action: string;
|
|
105
|
+
step?: string;
|
|
106
|
+
message?: string;
|
|
107
|
+
loopContext?: LoopContext;
|
|
108
|
+
timestamp: Date;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Variable change in diff
|
|
112
|
+
*/
|
|
113
|
+
export interface VariableChange {
|
|
114
|
+
name: string;
|
|
115
|
+
before: unknown;
|
|
116
|
+
after: unknown;
|
|
117
|
+
type: 'added' | 'removed' | 'changed';
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Snapshot comparison result
|
|
121
|
+
*/
|
|
122
|
+
export interface SnapshotDiff {
|
|
123
|
+
snapshot1: TraceSnapshot;
|
|
124
|
+
snapshot2: TraceSnapshot;
|
|
125
|
+
variableChanges: VariableChange[];
|
|
126
|
+
responseDifferent: boolean;
|
|
127
|
+
stepsExecuted: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Create a trace replayer
|
|
131
|
+
*/
|
|
132
|
+
export declare function createTraceReplayer(store: TraceStore): TraceReplayer;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Replay - Time-travel debugging for execution traces
|
|
3
|
+
*
|
|
4
|
+
* Allows stepping through recorded execution traces,
|
|
5
|
+
* inspecting state at each point, and comparing across runs.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Replay controller for navigating execution traces
|
|
9
|
+
*/
|
|
10
|
+
export class TraceReplayer {
|
|
11
|
+
store;
|
|
12
|
+
session = null;
|
|
13
|
+
constructor(store) {
|
|
14
|
+
this.store = store;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load a trace and start a replay session
|
|
18
|
+
*/
|
|
19
|
+
async loadTrace(traceId) {
|
|
20
|
+
const trace = await this.store.load(traceId);
|
|
21
|
+
if (!trace) {
|
|
22
|
+
throw new Error(`Trace not found: ${traceId}`);
|
|
23
|
+
}
|
|
24
|
+
this.session = {
|
|
25
|
+
trace,
|
|
26
|
+
currentIndex: 0,
|
|
27
|
+
totalSnapshots: trace.snapshots.length,
|
|
28
|
+
currentSnapshot: trace.snapshots[0] ?? null,
|
|
29
|
+
mode: 'paused',
|
|
30
|
+
};
|
|
31
|
+
return this.session;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Load the latest trace for a mission
|
|
35
|
+
*/
|
|
36
|
+
async loadLatest(mission) {
|
|
37
|
+
const trace = await this.store.findLatest(mission);
|
|
38
|
+
if (!trace) {
|
|
39
|
+
throw new Error(`No traces found for mission: ${mission}`);
|
|
40
|
+
}
|
|
41
|
+
// Load full trace with snapshots
|
|
42
|
+
const fullTrace = await this.store.load(trace.id);
|
|
43
|
+
if (!fullTrace) {
|
|
44
|
+
throw new Error(`Failed to load trace: ${trace.id}`);
|
|
45
|
+
}
|
|
46
|
+
this.session = {
|
|
47
|
+
trace: fullTrace,
|
|
48
|
+
currentIndex: 0,
|
|
49
|
+
totalSnapshots: fullTrace.snapshots.length,
|
|
50
|
+
currentSnapshot: fullTrace.snapshots[0] ?? null,
|
|
51
|
+
mode: 'paused',
|
|
52
|
+
};
|
|
53
|
+
return this.session;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get current session state
|
|
57
|
+
*/
|
|
58
|
+
getSession() {
|
|
59
|
+
return this.session;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Go to a specific step by index
|
|
63
|
+
*/
|
|
64
|
+
async goToStep(index) {
|
|
65
|
+
if (!this.session) {
|
|
66
|
+
throw new Error('No replay session active');
|
|
67
|
+
}
|
|
68
|
+
if (index < 0 || index >= this.session.totalSnapshots) {
|
|
69
|
+
throw new Error(`Invalid step index: ${index}. Valid range: 0-${this.session.totalSnapshots - 1}`);
|
|
70
|
+
}
|
|
71
|
+
this.session.currentIndex = index;
|
|
72
|
+
this.session.currentSnapshot = this.session.trace.snapshots[index];
|
|
73
|
+
return this.formatStepResult(this.session.currentSnapshot);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Go to the next step
|
|
77
|
+
*/
|
|
78
|
+
async next() {
|
|
79
|
+
if (!this.session) {
|
|
80
|
+
throw new Error('No replay session active');
|
|
81
|
+
}
|
|
82
|
+
if (this.session.currentIndex >= this.session.totalSnapshots - 1) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return this.goToStep(this.session.currentIndex + 1);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Go to the previous step
|
|
89
|
+
*/
|
|
90
|
+
async previous() {
|
|
91
|
+
if (!this.session) {
|
|
92
|
+
throw new Error('No replay session active');
|
|
93
|
+
}
|
|
94
|
+
if (this.session.currentIndex <= 0) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
return this.goToStep(this.session.currentIndex - 1);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Jump to the first step of an action
|
|
101
|
+
*/
|
|
102
|
+
async goToAction(actionName) {
|
|
103
|
+
if (!this.session) {
|
|
104
|
+
throw new Error('No replay session active');
|
|
105
|
+
}
|
|
106
|
+
const index = this.session.trace.snapshots.findIndex((s) => s.action === actionName && s.phase === 'before');
|
|
107
|
+
if (index === -1) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return this.goToStep(index);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Jump to a step where a specific variable changed
|
|
114
|
+
*/
|
|
115
|
+
async findVariableChange(variableName, fromIndex = 0) {
|
|
116
|
+
if (!this.session) {
|
|
117
|
+
throw new Error('No replay session active');
|
|
118
|
+
}
|
|
119
|
+
let previousValue = undefined;
|
|
120
|
+
for (let i = fromIndex; i < this.session.totalSnapshots; i++) {
|
|
121
|
+
const snapshot = this.session.trace.snapshots[i];
|
|
122
|
+
const currentValue = snapshot.variables[variableName];
|
|
123
|
+
if (i === fromIndex) {
|
|
124
|
+
previousValue = currentValue;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (JSON.stringify(currentValue) !== JSON.stringify(previousValue)) {
|
|
128
|
+
return this.goToStep(i);
|
|
129
|
+
}
|
|
130
|
+
previousValue = currentValue;
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Find steps where an error occurred
|
|
136
|
+
*/
|
|
137
|
+
findErrors() {
|
|
138
|
+
if (!this.session) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
return this.session.trace.snapshots.map((s, i) => (s.error ? i : -1)).filter((i) => i !== -1);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get all unique action names in the trace
|
|
145
|
+
*/
|
|
146
|
+
getActions() {
|
|
147
|
+
if (!this.session) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
const actions = new Set();
|
|
151
|
+
for (const snapshot of this.session.trace.snapshots) {
|
|
152
|
+
actions.add(snapshot.action);
|
|
153
|
+
}
|
|
154
|
+
return Array.from(actions);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get execution timeline with key events
|
|
158
|
+
*/
|
|
159
|
+
getTimeline() {
|
|
160
|
+
if (!this.session) {
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
const events = [];
|
|
164
|
+
let currentAction = '';
|
|
165
|
+
for (const snapshot of this.session.trace.snapshots) {
|
|
166
|
+
if (snapshot.action !== currentAction && snapshot.phase === 'before') {
|
|
167
|
+
events.push({
|
|
168
|
+
type: 'action-start',
|
|
169
|
+
index: snapshot.index,
|
|
170
|
+
action: snapshot.action,
|
|
171
|
+
timestamp: snapshot.timestamp,
|
|
172
|
+
});
|
|
173
|
+
currentAction = snapshot.action;
|
|
174
|
+
}
|
|
175
|
+
if (snapshot.error) {
|
|
176
|
+
events.push({
|
|
177
|
+
type: 'error',
|
|
178
|
+
index: snapshot.index,
|
|
179
|
+
action: snapshot.action,
|
|
180
|
+
step: snapshot.stepType,
|
|
181
|
+
message: snapshot.error,
|
|
182
|
+
timestamp: snapshot.timestamp,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
if (snapshot.loopContext && snapshot.phase === 'before') {
|
|
186
|
+
events.push({
|
|
187
|
+
type: 'loop-iteration',
|
|
188
|
+
index: snapshot.index,
|
|
189
|
+
action: snapshot.action,
|
|
190
|
+
loopContext: snapshot.loopContext,
|
|
191
|
+
timestamp: snapshot.timestamp,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return events;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Compare two snapshots
|
|
199
|
+
*/
|
|
200
|
+
compareSnapshots(index1, index2) {
|
|
201
|
+
if (!this.session) {
|
|
202
|
+
throw new Error('No replay session active');
|
|
203
|
+
}
|
|
204
|
+
const snap1 = this.session.trace.snapshots[index1];
|
|
205
|
+
const snap2 = this.session.trace.snapshots[index2];
|
|
206
|
+
if (!snap1 || !snap2) {
|
|
207
|
+
throw new Error('Invalid snapshot indices');
|
|
208
|
+
}
|
|
209
|
+
const variableChanges = [];
|
|
210
|
+
// Find variables that changed
|
|
211
|
+
const allVars = new Set([...Object.keys(snap1.variables), ...Object.keys(snap2.variables)]);
|
|
212
|
+
for (const varName of allVars) {
|
|
213
|
+
const val1 = snap1.variables[varName];
|
|
214
|
+
const val2 = snap2.variables[varName];
|
|
215
|
+
if (JSON.stringify(val1) !== JSON.stringify(val2)) {
|
|
216
|
+
variableChanges.push({
|
|
217
|
+
name: varName,
|
|
218
|
+
before: val1,
|
|
219
|
+
after: val2,
|
|
220
|
+
type: val1 === undefined ? 'added' : val2 === undefined ? 'removed' : 'changed',
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
snapshot1: snap1,
|
|
226
|
+
snapshot2: snap2,
|
|
227
|
+
variableChanges,
|
|
228
|
+
responseDifferent: JSON.stringify(snap1.response) !== JSON.stringify(snap2.response),
|
|
229
|
+
stepsExecuted: index2 - index1,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Export trace to JSON for external analysis
|
|
234
|
+
*/
|
|
235
|
+
exportTrace() {
|
|
236
|
+
return this.session?.trace ?? null;
|
|
237
|
+
}
|
|
238
|
+
formatStepResult(snapshot) {
|
|
239
|
+
const hasNext = this.session.currentIndex < this.session.totalSnapshots - 1;
|
|
240
|
+
const hasPrevious = this.session.currentIndex > 0;
|
|
241
|
+
let summary = `[${snapshot.index}] ${snapshot.phase.toUpperCase()} ${snapshot.action}.${snapshot.stepType}`;
|
|
242
|
+
if (snapshot.loopContext) {
|
|
243
|
+
summary += ` (loop ${snapshot.loopContext.itemIndex + 1}/${snapshot.loopContext.totalItems})`;
|
|
244
|
+
}
|
|
245
|
+
if (snapshot.stepDuration !== undefined) {
|
|
246
|
+
summary += ` - ${snapshot.stepDuration}ms`;
|
|
247
|
+
}
|
|
248
|
+
if (snapshot.error) {
|
|
249
|
+
summary += ` - ERROR: ${snapshot.error}`;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
snapshot,
|
|
253
|
+
hasNext,
|
|
254
|
+
hasPrevious,
|
|
255
|
+
summary,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Create a trace replayer
|
|
261
|
+
*/
|
|
262
|
+
export function createTraceReplayer(store) {
|
|
263
|
+
return new TraceReplayer(store);
|
|
264
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace State - Types for time-travel debugging
|
|
3
|
+
*
|
|
4
|
+
* Captures full execution state snapshots at each step,
|
|
5
|
+
* enabling replay and debugging of pipeline runs.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A single step snapshot in the execution trace
|
|
9
|
+
*/
|
|
10
|
+
export interface TraceSnapshot {
|
|
11
|
+
/** Unique snapshot ID */
|
|
12
|
+
id: string;
|
|
13
|
+
/** Index in the trace sequence */
|
|
14
|
+
index: number;
|
|
15
|
+
/** Timestamp when snapshot was captured */
|
|
16
|
+
timestamp: Date;
|
|
17
|
+
/** Mission name */
|
|
18
|
+
mission: string;
|
|
19
|
+
/** Current action name */
|
|
20
|
+
action: string;
|
|
21
|
+
/** Step index within action */
|
|
22
|
+
stepIndex: number;
|
|
23
|
+
/** Step type (fetch, for, map, etc.) */
|
|
24
|
+
stepType: string;
|
|
25
|
+
/** Phase: before or after step execution */
|
|
26
|
+
phase: 'before' | 'after';
|
|
27
|
+
/** All variables in scope (deep cloned) */
|
|
28
|
+
variables: Record<string, unknown>;
|
|
29
|
+
/** Current response value (deep cloned) */
|
|
30
|
+
response?: unknown;
|
|
31
|
+
/** Store states - map of store name to item count and sample */
|
|
32
|
+
stores: Record<string, StoreSnapshot>;
|
|
33
|
+
/** Duration of step execution (only for 'after' phase) */
|
|
34
|
+
stepDuration?: number;
|
|
35
|
+
/** Error if step failed */
|
|
36
|
+
error?: string;
|
|
37
|
+
/** For loop context (if inside a for loop) */
|
|
38
|
+
loopContext?: LoopContext;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Snapshot of a store's state
|
|
42
|
+
*/
|
|
43
|
+
export interface StoreSnapshot {
|
|
44
|
+
/** Store type (memory, file, etc.) */
|
|
45
|
+
type: string;
|
|
46
|
+
/** Number of items in store */
|
|
47
|
+
itemCount: number;
|
|
48
|
+
/** Sample of recent items (limited to avoid huge traces) */
|
|
49
|
+
sampleItems?: unknown[];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Context when inside a for loop
|
|
53
|
+
*/
|
|
54
|
+
export interface LoopContext {
|
|
55
|
+
/** Loop variable name */
|
|
56
|
+
variable: string;
|
|
57
|
+
/** Current item index */
|
|
58
|
+
itemIndex: number;
|
|
59
|
+
/** Total items in collection */
|
|
60
|
+
totalItems: number;
|
|
61
|
+
/** Current item value */
|
|
62
|
+
currentItem?: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Complete trace for a mission execution
|
|
66
|
+
*/
|
|
67
|
+
export interface ExecutionTrace {
|
|
68
|
+
/** Trace ID (same as execution ID) */
|
|
69
|
+
id: string;
|
|
70
|
+
/** Mission name */
|
|
71
|
+
mission: string;
|
|
72
|
+
/** Trace mode (full or minimal) */
|
|
73
|
+
mode: 'full' | 'minimal';
|
|
74
|
+
/** When trace started */
|
|
75
|
+
startedAt: Date;
|
|
76
|
+
/** When trace completed */
|
|
77
|
+
completedAt?: Date;
|
|
78
|
+
/** Total duration in ms */
|
|
79
|
+
duration?: number;
|
|
80
|
+
/** Whether execution succeeded */
|
|
81
|
+
success?: boolean;
|
|
82
|
+
/** All snapshots in execution order */
|
|
83
|
+
snapshots: TraceSnapshot[];
|
|
84
|
+
/** Metadata from execution */
|
|
85
|
+
metadata?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Generate a unique snapshot ID
|
|
89
|
+
*/
|
|
90
|
+
export declare function generateSnapshotId(traceId: string, index: number): string;
|
|
91
|
+
/**
|
|
92
|
+
* Create a new execution trace
|
|
93
|
+
*/
|
|
94
|
+
export declare function createExecutionTrace(executionId: string, mission: string, mode: 'full' | 'minimal', metadata?: Record<string, unknown>): ExecutionTrace;
|
|
95
|
+
/**
|
|
96
|
+
* Safe deep clone that handles circular references and special types
|
|
97
|
+
*/
|
|
98
|
+
export declare function safeClone<T>(value: T, maxDepth?: number): T;
|
|
99
|
+
/**
|
|
100
|
+
* Truncate large values for trace storage
|
|
101
|
+
*/
|
|
102
|
+
export declare function truncateForTrace(value: unknown, maxItems?: number, maxStringLength?: number): unknown;
|