footprintjs 4.17.2 → 6.0.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/CLAUDE.md +71 -9
- package/dist/advanced.js +2 -3
- package/dist/esm/advanced.js +2 -2
- package/dist/esm/index.js +3 -3
- package/dist/esm/lib/builder/FlowChartBuilder.js +359 -70
- package/dist/esm/lib/builder/index.js +1 -1
- package/dist/esm/lib/builder/structure/StructureRecorder.js +158 -0
- package/dist/esm/lib/builder/structure/StructureRecorderDispatcher.js +171 -0
- package/dist/esm/lib/builder/types.js +1 -1
- package/dist/esm/lib/decide/decide.js +9 -9
- package/dist/esm/lib/decide/evidence.js +2 -2
- package/dist/esm/lib/engine/errors/errorInfo.js +4 -3
- package/dist/esm/lib/engine/handlers/ChildrenExecutor.js +11 -2
- package/dist/esm/lib/engine/handlers/DeciderHandler.js +5 -7
- package/dist/esm/lib/engine/handlers/RuntimeStructureManager.js +2 -2
- package/dist/esm/lib/engine/handlers/SelectorHandler.js +9 -7
- package/dist/esm/lib/engine/handlers/SubflowExecutor.js +7 -1
- package/dist/esm/lib/engine/handlers/index.js +1 -3
- package/dist/esm/lib/engine/handlers/types.js +2 -2
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +14 -4
- package/dist/esm/lib/engine/narrative/FlowRecorderDispatcher.js +5 -5
- package/dist/esm/lib/engine/narrative/NarrativeFlowRecorder.js +8 -1
- package/dist/esm/lib/engine/narrative/types.js +1 -1
- package/dist/esm/lib/engine/runtimeStageId.js +64 -2
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +30 -56
- package/dist/esm/lib/engine/types.js +1 -1
- package/dist/esm/lib/engine/walkSubflowSpec.js +144 -0
- package/dist/esm/lib/memory/StageContext.js +3 -3
- package/dist/esm/lib/memory/backtrack.js +1 -1
- package/dist/esm/lib/reactive/createTypedScope.js +5 -5
- package/dist/esm/lib/reactive/types.js +7 -7
- package/dist/esm/lib/recorder/BoundaryStateStore.js +167 -0
- package/dist/esm/lib/recorder/BoundaryStateTracker.js +4 -4
- package/dist/esm/lib/recorder/CombinedRecorder.js +9 -9
- package/dist/esm/lib/recorder/CommitRangeIndex.js +207 -0
- package/dist/esm/lib/recorder/CompositeRecorder.js +6 -6
- package/dist/esm/lib/recorder/EmitRecorder.js +3 -3
- package/dist/esm/lib/recorder/InOutRecorder.js +1 -1
- package/dist/esm/lib/recorder/KeyedStore.js +113 -0
- package/dist/esm/lib/recorder/QualityRecorder.js +2 -2
- package/dist/esm/lib/recorder/SequenceRecorder.js +2 -2
- package/dist/esm/lib/recorder/SequenceStore.js +195 -0
- package/dist/esm/lib/recorder/TopologyRecorder.js +1 -1
- package/dist/esm/lib/recorder/index.js +13 -3
- package/dist/esm/lib/runner/ExecutionRuntime.js +1 -1
- package/dist/esm/lib/runner/FlowChartExecutor.js +75 -44
- package/dist/esm/lib/runner/RunContext.js +2 -2
- package/dist/esm/lib/runner/RunnableChart.js +1 -1
- package/dist/esm/lib/runner/getSubtreeSnapshot.js +3 -2
- package/dist/esm/lib/runner/runId.js +65 -0
- package/dist/esm/lib/scope/ScopeFacade.js +6 -6
- package/dist/esm/lib/scope/index.js +1 -1
- package/dist/esm/lib/scope/recorders/DebugRecorder.js +4 -4
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +2 -2
- package/dist/esm/lib/scope/recorders/index.js +1 -1
- package/dist/esm/lib/scope/types.js +1 -1
- package/dist/esm/recorders.js +1 -1
- package/dist/esm/trace.js +15 -2
- package/dist/index.js +3 -3
- package/dist/lib/builder/FlowChartBuilder.js +359 -70
- package/dist/lib/builder/index.js +1 -1
- package/dist/lib/builder/structure/StructureRecorder.js +159 -0
- package/dist/lib/builder/structure/StructureRecorderDispatcher.js +175 -0
- package/dist/lib/builder/types.js +1 -1
- package/dist/lib/decide/decide.js +9 -9
- package/dist/lib/decide/evidence.js +2 -2
- package/dist/lib/engine/errors/errorInfo.js +4 -3
- package/dist/lib/engine/handlers/ChildrenExecutor.js +11 -2
- package/dist/lib/engine/handlers/DeciderHandler.js +5 -7
- package/dist/lib/engine/handlers/RuntimeStructureManager.js +2 -2
- package/dist/lib/engine/handlers/SelectorHandler.js +9 -7
- package/dist/lib/engine/handlers/SubflowExecutor.js +7 -1
- package/dist/lib/engine/handlers/index.js +2 -5
- package/dist/lib/engine/handlers/types.js +2 -2
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +14 -4
- package/dist/lib/engine/narrative/FlowRecorderDispatcher.js +5 -5
- package/dist/lib/engine/narrative/NarrativeFlowRecorder.js +8 -1
- package/dist/lib/engine/narrative/types.js +1 -1
- package/dist/lib/engine/runtimeStageId.js +66 -3
- package/dist/lib/engine/traversal/FlowchartTraverser.js +30 -56
- package/dist/lib/engine/types.js +1 -1
- package/dist/lib/engine/walkSubflowSpec.js +148 -0
- package/dist/lib/memory/StageContext.js +3 -3
- package/dist/lib/memory/backtrack.js +1 -1
- package/dist/lib/reactive/createTypedScope.js +5 -5
- package/dist/lib/reactive/types.js +7 -7
- package/dist/lib/recorder/BoundaryStateStore.js +171 -0
- package/dist/lib/recorder/BoundaryStateTracker.js +4 -4
- package/dist/lib/recorder/CombinedRecorder.js +9 -9
- package/dist/lib/recorder/CommitRangeIndex.js +211 -0
- package/dist/lib/recorder/CompositeRecorder.js +6 -6
- package/dist/lib/recorder/EmitRecorder.js +3 -3
- package/dist/lib/recorder/InOutRecorder.js +1 -1
- package/dist/lib/recorder/KeyedStore.js +117 -0
- package/dist/lib/recorder/QualityRecorder.js +2 -2
- package/dist/lib/recorder/SequenceRecorder.js +2 -2
- package/dist/lib/recorder/SequenceStore.js +199 -0
- package/dist/lib/recorder/TopologyRecorder.js +1 -1
- package/dist/lib/recorder/index.js +19 -6
- package/dist/lib/runner/ExecutionRuntime.js +1 -1
- package/dist/lib/runner/FlowChartExecutor.js +75 -44
- package/dist/lib/runner/RunContext.js +2 -2
- package/dist/lib/runner/RunnableChart.js +1 -1
- package/dist/lib/runner/getSubtreeSnapshot.js +3 -2
- package/dist/lib/runner/runId.js +70 -0
- package/dist/lib/scope/ScopeFacade.js +6 -6
- package/dist/lib/scope/index.js +1 -1
- package/dist/lib/scope/recorders/DebugRecorder.js +4 -4
- package/dist/lib/scope/recorders/MetricRecorder.js +2 -2
- package/dist/lib/scope/recorders/index.js +1 -1
- package/dist/lib/scope/types.js +1 -1
- package/dist/recorders.js +1 -1
- package/dist/trace.js +21 -2
- package/dist/types/advanced.d.ts +4 -4
- package/dist/types/index.d.ts +6 -4
- package/dist/types/lib/builder/FlowChartBuilder.d.ts +110 -14
- package/dist/types/lib/builder/index.d.ts +2 -1
- package/dist/types/lib/builder/structure/StructureRecorder.d.ts +349 -0
- package/dist/types/lib/builder/structure/StructureRecorderDispatcher.d.ts +77 -0
- package/dist/types/lib/builder/types.d.ts +20 -6
- package/dist/types/lib/decide/evidence.d.ts +3 -3
- package/dist/types/lib/engine/errors/errorInfo.d.ts +3 -2
- package/dist/types/lib/engine/handlers/DeciderHandler.d.ts +3 -3
- package/dist/types/lib/engine/handlers/RuntimeStructureManager.d.ts +1 -1
- package/dist/types/lib/engine/handlers/SelectorHandler.d.ts +2 -2
- package/dist/types/lib/engine/handlers/index.d.ts +1 -2
- package/dist/types/lib/engine/handlers/types.d.ts +2 -9
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +1 -1
- package/dist/types/lib/engine/narrative/FlowRecorderDispatcher.d.ts +4 -4
- package/dist/types/lib/engine/narrative/types.d.ts +43 -4
- package/dist/types/lib/engine/runtimeStageId.d.ts +57 -1
- package/dist/types/lib/engine/traversal/FlowchartTraverser.d.ts +12 -6
- package/dist/types/lib/engine/types.d.ts +0 -26
- package/dist/types/lib/engine/walkSubflowSpec.d.ts +95 -0
- package/dist/types/lib/memory/StageContext.d.ts +2 -2
- package/dist/types/lib/memory/backtrack.d.ts +1 -1
- package/dist/types/lib/reactive/types.d.ts +7 -7
- package/dist/types/lib/recorder/BoundaryStateStore.d.ts +115 -0
- package/dist/types/lib/recorder/BoundaryStateTracker.d.ts +3 -3
- package/dist/types/lib/recorder/CombinedRecorder.d.ts +11 -11
- package/dist/types/lib/recorder/CommitRangeIndex.d.ts +147 -0
- package/dist/types/lib/recorder/CompositeRecorder.d.ts +8 -8
- package/dist/types/lib/recorder/EmitRecorder.d.ts +2 -2
- package/dist/types/lib/recorder/InOutRecorder.d.ts +1 -1
- package/dist/types/lib/recorder/KeyedStore.d.ts +70 -0
- package/dist/types/lib/recorder/QualityRecorder.d.ts +4 -4
- package/dist/types/lib/recorder/SequenceRecorder.d.ts +1 -1
- package/dist/types/lib/recorder/SequenceStore.d.ts +120 -0
- package/dist/types/lib/recorder/TopologyRecorder.d.ts +1 -1
- package/dist/types/lib/recorder/index.d.ts +5 -2
- package/dist/types/lib/runner/ExecutionRuntime.d.ts +1 -1
- package/dist/types/lib/runner/FlowChartExecutor.d.ts +40 -30
- package/dist/types/lib/runner/RunContext.d.ts +2 -2
- package/dist/types/lib/runner/RunnableChart.d.ts +2 -2
- package/dist/types/lib/runner/runId.d.ts +45 -0
- package/dist/types/lib/scope/ScopeFacade.d.ts +4 -4
- package/dist/types/lib/scope/index.d.ts +1 -1
- package/dist/types/lib/scope/recorders/DebugRecorder.d.ts +4 -4
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +4 -4
- package/dist/types/lib/scope/recorders/index.d.ts +1 -1
- package/dist/types/lib/scope/types.d.ts +1 -1
- package/dist/types/recorders.d.ts +1 -1
- package/dist/types/trace.d.ts +8 -1
- package/package.json +1 -1
- package/dist/esm/lib/engine/handlers/ExtractorRunner.js +0 -122
- package/dist/lib/engine/handlers/ExtractorRunner.js +0 -126
- package/dist/types/lib/engine/handlers/ExtractorRunner.d.ts +0 -41
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* const executor = new FlowChartExecutor(chart);
|
|
10
10
|
*
|
|
11
11
|
* // Options-object form (preferred when you need to customize behavior):
|
|
12
|
-
* const executor = new FlowChartExecutor(chart, { scopeFactory: myFactory
|
|
12
|
+
* const executor = new FlowChartExecutor(chart, { scopeFactory: myFactory });
|
|
13
13
|
*
|
|
14
14
|
* // 2-param form (accepts a ScopeFactory directly, for backward compatibility):
|
|
15
15
|
* const executor = new FlowChartExecutor(chart, myFactory);
|
|
@@ -21,12 +21,12 @@ import type { CombinedNarrativeRecorderOptions } from '../engine/narrative/Combi
|
|
|
21
21
|
import type { CombinedNarrativeEntry } from '../engine/narrative/narrativeTypes.js';
|
|
22
22
|
import type { ManifestEntry } from '../engine/narrative/recorders/ManifestFlowRecorder.js';
|
|
23
23
|
import type { FlowRecorder } from '../engine/narrative/types.js';
|
|
24
|
-
import { type ExecutorResult, type
|
|
24
|
+
import { type ExecutorResult, type RunOptions, type ScopeFactory, type SerializedPipelineStructure, type StageNode, type StreamHandlers, type SubflowResult } from '../engine/types.js';
|
|
25
25
|
import type { FlowchartCheckpoint } from '../pause/types.js';
|
|
26
26
|
import type { CombinedRecorder } from '../recorder/CombinedRecorder.js';
|
|
27
27
|
import type { EmitRecorder } from '../recorder/EmitRecorder.js';
|
|
28
28
|
import type { ScopeProtectionMode } from '../scope/protection/types.js';
|
|
29
|
-
import type {
|
|
29
|
+
import type { RedactionPolicy, RedactionReport, ScopeRecorder } from '../scope/types.js';
|
|
30
30
|
import { type RuntimeSnapshot } from './ExecutionRuntime.js';
|
|
31
31
|
/**
|
|
32
32
|
* Options object for `FlowChartExecutor` — preferred over positional params.
|
|
@@ -34,7 +34,7 @@ import { type RuntimeSnapshot } from './ExecutionRuntime.js';
|
|
|
34
34
|
* ```typescript
|
|
35
35
|
* const ex = new FlowChartExecutor(chart, {
|
|
36
36
|
* scopeFactory: myFactory,
|
|
37
|
-
*
|
|
37
|
+
* defaultValuesForContext: { ... },
|
|
38
38
|
* });
|
|
39
39
|
* ```
|
|
40
40
|
*
|
|
@@ -50,14 +50,6 @@ import { type RuntimeSnapshot } from './ExecutionRuntime.js';
|
|
|
50
50
|
export interface FlowChartExecutorOptions<TScope = any> {
|
|
51
51
|
/** Custom scope factory. Defaults to TypedScope or ScopeFacade auto-detection. */
|
|
52
52
|
scopeFactory?: ScopeFactory<TScope>;
|
|
53
|
-
/**
|
|
54
|
-
* Attach a per-stage scope snapshot to each extractor result. When `true`, the
|
|
55
|
-
* extraction callback receives the full shared state at the point that stage
|
|
56
|
-
* committed — useful for debugging multi-stage state transitions. Defaults to
|
|
57
|
-
* `false` (no scope snapshot attached). Can also be set on the chart via
|
|
58
|
-
* `flowChart(...).enrichSnapshots(true)`.
|
|
59
|
-
*/
|
|
60
|
-
enrichSnapshots?: boolean;
|
|
61
53
|
/**
|
|
62
54
|
* Default values pre-populated into the shared context before **each** stage
|
|
63
55
|
* (re-applied every stage, acting as baseline defaults).
|
|
@@ -86,6 +78,10 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
86
78
|
private traverser;
|
|
87
79
|
/** Shared execution counter — survives pause/resume. Reset on fresh run(). */
|
|
88
80
|
private _executionCounter;
|
|
81
|
+
/** Per-`run()` identifier — generated fresh per run + per resume. Threaded
|
|
82
|
+
* through every TraversalContext so recorders can scope state to a single
|
|
83
|
+
* run. See `runId.ts`. */
|
|
84
|
+
private _currentRunId;
|
|
89
85
|
private narrativeEnabled;
|
|
90
86
|
private narrativeOptions?;
|
|
91
87
|
private combinedRecorder;
|
|
@@ -117,7 +113,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
117
113
|
*
|
|
118
114
|
* **Options object form** (preferred):
|
|
119
115
|
* ```typescript
|
|
120
|
-
* new FlowChartExecutor(chart, { scopeFactory,
|
|
116
|
+
* new FlowChartExecutor(chart, { scopeFactory, defaultValuesForContext })
|
|
121
117
|
* ```
|
|
122
118
|
*
|
|
123
119
|
* **2-param form** (also supported):
|
|
@@ -159,6 +155,24 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
159
155
|
getCheckpoint(): FlowchartCheckpoint | undefined;
|
|
160
156
|
/** Returns `true` if the most recent run() was paused (checkpoint available). */
|
|
161
157
|
isPaused(): boolean;
|
|
158
|
+
/**
|
|
159
|
+
* Number of commits in the run's commit log. O(1) — direct length
|
|
160
|
+
* read, no snapshot materialization. Use this to stamp commit
|
|
161
|
+
* indices on observer events (e.g., `BoundaryRecorder` storing
|
|
162
|
+
* `commitIdxBefore` / `commitIdxAfter` per domain event for
|
|
163
|
+
* `CommitRangeIndex` queries — see `footprintjs/trace`).
|
|
164
|
+
*
|
|
165
|
+
* Returns 0 before any run; after, returns the cumulative commit
|
|
166
|
+
* count across the executor's lifetime (including resumes).
|
|
167
|
+
*
|
|
168
|
+
* IMPLEMENTATION NOTE: this returns `runtime.executionHistory.length`,
|
|
169
|
+
* which is the same value as `getSnapshot().commitLog.length`. The
|
|
170
|
+
* naming asymmetry is historical — the underlying `EventLog` field
|
|
171
|
+
* is named `executionHistory` but stores the `CommitBundle[]` that
|
|
172
|
+
* `commitLog` exposes. They are the SAME array (verified by the
|
|
173
|
+
* "matches commitLog.length" integration test).
|
|
174
|
+
*/
|
|
175
|
+
getCommitCount(): number;
|
|
162
176
|
/**
|
|
163
177
|
* Resume a paused flowchart from a checkpoint.
|
|
164
178
|
*
|
|
@@ -201,7 +215,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
201
215
|
/** DFS search for a node by ID in the StageNode graph. Cycle-safe via visited set. */
|
|
202
216
|
private dfsFind;
|
|
203
217
|
/**
|
|
204
|
-
* Attach a scope
|
|
218
|
+
* Attach a scope ScopeRecorder to observe data operations (reads, writes, commits).
|
|
205
219
|
* Automatically attached to every ScopeFacade created during traversal.
|
|
206
220
|
* Must be called before run().
|
|
207
221
|
*
|
|
@@ -216,18 +230,18 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
216
230
|
* @example
|
|
217
231
|
* ```typescript
|
|
218
232
|
* // Multiple recorders with different configs — each gets a unique ID
|
|
219
|
-
* executor.
|
|
220
|
-
* executor.
|
|
233
|
+
* executor.attachScopeRecorder(new MetricRecorder());
|
|
234
|
+
* executor.attachScopeRecorder(new DebugRecorder({ verbosity: 'minimal' }));
|
|
221
235
|
*
|
|
222
236
|
* // Override a framework-attached recorder by passing its well-known ID
|
|
223
|
-
* executor.
|
|
237
|
+
* executor.attachScopeRecorder(new MetricRecorder('metrics'));
|
|
224
238
|
*
|
|
225
239
|
* // Attaching twice with same ID replaces (no double-counting)
|
|
226
|
-
* executor.
|
|
227
|
-
* executor.
|
|
240
|
+
* executor.attachScopeRecorder(new MetricRecorder('my-metrics'));
|
|
241
|
+
* executor.attachScopeRecorder(new MetricRecorder('my-metrics')); // replaces previous
|
|
228
242
|
* ```
|
|
229
243
|
*/
|
|
230
|
-
|
|
244
|
+
attachScopeRecorder(recorder: ScopeRecorder): void;
|
|
231
245
|
/**
|
|
232
246
|
* Detach a child flowchart on the given driver and return a `DetachHandle`
|
|
233
247
|
* the caller can `wait()` on (Promise) or read `.status` from (sync).
|
|
@@ -257,9 +271,9 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
257
271
|
*/
|
|
258
272
|
detachAndForget(driver: import('../detach/types.js').DetachDriver, child: import('../builder/types.js').FlowChart, input?: unknown): void;
|
|
259
273
|
/** Detach all scope Recorders with the given ID. */
|
|
260
|
-
|
|
274
|
+
detachScopeRecorder(id: string): void;
|
|
261
275
|
/** Returns a defensive copy of attached scope Recorders. */
|
|
262
|
-
|
|
276
|
+
getScopeRecorders(): ScopeRecorder[];
|
|
263
277
|
/**
|
|
264
278
|
* Attach a FlowRecorder to observe control flow events.
|
|
265
279
|
* Automatically enables narrative if not already enabled.
|
|
@@ -277,7 +291,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
277
291
|
* data-flow, control-flow, or both). Detects at runtime which streams the
|
|
278
292
|
* recorder has methods for and routes it to the correct internal channels.
|
|
279
293
|
*
|
|
280
|
-
* Preferred over calling `
|
|
294
|
+
* Preferred over calling `attachScopeRecorder` and `attachFlowRecorder`
|
|
281
295
|
* separately, because forgetting one of the two is a silent foot-gun —
|
|
282
296
|
* half your events never fire and there is no runtime warning. With
|
|
283
297
|
* `attachCombinedRecorder` the library guarantees the recorder's declared
|
|
@@ -287,7 +301,7 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
287
301
|
*
|
|
288
302
|
* Idempotent by `id` across ALL channels — re-attaching with the same `id`
|
|
289
303
|
* replaces the previous instance everywhere it was registered. Mixing
|
|
290
|
-
* `attachCombinedRecorder(x)` with a prior `
|
|
304
|
+
* `attachCombinedRecorder(x)` with a prior `attachScopeRecorder(y)` or
|
|
291
305
|
* `attachFlowRecorder(y)` that share `x.id === y.id` is also safe: the
|
|
292
306
|
* combined attach replaces the single-channel registration on whichever
|
|
293
307
|
* channel(s) `x` has methods for. No duplicate firings occur.
|
|
@@ -330,8 +344,8 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
330
344
|
* Internally, emit recorders share the scope-recorder channel because
|
|
331
345
|
* emit events fire from inside `ScopeFacade` during stage execution,
|
|
332
346
|
* same timing as `onRead`/`onWrite`. This method is a convenience that
|
|
333
|
-
* delegates to `
|
|
334
|
-
* `
|
|
347
|
+
* delegates to `attachScopeRecorder` — consumers can also use
|
|
348
|
+
* `attachScopeRecorder` directly for a recorder that implements BOTH
|
|
335
349
|
* `onWrite` and `onEmit`. Either approach places the recorder on the
|
|
336
350
|
* same underlying list, so `onEmit` fires exactly once per event.
|
|
337
351
|
*
|
|
@@ -397,10 +411,6 @@ export declare class FlowChartExecutor<TOut = any, TScope = any> {
|
|
|
397
411
|
getRuntimeStructure(): SerializedPipelineStructure | undefined;
|
|
398
412
|
/** @internal */
|
|
399
413
|
getSubflowResults(): Map<string, SubflowResult>;
|
|
400
|
-
/** @internal */
|
|
401
|
-
getExtractedResults<TResult = unknown>(): Map<string, TResult>;
|
|
402
|
-
/** @internal */
|
|
403
|
-
getExtractorErrors(): ExtractorError[];
|
|
404
414
|
/**
|
|
405
415
|
* Returns the subflow manifest from an attached ManifestFlowRecorder.
|
|
406
416
|
* Returns empty array if no ManifestFlowRecorder is attached.
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import type { FlowChart } from '../builder/types.js';
|
|
11
11
|
import type { FlowRecorder } from '../engine/narrative/types.js';
|
|
12
12
|
import type { RunOptions } from '../engine/types.js';
|
|
13
|
-
import type {
|
|
13
|
+
import type { RedactionPolicy, ScopeRecorder } from '../scope/types.js';
|
|
14
14
|
/** Result from RunContext.run() — owns state and output. */
|
|
15
15
|
export interface RunResult {
|
|
16
16
|
/** Raw scope state after execution. */
|
|
@@ -29,7 +29,7 @@ export declare class RunContext<TOut = any, TScope = any> {
|
|
|
29
29
|
private redactionPolicy?;
|
|
30
30
|
constructor(chart: FlowChart<TOut, TScope>);
|
|
31
31
|
/** Attach a recorder. Auto-detects scope vs flow recorder. Chainable. */
|
|
32
|
-
recorder(r:
|
|
32
|
+
recorder(r: ScopeRecorder | FlowRecorder): RunContext<TOut, TScope>;
|
|
33
33
|
/** Set redaction policy for this run. Chainable. */
|
|
34
34
|
redact(policy: RedactionPolicy): RunContext<TOut, TScope>;
|
|
35
35
|
/** Execute the chart with accumulated config. Returns RunResult. */
|
|
@@ -9,7 +9,7 @@ import type { FlowChart } from '../builder/types.js';
|
|
|
9
9
|
import type { JsonSchema } from '../contract/types.js';
|
|
10
10
|
import type { FlowRecorder } from '../engine/narrative/types.js';
|
|
11
11
|
import type { RunOptions } from '../engine/types.js';
|
|
12
|
-
import type {
|
|
12
|
+
import type { RedactionPolicy, ScopeRecorder } from '../scope/types.js';
|
|
13
13
|
import { type RunResult, RunContext } from './RunContext.js';
|
|
14
14
|
/** OpenAPI generation options. */
|
|
15
15
|
export interface ChartOpenAPIOptions {
|
|
@@ -38,7 +38,7 @@ export interface MCPToolDescription {
|
|
|
38
38
|
*/
|
|
39
39
|
export interface RunnableFlowChart<TOut = any, TScope = any> extends FlowChart<TOut, TScope> {
|
|
40
40
|
/** Attach a recorder for the next run. Returns a chainable RunContext. */
|
|
41
|
-
recorder(r:
|
|
41
|
+
recorder(r: ScopeRecorder | FlowRecorder): RunContext<TOut, TScope>;
|
|
42
42
|
/** Set redaction policy for the next run. Returns a chainable RunContext. */
|
|
43
43
|
redact(policy: RedactionPolicy): RunContext<TOut, TScope>;
|
|
44
44
|
/** Execute the chart directly (bare run, no recorders). */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runId — per-`executor.run()` identifier generator.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: monotonic counter + clock-guarded timestamp. One id per
|
|
5
|
+
* call to `executor.run()` (or `executor.resume()`). Stable
|
|
6
|
+
* for the duration of that run; unique across consecutive
|
|
7
|
+
* runs.
|
|
8
|
+
* Role: primitive that solves the "two consecutive runs of the
|
|
9
|
+
* same executor produce identical runtimeStageIds" class of
|
|
10
|
+
* bugs. Recorders that accumulate state across runs detect
|
|
11
|
+
* "new run" via `runId` change and reset transient
|
|
12
|
+
* bookkeeping.
|
|
13
|
+
*
|
|
14
|
+
* Format: `${timestamp}-${counter}`.
|
|
15
|
+
* - `timestamp` is `Date.now()` clamped to a monotonic-clock guard
|
|
16
|
+
* (never decreases — protects against NTP / system-clock
|
|
17
|
+
* adjustments).
|
|
18
|
+
* - `counter` is a process-local incrementing integer, ZERO-PADDED
|
|
19
|
+
* to 10 digits so lexicographic sort matches numeric order
|
|
20
|
+
* (`"...001"` < `"...010"` < `"...100"`). 10 digits = 10 billion
|
|
21
|
+
* runs in a single process — sufficient for any real workload.
|
|
22
|
+
*
|
|
23
|
+
* Lexicographic ordering of `runId` strings matches chronological
|
|
24
|
+
* ordering for runs that are at least 1ms apart, AND for runs that
|
|
25
|
+
* happen within the same millisecond (because the padded counter
|
|
26
|
+
* tie-breaks). The counter NEVER resets — it is process-global.
|
|
27
|
+
*
|
|
28
|
+
* Process-local only. Cross-process correlation uses
|
|
29
|
+
* `getEnv().traceId` (consumer-supplied), not `runId`. Documented
|
|
30
|
+
* in `docs/design/v5-recorder-redesign.md` Section 8.1.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Generate a fresh runId. Called once per `executor.run()` and once
|
|
34
|
+
* per `executor.resume()`. Pure (deterministic for a given clock +
|
|
35
|
+
* counter state); no side effects beyond advancing the counter and
|
|
36
|
+
* monotonic-clock guard.
|
|
37
|
+
*/
|
|
38
|
+
export declare function generateRunId(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Reset the runId state. Test-only. NEVER call from production code —
|
|
41
|
+
* runIds must be process-globally monotonic.
|
|
42
|
+
*
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export declare function _resetRunIdStateForTesting(): void;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import type { ExecutionEnv } from '../engine/types.js';
|
|
17
17
|
import { StageContext } from '../memory/StageContext.js';
|
|
18
|
-
import type { CommitEvent,
|
|
18
|
+
import type { CommitEvent, RedactionPolicy, RedactionReport, ScopeRecorder } from './types.js';
|
|
19
19
|
export declare class ScopeFacade {
|
|
20
20
|
static readonly BRAND: unique symbol;
|
|
21
21
|
/**
|
|
@@ -60,9 +60,9 @@ export declare class ScopeFacade {
|
|
|
60
60
|
* Never includes actual values — only key names, field names, and patterns.
|
|
61
61
|
*/
|
|
62
62
|
getRedactionReport(): RedactionReport;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
attachScopeRecorder(recorder: ScopeRecorder): void;
|
|
64
|
+
detachScopeRecorder(recorderId: string): void;
|
|
65
|
+
getScopeRecorders(): ScopeRecorder[];
|
|
66
66
|
/** @internal */
|
|
67
67
|
notifyStageStart(): void;
|
|
68
68
|
/** @internal */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* providers, protection, and Zod-based scope definitions.
|
|
6
6
|
*/
|
|
7
7
|
export { ScopeFacade } from './ScopeFacade.js';
|
|
8
|
-
export type { CommitEvent, ErrorEvent, ReadEvent,
|
|
8
|
+
export type { CommitEvent, ErrorEvent, ReadEvent, RecorderContext, RedactionPolicy, RedactionReport, ScopeRecorder, StageEvent, WriteEvent, } from './types.js';
|
|
9
9
|
export type { DebugEntry, DebugRecorderOptions, DebugVerbosity } from './recorders/DebugRecorder.js';
|
|
10
10
|
export { DebugRecorder } from './recorders/DebugRecorder.js';
|
|
11
11
|
export type { AggregatedMetrics, StageMetrics } from './recorders/MetricRecorder.js';
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and stage lifecycle events for troubleshooting.
|
|
6
6
|
*/
|
|
7
7
|
import type { RecorderOperation } from '../../recorder/RecorderOperation.js';
|
|
8
|
-
import type { ErrorEvent, PauseEvent, ReadEvent,
|
|
8
|
+
import type { ErrorEvent, PauseEvent, ReadEvent, ResumeEvent, ScopeRecorder, StageEvent, WriteEvent } from '../types.js';
|
|
9
9
|
export type DebugVerbosity = 'minimal' | 'verbose';
|
|
10
10
|
export interface DebugEntry {
|
|
11
11
|
type: 'read' | 'write' | 'error' | 'stageStart' | 'stageEnd' | 'pause' | 'resume';
|
|
@@ -26,15 +26,15 @@ export interface DebugRecorderOptions {
|
|
|
26
26
|
* @example
|
|
27
27
|
* ```typescript
|
|
28
28
|
* // Verbose debug for development
|
|
29
|
-
* executor.
|
|
29
|
+
* executor.attachScopeRecorder(new DebugRecorder({ verbosity: 'verbose' }));
|
|
30
30
|
*
|
|
31
31
|
* // Minimal debug for production (errors only)
|
|
32
|
-
* executor.
|
|
32
|
+
* executor.attachScopeRecorder(new DebugRecorder({ verbosity: 'minimal' }));
|
|
33
33
|
*
|
|
34
34
|
* // Both coexist — different auto IDs
|
|
35
35
|
* ```
|
|
36
36
|
*/
|
|
37
|
-
export declare class DebugRecorder implements
|
|
37
|
+
export declare class DebugRecorder implements ScopeRecorder {
|
|
38
38
|
private static _counter;
|
|
39
39
|
readonly id: string;
|
|
40
40
|
readonly preferredOperation: RecorderOperation;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @example
|
|
8
8
|
* ```typescript
|
|
9
9
|
* const metric = new MetricRecorder();
|
|
10
|
-
* executor.
|
|
10
|
+
* executor.attachScopeRecorder(metric);
|
|
11
11
|
* await executor.run();
|
|
12
12
|
*
|
|
13
13
|
* // Per-step (time-travel):
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { KeyedRecorder } from '../../recorder/KeyedRecorder.js';
|
|
24
24
|
import type { RecorderOperation } from '../../recorder/RecorderOperation.js';
|
|
25
|
-
import type { CommitEvent, PauseEvent, ReadEvent,
|
|
25
|
+
import type { CommitEvent, PauseEvent, ReadEvent, ScopeRecorder, StageEvent, WriteEvent } from '../types.js';
|
|
26
26
|
/** Per-invocation metrics for a single execution step. */
|
|
27
27
|
export interface StepMetrics {
|
|
28
28
|
/** Human-readable stage name. */
|
|
@@ -60,14 +60,14 @@ export interface StageMetrics {
|
|
|
60
60
|
}
|
|
61
61
|
/** Options for MetricRecorder. */
|
|
62
62
|
export interface MetricRecorderOptions {
|
|
63
|
-
/**
|
|
63
|
+
/** ScopeRecorder ID. Defaults to auto-increment (`metrics-1`, `metrics-2`, ...). */
|
|
64
64
|
id?: string;
|
|
65
65
|
/** Filter which stages are recorded. Return `true` to record, `false` to skip. */
|
|
66
66
|
stageFilter?: (stageName: string) => boolean;
|
|
67
67
|
/** Preferred UI operation. Defaults to 'aggregate' (dashboard totals). */
|
|
68
68
|
preferredOperation?: RecorderOperation;
|
|
69
69
|
}
|
|
70
|
-
export declare class MetricRecorder extends KeyedRecorder<StepMetrics> implements
|
|
70
|
+
export declare class MetricRecorder extends KeyedRecorder<StepMetrics> implements ScopeRecorder {
|
|
71
71
|
private static _counter;
|
|
72
72
|
readonly id: string;
|
|
73
73
|
readonly preferredOperation: RecorderOperation;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { CommitEvent, ErrorEvent, ReadEvent,
|
|
1
|
+
export type { CommitEvent, ErrorEvent, ReadEvent, RecorderContext, ScopeRecorder, StageEvent, WriteEvent, } from '../types.js';
|
|
2
2
|
export type { DebugEntry, DebugRecorderOptions, DebugVerbosity } from './DebugRecorder.js';
|
|
3
3
|
export { DebugRecorder } from './DebugRecorder.js';
|
|
4
4
|
export type { AggregatedMetrics, StageMetrics, StepMetrics } from './MetricRecorder.js';
|
|
@@ -100,7 +100,7 @@ export interface RedactionReport {
|
|
|
100
100
|
* If a recorder throws, the error is caught and passed to onError
|
|
101
101
|
* hooks of other recorders; the scope operation continues normally.
|
|
102
102
|
*/
|
|
103
|
-
export interface
|
|
103
|
+
export interface ScopeRecorder {
|
|
104
104
|
readonly id: string;
|
|
105
105
|
onRead?(event: ReadEvent): void;
|
|
106
106
|
onWrite?(event: WriteEvent): void;
|
|
@@ -37,7 +37,7 @@ import { DebugRecorder } from './lib/scope/recorders/DebugRecorder.js';
|
|
|
37
37
|
import type { AggregatedMetrics, MetricRecorderOptions, StageMetrics } from './lib/scope/recorders/MetricRecorder.js';
|
|
38
38
|
import { MetricRecorder } from './lib/scope/recorders/MetricRecorder.js';
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
40
|
+
* ScopeRecorder factory for combined flow+data narrative.
|
|
41
41
|
*
|
|
42
42
|
* The returned recorder is a `CombinedNarrativeRecorder` — attach it to a
|
|
43
43
|
* chart/executor, then read structured entries via `.getEntries()` after
|
package/dist/types/trace.d.ts
CHANGED
|
@@ -21,10 +21,17 @@
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
export type { ExecutionCounter } from './lib/engine/runtimeStageId.js';
|
|
24
|
-
export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId } from './lib/engine/runtimeStageId.js';
|
|
24
|
+
export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId, splitStageId, } from './lib/engine/runtimeStageId.js';
|
|
25
|
+
export type { WalkerItem, WalkerOptions } from './lib/engine/walkSubflowSpec.js';
|
|
26
|
+
export { walkSubflowSpec } from './lib/engine/walkSubflowSpec.js';
|
|
25
27
|
export { findCommit, findCommits, findLastWriter } from './lib/memory/commitLogUtils.js';
|
|
26
28
|
export type { CausalChainOptions, CausalNode, KeysReadLookup } from './lib/memory/backtrack.js';
|
|
27
29
|
export { causalChain, flattenCausalDAG, formatCausalChain } from './lib/memory/backtrack.js';
|
|
30
|
+
export { BoundaryStateStore } from './lib/recorder/BoundaryStateStore.js';
|
|
31
|
+
export { KeyedStore } from './lib/recorder/KeyedStore.js';
|
|
32
|
+
export { SequenceStore } from './lib/recorder/SequenceStore.js';
|
|
33
|
+
export type { RangeEntry, RangeToken } from './lib/recorder/CommitRangeIndex.js';
|
|
34
|
+
export { CommitRangeIndex } from './lib/recorder/CommitRangeIndex.js';
|
|
28
35
|
export { KeyedRecorder } from './lib/recorder/KeyedRecorder.js';
|
|
29
36
|
export { SequenceRecorder } from './lib/recorder/SequenceRecorder.js';
|
|
30
37
|
export { BoundaryStateTracker } from './lib/recorder/BoundaryStateTracker.js';
|
package/package.json
CHANGED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ExtractorRunner — Per-stage snapshot extraction.
|
|
3
|
-
*
|
|
4
|
-
* Coordinates traversal extractor invocations: step counting,
|
|
5
|
-
* snapshot enrichment, error collection, and result storage.
|
|
6
|
-
*/
|
|
7
|
-
import { computeNodeType } from './RuntimeStructureManager.js';
|
|
8
|
-
export class ExtractorRunner {
|
|
9
|
-
extractor;
|
|
10
|
-
enrichSnapshots;
|
|
11
|
-
executionRuntime;
|
|
12
|
-
logger;
|
|
13
|
-
extractedResults = new Map();
|
|
14
|
-
extractorErrors = [];
|
|
15
|
-
stepCounter = 0;
|
|
16
|
-
/** Current subflow context for metadata propagation. Set/cleared during subflow execution. */
|
|
17
|
-
currentSubflowId;
|
|
18
|
-
/** Current fork context for metadata propagation. Set/cleared during parallel children execution. */
|
|
19
|
-
currentForkId;
|
|
20
|
-
constructor(extractor, enrichSnapshots, executionRuntime, logger) {
|
|
21
|
-
this.extractor = extractor;
|
|
22
|
-
this.enrichSnapshots = enrichSnapshots;
|
|
23
|
-
this.executionRuntime = executionRuntime;
|
|
24
|
-
this.logger = logger;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Call the extractor for a stage and store the result.
|
|
28
|
-
* Increments stepCounter (1-based) before creating snapshot.
|
|
29
|
-
*/
|
|
30
|
-
callExtractor(node, context, stagePath, stageOutput, errorInfo) {
|
|
31
|
-
if (!this.extractor)
|
|
32
|
-
return;
|
|
33
|
-
this.stepCounter++;
|
|
34
|
-
try {
|
|
35
|
-
const snapshot = {
|
|
36
|
-
node,
|
|
37
|
-
context,
|
|
38
|
-
stepNumber: this.stepCounter,
|
|
39
|
-
structureMetadata: this.buildStructureMetadata(node),
|
|
40
|
-
};
|
|
41
|
-
if (this.enrichSnapshots) {
|
|
42
|
-
try {
|
|
43
|
-
snapshot.scopeState = { ...this.executionRuntime.globalStore.getState() };
|
|
44
|
-
snapshot.debugInfo = {
|
|
45
|
-
logs: { ...context.debug.logContext },
|
|
46
|
-
errors: { ...context.debug.errorContext },
|
|
47
|
-
metrics: { ...context.debug.metricContext },
|
|
48
|
-
evals: { ...context.debug.evalContext },
|
|
49
|
-
};
|
|
50
|
-
if (context.debug.flowMessages.length > 0) {
|
|
51
|
-
snapshot.debugInfo.flowMessages = [...context.debug.flowMessages];
|
|
52
|
-
}
|
|
53
|
-
snapshot.stageOutput = stageOutput;
|
|
54
|
-
if (errorInfo) {
|
|
55
|
-
snapshot.errorInfo = errorInfo;
|
|
56
|
-
}
|
|
57
|
-
snapshot.historyIndex = this.executionRuntime.executionHistory.list().length;
|
|
58
|
-
}
|
|
59
|
-
catch (enrichError) {
|
|
60
|
-
this.logger.warn(`Enrichment error at stage '${stagePath}':`, { error: enrichError });
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const result = this.extractor(snapshot);
|
|
64
|
-
if (result !== undefined && result !== null) {
|
|
65
|
-
this.extractedResults.set(stagePath, result);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
this.logger.error(`Extractor error at stage '${stagePath}':`, { error });
|
|
70
|
-
this.extractorErrors.push({
|
|
71
|
-
stagePath,
|
|
72
|
-
message: error?.message ?? String(error),
|
|
73
|
-
error,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Generate the stage path for extractor results.
|
|
79
|
-
* Uses node.id combined with branchPath.
|
|
80
|
-
*/
|
|
81
|
-
getStagePath(node, branchPath, contextStageName) {
|
|
82
|
-
const baseName = node.id;
|
|
83
|
-
const nodeId = contextStageName && contextStageName !== node.name ? contextStageName : baseName;
|
|
84
|
-
if (!branchPath)
|
|
85
|
-
return nodeId;
|
|
86
|
-
return `${branchPath}.${nodeId}`;
|
|
87
|
-
}
|
|
88
|
-
buildStructureMetadata(node) {
|
|
89
|
-
const metadata = {
|
|
90
|
-
type: computeNodeType(node),
|
|
91
|
-
};
|
|
92
|
-
if (node.isSubflowRoot) {
|
|
93
|
-
metadata.isSubflowRoot = true;
|
|
94
|
-
metadata.subflowId = node.subflowId;
|
|
95
|
-
metadata.subflowName = node.subflowName;
|
|
96
|
-
}
|
|
97
|
-
else if (this.currentSubflowId) {
|
|
98
|
-
metadata.subflowId = this.currentSubflowId;
|
|
99
|
-
}
|
|
100
|
-
if (this.currentForkId) {
|
|
101
|
-
metadata.isParallelChild = true;
|
|
102
|
-
metadata.parallelGroupId = this.currentForkId;
|
|
103
|
-
}
|
|
104
|
-
if (node.isStreaming) {
|
|
105
|
-
metadata.streamId = node.streamId;
|
|
106
|
-
}
|
|
107
|
-
const hasDynamicChildren = Boolean(node.children?.length && !node.nextNodeSelector && node.fn);
|
|
108
|
-
if (hasDynamicChildren) {
|
|
109
|
-
metadata.isDynamic = true;
|
|
110
|
-
}
|
|
111
|
-
return metadata;
|
|
112
|
-
}
|
|
113
|
-
/** Returns extracted results collected during execution. */
|
|
114
|
-
getExtractedResults() {
|
|
115
|
-
return this.extractedResults;
|
|
116
|
-
}
|
|
117
|
-
/** Returns errors encountered during extraction. */
|
|
118
|
-
getExtractorErrors() {
|
|
119
|
-
return this.extractorErrors;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRXh0cmFjdG9yUnVubmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9lbmdpbmUvaGFuZGxlcnMvRXh0cmFjdG9yUnVubmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBWUgsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRS9ELE1BQU0sT0FBTyxlQUFlO0lBQ1QsU0FBUyxDQUFzQjtJQUMvQixlQUFlLENBQVU7SUFDekIsZ0JBQWdCLENBQW9CO0lBQ3BDLE1BQU0sQ0FBVTtJQUV6QixnQkFBZ0IsR0FBeUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNuRCxlQUFlLEdBQXFCLEVBQUUsQ0FBQztJQUN2QyxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBRXhCLDhGQUE4RjtJQUM5RixnQkFBZ0IsQ0FBVTtJQUUxQixxR0FBcUc7SUFDckcsYUFBYSxDQUFVO0lBRXZCLFlBQ0UsU0FBeUMsRUFDekMsZUFBd0IsRUFDeEIsZ0JBQW1DLEVBQ25DLE1BQWU7UUFFZixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUM7UUFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs7T0FHRztJQUNILGFBQWEsQ0FDWCxJQUFlLEVBQ2YsT0FBcUIsRUFDckIsU0FBaUIsRUFDakIsV0FBcUIsRUFDckIsU0FBNkM7UUFFN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTO1lBQUUsT0FBTztRQUU1QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFbkIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQWtCO2dCQUM5QixJQUFJO2dCQUNKLE9BQU87Z0JBQ1AsVUFBVSxFQUFFLElBQUksQ0FBQyxXQUFX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KiBFeHRyYWN0b3JSdW5uZXIg4oCUIFBlci1zdGFnZSBzbmFwc2hvdCBleHRyYWN0aW9uLlxuICpcbiAqIENvb3JkaW5hdGVzIHRyYXZlcnNhbCBleHRyYWN0b3IgaW52b2NhdGlvbnM6IHN0ZXAgY291bnRpbmcsXG4gKiBzbmFwc2hvdCBlbnJpY2htZW50LCBlcnJvciBjb2xsZWN0aW9uLCBhbmQgcmVzdWx0IHN0b3JhZ2UuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBTdGFnZUNvbnRleHQgfSBmcm9tICcuLi8uLi9tZW1vcnkvU3RhZ2VDb250ZXh0LmpzJztcbmltcG9ydCB0eXBlIHsgU3RhZ2VOb2RlIH0gZnJvbSAnLi4vZ3JhcGgvU3RhZ2VOb2RlLmpzJztcbmltcG9ydCB0eXBlIHtcbiAgRXh0cmFjdG9yRXJyb3IsXG4gIElFeGVjdXRpb25SdW50aW1lLFxuICBJTG9nZ2VyLFxuICBSdW50aW1lU3RydWN0dXJlTWV0YWRhdGEsXG4gIFN0YWdlU25hcHNob3QsXG4gIFRyYXZlcnNhbEV4dHJhY3Rvcixcbn0gZnJvbSAnLi4vdHlwZXMuanMnO1xuaW1wb3J0IHsgY29tcHV0ZU5vZGVUeXBlIH0gZnJvbSAnLi9SdW50aW1lU3RydWN0dXJlTWFuYWdlci5qcyc7XG5cbmV4cG9ydCBjbGFzcyBFeHRyYWN0b3JSdW5uZXI8VE91dCA9IGFueSwgVFNjb3BlID0gYW55PiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZXh0cmFjdG9yPzogVHJhdmVyc2FsRXh0cmFjdG9yO1xuICBwcml2YXRlIHJlYWRvbmx5IGVucmljaFNuYXBzaG90czogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBleGVjdXRpb25SdW50aW1lOiBJRXhlY3V0aW9uUnVudGltZTtcbiAgcHJpdmF0ZSByZWFkb25seSBsb2dnZXI6IElMb2dnZXI7XG5cbiAgcHJpdmF0ZSBleHRyYWN0ZWRSZXN1bHRzOiBNYXA8c3RyaW5nLCB1bmtub3duPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBleHRyYWN0b3JFcnJvcnM6IEV4dHJhY3RvckVycm9yW10gPSBbXTtcbiAgcHJpdmF0ZSBzdGVwQ291bnRlciA9IDA7XG5cbiAgLyoqIEN1cnJlbnQgc3ViZmxvdyBjb250ZXh0IGZvciBtZXRhZGF0YSBwcm9wYWdhdGlvbi4gU2V0L2NsZWFyZWQgZHVyaW5nIHN1YmZsb3cgZXhlY3V0aW9uLiAqL1xuICBjdXJyZW50U3ViZmxvd0lkPzogc3RyaW5nO1xuXG4gIC8qKiBDdXJyZW50IGZvcmsgY29udGV4dCBmb3IgbWV0YWRhdGEgcHJvcGFnYXRpb24uIFNldC9jbGVhcmVkIGR1cmluZyBwYXJhbGxlbCBjaGlsZHJlbiBleGVjdXRpb24uICovXG4gIGN1cnJlbnRGb3JrSWQ/OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgZXh0cmFjdG9yOiBUcmF2ZXJzYWxFeHRyYWN0b3IgfCB1bmRlZmluZWQsXG4gICAgZW5yaWNoU25hcHNob3RzOiBib29sZWFuLFxuICAgIGV4ZWN1dGlvblJ1bnRpbWU6IElFeGVjdXRpb25SdW50aW1lLFxuICAgIGxvZ2dlcjogSUxvZ2dlcixcbiAgKSB7XG4gICAgdGhpcy5leHRyYWN0b3IgPSBleHRyYWN0b3I7XG4gICAgdGhpcy5lbnJpY2hTbmFwc2hvdHMgPSBlbnJpY2hTbmFwc2hvdHM7XG4gICAgdGhpcy5leGVjdXRpb25SdW50aW1lID0gZXhlY3V0aW9uUnVudGltZTtcbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsIHRoZSBleHRyYWN0b3IgZm9yIGEgc3RhZ2UgYW5kIHN0b3JlIHRoZSByZXN1bHQuXG4gICAqIEluY3JlbWVudHMgc3RlcENvdW50ZXIgKDEtYmFzZWQpIGJlZm9yZSBjcmVhdGluZyBzbmFwc2hvdC5cbiAgICovXG4gIGNhbGxFeHRyYWN0b3IoXG4gICAgbm9kZTogU3RhZ2VOb2RlLFxuICAgIGNvbnRleHQ6IFN0YWdlQ29udGV4dCxcbiAgICBzdGFnZVBhdGg6IHN0cmluZyxcbiAgICBzdGFnZU91dHB1dD86IHVua25vd24sXG4gICAgZXJyb3JJbmZvPzogeyB0eXBlOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZyB9LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZXh0cmFjdG9yKSByZXR1cm47XG5cbiAgICB0aGlzLnN0ZXBDb3VudGVyKys7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgc25hcHNob3Q6IFN0YWdlU25hcHNob3QgPSB7XG4gICAgICAgIG5vZGUsXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIHN0ZXBOdW1iZXI6IHRoaXMuc3RlcENvdW50ZXIsXG4gICAgICAgIHN0cnVjdHVyZU1ldGFkYXRhOiB0aGlzLmJ1aWxkU3RydWN0dXJlTWV0YWRhdGEobm9kZSksXG4gICAgICB9O1xuXG4gICAgICBpZiAodGhpcy5lbnJpY2hTbmFwc2hvdHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzbmFwc2hvdC5zY29wZVN0YXRlID0geyAuLi50aGlzLmV4ZWN1dGlvblJ1bnRpbWUuZ2xvYmFsU3RvcmUuZ2V0U3RhdGUoKSB9O1xuXG4gICAgICAgICAgc25hcHNob3QuZGVidWdJbmZvID0ge1xuICAgICAgICAgICAgbG9nczogeyAuLi5jb250ZXh0LmRlYnVnLmxvZ0NvbnRleHQgfSxcbiAgICAgICAgICAgIGVycm9yczogeyAuLi5jb250ZXh0LmRlYnVnLmVycm9yQ29udGV4dCB9LFxuICAgICAgICAgICAgbWV0cmljczogeyAuLi5jb250ZXh0LmRlYnVnLm1ldHJpY0NvbnRleHQgfSxcbiAgICAgICAgICAgIGV2YWxzOiB7IC4uLmNvbnRleHQuZGVidWcuZXZhbENvbnRleHQgfSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmIChjb250ZXh0LmRlYnVnLmZsb3dNZXNzYWdlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBzbmFwc2hvdC5kZWJ1Z0luZm8uZmxvd01lc3NhZ2VzID0gWy4uLmNvbnRleHQuZGVidWcuZmxvd01lc3NhZ2VzXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzbmFwc2hvdC5zdGFnZU91dHB1dCA9IHN0YWdlT3V0cHV0O1xuXG4gICAgICAgICAgaWYgKGVycm9ySW5mbykge1xuICAgICAgICAgICAgc25hcHNob3QuZXJyb3JJbmZvID0gZXJyb3JJbmZvO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHNuYXBzaG90Lmhpc3RvcnlJbmRleCA9IHRoaXMuZXhlY3V0aW9uUnVudGltZS5leGVjdXRpb25IaXN0b3J5Lmxpc3QoKS5sZW5ndGg7XG4gICAgICAgIH0gY2F0Y2ggKGVucmljaEVycm9yOiBhbnkpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKGBFbnJpY2htZW50IGVycm9yIGF0IHN0YWdlICcke3N0YWdlUGF0aH0nOmAsIHsgZXJyb3I6IGVucmljaEVycm9yIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZXh0cmFjdG9yKHNuYXBzaG90KTtcblxuICAgICAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkICYmIHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLmV4dHJhY3RlZFJlc3VsdHMuc2V0KHN0YWdlUGF0aCwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRXh0cmFjdG9yIGVycm9yIGF0IHN0YWdlICcke3N0YWdlUGF0aH0nOmAsIHsgZXJyb3IgfSk7XG4gICAgICB0aGlzLmV4dHJhY3RvckVycm9ycy5wdXNoKHtcbiAgICAgICAgc3RhZ2VQYXRoLFxuICAgICAgICBtZXNzYWdlOiBlcnJvcj8ubWVzc2FnZSA/PyBTdHJpbmcoZXJyb3IpLFxuICAgICAgICBlcnJvcixcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSB0aGUgc3RhZ2UgcGF0aCBmb3IgZXh0cmFjdG9yIHJlc3VsdHMuXG4gICAqIFVzZXMgbm9kZS5pZCBjb21iaW5lZCB3aXRoIGJyYW5jaFBhdGguXG4gICAqL1xuICBnZXRTdGFnZVBhdGgobm9kZTogU3RhZ2VOb2RlLCBicmFuY2hQYXRoPzogc3RyaW5nLCBjb250ZXh0U3RhZ2VOYW1lPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBiYXNlTmFtZSA9IG5vZGUuaWQ7XG4gICAgY29uc3Qgbm9kZUlkID0gY29udGV4dFN0YWdlTmFtZSAmJiBjb250ZXh0U3RhZ2VOYW1lICE9PSBub2RlLm5hbWUgPyBjb250ZXh0U3RhZ2VOYW1lIDogYmFzZU5hbWU7XG4gICAgaWYgKCFicmFuY2hQYXRoKSByZXR1cm4gbm9kZUlkO1xuICAgIHJldHVybiBgJHticmFuY2hQYXRofS4ke25vZGVJZH1gO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZFN0cnVjdHVyZU1ldGFkYXRhKG5vZGU6IFN0YWdlTm9kZSk6IFJ1bnRpbWVTdHJ1Y3R1cmVNZXRhZGF0YSB7XG4gICAgY29uc3QgbWV0YWRhdGE6IFJ1bnRpbWVTdHJ1Y3R1cmVNZXRhZGF0YSA9IHtcbiAgICAgIHR5cGU6IGNvbXB1dGVOb2RlVHlwZShub2RlKSxcbiAgICB9O1xuXG4gICAgaWYgKG5vZGUuaXNTdWJmbG93Um9vdCkge1xuICAgICAgbWV0YWRhdGEuaXNTdWJmbG93Um9vdCA9IHRydWU7XG4gICAgICBtZXRhZGF0YS5zdWJmbG93SWQgPSBub2RlLnN1YmZsb3dJZDtcbiAgICAgIG1ldGFkYXRhLnN1YmZsb3dOYW1lID0gbm9kZS5zdWJmbG93TmFtZTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY3VycmVudFN1YmZsb3dJZCkge1xuICAgICAgbWV0YWRhdGEuc3ViZmxvd0lkID0gdGhpcy5jdXJyZW50U3ViZmxvd0lkO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmN1cnJlbnRGb3JrSWQpIHtcbiAgICAgIG1ldGFkYXRhLmlzUGFyYWxsZWxDaGlsZCA9IHRydWU7XG4gICAgICBtZXRhZGF0YS5wYXJhbGxlbEdyb3VwSWQgPSB0aGlzLmN1cnJlbnRGb3JrSWQ7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUuaXNTdHJlYW1pbmcpIHtcbiAgICAgIG1ldGFkYXRhLnN0cmVhbUlkID0gbm9kZS5zdHJlYW1JZDtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNEeW5hbWljQ2hpbGRyZW4gPSBCb29sZWFuKG5vZGUuY2hpbGRyZW4/Lmxlbmd0aCAmJiAhbm9kZS5uZXh0Tm9kZVNlbGVjdG9yICYmIG5vZGUuZm4pO1xuICAgIGlmIChoYXNEeW5hbWljQ2hpbGRyZW4pIHtcbiAgICAgIG1ldGFkYXRhLmlzRHluYW1pYyA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1ldGFkYXRhO1xuICB9XG5cbiAgLyoqIFJldHVybnMgZXh0cmFjdGVkIHJlc3VsdHMgY29sbGVjdGVkIGR1cmluZyBleGVjdXRpb24uICovXG4gIGdldEV4dHJhY3RlZFJlc3VsdHM8VFJlc3VsdCA9IHVua25vd24+KCk6IE1hcDxzdHJpbmcsIFRSZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5leHRyYWN0ZWRSZXN1bHRzIGFzIE1hcDxzdHJpbmcsIFRSZXN1bHQ+O1xuICB9XG5cbiAgLyoqIFJldHVybnMgZXJyb3JzIGVuY291bnRlcmVkIGR1cmluZyBleHRyYWN0aW9uLiAqL1xuICBnZXRFeHRyYWN0b3JFcnJvcnMoKTogRXh0cmFjdG9yRXJyb3JbXSB7XG4gICAgcmV0dXJuIHRoaXMuZXh0cmFjdG9yRXJyb3JzO1xuICB9XG59XG4iXX0=
|