agentfootprint 2.14.5 → 3.1.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/README.md +1 -1
- package/dist/cache/CacheDecisionSubflow.js +13 -16
- package/dist/cache/CacheDecisionSubflow.js.map +1 -1
- package/dist/cache/CacheGateDecider.js +18 -3
- package/dist/cache/CacheGateDecider.js.map +1 -1
- package/dist/cache/cacheRecorder.js +12 -3
- package/dist/cache/cacheRecorder.js.map +1 -1
- package/dist/conventions.js +155 -4
- package/dist/conventions.js.map +1 -1
- package/dist/core/Agent.js +115 -32
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/LLMCall.js +213 -41
- package/dist/core/LLMCall.js.map +1 -1
- package/dist/core/RunnerBase.js +187 -0
- package/dist/core/RunnerBase.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +127 -48
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildAgentMessageApiChart.js +201 -0
- package/dist/core/agent/buildAgentMessageApiChart.js.map +1 -0
- package/dist/core/agent/buildCacheSubflow.js +62 -0
- package/dist/core/agent/buildCacheSubflow.js.map +1 -0
- package/dist/core/agent/buildDynamicAgentChart.js +364 -0
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -0
- package/dist/core/agent/buildMessageApiChart.js +154 -0
- package/dist/core/agent/buildMessageApiChart.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +11 -0
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/reliabilityExecution.js +64 -9
- package/dist/core/agent/stages/reliabilityExecution.js.map +1 -1
- package/dist/core/humanizeLLMError.js +66 -0
- package/dist/core/humanizeLLMError.js.map +1 -0
- package/dist/core/runner.js +4 -3
- package/dist/core/runner.js.map +1 -1
- package/dist/core/slots/buildMessagesSlot.js +2 -2
- package/dist/core/slots/buildMessagesSlot.js.map +1 -1
- package/dist/core/slots/buildSystemPromptSlot.js +1 -1
- package/dist/core/slots/buildSystemPromptSlot.js.map +1 -1
- package/dist/core/slots/buildThinkingSubflow.js +1 -1
- package/dist/core/slots/buildThinkingSubflow.js.map +1 -1
- package/dist/core/slots/buildToolsSlot.js +3 -1
- package/dist/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/core/translator.js +32 -0
- package/dist/core/translator.js.map +1 -0
- package/dist/core-flow/Conditional.js +72 -10
- package/dist/core-flow/Conditional.js.map +1 -1
- package/dist/core-flow/Loop.js +59 -16
- package/dist/core-flow/Loop.js.map +1 -1
- package/dist/core-flow/Parallel.js +239 -92
- package/dist/core-flow/Parallel.js.map +1 -1
- package/dist/core-flow/Sequence.js +50 -8
- package/dist/core-flow/Sequence.js.map +1 -1
- package/dist/esm/cache/CacheDecisionSubflow.js +11 -15
- package/dist/esm/cache/CacheDecisionSubflow.js.map +1 -1
- package/dist/esm/cache/CacheGateDecider.js +18 -3
- package/dist/esm/cache/CacheGateDecider.js.map +1 -1
- package/dist/esm/cache/cacheRecorder.js +12 -3
- package/dist/esm/cache/cacheRecorder.js.map +1 -1
- package/dist/esm/conventions.js +151 -3
- package/dist/esm/conventions.js.map +1 -1
- package/dist/esm/core/Agent.js +116 -33
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/LLMCall.js +213 -41
- package/dist/esm/core/LLMCall.js.map +1 -1
- package/dist/esm/core/RunnerBase.js +187 -0
- package/dist/esm/core/RunnerBase.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.js +128 -49
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildAgentMessageApiChart.js +197 -0
- package/dist/esm/core/agent/buildAgentMessageApiChart.js.map +1 -0
- package/dist/esm/core/agent/buildCacheSubflow.js +58 -0
- package/dist/esm/core/agent/buildCacheSubflow.js.map +1 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js +360 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -0
- package/dist/esm/core/agent/buildMessageApiChart.js +150 -0
- package/dist/esm/core/agent/buildMessageApiChart.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.js +11 -0
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/reliabilityExecution.js +64 -9
- package/dist/esm/core/agent/stages/reliabilityExecution.js.map +1 -1
- package/dist/esm/core/humanizeLLMError.js +61 -0
- package/dist/esm/core/humanizeLLMError.js.map +1 -0
- package/dist/esm/core/runner.js +4 -3
- package/dist/esm/core/runner.js.map +1 -1
- package/dist/esm/core/slots/buildMessagesSlot.js +2 -2
- package/dist/esm/core/slots/buildMessagesSlot.js.map +1 -1
- package/dist/esm/core/slots/buildSystemPromptSlot.js +1 -1
- package/dist/esm/core/slots/buildSystemPromptSlot.js.map +1 -1
- package/dist/esm/core/slots/buildThinkingSubflow.js +1 -1
- package/dist/esm/core/slots/buildThinkingSubflow.js.map +1 -1
- package/dist/esm/core/slots/buildToolsSlot.js +3 -1
- package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/esm/core/translator.js +31 -0
- package/dist/esm/core/translator.js.map +1 -0
- package/dist/esm/core-flow/Conditional.js +72 -10
- package/dist/esm/core-flow/Conditional.js.map +1 -1
- package/dist/esm/core-flow/Loop.js +59 -16
- package/dist/esm/core-flow/Loop.js.map +1 -1
- package/dist/esm/core-flow/Parallel.js +240 -93
- package/dist/esm/core-flow/Parallel.js.map +1 -1
- package/dist/esm/core-flow/Sequence.js +50 -8
- package/dist/esm/core-flow/Sequence.js.map +1 -1
- package/dist/esm/events/registry.js +10 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/index.js +22 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js +16 -9
- package/dist/esm/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/esm/memory/causal/snapshotPipeline.js +6 -2
- package/dist/esm/memory/causal/snapshotPipeline.js.map +1 -1
- package/dist/esm/memory/pipeline/auto.js +2 -2
- package/dist/esm/memory/pipeline/auto.js.map +1 -1
- package/dist/esm/memory/pipeline/default.js +4 -2
- package/dist/esm/memory/pipeline/default.js.map +1 -1
- package/dist/esm/memory/pipeline/ephemeral.js +3 -1
- package/dist/esm/memory/pipeline/ephemeral.js.map +1 -1
- package/dist/esm/memory/pipeline/fact.js +4 -2
- package/dist/esm/memory/pipeline/fact.js.map +1 -1
- package/dist/esm/memory/pipeline/narrative.js +4 -2
- package/dist/esm/memory/pipeline/narrative.js.map +1 -1
- package/dist/esm/memory/pipeline/semantic.js +2 -2
- package/dist/esm/memory/pipeline/semantic.js.map +1 -1
- package/dist/esm/observe.js +1 -1
- package/dist/esm/observe.js.map +1 -1
- package/dist/esm/patterns/MapReduce.js +5 -5
- package/dist/esm/patterns/MapReduce.js.map +1 -1
- package/dist/esm/patterns/Swarm.js +1 -1
- package/dist/esm/patterns/Swarm.js.map +1 -1
- package/dist/esm/recorders/core/ContextEvaluatedRecorder.js +31 -0
- package/dist/esm/recorders/core/ContextEvaluatedRecorder.js.map +1 -0
- package/dist/esm/recorders/core/ContextRecorder.js +12 -14
- package/dist/esm/recorders/core/ContextRecorder.js.map +1 -1
- package/dist/esm/recorders/core/ErrorBridge.js +59 -0
- package/dist/esm/recorders/core/ErrorBridge.js.map +1 -0
- package/dist/esm/recorders/core/ReliabilityRecorder.js +29 -0
- package/dist/esm/recorders/core/ReliabilityRecorder.js.map +1 -0
- package/dist/esm/recorders/observability/BoundaryRecorder.js +338 -36
- package/dist/esm/recorders/observability/BoundaryRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/FlowchartRecorder.js +10 -0
- package/dist/esm/recorders/observability/FlowchartRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/LiveStateRecorder.js +120 -21
- package/dist/esm/recorders/observability/LiveStateRecorder.js.map +1 -1
- package/dist/esm/recorders/observability/RunStepRecorder.js +652 -0
- package/dist/esm/recorders/observability/RunStepRecorder.js.map +1 -0
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js +1 -0
- package/dist/esm/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/esm/recorders/observability/internal/ActorArrowClassifier.js +34 -0
- package/dist/esm/recorders/observability/internal/ActorArrowClassifier.js.map +1 -0
- package/dist/esm/recorders/observability/internal/CandidateAnswerBuffer.js +32 -0
- package/dist/esm/recorders/observability/internal/CandidateAnswerBuffer.js.map +1 -0
- package/dist/esm/recorders/observability/internal/ForkTracker.js +84 -0
- package/dist/esm/recorders/observability/internal/ForkTracker.js.map +1 -0
- package/dist/esm/recorders/observability/internal/RootInferrer.js +114 -0
- package/dist/esm/recorders/observability/internal/RootInferrer.js.map +1 -0
- package/dist/esm/recorders/observability/internal/SequenceSiblingTracker.js +31 -0
- package/dist/esm/recorders/observability/internal/SequenceSiblingTracker.js.map +1 -0
- package/dist/esm/recorders/observability/observeRunId.js +21 -0
- package/dist/esm/recorders/observability/observeRunId.js.map +1 -0
- package/dist/esm/reliability/buildReliabilityGateChart.js +11 -5
- package/dist/esm/reliability/buildReliabilityGateChart.js.map +1 -1
- package/dist/events/registry.js +10 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/index.js +30 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js +16 -9
- package/dist/lib/injection-engine/buildInjectionEngineSubflow.js.map +1 -1
- package/dist/memory/causal/snapshotPipeline.js +6 -2
- package/dist/memory/causal/snapshotPipeline.js.map +1 -1
- package/dist/memory/pipeline/auto.js +2 -2
- package/dist/memory/pipeline/auto.js.map +1 -1
- package/dist/memory/pipeline/default.js +4 -2
- package/dist/memory/pipeline/default.js.map +1 -1
- package/dist/memory/pipeline/ephemeral.js +3 -1
- package/dist/memory/pipeline/ephemeral.js.map +1 -1
- package/dist/memory/pipeline/fact.js +4 -2
- package/dist/memory/pipeline/fact.js.map +1 -1
- package/dist/memory/pipeline/narrative.js +4 -2
- package/dist/memory/pipeline/narrative.js.map +1 -1
- package/dist/memory/pipeline/semantic.js +2 -2
- package/dist/memory/pipeline/semantic.js.map +1 -1
- package/dist/observe.js +1 -1
- package/dist/observe.js.map +1 -1
- package/dist/patterns/MapReduce.js +5 -5
- package/dist/patterns/MapReduce.js.map +1 -1
- package/dist/patterns/Swarm.js +1 -1
- package/dist/patterns/Swarm.js.map +1 -1
- package/dist/recorders/core/ContextEvaluatedRecorder.js +35 -0
- package/dist/recorders/core/ContextEvaluatedRecorder.js.map +1 -0
- package/dist/recorders/core/ContextRecorder.js +11 -13
- package/dist/recorders/core/ContextRecorder.js.map +1 -1
- package/dist/recorders/core/ErrorBridge.js +64 -0
- package/dist/recorders/core/ErrorBridge.js.map +1 -0
- package/dist/recorders/core/ReliabilityRecorder.js +33 -0
- package/dist/recorders/core/ReliabilityRecorder.js.map +1 -0
- package/dist/recorders/observability/BoundaryRecorder.js +337 -35
- package/dist/recorders/observability/BoundaryRecorder.js.map +1 -1
- package/dist/recorders/observability/FlowchartRecorder.js +10 -0
- package/dist/recorders/observability/FlowchartRecorder.js.map +1 -1
- package/dist/recorders/observability/LiveStateRecorder.js +119 -20
- package/dist/recorders/observability/LiveStateRecorder.js.map +1 -1
- package/dist/recorders/observability/RunStepRecorder.js +658 -0
- package/dist/recorders/observability/RunStepRecorder.js.map +1 -0
- package/dist/recorders/observability/commentary/commentaryTemplates.js +1 -0
- package/dist/recorders/observability/commentary/commentaryTemplates.js.map +1 -1
- package/dist/recorders/observability/internal/ActorArrowClassifier.js +38 -0
- package/dist/recorders/observability/internal/ActorArrowClassifier.js.map +1 -0
- package/dist/recorders/observability/internal/CandidateAnswerBuffer.js +36 -0
- package/dist/recorders/observability/internal/CandidateAnswerBuffer.js.map +1 -0
- package/dist/recorders/observability/internal/ForkTracker.js +88 -0
- package/dist/recorders/observability/internal/ForkTracker.js.map +1 -0
- package/dist/recorders/observability/internal/RootInferrer.js +118 -0
- package/dist/recorders/observability/internal/RootInferrer.js.map +1 -0
- package/dist/recorders/observability/internal/SequenceSiblingTracker.js +35 -0
- package/dist/recorders/observability/internal/SequenceSiblingTracker.js.map +1 -0
- package/dist/recorders/observability/observeRunId.js +25 -0
- package/dist/recorders/observability/observeRunId.js.map +1 -0
- package/dist/reliability/buildReliabilityGateChart.js +11 -5
- package/dist/reliability/buildReliabilityGateChart.js.map +1 -1
- package/dist/types/cache/CacheDecisionSubflow.d.ts +7 -10
- package/dist/types/cache/CacheDecisionSubflow.d.ts.map +1 -1
- package/dist/types/cache/CacheGateDecider.d.ts +16 -2
- package/dist/types/cache/CacheGateDecider.d.ts.map +1 -1
- package/dist/types/cache/cacheRecorder.d.ts.map +1 -1
- package/dist/types/conventions.d.ts +101 -1
- package/dist/types/conventions.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +28 -18
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/LLMCall.d.ts +73 -11
- package/dist/types/core/LLMCall.d.ts.map +1 -1
- package/dist/types/core/RunnerBase.d.ts +136 -4
- package/dist/types/core/RunnerBase.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +38 -19
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentMessageApiChart.d.ts +41 -0
- package/dist/types/core/agent/buildAgentMessageApiChart.d.ts.map +1 -0
- package/dist/types/core/agent/buildCacheSubflow.d.ts +36 -0
- package/dist/types/core/agent/buildCacheSubflow.d.ts.map +1 -0
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts +57 -0
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -0
- package/dist/types/core/agent/buildMessageApiChart.d.ts +48 -0
- package/dist/types/core/agent/buildMessageApiChart.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/reliabilityExecution.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +96 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/humanizeLLMError.d.ts +24 -0
- package/dist/types/core/humanizeLLMError.d.ts.map +1 -0
- package/dist/types/core/runner.d.ts +51 -5
- package/dist/types/core/runner.d.ts.map +1 -1
- package/dist/types/core/slots/buildMessagesSlot.d.ts.map +1 -1
- package/dist/types/core/slots/buildSystemPromptSlot.d.ts.map +1 -1
- package/dist/types/core/slots/buildThinkingSubflow.d.ts.map +1 -1
- package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
- package/dist/types/core/translator.d.ts +95 -0
- package/dist/types/core/translator.d.ts.map +1 -0
- package/dist/types/core-flow/Conditional.d.ts +48 -4
- package/dist/types/core-flow/Conditional.d.ts.map +1 -1
- package/dist/types/core-flow/Loop.d.ts +42 -3
- package/dist/types/core-flow/Loop.d.ts.map +1 -1
- package/dist/types/core-flow/Parallel.d.ts +99 -4
- package/dist/types/core-flow/Parallel.d.ts.map +1 -1
- package/dist/types/core-flow/Sequence.d.ts +49 -3
- package/dist/types/core-flow/Sequence.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +99 -1
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +11 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/index.d.ts +8 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/buildInjectionEngineSubflow.d.ts.map +1 -1
- package/dist/types/memory/causal/snapshotPipeline.d.ts.map +1 -1
- package/dist/types/memory/pipeline/auto.d.ts.map +1 -1
- package/dist/types/memory/pipeline/default.d.ts.map +1 -1
- package/dist/types/memory/pipeline/ephemeral.d.ts.map +1 -1
- package/dist/types/memory/pipeline/fact.d.ts.map +1 -1
- package/dist/types/memory/pipeline/narrative.d.ts.map +1 -1
- package/dist/types/memory/pipeline/semantic.d.ts.map +1 -1
- package/dist/types/observe.d.ts +2 -2
- package/dist/types/observe.d.ts.map +1 -1
- package/dist/types/recorders/core/ContextEvaluatedRecorder.d.ts +24 -0
- package/dist/types/recorders/core/ContextEvaluatedRecorder.d.ts.map +1 -0
- package/dist/types/recorders/core/ContextRecorder.d.ts +0 -2
- package/dist/types/recorders/core/ContextRecorder.d.ts.map +1 -1
- package/dist/types/recorders/core/ErrorBridge.d.ts +39 -0
- package/dist/types/recorders/core/ErrorBridge.d.ts.map +1 -0
- package/dist/types/recorders/core/ReliabilityRecorder.d.ts +25 -0
- package/dist/types/recorders/core/ReliabilityRecorder.d.ts.map +1 -0
- package/dist/types/recorders/observability/BoundaryRecorder.d.ts +167 -6
- package/dist/types/recorders/observability/BoundaryRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/FlowchartRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/LiveStateRecorder.d.ts +42 -6
- package/dist/types/recorders/observability/LiveStateRecorder.d.ts.map +1 -1
- package/dist/types/recorders/observability/RunStepRecorder.d.ts +232 -0
- package/dist/types/recorders/observability/RunStepRecorder.d.ts.map +1 -0
- package/dist/types/recorders/observability/commentary/commentaryTemplates.d.ts.map +1 -1
- package/dist/types/recorders/observability/internal/ActorArrowClassifier.d.ts +26 -0
- package/dist/types/recorders/observability/internal/ActorArrowClassifier.d.ts.map +1 -0
- package/dist/types/recorders/observability/internal/CandidateAnswerBuffer.d.ts +29 -0
- package/dist/types/recorders/observability/internal/CandidateAnswerBuffer.d.ts.map +1 -0
- package/dist/types/recorders/observability/internal/ForkTracker.d.ts +61 -0
- package/dist/types/recorders/observability/internal/ForkTracker.d.ts.map +1 -0
- package/dist/types/recorders/observability/internal/RootInferrer.d.ts +52 -0
- package/dist/types/recorders/observability/internal/RootInferrer.d.ts.map +1 -0
- package/dist/types/recorders/observability/internal/SequenceSiblingTracker.d.ts +25 -0
- package/dist/types/recorders/observability/internal/SequenceSiblingTracker.d.ts.map +1 -0
- package/dist/types/recorders/observability/observeRunId.d.ts +37 -0
- package/dist/types/recorders/observability/observeRunId.d.ts.map +1 -0
- package/dist/types/reliability/buildReliabilityGateChart.d.ts.map +1 -1
- package/package.json +6 -5
- package/dist/core/agent/stages/iterationStart.js +0 -24
- package/dist/core/agent/stages/iterationStart.js.map +0 -1
- package/dist/esm/core/agent/stages/iterationStart.js +0 -20
- package/dist/esm/core/agent/stages/iterationStart.js.map +0 -1
- package/dist/types/core/agent/stages/iterationStart.d.ts +0 -16
- package/dist/types/core/agent/stages/iterationStart.d.ts.map +0 -1
|
@@ -80,6 +80,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
80
80
|
exports.BoundaryRecorder = exports.boundaryRecorder = void 0;
|
|
81
81
|
const trace_1 = require("footprintjs/trace");
|
|
82
82
|
const conventions_js_1 = require("../../conventions.js");
|
|
83
|
+
const observeRunId_js_1 = require("./observeRunId.js");
|
|
83
84
|
/** Closed set of routing/wrapper subflow IDs that are pure plumbing.
|
|
84
85
|
* Slot subflows (`sf-system-prompt` / `sf-messages` / `sf-tools`) are
|
|
85
86
|
* NOT in this set — they're real context-engineering moments.
|
|
@@ -93,15 +94,21 @@ const conventions_js_1 = require("../../conventions.js");
|
|
|
93
94
|
const AGENT_INTERNAL_LOCAL_IDS = new Set([
|
|
94
95
|
// Subflow ids (`sf-*`)
|
|
95
96
|
conventions_js_1.SUBFLOW_IDS.INJECTION_ENGINE, // collects activeInjections; pure plumbing
|
|
97
|
+
conventions_js_1.SUBFLOW_IDS.LLM_CALL, // LLMCall's inner invocation wrapper — the meaningful step is the call-llm stage INSIDE; the wrapper itself is a chart-shape container
|
|
96
98
|
conventions_js_1.SUBFLOW_IDS.ROUTE,
|
|
97
99
|
conventions_js_1.SUBFLOW_IDS.TOOL_CALLS,
|
|
98
100
|
conventions_js_1.SUBFLOW_IDS.FINAL,
|
|
99
101
|
conventions_js_1.SUBFLOW_IDS.MERGE,
|
|
102
|
+
conventions_js_1.SUBFLOW_IDS.CACHE, // v2.14 — per-turn cache decision wrapper; pure plumbing
|
|
100
103
|
conventions_js_1.SUBFLOW_IDS.CACHE_DECISION, // v2.6 — emits cacheMarkers; not a user step
|
|
101
104
|
conventions_js_1.SUBFLOW_IDS.THINKING, // v2.14 — normalize result lands on parent LLM step
|
|
102
105
|
// Decider stage ids (the same set is used to filter `decision.branch`
|
|
103
106
|
// events whose deciding stage is plumbing rather than user-facing).
|
|
104
107
|
conventions_js_1.STAGE_IDS.CACHE_GATE, // v2.6 — apply-markers / no-markers routing; plumbing
|
|
108
|
+
// LLMCall outer wrapper stage + post-invocation marker — pure chart
|
|
109
|
+
// shape, not user-meaningful steps.
|
|
110
|
+
conventions_js_1.STAGE_IDS.CLIENT,
|
|
111
|
+
conventions_js_1.STAGE_IDS.EXTRACT_FINAL,
|
|
105
112
|
]);
|
|
106
113
|
// Constructed as a set on a separate line so we can extend with the
|
|
107
114
|
// thinking-handler inner-subflow ids below without the literal set
|
|
@@ -127,6 +134,53 @@ function isAgentInternalId(localId) {
|
|
|
127
134
|
}
|
|
128
135
|
return false;
|
|
129
136
|
}
|
|
137
|
+
function toBoundaryLabel(e) {
|
|
138
|
+
if (e.type === 'subflow.entry') {
|
|
139
|
+
return {
|
|
140
|
+
type: 'subflow.entry',
|
|
141
|
+
runtimeStageId: e.runtimeStageId,
|
|
142
|
+
subflowPath: e.subflowPath,
|
|
143
|
+
depth: e.depth,
|
|
144
|
+
ts: e.ts,
|
|
145
|
+
subflowId: e.subflowId,
|
|
146
|
+
localSubflowId: e.localSubflowId,
|
|
147
|
+
subflowName: e.subflowName,
|
|
148
|
+
...(e.description !== undefined ? { description: e.description } : {}),
|
|
149
|
+
...(e.primitiveKind !== undefined ? { primitiveKind: e.primitiveKind } : {}),
|
|
150
|
+
...(e.slotKind !== undefined ? { slotKind: e.slotKind } : {}),
|
|
151
|
+
isAgentInternal: e.isAgentInternal,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
type: 'run.entry',
|
|
156
|
+
runtimeStageId: e.runtimeStageId,
|
|
157
|
+
subflowPath: e.subflowPath,
|
|
158
|
+
depth: e.depth,
|
|
159
|
+
ts: e.ts,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** Build a BoundaryRangeLabel for the open side of a composition pair. */
|
|
163
|
+
function toCompositionBoundaryLabel(e) {
|
|
164
|
+
return {
|
|
165
|
+
type: 'composition.start',
|
|
166
|
+
runtimeStageId: e.runtimeStageId,
|
|
167
|
+
subflowPath: e.subflowPath,
|
|
168
|
+
depth: e.depth,
|
|
169
|
+
ts: e.ts,
|
|
170
|
+
compositionKind: e.kind,
|
|
171
|
+
compositionName: e.name,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
/** Clamp `getCommitCount()` returns to a safe non-negative integer.
|
|
175
|
+
* Defensive against malformed injections returning NaN/Infinity/negatives
|
|
176
|
+
* (security panel review YELLOW #2). */
|
|
177
|
+
function sanitizeCommitCount(n) {
|
|
178
|
+
if (!Number.isFinite(n))
|
|
179
|
+
return 0;
|
|
180
|
+
if (n < 0)
|
|
181
|
+
return 0;
|
|
182
|
+
return n;
|
|
183
|
+
}
|
|
130
184
|
let _counter = 0;
|
|
131
185
|
/** Factory — matches the `inOutRecorder()` / `topologyRecorder()` style. */
|
|
132
186
|
function boundaryRecorder(options = {}) {
|
|
@@ -138,12 +192,35 @@ exports.boundaryRecorder = boundaryRecorder;
|
|
|
138
192
|
* attach to the executor's FlowRecorder channel; exposes `subscribe()`
|
|
139
193
|
* to wire to the agentfootprint typed-event dispatcher.
|
|
140
194
|
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
195
|
+
* v5: composes a `SequenceStore<DomainEvent>` (storage) instead of
|
|
196
|
+
* extending the deprecated `SequenceRecorder<T>` base. Time-travel
|
|
197
|
+
* utilities (`getEntryRanges`, `accumulate`) are accessed through the
|
|
198
|
+
* store via the public read API on this class.
|
|
144
199
|
*/
|
|
145
|
-
class BoundaryRecorder
|
|
200
|
+
class BoundaryRecorder {
|
|
146
201
|
id;
|
|
202
|
+
/** Composition: storage shelf. */
|
|
203
|
+
store = new trace_1.SequenceStore();
|
|
204
|
+
/**
|
|
205
|
+
* Phase 5 Layer 2 — interval index over commit indices, populated
|
|
206
|
+
* live as boundary entry/exit pairs fire. Consumers (Lens) read
|
|
207
|
+
* `enclosing(commitIdx)` for breadcrumbs and `overlapping(slice)`
|
|
208
|
+
* for time-range queries. Empty when `getCommitCount` is not
|
|
209
|
+
* injected. See `docs/design/boundary-commit-ranges.md`.
|
|
210
|
+
*/
|
|
211
|
+
boundaryIndex = new trace_1.CommitRangeIndex();
|
|
212
|
+
/** Open-range tokens keyed by `runtimeStageId` so the matching exit
|
|
213
|
+
* can close the correct range. Pure side-table; cleared on runId
|
|
214
|
+
* reset. Not exposed externally. */
|
|
215
|
+
openTokens = new Map();
|
|
216
|
+
/** Live commit-count accessor injected by the runner. Sanitized
|
|
217
|
+
* (NaN/Infinity/negative → 0) before use. */
|
|
218
|
+
getCommitCount;
|
|
219
|
+
/** True when `getCommitCount` was explicitly injected. In LEGACY
|
|
220
|
+
* MODE (false), `boundaryIndex` is intentionally NOT populated —
|
|
221
|
+
* zero-width [0,0] ranges would mislead consumers querying the
|
|
222
|
+
* index. Multi-panel review flagged this footgun. */
|
|
223
|
+
hasCommitTracking;
|
|
147
224
|
/**
|
|
148
225
|
* Tracks whether the most recent `llm.end` had toolCalls. Used to
|
|
149
226
|
* classify the NEXT `llm.start` as `'tool→llm'` (vs `'user→llm'` if
|
|
@@ -151,50 +228,184 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
151
228
|
* `llm.start` event after the classification is applied.
|
|
152
229
|
*/
|
|
153
230
|
prevLLMEndHadTools = false;
|
|
231
|
+
/**
|
|
232
|
+
* Run-boundary observer — fires resetForNewRun() when
|
|
233
|
+
* traversalContext.runId changes between events AND no boundary is
|
|
234
|
+
* currently open. The "no open boundary" gate distinguishes:
|
|
235
|
+
*
|
|
236
|
+
* - **Legitimate new run** — consumer reuses one recorder across
|
|
237
|
+
* sequential `executor.run()` calls. All prior boundaries closed
|
|
238
|
+
* before the second run began; openTokens is empty when the new
|
|
239
|
+
* runId arrives → safe to wipe state so the second run doesn't
|
|
240
|
+
* alias with the first.
|
|
241
|
+
* - **Composition sub-run** — primitives like `LLMCall`, `Sequence`,
|
|
242
|
+
* and `Parallel` internally spawn their own `FlowChartExecutor`
|
|
243
|
+
* instances. Each sub-executor mints a NEW runId. When that
|
|
244
|
+
* sub-executor fires events on the SHARED recorder, the recorder
|
|
245
|
+
* is still inside the parent run — `openTokens` is non-empty.
|
|
246
|
+
* Resetting here would wipe the parent's boundary index mid-run
|
|
247
|
+
* (the bug Layer 4 surfaced in agentfootprint-lens fanout).
|
|
248
|
+
*
|
|
249
|
+
* The `openTokens.size === 0` check is the cleanest semantic signal:
|
|
250
|
+
* if nothing is in-flight, a runId change means "the consumer started
|
|
251
|
+
* fresh"; if something is open, the new runId is from a sub-executor
|
|
252
|
+
* nested inside the still-ongoing parent.
|
|
253
|
+
*/
|
|
254
|
+
runIdGuard = (0, observeRunId_js_1.createRunIdObserver)(() => {
|
|
255
|
+
if (this.openTokens.size > 0) {
|
|
256
|
+
// Inside an active run — new runId is from a composition sub-
|
|
257
|
+
// executor (LLMCall / Sequence / Parallel). Do NOT reset.
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
this.store.clear();
|
|
261
|
+
this.boundaryIndex.clear();
|
|
262
|
+
this.openTokens.clear();
|
|
263
|
+
this.prevLLMEndHadTools = false;
|
|
264
|
+
});
|
|
154
265
|
constructor(options = {}) {
|
|
155
|
-
super();
|
|
156
266
|
this.id = options.id ?? `boundary-${++_counter}`;
|
|
267
|
+
this.hasCommitTracking = options.getCommitCount !== undefined;
|
|
268
|
+
const raw = options.getCommitCount;
|
|
269
|
+
this.getCommitCount = raw === undefined ? () => 0 : () => sanitizeCommitCount(raw());
|
|
157
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Reset all transient state.
|
|
273
|
+
*
|
|
274
|
+
* **Composition-safe gate (Phase 5 Layer 4):** if `openTokens.size > 0`
|
|
275
|
+
* the call is a no-op. Rationale: `FlowChartExecutor.run()` calls
|
|
276
|
+
* `r.clear?.()` on every attached recorder during its pre-run loop.
|
|
277
|
+
* When agentfootprint composition primitives (LLMCall, Sequence,
|
|
278
|
+
* Parallel, etc.) propagate the parent's recorders to nested
|
|
279
|
+
* sub-executors, EACH sub-executor's pre-run clear loop calls
|
|
280
|
+
* `clear()` on the SHARED parent recorder mid-run — wiping live
|
|
281
|
+
* parent state. The `openTokens.size > 0` check distinguishes:
|
|
282
|
+
*
|
|
283
|
+
* - **Legitimate reset** — consumer or executor calls `clear()`
|
|
284
|
+
* when no boundary is in-flight (`openTokens` empty). Safe to
|
|
285
|
+
* wipe; the recorder is idle.
|
|
286
|
+
* - **Composition wipe** — sub-executor's pre-run clear fires
|
|
287
|
+
* while the parent has open boundaries (`openTokens` non-empty).
|
|
288
|
+
* Skip the wipe; the parent's state must be preserved.
|
|
289
|
+
*
|
|
290
|
+
* If a consumer needs to forcibly wipe state even with open tokens
|
|
291
|
+
* (e.g., manual recovery after a crashed run), pair `clear()` with
|
|
292
|
+
* an explicit `forceClear()` (TODO — add when the use case shows up;
|
|
293
|
+
* today the recorder lifecycle pattern is "one recorder per logical
|
|
294
|
+
* run" so leaked tokens shouldn't occur).
|
|
295
|
+
*/
|
|
158
296
|
clear() {
|
|
159
|
-
|
|
297
|
+
if (this.openTokens.size > 0) {
|
|
298
|
+
// Mid-run wipe attempt — almost certainly a sub-executor's
|
|
299
|
+
// pre-run clear via composition propagation. Skip.
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
this.store.clear();
|
|
303
|
+
this.boundaryIndex.clear();
|
|
304
|
+
this.openTokens.clear();
|
|
160
305
|
this.prevLLMEndHadTools = false;
|
|
306
|
+
this.runIdGuard.reset();
|
|
307
|
+
}
|
|
308
|
+
observeRunId(runId) {
|
|
309
|
+
this.runIdGuard.observe(runId);
|
|
161
310
|
}
|
|
162
311
|
// ── FlowRecorder hooks (footprintjs side) ───────────────────────────
|
|
163
312
|
onRunStart(event) {
|
|
164
|
-
this.
|
|
313
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
314
|
+
const commitIdxBefore = this.getCommitCount();
|
|
315
|
+
const e = buildRunEvent('run.entry', event.payload, commitIdxBefore);
|
|
316
|
+
// Open range BEFORE the store push so a failed push doesn't leak
|
|
317
|
+
// an unclosed range (DS+logic panel review). The label is the
|
|
318
|
+
// stripped projection (no payload) — security-panel YELLOW #1.
|
|
319
|
+
if (this.hasCommitTracking) {
|
|
320
|
+
const token = this.boundaryIndex.open(toBoundaryLabel(e), commitIdxBefore);
|
|
321
|
+
this.openTokens.set(e.runtimeStageId, token);
|
|
322
|
+
}
|
|
323
|
+
this.store.push(e);
|
|
165
324
|
}
|
|
166
325
|
onRunEnd(event) {
|
|
167
|
-
this.
|
|
326
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
327
|
+
const commitIdxBefore = this.getCommitCount();
|
|
328
|
+
const e = buildRunEvent('run.exit', event.payload, commitIdxBefore);
|
|
329
|
+
// Close the range BEFORE store.push so a failed push doesn't
|
|
330
|
+
// leak a permanently-open range. The range is the canonical
|
|
331
|
+
// truth; the store entry is downstream telemetry.
|
|
332
|
+
if (this.hasCommitTracking) {
|
|
333
|
+
const token = this.openTokens.get(e.runtimeStageId);
|
|
334
|
+
if (token) {
|
|
335
|
+
this.boundaryIndex.close(token, commitIdxBefore);
|
|
336
|
+
this.openTokens.delete(e.runtimeStageId);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
this.store.push(e);
|
|
340
|
+
}
|
|
341
|
+
onRunFailed(event) {
|
|
342
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
343
|
+
const commitIdxBefore = this.getCommitCount();
|
|
344
|
+
// A failed run still TERMINATES — close the root range (mirror
|
|
345
|
+
// onRunEnd) so consumers get a terminal "Run · failed" boundary
|
|
346
|
+
// position instead of a slider that stops mid-call. The error rides
|
|
347
|
+
// as the exit payload so the WHY is reachable at that boundary.
|
|
348
|
+
const e = buildRunEvent('run.exit', { error: event.structuredError.message }, commitIdxBefore);
|
|
349
|
+
if (this.hasCommitTracking) {
|
|
350
|
+
const token = this.openTokens.get(e.runtimeStageId);
|
|
351
|
+
if (token) {
|
|
352
|
+
this.boundaryIndex.close(token, commitIdxBefore);
|
|
353
|
+
this.openTokens.delete(e.runtimeStageId);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
this.store.push(e);
|
|
168
357
|
}
|
|
169
358
|
onSubflowEntry(event) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
359
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
360
|
+
const commitIdxBefore = this.getCommitCount();
|
|
361
|
+
const e = buildSubflowEvent(event, 'subflow.entry', commitIdxBefore);
|
|
362
|
+
if (!e)
|
|
363
|
+
return;
|
|
364
|
+
if (this.hasCommitTracking) {
|
|
365
|
+
const token = this.boundaryIndex.open(toBoundaryLabel(e), commitIdxBefore);
|
|
366
|
+
this.openTokens.set(e.runtimeStageId, token);
|
|
367
|
+
}
|
|
368
|
+
this.store.push(e);
|
|
173
369
|
}
|
|
174
370
|
onSubflowExit(event) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
371
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
372
|
+
const commitIdxBefore = this.getCommitCount();
|
|
373
|
+
const e = buildSubflowEvent(event, 'subflow.exit', commitIdxBefore);
|
|
374
|
+
if (!e)
|
|
375
|
+
return;
|
|
376
|
+
if (this.hasCommitTracking) {
|
|
377
|
+
const token = this.openTokens.get(e.runtimeStageId);
|
|
378
|
+
if (token) {
|
|
379
|
+
this.boundaryIndex.close(token, commitIdxBefore);
|
|
380
|
+
this.openTokens.delete(e.runtimeStageId);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
this.store.push(e);
|
|
178
384
|
}
|
|
179
385
|
onFork(event) {
|
|
386
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
180
387
|
const ts = Date.now();
|
|
181
388
|
const ctx = event.traversalContext;
|
|
182
389
|
const runtimeStageId = ctx?.runtimeStageId ?? '';
|
|
183
390
|
const segments = ctx?.subflowPath ? ctx.subflowPath.split('/').filter(Boolean) : [];
|
|
184
391
|
const subflowPath = [trace_1.ROOT_SUBFLOW_ID, ...segments];
|
|
392
|
+
const commitIdxBefore = this.getCommitCount();
|
|
185
393
|
for (const childName of event.children) {
|
|
186
|
-
this.
|
|
394
|
+
this.store.push({
|
|
187
395
|
type: 'fork.branch',
|
|
188
396
|
runtimeStageId,
|
|
189
397
|
subflowPath,
|
|
190
398
|
depth: subflowPath.length - 1,
|
|
191
399
|
ts,
|
|
400
|
+
commitIdxBefore,
|
|
401
|
+
commitIdxAfter: commitIdxBefore,
|
|
192
402
|
parentSubflowId: event.parent,
|
|
193
403
|
childName,
|
|
194
404
|
});
|
|
195
405
|
}
|
|
196
406
|
}
|
|
197
407
|
onDecision(event) {
|
|
408
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
198
409
|
const ctx = event.traversalContext;
|
|
199
410
|
// Agent-internal decisions (Route picking tool-calls / final) are
|
|
200
411
|
// identified by the deciding stage's stableId matching one of the
|
|
@@ -208,12 +419,15 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
208
419
|
? stageId.slice(stageId.lastIndexOf('/') + 1)
|
|
209
420
|
: stageId;
|
|
210
421
|
const isAgentInternal = isAgentInternalId(localStageId);
|
|
211
|
-
this.
|
|
422
|
+
const commitIdxBefore = this.getCommitCount();
|
|
423
|
+
this.store.push({
|
|
212
424
|
type: 'decision.branch',
|
|
213
425
|
runtimeStageId: ctx?.runtimeStageId ?? '',
|
|
214
426
|
subflowPath: pathFromCtx(ctx?.subflowPath),
|
|
215
427
|
depth: ctxDepth(ctx?.subflowPath),
|
|
216
428
|
ts: Date.now(),
|
|
429
|
+
commitIdxBefore,
|
|
430
|
+
commitIdxAfter: commitIdxBefore,
|
|
217
431
|
decider: event.decider,
|
|
218
432
|
chosen: event.chosen,
|
|
219
433
|
...(event.rationale ? { rationale: event.rationale } : {}),
|
|
@@ -221,13 +435,17 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
221
435
|
});
|
|
222
436
|
}
|
|
223
437
|
onLoop(event) {
|
|
438
|
+
this.observeRunId(event.traversalContext?.runId);
|
|
224
439
|
const ctx = event.traversalContext;
|
|
225
|
-
this.
|
|
440
|
+
const commitIdxBefore = this.getCommitCount();
|
|
441
|
+
this.store.push({
|
|
226
442
|
type: 'loop.iteration',
|
|
227
443
|
runtimeStageId: ctx?.runtimeStageId ?? '',
|
|
228
444
|
subflowPath: pathFromCtx(ctx?.subflowPath),
|
|
229
445
|
depth: ctxDepth(ctx?.subflowPath),
|
|
230
446
|
ts: Date.now(),
|
|
447
|
+
commitIdxBefore,
|
|
448
|
+
commitIdxAfter: commitIdxBefore,
|
|
231
449
|
target: event.target,
|
|
232
450
|
iteration: event.iteration,
|
|
233
451
|
});
|
|
@@ -245,11 +463,22 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
245
463
|
return dispatcher.on('*', (event) => this.ingestTypedEvent(event));
|
|
246
464
|
}
|
|
247
465
|
ingestTypedEvent(event) {
|
|
466
|
+
// NOTE: deliberately does NOT call observeRunId(event.meta.runId).
|
|
467
|
+
// The agentfootprint dispatcher's runId is generated by a DIFFERENT
|
|
468
|
+
// generator than footprintjs's traversalContext.runId. Mixing them
|
|
469
|
+
// would toggle lastRunId on every event and trigger a false reset.
|
|
470
|
+
// Run-boundary detection happens reliably via the FlowRecorder hooks
|
|
471
|
+
// (onRunStart fires FIRST in any new run, before any typed event).
|
|
248
472
|
const meta = event.meta;
|
|
249
473
|
const runtimeStageId = meta.runtimeStageId ?? '';
|
|
250
474
|
const subflowPath = [trace_1.ROOT_SUBFLOW_ID, ...(meta.subflowPath ?? [])];
|
|
251
475
|
const depth = subflowPath.length - 1;
|
|
252
476
|
const ts = meta.wallClockMs;
|
|
477
|
+
// Phase 5 Layer 2: stamp commit index on every typed event for
|
|
478
|
+
// consumers that want to join domain events with the commit log
|
|
479
|
+
// (e.g., "which LLM call happened during this commit slice?").
|
|
480
|
+
// Typed events don't write to scope themselves, so before === after.
|
|
481
|
+
const commitIdxBefore = this.getCommitCount();
|
|
253
482
|
switch (event.type) {
|
|
254
483
|
case 'agentfootprint.stream.llm_start': {
|
|
255
484
|
const p = event.payload;
|
|
@@ -261,12 +490,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
261
490
|
? 'tool→llm'
|
|
262
491
|
: 'user→llm';
|
|
263
492
|
this.prevLLMEndHadTools = false;
|
|
264
|
-
this.
|
|
493
|
+
this.store.push({
|
|
265
494
|
type: 'llm.start',
|
|
266
495
|
runtimeStageId,
|
|
267
496
|
subflowPath,
|
|
268
497
|
depth,
|
|
269
498
|
ts,
|
|
499
|
+
commitIdxBefore,
|
|
500
|
+
commitIdxAfter: commitIdxBefore,
|
|
270
501
|
model: p.model,
|
|
271
502
|
provider: p.provider,
|
|
272
503
|
...(p.systemPromptChars !== undefined ? { systemPromptChars: p.systemPromptChars } : {}),
|
|
@@ -283,12 +514,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
283
514
|
// terminal call (toolCallCount === 0) leaves the flag false so
|
|
284
515
|
// a hypothetical follow-up call would correctly be 'user→llm'.
|
|
285
516
|
this.prevLLMEndHadTools = p.toolCallCount > 0;
|
|
286
|
-
this.
|
|
517
|
+
this.store.push({
|
|
287
518
|
type: 'llm.end',
|
|
288
519
|
runtimeStageId,
|
|
289
520
|
subflowPath,
|
|
290
521
|
depth,
|
|
291
522
|
ts,
|
|
523
|
+
commitIdxBefore,
|
|
524
|
+
commitIdxAfter: commitIdxBefore,
|
|
292
525
|
content: p.content,
|
|
293
526
|
toolCallCount: p.toolCallCount,
|
|
294
527
|
usage: { input: p.usage.input, output: p.usage.output },
|
|
@@ -299,12 +532,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
299
532
|
}
|
|
300
533
|
case 'agentfootprint.stream.tool_start': {
|
|
301
534
|
const p = event.payload;
|
|
302
|
-
this.
|
|
535
|
+
this.store.push({
|
|
303
536
|
type: 'tool.start',
|
|
304
537
|
runtimeStageId,
|
|
305
538
|
subflowPath,
|
|
306
539
|
depth,
|
|
307
540
|
ts,
|
|
541
|
+
commitIdxBefore,
|
|
542
|
+
commitIdxAfter: commitIdxBefore,
|
|
308
543
|
toolName: p.toolName,
|
|
309
544
|
toolCallId: p.toolCallId,
|
|
310
545
|
...(p.args !== undefined ? { args: p.args } : {}),
|
|
@@ -313,12 +548,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
313
548
|
}
|
|
314
549
|
case 'agentfootprint.stream.tool_end': {
|
|
315
550
|
const p = event.payload;
|
|
316
|
-
this.
|
|
551
|
+
this.store.push({
|
|
317
552
|
type: 'tool.end',
|
|
318
553
|
runtimeStageId,
|
|
319
554
|
subflowPath,
|
|
320
555
|
depth,
|
|
321
556
|
ts,
|
|
557
|
+
commitIdxBefore,
|
|
558
|
+
commitIdxAfter: commitIdxBefore,
|
|
322
559
|
toolCallId: p.toolCallId,
|
|
323
560
|
...(p.result !== undefined ? { result: p.result } : {}),
|
|
324
561
|
...(p.durationMs !== undefined ? { durationMs: p.durationMs } : {}),
|
|
@@ -328,12 +565,14 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
328
565
|
}
|
|
329
566
|
case 'agentfootprint.context.injected': {
|
|
330
567
|
const p = event.payload;
|
|
331
|
-
this.
|
|
568
|
+
this.store.push({
|
|
332
569
|
type: 'context.injected',
|
|
333
570
|
runtimeStageId,
|
|
334
571
|
subflowPath,
|
|
335
572
|
depth,
|
|
336
573
|
ts,
|
|
574
|
+
commitIdxBefore,
|
|
575
|
+
commitIdxAfter: commitIdxBefore,
|
|
337
576
|
slot: p.slot,
|
|
338
577
|
source: p.source ?? 'unknown',
|
|
339
578
|
...(p.sourceId ? { sourceId: p.sourceId } : {}),
|
|
@@ -351,23 +590,82 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
351
590
|
});
|
|
352
591
|
break;
|
|
353
592
|
}
|
|
593
|
+
case 'agentfootprint.composition.enter': {
|
|
594
|
+
// Open a boundary range for the composition. The MATCHING KEY
|
|
595
|
+
// for open/close is `payload.id` (the composition's stable id),
|
|
596
|
+
// NOT `meta.runtimeStageId`. Reason: the composition's enter
|
|
597
|
+
// event fires from a different stage (entry hook) than its
|
|
598
|
+
// exit event (merge / exit hook) — different `meta.runtimeStageId`s.
|
|
599
|
+
// The composition's `id` is the only field that's the same on
|
|
600
|
+
// both. The boundary range's runtimeStageId (used as the Lens
|
|
601
|
+
// group identity) is the ENTER event's `meta.runtimeStageId`
|
|
602
|
+
// (the entry stage's id) — that's the "fork moment."
|
|
603
|
+
const p = event.payload;
|
|
604
|
+
const e = {
|
|
605
|
+
type: 'composition.start',
|
|
606
|
+
runtimeStageId,
|
|
607
|
+
subflowPath,
|
|
608
|
+
depth,
|
|
609
|
+
ts,
|
|
610
|
+
commitIdxBefore,
|
|
611
|
+
commitIdxAfter: commitIdxBefore,
|
|
612
|
+
kind: p.kind,
|
|
613
|
+
compositionId: p.id,
|
|
614
|
+
name: p.name,
|
|
615
|
+
};
|
|
616
|
+
if (this.hasCommitTracking) {
|
|
617
|
+
const token = this.boundaryIndex.open(toCompositionBoundaryLabel(e), commitIdxBefore);
|
|
618
|
+
this.openTokens.set(`composition:${p.id}`, token);
|
|
619
|
+
}
|
|
620
|
+
this.store.push(e);
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
case 'agentfootprint.composition.exit': {
|
|
624
|
+
// Close the matching composition range. Keyed by `payload.id`
|
|
625
|
+
// — see the enter handler for why this differs from
|
|
626
|
+
// meta.runtimeStageId.
|
|
627
|
+
const p = event.payload;
|
|
628
|
+
const e = {
|
|
629
|
+
type: 'composition.end',
|
|
630
|
+
runtimeStageId,
|
|
631
|
+
subflowPath,
|
|
632
|
+
depth,
|
|
633
|
+
ts,
|
|
634
|
+
commitIdxBefore,
|
|
635
|
+
commitIdxAfter: commitIdxBefore,
|
|
636
|
+
kind: p.kind,
|
|
637
|
+
compositionId: p.id,
|
|
638
|
+
name: p.name ?? '',
|
|
639
|
+
status: p.status,
|
|
640
|
+
durationMs: p.durationMs,
|
|
641
|
+
};
|
|
642
|
+
if (this.hasCommitTracking) {
|
|
643
|
+
const key = `composition:${p.id}`;
|
|
644
|
+
const token = this.openTokens.get(key);
|
|
645
|
+
if (token) {
|
|
646
|
+
this.boundaryIndex.close(token, commitIdxBefore);
|
|
647
|
+
this.openTokens.delete(key);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
this.store.push(e);
|
|
651
|
+
break;
|
|
652
|
+
}
|
|
354
653
|
default:
|
|
355
|
-
// Other typed events (
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
// (agent.turn_*) that downstream selectors derive on demand.
|
|
654
|
+
// Other typed events (agent.*, eval.*, etc.) are not mapped to
|
|
655
|
+
// DomainEvent for now — they're higher-level summaries that
|
|
656
|
+
// downstream selectors derive on demand.
|
|
359
657
|
break;
|
|
360
658
|
}
|
|
361
659
|
}
|
|
362
660
|
// ── Read API ────────────────────────────────────────────────────────
|
|
363
661
|
/** All events in capture order (the canonical projection). */
|
|
364
662
|
getEvents() {
|
|
365
|
-
return this.
|
|
663
|
+
return this.store.getAll();
|
|
366
664
|
}
|
|
367
665
|
/** Type-narrowed lookup: all events of one kind. */
|
|
368
666
|
getEventsByType(type) {
|
|
369
667
|
const out = [];
|
|
370
|
-
for (const e of this.
|
|
668
|
+
for (const e of this.store.getAll()) {
|
|
371
669
|
if (e.type === type)
|
|
372
670
|
out.push(e);
|
|
373
671
|
}
|
|
@@ -377,7 +675,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
377
675
|
/** All boundary events (run + subflow, entry + exit interleaved). */
|
|
378
676
|
getBoundaries() {
|
|
379
677
|
const out = [];
|
|
380
|
-
for (const e of this.
|
|
678
|
+
for (const e of this.store.getAll()) {
|
|
381
679
|
if (e.type === 'run.entry' ||
|
|
382
680
|
e.type === 'run.exit' ||
|
|
383
681
|
e.type === 'subflow.entry' ||
|
|
@@ -397,7 +695,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
397
695
|
}
|
|
398
696
|
/** Entry/exit pair for one chart execution by `runtimeStageId`. */
|
|
399
697
|
getBoundary(runtimeStageId) {
|
|
400
|
-
const matches = this.
|
|
698
|
+
const matches = this.store.getByKey(runtimeStageId);
|
|
401
699
|
let entry;
|
|
402
700
|
let exit;
|
|
403
701
|
for (const e of matches) {
|
|
@@ -424,7 +722,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
424
722
|
const systemPrompt = [];
|
|
425
723
|
const messages = [];
|
|
426
724
|
const tools = [];
|
|
427
|
-
for (const e of this.
|
|
725
|
+
for (const e of this.store.getAll()) {
|
|
428
726
|
if (e.type !== 'subflow.entry' && e.type !== 'subflow.exit')
|
|
429
727
|
continue;
|
|
430
728
|
if (e.slotKind === 'system-prompt')
|
|
@@ -463,7 +761,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
463
761
|
* matches `runtimeStageId`.
|
|
464
762
|
*/
|
|
465
763
|
aggregateForBoundary(runtimeStageId) {
|
|
466
|
-
const events = this.
|
|
764
|
+
const events = this.store.getAll();
|
|
467
765
|
let entry;
|
|
468
766
|
let exit;
|
|
469
767
|
for (const e of events) {
|
|
@@ -488,7 +786,7 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
488
786
|
* not user-facing rollup units.
|
|
489
787
|
*/
|
|
490
788
|
aggregateAllBoundaries() {
|
|
491
|
-
const events = this.
|
|
789
|
+
const events = this.store.getAll();
|
|
492
790
|
const out = [];
|
|
493
791
|
// Index exits by runtimeStageId for O(1) pair-up.
|
|
494
792
|
const exitByRid = new Map();
|
|
@@ -518,18 +816,20 @@ class BoundaryRecorder extends trace_1.SequenceRecorder {
|
|
|
518
816
|
}
|
|
519
817
|
exports.BoundaryRecorder = BoundaryRecorder;
|
|
520
818
|
// ── Internal helpers ─────────────────────────────────────────────────
|
|
521
|
-
function buildRunEvent(type, payload) {
|
|
819
|
+
function buildRunEvent(type, payload, commitIdxBefore) {
|
|
522
820
|
return {
|
|
523
821
|
type,
|
|
524
822
|
runtimeStageId: trace_1.ROOT_RUNTIME_STAGE_ID,
|
|
525
823
|
subflowPath: [trace_1.ROOT_SUBFLOW_ID],
|
|
526
824
|
depth: 0,
|
|
527
825
|
ts: Date.now(),
|
|
826
|
+
commitIdxBefore,
|
|
827
|
+
commitIdxAfter: commitIdxBefore,
|
|
528
828
|
payload,
|
|
529
829
|
isRoot: true,
|
|
530
830
|
};
|
|
531
831
|
}
|
|
532
|
-
function buildSubflowEvent(event, type) {
|
|
832
|
+
function buildSubflowEvent(event, type, commitIdxBefore) {
|
|
533
833
|
const subflowId = event.subflowId;
|
|
534
834
|
if (!subflowId)
|
|
535
835
|
return undefined;
|
|
@@ -550,6 +850,8 @@ function buildSubflowEvent(event, type) {
|
|
|
550
850
|
subflowPath,
|
|
551
851
|
depth,
|
|
552
852
|
ts: Date.now(),
|
|
853
|
+
commitIdxBefore,
|
|
854
|
+
commitIdxAfter: commitIdxBefore,
|
|
553
855
|
subflowId,
|
|
554
856
|
localSubflowId,
|
|
555
857
|
subflowName: event.name,
|