footprintjs 4.6.0 → 4.8.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.
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KeyedRecorder = void 0;
4
+ /**
5
+ * KeyedRecorder<T> — base class for Map-based recorders keyed by runtimeStageId.
6
+ *
7
+ * Provides typed key-value storage with O(1) lookup, insertion-ordered iteration,
8
+ * and three standard operations on auto-collected traversal data:
9
+ *
10
+ * - **Translate** (raw): `getByKey(id)` — per-step value
11
+ * - **Accumulate** (progressive): `accumulate(fn, initial, keys?)` — running total up to a point
12
+ * - **Aggregate** (summary): `aggregate(fn, initial)` — reduce all entries
13
+ *
14
+ * Data is automatically collected during the single DFS traversal.
15
+ * The consumer chooses the operation at read time.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * class TokenRecorder extends KeyedRecorder<LLMCallEntry> {
20
+ * readonly id = 'tokens';
21
+ * onLLMCall(event) { this.store(event.runtimeStageId, { tokens: event.usage }); }
22
+ *
23
+ * // Translate: per-step
24
+ * getForStep(id: string) { return this.getByKey(id); }
25
+ *
26
+ * // Aggregate: total
27
+ * getTotalTokens() { return this.aggregate((sum, e) => sum + e.tokens, 0); }
28
+ *
29
+ * // Accumulate: progressive up to slider position
30
+ * getTokensUpTo(keys: Set<string>) { return this.accumulate((sum, e) => sum + e.tokens, 0, keys); }
31
+ * }
32
+ * ```
33
+ */
34
+ class KeyedRecorder {
35
+ constructor() {
36
+ this.data = new Map();
37
+ }
38
+ /** Store an entry keyed by runtimeStageId. */
39
+ store(runtimeStageId, entry) {
40
+ this.data.set(runtimeStageId, entry);
41
+ }
42
+ // ── Translate (raw per-step) ──────────────────────────────
43
+ /** O(1) lookup by runtimeStageId. */
44
+ getByKey(runtimeStageId) {
45
+ return this.data.get(runtimeStageId);
46
+ }
47
+ /** All entries as a read-only Map (insertion-ordered). */
48
+ getMap() {
49
+ return this.data;
50
+ }
51
+ /** All entries as an array (insertion-ordered). */
52
+ values() {
53
+ return [...this.data.values()];
54
+ }
55
+ /** Number of entries stored. */
56
+ get size() {
57
+ return this.data.size;
58
+ }
59
+ // ── Aggregate (reduce all entries) ────────────────────────
60
+ /** Reduce ALL entries to a single value. For dashboards, totals, summaries. */
61
+ aggregate(fn, initial) {
62
+ let acc = initial;
63
+ for (const [key, entry] of this.data) {
64
+ acc = fn(acc, entry, key);
65
+ }
66
+ return acc;
67
+ }
68
+ // ── Accumulate (progressive reduce) ───────────────────────
69
+ /**
70
+ * Reduce entries, optionally filtered by a set of keys.
71
+ * For time-travel progressive view: pass the runtimeStageIds visible at the current slider position.
72
+ * Without keys, reduces all entries (same as aggregate).
73
+ */
74
+ accumulate(fn, initial, keys) {
75
+ let acc = initial;
76
+ for (const [key, entry] of this.data) {
77
+ if (keys && !keys.has(key))
78
+ continue;
79
+ acc = fn(acc, entry, key);
80
+ }
81
+ return acc;
82
+ }
83
+ // ── Filter (subset by keys) ───────────────────────────────
84
+ /** Return entries whose keys are in the set, preserving insertion order. */
85
+ filterByKeys(keys) {
86
+ const result = [];
87
+ for (const [key, entry] of this.data) {
88
+ if (keys.has(key))
89
+ result.push(entry);
90
+ }
91
+ return result;
92
+ }
93
+ // ── Lifecycle ─────────────────────────────────────────────
94
+ /** Clear all stored data. Called by executor before each run(). */
95
+ clear() {
96
+ this.data.clear();
97
+ }
98
+ }
99
+ exports.KeyedRecorder = KeyedRecorder;
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiS2V5ZWRSZWNvcmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvcmVjb3JkZXIvS2V5ZWRSZWNvcmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFDSCxNQUFzQixhQUFhO0lBQW5DO1FBR21CLFNBQUksR0FBRyxJQUFJLEdBQUcsRUFBYSxDQUFDO0lBeUUvQyxDQUFDO0lBdkVDLDhDQUE4QztJQUNwQyxLQUFLLENBQUMsY0FBc0IsRUFBRSxLQUFRO1FBQzlDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsNkRBQTZEO0lBRTdELHFDQUFxQztJQUNyQyxRQUFRLENBQUMsY0FBc0I7UUFDN0IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsMERBQTBEO0lBQzFELE1BQU07UUFDSixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQUVELG1EQUFtRDtJQUNuRCxNQUFNO1FBQ0osT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFFRCxnQ0FBZ0M7SUFDaEMsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztJQUN4QixDQUFDO0lBRUQsNkRBQTZEO0lBRTdELCtFQUErRTtJQUMvRSxTQUFTLENBQUksRUFBd0MsRUFBRSxPQUFVO1FBQy9ELElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQztRQUNsQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3JDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQsNkRBQTZEO0lBRTdEOzs7O09BSUc7SUFDSCxVQUFVLENBQUksRUFBd0MsRUFBRSxPQUFVLEVBQUUsSUFBMEI7UUFDNUYsSUFBSSxHQUFHLEdBQUcsT0FBTyxDQUFDO1FBQ2xCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztnQkFBRSxTQUFTO1lBQ3JDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQ0QsT0FBTyxHQUFHLENBQUM7SUFDYixDQUFDO0lBRUQsNkRBQTZEO0lBRTdELDRFQUE0RTtJQUM1RSxZQUFZLENBQUMsSUFBeUI7UUFDcEMsTUFBTSxNQUFNLEdBQVEsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztnQkFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQsNkRBQTZEO0lBRTdELG1FQUFtRTtJQUNuRSxLQUFLO1FBQ0gsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUE1RUQsc0NBNEVDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBLZXllZFJlY29yZGVyPFQ+IOKAlCBiYXNlIGNsYXNzIGZvciBNYXAtYmFzZWQgcmVjb3JkZXJzIGtleWVkIGJ5IHJ1bnRpbWVTdGFnZUlkLlxuICpcbiAqIFByb3ZpZGVzIHR5cGVkIGtleS12YWx1ZSBzdG9yYWdlIHdpdGggTygxKSBsb29rdXAsIGluc2VydGlvbi1vcmRlcmVkIGl0ZXJhdGlvbixcbiAqIGFuZCB0aHJlZSBzdGFuZGFyZCBvcGVyYXRpb25zIG9uIGF1dG8tY29sbGVjdGVkIHRyYXZlcnNhbCBkYXRhOlxuICpcbiAqICAgLSAqKlRyYW5zbGF0ZSoqIChyYXcpOiBgZ2V0QnlLZXkoaWQpYCDigJQgcGVyLXN0ZXAgdmFsdWVcbiAqICAgLSAqKkFjY3VtdWxhdGUqKiAocHJvZ3Jlc3NpdmUpOiBgYWNjdW11bGF0ZShmbiwgaW5pdGlhbCwga2V5cz8pYCDigJQgcnVubmluZyB0b3RhbCB1cCB0byBhIHBvaW50XG4gKiAgIC0gKipBZ2dyZWdhdGUqKiAoc3VtbWFyeSk6IGBhZ2dyZWdhdGUoZm4sIGluaXRpYWwpYCDigJQgcmVkdWNlIGFsbCBlbnRyaWVzXG4gKlxuICogRGF0YSBpcyBhdXRvbWF0aWNhbGx5IGNvbGxlY3RlZCBkdXJpbmcgdGhlIHNpbmdsZSBERlMgdHJhdmVyc2FsLlxuICogVGhlIGNvbnN1bWVyIGNob29zZXMgdGhlIG9wZXJhdGlvbiBhdCByZWFkIHRpbWUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNsYXNzIFRva2VuUmVjb3JkZXIgZXh0ZW5kcyBLZXllZFJlY29yZGVyPExMTUNhbGxFbnRyeT4ge1xuICogICByZWFkb25seSBpZCA9ICd0b2tlbnMnO1xuICogICBvbkxMTUNhbGwoZXZlbnQpIHsgdGhpcy5zdG9yZShldmVudC5ydW50aW1lU3RhZ2VJZCwgeyB0b2tlbnM6IGV2ZW50LnVzYWdlIH0pOyB9XG4gKlxuICogICAvLyBUcmFuc2xhdGU6IHBlci1zdGVwXG4gKiAgIGdldEZvclN0ZXAoaWQ6IHN0cmluZykgeyByZXR1cm4gdGhpcy5nZXRCeUtleShpZCk7IH1cbiAqXG4gKiAgIC8vIEFnZ3JlZ2F0ZTogdG90YWxcbiAqICAgZ2V0VG90YWxUb2tlbnMoKSB7IHJldHVybiB0aGlzLmFnZ3JlZ2F0ZSgoc3VtLCBlKSA9PiBzdW0gKyBlLnRva2VucywgMCk7IH1cbiAqXG4gKiAgIC8vIEFjY3VtdWxhdGU6IHByb2dyZXNzaXZlIHVwIHRvIHNsaWRlciBwb3NpdGlvblxuICogICBnZXRUb2tlbnNVcFRvKGtleXM6IFNldDxzdHJpbmc+KSB7IHJldHVybiB0aGlzLmFjY3VtdWxhdGUoKHN1bSwgZSkgPT4gc3VtICsgZS50b2tlbnMsIDAsIGtleXMpOyB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEtleWVkUmVjb3JkZXI8VD4ge1xuICBhYnN0cmFjdCByZWFkb25seSBpZDogc3RyaW5nO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZGF0YSA9IG5ldyBNYXA8c3RyaW5nLCBUPigpO1xuXG4gIC8qKiBTdG9yZSBhbiBlbnRyeSBrZXllZCBieSBydW50aW1lU3RhZ2VJZC4gKi9cbiAgcHJvdGVjdGVkIHN0b3JlKHJ1bnRpbWVTdGFnZUlkOiBzdHJpbmcsIGVudHJ5OiBUKTogdm9pZCB7XG4gICAgdGhpcy5kYXRhLnNldChydW50aW1lU3RhZ2VJZCwgZW50cnkpO1xuICB9XG5cbiAgLy8g4pSA4pSAIFRyYW5zbGF0ZSAocmF3IHBlci1zdGVwKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogTygxKSBsb29rdXAgYnkgcnVudGltZVN0YWdlSWQuICovXG4gIGdldEJ5S2V5KHJ1bnRpbWVTdGFnZUlkOiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLmdldChydW50aW1lU3RhZ2VJZCk7XG4gIH1cblxuICAvKiogQWxsIGVudHJpZXMgYXMgYSByZWFkLW9ubHkgTWFwIChpbnNlcnRpb24tb3JkZXJlZCkuICovXG4gIGdldE1hcCgpOiBSZWFkb25seU1hcDxzdHJpbmcsIFQ+IHtcbiAgICByZXR1cm4gdGhpcy5kYXRhO1xuICB9XG5cbiAgLyoqIEFsbCBlbnRyaWVzIGFzIGFuIGFycmF5IChpbnNlcnRpb24tb3JkZXJlZCkuICovXG4gIHZhbHVlcygpOiBUW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5kYXRhLnZhbHVlcygpXTtcbiAgfVxuXG4gIC8qKiBOdW1iZXIgb2YgZW50cmllcyBzdG9yZWQuICovXG4gIGdldCBzaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5zaXplO1xuICB9XG5cbiAgLy8g4pSA4pSAIEFnZ3JlZ2F0ZSAocmVkdWNlIGFsbCBlbnRyaWVzKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogUmVkdWNlIEFMTCBlbnRyaWVzIHRvIGEgc2luZ2xlIHZhbHVlLiBGb3IgZGFzaGJvYXJkcywgdG90YWxzLCBzdW1tYXJpZXMuICovXG4gIGFnZ3JlZ2F0ZTxSPihmbjogKGFjYzogUiwgZW50cnk6IFQsIGtleTogc3RyaW5nKSA9PiBSLCBpbml0aWFsOiBSKTogUiB7XG4gICAgbGV0IGFjYyA9IGluaXRpYWw7XG4gICAgZm9yIChjb25zdCBba2V5LCBlbnRyeV0gb2YgdGhpcy5kYXRhKSB7XG4gICAgICBhY2MgPSBmbihhY2MsIGVudHJ5LCBrZXkpO1xuICAgIH1cbiAgICByZXR1cm4gYWNjO1xuICB9XG5cbiAgLy8g4pSA4pSAIEFjY3VtdWxhdGUgKHByb2dyZXNzaXZlIHJlZHVjZSkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqXG4gICAqIFJlZHVjZSBlbnRyaWVzLCBvcHRpb25hbGx5IGZpbHRlcmVkIGJ5IGEgc2V0IG9mIGtleXMuXG4gICAqIEZvciB0aW1lLXRyYXZlbCBwcm9ncmVzc2l2ZSB2aWV3OiBwYXNzIHRoZSBydW50aW1lU3RhZ2VJZHMgdmlzaWJsZSBhdCB0aGUgY3VycmVudCBzbGlkZXIgcG9zaXRpb24uXG4gICAqIFdpdGhvdXQga2V5cywgcmVkdWNlcyBhbGwgZW50cmllcyAoc2FtZSBhcyBhZ2dyZWdhdGUpLlxuICAgKi9cbiAgYWNjdW11bGF0ZTxSPihmbjogKGFjYzogUiwgZW50cnk6IFQsIGtleTogc3RyaW5nKSA9PiBSLCBpbml0aWFsOiBSLCBrZXlzPzogUmVhZG9ubHlTZXQ8c3RyaW5nPik6IFIge1xuICAgIGxldCBhY2MgPSBpbml0aWFsO1xuICAgIGZvciAoY29uc3QgW2tleSwgZW50cnldIG9mIHRoaXMuZGF0YSkge1xuICAgICAgaWYgKGtleXMgJiYgIWtleXMuaGFzKGtleSkpIGNvbnRpbnVlO1xuICAgICAgYWNjID0gZm4oYWNjLCBlbnRyeSwga2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIGFjYztcbiAgfVxuXG4gIC8vIOKUgOKUgCBGaWx0ZXIgKHN1YnNldCBieSBrZXlzKSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogUmV0dXJuIGVudHJpZXMgd2hvc2Uga2V5cyBhcmUgaW4gdGhlIHNldCwgcHJlc2VydmluZyBpbnNlcnRpb24gb3JkZXIuICovXG4gIGZpbHRlckJ5S2V5cyhrZXlzOiBSZWFkb25seVNldDxzdHJpbmc+KTogVFtdIHtcbiAgICBjb25zdCByZXN1bHQ6IFRbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW2tleSwgZW50cnldIG9mIHRoaXMuZGF0YSkge1xuICAgICAgaWYgKGtleXMuaGFzKGtleSkpIHJlc3VsdC5wdXNoKGVudHJ5KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIOKUgOKUgCBMaWZlY3ljbGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIENsZWFyIGFsbCBzdG9yZWQgZGF0YS4gQ2FsbGVkIGJ5IGV4ZWN1dG9yIGJlZm9yZSBlYWNoIHJ1bigpLiAqL1xuICBjbGVhcigpOiB2b2lkIHtcbiAgICB0aGlzLmRhdGEuY2xlYXIoKTtcbiAgfVxufVxuIl19
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CompositeRecorder = void 0;
3
+ exports.KeyedRecorder = exports.CompositeRecorder = void 0;
4
4
  var CompositeRecorder_js_1 = require("./CompositeRecorder.js");
