footprintjs 4.7.0 → 4.9.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 +38 -14
- package/dist/esm/lib/engine/narrative/CombinedNarrativeRecorder.js +97 -90
- package/dist/esm/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/esm/lib/engine/traversal/FlowchartTraverser.js +8 -6
- package/dist/esm/lib/memory/StageContext.js +2 -1
- package/dist/esm/lib/memory/types.js +1 -1
- package/dist/esm/lib/recorder/KeyedRecorder.js +56 -7
- package/dist/esm/lib/recorder/SequenceRecorder.js +194 -0
- package/dist/esm/lib/recorder/index.js +2 -1
- package/dist/esm/lib/scope/recorders/MetricRecorder.js +85 -82
- package/dist/esm/lib/scope/recorders/index.js +1 -1
- package/dist/esm/trace.js +10 -5
- package/dist/lib/engine/narrative/CombinedNarrativeRecorder.js +97 -90
- package/dist/lib/engine/narrative/narrativeTypes.js +1 -1
- package/dist/lib/engine/traversal/FlowchartTraverser.js +8 -6
- package/dist/lib/memory/StageContext.js +2 -1
- package/dist/lib/memory/types.js +1 -1
- package/dist/lib/recorder/KeyedRecorder.js +56 -7
- package/dist/lib/recorder/SequenceRecorder.js +198 -0
- package/dist/lib/recorder/index.js +4 -2
- package/dist/lib/scope/recorders/MetricRecorder.js +85 -82
- package/dist/lib/scope/recorders/index.js +1 -1
- package/dist/trace.js +12 -6
- package/dist/types/lib/engine/narrative/CombinedNarrativeRecorder.d.ts +8 -18
- package/dist/types/lib/engine/narrative/narrativeTypes.d.ts +7 -0
- package/dist/types/lib/memory/types.d.ts +2 -0
- package/dist/types/lib/recorder/KeyedRecorder.d.ts +29 -6
- package/dist/types/lib/recorder/SequenceRecorder.d.ts +112 -0
- package/dist/types/lib/recorder/index.d.ts +1 -0
- package/dist/types/lib/scope/recorders/MetricRecorder.d.ts +47 -40
- package/dist/types/lib/scope/recorders/index.d.ts +1 -1
- package/dist/types/trace.d.ts +7 -3
- package/package.json +1 -1
package/CLAUDE.md
CHANGED
|
@@ -16,7 +16,7 @@ src/lib/
|
|
|
16
16
|
├── scope/ → Per-stage facades + recorders + providers
|
|
17
17
|
├── reactive/ → TypedScope<T> deep Proxy (typed property access, $-methods, cycle-safe)
|
|
18
18
|
├── decide/ → decide()/select() decision evidence capture (filter + function)
|
|
19
|
-
├── recorder/ → CompositeRecorder, KeyedRecorder<T
|
|
19
|
+
├── recorder/ → CompositeRecorder, KeyedRecorder<T>, SequenceRecorder<T>, composition primitives
|
|
20
20
|
├── pause/ → Pause/Resume (PauseSignal, FlowchartCheckpoint, PausableHandler)
|
|
21
21
|
├── engine/ → DFS traversal + narrative + 13 handlers
|
|
22
22
|
├── runner/ → High-level executor (FlowChartExecutor)
|
|
@@ -27,7 +27,7 @@ Dependency DAG: `memory <- scope <- reactive <- engine <- runner`, `schema <- en
|
|
|
27
27
|
|
|
28
28
|
Three entry points:
|
|
29
29
|
- `import { ... } from 'footprintjs'` — public API
|
|
30
|
-
- `import { ... } from 'footprintjs/trace'` — execution tracing: runtimeStageId, commitLog queries, KeyedRecorder
|
|
30
|
+
- `import { ... } from 'footprintjs/trace'` — execution tracing: runtimeStageId, commitLog queries, KeyedRecorder, SequenceRecorder
|
|
31
31
|
- `import { ... } from 'footprintjs/advanced'` — engine internals (also re-exports trace)
|
|
32
32
|
|
|
33
33
|
## Key API
|
|
@@ -266,25 +266,49 @@ const llmCommit = findCommit(commitLog, 'call-llm', 'adapterRawResponse');
|
|
|
266
266
|
| `findCommit(commitLog, stageId, key?)` | `CommitBundle \| undefined` | Find first commit by stageId |
|
|
267
267
|
| `findCommits(commitLog, stageId)` | `CommitBundle[]` | Find all commits by stageId |
|
|
268
268
|
| `findLastWriter(commitLog, key, beforeIdx?)` | `CommitBundle \| undefined` | Search backwards for who wrote a key |
|
|
269
|
-
| `KeyedRecorder<T>` | abstract class | Base for Map-based recorders |
|
|
269
|
+
| `KeyedRecorder<T>` | abstract class | Base for 1:1 Map-based recorders |
|
|
270
|
+
| `SequenceRecorder<T>` | abstract class | Base for 1:N ordered sequence recorders (has `getEntryRanges()` for O(1) time-travel) |
|
|
270
271
|
|
|
271
|
-
**
|
|
272
|
+
**Two recorder base classes** — choose based on data shape:
|
|
273
|
+
|
|
274
|
+
| Base Class | Relationship | Use When |
|
|
275
|
+
|------------|-------------|----------|
|
|
276
|
+
| `KeyedRecorder<T>` | 1:1 Map | Each step produces one record (MetricRecorder, TokenRecorder) |
|
|
277
|
+
| `SequenceRecorder<T>` | 1:N sequence + Map | Multiple records per step, ordering matters (CombinedNarrativeRecorder) |
|
|
272
278
|
|
|
273
279
|
```typescript
|
|
274
|
-
import { KeyedRecorder } from 'footprintjs/trace';
|
|
280
|
+
import { KeyedRecorder, SequenceRecorder } from 'footprintjs/trace';
|
|
275
281
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
282
|
+
// KeyedRecorder: one entry per step
|
|
283
|
+
class TokenRecorder extends KeyedRecorder<TokenEntry> {
|
|
284
|
+
readonly id = 'tokens';
|
|
285
|
+
onLLMCall(event) { this.store(event.runtimeStageId, { tokens: event.usage }); }
|
|
286
|
+
}
|
|
287
|
+
recorder.getByKey('call-llm#5'); // Translate: per-step value
|
|
288
|
+
recorder.aggregate((sum, e) => sum + e.tokens, 0); // Aggregate: grand total
|
|
289
|
+
recorder.accumulate((sum, e) => sum + e.tokens, 0, visibleKeys); // Accumulate: up to slider
|
|
290
|
+
|
|
291
|
+
// SequenceRecorder: multiple entries per step, ordered
|
|
292
|
+
class AuditRecorder extends SequenceRecorder<AuditEntry> {
|
|
293
|
+
readonly id = 'audit';
|
|
294
|
+
onRead(event) { this.emit({ runtimeStageId: event.runtimeStageId, type: 'read', key: event.key }); }
|
|
295
|
+
onDecision(event) { this.emit({ runtimeStageId: event.traversalContext?.runtimeStageId, ... }); }
|
|
281
296
|
}
|
|
282
|
-
recorder.
|
|
283
|
-
recorder.
|
|
284
|
-
recorder.
|
|
285
|
-
recorder.
|
|
297
|
+
recorder.getEntriesForStep('call-llm#5'); // Translate: per-step entries
|
|
298
|
+
recorder.aggregate((count, _) => count + 1, 0); // Aggregate: grand total
|
|
299
|
+
recorder.getEntriesUpTo(visibleKeys); // Progressive: up to slider
|
|
300
|
+
recorder.getEntryRanges(); // Range index: O(1) slider sync
|
|
286
301
|
```
|
|
287
302
|
|
|
303
|
+
**`getEntryRanges()`** returns a precomputed `Map<runtimeStageId, {firstIdx, endIdx}>` maintained during `emit()`. Use for O(1) per-step range lookups during time-travel scrubbing. Same shape as `buildEntryRangeIndex()` in `footprint-explainable-ui`.
|
|
304
|
+
|
|
305
|
+
**`CombinedNarrativeEntry.direction`** — subflow entries carry `direction: 'entry' | 'exit'`. Use for programmatic subflow boundary detection instead of text scanning (which breaks with custom `NarrativeRenderer`).
|
|
306
|
+
|
|
307
|
+
**`footprint-explainable-ui` narrative utilities** — for consumers building custom shells without `ExplainableShell`:
|
|
308
|
+
- `buildEntryRangeIndex(entries)` — build range index from flat array (when no recorder access)
|
|
309
|
+
- `computeRevealedEntryCount(entries, snapshots, idx, rangeIndex?)` — slider position → entry count
|
|
310
|
+
- `extractSubflowNarrative(entries, subflowId)` — three-tier subflow entry extraction
|
|
311
|
+
|
|
288
312
|
**How runtimeStageId is generated:** A counter starts at 0 and increments by 1 for each stage execution across the entire run, including subflow stages. Subflow child traversers share the parent counter so indices are globally unique. Stages inside subflows have stageIds already prefixed by the builder (e.g., `sf-tools/execute-tool-calls`), so `buildRuntimeStageId` just appends `#index`.
|
|
289
313
|
|
|
290
314
|
## Anti-Patterns
|