agentfootprint 9.94.3 → 9.96.1
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/CHANGELOG.md +48 -0
- package/CLAUDE.md +4 -1
- package/dist/answer-validation/evidence.js +121 -0
- package/dist/answer-validation/evidence.js.map +1 -0
- package/dist/answer-validation/index.js +10 -0
- package/dist/answer-validation/index.js.map +1 -0
- package/dist/answer-validation/types.js +24 -0
- package/dist/answer-validation/types.js.map +1 -0
- package/dist/answer-validation/validate.js +326 -0
- package/dist/answer-validation/validate.js.map +1 -0
- package/dist/core/Agent.js +93 -3
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +27 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +17 -2
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +27 -2
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/evidence/gate.js +13 -1
- package/dist/core/agent/evidence/gate.js.map +1 -1
- package/dist/core/agent/evidence/recovery.js +75 -0
- package/dist/core/agent/evidence/recovery.js.map +1 -0
- package/dist/core/agent/outputEnforcement.js.map +1 -1
- package/dist/core/agent/stages/answerValidation.js +57 -0
- package/dist/core/agent/stages/answerValidation.js.map +1 -0
- package/dist/core/agent/stages/breakFinal.js +11 -1
- package/dist/core/agent/stages/breakFinal.js.map +1 -1
- package/dist/core/agent/stages/callLLM.js +31 -8
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/evidenceRecheck.js +12 -22
- package/dist/core/agent/stages/evidenceRecheck.js.map +1 -1
- package/dist/core/agent/stages/prepareFinal.js +35 -2
- package/dist/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/core/agent/stages/route.js +9 -5
- package/dist/core/agent/stages/route.js.map +1 -1
- package/dist/core/agent/stages/seed.js +6 -1
- package/dist/core/agent/stages/seed.js.map +1 -1
- package/dist/core/runCheckpoint.js +22 -1
- package/dist/core/runCheckpoint.js.map +1 -1
- package/dist/esm/answer-validation/evidence.d.ts +12 -0
- package/dist/esm/answer-validation/evidence.js +117 -0
- package/dist/esm/answer-validation/evidence.js.map +1 -0
- package/dist/esm/answer-validation/index.d.ts +3 -0
- package/dist/esm/answer-validation/index.js +4 -0
- package/dist/esm/answer-validation/index.js.map +1 -0
- package/dist/esm/answer-validation/types.d.ts +94 -0
- package/dist/esm/answer-validation/types.js +20 -0
- package/dist/esm/answer-validation/types.js.map +1 -0
- package/dist/esm/answer-validation/validate.d.ts +15 -0
- package/dist/esm/answer-validation/validate.js +321 -0
- package/dist/esm/answer-validation/validate.js.map +1 -0
- package/dist/esm/core/Agent.d.ts +10 -1
- package/dist/esm/core/Agent.js +93 -3
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +11 -0
- package/dist/esm/core/agent/AgentBuilder.js +27 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/buildAgentChart.d.ts +2 -0
- package/dist/esm/core/agent/buildAgentChart.js +19 -4
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +29 -4
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/evidence/gate.js +13 -1
- package/dist/esm/core/agent/evidence/gate.js.map +1 -1
- package/dist/esm/core/agent/evidence/index.d.ts +1 -1
- package/dist/esm/core/agent/evidence/recovery.d.ts +21 -0
- package/dist/esm/core/agent/evidence/recovery.js +69 -0
- package/dist/esm/core/agent/evidence/recovery.js.map +1 -0
- package/dist/esm/core/agent/evidence/types.d.ts +30 -0
- package/dist/esm/core/agent/outputEnforcement.d.ts +2 -0
- package/dist/esm/core/agent/outputEnforcement.js.map +1 -1
- package/dist/esm/core/agent/stages/answerValidation.d.ts +10 -0
- package/dist/esm/core/agent/stages/answerValidation.js +53 -0
- package/dist/esm/core/agent/stages/answerValidation.js.map +1 -0
- package/dist/esm/core/agent/stages/breakFinal.d.ts +6 -0
- package/dist/esm/core/agent/stages/breakFinal.js +9 -0
- package/dist/esm/core/agent/stages/breakFinal.js.map +1 -1
- package/dist/esm/core/agent/stages/callLLM.d.ts +4 -0
- package/dist/esm/core/agent/stages/callLLM.js +31 -8
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/evidenceRecheck.d.ts +3 -6
- package/dist/esm/core/agent/stages/evidenceRecheck.js +13 -23
- package/dist/esm/core/agent/stages/evidenceRecheck.js.map +1 -1
- package/dist/esm/core/agent/stages/prepareFinal.d.ts +7 -0
- package/dist/esm/core/agent/stages/prepareFinal.js +33 -1
- package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/core/agent/stages/route.js +9 -5
- package/dist/esm/core/agent/stages/route.js.map +1 -1
- package/dist/esm/core/agent/stages/seed.d.ts +3 -0
- package/dist/esm/core/agent/stages/seed.js +6 -1
- package/dist/esm/core/agent/stages/seed.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +12 -1
- package/dist/esm/core/runCheckpoint.d.ts +17 -1
- package/dist/esm/core/runCheckpoint.js +22 -1
- package/dist/esm/core/runCheckpoint.js.map +1 -1
- package/dist/esm/events/types.d.ts +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/time-travel/servedView.js +5 -2
- package/dist/esm/lib/time-travel/servedView.js.map +1 -1
- package/dist/esm/recorders/core/contextEngineering.js +1 -0
- package/dist/esm/recorders/core/contextEngineering.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/time-travel/servedView.js +5 -2
- package/dist/lib/time-travel/servedView.js.map +1 -1
- package/dist/recorders/core/contextEngineering.js +1 -0
- package/dist/recorders/core/contextEngineering.js.map +1 -1
- package/dist/types/answer-validation/evidence.d.ts +13 -0
- package/dist/types/answer-validation/evidence.d.ts.map +1 -0
- package/dist/types/answer-validation/index.d.ts +4 -0
- package/dist/types/answer-validation/index.d.ts.map +1 -0
- package/dist/types/answer-validation/types.d.ts +95 -0
- package/dist/types/answer-validation/types.d.ts.map +1 -0
- package/dist/types/answer-validation/validate.d.ts +16 -0
- package/dist/types/answer-validation/validate.d.ts.map +1 -0
- package/dist/types/core/Agent.d.ts +10 -1
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +11 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +2 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/gate.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/index.d.ts +1 -1
- package/dist/types/core/agent/evidence/index.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/recovery.d.ts +22 -0
- package/dist/types/core/agent/evidence/recovery.d.ts.map +1 -0
- package/dist/types/core/agent/evidence/types.d.ts +30 -0
- package/dist/types/core/agent/evidence/types.d.ts.map +1 -1
- package/dist/types/core/agent/outputEnforcement.d.ts +2 -0
- package/dist/types/core/agent/outputEnforcement.d.ts.map +1 -1
- package/dist/types/core/agent/stages/answerValidation.d.ts +11 -0
- package/dist/types/core/agent/stages/answerValidation.d.ts.map +1 -0
- package/dist/types/core/agent/stages/breakFinal.d.ts +6 -0
- package/dist/types/core/agent/stages/breakFinal.d.ts.map +1 -1
- package/dist/types/core/agent/stages/callLLM.d.ts +4 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/evidenceRecheck.d.ts +3 -6
- package/dist/types/core/agent/stages/evidenceRecheck.d.ts.map +1 -1
- package/dist/types/core/agent/stages/prepareFinal.d.ts +7 -0
- package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
- package/dist/types/core/agent/stages/seed.d.ts +3 -0
- package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +12 -1
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/runCheckpoint.d.ts +17 -1
- package/dist/types/core/runCheckpoint.d.ts.map +1 -1
- package/dist/types/events/types.d.ts +1 -1
- package/dist/types/events/types.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
- package/dist/types/recorders/core/contextEngineering.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/** One explicit JSON-answer validation; the runner owns when to invoke it. */
|
|
2
|
+
import { applyOutputSchema } from '../core/outputSchema.js';
|
|
3
|
+
import { computeArtifactDigest } from '../artifacts/payload.js';
|
|
4
|
+
import { createAnswerEvidenceResolver } from './evidence.js';
|
|
5
|
+
const DEFAULT_LIMITS = Object.freeze({
|
|
6
|
+
maxReads: 16,
|
|
7
|
+
maxBytes: 4 * 1024 * 1024,
|
|
8
|
+
maxChecks: 100,
|
|
9
|
+
maxCandidateBytes: 1024 * 1024,
|
|
10
|
+
timeoutMs: 5000,
|
|
11
|
+
});
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
const dispositions = new Set(['checked-pass', 'checked-fail', 'not-applicable', 'unreachable']);
|
|
14
|
+
function ownData(value, allowed) {
|
|
15
|
+
if (value === null ||
|
|
16
|
+
typeof value !== 'object' ||
|
|
17
|
+
Array.isArray(value) ||
|
|
18
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value)))
|
|
19
|
+
throw new Error('Expected a plain data object.');
|
|
20
|
+
const result = Object.create(null);
|
|
21
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
22
|
+
if (typeof key !== 'string' || (allowed && !allowed.includes(key)))
|
|
23
|
+
throw new Error('Unknown property.');
|
|
24
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
25
|
+
if (!descriptor?.enumerable || !('value' in descriptor))
|
|
26
|
+
throw new Error('Expected an enumerable data property.');
|
|
27
|
+
Object.defineProperty(result, key, { value: descriptor.value, enumerable: true });
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
function text(value, max) {
|
|
32
|
+
if (typeof value !== 'string' || value.trim() === '' || value.length > max)
|
|
33
|
+
throw new Error('Expected bounded non-empty text.');
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
/** Validate and snapshot an authored contract once, before running an agent. */
|
|
37
|
+
export function resolveAnswerValidation(options) {
|
|
38
|
+
const source = ownData(options, ['id', 'version', 'mode', 'limits', 'validate']);
|
|
39
|
+
const id = text(source.id, 128);
|
|
40
|
+
const version = text(source.version, 128);
|
|
41
|
+
const mode = source.mode === undefined ? 'enforce' : source.mode;
|
|
42
|
+
if (mode !== 'enforce' && mode !== 'observe')
|
|
43
|
+
throw new Error('answerValidation.mode must be enforce or observe.');
|
|
44
|
+
if (typeof source.validate !== 'function')
|
|
45
|
+
throw new Error('answerValidation.validate must be a function.');
|
|
46
|
+
const validate = source.validate;
|
|
47
|
+
const supplied = source.limits === undefined ? {} : ownData(source.limits, Object.keys(DEFAULT_LIMITS));
|
|
48
|
+
const limits = { ...DEFAULT_LIMITS };
|
|
49
|
+
for (const key of Object.keys(DEFAULT_LIMITS)) {
|
|
50
|
+
if (Object.hasOwn(supplied, key)) {
|
|
51
|
+
const value = supplied[key];
|
|
52
|
+
if (typeof value !== 'number' ||
|
|
53
|
+
!Number.isSafeInteger(value) ||
|
|
54
|
+
value <= 0 ||
|
|
55
|
+
(key === 'timeoutMs' && value > 2147483647))
|
|
56
|
+
throw new Error(`answerValidation.limits.${key} must be a positive bounded integer.`);
|
|
57
|
+
limits[key] = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return Object.freeze({
|
|
61
|
+
id,
|
|
62
|
+
version,
|
|
63
|
+
mode,
|
|
64
|
+
limits: Object.freeze(limits),
|
|
65
|
+
validate: (candidate, context) => validate(candidate, context),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** JSON copy without invoking toJSON/getters or silently dropping data. */
|
|
69
|
+
function jsonCopy(value, maxBytes, freeze) {
|
|
70
|
+
let budget = maxBytes;
|
|
71
|
+
const ancestors = new Set();
|
|
72
|
+
const spend = (bytes) => {
|
|
73
|
+
budget -= bytes;
|
|
74
|
+
if (budget < 0)
|
|
75
|
+
throw new Error('JSON byte limit.');
|
|
76
|
+
};
|
|
77
|
+
const string = (item) => {
|
|
78
|
+
if (item.length > budget)
|
|
79
|
+
throw new Error('JSON byte limit.');
|
|
80
|
+
spend(encoder.encode(JSON.stringify(item)).byteLength);
|
|
81
|
+
};
|
|
82
|
+
const copy = (item, depth) => {
|
|
83
|
+
if (depth > 100)
|
|
84
|
+
throw new Error('JSON nesting limit.');
|
|
85
|
+
if (item === null) {
|
|
86
|
+
spend(4);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (typeof item === 'string') {
|
|
90
|
+
string(item);
|
|
91
|
+
return item;
|
|
92
|
+
}
|
|
93
|
+
if (typeof item === 'boolean') {
|
|
94
|
+
spend(item ? 4 : 5);
|
|
95
|
+
return item;
|
|
96
|
+
}
|
|
97
|
+
if (typeof item === 'number') {
|
|
98
|
+
if (!Number.isFinite(item) || Object.is(item, -0))
|
|
99
|
+
throw new Error('Non-lossless JSON number.');
|
|
100
|
+
spend(JSON.stringify(item).length);
|
|
101
|
+
return item;
|
|
102
|
+
}
|
|
103
|
+
if (typeof item !== 'object')
|
|
104
|
+
throw new Error('Non-JSON value.');
|
|
105
|
+
if (ancestors.has(item))
|
|
106
|
+
throw new Error('Cyclic JSON value.');
|
|
107
|
+
ancestors.add(item);
|
|
108
|
+
spend(2);
|
|
109
|
+
let output;
|
|
110
|
+
if (Array.isArray(item)) {
|
|
111
|
+
if (Object.getPrototypeOf(item) !== Array.prototype)
|
|
112
|
+
throw new Error('Non-JSON array prototype.');
|
|
113
|
+
if (item.length > budget + 1)
|
|
114
|
+
throw new Error('JSON byte limit.');
|
|
115
|
+
const keys = Reflect.ownKeys(item);
|
|
116
|
+
if (keys.length !== item.length + 1)
|
|
117
|
+
throw new Error('Sparse or decorated array.');
|
|
118
|
+
const result = [];
|
|
119
|
+
for (let index = 0; index < item.length; index++) {
|
|
120
|
+
const descriptor = Object.getOwnPropertyDescriptor(item, String(index));
|
|
121
|
+
if (!descriptor?.enumerable || !('value' in descriptor))
|
|
122
|
+
throw new Error('Sparse or accessor array.');
|
|
123
|
+
if (index)
|
|
124
|
+
spend(1);
|
|
125
|
+
result.push(copy(descriptor.value, depth + 1));
|
|
126
|
+
}
|
|
127
|
+
output = result;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const fields = ownData(item);
|
|
131
|
+
const result = {};
|
|
132
|
+
let index = 0;
|
|
133
|
+
for (const key of Object.keys(fields)) {
|
|
134
|
+
if (index++)
|
|
135
|
+
spend(1);
|
|
136
|
+
string(key);
|
|
137
|
+
spend(1);
|
|
138
|
+
Object.defineProperty(result, key, {
|
|
139
|
+
value: copy(fields[key], depth + 1),
|
|
140
|
+
enumerable: true,
|
|
141
|
+
writable: true,
|
|
142
|
+
configurable: true,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
output = result;
|
|
146
|
+
}
|
|
147
|
+
ancestors.delete(item);
|
|
148
|
+
return freeze ? Object.freeze(output) : output;
|
|
149
|
+
};
|
|
150
|
+
return copy(value, 0);
|
|
151
|
+
}
|
|
152
|
+
function readChecks(value, config, resolved) {
|
|
153
|
+
// Bound before copying. The copy rejects getters, class instances, cycles,
|
|
154
|
+
// decorated arrays and values JSON would otherwise silently discard.
|
|
155
|
+
const source = ownData(value, ['checks']);
|
|
156
|
+
if (!Array.isArray(source.checks) || source.checks.length > config.limits.maxChecks)
|
|
157
|
+
throw new Error('Invalid checks.');
|
|
158
|
+
const detached = jsonCopy(source.checks, config.limits.maxChecks * 4096, false);
|
|
159
|
+
const ids = new Set();
|
|
160
|
+
const refs = new Set(resolved);
|
|
161
|
+
return detached.map((raw) => {
|
|
162
|
+
const check = ownData(raw, ['id', 'disposition', 'reason', 'path', 'evidenceRefs']);
|
|
163
|
+
const id = text(check.id, 128);
|
|
164
|
+
if (ids.has(id) ||
|
|
165
|
+
typeof check.disposition !== 'string' ||
|
|
166
|
+
!dispositions.has(check.disposition))
|
|
167
|
+
throw new Error('Invalid check identity or disposition.');
|
|
168
|
+
ids.add(id);
|
|
169
|
+
const reason = check.reason === undefined ? undefined : text(check.reason, 1024);
|
|
170
|
+
const path = check.path;
|
|
171
|
+
if (path !== undefined && (typeof path !== 'string' || path.length > 256))
|
|
172
|
+
throw new Error('Invalid check path.');
|
|
173
|
+
let evidenceRefs;
|
|
174
|
+
if (check.evidenceRefs !== undefined) {
|
|
175
|
+
if (!Array.isArray(check.evidenceRefs) || check.evidenceRefs.length > config.limits.maxReads)
|
|
176
|
+
throw new Error('Invalid evidence references.');
|
|
177
|
+
evidenceRefs = check.evidenceRefs.map((ref) => {
|
|
178
|
+
if (typeof ref !== 'string' || !refs.has(ref))
|
|
179
|
+
throw new Error('Unresolved evidence reference.');
|
|
180
|
+
return ref;
|
|
181
|
+
});
|
|
182
|
+
if (new Set(evidenceRefs).size !== evidenceRefs.length)
|
|
183
|
+
throw new Error('Duplicate evidence reference.');
|
|
184
|
+
}
|
|
185
|
+
return Object.freeze({
|
|
186
|
+
id,
|
|
187
|
+
disposition: check.disposition,
|
|
188
|
+
...(reason !== undefined && { reason }),
|
|
189
|
+
...(path !== undefined && { path }),
|
|
190
|
+
...(evidenceRefs !== undefined && { evidenceRefs: Object.freeze(evidenceRefs) }),
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Validate once. Content is present only when delivery is permitted by this
|
|
196
|
+
* contract. It is the exact JSON string whose detached value was checked;
|
|
197
|
+
* callers must not reparse through a transforming schema or rewrite afterward.
|
|
198
|
+
*/
|
|
199
|
+
export async function executeAnswerValidation(raw, parser, config, store, scope, signal) {
|
|
200
|
+
const controller = new AbortController();
|
|
201
|
+
const evidence = createAnswerEvidenceResolver(store, scope, config.limits, controller.signal);
|
|
202
|
+
let reason;
|
|
203
|
+
let schemaAccepted = false;
|
|
204
|
+
let canonical;
|
|
205
|
+
let candidateDigest;
|
|
206
|
+
let checks = [];
|
|
207
|
+
let active = true;
|
|
208
|
+
let stop;
|
|
209
|
+
const abort = () => {
|
|
210
|
+
reason = 'aborted';
|
|
211
|
+
controller.abort();
|
|
212
|
+
stop?.();
|
|
213
|
+
};
|
|
214
|
+
const timedOut = () => {
|
|
215
|
+
reason = 'timeout';
|
|
216
|
+
controller.abort();
|
|
217
|
+
stop?.();
|
|
218
|
+
};
|
|
219
|
+
const deadline = Date.now() + config.limits.timeoutMs;
|
|
220
|
+
const timer = setTimeout(timedOut, config.limits.timeoutMs);
|
|
221
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
222
|
+
if (signal?.aborted)
|
|
223
|
+
abort();
|
|
224
|
+
try {
|
|
225
|
+
const interrupted = new Promise((resolve) => {
|
|
226
|
+
stop = resolve;
|
|
227
|
+
if (controller.signal.aborted)
|
|
228
|
+
resolve();
|
|
229
|
+
});
|
|
230
|
+
const work = async () => {
|
|
231
|
+
if (controller.signal.aborted)
|
|
232
|
+
return;
|
|
233
|
+
let candidate;
|
|
234
|
+
try {
|
|
235
|
+
if (raw.length > config.limits.maxCandidateBytes ||
|
|
236
|
+
encoder.encode(raw).byteLength > config.limits.maxCandidateBytes) {
|
|
237
|
+
reason = 'candidate-limit';
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
candidate = applyOutputSchema(raw, parser);
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
reason = 'schema-rejected';
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
candidate = jsonCopy(candidate, config.limits.maxCandidateBytes, true);
|
|
248
|
+
canonical = JSON.stringify(candidate);
|
|
249
|
+
schemaAccepted = true;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
reason = 'non-json-candidate';
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
if (Date.now() >= deadline) {
|
|
256
|
+
timedOut();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
try {
|
|
260
|
+
const digest = await computeArtifactDigest(canonical);
|
|
261
|
+
if (!active || controller.signal.aborted)
|
|
262
|
+
return;
|
|
263
|
+
candidateDigest = digest;
|
|
264
|
+
const returned = await config.validate(candidate, Object.freeze({ signal: controller.signal, artifacts: evidence.resolver }));
|
|
265
|
+
if (!active || controller.signal.aborted)
|
|
266
|
+
return;
|
|
267
|
+
if (Date.now() >= deadline) {
|
|
268
|
+
timedOut();
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
try {
|
|
272
|
+
checks = readChecks(returned, config, evidence.resolvedRefs());
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
reason = 'invalid-validator-result';
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
if (active && !controller.signal.aborted)
|
|
280
|
+
reason = 'validator-error';
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
await Promise.race([work(), interrupted]);
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
active = false;
|
|
287
|
+
clearTimeout(timer);
|
|
288
|
+
signal?.removeEventListener('abort', abort);
|
|
289
|
+
evidence.close();
|
|
290
|
+
controller.abort();
|
|
291
|
+
}
|
|
292
|
+
const failed = checks.filter((check) => check.disposition === 'checked-fail').length;
|
|
293
|
+
const checked = failed + checks.filter((check) => check.disposition === 'checked-pass').length;
|
|
294
|
+
const unreachable = checks.filter((check) => check.disposition === 'unreachable').length;
|
|
295
|
+
const notApplicable = checks.filter((check) => check.disposition === 'not-applicable').length;
|
|
296
|
+
if (!reason && evidence.failureReason())
|
|
297
|
+
reason = `evidence-${evidence.failureReason()}`;
|
|
298
|
+
if (!reason && checked === 0)
|
|
299
|
+
reason = 'no-comparable-checks';
|
|
300
|
+
if (!reason && unreachable > 0)
|
|
301
|
+
reason = 'unreachable-checks';
|
|
302
|
+
const status = reason ? 'unverified' : failed > 0 ? 'failed' : 'passed';
|
|
303
|
+
const report = Object.freeze({
|
|
304
|
+
validatorId: config.id,
|
|
305
|
+
validatorVersion: config.version,
|
|
306
|
+
mode: config.mode,
|
|
307
|
+
status,
|
|
308
|
+
checked,
|
|
309
|
+
failed,
|
|
310
|
+
unreachable,
|
|
311
|
+
notApplicable,
|
|
312
|
+
checks: Object.freeze(checks),
|
|
313
|
+
schemaAccepted,
|
|
314
|
+
...(reason !== undefined && { reason }),
|
|
315
|
+
...(candidateDigest !== undefined && { candidateDigest }),
|
|
316
|
+
resolvedRefs: Object.freeze(evidence.resolvedRefs()),
|
|
317
|
+
});
|
|
318
|
+
const content = status === 'passed' || config.mode === 'observe' ? canonical ?? raw : undefined;
|
|
319
|
+
return { report, ...(content !== undefined && { content }) };
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/answer-validation/validate.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAA2B,MAAM,yBAAyB,CAAC;AAErF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAS7D,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IACzB,SAAS,EAAE,GAAG;IACd,iBAAiB,EAAE,IAAI,GAAG,IAAI;IAC9B,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AACH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC,CAAC;AAEhG,SAAS,OAAO,CAAC,KAAc,EAAE,OAA2B;IAC1D,IACE,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACpB,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAEhE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,MAAM,MAAM,GAA4B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA4B,CAAC;IACvF,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAChE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,IAAI,CAAC,KAAc,EAAE,GAAW;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;QACxE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,uBAAuB,CACrC,OAAmC;IAEnC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IACjF,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IACjE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;QAC1C,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU;QACvC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAkD,CAAC;IAC3E,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACzF,MAAM,MAAM,GAA6D,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/F,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAuC,EAAE,CAAC;QACpF,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC5B,IACE,OAAO,KAAK,KAAK,QAAQ;gBACzB,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC;gBAC5B,KAAK,IAAI,CAAC;gBACV,CAAC,GAAG,KAAK,WAAW,IAAI,KAAK,GAAG,UAAU,CAAC;gBAE3C,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,sCAAsC,CAAC,CAAC;YACxF,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,EAAE;QACF,OAAO;QACP,IAAI;QACJ,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,QAAQ,EAAE,CAAC,SAAkB,EAAE,OAAgC,EAAE,EAAE,CACjE,QAAQ,CAAC,SAAwB,EAAE,OAAO,CAAC;KAC9C,CAAC,CAAC;AACL,CAAC;AAED,2EAA2E;AAC3E,SAAS,QAAQ,CAAC,KAAc,EAAE,QAAgB,EAAE,MAAe;IACjE,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE;QAC9B,MAAM,IAAI,KAAK,CAAC;QAChB,IAAI,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtD,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;QAC9B,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC9D,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,CAAC,IAAa,EAAE,KAAa,EAAW,EAAE;QACrD,IAAI,KAAK,GAAG,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACxD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,KAAK,CAAC,CAAC,CAAC,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,CAAC;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC/C,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACjE,IAAI,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QAC/D,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,KAAK,CAAC,CAAC,CAAC,CAAC;QACT,IAAI,MAAe,CAAC;QACpB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,SAAS;gBACjD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;YAClE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YACnF,MAAM,MAAM,GAAc,EAAE,CAAC;YAC7B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBACjD,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBACxE,IAAI,CAAC,UAAU,EAAE,UAAU,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC;oBACrD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBAC/C,IAAI,KAAK;oBAAE,KAAK,CAAC,CAAC,CAAC,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YACjD,CAAC;YACD,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM,MAAM,GAA4B,EAAE,CAAC;YAC3C,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,IAAI,KAAK,EAAE;oBAAE,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,CAAC,GAAG,CAAC,CAAC;gBACZ,KAAK,CAAC,CAAC,CAAC,CAAC;gBACT,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE;oBACjC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;oBACnC,UAAU,EAAE,IAAI;oBAChB,QAAQ,EAAE,IAAI;oBACd,YAAY,EAAE,IAAI;iBACnB,CAAC,CAAC;YACL,CAAC;YACD,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC;QACD,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACjD,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,UAAU,CACjB,KAAc,EACd,MAAgC,EAChC,QAA2B;IAE3B,2EAA2E;IAC3E,qEAAqE;IACrE,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS;QACjF,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,EAAE,KAAK,CAAc,CAAC;IAC7F,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;QACpF,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC/B,IACE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ;YACrC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC;YAEpC,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACZ,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,IAAI,YAAkC,CAAC;QACvC,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ;gBAC1F,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,YAAY,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;oBAC3C,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;gBACpD,OAAO,GAAG,CAAC;YACb,CAAC,CAAC,CAAC;YACH,IAAI,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,MAAM;gBACpD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,EAAE;YACF,WAAW,EAAE,KAAK,CAAC,WAAyC;YAC5D,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;YACvC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;YACnC,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;SACjF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAW,EACX,MAAmC,EACnC,MAAgC,EAChC,KAAgC,EAChC,KAAoB,EACpB,MAAoB;IAEpB,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,QAAQ,GAAG,4BAA4B,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAC9F,IAAI,MAA0B,CAAC;IAC/B,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,SAA6B,CAAC;IAClC,IAAI,eAAmC,CAAC;IACxC,IAAI,MAAM,GAAkB,EAAE,CAAC;IAC/B,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,IAA8B,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,MAAM,GAAG,SAAS,CAAC;QACnB,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,EAAE,EAAE,CAAC;IACX,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,MAAM,GAAG,SAAS,CAAC;QACnB,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,EAAE,EAAE,CAAC;IACX,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;IACtD,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5D,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,IAAI,MAAM,EAAE,OAAO;QAAE,KAAK,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAChD,IAAI,GAAG,OAAO,CAAC;YACf,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO,EAAE,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;YACtB,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YACtC,IAAI,SAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,IACE,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB;oBAC5C,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAChE,CAAC;oBACD,MAAM,GAAG,iBAAiB,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBACD,SAAS,GAAG,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,iBAAiB,CAAC;gBAC3B,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,SAAS,GAAG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;gBACvE,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;gBACtC,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,oBAAoB,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC3B,QAAQ,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC,CAAC;gBACtD,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,OAAO;gBACjD,eAAe,GAAG,MAAM,CAAC;gBACzB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CACpC,SAAS,EACT,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAC3E,CAAC;gBACF,IAAI,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,OAAO;gBACjD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;oBAC3B,QAAQ,EAAE,CAAC;oBACX,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC;oBACH,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;gBACjE,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,GAAG,0BAA0B,CAAC;gBACtC,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO;oBAAE,MAAM,GAAG,iBAAiB,CAAC;YACvE,CAAC;QACH,CAAC,CAAC;QACF,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,KAAK,CAAC;QACf,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC5C,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,cAAc,CAAC,CAAC,MAAM,CAAC;IACrF,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,cAAc,CAAC,CAAC,MAAM,CAAC;IAC/F,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,aAAa,CAAC,CAAC,MAAM,CAAC;IACzF,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,gBAAgB,CAAC,CAAC,MAAM,CAAC;IAC9F,IAAI,CAAC,MAAM,IAAI,QAAQ,CAAC,aAAa,EAAE;QAAE,MAAM,GAAG,YAAY,QAAQ,CAAC,aAAa,EAAE,EAAE,CAAC;IACzF,IAAI,CAAC,MAAM,IAAI,OAAO,KAAK,CAAC;QAAE,MAAM,GAAG,sBAAsB,CAAC;IAC9D,IAAI,CAAC,MAAM,IAAI,WAAW,GAAG,CAAC;QAAE,MAAM,GAAG,oBAAoB,CAAC;IAC9D,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxE,MAAM,MAAM,GAA2B,MAAM,CAAC,MAAM,CAAC;QACnD,WAAW,EAAE,MAAM,CAAC,EAAE;QACtB,gBAAgB,EAAE,MAAM,CAAC,OAAO;QAChC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM;QACN,OAAO;QACP,MAAM;QACN,WAAW;QACX,aAAa;QACb,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,cAAc;QACd,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,MAAM,EAAE,CAAC;QACvC,GAAG,CAAC,eAAe,KAAK,SAAS,IAAI,EAAE,eAAe,EAAE,CAAC;QACzD,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;KACrD,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IAChG,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAC/D,CAAC"}
|
package/dist/esm/core/Agent.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ import { RunnerBase } from './RunnerBase.js';
|
|
|
36
36
|
import type { ToolRegistryEntry } from './tools.js';
|
|
37
37
|
import type { ToolProvider } from '../tool-providers/types.js';
|
|
38
38
|
import type { AgentArtifactsOptions, AgentInput, AgentOptions, AgentOutput, AgentRecordingsOptions, AgentState, ObserverDeliveryOptions, RunConfig, RunConfigContext, RunConfigFn, WriteProvenanceMode } from './agent/types.js';
|
|
39
|
+
import { type AnswerValidationReport, type ResolvedAnswerValidation } from '../answer-validation/index.js';
|
|
39
40
|
import type { MessageMiddleware, ToolMiddleware } from './agent/middleware/types.js';
|
|
40
41
|
import { AgentBuilder } from './agent/AgentBuilder.js';
|
|
41
42
|
export type { SkillGraphOptions } from './agent/AgentBuilder.js';
|
|
@@ -361,6 +362,8 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
|
|
|
361
362
|
* function restores `scope.history` from this instead of starting
|
|
362
363
|
* fresh. Cleared on first read so subsequent runs start clean. */
|
|
363
364
|
private pendingResumeHistory?;
|
|
365
|
+
/** Retried request's repair state; never inherited by a new human turn. */
|
|
366
|
+
private pendingEvidenceRecovery?;
|
|
364
367
|
/** Its sibling for the folded spans. A restored conversation that dropped
|
|
365
368
|
* them would carry summaries nobody could unpack — the evidence would be
|
|
366
369
|
* destroyed by the act of continuing, which is the one thing retention
|
|
@@ -463,6 +466,7 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
|
|
|
463
466
|
/** `AgentOptions.recordReceipt` (9.88.0) — ON by default. `false` declines
|
|
464
467
|
* the mint at `callLLM`; nothing else about the run changes. */
|
|
465
468
|
private readonly recordReceiptValue;
|
|
469
|
+
private readonly answerValidationConfig?;
|
|
466
470
|
constructor(opts: AgentOptions, systemPromptValue: string, registry: readonly ToolRegistryEntry[], voice: {
|
|
467
471
|
readonly appName: string;
|
|
468
472
|
readonly commentaryTemplates: Readonly<Record<string, string>>;
|
|
@@ -472,7 +476,7 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
|
|
|
472
476
|
readonly strictness: 'assist' | 'guard' | 'rails';
|
|
473
477
|
readonly continuity: 'turn' | 'conversation';
|
|
474
478
|
readonly nodeIds: ReadonlySet<string>;
|
|
475
|
-
}, skillBrains?: import('./agent/skillBrains.js').FoldedSkillBrains, evidenceGate?: ResolvedEvidenceGate, limitsTravelWithTheAnswer?: boolean, recipes?: readonly AppliedRecipe[], skillGraphDeclared?: SkillGraphDeclaredMap, mapsPlan?: import('../maps/engagement/types.js').EngagementPlan, claimContract?: readonly import('../integrity/unsupported-claim/check.js').DeclaredClaim[]);
|
|
479
|
+
}, skillBrains?: import('./agent/skillBrains.js').FoldedSkillBrains, evidenceGate?: ResolvedEvidenceGate, limitsTravelWithTheAnswer?: boolean, recipes?: readonly AppliedRecipe[], skillGraphDeclared?: SkillGraphDeclaredMap, mapsPlan?: import('../maps/engagement/types.js').EngagementPlan, claimContract?: readonly import('../integrity/unsupported-claim/check.js').DeclaredClaim[], answerValidationConfig?: ResolvedAnswerValidation);
|
|
476
480
|
static create(opts: AgentOptions): AgentBuilder;
|
|
477
481
|
/**
|
|
478
482
|
* Cache policy for the base system prompt. Read by the CacheDecision
|
|
@@ -873,6 +877,8 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
|
|
|
873
877
|
* ```
|
|
874
878
|
*/
|
|
875
879
|
checkpoint(): AgentRunCheckpoint | undefined;
|
|
880
|
+
/** Both checkpoint doors keep the repair budget separately from conversation text. */
|
|
881
|
+
private evidenceRecoveryOf;
|
|
876
882
|
/**
|
|
877
883
|
* The graph cursor a conversation carrier stores — the run's final
|
|
878
884
|
* committed `currentSkillId`, read from the SNAPSHOT (the state the run
|
|
@@ -1302,6 +1308,9 @@ export declare class Agent extends RunnerBase<AgentInput, AgentOutput> {
|
|
|
1302
1308
|
* ```
|
|
1303
1309
|
*/
|
|
1304
1310
|
unsupportedValues(): AgentState['unsupportedValues'];
|
|
1311
|
+
/** The last run's answer checks, detached from its execution record.
|
|
1312
|
+
* Undefined means no terminal validation ran, never an implicit pass. */
|
|
1313
|
+
answerValidation(): AnswerValidationReport | undefined;
|
|
1305
1314
|
private finalizeResult;
|
|
1306
1315
|
private buildChart;
|
|
1307
1316
|
}
|
package/dist/esm/core/Agent.js
CHANGED
|
@@ -121,6 +121,8 @@ import { buildOutputRetryStage } from './agent/stages/outputRetry.js';
|
|
|
121
121
|
import { RunnerBase, makeRunId } from './RunnerBase.js';
|
|
122
122
|
import { clampIterations, validateMemoryIdUniqueness, validateToolNameUniqueness, } from './agent/validators.js';
|
|
123
123
|
import { buildRouteDeciderStage } from './agent/stages/route.js';
|
|
124
|
+
import { withAnswerValidation } from './agent/stages/answerValidation.js';
|
|
125
|
+
import { AnswerValidationError, } from '../answer-validation/index.js';
|
|
124
126
|
import { buildSeedStage } from './agent/stages/seed.js';
|
|
125
127
|
import { MessageDeniedError } from './agent/middleware/errors.js';
|
|
126
128
|
import { buildCallLLMStage } from './agent/stages/callLLM.js';
|
|
@@ -414,6 +416,8 @@ export class Agent extends RunnerBase {
|
|
|
414
416
|
* function restores `scope.history` from this instead of starting
|
|
415
417
|
* fresh. Cleared on first read so subsequent runs start clean. */
|
|
416
418
|
pendingResumeHistory;
|
|
419
|
+
/** Retried request's repair state; never inherited by a new human turn. */
|
|
420
|
+
pendingEvidenceRecovery;
|
|
417
421
|
/** Its sibling for the folded spans. A restored conversation that dropped
|
|
418
422
|
* them would carry summaries nobody could unpack — the evidence would be
|
|
419
423
|
* destroyed by the act of continuing, which is the one thing retention
|
|
@@ -516,8 +520,10 @@ export class Agent extends RunnerBase {
|
|
|
516
520
|
/** `AgentOptions.recordReceipt` (9.88.0) — ON by default. `false` declines
|
|
517
521
|
* the mint at `callLLM`; nothing else about the run changes. */
|
|
518
522
|
recordReceiptValue = true;
|
|
519
|
-
|
|
523
|
+
answerValidationConfig;
|
|
524
|
+
constructor(opts, systemPromptValue, registry, voice, injections = [], memories = [], outputSchemaParser, toolProvider, systemPromptCachePolicy = 'always', cachingDisabled = false, cacheStrategy, outputFallbackCfg, reliabilityConfig, thinkingHandlerValue, thinkingBudgetValue, skillGraphNextSkill, skillGraphReachable, skillGraphScoreEntries, checkInOptions, runConfigFn, windowStrategy, toolMiddleware, messageMiddleware, outputEnforcement, skillGraphEdgeTargets, skillGraphExplainNextSkill, skillGraphIsTree, skillGraphSupersededEntries, skillGraphCascade, skillBrains, evidenceGate, limitsTravelWithTheAnswer, recipes, skillGraphDeclared, mapsPlan, claimContract, answerValidationConfig) {
|
|
520
525
|
super();
|
|
526
|
+
this.answerValidationConfig = answerValidationConfig;
|
|
521
527
|
this.provider = opts.provider;
|
|
522
528
|
this.name = opts.name ?? 'Agent';
|
|
523
529
|
this.id = opts.id ?? 'agent';
|
|
@@ -1144,6 +1150,17 @@ export class Agent extends RunnerBase {
|
|
|
1144
1150
|
throw new Error('Agent.runTyped: run paused — typed mode does not support pauses. ' +
|
|
1145
1151
|
'Use agent.run() + agent.parseOutput(...) after resume.');
|
|
1146
1152
|
}
|
|
1153
|
+
if (this.answerValidationConfig !== undefined) {
|
|
1154
|
+
// The validator judged the schema's JSON output. Do not run a transforming
|
|
1155
|
+
// or stateful parser again and hand back a value the validator never saw.
|
|
1156
|
+
if (this.answerValidation()?.schemaAccepted !== true) {
|
|
1157
|
+
throw new OutputSchemaError('Answer validation could not establish a JSON schema result.', {
|
|
1158
|
+
rawOutput: out,
|
|
1159
|
+
stage: 'schema-validate',
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
return JSON.parse(out);
|
|
1163
|
+
}
|
|
1147
1164
|
return this.parseOutputAsync(out);
|
|
1148
1165
|
}
|
|
1149
1166
|
/**
|
|
@@ -1306,6 +1323,7 @@ export class Agent extends RunnerBase {
|
|
|
1306
1323
|
// named values one `.cause` deep, where the person deciding what to
|
|
1307
1324
|
// do about them will not look.
|
|
1308
1325
|
cause instanceof UnsupportedValuesError ||
|
|
1326
|
+
cause instanceof AnswerValidationError ||
|
|
1309
1327
|
// 9.60.0 — a dead checker is a WIRING verdict on this build, not a
|
|
1310
1328
|
// recoverable run state: resuming would run the same dead wiring.
|
|
1311
1329
|
cause.name === 'CheckerDeadError');
|
|
@@ -1334,7 +1352,7 @@ export class Agent extends RunnerBase {
|
|
|
1334
1352
|
this.conversationOwner(),
|
|
1335
1353
|
// …and the same graph cursor (SG-C), from the same snapshot reader —
|
|
1336
1354
|
// one reader, two carriers, so neither can lose what the other keeps.
|
|
1337
|
-
this.continuityCursorOf(this.getLastSnapshot()?.sharedState));
|
|
1355
|
+
this.continuityCursorOf(this.getLastSnapshot()?.sharedState), this.evidenceRecoveryOf(this.getLastSnapshot()?.sharedState));
|
|
1338
1356
|
throw new RunCheckpointError(cause, checkpoint);
|
|
1339
1357
|
}
|
|
1340
1358
|
throw cause;
|
|
@@ -1356,6 +1374,7 @@ export class Agent extends RunnerBase {
|
|
|
1356
1374
|
this.pendingResumeHistory = undefined;
|
|
1357
1375
|
this.pendingResumeFolded = undefined;
|
|
1358
1376
|
this.pendingResumeSkillCursor = undefined;
|
|
1377
|
+
this.pendingEvidenceRecovery = undefined;
|
|
1359
1378
|
}
|
|
1360
1379
|
}
|
|
1361
1380
|
/**
|
|
@@ -1724,6 +1743,7 @@ export class Agent extends RunnerBase {
|
|
|
1724
1743
|
const folded = this.foldedSpansOf(state);
|
|
1725
1744
|
const owner = this.conversationOwner();
|
|
1726
1745
|
const skillCursor = this.continuityCursorOf(state);
|
|
1746
|
+
const evidenceRecovery = this.evidenceRecoveryOf(state);
|
|
1727
1747
|
return {
|
|
1728
1748
|
version: 1,
|
|
1729
1749
|
runId: this.currentRunContext.runId,
|
|
@@ -1742,6 +1762,20 @@ export class Agent extends RunnerBase {
|
|
|
1742
1762
|
// `continuity: 'conversation'`, so every other checkpoint keeps its
|
|
1743
1763
|
// exact byte shape.
|
|
1744
1764
|
...(skillCursor !== undefined && { skillCursor }),
|
|
1765
|
+
...(evidenceRecovery !== undefined && { evidenceRecovery }),
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
/** Both checkpoint doors keep the repair budget separately from conversation text. */
|
|
1769
|
+
evidenceRecoveryOf(state) {
|
|
1770
|
+
if (state?.evidenceRevisionSpent !== true)
|
|
1771
|
+
return undefined;
|
|
1772
|
+
const pending = state.evidenceRecovery;
|
|
1773
|
+
return {
|
|
1774
|
+
revisionSpent: true,
|
|
1775
|
+
...(pending !== undefined &&
|
|
1776
|
+
state.evidenceRecoveryUsed !== true && {
|
|
1777
|
+
pending: { instruction: pending.instruction },
|
|
1778
|
+
}),
|
|
1745
1779
|
};
|
|
1746
1780
|
}
|
|
1747
1781
|
/**
|
|
@@ -1834,6 +1868,12 @@ export class Agent extends RunnerBase {
|
|
|
1834
1868
|
// continuity graph and continued on a `'turn'` one is consumed and
|
|
1835
1869
|
// ignored, exactly like a `folded` field on an agent that never folds.
|
|
1836
1870
|
this.pendingResumeSkillCursor = cp.skillCursor;
|
|
1871
|
+
// Same failed request retains its single repair budget. A new user turn
|
|
1872
|
+
// receives neither the rejected draft nor a spent retry allowance.
|
|
1873
|
+
this.pendingEvidenceRecovery =
|
|
1874
|
+
appendMessage === undefined && cp.evidenceRecovery !== undefined
|
|
1875
|
+
? structuredClone(cp.evidenceRecovery)
|
|
1876
|
+
: undefined;
|
|
1837
1877
|
}
|
|
1838
1878
|
/** One turn at a time — see `RunInFlightError`. @internal */
|
|
1839
1879
|
assertNotRunning(door) {
|
|
@@ -2717,6 +2757,13 @@ export class Agent extends RunnerBase {
|
|
|
2717
2757
|
const state = this.getLastSnapshot()?.sharedState;
|
|
2718
2758
|
return state?.unsupportedValues;
|
|
2719
2759
|
}
|
|
2760
|
+
/** The last run's answer checks, detached from its execution record.
|
|
2761
|
+
* Undefined means no terminal validation ran, never an implicit pass. */
|
|
2762
|
+
answerValidation() {
|
|
2763
|
+
const report = this.getLastSnapshot()?.sharedState
|
|
2764
|
+
?.answerValidation;
|
|
2765
|
+
return report === undefined ? undefined : structuredClone(report);
|
|
2766
|
+
}
|
|
2720
2767
|
finalizeResult(executor, result) {
|
|
2721
2768
|
const paused = this.detectPause(executor, result);
|
|
2722
2769
|
if (paused)
|
|
@@ -2844,6 +2891,32 @@ export class Agent extends RunnerBase {
|
|
|
2844
2891
|
}
|
|
2845
2892
|
if (result instanceof Error)
|
|
2846
2893
|
throw result;
|
|
2894
|
+
if (this.answerValidationConfig !== undefined) {
|
|
2895
|
+
const state = executor.getSnapshot().sharedState;
|
|
2896
|
+
if (state.answerValidationBlocked === true && state.answerValidation !== undefined) {
|
|
2897
|
+
throw new AnswerValidationError(state.answerValidation);
|
|
2898
|
+
}
|
|
2899
|
+
if (state.answerValidation === undefined ||
|
|
2900
|
+
state.answerValidationCommitted !== true ||
|
|
2901
|
+
typeof state.finalContent !== 'string') {
|
|
2902
|
+
const config = this.answerValidationConfig;
|
|
2903
|
+
throw new AnswerValidationError({
|
|
2904
|
+
validatorId: config.id,
|
|
2905
|
+
validatorVersion: config.version,
|
|
2906
|
+
mode: config.mode,
|
|
2907
|
+
status: 'unverified',
|
|
2908
|
+
checked: 0,
|
|
2909
|
+
failed: 0,
|
|
2910
|
+
unreachable: 0,
|
|
2911
|
+
notApplicable: 0,
|
|
2912
|
+
checks: [],
|
|
2913
|
+
resolvedRefs: [],
|
|
2914
|
+
schemaAccepted: false,
|
|
2915
|
+
reason: 'delivery-incomplete',
|
|
2916
|
+
});
|
|
2917
|
+
}
|
|
2918
|
+
return state.finalContent;
|
|
2919
|
+
}
|
|
2847
2920
|
if (typeof result === 'string')
|
|
2848
2921
|
return result;
|
|
2849
2922
|
throw new Error('Agent: unexpected result shape — expected final-answer string');
|
|
@@ -2923,6 +2996,14 @@ export class Agent extends RunnerBase {
|
|
|
2923
2996
|
this.pendingResumeHistory = undefined;
|
|
2924
2997
|
return h;
|
|
2925
2998
|
},
|
|
2999
|
+
...(this.evidenceGate !== undefined &&
|
|
3000
|
+
this.evidenceGate.posture !== 'assist' && {
|
|
3001
|
+
consumePendingEvidenceRecovery: () => {
|
|
3002
|
+
const recovery = this.pendingEvidenceRecovery;
|
|
3003
|
+
this.pendingEvidenceRecovery = undefined;
|
|
3004
|
+
return recovery;
|
|
3005
|
+
},
|
|
3006
|
+
}),
|
|
2926
3007
|
consumePendingResumeFolded: () => {
|
|
2927
3008
|
const f = this.pendingResumeFolded;
|
|
2928
3009
|
this.pendingResumeFolded = undefined;
|
|
@@ -3254,6 +3335,11 @@ export class Agent extends RunnerBase {
|
|
|
3254
3335
|
// callLLM extracted to ./agent/stages/callLLM.ts (v2.11.2). Same
|
|
3255
3336
|
// late-binding pattern as seed for toolSchemas (computed below).
|
|
3256
3337
|
const callLLM = buildCallLLMStage({
|
|
3338
|
+
...(this.evidenceGate !== undefined &&
|
|
3339
|
+
this.evidenceGate.posture !== 'assist' && {
|
|
3340
|
+
hasEvidenceRecovery: true,
|
|
3341
|
+
}),
|
|
3342
|
+
...(this.answerValidationConfig !== undefined && { suppressDraftTokens: true }),
|
|
3257
3343
|
// The receipt's salt (9.88.0) — read per call, like seed's own accessor.
|
|
3258
3344
|
getRunId: () => this.currentRunContext?.runId,
|
|
3259
3345
|
// …and its off switch. Value-conditional, so an agent on the default
|
|
@@ -3381,13 +3467,16 @@ export class Agent extends RunnerBase {
|
|
|
3381
3467
|
// question a build-time mount can answer.
|
|
3382
3468
|
const canCallTools = registryByName.size > 0 || this.externalToolProvider !== undefined;
|
|
3383
3469
|
const hasWrapUp = canCallTools && this.wrapUpAtMaxIterations !== false;
|
|
3384
|
-
const
|
|
3470
|
+
const baseRouteDecider = buildRouteDeciderStage(this.messageMiddleware, this.outputEnforcement, stepPlanFor, this.evidenceGate, hasWrapUp, this.claimContract, this.integrityLedgerHolder,
|
|
3385
3471
|
// THE CLAIM SEAM'S RECENCY READ (9.83.0). Value-conditional on both
|
|
3386
3472
|
// halves, so an agent that armed neither hands the decider builder
|
|
3387
3473
|
// exactly the arguments it always did — and `buildRouteDeciderStage`'s
|
|
3388
3474
|
// no-judge fast path still returns the very function reference every
|
|
3389
3475
|
// pre-9.83.0 chart was given.
|
|
3390
3476
|
this.noticePriorTurnEvidence && this.evidenceGate !== undefined ? true : undefined);
|
|
3477
|
+
const routeDecider = this.answerValidationConfig === undefined
|
|
3478
|
+
? baseRouteDecider
|
|
3479
|
+
: withAnswerValidation(baseRouteDecider, this.answerValidationConfig, this.outputSchemaParser, artifactStore, () => this.consentOutstanding.size > 0);
|
|
3391
3480
|
// toolCallsHandler extracted to ./agent/stages/toolCalls.ts (v2.11.2).
|
|
3392
3481
|
const toolCallsHandler = buildToolCallsHandler({
|
|
3393
3482
|
registryByName,
|
|
@@ -3595,6 +3684,7 @@ export class Agent extends RunnerBase {
|
|
|
3595
3684
|
// agent that did not ask, so both builders mount the final-branch stage
|
|
3596
3685
|
// function they have always mounted.
|
|
3597
3686
|
...(this.limitsTravelWithTheAnswerValue && { attachCoverageLimits: true }),
|
|
3687
|
+
...(this.answerValidationConfig !== undefined && { hasAnswerValidation: true }),
|
|
3598
3688
|
// The out-of-budget wrap-up branch (9.56.0) — the conditional-mount law
|
|
3599
3689
|
// above, decided once beside the Route decider that routes to it so the
|
|
3600
3690
|
// two can never disagree about whether the branch exists.
|