reqon-dsl 0.2.0 → 0.3.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 +22 -0
- package/dist/ast/nodes.d.ts +83 -4
- package/dist/ast/nodes.js +14 -0
- package/dist/auth/circuit-breaker.js +7 -6
- package/dist/auth/rate-limiter.d.ts +4 -0
- package/dist/auth/rate-limiter.js +9 -16
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +84 -4
- package/dist/config/constants.d.ts +141 -0
- package/dist/config/constants.js +128 -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 +88 -0
- package/dist/control/server.js +238 -0
- package/dist/control/types.d.ts +55 -0
- package/dist/control/types.js +7 -0
- package/dist/debug/cli-debugger.d.ts +17 -0
- package/dist/debug/cli-debugger.js +180 -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/index.d.ts +21 -1
- package/dist/index.js +33 -2
- package/dist/interpreter/context.d.ts +14 -0
- package/dist/interpreter/context.js +15 -0
- package/dist/interpreter/evaluator.d.ts +63 -1
- package/dist/interpreter/evaluator.js +186 -39
- package/dist/interpreter/executor.d.ts +70 -14
- package/dist/interpreter/executor.js +503 -174
- package/dist/interpreter/fetch-handler.d.ts +9 -0
- package/dist/interpreter/fetch-handler.js +133 -24
- package/dist/interpreter/http.d.ts +5 -0
- package/dist/interpreter/http.js +26 -12
- package/dist/interpreter/index.d.ts +3 -1
- package/dist/interpreter/index.js +2 -0
- package/dist/interpreter/pagination.d.ts +11 -2
- package/dist/interpreter/pagination.js +95 -31
- 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 +13 -0
- package/dist/interpreter/step-handlers/for-handler.js +71 -4
- 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 +43 -16
- 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 +11 -1
- package/dist/interpreter/step-handlers/store-handler.js +45 -13
- 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 +4 -2
- package/dist/interpreter/step-handlers/webhook-handler.d.ts +3 -0
- package/dist/interpreter/step-handlers/webhook-handler.js +18 -2
- package/dist/interpreter/store-manager.d.ts +46 -0
- package/dist/interpreter/store-manager.js +66 -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/mcp/index.d.ts +11 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/server.d.ts +17 -0
- package/dist/mcp/server.js +451 -0
- package/dist/oas/index.d.ts +2 -0
- package/dist/oas/index.js +1 -0
- package/dist/oas/mock-generator.d.ts +12 -0
- package/dist/oas/mock-generator.js +187 -0
- package/dist/observability/events.d.ts +244 -0
- package/dist/observability/events.js +90 -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 +259 -0
- package/dist/observability/otel.d.ts +135 -0
- package/dist/observability/otel.js +386 -0
- package/dist/parser/action-parser.d.ts +105 -0
- package/dist/parser/action-parser.js +645 -0
- package/dist/parser/expressions.d.ts +13 -0
- package/dist/parser/expressions.js +72 -2
- package/dist/parser/fetch-parser.d.ts +27 -0
- package/dist/parser/fetch-parser.js +269 -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 +14 -0
- package/dist/pause/index.js +11 -0
- package/dist/pause/manager.d.ts +118 -0
- package/dist/pause/manager.js +245 -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 +156 -0
- package/dist/plugin.d.ts +9 -12
- package/dist/plugin.js +10 -13
- package/dist/stores/factory.d.ts +1 -1
- package/dist/stores/factory.js +3 -2
- package/dist/stores/file.d.ts +26 -0
- package/dist/stores/file.js +64 -10
- 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 +11 -0
- package/dist/stores/types.d.ts +17 -0
- package/dist/stores/types.js +12 -0
- package/dist/trace/index.d.ts +16 -0
- package/dist/trace/index.js +12 -0
- package/dist/trace/recorder.d.ts +71 -0
- package/dist/trace/recorder.js +144 -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 +69 -0
- package/dist/trace/store.js +225 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/type-guards.d.ts +58 -0
- package/dist/utils/type-guards.js +92 -0
- package/dist/webhook/server.js +7 -6
- package/package.json +55 -6
- 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,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;
|
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
* Generate a unique snapshot ID
|
|
9
|
+
*/
|
|
10
|
+
export function generateSnapshotId(traceId, index) {
|
|
11
|
+
return `${traceId}_snap_${index.toString().padStart(6, '0')}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a new execution trace
|
|
15
|
+
*/
|
|
16
|
+
export function createExecutionTrace(executionId, mission, mode, metadata) {
|
|
17
|
+
return {
|
|
18
|
+
id: executionId,
|
|
19
|
+
mission,
|
|
20
|
+
mode,
|
|
21
|
+
startedAt: new Date(),
|
|
22
|
+
snapshots: [],
|
|
23
|
+
metadata,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Safe deep clone that handles circular references and special types
|
|
28
|
+
*/
|
|
29
|
+
export function safeClone(value, maxDepth = 10) {
|
|
30
|
+
const seen = new WeakSet();
|
|
31
|
+
function clone(val, depth) {
|
|
32
|
+
if (depth > maxDepth)
|
|
33
|
+
return '[max depth exceeded]';
|
|
34
|
+
if (val === null || typeof val !== 'object')
|
|
35
|
+
return val;
|
|
36
|
+
if (val instanceof Date)
|
|
37
|
+
return new Date(val.getTime());
|
|
38
|
+
if (val instanceof RegExp)
|
|
39
|
+
return new RegExp(val.source, val.flags);
|
|
40
|
+
if (seen.has(val))
|
|
41
|
+
return '[circular reference]';
|
|
42
|
+
seen.add(val);
|
|
43
|
+
if (Array.isArray(val)) {
|
|
44
|
+
return val.map((item) => clone(item, depth + 1));
|
|
45
|
+
}
|
|
46
|
+
if (val instanceof Map) {
|
|
47
|
+
const result = {};
|
|
48
|
+
for (const [k, v] of val) {
|
|
49
|
+
result[String(k)] = clone(v, depth + 1);
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
if (val instanceof Set) {
|
|
54
|
+
return Array.from(val).map((item) => clone(item, depth + 1));
|
|
55
|
+
}
|
|
56
|
+
const result = {};
|
|
57
|
+
for (const key of Object.keys(val)) {
|
|
58
|
+
result[key] = clone(val[key], depth + 1);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
return clone(value, 0);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Truncate large values for trace storage
|
|
66
|
+
*/
|
|
67
|
+
export function truncateForTrace(value, maxItems = 100, maxStringLength = 1000) {
|
|
68
|
+
if (typeof value === 'string' && value.length > maxStringLength) {
|
|
69
|
+
return value.slice(0, maxStringLength) + `... [truncated, ${value.length} chars total]`;
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(value) && value.length > maxItems) {
|
|
72
|
+
return [...value.slice(0, maxItems), `... [truncated, ${value.length} items total]`];
|
|
73
|
+
}
|
|
74
|
+
if (value && typeof value === 'object') {
|
|
75
|
+
const keys = Object.keys(value);
|
|
76
|
+
if (keys.length > maxItems) {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const key of keys.slice(0, maxItems)) {
|
|
79
|
+
result[key] = value[key];
|
|
80
|
+
}
|
|
81
|
+
result['__truncated__'] = `${keys.length} keys total`;
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trace Store - Persistence for execution traces
|
|
3
|
+
*
|
|
4
|
+
* Stores complete execution traces for time-travel debugging,
|
|
5
|
+
* enabling replay and step-by-step inspection of past runs.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExecutionTrace, TraceSnapshot } from './state.js';
|
|
8
|
+
/**
|
|
9
|
+
* Trace store interface
|
|
10
|
+
*/
|
|
11
|
+
export interface TraceStore {
|
|
12
|
+
/** Save a complete trace */
|
|
13
|
+
save(trace: ExecutionTrace): Promise<void>;
|
|
14
|
+
/** Append a snapshot to an existing trace */
|
|
15
|
+
appendSnapshot(traceId: string, snapshot: TraceSnapshot): Promise<void>;
|
|
16
|
+
/** Load a trace by ID */
|
|
17
|
+
load(id: string): Promise<ExecutionTrace | null>;
|
|
18
|
+
/** Load a specific snapshot from a trace */
|
|
19
|
+
loadSnapshot(traceId: string, snapshotIndex: number): Promise<TraceSnapshot | null>;
|
|
20
|
+
/** List all traces for a mission */
|
|
21
|
+
listByMission(mission: string, limit?: number): Promise<ExecutionTrace[]>;
|
|
22
|
+
/** List recent traces across all missions */
|
|
23
|
+
listRecent(limit?: number): Promise<ExecutionTrace[]>;
|
|
24
|
+
/** Delete a trace */
|
|
25
|
+
delete(id: string): Promise<void>;
|
|
26
|
+
/** Find the latest trace for a mission */
|
|
27
|
+
findLatest(mission: string): Promise<ExecutionTrace | null>;
|
|
28
|
+
/** Get trace metadata without loading all snapshots (for performance) */
|
|
29
|
+
getMetadata(id: string): Promise<Omit<ExecutionTrace, 'snapshots'> | null>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* File-based trace store
|
|
33
|
+
* Stores traces in .reqon-data/traces/ with separate files for metadata and snapshots
|
|
34
|
+
*/
|
|
35
|
+
export declare class FileTraceStore implements TraceStore {
|
|
36
|
+
private baseDir;
|
|
37
|
+
private initialized;
|
|
38
|
+
constructor(baseDir?: string);
|
|
39
|
+
private getTraceDir;
|
|
40
|
+
private getMetadataPath;
|
|
41
|
+
private getSnapshotPath;
|
|
42
|
+
private deserializeTrace;
|
|
43
|
+
private deserializeSnapshot;
|
|
44
|
+
save(trace: ExecutionTrace): Promise<void>;
|
|
45
|
+
appendSnapshot(traceId: string, snapshot: TraceSnapshot): Promise<void>;
|
|
46
|
+
load(id: string): Promise<ExecutionTrace | null>;
|
|
47
|
+
loadSnapshot(traceId: string, snapshotIndex: number): Promise<TraceSnapshot | null>;
|
|
48
|
+
listByMission(mission: string, limit?: number): Promise<ExecutionTrace[]>;
|
|
49
|
+
listRecent(limit?: number): Promise<ExecutionTrace[]>;
|
|
50
|
+
delete(id: string): Promise<void>;
|
|
51
|
+
findLatest(mission: string): Promise<ExecutionTrace | null>;
|
|
52
|
+
getMetadata(id: string): Promise<Omit<ExecutionTrace, 'snapshots'> | null>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* In-memory trace store (for testing)
|
|
56
|
+
*/
|
|
57
|
+
export declare class MemoryTraceStore implements TraceStore {
|
|
58
|
+
private traces;
|
|
59
|
+
save(trace: ExecutionTrace): Promise<void>;
|
|
60
|
+
appendSnapshot(traceId: string, snapshot: TraceSnapshot): Promise<void>;
|
|
61
|
+
load(id: string): Promise<ExecutionTrace | null>;
|
|
62
|
+
loadSnapshot(traceId: string, snapshotIndex: number): Promise<TraceSnapshot | null>;
|
|
63
|
+
listByMission(mission: string, limit?: number): Promise<ExecutionTrace[]>;
|
|
64
|
+
listRecent(limit?: number): Promise<ExecutionTrace[]>;
|
|
65
|
+
delete(id: string): Promise<void>;
|
|
66
|
+
findLatest(mission: string): Promise<ExecutionTrace | null>;
|
|
67
|
+
getMetadata(id: string): Promise<Omit<ExecutionTrace, 'snapshots'> | null>;
|
|
68
|
+
clear(): void;
|
|
69
|
+
}
|