5
5
  Object.defineProperty(exports, "CompositeRecorder", { enumerable: true, get: function () { return CompositeRecorder_js_1.CompositeRecorder; } });
6
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JlY29yZGVyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtEQUEyRDtBQUFsRCx5SEFBQSxpQkFBaUIsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCB0eXBlIHsgQ29tcG9zaXRlU25hcHNob3QgfSBmcm9tICcuL0NvbXBvc2l0ZVJlY29yZGVyLmpzJztcbmV4cG9ydCB7IENvbXBvc2l0ZVJlY29yZGVyIH0gZnJvbSAnLi9Db21wb3NpdGVSZWNvcmRlci5qcyc7XG4iXX0=
6
+ var KeyedRecorder_js_1 = require("./KeyedRecorder.js");
7
+ Object.defineProperty(exports, "KeyedRecorder", { enumerable: true, get: function () { return KeyedRecorder_js_1.KeyedRecorder; } });
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3JlY29yZGVyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtEQUEyRDtBQUFsRCx5SEFBQSxpQkFBaUIsT0FBQTtBQUMxQix1REFBbUQ7QUFBMUMsaUhBQUEsYUFBYSxPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHR5cGUgeyBDb21wb3NpdGVTbmFwc2hvdCB9IGZyb20gJy4vQ29tcG9zaXRlUmVjb3JkZXIuanMnO1xuZXhwb3J0IHsgQ29tcG9zaXRlUmVjb3JkZXIgfSBmcm9tICcuL0NvbXBvc2l0ZVJlY29yZGVyLmpzJztcbmV4cG9ydCB7IEtleWVkUmVjb3JkZXIgfSBmcm9tICcuL0tleWVkUmVjb3JkZXIuanMnO1xuIl19
@@ -1,42 +1,35 @@
1
1
  "use strict";
2
2
  /**
3
- * MetricRecorder — Production-focused recorder for timing and execution counts.
3
+ * MetricRecorder — per-step timing and execution counts, keyed by runtimeStageId.
4
4
  *
5
- * Tracks read/write/commit counts per stage and measures stage execution duration.
6
- *
7
- * Each instance gets a unique auto-increment ID (`metrics-1`, `metrics-2`, ...),
8
- * so multiple recorders with different configs coexist. Pass an explicit ID to
9
- * override a specific instance (e.g., a framework-attached recorder).
5
+ * Stores per-invocation data during traversal. Aggregated views computed on read.
6
+ * Extends KeyedRecorder<StepMetrics> for O(1) lookup and standard operations.
10
7
  *
11
8
  * @example
12
9
  * ```typescript
13
- * // Track all stages (default)
14
- * executor.attachRecorder(new MetricRecorder());
10
+ * const metric = new MetricRecorder();
11
+ * executor.attachRecorder(metric);
12
+ * await executor.run();
15
13
  *
16
- * // Track only LLM-related stages
17
- * executor.attachRecorder(new MetricRecorder({
18
- * stageFilter: (name) => ['CallLLM', 'ParseResponse'].includes(name),
19
- * }));
14
+ * // Per-step (time-travel):
15
+ * metric.getByKey('call-llm#5'); // { stageName, readCount, writeCount, duration }
20
16
  *
21
- * // Two recorders: one for LLM timing, one for everything else
22
- * executor.attachRecorder(new MetricRecorder({
23
- * stageFilter: (name) => name === 'CallLLM',
24
- * }));
25
- * executor.attachRecorder(new MetricRecorder({
26
- * stageFilter: (name) => name !== 'CallLLM',
27
- * }));
17
+ * // Aggregated (backward compat):
18
+ * metric.getMetrics(); // { totalDuration, totalReads, stageMetrics: Map<stageName, aggregated> }
28
19
  *
29
- * // Override a framework-attached recorder by passing its well-known ID
30
- * executor.attachRecorder(new MetricRecorder({ id: 'metrics' }));
20
+ * // Progressive (slider):
21
+ * metric.accumulate((sum, m) => sum + m.duration, 0, visibleKeys);
31
22
  * ```
32
23
  */
33
24
  Object.defineProperty(exports, "__esModule", { value: true });
34
25
  exports.MetricRecorder = void 0;
