agentfootprint 2.11.0 → 2.11.2
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 +2 -1
- package/dist/core/Agent.js +89 -1341
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +489 -0
- package/dist/core/agent/AgentBuilder.js.map +1 -0
- package/dist/core/agent/buildAgentChart.js +227 -0
- package/dist/core/agent/buildAgentChart.js.map +1 -0
- package/dist/core/agent/buildToolRegistry.js +115 -0
- package/dist/core/agent/buildToolRegistry.js.map +1 -0
- package/dist/core/agent/stages/breakFinal.js +28 -0
- package/dist/core/agent/stages/breakFinal.js.map +1 -0
- package/dist/core/agent/stages/callLLM.js +129 -0
- package/dist/core/agent/stages/callLLM.js.map +1 -0
- package/dist/core/agent/stages/iterationStart.js +24 -0
- package/dist/core/agent/stages/iterationStart.js.map +1 -0
- package/dist/core/agent/stages/prepareFinal.js +45 -0
- package/dist/core/agent/stages/prepareFinal.js.map +1 -0
- package/dist/core/agent/stages/route.js +36 -0
- package/dist/core/agent/stages/route.js.map +1 -0
- package/dist/core/agent/stages/seed.js +95 -0
- package/dist/core/agent/stages/seed.js.map +1 -0
- package/dist/core/agent/stages/toolCalls.js +250 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -0
- package/dist/core/agent/types.js +12 -0
- package/dist/core/agent/types.js.map +1 -0
- package/dist/core/agent/validators.js +131 -0
- package/dist/core/agent/validators.js.map +1 -0
- package/dist/esm/core/Agent.js +87 -1338
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.js +485 -0
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -0
- package/dist/esm/core/agent/buildAgentChart.js +223 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -0
- package/dist/esm/core/agent/buildToolRegistry.js +111 -0
- package/dist/esm/core/agent/buildToolRegistry.js.map +1 -0
- package/dist/esm/core/agent/stages/breakFinal.js +24 -0
- package/dist/esm/core/agent/stages/breakFinal.js.map +1 -0
- package/dist/esm/core/agent/stages/callLLM.js +125 -0
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -0
- package/dist/esm/core/agent/stages/iterationStart.js +20 -0
- package/dist/esm/core/agent/stages/iterationStart.js.map +1 -0
- package/dist/esm/core/agent/stages/prepareFinal.js +41 -0
- package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -0
- package/dist/esm/core/agent/stages/route.js +32 -0
- package/dist/esm/core/agent/stages/route.js.map +1 -0
- package/dist/esm/core/agent/stages/seed.js +91 -0
- package/dist/esm/core/agent/stages/seed.js.map +1 -0
- package/dist/esm/core/agent/stages/toolCalls.js +246 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -0
- package/dist/esm/core/agent/types.js +11 -0
- package/dist/esm/core/agent/types.js.map +1 -0
- package/dist/esm/core/agent/validators.js +124 -0
- package/dist/esm/core/agent/validators.js.map +1 -0
- package/dist/esm/reliability/CircuitBreaker.js +156 -0
- package/dist/esm/reliability/CircuitBreaker.js.map +1 -0
- package/dist/esm/reliability/buildReliabilityGateChart.js +359 -0
- package/dist/esm/reliability/buildReliabilityGateChart.js.map +1 -0
- package/dist/esm/reliability/classifyError.js +56 -0
- package/dist/esm/reliability/classifyError.js.map +1 -0
- package/dist/esm/reliability/index.js +36 -0
- package/dist/esm/reliability/index.js.map +1 -0
- package/dist/esm/reliability/types.js +44 -0
- package/dist/esm/reliability/types.js.map +1 -0
- package/dist/reliability/CircuitBreaker.js +165 -0
- package/dist/reliability/CircuitBreaker.js.map +1 -0
- package/dist/reliability/buildReliabilityGateChart.js +363 -0
- package/dist/reliability/buildReliabilityGateChart.js.map +1 -0
- package/dist/reliability/classifyError.js +60 -0
- package/dist/reliability/classifyError.js.map +1 -0
- package/dist/reliability/index.js +42 -0
- package/dist/reliability/index.js.map +1 -0
- package/dist/reliability/types.js +48 -0
- package/dist/reliability/types.js.map +1 -0
- package/dist/types/core/Agent.d.ts +7 -400
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +348 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -0
- package/dist/types/core/agent/buildAgentChart.d.ts +74 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -0
- package/dist/types/core/agent/buildToolRegistry.d.ts +62 -0
- package/dist/types/core/agent/buildToolRegistry.d.ts.map +1 -0
- package/dist/types/core/agent/stages/breakFinal.d.ts +23 -0
- package/dist/types/core/agent/stages/breakFinal.d.ts.map +1 -0
- package/dist/types/core/agent/stages/callLLM.d.ts +54 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -0
- package/dist/types/core/agent/stages/iterationStart.d.ts +16 -0
- package/dist/types/core/agent/stages/iterationStart.d.ts.map +1 -0
- package/dist/types/core/agent/stages/prepareFinal.d.ts +20 -0
- package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -0
- package/dist/types/core/agent/stages/route.d.ts +19 -0
- package/dist/types/core/agent/stages/route.d.ts.map +1 -0
- package/dist/types/core/agent/stages/seed.d.ts +54 -0
- package/dist/types/core/agent/stages/seed.d.ts.map +1 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts +50 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -0
- package/dist/types/core/agent/types.d.ts +154 -0
- package/dist/types/core/agent/types.d.ts.map +1 -0
- package/dist/types/core/agent/validators.d.ts +48 -0
- package/dist/types/core/agent/validators.d.ts.map +1 -0
- package/dist/types/reliability/CircuitBreaker.d.ts +76 -0
- package/dist/types/reliability/CircuitBreaker.d.ts.map +1 -0
- package/dist/types/reliability/buildReliabilityGateChart.d.ts +54 -0
- package/dist/types/reliability/buildReliabilityGateChart.d.ts.map +1 -0
- package/dist/types/reliability/classifyError.d.ts +29 -0
- package/dist/types/reliability/classifyError.d.ts.map +1 -0
- package/dist/types/reliability/index.d.ts +34 -0
- package/dist/types/reliability/index.d.ts.map +1 -0
- package/dist/types/reliability/types.d.ts +256 -0
- package/dist/types/reliability/types.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CircuitBreaker.js","sourceRoot":"","sources":["../../../src/reliability/CircuitBreaker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* buildReliabilityGateChart — produces a footprintjs FlowChart that wraps
|
|
3
|
+
* an LLM call with rules-based reliability semantics, using the native
|
|
4
|
+
* `decide()` DSL via `addDeciderFunction` decider stages.
|
|
5
|
+
*
|
|
6
|
+
* The returned chart is mounted as a subflow in the agent's chart at
|
|
7
|
+
* Agent.build() time (only when reliability is configured). Inside the
|
|
8
|
+
* subflow:
|
|
9
|
+
*
|
|
10
|
+
* PreCheck (decider) → CallProvider (function) → PostDecide (decider)
|
|
11
|
+
* │
|
|
12
|
+
* ┌───────────────┘
|
|
13
|
+
* ▼ loopTo('pre-check')
|
|
14
|
+
*
|
|
15
|
+
* Branch outcomes (escape via $break() to stop the gate's loop;
|
|
16
|
+
* fall-through via no-$break to trigger loopTo back to PreCheck):
|
|
17
|
+
*
|
|
18
|
+
* PreCheck:
|
|
19
|
+
* 'continue' → no-op → falls through to CallProvider
|
|
20
|
+
* 'fail-fast' → set failKind, $emit, $break(reason)
|
|
21
|
+
*
|
|
22
|
+
* PostDecide:
|
|
23
|
+
* 'ok' → $break() (subflow exits normally; agent continues)
|
|
24
|
+
* 'retry' → bump attempt; falls through to loopTo
|
|
25
|
+
* 'retry-other' → bump providerIdx; falls through to loopTo
|
|
26
|
+
* 'fallback' → call config.fallback(); $break() on success
|
|
27
|
+
* 'fail-fast' → set failKind, $emit, $break(reason)
|
|
28
|
+
*
|
|
29
|
+
* The subflow is mounted WITHOUT `propagateBreak: true`. Subflow $break is
|
|
30
|
+
* local — agent.ts adds a `TranslateFailFast` agent-level stage AFTER the
|
|
31
|
+
* subflow that reads scope.reliabilityFailKind and converts it into an
|
|
32
|
+
* agent-level `$break(reason)`. This split lets normal subflow exits
|
|
33
|
+
* (`ok`/`fallback`) leave the agent running while fail-fast stops it.
|
|
34
|
+
*
|
|
35
|
+
* Three-channel discipline preserved:
|
|
36
|
+
* • SCOPE STATE — failKind/failPayload/failReason mapped to parent via
|
|
37
|
+
* outputMapper; consumed by agent's TranslateFailFast.
|
|
38
|
+
* • $emit — passive observability for external consumers.
|
|
39
|
+
* • $break(reason)— control flow + human reason for narrative.
|
|
40
|
+
*/
|
|
41
|
+
import { decide, flowChart } from 'footprintjs';
|
|
42
|
+
import { CircuitOpenError, admitCall, initialBreakerState, nextProbeTime, recordFailure, recordSuccess, } from './CircuitBreaker.js';
|
|
43
|
+
import { classifyError } from './classifyError.js';
|
|
44
|
+
// ─── Stage IDs (also used for narrative/topology readability) ────────
|
|
45
|
+
const STAGE_IDS = {
|
|
46
|
+
INIT: 'reliability-init',
|
|
47
|
+
PRE_CHECK: 'pre-check',
|
|
48
|
+
CALL_PROVIDER: 'call-provider',
|
|
49
|
+
POST_DECIDE: 'post-decide',
|
|
50
|
+
};
|
|
51
|
+
// Branch IDs must be globally unique within the chart's stageMap, so
|
|
52
|
+
// each branch carries its decider's prefix. The decider's RETURN value
|
|
53
|
+
// from preCheckDeciderFn / postDecideDeciderFn is the branch's local id
|
|
54
|
+
// (e.g., 'continue', 'ok') — the decide() result map below translates.
|
|
55
|
+
const BRANCH_IDS = {
|
|
56
|
+
// PreCheck branches
|
|
57
|
+
PRE_CONTINUE: 'pre-continue',
|
|
58
|
+
PRE_FAIL_FAST: 'pre-fail-fast',
|
|
59
|
+
// PostDecide branches
|
|
60
|
+
POST_OK: 'post-ok',
|
|
61
|
+
POST_RETRY: 'post-retry',
|
|
62
|
+
POST_RETRY_OTHER: 'post-retry-other',
|
|
63
|
+
POST_FALLBACK: 'post-fallback',
|
|
64
|
+
POST_FAIL_FAST: 'post-fail-fast',
|
|
65
|
+
};
|
|
66
|
+
// Map from `ReliabilityDecision` (consumer-facing rule.then values) to
|
|
67
|
+
// the prefixed branch ids. The decider functions translate before
|
|
68
|
+
// returning so consumers never see the prefixed names.
|
|
69
|
+
const PRE_DECISION_TO_BRANCH = {
|
|
70
|
+
continue: BRANCH_IDS.PRE_CONTINUE,
|
|
71
|
+
'fail-fast': BRANCH_IDS.PRE_FAIL_FAST,
|
|
72
|
+
};
|
|
73
|
+
const POST_DECISION_TO_BRANCH = {
|
|
74
|
+
ok: BRANCH_IDS.POST_OK,
|
|
75
|
+
retry: BRANCH_IDS.POST_RETRY,
|
|
76
|
+
'retry-other': BRANCH_IDS.POST_RETRY_OTHER,
|
|
77
|
+
fallback: BRANCH_IDS.POST_FALLBACK,
|
|
78
|
+
'fail-fast': BRANCH_IDS.POST_FAIL_FAST,
|
|
79
|
+
};
|
|
80
|
+
// ─── Helpers ─────────────────────────────────────────────────────────
|
|
81
|
+
/** Build the structured failure payload from current scope state. */
|
|
82
|
+
function buildFailPayload(scope, phase) {
|
|
83
|
+
return {
|
|
84
|
+
phase,
|
|
85
|
+
attempt: scope.attempt,
|
|
86
|
+
providerUsed: scope.currentProvider,
|
|
87
|
+
errorKind: scope.errorKind,
|
|
88
|
+
...(scope.error?.message !== undefined && { errorMessage: scope.error.message }),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Find the matched rule's index in a DecisionResult evidence list. */
|
|
92
|
+
function findMatchedIndex(evidence) {
|
|
93
|
+
for (let i = 0; i < evidence.rules.length; i++) {
|
|
94
|
+
if (evidence.rules[i].matched)
|
|
95
|
+
return i;
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
/** Resolve {kind, label} from a rule list and the matched index. */
|
|
100
|
+
function matchedKindLabel(rules, matchedIdx) {
|
|
101
|
+
if (matchedIdx === undefined || matchedIdx < 0 || matchedIdx >= rules.length) {
|
|
102
|
+
return { kind: 'unknown', label: 'unknown' };
|
|
103
|
+
}
|
|
104
|
+
const rule = rules[matchedIdx];
|
|
105
|
+
return { kind: rule.kind, label: rule.label ?? rule.kind };
|
|
106
|
+
}
|
|
107
|
+
// ─── Build the chart ─────────────────────────────────────────────────
|
|
108
|
+
/**
|
|
109
|
+
* Build the reliability gate FlowChart from a config. Mount via
|
|
110
|
+
* `addSubFlowChartNext` in the agent's chart — see `Agent.build()`.
|
|
111
|
+
*
|
|
112
|
+
* Closure state captured by stage functions:
|
|
113
|
+
* • `breakers` — Map<providerName, CircuitBreaker>; per-instance state
|
|
114
|
+
* persists across gate invocations within ONE agent process.
|
|
115
|
+
* • `preRules` / `postRules` — frozen rule arrays.
|
|
116
|
+
* • `fallbackFn` — consumer's fallback function, if configured.
|
|
117
|
+
*/
|
|
118
|
+
export function buildReliabilityGateChart(config) {
|
|
119
|
+
// FROZEN CONFIG captured by the factory closure. None of these mutate
|
|
120
|
+
// at runtime — they're the chart's CODE, not state. Same pattern as
|
|
121
|
+
// every other footprintjs chart factory (cacheDecisionSubflow,
|
|
122
|
+
// injectionEngineSubflow, etc.) capturing rules/directives at build.
|
|
123
|
+
//
|
|
124
|
+
// • providers — functions can't structuredClone into scope
|
|
125
|
+
// • preRules/postRules — frozen at chart-build time
|
|
126
|
+
// • fallbackFn — function, can't structuredClone into scope
|
|
127
|
+
//
|
|
128
|
+
// RUNTIME STATE (attempt counts, errorKind, breaker counters,
|
|
129
|
+
// response, latency, etc.) lives in SCOPE. Breaker state in
|
|
130
|
+
// particular is a plain serializable record that round-trips across
|
|
131
|
+
// gate invocations via inputMapper/outputMapper — no closure.
|
|
132
|
+
const providers = config.providers ?? [];
|
|
133
|
+
const breakerConfig = config.circuitBreaker;
|
|
134
|
+
const preRules = config.preCheck ?? [];
|
|
135
|
+
const postRules = config.postDecide ?? [];
|
|
136
|
+
const fallbackFn = config.fallback;
|
|
137
|
+
// ─── PreCheck decider function ───────────────────────────────
|
|
138
|
+
// Returns one of the PRE_* branch ids. If consumer rules use
|
|
139
|
+
// ReliabilityDecision values ('continue'/'fail-fast'), map them.
|
|
140
|
+
const preCheckDeciderFn = (scope) => {
|
|
141
|
+
if (preRules.length === 0)
|
|
142
|
+
return BRANCH_IDS.PRE_CONTINUE;
|
|
143
|
+
const result = decide(scope, preRules, 'continue');
|
|
144
|
+
return PRE_DECISION_TO_BRANCH[result.branch] ?? BRANCH_IDS.PRE_CONTINUE;
|
|
145
|
+
};
|
|
146
|
+
// ─── PreCheck 'fail-fast' branch fn ──────────────────────────
|
|
147
|
+
const preFailFastBranchFn = (scope) => {
|
|
148
|
+
// Pre-check rules carry kind via the decide() result. Re-evaluate
|
|
149
|
+
// to extract the matched rule's kind/label for the failure payload.
|
|
150
|
+
if (preRules.length === 0)
|
|
151
|
+
return;
|
|
152
|
+
const result = decide(scope, preRules, 'continue');
|
|
153
|
+
const matchedIdx = findMatchedIndex(result.evidence);
|
|
154
|
+
const { kind, label } = matchedKindLabel(preRules, matchedIdx);
|
|
155
|
+
scope.failKind = kind;
|
|
156
|
+
scope.failPayload = buildFailPayload(scope, 'pre-check');
|
|
157
|
+
scope.$emit('agentfootprint.reliability.fail_fast', {
|
|
158
|
+
phase: 'pre-check',
|
|
159
|
+
kind,
|
|
160
|
+
label,
|
|
161
|
+
attempt: scope.attempt,
|
|
162
|
+
providerUsed: scope.currentProvider,
|
|
163
|
+
});
|
|
164
|
+
scope.$break(`reliability-pre-check: ${label}`);
|
|
165
|
+
};
|
|
166
|
+
// ─── CallProvider stage fn ───────────────────────────────────
|
|
167
|
+
const callProviderStageFn = async (scope) => {
|
|
168
|
+
const providerEntry = providers[scope.providerIdx];
|
|
169
|
+
if (!providerEntry) {
|
|
170
|
+
// Misconfiguration — no provider at this index. Fail-fast cleanly.
|
|
171
|
+
scope.failKind = 'misconfigured-provider';
|
|
172
|
+
scope.failPayload = buildFailPayload(scope, 'pre-check');
|
|
173
|
+
scope.$emit('agentfootprint.reliability.fail_fast', {
|
|
174
|
+
phase: 'pre-check',
|
|
175
|
+
kind: 'misconfigured-provider',
|
|
176
|
+
providerIdx: scope.providerIdx,
|
|
177
|
+
});
|
|
178
|
+
scope.$break(`reliability-pre-check: misconfigured-provider (idx ${scope.providerIdx} out of bounds)`);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const t0 = Date.now();
|
|
182
|
+
try {
|
|
183
|
+
// Breaker check (pure): admit + transition based on cooldown.
|
|
184
|
+
if (breakerConfig !== undefined) {
|
|
185
|
+
const current = scope.breakerStates[providerEntry.name] ?? initialBreakerState();
|
|
186
|
+
const { admitted, nextState } = admitCall(current, breakerConfig);
|
|
187
|
+
scope.breakerStates[providerEntry.name] = nextState;
|
|
188
|
+
if (!admitted) {
|
|
189
|
+
throw new CircuitOpenError(providerEntry.name, nextState.lastErrorMessage, nextProbeTime(nextState, breakerConfig));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const response = await providerEntry.provider.complete(scope.request);
|
|
193
|
+
scope.response = response;
|
|
194
|
+
scope.error = undefined;
|
|
195
|
+
scope.errorKind = 'ok';
|
|
196
|
+
// Record success (pure): may CLOSE a HALF-OPEN breaker
|
|
197
|
+
if (breakerConfig !== undefined) {
|
|
198
|
+
scope.breakerStates[providerEntry.name] = recordSuccess(scope.breakerStates[providerEntry.name] ?? initialBreakerState(), breakerConfig);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
scope.response = undefined;
|
|
203
|
+
scope.error = err instanceof Error ? err : new Error(String(err));
|
|
204
|
+
scope.errorKind = classifyError(err);
|
|
205
|
+
// CircuitOpenError is the breaker rejecting; don't double-count.
|
|
206
|
+
if (breakerConfig !== undefined && !(err instanceof CircuitOpenError)) {
|
|
207
|
+
scope.breakerStates[providerEntry.name] = recordFailure(scope.breakerStates[providerEntry.name] ?? initialBreakerState(), err, breakerConfig);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
scope.latencyMs = Date.now() - t0;
|
|
212
|
+
scope.attemptsPerProvider[providerEntry.name] =
|
|
213
|
+
(scope.attemptsPerProvider[providerEntry.name] ?? 0) + 1;
|
|
214
|
+
scope.attempt += 1;
|
|
215
|
+
scope.canSwitchProvider = scope.providerIdx < providers.length - 1;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
// ─── PostDecide decider function ─────────────────────────────
|
|
219
|
+
// Returns one of the POST_* branch ids. Maps ReliabilityDecision
|
|
220
|
+
// values from rule.then to the prefixed branch ids.
|
|
221
|
+
const postDecideDeciderFn = (scope) => {
|
|
222
|
+
if (postRules.length === 0) {
|
|
223
|
+
return scope.error === undefined ? BRANCH_IDS.POST_OK : BRANCH_IDS.POST_FAIL_FAST;
|
|
224
|
+
}
|
|
225
|
+
const result = decide(scope, postRules, 'ok');
|
|
226
|
+
return POST_DECISION_TO_BRANCH[result.branch] ?? BRANCH_IDS.POST_OK;
|
|
227
|
+
};
|
|
228
|
+
// ─── PostDecide branch fns ───────────────────────────────────
|
|
229
|
+
const okBranchFn = (scope) => {
|
|
230
|
+
// Success exit — $break stops subflow; outputMapper still runs.
|
|
231
|
+
scope.$break();
|
|
232
|
+
};
|
|
233
|
+
const retryBranchFn = (_scope) => {
|
|
234
|
+
// No-op — `attempt` was already incremented by CallProvider's
|
|
235
|
+
// finally block. Falling through (no $break) triggers loopTo
|
|
236
|
+
// back to PreCheck.
|
|
237
|
+
void _scope;
|
|
238
|
+
};
|
|
239
|
+
const retryOtherBranchFn = (scope) => {
|
|
240
|
+
// Advance to the next provider in the failover list (held in closure).
|
|
241
|
+
scope.providerIdx += 1;
|
|
242
|
+
if (scope.providerIdx < providers.length) {
|
|
243
|
+
scope.currentProvider = providers[scope.providerIdx].name;
|
|
244
|
+
}
|
|
245
|
+
scope.canSwitchProvider = scope.providerIdx < providers.length - 1;
|
|
246
|
+
// No $break — loopTo re-enters PreCheck with the new provider.
|
|
247
|
+
};
|
|
248
|
+
const fallbackBranchFn = async (scope) => {
|
|
249
|
+
if (!fallbackFn) {
|
|
250
|
+
// Routed here but no fallback configured — convert to fail-fast.
|
|
251
|
+
scope.failKind = 'fallback-not-configured';
|
|
252
|
+
scope.failPayload = buildFailPayload(scope, 'post-decide');
|
|
253
|
+
scope.$emit('agentfootprint.reliability.fail_fast', {
|
|
254
|
+
phase: 'post-decide',
|
|
255
|
+
kind: 'fallback-not-configured',
|
|
256
|
+
attempt: scope.attempt,
|
|
257
|
+
providerUsed: scope.currentProvider,
|
|
258
|
+
});
|
|
259
|
+
scope.$break('reliability-post-decide: fallback-not-configured');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
const repaired = await fallbackFn(scope.request, scope.error);
|
|
264
|
+
scope.response = repaired;
|
|
265
|
+
scope.error = undefined;
|
|
266
|
+
scope.errorKind = 'ok';
|
|
267
|
+
scope.$break(); // success via fallback; exit subflow
|
|
268
|
+
}
|
|
269
|
+
catch (fallbackErr) {
|
|
270
|
+
// Fallback threw — re-classify and let next iteration's
|
|
271
|
+
// post-decide rules route on the new error (typically fail-fast).
|
|
272
|
+
scope.error = fallbackErr instanceof Error ? fallbackErr : new Error(String(fallbackErr));
|
|
273
|
+
scope.errorKind = classifyError(fallbackErr);
|
|
274
|
+
// Don't $break — loopTo re-enters PreCheck with new error state.
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
const failFastBranchFn = (scope) => {
|
|
278
|
+
if (postRules.length === 0) {
|
|
279
|
+
// Default-path fail-fast (no rules configured but error occurred)
|
|
280
|
+
scope.failKind = scope.errorKind;
|
|
281
|
+
scope.failPayload = buildFailPayload(scope, 'post-decide');
|
|
282
|
+
scope.$emit('agentfootprint.reliability.fail_fast', {
|
|
283
|
+
phase: 'post-decide',
|
|
284
|
+
kind: scope.errorKind,
|
|
285
|
+
attempt: scope.attempt,
|
|
286
|
+
providerUsed: scope.currentProvider,
|
|
287
|
+
...(scope.error?.message !== undefined && { errorMessage: scope.error.message }),
|
|
288
|
+
});
|
|
289
|
+
scope.$break(`reliability-post-decide: ${scope.errorKind}`);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
// Re-evaluate to extract the matched rule's kind/label.
|
|
293
|
+
const result = decide(scope, postRules, 'ok');
|
|
294
|
+
const matchedIdx = findMatchedIndex(result.evidence);
|
|
295
|
+
const { kind, label } = matchedKindLabel(postRules, matchedIdx);
|
|
296
|
+
scope.failKind = kind;
|
|
297
|
+
scope.failPayload = buildFailPayload(scope, 'post-decide');
|
|
298
|
+
scope.$emit('agentfootprint.reliability.fail_fast', {
|
|
299
|
+
phase: 'post-decide',
|
|
300
|
+
kind,
|
|
301
|
+
label,
|
|
302
|
+
attempt: scope.attempt,
|
|
303
|
+
providerUsed: scope.currentProvider,
|
|
304
|
+
errorKind: scope.errorKind,
|
|
305
|
+
...(scope.error?.message !== undefined && { errorMessage: scope.error.message }),
|
|
306
|
+
});
|
|
307
|
+
scope.$break(`reliability-post-decide: ${label}`);
|
|
308
|
+
};
|
|
309
|
+
// ─── Compose the chart ───────────────────────────────────────
|
|
310
|
+
// The chart starts with an Init stage that seeds the MUTABLE scope
|
|
311
|
+
// state (attempt, providerIdx, errorKind, attemptsPerProvider, etc.).
|
|
312
|
+
// We can't seed mutable state via inputMapper because inputMapper
|
|
313
|
+
// supplies READ-ONLY inputs (the subflow's "args"). Instead, only
|
|
314
|
+
// truly-readonly inputs (request, providersCount, hasFallback,
|
|
315
|
+
// cumulativeCostUsd) come via inputMapper; the rest is initialized
|
|
316
|
+
// here.
|
|
317
|
+
return flowChart('Init', (scope) => {
|
|
318
|
+
// Seed mutable state. Read-only inputs (request, providersCount,
|
|
319
|
+
// hasFallback, cumulativeCostUsd, AND incomingBreakerStates) come
|
|
320
|
+
// via inputMapper and are accessible via $getArgs(); only mutable
|
|
321
|
+
// fields seeded into scope here.
|
|
322
|
+
const args = scope.$getArgs();
|
|
323
|
+
scope.attempt = 0;
|
|
324
|
+
scope.providerIdx = 0;
|
|
325
|
+
scope.currentProvider = providers[0]?.name ?? '';
|
|
326
|
+
scope.canSwitchProvider = providers.length > 1;
|
|
327
|
+
scope.errorKind = 'ok';
|
|
328
|
+
scope.latencyMs = 0;
|
|
329
|
+
scope.attemptsPerProvider = {};
|
|
330
|
+
// Breaker state restoration: if the agent passed prior breaker
|
|
331
|
+
// states (across gate invocations within one ReAct loop, or
|
|
332
|
+
// hydrated from a persistence store), use them; else start fresh.
|
|
333
|
+
// This is the round-trip mechanism that replaces closure state.
|
|
334
|
+
const incoming = args.incomingBreakerStates ?? {};
|
|
335
|
+
scope.breakerStates = {};
|
|
336
|
+
if (breakerConfig !== undefined) {
|
|
337
|
+
for (const p of providers) {
|
|
338
|
+
scope.breakerStates[p.name] = incoming[p.name] ?? initialBreakerState();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}, STAGE_IDS.INIT, undefined, 'Reliability gate state init')
|
|
342
|
+
.addDeciderFunction('PreCheck', preCheckDeciderFn, STAGE_IDS.PRE_CHECK, 'Reliability: pre-call rule check')
|
|
343
|
+
.addFunctionBranch(BRANCH_IDS.PRE_CONTINUE, 'PreContinue', () => { })
|
|
344
|
+
.addFunctionBranch(BRANCH_IDS.PRE_FAIL_FAST, 'PreFailFast', preFailFastBranchFn)
|
|
345
|
+
.setDefault(BRANCH_IDS.PRE_CONTINUE)
|
|
346
|
+
.end()
|
|
347
|
+
.addFunction('CallProvider', callProviderStageFn, STAGE_IDS.CALL_PROVIDER, 'Invoke LLM provider; capture response/error to scope')
|
|
348
|
+
.addDeciderFunction('PostDecide', postDecideDeciderFn, STAGE_IDS.POST_DECIDE, 'Reliability: post-call rule check')
|
|
349
|
+
.addFunctionBranch(BRANCH_IDS.POST_OK, 'PostOk', okBranchFn)
|
|
350
|
+
.addFunctionBranch(BRANCH_IDS.POST_RETRY, 'PostRetry', retryBranchFn)
|
|
351
|
+
.addFunctionBranch(BRANCH_IDS.POST_RETRY_OTHER, 'PostRetryOther', retryOtherBranchFn)
|
|
352
|
+
.addFunctionBranch(BRANCH_IDS.POST_FALLBACK, 'PostFallback', fallbackBranchFn)
|
|
353
|
+
.addFunctionBranch(BRANCH_IDS.POST_FAIL_FAST, 'PostFailFast', failFastBranchFn)
|
|
354
|
+
.setDefault(BRANCH_IDS.POST_OK)
|
|
355
|
+
.end()
|
|
356
|
+
.loopTo(STAGE_IDS.PRE_CHECK)
|
|
357
|
+
.build();
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=buildReliabilityGateChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildReliabilityGateChart.js","sourceRoot":"","sources":["../../../src/reliability/buildReliabilityGateChart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* classifyError — pure function mapping a thrown error to one of the
|
|
3
|
+
* coarse `ReliabilityScope.errorKind` categories used by reliability rules.
|
|
4
|
+
*
|
|
5
|
+
* Centralized so rules read structured `errorKind` instead of doing
|
|
6
|
+
* regex on `error.message` themselves. Add new categories ONLY when a
|
|
7
|
+
* new rule needs to discriminate them — keep the taxonomy small.
|
|
8
|
+
*
|
|
9
|
+
* Categories:
|
|
10
|
+
* • 'ok' — no error (caller should pass `undefined` or omit)
|
|
11
|
+
* • 'circuit-open' — `CircuitOpenError` from the breaker layer
|
|
12
|
+
* • 'rate-limit' — HTTP 429 or vendor rate-limit signal
|
|
13
|
+
* • '5xx-transient' — HTTP 5xx, ETIMEDOUT, ECONNRESET, ECONNREFUSED
|
|
14
|
+
* • 'schema-fail' — `OutputSchemaError` from the schema validator
|
|
15
|
+
* • 'unknown' — anything else (default; still routable but
|
|
16
|
+
* consumers usually `'fail-fast'` on this)
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Classify an error into a `ReliabilityScope['errorKind']` category.
|
|
20
|
+
*
|
|
21
|
+
* @param err - The thrown value. May be an Error, a vendor SDK error
|
|
22
|
+
* shape with `.status`/`.code`, or anything else (`unknown` defaults).
|
|
23
|
+
* @returns the matching coarse category string.
|
|
24
|
+
*/
|
|
25
|
+
export function classifyError(err) {
|
|
26
|
+
if (err === undefined || err === null)
|
|
27
|
+
return 'ok';
|
|
28
|
+
const e = err;
|
|
29
|
+
// Circuit breaker tripped — most specific check first
|
|
30
|
+
if (e.code === 'ERR_CIRCUIT_OPEN')
|
|
31
|
+
return 'circuit-open';
|
|
32
|
+
// Output schema validation failure — common after LLM produces
|
|
33
|
+
// malformed JSON when an outputSchema is configured
|
|
34
|
+
if (e.code === 'ERR_OUTPUT_SCHEMA')
|
|
35
|
+
return 'schema-fail';
|
|
36
|
+
// HTTP status discrimination (status OR statusCode — vendors differ)
|
|
37
|
+
const status = e.status ?? e.statusCode;
|
|
38
|
+
if (typeof status === 'number') {
|
|
39
|
+
if (status === 429)
|
|
40
|
+
return 'rate-limit';
|
|
41
|
+
if (status >= 500 && status < 600)
|
|
42
|
+
return '5xx-transient';
|
|
43
|
+
}
|
|
44
|
+
// String-based detection for transient network errors that don't
|
|
45
|
+
// carry a status code (Node's net/dns error shapes)
|
|
46
|
+
const msg = (e.message ?? '').toString();
|
|
47
|
+
if (/(ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up)/i.test(msg)) {
|
|
48
|
+
return '5xx-transient';
|
|
49
|
+
}
|
|
50
|
+
// Some vendor SDKs include "rate limit" in the message even when status
|
|
51
|
+
// is null (e.g., on streaming pipelines that surface errors mid-stream)
|
|
52
|
+
if (/rate.?limit|too many requests/i.test(msg))
|
|
53
|
+
return 'rate-limit';
|
|
54
|
+
return 'unknown';
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=classifyError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classifyError.js","sourceRoot":"","sources":["../../../src/reliability/classifyError.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEnD,MAAM,CAAC,GAAG,GAAgB,CAAC;IAE3B,sDAAsD;IACtD,IAAI,CAAC,CAAC,IAAI,KAAK,kBAAkB;QAAE,OAAO,cAAc,CAAC;IAEzD,+DAA+D;IAC/D,oDAAoD;IACpD,IAAI,CAAC,CAAC,IAAI,KAAK,mBAAmB;QAAE,OAAO,aAAa,CAAC;IAEzD,qEAAqE;IACrE,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,UAAU,CAAC;IACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,YAAY,CAAC;QACxC,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;YAAE,OAAO,eAAe,CAAC;IAC5D,CAAC;IAED,iEAAiE;IACjE,oDAAoD;IACpD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzC,IAAI,+DAA+D,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9E,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,wEAAwE;IACxE,wEAAwE;IACxE,IAAI,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,YAAY,CAAC;IAEpE,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reliability — public surface for the v2.11.1 rules-based reliability
|
|
3
|
+
* subsystem. Internal-only helpers (CircuitBreaker class, classifyError,
|
|
4
|
+
* buildReliabilityGate) live in their own files; this barrel exports
|
|
5
|
+
* the consumer-facing types and the typed error.
|
|
6
|
+
*
|
|
7
|
+
* Consumer use:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Agent } from 'agentfootprint';
|
|
10
|
+
* import type { ReliabilityRule, ReliabilityScope } from 'agentfootprint/reliability';
|
|
11
|
+
* import { ReliabilityFailFastError } from 'agentfootprint/reliability';
|
|
12
|
+
*
|
|
13
|
+
* const agent = Agent.create({...}).reliability({
|
|
14
|
+
* postDecide: [
|
|
15
|
+
* { when: (s) => s.errorKind === '5xx-transient' && s.attempt < 3,
|
|
16
|
+
* then: 'retry', kind: 'transient-retry' },
|
|
17
|
+
* { when: (s) => s.error !== undefined,
|
|
18
|
+
* then: 'fail-fast', kind: 'unrecoverable' },
|
|
19
|
+
* ],
|
|
20
|
+
* }).build();
|
|
21
|
+
*
|
|
22
|
+
* try {
|
|
23
|
+
* await agent.run({ message: '...' });
|
|
24
|
+
* } catch (e) {
|
|
25
|
+
* if (e instanceof ReliabilityFailFastError) {
|
|
26
|
+
* console.log(e.kind, e.reason);
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export { ReliabilityFailFastError } from './types.js';
|
|
32
|
+
// CircuitBreaker pure-state-machine surface — exposed so consumers can
|
|
33
|
+
// hydrate breaker state from a persistence store (Redis/DynamoDB) or
|
|
34
|
+
// inspect projected state in their own observability adapters.
|
|
35
|
+
export { CircuitOpenError, initialBreakerState, } from './CircuitBreaker.js';
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/reliability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAYH,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,uEAAuE;AACvE,qEAAqE;AACrE,+DAA+D;AAC/D,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// ─── Public typed error ──────────────────────────────────────────────
|
|
2
|
+
/**
|
|
3
|
+
* Thrown by `Agent.run()` when a reliability rule routes to `'fail-fast'`
|
|
4
|
+
* and the gate $breaks with a reason. Carries:
|
|
5
|
+
*
|
|
6
|
+
* • `kind` — machine-readable identifier from the matched rule's
|
|
7
|
+
* `kind` field. Stable across versions; consumers
|
|
8
|
+
* branch on this.
|
|
9
|
+
* • `reason` — human-readable narrative string from `$break(reason)`.
|
|
10
|
+
* Format: `'reliability-{phase}: {label}'` (e.g.,
|
|
11
|
+
* `'reliability-post-decide: cost-cap-exceeded'`).
|
|
12
|
+
* • `cause` — the originating error from the LLM call, when one
|
|
13
|
+
* drove the fail-fast decision (e.g., the underlying
|
|
14
|
+
* HTTP error that tripped a circuit breaker).
|
|
15
|
+
* • `snapshot` — the full `executor.getSnapshot()` at fail-fast time
|
|
16
|
+
* for forensics. Consumers persist this for postmortem
|
|
17
|
+
* analysis (commitLog, narrative, scope state, etc.).
|
|
18
|
+
*
|
|
19
|
+
* Three-channel discipline: `kind`/`payload` came from scope state,
|
|
20
|
+
* `reason` came from $break, `snapshot` is the engine's own audit trail.
|
|
21
|
+
* Emit events flowed independently to any attached observability adapter
|
|
22
|
+
* (this error is the RUNTIME signal; emit is the OBSERVABILITY signal).
|
|
23
|
+
*/
|
|
24
|
+
export class ReliabilityFailFastError extends Error {
|
|
25
|
+
code = 'ERR_RELIABILITY_FAIL_FAST';
|
|
26
|
+
kind;
|
|
27
|
+
reason;
|
|
28
|
+
cause;
|
|
29
|
+
snapshot;
|
|
30
|
+
payload;
|
|
31
|
+
constructor(opts) {
|
|
32
|
+
super(`[reliability] ${opts.kind}: ${opts.reason}`);
|
|
33
|
+
this.name = 'ReliabilityFailFastError';
|
|
34
|
+
this.kind = opts.kind;
|
|
35
|
+
this.reason = opts.reason;
|
|
36
|
+
if (opts.cause !== undefined)
|
|
37
|
+
this.cause = opts.cause;
|
|
38
|
+
if (opts.snapshot !== undefined)
|
|
39
|
+
this.snapshot = opts.snapshot;
|
|
40
|
+
if (opts.payload !== undefined)
|
|
41
|
+
this.payload = opts.payload;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/reliability/types.ts"],"names":[],"mappings":"AA2QA,wEAAwE;AAExE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACxC,IAAI,GAAG,2BAAoC,CAAC;IAC5C,IAAI,CAAS;IACb,MAAM,CAAS;IACf,KAAK,CAAS;IACd,QAAQ,CAAW;IACnB,OAAO,CAAmC;IAEnD,YAAY,IAMX;QACC,KAAK,CAAC,iBAAiB,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACtD,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;YAAE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/D,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;YAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC9D,CAAC;CACF"}
|