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.
- package/AGENTS.md +17 -1
- package/CLAUDE.md +74 -3
- package/dist/advanced.js +12 -2
- package/dist/esm/advanced.js +4 -1
- package/dist/esm/lib/memory/StageContext.js +2 -1
- package/dist/esm/lib/memory/commitLogUtils.js +25 -0
- package/dist/esm/lib/memory/types.js +1 -1
- package/dist/esm/lib/recorder/KeyedRecorder.js +96 -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 +25 -0
- package/dist/lib/memory/StageContext.js +2 -1
- package/dist/lib/memory/commitLogUtils.js +31 -0
- package/dist/lib/memory/types.js +1 -1
- package/dist/lib/recorder/KeyedRecorder.js +100 -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 +35 -0
- package/dist/types/advanced.d.ts +4 -0
- package/dist/types/lib/memory/commitLogUtils.d.ts +13 -0
- package/dist/types/lib/memory/types.d.ts +2 -0
- package/dist/types/lib/recorder/KeyedRecorder.d.ts +56 -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 +23 -0
- package/package.json +6 -1
|
@@ -1,89 +1,96 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MetricRecorder —
|
|
2
|
+
* MetricRecorder — per-step timing and execution counts, keyed by runtimeStageId.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Each instance gets a unique auto-increment ID (`metrics-1`, `metrics-2`, ...),
|
|
7
|
-
* so multiple recorders with different configs coexist. Pass an explicit ID to
|
|
8
|
-
* override a specific instance (e.g., a framework-attached recorder).
|
|
4
|
+
* Stores per-invocation data during traversal. Aggregated views computed on read.
|
|
5
|
+
* Extends KeyedRecorder<StepMetrics> for O(1) lookup and standard operations.
|
|
9
6
|
*
|
|
10
7
|
* @example
|
|
11
8
|
* ```typescript
|
|
12
|
-
*
|
|
13
|
-
* executor.attachRecorder(
|
|
9
|
+
* const metric = new MetricRecorder();
|
|
10
|
+
* executor.attachRecorder(metric);
|
|
11
|
+
* await executor.run();
|
|
14
12
|
*
|
|
15
|
-
* //
|
|
16
|
-
*
|
|
17
|
-
* stageFilter: (name) => ['CallLLM', 'ParseResponse'].includes(name),
|
|
18
|
-
* }));
|
|
13
|
+
* // Per-step (time-travel):
|
|
14
|
+
* metric.getByKey('call-llm#5'); // { stageName, readCount, writeCount, duration }
|
|
19
15
|
*
|
|
20
|
-
* //
|
|
21
|
-
*
|
|
22
|
-
* stageFilter: (name) => name === 'CallLLM',
|
|
23
|
-
* }));
|
|
24
|
-
* executor.attachRecorder(new MetricRecorder({
|
|
25
|
-
* stageFilter: (name) => name !== 'CallLLM',
|
|
26
|
-
* }));
|
|
16
|
+
* // Aggregated (backward compat):
|
|
17
|
+
* metric.getMetrics(); // { totalDuration, totalReads, stageMetrics: Map<stageName, aggregated> }
|
|
27
18
|
*
|
|
28
|
-
* //
|
|
29
|
-
*
|
|
19
|
+
* // Progressive (slider):
|
|
20
|
+
* metric.accumulate((sum, m) => sum + m.duration, 0, visibleKeys);
|
|
30
21
|
* ```
|
|
31
22
|
*/
|
|
23
|
+
import { KeyedRecorder } from '../../recorder/KeyedRecorder.js';
|
|
32
24
|
import type { CommitEvent, PauseEvent, ReadEvent, Recorder, StageEvent, WriteEvent } from '../types.js';
|
|
33
|
-
|
|
25
|
+
/** Per-invocation metrics for a single execution step. */
|
|
26
|
+
export interface StepMetrics {
|
|
27
|
+
/** Human-readable stage name. */
|
|
34
28
|
stageName: string;
|
|
29
|
+
/** Number of scope reads during this invocation. */
|
|
35
30
|
readCount: number;
|
|
31
|
+
/** Number of scope writes during this invocation. */
|
|
36
32
|
writeCount: number;
|
|
33
|
+
/** Number of commits during this invocation. */
|
|
37
34
|
commitCount: number;
|
|
35
|
+
/** Number of pauses during this invocation. */
|
|
38
36
|
pauseCount: number;
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
/** Duration in ms for this invocation. */
|
|
38
|
+
duration: number;
|
|
41
39
|
}
|
|
40
|
+
/** Aggregated metrics across all invocations (backward compatible). */
|
|
42
41
|
export interface AggregatedMetrics {
|
|
43
42
|
totalDuration: number;
|
|
44
43
|
totalReads: number;
|
|
45
44
|
totalWrites: number;
|
|
46
45
|
totalCommits: number;
|
|
47
46
|
totalPauses: number;
|
|
47
|
+
/** Aggregated by stageName — sums across loop invocations. */
|
|
48
48
|
stageMetrics: Map<string, StageMetrics>;
|
|
49
49
|
}
|
|
50
|
-
/**
|
|
50
|
+
/** Aggregated per-stageName (backward compatible with pre-runtimeStageId API). */
|
|
51
|
+
export interface StageMetrics {
|
|
52
|
+
stageName: string;
|
|
53
|
+
readCount: number;
|
|
54
|
+
writeCount: number;
|
|
55
|
+
commitCount: number;
|
|
56
|
+
pauseCount: number;
|
|
57
|
+
totalDuration: number;
|
|
58
|
+
invocationCount: number;
|
|
59
|
+
}
|
|
60
|
+
/** Options for MetricRecorder. */
|
|
51
61
|
export interface MetricRecorderOptions {
|
|
52
62
|
/** Recorder ID. Defaults to auto-increment (`metrics-1`, `metrics-2`, ...). */
|
|
53
63
|
id?: string;
|
|
54
|
-
/**
|
|
55
|
-
* Filter which stages are recorded. Return `true` to record, `false` to skip.
|
|
56
|
-
* When omitted, all stages are recorded.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* // Only track stages that start with "Call"
|
|
61
|
-
* stageFilter: (name) => name.startsWith('Call')
|
|
62
|
-
* ```
|
|
63
|
-
*/
|
|
64
|
+
/** Filter which stages are recorded. Return `true` to record, `false` to skip. */
|
|
64
65
|
stageFilter?: (stageName: string) => boolean;
|
|
65
66
|
}
|
|
66
|
-
export declare class MetricRecorder implements Recorder {
|
|
67
|
+
export declare class MetricRecorder extends KeyedRecorder<StepMetrics> implements Recorder {
|
|
67
68
|
private static _counter;
|
|
68
69
|
readonly id: string;
|
|
69
|
-
private metrics;
|
|
70
70
|
private stageStartTimes;
|
|
71
|
+
private currentRuntimeStageId;
|
|
71
72
|
private stageFilter?;
|
|
72
73
|
constructor(idOrOptions?: string | MetricRecorderOptions);
|
|
73
74
|
private shouldRecord;
|
|
75
|
+
/** Get or create the StepMetrics for the current stage. */
|
|
76
|
+
private current;
|
|
77
|
+
onStageStart(event: StageEvent): void;
|
|
74
78
|
onRead(event: ReadEvent): void;
|
|
75
79
|
onWrite(event: WriteEvent): void;
|
|
76
80
|
onCommit(event: CommitEvent): void;
|
|
77
81
|
onPause(event: PauseEvent): void;
|
|
78
|
-
onStageStart(event: StageEvent): void;
|
|
79
82
|
onStageEnd(event: StageEvent): void;
|
|
83
|
+
/** Aggregated metrics — computes totals on the fly from per-step data (backward compatible). */
|
|
80
84
|
getMetrics(): AggregatedMetrics;
|
|
85
|
+
/** Get aggregated metrics for a specific stage name (backward compatible). */
|
|
81
86
|
getStageMetrics(stageName: string): StageMetrics | undefined;
|
|
87
|
+
/** Snapshot for serialization (backward compatible format). */
|
|
82
88
|
toSnapshot(): {
|
|
83
89
|
name: string;
|
|
84
90
|
data: unknown;
|
|
85
91
|
};
|
|
86
|
-
|
|
92
|
+
/** Clear all state — called by executor before each run(). */
|
|
87
93
|
clear(): void;
|
|
88
|
-
|
|
94
|
+
/** Alias for clear() (backward compat). */
|
|
95
|
+
reset(): void;
|
|
89
96
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type { CommitEvent, ErrorEvent, ReadEvent, Recorder, RecorderContext, StageEvent, WriteEvent, } from '../types.js';
|
|
2
2
|
export type { DebugEntry, DebugRecorderOptions, DebugVerbosity } from './DebugRecorder.js';
|
|
3
3
|
export { DebugRecorder } from './DebugRecorder.js';
|
|
4
|
-
export type { AggregatedMetrics, StageMetrics } from './MetricRecorder.js';
|
|
4
|
+
export type { AggregatedMetrics, StageMetrics, StepMetrics } from './MetricRecorder.js';
|
|
5
5
|
export { MetricRecorder } from './MetricRecorder.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* footprintjs/trace — Execution tracing, debugging, and backtracking utilities.
|
|
3
|
+
*
|
|
4
|
+
* Runtime stage IDs, commit log queries, and keyed recorder base class.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { parseRuntimeStageId, findLastWriter, KeyedRecorder } from 'footprintjs/trace';
|
|
9
|
+
*
|
|
10
|
+
* // Parse a runtimeStageId
|
|
11
|
+
* const { stageId, executionIndex } = parseRuntimeStageId('call-llm#5');
|
|
12
|
+
*
|
|
13
|
+
* // Backtrack: who wrote 'systemPrompt' before stage at idx 8?
|
|
14
|
+
* const writer = findLastWriter(commitLog, 'systemPrompt', 8);
|
|
15
|
+
*
|
|
16
|
+
* // Build a keyed recorder
|
|
17
|
+
* class MyRecorder extends KeyedRecorder<MyEntry> { ... }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export type { ExecutionCounter } from './lib/engine/runtimeStageId.js';
|
|
21
|
+
export { buildRuntimeStageId, createExecutionCounter, parseRuntimeStageId } from './lib/engine/runtimeStageId.js';
|
|
22
|
+
export { findCommit, findCommits, findLastWriter } from './lib/memory/commitLogUtils.js';
|
|
23
|
+
export { KeyedRecorder } from './lib/recorder/KeyedRecorder.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "footprintjs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Explainable backend flows — automatic causal traces, decision evidence, and MCP tool generation for AI agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Sanjay Krishna Anbalagan",
|
|
@@ -82,6 +82,11 @@
|
|
|
82
82
|
"types": "./dist/types/recorders.d.ts",
|
|
83
83
|
"import": "./dist/esm/recorders.js",
|
|
84
84
|
"require": "./dist/recorders.js"
|
|
85
|
+
},
|
|
86
|
+
"./trace": {
|
|
87
|
+
"types": "./dist/types/trace.d.ts",
|
|
88
|
+
"import": "./dist/esm/trace.js",
|
|
89
|
+
"require": "./dist/trace.js"
|
|
85
90
|
}
|
|
86
91
|
},
|
|
87
92
|
"lint-staged": {
|