35
- class MetricRecorder {
26
+ const KeyedRecorder_js_1 = require("../../recorder/KeyedRecorder.js");
27
+ class MetricRecorder extends KeyedRecorder_js_1.KeyedRecorder {
36
28
  constructor(idOrOptions) {
37
29
  var _a;
38
- this.metrics = new Map();
30
+ super();
39
31
  this.stageStartTimes = new Map();
32
+ this.currentRuntimeStageId = '';
40
33
  if (typeof idOrOptions === 'string') {
41
34
  this.id = idOrOptions;
42
35
  }
@@ -48,73 +41,96 @@ class MetricRecorder {
48
41
  shouldRecord(stageName) {
49
42
  return !this.stageFilter || this.stageFilter(stageName);
50
43
  }
44
+ /** Get or create the StepMetrics for the current stage. */
45
+ current() {
46
+ const key = this.currentRuntimeStageId;
47
+ let m = this.getByKey(key);
48
+ if (!m) {
49
+ m = { stageName: '', readCount: 0, writeCount: 0, commitCount: 0, pauseCount: 0, duration: 0 };
50
+ this.store(key, m);
51
+ }
52
+ return m;
53
+ }
54
+ onStageStart(event) {
55
+ if (!this.shouldRecord(event.stageName))
56
+ return;
57
+ this.currentRuntimeStageId = event.runtimeStageId;
58
+ this.stageStartTimes.set(event.runtimeStageId, event.timestamp);
59
+ const m = this.current();
60
+ m.stageName = event.stageName;
61
+ }
51
62
  onRead(event) {
52
63
  if (!this.shouldRecord(event.stageName))
53
64
  return;
54
- this.getOrCreateStageMetrics(event.stageName).readCount++;
65
+ this.current().readCount++;
55
66
  }
56
67
  onWrite(event) {
57
68
  if (!this.shouldRecord(event.stageName))
58
69
  return;
59
- this.getOrCreateStageMetrics(event.stageName).writeCount++;
70
+ this.current().writeCount++;
60
71
  }
61
72
  onCommit(event) {
62
73
  if (!this.shouldRecord(event.stageName))
63
74
  return;
64
- this.getOrCreateStageMetrics(event.stageName).commitCount++;
75
+ this.current().commitCount++;
65
76
  }
66
77
  onPause(event) {
67
78
  if (!this.shouldRecord(event.stageName))
68
79
  return;
69
- this.getOrCreateStageMetrics(event.stageName).pauseCount++;
70
- }
71
- onStageStart(event) {
72
- if (!this.shouldRecord(event.stageName))
73
- return;
74
- this.stageStartTimes.set(event.stageName, event.timestamp);
75
- this.getOrCreateStageMetrics(event.stageName).invocationCount++;
80
+ this.current().pauseCount++;
76
81
  }
77
82
  onStageEnd(event) {
78
83
  if (!this.shouldRecord(event.stageName))
79
84
  return;
80
- const stageMetrics = this.getOrCreateStageMetrics(event.stageName);
81
- let duration;
85
+ const m = this.current();
82
86
  if (event.duration !== undefined) {
83
- duration = event.duration;
87
+ m.duration = event.duration;
84
88
  }
85
89
  else {
86
- const startTime = this.stageStartTimes.get(event.stageName);
87
- duration = startTime !== undefined ? event.timestamp - startTime : 0;
90
+ const startTime = this.stageStartTimes.get(event.runtimeStageId);
91
+ m.duration = startTime !== undefined ? event.timestamp - startTime : 0;
88
92
  }
89
- stageMetrics.totalDuration += duration;
90
- this.stageStartTimes.delete(event.stageName);
93
+ this.stageStartTimes.delete(event.runtimeStageId);
91
94
  }
95
+ /** Aggregated metrics — computes totals on the fly from per-step data (backward compatible). */
92
96
  getMetrics() {
93
- let totalDuration = 0;
94
- let totalReads = 0;
95
- let totalWrites = 0;
96
- let totalCommits = 0;
97
- let totalPauses = 0;
98
- for (const stageMetrics of this.metrics.values()) {
99
- totalDuration += stageMetrics.totalDuration;
100
- totalReads += stageMetrics.readCount;
101
- totalWrites += stageMetrics.writeCount;
102
- totalCommits += stageMetrics.commitCount;
103
- totalPauses += stageMetrics.pauseCount;
97
+ const byName = new Map();
98
+ const totalDuration = this.aggregate((sum, m) => sum + m.duration, 0);
99
+ const totalReads = this.aggregate((sum, m) => sum + m.readCount, 0);
100
+ const totalWrites = this.aggregate((sum, m) => sum + m.writeCount, 0);
101
+ const totalCommits = this.aggregate((sum, m) => sum + m.commitCount, 0);
102
+ const totalPauses = this.aggregate((sum, m) => sum + m.pauseCount, 0);
103
+ // Group by stageName for backward compat
104
+ for (const m of this.values()) {
105
+ const existing = byName.get(m.stageName);
106
+ if (existing) {
107
+ existing.readCount += m.readCount;
108
+ existing.writeCount += m.writeCount;
109
+ existing.commitCount += m.commitCount;
110
+ existing.pauseCount += m.pauseCount;
111
+ existing.totalDuration += m.duration;
112
+ existing.invocationCount++;
113
+ }
114
+ else {
115
+ byName.set(m.stageName, {
116
+ stageName: m.stageName,
117
+ readCount: m.readCount,
118
+ writeCount: m.writeCount,
119
+ commitCount: m.commitCount,
120
+ pauseCount: m.pauseCount,
121
+ totalDuration: m.duration,
122
+ invocationCount: 1,
123
+ });
124
+ }
104
125
  }
105
- return {
106
- totalDuration,
107
- totalReads,
108
- totalWrites,
109
- totalCommits,
110
- totalPauses,
111
- stageMetrics: new Map(this.metrics),
112
- };
126
+ return { totalDuration, totalReads, totalWrites, totalCommits, totalPauses, stageMetrics: byName };
113
127
  }
128
+ /** Get aggregated metrics for a specific stage name (backward compatible). */
114
129
  getStageMetrics(stageName) {
115
- const metrics = this.metrics.get(stageName);
116
- return metrics ? { ...metrics } : undefined;
130
+ const metrics = this.getMetrics();
131
+ return metrics.stageMetrics.get(stageName);
117
132
  }
133
+ /** Snapshot for serialization (backward compatible format). */
118
134
  toSnapshot() {
119
135
  const metrics = this.getMetrics();
120
136
  return {
@@ -128,30 +144,17 @@ class MetricRecorder {
128
144
  },
129
145
  };
130
146
  }
131
- reset() {
132
- this.metrics.clear();
133
- this.stageStartTimes.clear();
134
- }
147
+ /** Clear all state — called by executor before each run(). */
135
148
  clear() {
136
- this.reset();
149
+ super.clear();
150
+ this.stageStartTimes.clear();
151
+ this.currentRuntimeStageId = '';
137
152
  }
138
- getOrCreateStageMetrics(stageName) {
139
- let stageMetrics = this.metrics.get(stageName);
140
- if (!stageMetrics) {
141
- stageMetrics = {
142
- stageName,
143
- readCount: 0,
144
- writeCount: 0,
145
- commitCount: 0,
146
- pauseCount: 0,
147
- totalDuration: 0,
148
- invocationCount: 0,
149
- };
150
- this.metrics.set(stageName, stageMetrics);
151
- }
152
- return stageMetrics;
153
+ /** Alias for clear() (backward compat). */
154
+ reset() {
155
+ this.clear();
153
156
  }
154
157
  }
155
158
  exports.MetricRecorder = MetricRecorder;
156
159
  MetricRecorder._counter = 0;
157
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWV0cmljUmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3JlY29yZGVycy9NZXRyaWNSZWNvcmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThCRzs7O0FBd0NILE1BQWEsY0FBYztJQVF6QixZQUFZLFdBQTRDOztRQUpoRCxZQUFPLEdBQThCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDL0Msb0JBQWUsR0FBd0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUl2RCxJQUFJLE9BQU8sV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxFQUFFLEdBQUcsV0FBVyxDQUFDO1FBQ3hCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFBLFdBQVcsYUFBWCxXQUFXLHVCQUFYLFdBQVcsQ0FBRSxFQUFFLG1DQUFJLFdBQVcsRUFBRSxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLGFBQVgsV0FBVyx1QkFBWCxXQUFXLENBQUUsV0FBVyxDQUFDO1FBQzlDLENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWSxDQUFDLFNBQWlCO1FBQ3BDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFnQjtRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO1lBQUUsT0FBTztRQUNoRCxJQUFJLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzVELENBQUM7SUFFRCxPQUFPLENBQUMsS0FBaUI7UUFDdkIsSUFBSSxDQUFDLElB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LGFBQWEsRUFBRSxDQUFDO2dCQUNoQixlQUFlLEVBQUUsQ0FBQzthQUNuQixDQUFDO1lBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzVDLENBQUM7UUFDRCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDOztBQWpJSCx3Q0FrSUM7QUFqSWdCLHVCQUFRLEdBQUcsQ0FBQyxBQUFKLENBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1ldHJpY1JlY29yZGVyIOKAlCBQcm9kdWN0aW9uLWZvY3VzZWQgcmVjb3JkZXIgZm9yIHRpbWluZyBhbmQgZXhlY3V0aW9uIGNvdW50cy5cbiAqXG4gKiBUcmFja3MgcmVhZC93cml0ZS9jb21taXQgY291bnRzIHBlciBzdGFnZSBhbmQgbWVhc3VyZXMgc3RhZ2UgZXhlY3V0aW9uIGR1cmF0aW9uLlxuICpcbiAqIEVhY2ggaW5zdGFuY2UgZ2V0cyBhIHVuaXF1ZSBhdXRvLWluY3JlbWVudCBJRCAoYG1ldHJpY3MtMWAsIGBtZXRyaWNzLTJgLCAuLi4pLFxuICogc28gbXVsdGlwbGUgcmVjb3JkZXJzIHdpdGggZGlmZmVyZW50IGNvbmZpZ3MgY29leGlzdC4gUGFzcyBhbiBleHBsaWNpdCBJRCB0b1xuICogb3ZlcnJpZGUgYSBzcGVjaWZpYyBpbnN0YW5jZSAoZS5nLiwgYSBmcmFtZXdvcmstYXR0YWNoZWQgcmVjb3JkZXIpLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBUcmFjayBhbGwgc3RhZ2VzIChkZWZhdWx0KVxuICogZXhlY3V0b3IuYXR0YWNoUmVjb3JkZXIobmV3IE1ldHJpY1JlY29yZGVyKCkpO1xuICpcbiAqIC8vIFRyYWNrIG9ubHkgTExNLXJlbGF0ZWQgc3RhZ2VzXG4gKiBleGVjdXRvci5hdHRhY2hSZWNvcmRlcihuZXcgTWV0cmljUmVjb3JkZXIoe1xuICogICBzdGFnZUZpbHRlcjogKG5hbWUpID0+IFsnQ2FsbExMTScsICdQYXJzZVJlc3BvbnNlJ10uaW5jbHVkZXMobmFtZSksXG4gKiB9KSk7XG4gKlxuICogLy8gVHdvIHJlY29yZGVyczogb25lIGZvciBMTE0gdGltaW5nLCBvbmUgZm9yIGV2ZXJ5dGhpbmcgZWxzZVxuICogZXhlY3V0b3IuYXR0YWNoUmVjb3JkZXIobmV3IE1ldHJpY1JlY29yZGVyKHtcbiAqICAgc3RhZ2VGaWx0ZXI6IChuYW1lKSA9PiBuYW1lID09PSAnQ2FsbExMTScsXG4gKiB9KSk7XG4gKiBleGVjdXRvci5hdHRhY2hSZWNvcmRlcihuZXcgTWV0cmljUmVjb3JkZXIoe1xuICogICBzdGFnZUZpbHRlcjogKG5hbWUpID0+IG5hbWUgIT09ICdDYWxsTExNJyxcbiAqIH0pKTtcbiAqXG4gKiAvLyBPdmVycmlkZSBhIGZyYW1ld29yay1hdHRhY2hlZCByZWNvcmRlciBieSBwYXNzaW5nIGl0cyB3ZWxsLWtub3duIElEXG4gKiBleGVjdXRvci5hdHRhY2hSZWNvcmRlcihuZXcgTWV0cmljUmVjb3JkZXIoeyBpZDogJ21ldHJpY3MnIH0pKTtcbiAqIGBgYFxuICovXG5cbmltcG9ydCB0eXBlIHsgQ29tbWl0RXZlbnQsIFBhdXNlRXZlbnQsIFJlYWRFdmVudCwgUmVjb3JkZXIsIFN0YWdlRXZlbnQsIFdyaXRlRXZlbnQgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhZ2VNZXRyaWNzIHtcbiAgc3RhZ2VOYW1lOiBzdHJpbmc7XG4gIHJlYWRDb3VudDogbnVtYmVyO1xuICB3cml0ZUNvdW50OiBudW1iZXI7XG4gIGNvbW1pdENvdW50OiBudW1iZXI7XG4gIHBhdXNlQ291bnQ6IG51bWJlcjtcbiAgdG90YWxEdXJhdGlvbjogbnVtYmVyO1xuICBpbnZvY2F0aW9uQ291bnQ6IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2dyZWdhdGVkTWV0cmljcyB7XG4gIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbiAgdG90YWxSZWFkczogbnVtYmVyO1xuICB0b3RhbFdyaXRlczogbnVtYmVyO1xuICB0b3RhbENvbW1pdHM6IG51bWJlcjtcbiAgdG90YWxQYXVzZXM6IG51bWJlcjtcbiAgc3RhZ2VNZXRyaWNzOiBNYXA8c3RyaW5nLCBTdGFnZU1ldHJpY3M+O1xufVxuXG4vKiogT3B0aW9ucyBmb3IgTWV0cmljUmVjb3JkZXIuIEFsbCBmaWVsZHMgYXJlIG9wdGlvbmFsLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXRyaWNSZWNvcmRlck9wdGlvbnMge1xuICAvKiogUmVjb3JkZXIgSUQuIERlZmF1bHRzIHRvIGF1dG8taW5jcmVtZW50IChgbWV0cmljcy0xYCwgYG1ldHJpY3MtMmAsIC4uLikuICovXG4gIGlkPzogc3RyaW5nO1xuICAvKipcbiAgICogRmlsdGVyIHdoaWNoIHN0YWdlcyBhcmUgcmVjb3JkZWQuIFJldHVybiBgdHJ1ZWAgdG8gcmVjb3JkLCBgZmFsc2VgIHRvIHNraXAuXG4gICAqIFdoZW4gb21pdHRlZCwgYWxsIHN0YWdlcyBhcmUgcmVjb3JkZWQuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gT25seSB0cmFjayBzdGFnZXMgdGhhdCBzdGFydCB3aXRoIFwiQ2FsbFwiXG4gICAqIHN0YWdlRmlsdGVyOiAobmFtZSkgPT4gbmFtZS5zdGFydHNXaXRoKCdDYWxsJylcbiAgICogYGBgXG4gICAqL1xuICBzdGFnZUZpbHRlcj86IChzdGFnZU5hbWU6IHN0cmluZykgPT4gYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIE1ldHJpY1JlY29yZGVyIGltcGxlbWVudHMgUmVjb3JkZXIge1xuICBwcml2YXRlIHN0YXRpYyBfY291bnRlciA9IDA7XG5cbiAgcmVhZG9ubHkgaWQ6IHN0cmluZztcbiAgcHJpdmF0ZSBtZXRyaWNzOiBNYXA8c3RyaW5nLCBTdGFnZU1ldHJpY3M+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIHN0YWdlU3RhcnRUaW1lczogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBzdGFnZUZpbHRlcj86IChzdGFnZU5hbWU6IHN0cmluZykgPT4gYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihpZE9yT3B0aW9ucz86IHN0cmluZyB8IE1ldHJpY1JlY29yZGVyT3B0aW9ucykge1xuICAgIGlmICh0eXBlb2YgaWRPck9wdGlvbnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLmlkID0gaWRPck9wdGlvbnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuaWQgPSBpZE9yT3B0aW9ucz8uaWQgPz8gYG1ldHJpY3MtJHsrK01ldHJpY1JlY29yZGVyLl9jb3VudGVyfWA7XG4gICAgICB0aGlzLnN0YWdlRmlsdGVyID0gaWRPck9wdGlvbnM/LnN0YWdlRmlsdGVyO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc2hvdWxkUmVjb3JkKHN0YWdlTmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICF0aGlzLnN0YWdlRmlsdGVyIHx8IHRoaXMuc3RhZ2VGaWx0ZXIoc3RhZ2VOYW1lKTtcbiAgfVxuXG4gIG9uUmVhZChldmVudDogUmVhZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFJlY29yZChldmVudC5zdGFnZU5hbWUpKSByZXR1cm47XG4gICAgdGhpcy5nZXRPckNyZWF0ZVN0YWdlTWV0cmljcyhldmVudC5zdGFnZU5hbWUpLnJlYWRDb3VudCsrO1xuICB9XG5cbiAgb25Xcml0ZShldmVudDogV3JpdGVFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zaG91bGRSZWNvcmQoZXZlbnQuc3RhZ2VOYW1lKSkgcmV0dXJuO1xuICAgIHRoaXMuZ2V0T3JDcmVhdGVTdGFnZU1ldHJpY3MoZXZlbnQuc3RhZ2VOYW1lKS53cml0ZUNvdW50Kys7XG4gIH1cblxuICBvbkNvbW1pdChldmVudDogQ29tbWl0RXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICB0aGlzLmdldE9yQ3JlYXRlU3RhZ2VNZXRyaWNzKGV2ZW50LnN0YWdlTmFtZSkuY29tbWl0Q291bnQrKztcbiAgfVxuXG4gIG9uUGF1c2UoZXZlbnQ6IFBhdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICB0aGlzLmdldE9yQ3JlYXRlU3RhZ2VNZXRyaWNzKGV2ZW50LnN0YWdlTmFtZSkucGF1c2VDb3VudCsrO1xuICB9XG5cbiAgb25TdGFnZVN0YXJ0KGV2ZW50OiBTdGFnZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFJlY29yZChldmVudC5zdGFnZU5hbWUpKSByZXR1cm47XG4gICAgdGhpcy5zdGFnZVN0YXJ0VGltZXMuc2V0KGV2ZW50LnN0YWdlTmFtZSwgZXZlbnQudGltZXN0YW1wKTtcbiAgICB0aGlzLmdldE9yQ3JlYXRlU3RhZ2VNZXRyaWNzKGV2ZW50LnN0YWdlTmFtZSkuaW52b2NhdGlvbkNvdW50Kys7XG4gIH1cblxuICBvblN0YWdlRW5kKGV2ZW50OiBTdGFnZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFJlY29yZChldmVudC5zdGFnZU5hbWUpKSByZXR1cm47XG4gICAgY29uc3Qgc3RhZ2VNZXRyaWNzID0gdGhpcy5nZXRPckNyZWF0ZVN0YWdlTWV0cmljcyhldmVudC5zdGFnZU5hbWUpO1xuICAgIGxldCBkdXJhdGlvbjogbnVtYmVyO1xuICAgIGlmIChldmVudC5kdXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkdXJhdGlvbiA9IGV2ZW50LmR1cmF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzdGFydFRpbWUgPSB0aGlzLnN0YWdlU3RhcnRUaW1lcy5nZXQoZXZlbnQuc3RhZ2VOYW1lKTtcbiAgICAgIGR1cmF0aW9uID0gc3RhcnRUaW1lICE9PSB1bmRlZmluZWQgPyBldmVudC50aW1lc3RhbXAgLSBzdGFydFRpbWUgOiAwO1xuICAgIH1cbiAgICBzdGFnZU1ldHJpY3MudG90YWxEdXJhdGlvbiArPSBkdXJhdGlvbjtcbiAgICB0aGlzLnN0YWdlU3RhcnRUaW1lcy5kZWxldGUoZXZlbnQuc3RhZ2VOYW1lKTtcbiAgfVxuXG4gIGdldE1ldHJpY3MoKTogQWdncmVnYXRlZE1ldHJpY3Mge1xuICAgIGxldCB0b3RhbER1cmF0aW9uID0gMDtcbiAgICBsZXQgdG90YWxSZWFkcyA9IDA7XG4gICAgbGV0IHRvdGFsV3JpdGVzID0gMDtcbiAgICBsZXQgdG90YWxDb21taXRzID0gMDtcbiAgICBsZXQgdG90YWxQYXVzZXMgPSAwO1xuXG4gICAgZm9yIChjb25zdCBzdGFnZU1ldHJpY3Mgb2YgdGhpcy5tZXRyaWNzLnZhbHVlcygpKSB7XG4gICAgICB0b3RhbER1cmF0aW9uICs9IHN0YWdlTWV0cmljcy50b3RhbER1cmF0aW9uO1xuICAgICAgdG90YWxSZWFkcyArPSBzdGFnZU1ldHJpY3MucmVhZENvdW50O1xuICAgICAgdG90YWxXcml0ZXMgKz0gc3RhZ2VNZXRyaWNzLndyaXRlQ291bnQ7XG4gICAgICB0b3RhbENvbW1pdHMgKz0gc3RhZ2VNZXRyaWNzLmNvbW1pdENvdW50O1xuICAgICAgdG90YWxQYXVzZXMgKz0gc3RhZ2VNZXRyaWNzLnBhdXNlQ291bnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRvdGFsRHVyYXRpb24sXG4gICAgICB0b3RhbFJlYWRzLFxuICAgICAgdG90YWxXcml0ZXMsXG4gICAgICB0b3RhbENvbW1pdHMsXG4gICAgICB0b3RhbFBhdXNlcyxcbiAgICAgIHN0YWdlTWV0cmljczogbmV3IE1hcCh0aGlzLm1ldHJpY3MpLFxuICAgIH07XG4gIH1cblxuICBnZXRTdGFnZU1ldHJpY3Moc3RhZ2VOYW1lOiBzdHJpbmcpOiBTdGFnZU1ldHJpY3MgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG1ldHJpY3MgPSB0aGlzLm1ldHJpY3MuZ2V0KHN0YWdlTmFtZSk7XG4gICAgcmV0dXJuIG1ldHJpY3MgPyB7IC4uLm1ldHJpY3MgfSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHRvU25hcHNob3QoKTogeyBuYW1lOiBzdHJpbmc7IGRhdGE6IHVua25vd24gfSB7XG4gICAgY29uc3QgbWV0cmljcyA9IHRoaXMuZ2V0TWV0cmljcygpO1xuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnTWV0cmljcycsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIHRvdGFsRHVyYXRpb246IG1ldHJpY3MudG90YWxEdXJhdGlvbixcbiAgICAgICAgdG90YWxSZWFkczogbWV0cmljcy50b3RhbFJlYWRzLFxuICAgICAgICB0b3RhbFdyaXRlczogbWV0cmljcy50b3RhbFdyaXRlcyxcbiAgICAgICAgdG90YWxDb21taXRzOiBtZXRyaWNzLnRvdGFsQ29tbWl0cyxcbiAgICAgICAgc3RhZ2VzOiBPYmplY3QuZnJvbUVudHJpZXMobWV0cmljcy5zdGFnZU1ldHJpY3MpLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5tZXRyaWNzLmNsZWFyKCk7XG4gICAgdGhpcy5zdGFnZVN0YXJ0VGltZXMuY2xlYXIoKTtcbiAgfVxuXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIHRoaXMucmVzZXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0T3JDcmVhdGVTdGFnZU1ldHJpY3Moc3RhZ2VOYW1lOiBzdHJpbmcpOiBTdGFnZU1ldHJpY3Mge1xuICAgIGxldCBzdGFnZU1ldHJpY3MgPSB0aGlzLm1ldHJpY3MuZ2V0KHN0YWdlTmFtZSk7XG4gICAgaWYgKCFzdGFnZU1ldHJpY3MpIHtcbiAgICAgIHN0YWdlTWV0cmljcyA9IHtcbiAgICAgICAgc3RhZ2VOYW1lLFxuICAgICAgICByZWFkQ291bnQ6IDAsXG4gICAgICAgIHdyaXRlQ291bnQ6IDAsXG4gICAgICAgIGNvbW1pdENvdW50OiAwLFxuICAgICAgICBwYXVzZUNvdW50OiAwLFxuICAgICAgICB0b3RhbER1cmF0aW9uOiAwLFxuICAgICAgICBpbnZvY2F0aW9uQ291bnQ6IDAsXG4gICAgICB9O1xuICAgICAgdGhpcy5tZXRyaWNzLnNldChzdGFnZU5hbWUsIHN0YWdlTWV0cmljcyk7XG4gICAgfVxuICAgIHJldHVybiBzdGFnZU1ldHJpY3M7XG4gIH1cbn1cbiJdfQ==
160
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWV0cmljUmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3JlY29yZGVycy9NZXRyaWNSZWNvcmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRzs7O0FBRUgsc0VBQWdFO0FBaURoRSxNQUFhLGNBQWUsU0FBUSxnQ0FBMEI7SUFRNUQsWUFBWSxXQUE0Qzs7UUFDdEQsS0FBSyxFQUFFLENBQUM7UUFMRixvQkFBZSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQzVDLDBCQUFxQixHQUFHLEVBQUUsQ0FBQztRQUtqQyxJQUFJLE9BQU8sV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxFQUFFLEdBQUcsV0FBVyxDQUFDO1FBQ3hCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFBLFdBQVcsYUFBWCxXQUFXLHVCQUFYLFdBQVcsQ0FBRSxFQUFFLG1DQUFJLFdBQVcsRUFBRSxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEUsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLGFBQVgsV0FBVyx1QkFBWCxXQUFXLENBQUUsV0FBVyxDQUFDO1FBQzlDLENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWSxDQUFDLFNBQWlCO1FBQ3BDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVELDJEQUEyRDtJQUNuRCxPQUFPO1FBQ2IsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDO1FBQ3ZDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0IsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1AsQ0FBQyxHQUFHLEVBQUUsU0FBUyxF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QztJQUVELDhEQUE4RDtJQUNyRCxLQUFLO1FBQ1osS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRCwyQ0FBMkM7SUFDM0MsS0FBSztRQUNILElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNmLENBQUM7O0FBNUlILHdDQTZJQztBQTVJZ0IsdUJBQVEsR0FBRyxDQUFDLEFBQUosQ0FBSyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWV0cmljUmVjb3JkZXIg4oCUIHBlci1zdGVwIHRpbWluZyBhbmQgZXhlY3V0aW9uIGNvdW50cywga2V5ZWQgYnkgcnVudGltZVN0YWdlSWQuXG4gKlxuICogU3RvcmVzIHBlci1pbnZvY2F0aW9uIGRhdGEgZHVyaW5nIHRyYXZlcnNhbC4gQWdncmVnYXRlZCB2aWV3cyBjb21wdXRlZCBvbiByZWFkLlxuICogRXh0ZW5kcyBLZXllZFJlY29yZGVyPFN0ZXBNZXRyaWNzPiBmb3IgTygxKSBsb29rdXAgYW5kIHN0YW5kYXJkIG9wZXJhdGlvbnMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IG1ldHJpYyA9IG5ldyBNZXRyaWNSZWNvcmRlcigpO1xuICogZXhlY3V0b3IuYXR0YWNoUmVjb3JkZXIobWV0cmljKTtcbiAqIGF3YWl0IGV4ZWN1dG9yLnJ1bigpO1xuICpcbiAqIC8vIFBlci1zdGVwICh0aW1lLXRyYXZlbCk6XG4gKiBtZXRyaWMuZ2V0QnlLZXkoJ2NhbGwtbGxtIzUnKTsgIC8vIHsgc3RhZ2VOYW1lLCByZWFkQ291bnQsIHdyaXRlQ291bnQsIGR1cmF0aW9uIH1cbiAqXG4gKiAvLyBBZ2dyZWdhdGVkIChiYWNrd2FyZCBjb21wYXQpOlxuICogbWV0cmljLmdldE1ldHJpY3MoKTsgIC8vIHsgdG90YWxEdXJhdGlvbiwgdG90YWxSZWFkcywgc3RhZ2VNZXRyaWNzOiBNYXA8c3RhZ2VOYW1lLCBhZ2dyZWdhdGVkPiB9XG4gKlxuICogLy8gUHJvZ3Jlc3NpdmUgKHNsaWRlcik6XG4gKiBtZXRyaWMuYWNjdW11bGF0ZSgoc3VtLCBtKSA9PiBzdW0gKyBtLmR1cmF0aW9uLCAwLCB2aXNpYmxlS2V5cyk7XG4gKiBgYGBcbiAqL1xuXG5pbXBvcnQgeyBLZXllZFJlY29yZGVyIH0gZnJvbSAnLi4vLi4vcmVjb3JkZXIvS2V5ZWRSZWNvcmRlci5qcyc7XG5pbXBvcnQgdHlwZSB7IENvbW1pdEV2ZW50LCBQYXVzZUV2ZW50LCBSZWFkRXZlbnQsIFJlY29yZGVyLCBTdGFnZUV2ZW50LCBXcml0ZUV2ZW50IH0gZnJvbSAnLi4vdHlwZXMuanMnO1xuXG4vKiogUGVyLWludm9jYXRpb24gbWV0cmljcyBmb3IgYSBzaW5nbGUgZXhlY3V0aW9uIHN0ZXAuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0ZXBNZXRyaWNzIHtcbiAgLyoqIEh1bWFuLXJlYWRhYmxlIHN0YWdlIG5hbWUuICovXG4gIHN0YWdlTmFtZTogc3RyaW5nO1xuICAvKiogTnVtYmVyIG9mIHNjb3BlIHJlYWRzIGR1cmluZyB0aGlzIGludm9jYXRpb24uICovXG4gIHJlYWRDb3VudDogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIHNjb3BlIHdyaXRlcyBkdXJpbmcgdGhpcyBpbnZvY2F0aW9uLiAqL1xuICB3cml0ZUNvdW50OiBudW1iZXI7XG4gIC8qKiBOdW1iZXIgb2YgY29tbWl0cyBkdXJpbmcgdGhpcyBpbnZvY2F0aW9uLiAqL1xuICBjb21taXRDb3VudDogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIHBhdXNlcyBkdXJpbmcgdGhpcyBpbnZvY2F0aW9uLiAqL1xuICBwYXVzZUNvdW50OiBudW1iZXI7XG4gIC8qKiBEdXJhdGlvbiBpbiBtcyBmb3IgdGhpcyBpbnZvY2F0aW9uLiAqL1xuICBkdXJhdGlvbjogbnVtYmVyO1xufVxuXG4vKiogQWdncmVnYXRlZCBtZXRyaWNzIGFjcm9zcyBhbGwgaW52b2NhdGlvbnMgKGJhY2t3YXJkIGNvbXBhdGlibGUpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZ2dyZWdhdGVkTWV0cmljcyB7XG4gIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbiAgdG90YWxSZWFkczogbnVtYmVyO1xuICB0b3RhbFdyaXRlczogbnVtYmVyO1xuICB0b3RhbENvbW1pdHM6IG51bWJlcjtcbiAgdG90YWxQYXVzZXM6IG51bWJlcjtcbiAgLyoqIEFnZ3JlZ2F0ZWQgYnkgc3RhZ2VOYW1lIOKAlCBzdW1zIGFjcm9zcyBsb29wIGludm9jYXRpb25zLiAqL1xuICBzdGFnZU1ldHJpY3M6IE1hcDxzdHJpbmcsIFN0YWdlTWV0cmljcz47XG59XG5cbi8qKiBBZ2dyZWdhdGVkIHBlci1zdGFnZU5hbWUgKGJhY2t3YXJkIGNvbXBhdGlibGUgd2l0aCBwcmUtcnVudGltZVN0YWdlSWQgQVBJKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhZ2VNZXRyaWNzIHtcbiAgc3RhZ2VOYW1lOiBzdHJpbmc7XG4gIHJlYWRDb3VudDogbnVtYmVyO1xuICB3cml0ZUNvdW50OiBudW1iZXI7XG4gIGNvbW1pdENvdW50OiBudW1iZXI7XG4gIHBhdXNlQ291bnQ6IG51bWJlcjtcbiAgdG90YWxEdXJhdGlvbjogbnVtYmVyO1xuICBpbnZvY2F0aW9uQ291bnQ6IG51bWJlcjtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIE1ldHJpY1JlY29yZGVyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXRyaWNSZWNvcmRlck9wdGlvbnMge1xuICAvKiogUmVjb3JkZXIgSUQuIERlZmF1bHRzIHRvIGF1dG8taW5jcmVtZW50IChgbWV0cmljcy0xYCwgYG1ldHJpY3MtMmAsIC4uLikuICovXG4gIGlkPzogc3RyaW5nO1xuICAvKiogRmlsdGVyIHdoaWNoIHN0YWdlcyBhcmUgcmVjb3JkZWQuIFJldHVybiBgdHJ1ZWAgdG8gcmVjb3JkLCBgZmFsc2VgIHRvIHNraXAuICovXG4gIHN0YWdlRmlsdGVyPzogKHN0YWdlTmFtZTogc3RyaW5nKSA9PiBib29sZWFuO1xufVxuXG5leHBvcnQgY2xhc3MgTWV0cmljUmVjb3JkZXIgZXh0ZW5kcyBLZXllZFJlY29yZGVyPFN0ZXBNZXRyaWNzPiBpbXBsZW1lbnRzIFJlY29yZGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgX2NvdW50ZXIgPSAwO1xuXG4gIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIHByaXZhdGUgc3RhZ2VTdGFydFRpbWVzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgcHJpdmF0ZSBjdXJyZW50UnVudGltZVN0YWdlSWQgPSAnJztcbiAgcHJpdmF0ZSBzdGFnZUZpbHRlcj86IChzdGFnZU5hbWU6IHN0cmluZykgPT4gYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihpZE9yT3B0aW9ucz86IHN0cmluZyB8IE1ldHJpY1JlY29yZGVyT3B0aW9ucykge1xuICAgIHN1cGVyKCk7XG4gICAgaWYgKHR5cGVvZiBpZE9yT3B0aW9ucyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMuaWQgPSBpZE9yT3B0aW9ucztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5pZCA9IGlkT3JPcHRpb25zPy5pZCA/PyBgbWV0cmljcy0keysrTWV0cmljUmVjb3JkZXIuX2NvdW50ZXJ9YDtcbiAgICAgIHRoaXMuc3RhZ2VGaWx0ZXIgPSBpZE9yT3B0aW9ucz8uc3RhZ2VGaWx0ZXI7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzaG91bGRSZWNvcmQoc3RhZ2VOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gIXRoaXMuc3RhZ2VGaWx0ZXIgfHwgdGhpcy5zdGFnZUZpbHRlcihzdGFnZU5hbWUpO1xuICB9XG5cbiAgLyoqIEdldCBvciBjcmVhdGUgdGhlIFN0ZXBNZXRyaWNzIGZvciB0aGUgY3VycmVudCBzdGFnZS4gKi9cbiAgcHJpdmF0ZSBjdXJyZW50KCk6IFN0ZXBNZXRyaWNzIHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmN1cnJlbnRSdW50aW1lU3RhZ2VJZDtcbiAgICBsZXQgbSA9IHRoaXMuZ2V0QnlLZXkoa2V5KTtcbiAgICBpZiAoIW0pIHtcbiAgICAgIG0gPSB7IHN0YWdlTmFtZTogJycsIHJlYWRDb3VudDogMCwgd3JpdGVDb3VudDogMCwgY29tbWl0Q291bnQ6IDAsIHBhdXNlQ291bnQ6IDAsIGR1cmF0aW9uOiAwIH07XG4gICAgICB0aGlzLnN0b3JlKGtleSwgbSk7XG4gICAgfVxuICAgIHJldHVybiBtO1xuICB9XG5cbiAgb25TdGFnZVN0YXJ0KGV2ZW50OiBTdGFnZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFJlY29yZChldmVudC5zdGFnZU5hbWUpKSByZXR1cm47XG4gICAgdGhpcy5jdXJyZW50UnVudGltZVN0YWdlSWQgPSBldmVudC5ydW50aW1lU3RhZ2VJZDtcbiAgICB0aGlzLnN0YWdlU3RhcnRUaW1lcy5zZXQoZXZlbnQucnVudGltZVN0YWdlSWQsIGV2ZW50LnRpbWVzdGFtcCk7XG4gICAgY29uc3QgbSA9IHRoaXMuY3VycmVudCgpO1xuICAgIG0uc3RhZ2VOYW1lID0gZXZlbnQuc3RhZ2VOYW1lO1xuICB9XG5cbiAgb25SZWFkKGV2ZW50OiBSZWFkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICB0aGlzLmN1cnJlbnQoKS5yZWFkQ291bnQrKztcbiAgfVxuXG4gIG9uV3JpdGUoZXZlbnQ6IFdyaXRlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICB0aGlzLmN1cnJlbnQoKS53cml0ZUNvdW50Kys7XG4gIH1cblxuICBvbkNvbW1pdChldmVudDogQ29tbWl0RXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICB0aGlzLmN1cnJlbnQoKS5jb21taXRDb3VudCsrO1xuICB9XG5cbiAgb25QYXVzZShldmVudDogUGF1c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zaG91bGRSZWNvcmQoZXZlbnQuc3RhZ2VOYW1lKSkgcmV0dXJuO1xuICAgIHRoaXMuY3VycmVudCgpLnBhdXNlQ291bnQrKztcbiAgfVxuXG4gIG9uU3RhZ2VFbmQoZXZlbnQ6IFN0YWdlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkUmVjb3JkKGV2ZW50LnN0YWdlTmFtZSkpIHJldHVybjtcbiAgICBjb25zdCBtID0gdGhpcy5jdXJyZW50KCk7XG4gICAgaWYgKGV2ZW50LmR1cmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG0uZHVyYXRpb24gPSBldmVudC5kdXJhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gdGhpcy5zdGFnZVN0YXJ0VGltZXMuZ2V0KGV2ZW50LnJ1bnRpbWVTdGFnZUlkKTtcbiAgICAgIG0uZHVyYXRpb24gPSBzdGFydFRpbWUgIT09IHVuZGVmaW5lZCA/IGV2ZW50LnRpbWVzdGFtcCAtIHN0YXJ0VGltZSA6IDA7XG4gICAgfVxuICAgIHRoaXMuc3RhZ2VTdGFydFRpbWVzLmRlbGV0ZShldmVudC5ydW50aW1lU3RhZ2VJZCk7XG4gIH1cblxuICAvKiogQWdncmVnYXRlZCBtZXRyaWNzIOKAlCBjb21wdXRlcyB0b3RhbHMgb24gdGhlIGZseSBmcm9tIHBlci1zdGVwIGRhdGEgKGJhY2t3YXJkIGNvbXBhdGlibGUpLiAqL1xuICBnZXRNZXRyaWNzKCk6IEFnZ3JlZ2F0ZWRNZXRyaWNzIHtcbiAgICBjb25zdCBieU5hbWUgPSBuZXcgTWFwPHN0cmluZywgU3RhZ2VNZXRyaWNzPigpO1xuXG4gICAgY29uc3QgdG90YWxEdXJhdGlvbiA9IHRoaXMuYWdncmVnYXRlKChzdW0sIG0pID0+IHN1bSArIG0uZHVyYXRpb24sIDApO1xuICAgIGNvbnN0IHRvdGFsUmVhZHMgPSB0aGlzLmFnZ3JlZ2F0ZSgoc3VtLCBtKSA9PiBzdW0gKyBtLnJlYWRDb3VudCwgMCk7XG4gICAgY29uc3QgdG90YWxXcml0ZXMgPSB0aGlzLmFnZ3JlZ2F0ZSgoc3VtLCBtKSA9PiBzdW0gKyBtLndyaXRlQ291bnQsIDApO1xuICAgIGNvbnN0IHRvdGFsQ29tbWl0cyA9IHRoaXMuYWdncmVnYXRlKChzdW0sIG0pID0+IHN1bSArIG0uY29tbWl0Q291bnQsIDApO1xuICAgIGNvbnN0IHRvdGFsUGF1c2VzID0gdGhpcy5hZ2dyZWdhdGUoKHN1bSwgbSkgPT4gc3VtICsgbS5wYXVzZUNvdW50LCAwKTtcblxuICAgIC8vIEdyb3VwIGJ5IHN0YWdlTmFtZSBmb3IgYmFja3dhcmQgY29tcGF0XG4gICAgZm9yIChjb25zdCBtIG9mIHRoaXMudmFsdWVzKCkpIHtcbiAgICAgIGNvbnN0IGV4aXN0aW5nID0gYnlOYW1lLmdldChtLnN0YWdlTmFtZSk7XG4gICAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgICAgZXhpc3RpbmcucmVhZENvdW50ICs9IG0ucmVhZENvdW50O1xuICAgICAgICBleGlzdGluZy53cml0ZUNvdW50ICs9IG0ud3JpdGVDb3VudDtcbiAgICAgICAgZXhpc3RpbmcuY29tbWl0Q291bnQgKz0gbS5jb21taXRDb3VudDtcbiAgICAgICAgZXhpc3RpbmcucGF1c2VDb3VudCArPSBtLnBhdXNlQ291bnQ7XG4gICAgICAgIGV4aXN0aW5nLnRvdGFsRHVyYXRpb24gKz0gbS5kdXJhdGlvbjtcbiAgICAgICAgZXhpc3RpbmcuaW52b2NhdGlvbkNvdW50Kys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBieU5hbWUuc2V0KG0uc3RhZ2VOYW1lLCB7XG4gICAgICAgICAgc3RhZ2VOYW1lOiBtLnN0YWdlTmFtZSxcbiAgICAgICAgICByZWFkQ291bnQ6IG0ucmVhZENvdW50LFxuICAgICAgICAgIHdyaXRlQ291bnQ6IG0ud3JpdGVDb3VudCxcbiAgICAgICAgICBjb21taXRDb3VudDogbS5jb21taXRDb3VudCxcbiAgICAgICAgICBwYXVzZUNvdW50OiBtLnBhdXNlQ291bnQsXG4gICAgICAgICAgdG90YWxEdXJhdGlvbjogbS5kdXJhdGlvbixcbiAgICAgICAgICBpbnZvY2F0aW9uQ291bnQ6IDEsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IHRvdGFsRHVyYXRpb24sIHRvdGFsUmVhZHMsIHRvdGFsV3JpdGVzLCB0b3RhbENvbW1pdHMsIHRvdGFsUGF1c2VzLCBzdGFnZU1ldHJpY3M6IGJ5TmFtZSB9O1xuICB9XG5cbiAgLyoqIEdldCBhZ2dyZWdhdGVkIG1ldHJpY3MgZm9yIGEgc3BlY2lmaWMgc3RhZ2UgbmFtZSAoYmFja3dhcmQgY29tcGF0aWJsZSkuICovXG4gIGdldFN0YWdlTWV0cmljcyhzdGFnZU5hbWU6IHN0cmluZyk6IFN0YWdlTWV0cmljcyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWV0cmljcyA9IHRoaXMuZ2V0TWV0cmljcygpO1xuICAgIHJldHVybiBtZXRyaWNzLnN0YWdlTWV0cmljcy5nZXQoc3RhZ2VOYW1lKTtcbiAgfVxuXG4gIC8qKiBTbmFwc2hvdCBmb3Igc2VyaWFsaXphdGlvbiAoYmFja3dhcmQgY29tcGF0aWJsZSBmb3JtYXQpLiAqL1xuICB0b1NuYXBzaG90KCk6IHsgbmFtZTogc3RyaW5nOyBkYXRhOiB1bmtub3duIH0ge1xuICAgIGNvbnN0IG1ldHJpY3MgPSB0aGlzLmdldE1ldHJpY3MoKTtcbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ01ldHJpY3MnLFxuICAgICAgZGF0YToge1xuICAgICAgICB0b3RhbER1cmF0aW9uOiBtZXRyaWNzLnRvdGFsRHVyYXRpb24sXG4gICAgICAgIHRvdGFsUmVhZHM6IG1ldHJpY3MudG90YWxSZWFkcyxcbiAgICAgICAgdG90YWxXcml0ZXM6IG1ldHJpY3MudG90YWxXcml0ZXMsXG4gICAgICAgIHRvdGFsQ29tbWl0czogbWV0cmljcy50b3RhbENvbW1pdHMsXG4gICAgICAgIHN0YWdlczogT2JqZWN0LmZyb21FbnRyaWVzKG1ldHJpY3Muc3RhZ2VNZXRyaWNzKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBDbGVhciBhbGwgc3RhdGUg4oCUIGNhbGxlZCBieSBleGVjdXRvciBiZWZvcmUgZWFjaCBydW4oKS4gKi9cbiAgb3ZlcnJpZGUgY2xlYXIoKTogdm9pZCB7XG4gICAgc3VwZXIuY2xlYXIoKTtcbiAgICB0aGlzLnN0YWdlU3RhcnRUaW1lcy5jbGVhcigpO1xuICAgIHRoaXMuY3VycmVudFJ1bnRpbWVTdGFnZUlkID0gJyc7XG4gIH1cblxuICAvKiogQWxpYXMgZm9yIGNsZWFyKCkgKGJhY2t3YXJkIGNvbXBhdCkuICovXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXIoKTtcbiAgfVxufVxuIl19
@@ -5,4 +5,4 @@ var DebugRecorder_js_1 = require("./DebugRecorder.js");
5
5
  Object.defineProperty(exports, "DebugRecorder", { enumerable: true, get: function () { return DebugRecorder_js_1.DebugRecorder; } });
6
6
  var MetricRecorder_js_1 = require("./MetricRecorder.js");
7
7
  Object.defineProperty(exports, "MetricRecorder", { enumerable: true, get: function () { return MetricRecorder_js_1.MetricRecorder; } });
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3JlY29yZGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFXQSx1REFBbUQ7QUFBMUMsaUhBQUEsYUFBYSxPQUFBO0FBRXRCLHlEQUFxRDtBQUE1QyxtSEFBQSxjQUFjLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuZXhwb3J0IHR5cGUge1xuICBDb21taXRFdmVudCxcbiAgRXJyb3JFdmVudCxcbiAgUmVhZEV2ZW50LFxuICBSZWNvcmRlcixcbiAgUmVjb3JkZXJDb250ZXh0LFxuICBTdGFnZUV2ZW50LFxuICBXcml0ZUV2ZW50LFxufSBmcm9tICcuLi90eXBlcy5qcyc7XG5leHBvcnQgdHlwZSB7IERlYnVnRW50cnksIERlYnVnUmVjb3JkZXJPcHRpb25zLCBEZWJ1Z1ZlcmJvc2l0eSB9IGZyb20gJy4vRGVidWdSZWNvcmRlci5qcyc7XG5leHBvcnQgeyBEZWJ1Z1JlY29yZGVyIH0gZnJvbSAnLi9EZWJ1Z1JlY29yZGVyLmpzJztcbmV4cG9ydCB0eXBlIHsgQWdncmVnYXRlZE1ldHJpY3MsIFN0YWdlTWV0cmljcyB9IGZyb20gJy4vTWV0cmljUmVjb3JkZXIuanMnO1xuZXhwb3J0IHsgTWV0cmljUmVjb3JkZXIgfSBmcm9tICcuL01ldHJpY1JlY29yZGVyLmpzJztcbiJdfQ==
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3Njb3BlL3JlY29yZGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFXQSx1REFBbUQ7QUFBMUMsaUhBQUEsYUFBYSxPQUFBO0FBRXRCLHlEQUFxRDtBQUE1QyxtSEFBQSxjQUFjLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBpc3RhbmJ1bCBpZ25vcmUgZmlsZSAqL1xuZXhwb3J0IHR5cGUge1xuICBDb21taXRFdmVudCxcbiAgRXJyb3JFdmVudCxcbiAgUmVhZEV2ZW50LFxuICBSZWNvcmRlcixcbiAgUmVjb3JkZXJDb250ZXh0LFxuICBTdGFnZUV2ZW50LFxuICBXcml0ZUV2ZW50LFxufSBmcm9tICcuLi90eXBlcy5qcyc7XG5leHBvcnQgdHlwZSB7IERlYnVnRW50cnksIERlYnVnUmVjb3JkZXJPcHRpb25zLCBEZWJ1Z1ZlcmJvc2l0eSB9IGZyb20gJy4vRGVidWdSZWNvcmRlci5qcyc7XG5leHBvcnQgeyBEZWJ1Z1JlY29yZGVyIH0gZnJvbSAnLi9EZWJ1Z1JlY29yZGVyLmpzJztcbmV4cG9ydCB0eXBlIHsgQWdncmVnYXRlZE1ldHJpY3MsIFN0YWdlTWV0cmljcywgU3RlcE1ldHJpY3MgfSBmcm9tICcuL01ldHJpY1JlY29yZGVyLmpzJztcbmV4cG9ydCB7IE1ldHJpY1JlY29yZGVyIH0gZnJvbSAnLi9NZXRyaWNSZWNvcmRlci5qcyc7XG4iXX0=
package/dist/trace.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * footprintjs/trace — Execution tracing, debugging, and backtracking utilities.
4
+ *
5
+ * Runtime stage IDs, commit log queries, and keyed recorder base class.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { parseRuntimeStageId, findLastWriter, KeyedRecorder } from 'footprintjs/trace';
10
+ *
11
+ * // Parse a runtimeStageId
12
+ * const { stageId, executionIndex } = parseRuntimeStageId('call-llm#5');
13
+ *
14
+ * // Backtrack: who wrote 'systemPrompt' before stage at idx 8?
15
+ * const writer = findLastWriter(commitLog, 'systemPrompt', 8);
16
+ *
17
+ * // Build a keyed recorder
18
+ * class MyRecorder extends KeyedRecorder<MyEntry> { ... }
19
+ * ```
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.KeyedRecorder = exports.findLastWriter = exports.findCommits = exports.findCommit = exports.parseRuntimeStageId = exports.createExecutionCounter = exports.buildRuntimeStageId = void 0;
23
+ var runtimeStageId_js_1 = require("./lib/engine/runtimeStageId.js");
24
+ Object.defineProperty(exports, "buildRuntimeStageId", { enumerable: true, get: function () { return runtimeStageId_js_1.buildRuntimeStageId; } });
25
+ Object.defineProperty(exports, "createExecutionCounter", { enumerable: true, get: function () { return runtimeStageId_js_1.createExecutionCounter; } });
26
+ Object.defineProperty(exports, "parseRuntimeStageId", { enumerable: true, get: function () { return runtimeStageId_js_1.parseRuntimeStageId; } });
27
+ // Commit log queries — typed utilities for backtracking
28
+ var commitLogUtils_js_1 = require("./lib/memory/commitLogUtils.js");
29
+ Object.defineProperty(exports, "findCommit", { enumerable: true, get: function () { return commitLogUtils_js_1.findCommit; } });
30
+ Object.defineProperty(exports, "findCommits", { enumerable: true, get: function () { return commitLogUtils_js_1.findCommits; } });
31
+ Object.defineProperty(exports, "findLastWriter", { enumerable: true, get: function () { return commitLogUtils_js_1.findLastWriter; } });
32
+ // KeyedRecorder — base class for Map-based recorders
33
+ var KeyedRecorder_js_1 = require("./lib/recorder/KeyedRecorder.js");
34
+ Object.defineProperty(exports, "KeyedRecorder", { enumerable: true, get: function () { return KeyedRecorder_js_1.KeyedRecorder; } });
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHJhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7OztBQUlILG9FQUFrSDtBQUF6Ryx3SEFBQSxtQkFBbUIsT0FBQTtBQUFFLDJIQUFBLHNCQUFzQixPQUFBO0FBQUUsd0hBQUEsbUJBQW1CLE9BQUE7QUFFekUsd0RBQXdEO0FBQ3hELG9FQUF5RjtBQUFoRiwrR0FBQSxVQUFVLE9BQUE7QUFBRSxnSEFBQSxXQUFXLE9BQUE7QUFBRSxtSEFBQSxjQUFjLE9BQUE7QUFFaEQscURBQXFEO0FBQ3JELG9FQUFnRTtBQUF2RCxpSEFBQSxhQUFhLE9BQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGZvb3RwcmludGpzL3RyYWNlIOKAlCBFeGVjdXRpb24gdHJhY2luZywgZGVidWdnaW5nLCBhbmQgYmFja3RyYWNraW5nIHV0aWxpdGllcy5cbiAqXG4gKiBSdW50aW1lIHN0YWdlIElEcywgY29tbWl0IGxvZyBxdWVyaWVzLCBhbmQga2V5ZWQgcmVjb3JkZXIgYmFzZSBjbGFzcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgcGFyc2VSdW50aW1lU3RhZ2VJZCwgZmluZExhc3RXcml0ZXIsIEtleWVkUmVjb3JkZXIgfSBmcm9tICdmb290cHJpbnRqcy90cmFjZSc7XG4gKlxuICogLy8gUGFyc2UgYSBydW50aW1lU3RhZ2VJZFxuICogY29uc3QgeyBzdGFnZUlkLCBleGVjdXRpb25JbmRleCB9ID0gcGFyc2VSdW50aW1lU3RhZ2VJZCgnY2FsbC1sbG0jNScpO1xuICpcbiAqIC8vIEJhY2t0cmFjazogd2hvIHdyb3RlICdzeXN0ZW1Qcm9tcHQnIGJlZm9yZSBzdGFnZSBhdCBpZHggOD9cbiAqIGNvbnN0IHdyaXRlciA9IGZpbmRMYXN0V3JpdGVyKGNvbW1pdExvZywgJ3N5c3RlbVByb21wdCcsIDgpO1xuICpcbiAqIC8vIEJ1aWxkIGEga2V5ZWQgcmVjb3JkZXJcbiAqIGNsYXNzIE15UmVjb3JkZXIgZXh0ZW5kcyBLZXllZFJlY29yZGVyPE15RW50cnk+IHsgLi4uIH1cbiAqIGBgYFxuICovXG5cbi8vIFJ1bnRpbWUgc3RhZ2UgSUQg4oCUIHVuaXF1ZSBleGVjdXRpb24gc3RlcCBpZGVudGlmaWVyc1xuZXhwb3J0IHR5cGUgeyBFeGVjdXRpb25Db3VudGVyIH0gZnJvbSAnLi9saWIvZW5naW5lL3J1bnRpbWVTdGFnZUlkLmpzJztcbmV4cG9ydCB7IGJ1aWxkUnVudGltZVN0YWdlSWQsIGNyZWF0ZUV4ZWN1dGlvbkNvdW50ZXIsIHBhcnNlUnVudGltZVN0YWdlSWQgfSBmcm9tICcuL2xpYi9lbmdpbmUvcnVudGltZVN0YWdlSWQuanMnO1xuXG4vLyBDb21taXQgbG9nIHF1ZXJpZXMg4oCUIHR5cGVkIHV0aWxpdGllcyBmb3IgYmFja3RyYWNraW5nXG5leHBvcnQgeyBmaW5kQ29tbWl0LCBmaW5kQ29tbWl0cywgZmluZExhc3RXcml0ZXIgfSBmcm9tICcuL2xpYi9tZW1vcnkvY29tbWl0TG9nVXRpbHMuanMnO1xuXG4vLyBLZXllZFJlY29yZGVyIOKAlCBiYXNlIGNsYXNzIGZvciBNYXAtYmFzZWQgcmVjb3JkZXJzXG5leHBvcnQgeyBLZXllZFJlY29yZGVyIH0gZnJvbSAnLi9saWIvcmVjb3JkZXIvS2V5ZWRSZWNvcmRlci5qcyc7XG4iXX0=
@@ -48,3 +48,7 @@ export type { BranchResult, BranchResults, SerializedPipelineStructure as Engine
48
48
  export { NullControlFlowNarrativeGenerator } from './lib/engine/index.js';
49
49
  export type { CallExtractorFn, ExecuteNodeFn, GetStagePathFn, RunStageFn } from './lib/engine/index.js';
50
50
  export { applyOutputMapping, ChildrenExecutor, computeNodeType, ContinuationResolver, createSubflowHandlerDeps, DeciderHandler, DEFAULT_MAX_ITERATIONS, ExtractorRunner, extractParentScopeValues, getInitialScopeValues, NodeResolver, RuntimeStructureManager, seedSubflowGlobalStore, SelectorHandler, StageRunner, SubflowExecutor, } from './lib/engine/index.js';
51
+ export type { ExecutionCounter } from './lib/engine/runtimeStageId.js';
52
+ export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId } from './lib/engine/runtimeStageId.js';
53
+ export { findCommit, findCommits, findLastWriter } from './lib/memory/commitLogUtils.js';
54
+ export { KeyedRecorder } from './lib/recorder/KeyedRecorder.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Typed utilities for querying the commit log.
3
+ *
4
+ * The commitLog is an ordered array of CommitBundle — one per stage commit.
5
+ * These helpers provide type-safe queries without (b: any) casts.
6
+ */
7
+ import type { CommitBundle } from './types.js';
8
+ /** Find the first commit by stageId, optionally filtering by a written key. */
9
+ export declare function findCommit(commitLog: CommitBundle[], stageId: string, key?: string): CommitBundle | undefined;
10
+ /** Find all commits by stageId. */
11
+ export declare function findCommits(commitLog: CommitBundle[], stageId: string): CommitBundle[];
12
+ /** Find the last commit that wrote a specific key (for backtracking). */
13
+ export declare function findLastWriter(commitLog: CommitBundle[], key: string, beforeIdx?: number): CommitBundle | undefined;
@@ -48,6 +48,8 @@ export interface FlowMessage {
48
48
  /** Serialisable representation of a stage's state (for debugging / visualisation). */
49
49
  export type StageSnapshot = {
50
50
  id: string;
51
+ /** Unique per-execution-step identifier. Format: [subflowPath/]stageId#executionIndex */
52
+ runtimeStageId?: string;
51
53
  name?: string;
52
54
  /** Human-readable description of what this stage does (from builder). */
53
55
  description?: string;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * KeyedRecorder<T> — base class for Map-based recorders keyed by runtimeStageId.
3
+ *
4
+ * Provides typed key-value storage with O(1) lookup, insertion-ordered iteration,
5
+ * and three standard operations on auto-collected traversal data:
6
+ *
7
+ * - **Translate** (raw): `getByKey(id)` — per-step value
8
+ * - **Accumulate** (progressive): `accumulate(fn, initial, keys?)` — running total up to a point
9
+ * - **Aggregate** (summary): `aggregate(fn, initial)` — reduce all entries
10
+ *
11
+ * Data is automatically collected during the single DFS traversal.
12
+ * The consumer chooses the operation at read time.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * class TokenRecorder extends KeyedRecorder<LLMCallEntry> {
17
+ * readonly id = 'tokens';
18
+ * onLLMCall(event) { this.store(event.runtimeStageId, { tokens: event.usage }); }
19
+ *
20
+ * // Translate: per-step
21
+ * getForStep(id: string) { return this.getByKey(id); }
22
+ *
23
+ * // Aggregate: total
24
+ * getTotalTokens() { return this.aggregate((sum, e) => sum + e.tokens, 0); }
25
+ *
26
+ * // Accumulate: progressive up to slider position
27
+ * getTokensUpTo(keys: Set<string>) { return this.accumulate((sum, e) => sum + e.tokens, 0, keys); }
28
+ * }
29
+ * ```
30
+ */
31
+ export declare abstract class KeyedRecorder<T> {
32
+ abstract readonly id: string;
33
+ private readonly data;
34
+ /** Store an entry keyed by runtimeStageId. */
35
+ protected store(runtimeStageId: string, entry: T): void;
36
+ /** O(1) lookup by runtimeStageId. */
37
+ getByKey(runtimeStageId: string): T | undefined;
38
+ /** All entries as a read-only Map (insertion-ordered). */
39
+ getMap(): ReadonlyMap<string, T>;
40
+ /** All entries as an array (insertion-ordered). */
41
+ values(): T[];
42
+ /** Number of entries stored. */
43
+ get size(): number;
44
+ /** Reduce ALL entries to a single value. For dashboards, totals, summaries. */
45
+ aggregate<R>(fn: (acc: R, entry: T, key: string) => R, initial: R): R;
46
+ /**
47
+ * Reduce entries, optionally filtered by a set of keys.
48
+ * For time-travel progressive view: pass the runtimeStageIds visible at the current slider position.
49
+ * Without keys, reduces all entries (same as aggregate).
50
+ */
51
+ accumulate<R>(fn: (acc: R, entry: T, key: string) => R, initial: R, keys?: ReadonlySet<string>): R;
52
+ /** Return entries whose keys are in the set, preserving insertion order. */
53
+ filterByKeys(keys: ReadonlySet<string>): T[];
54
+ /** Clear all stored data. Called by executor before each run(). */
55
+ clear(): void;
56
+ }
@@ -1,2 +1,3 @@
1
1
  export type { CompositeSnapshot } from './CompositeRecorder.js';
2
2
  export { CompositeRecorder } from './CompositeRecorder.js';
3
+ export { KeyedRecorder } from './KeyedRecorder.js';