@leostera/evalkit 0.5.0 → 0.6.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 +70 -6
- package/README.md +10 -8
- package/dist/cli.mjs +1227 -258
- package/dist/dashboard/assets/index-CTJpd8q8.js +34 -0
- package/dist/dashboard/assets/index-YAabTN3X.css +2 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/files-C-U0-PWW.mjs +0 -2
- package/dist/index-db-vbqEGFaU.mjs +0 -2
- package/dist/index.d.mts +1346 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -4
- package/dist/runner.d.mts +809 -11
- package/dist/runner.d.mts.map +1 -1
- package/dist/runner.mjs +2 -2
- package/dist/share-worker.d.mts +76 -1
- package/dist/share-worker.d.mts.map +1 -1
- package/dist/share-worker.mjs +0 -2
- package/dist/share.d.mts +149 -6
- package/dist/share.d.mts.map +1 -1
- package/dist/share.mjs +1 -1
- package/dist/skills/evalkit/SKILL.md +32 -0
- package/dist/skills/evalkit-agents/SKILL.md +16 -0
- package/dist/skills/evalkit-datasets/SKILL.md +17 -0
- package/dist/skills/evalkit-evals/SKILL.md +19 -0
- package/dist/skills/evalkit-judges/SKILL.md +17 -0
- package/dist/skills/evalkit-matrices/SKILL.md +14 -0
- package/dist/skills/evalkit-results/SKILL.md +14 -0
- package/dist/{src-DoPs9Yug.mjs → src-CKqOzeBi.mjs} +448 -116
- package/dist/{src-ButXPY8P.mjs → src-CZPufWN_.mjs} +419 -94
- package/dist/{src-DzZueFn3.mjs → src-CZnDXP1K.mjs} +46 -10
- package/package.json +3 -2
- package/dist/cli.mjs.map +0 -1
- package/dist/dashboard/assets/index-D9NtA46z.css +0 -2
- package/dist/dashboard/assets/index-DrBwLKJD.js +0 -30
- package/dist/files-C-U0-PWW.mjs.map +0 -1
- package/dist/index-db-HdZXelOS.d.mts +0 -142
- package/dist/index-db-HdZXelOS.d.mts.map +0 -1
- package/dist/index-db-vbqEGFaU.mjs.map +0 -1
- package/dist/index-lOw0fmak.d.mts +0 -1028
- package/dist/index-lOw0fmak.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/share-worker.mjs.map +0 -1
- package/dist/src-ButXPY8P.mjs.map +0 -1
- package/dist/src-DoPs9Yug.mjs.map +0 -1
- package/dist/src-DzZueFn3.mjs.map +0 -1
|
@@ -31,6 +31,291 @@ function resourceUuid(value, expectedKind) {
|
|
|
31
31
|
return parseResourceUri(value, expectedKind).uuid;
|
|
32
32
|
}
|
|
33
33
|
//#endregion
|
|
34
|
+
//#region ../core/src/definition-site.ts
|
|
35
|
+
const SITE = Symbol.for("evalkit.definitionSite");
|
|
36
|
+
const internalFiles = /* @__PURE__ */ new Set();
|
|
37
|
+
/** Call from each module that defines helpers, so its frames are skipped. */
|
|
38
|
+
function internalModule(url) {
|
|
39
|
+
if (url) internalFiles.add(filePath(url));
|
|
40
|
+
}
|
|
41
|
+
internalModule(import.meta.url);
|
|
42
|
+
function markDefinitionSite(value) {
|
|
43
|
+
if (Object.hasOwn(value, SITE)) return value;
|
|
44
|
+
const site = callerSite();
|
|
45
|
+
if (site) Object.defineProperty(value, SITE, {
|
|
46
|
+
value: site,
|
|
47
|
+
enumerable: false
|
|
48
|
+
});
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
function definitionSite(value) {
|
|
52
|
+
return typeof value === "object" && value !== null ? value[SITE] ?? void 0 : void 0;
|
|
53
|
+
}
|
|
54
|
+
/** `file:line` relative to `root`, or undefined outside it (never an absolute path). */
|
|
55
|
+
function relativeSite(site, root) {
|
|
56
|
+
if (!site || !root) return void 0;
|
|
57
|
+
const base = root.replace(/[\\/]+$/, "") + "/";
|
|
58
|
+
const file = site.file.replace(/\\/g, "/");
|
|
59
|
+
const prefix = base.replace(/\\/g, "/");
|
|
60
|
+
if (!file.startsWith(prefix)) return void 0;
|
|
61
|
+
return `${file.slice(prefix.length)}:${site.line}`;
|
|
62
|
+
}
|
|
63
|
+
const FRAME = /\(?((?:file:\/\/)?(?:\/|[A-Za-z]:[\\/])[^():]*):(\d+):\d+\)?\s*$/;
|
|
64
|
+
function callerSite() {
|
|
65
|
+
const stack = (/* @__PURE__ */ new Error()).stack?.split("\n").slice(1) ?? [];
|
|
66
|
+
for (const frame of stack) {
|
|
67
|
+
const match = FRAME.exec(frame);
|
|
68
|
+
if (!match) continue;
|
|
69
|
+
const file = filePath(match[1]);
|
|
70
|
+
if (internalFiles.has(file) || file.includes("/node_modules/")) continue;
|
|
71
|
+
return {
|
|
72
|
+
file,
|
|
73
|
+
line: Number(match[2])
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function filePath(location) {
|
|
78
|
+
if (!location.startsWith("file://")) return location;
|
|
79
|
+
try {
|
|
80
|
+
return decodeURIComponent(new URL(location).pathname);
|
|
81
|
+
} catch {
|
|
82
|
+
return location.slice(7);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region ../core/src/dataset.ts
|
|
87
|
+
internalModule(import.meta.url);
|
|
88
|
+
/** Normalizes a relative POSIX path and rejects absolute or escaping ones. */
|
|
89
|
+
function relativeDatasetPath(value, label) {
|
|
90
|
+
const parts = [];
|
|
91
|
+
if (!value || value.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(value)) throw new Error(`${label} must be a non-empty relative path: ${value}`);
|
|
92
|
+
for (const part of value.replace(/\\/g, "/").split("/")) {
|
|
93
|
+
if (part === "" || part === ".") continue;
|
|
94
|
+
if (part === "..") {
|
|
95
|
+
if (!parts.length) throw new Error(`${label} escapes its workspace: ${value}`);
|
|
96
|
+
parts.pop();
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
parts.push(part);
|
|
100
|
+
}
|
|
101
|
+
return parts.length ? parts.join("/") : ".";
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Declares named data that scenarios use: files placed in each trial's
|
|
105
|
+
* workspace, a value for the agent and scorers, or both. Static datasets give
|
|
106
|
+
* `files`, `value` or `valueFile`; computed datasets give `onLoad` (cached per
|
|
107
|
+
* process) and optionally `onRun` (per trial).
|
|
108
|
+
*/
|
|
109
|
+
function defineDataset(definition) {
|
|
110
|
+
return markDefinitionSite(checkedDataset(definition));
|
|
111
|
+
}
|
|
112
|
+
function checkedDataset(definition) {
|
|
113
|
+
if ("uri" in definition || "uuid" in definition || "slug" in definition) throw new Error("Authored resources use id, not uri, uuid, or slug");
|
|
114
|
+
const id = authorId(definition.id);
|
|
115
|
+
const visibility = definition.visibility ?? "candidate";
|
|
116
|
+
if (visibility !== "candidate" && visibility !== "evaluator") throw new Error(`Dataset ${id} visibility must be candidate or evaluator; received ${String(visibility)}`);
|
|
117
|
+
const mount = relativeDatasetPath(definition.mount ?? id, `Dataset ${id} mount`);
|
|
118
|
+
const common = {
|
|
119
|
+
kind: "dataset",
|
|
120
|
+
id,
|
|
121
|
+
...definition.name ? { name: definition.name } : {},
|
|
122
|
+
visibility,
|
|
123
|
+
mount
|
|
124
|
+
};
|
|
125
|
+
if (definition.onLoad !== void 0) {
|
|
126
|
+
if (typeof definition.onLoad !== "function") throw new Error(`Dataset ${id} onLoad must be a function`);
|
|
127
|
+
if (definition.files !== void 0 || definition.value !== void 0 || definition.valueFile !== void 0) throw new Error(`Dataset ${id} is computed (onLoad); move files and values into what onLoad returns`);
|
|
128
|
+
if (definition.onRun !== void 0 && typeof definition.onRun !== "function") throw new Error(`Dataset ${id} onRun must be a function`);
|
|
129
|
+
return {
|
|
130
|
+
...common,
|
|
131
|
+
source: {
|
|
132
|
+
kind: "computed",
|
|
133
|
+
onLoad: definition.onLoad,
|
|
134
|
+
...definition.onRun ? { onRun: definition.onRun } : {}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (definition.onRun !== void 0) throw new Error(`Dataset ${id} has onRun without onLoad`);
|
|
139
|
+
if (definition.value !== void 0 && definition.valueFile !== void 0) throw new Error(`Dataset ${id} has both value and valueFile; give one`);
|
|
140
|
+
if (definition.files === void 0 && definition.value === void 0 && definition.valueFile === void 0) throw new Error(`Dataset ${id} is empty; give files, value, valueFile or onLoad`);
|
|
141
|
+
return {
|
|
142
|
+
...common,
|
|
143
|
+
source: {
|
|
144
|
+
kind: "static",
|
|
145
|
+
...definition.files !== void 0 ? { files: definition.files } : {},
|
|
146
|
+
...definition.value !== void 0 ? { value: definition.value } : {},
|
|
147
|
+
...definition.valueFile !== void 0 ? { valueFile: definition.valueFile } : {}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function isDataset(value) {
|
|
152
|
+
return typeof value === "object" && value !== null && value.kind === "dataset" && typeof value.source === "object";
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region ../core/src/json.ts
|
|
156
|
+
/** A value that cannot be stored in a report, with the path of the offending part. */
|
|
157
|
+
var NotJsonError = class extends Error {
|
|
158
|
+
path;
|
|
159
|
+
reason;
|
|
160
|
+
name = "NotJsonError";
|
|
161
|
+
constructor(path, reason) {
|
|
162
|
+
super(`${path}: ${reason}`);
|
|
163
|
+
this.path = path;
|
|
164
|
+
this.reason = reason;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Converts an author-supplied value to JSON once, where it enters EvalKit.
|
|
169
|
+
* Honours `toJSON()` (so `Date` becomes an ISO string) and drops `undefined`
|
|
170
|
+
* object fields. Rejects functions, symbols, bigints, non-finite numbers and
|
|
171
|
+
* cycles, naming the path of the bad value.
|
|
172
|
+
*/
|
|
173
|
+
function toJson(value, path = "value") {
|
|
174
|
+
return convert(value, path, /* @__PURE__ */ new Set());
|
|
175
|
+
}
|
|
176
|
+
function convert(value, path, seen) {
|
|
177
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
178
|
+
if (typeof value === "number") {
|
|
179
|
+
if (!Number.isFinite(value)) throw new NotJsonError(path, `${value} is not JSON`);
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
if (value === void 0) throw new NotJsonError(path, "undefined is not JSON");
|
|
183
|
+
if (typeof value !== "object") throw new NotJsonError(path, `${typeof value} is not JSON`);
|
|
184
|
+
if (seen.has(value)) throw new NotJsonError(path, "cycle is not JSON");
|
|
185
|
+
const withToJson = value;
|
|
186
|
+
if (typeof withToJson.toJSON === "function") return convert(withToJson.toJSON(), path, seen);
|
|
187
|
+
seen.add(value);
|
|
188
|
+
try {
|
|
189
|
+
if (Array.isArray(value)) return value.map((item, index) => convert(item === void 0 ? null : item, `${path}[${index}]`, seen));
|
|
190
|
+
if (value instanceof Map || value instanceof Set) throw new NotJsonError(path, `${value.constructor.name} is not JSON`);
|
|
191
|
+
const result = {};
|
|
192
|
+
for (const [key, field] of Object.entries(value)) {
|
|
193
|
+
if (field === void 0) continue;
|
|
194
|
+
result[key] = convert(field, `${path}.${key}`, seen);
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
} finally {
|
|
198
|
+
seen.delete(value);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/** `toJson` for values that must be objects, such as metadata. */
|
|
202
|
+
function toJsonObject(value, path) {
|
|
203
|
+
const converted = toJson(value, path);
|
|
204
|
+
if (converted === null || typeof converted !== "object" || Array.isArray(converted)) throw new NotJsonError(path, "must be a JSON object");
|
|
205
|
+
return converted;
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region ../core/src/catalog.ts
|
|
209
|
+
function catalogEntry(evaluation, suite, options = {}) {
|
|
210
|
+
const at = (value) => relativeSite(definitionSite(value), options.root);
|
|
211
|
+
const definedAt = at(evaluation);
|
|
212
|
+
const judgeAgent = evaluation.judge ? catalogAgent(evaluation.judge, at) : void 0;
|
|
213
|
+
const policy = evaluation.policy ?? {};
|
|
214
|
+
return {
|
|
215
|
+
id: evaluation.id,
|
|
216
|
+
path: suite ? `${suite.id}#${evaluation.id}` : evaluation.id,
|
|
217
|
+
...evaluation.name ? { name: evaluation.name } : {},
|
|
218
|
+
...suite ? { suiteId: authoringId(suite) } : {},
|
|
219
|
+
agent: catalogAgent(evaluation.agent, at),
|
|
220
|
+
...judgeAgent ? { judgeAgent } : {},
|
|
221
|
+
datasets: (evaluation.datasets ?? []).map((dataset) => catalogDataset(dataset, at)),
|
|
222
|
+
trialCount: policy.trials ?? 1,
|
|
223
|
+
policy: {
|
|
224
|
+
trials: policy.trials ?? 1,
|
|
225
|
+
...policy.timeoutMs !== void 0 ? { timeoutMs: policy.timeoutMs } : {},
|
|
226
|
+
...policy.failfast !== void 0 ? { failfast: policy.failfast } : {}
|
|
227
|
+
},
|
|
228
|
+
transcript: evaluation.transcript.map((step) => catalogStep(step, at)),
|
|
229
|
+
scorers: evaluation.scoring.map((rule) => catalogScorer(rule, at)),
|
|
230
|
+
...evaluation.metadata !== void 0 ? { metadata: toJson(evaluation.metadata, `${evaluation.id}.metadata`) } : {},
|
|
231
|
+
...definedAt ? { definedAt } : {}
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function catalogAgent(agent, at) {
|
|
235
|
+
const identity = agent.identity;
|
|
236
|
+
const definedAt = at(agent);
|
|
237
|
+
return {
|
|
238
|
+
...identity?.name ? { name: identity.name } : {},
|
|
239
|
+
kind: identity?.kind ?? "adapter",
|
|
240
|
+
...identity?.id ? { id: identity.id } : {},
|
|
241
|
+
...identity?.version ? { version: identity.version } : {},
|
|
242
|
+
runtimes: Object.entries(agentRuntimes(agent)).map(([name, runtime]) => ({
|
|
243
|
+
name,
|
|
244
|
+
kind: runtime.kind
|
|
245
|
+
})),
|
|
246
|
+
...definedAt ? { definedAt } : {}
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
function catalogDataset(dataset, at) {
|
|
250
|
+
const definedAt = at(dataset);
|
|
251
|
+
const source = dataset.source;
|
|
252
|
+
const base = {
|
|
253
|
+
id: dataset.id,
|
|
254
|
+
...dataset.name ? { name: dataset.name } : {},
|
|
255
|
+
visibility: dataset.visibility,
|
|
256
|
+
source: source.kind,
|
|
257
|
+
mount: dataset.mount,
|
|
258
|
+
...definedAt ? { definedAt } : {}
|
|
259
|
+
};
|
|
260
|
+
if (source.kind === "computed") return {
|
|
261
|
+
...base,
|
|
262
|
+
hooks: {
|
|
263
|
+
onLoad: true,
|
|
264
|
+
onRun: !!source.onRun
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
return {
|
|
268
|
+
...base,
|
|
269
|
+
...source.files === void 0 ? {} : typeof source.files === "string" ? { files: { directory: source.files } } : { files: { paths: Object.keys(source.files).sort() } },
|
|
270
|
+
...source.valueFile !== void 0 ? { value: { file: source.valueFile } } : source.value !== void 0 ? { value: { shape: shapeOf(source.value) } } : {}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function catalogScorer(rule, at) {
|
|
274
|
+
const definedAt = at(rule);
|
|
275
|
+
return {
|
|
276
|
+
name: rule.name,
|
|
277
|
+
kind: rule.kind,
|
|
278
|
+
...rule.kind === "predicate" && rule.passAt !== void 0 ? { passAt: rule.passAt } : {},
|
|
279
|
+
...rule.supportsPartial !== void 0 ? { supportsPartial: rule.supportsPartial } : {},
|
|
280
|
+
...rule.kind === "judge" ? { rubric: rule.rubric } : {},
|
|
281
|
+
...definedAt ? { definedAt } : {}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function catalogStep(step, at) {
|
|
285
|
+
switch (step.kind) {
|
|
286
|
+
case "user": return {
|
|
287
|
+
kind: "user",
|
|
288
|
+
message: step.message
|
|
289
|
+
};
|
|
290
|
+
case "agent": return {
|
|
291
|
+
kind: "agent",
|
|
292
|
+
expectation: step.expectation
|
|
293
|
+
};
|
|
294
|
+
case "expect-tool-call": return {
|
|
295
|
+
kind: "expect-tool-call",
|
|
296
|
+
name: step.expected.name,
|
|
297
|
+
...step.expected.arguments !== void 0 ? { arguments: step.expected.arguments } : {}
|
|
298
|
+
};
|
|
299
|
+
default: return {
|
|
300
|
+
kind: "checkpoint",
|
|
301
|
+
scorer: catalogScorer(step, at)
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function shapeOf(value) {
|
|
306
|
+
const json = toJson(value, "dataset value");
|
|
307
|
+
if (Array.isArray(json)) return {
|
|
308
|
+
type: "array",
|
|
309
|
+
items: json.length
|
|
310
|
+
};
|
|
311
|
+
if (json === null) return { type: "null" };
|
|
312
|
+
if (typeof json === "object") return {
|
|
313
|
+
type: "object",
|
|
314
|
+
keys: Object.keys(json).sort()
|
|
315
|
+
};
|
|
316
|
+
return { type: typeof json };
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
34
319
|
//#region ../core/src/canonical-json.ts
|
|
35
320
|
/** Canonical JSON: keys sorted recursively, array order preserved. Rejects non-JSON inputs. */
|
|
36
321
|
function canonicalParameters(value) {
|
|
@@ -176,6 +461,83 @@ function defineEvalMatrix(definition) {
|
|
|
176
461
|
};
|
|
177
462
|
}
|
|
178
463
|
//#endregion
|
|
464
|
+
//#region ../core/src/aut-events.ts
|
|
465
|
+
/** Converts an adapter event into a recorded `AutEvent`. */
|
|
466
|
+
function normalizeAutEvent(input, now) {
|
|
467
|
+
if (typeof input !== "object" || input === null) throw new Error("AUT events must be objects");
|
|
468
|
+
const timestamp = input.timestamp ?? now().toISOString();
|
|
469
|
+
switch (input.kind) {
|
|
470
|
+
case "message": return {
|
|
471
|
+
kind: "message",
|
|
472
|
+
role: input.role,
|
|
473
|
+
content: toJson(input.content, "event.content"),
|
|
474
|
+
timestamp
|
|
475
|
+
};
|
|
476
|
+
case "tool-call": return {
|
|
477
|
+
kind: "tool-call",
|
|
478
|
+
id: input.id,
|
|
479
|
+
name: input.name,
|
|
480
|
+
arguments: input.arguments === void 0 ? {} : toJson(input.arguments, "event.arguments"),
|
|
481
|
+
timestamp
|
|
482
|
+
};
|
|
483
|
+
case "tool-result": return {
|
|
484
|
+
kind: "tool-result",
|
|
485
|
+
id: input.id,
|
|
486
|
+
...input.name === void 0 ? {} : { name: input.name },
|
|
487
|
+
result: input.result === void 0 ? null : toJson(input.result, "event.result"),
|
|
488
|
+
timestamp
|
|
489
|
+
};
|
|
490
|
+
case "completed": return {
|
|
491
|
+
kind: "completed",
|
|
492
|
+
...input.output === void 0 ? {} : { output: toJson(input.output, "event.output") },
|
|
493
|
+
timestamp
|
|
494
|
+
};
|
|
495
|
+
case "started":
|
|
496
|
+
case "turn-started":
|
|
497
|
+
case "turn-completed":
|
|
498
|
+
case "error": return {
|
|
499
|
+
...input,
|
|
500
|
+
timestamp
|
|
501
|
+
};
|
|
502
|
+
default: throw new Error(`Unknown AUT event kind: ${String(input.kind)}`);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* The events a returned turn result stands for: each tool call (and its
|
|
507
|
+
* result), then the reply, then the usage as a `turn-completed` event.
|
|
508
|
+
*/
|
|
509
|
+
function turnResultEvents(result, turn, now) {
|
|
510
|
+
if (typeof result === "string") result = { reply: result };
|
|
511
|
+
if (typeof result !== "object" || result === null) throw new Error("send() must return nothing, a string, or a turn result");
|
|
512
|
+
const events = [];
|
|
513
|
+
for (const [index, call] of (result.toolCalls ?? []).entries()) {
|
|
514
|
+
const id = call.id ?? `turn-${turn}-call-${index + 1}`;
|
|
515
|
+
events.push(normalizeAutEvent({
|
|
516
|
+
kind: "tool-call",
|
|
517
|
+
id,
|
|
518
|
+
name: call.name,
|
|
519
|
+
arguments: call.arguments
|
|
520
|
+
}, now));
|
|
521
|
+
if (call.result !== void 0) events.push(normalizeAutEvent({
|
|
522
|
+
kind: "tool-result",
|
|
523
|
+
id,
|
|
524
|
+
name: call.name,
|
|
525
|
+
result: call.result
|
|
526
|
+
}, now));
|
|
527
|
+
}
|
|
528
|
+
if (result.reply !== void 0) events.push(normalizeAutEvent({
|
|
529
|
+
kind: "message",
|
|
530
|
+
role: "assistant",
|
|
531
|
+
content: result.reply
|
|
532
|
+
}, now));
|
|
533
|
+
if (result.usage) events.push(normalizeAutEvent({
|
|
534
|
+
kind: "turn-completed",
|
|
535
|
+
turn,
|
|
536
|
+
usage: result.usage
|
|
537
|
+
}, now));
|
|
538
|
+
return events;
|
|
539
|
+
}
|
|
540
|
+
//#endregion
|
|
179
541
|
//#region ../core/src/schema.ts
|
|
180
542
|
/** Runtime schemas for serialized EvalKit report and API boundaries. */
|
|
181
543
|
const RunStatusSchema = Schema.Literal("running", "completed", "failed", "cancelled");
|
|
@@ -217,7 +579,7 @@ const RunSourceSchema = Schema.Struct({
|
|
|
217
579
|
}))
|
|
218
580
|
});
|
|
219
581
|
const RunMetadataSchema = Schema.Struct({
|
|
220
|
-
schemaVersion: Schema.Literal(2, 3, 4),
|
|
582
|
+
schemaVersion: Schema.Literal(2, 3, 4, 5),
|
|
221
583
|
runUri: resourceUriSchema("run"),
|
|
222
584
|
evalId: Schema.String,
|
|
223
585
|
suiteId: Schema.optional(Schema.String),
|
|
@@ -225,10 +587,14 @@ const RunMetadataSchema = Schema.Struct({
|
|
|
225
587
|
matrix: Schema.optional(MatrixCellSchema),
|
|
226
588
|
aut: Schema.optional(AutIdentitySchema),
|
|
227
589
|
startedAt: Schema.String,
|
|
228
|
-
source: Schema.optional(RunSourceSchema)
|
|
590
|
+
source: Schema.optional(RunSourceSchema),
|
|
591
|
+
process: Schema.optional(Schema.Struct({
|
|
592
|
+
pid: Schema.Number,
|
|
593
|
+
hostname: Schema.String
|
|
594
|
+
}))
|
|
229
595
|
});
|
|
230
596
|
const TrialMetadataSchema = Schema.Struct({
|
|
231
|
-
schemaVersion: Schema.Literal(2, 3, 4),
|
|
597
|
+
schemaVersion: Schema.Literal(2, 3, 4, 5),
|
|
232
598
|
runUri: resourceUriSchema("run"),
|
|
233
599
|
trialUri: resourceUriSchema("trial"),
|
|
234
600
|
trialIndex: Schema.Number,
|
|
@@ -236,7 +602,13 @@ const TrialMetadataSchema = Schema.Struct({
|
|
|
236
602
|
parameters: Schema.optional(ParametersSchema),
|
|
237
603
|
matrix: Schema.optional(MatrixCellSchema),
|
|
238
604
|
aut: Schema.optional(AutIdentitySchema),
|
|
239
|
-
startedAt: Schema.String
|
|
605
|
+
startedAt: Schema.String,
|
|
606
|
+
datasets: Schema.optional(Schema.mutable(Schema.Array(Schema.Struct({
|
|
607
|
+
id: Schema.String,
|
|
608
|
+
visibility: Schema.Literal("candidate", "evaluator"),
|
|
609
|
+
source: Schema.Literal("static", "computed"),
|
|
610
|
+
digest: Schema.String
|
|
611
|
+
}))))
|
|
240
612
|
});
|
|
241
613
|
/** On-disk manifests include a lifecycle status; older finalized manifests may still say running. */
|
|
242
614
|
const RunManifestSchema = Schema.Struct({
|
|
@@ -271,7 +643,8 @@ const ScoreResultSchema = Schema.Struct({
|
|
|
271
643
|
evidence: Schema.optional(JsonValueSchema),
|
|
272
644
|
judge: Schema.optional(JudgeRunInfoSchema),
|
|
273
645
|
durationMs: Schema.Number,
|
|
274
|
-
error: Schema.optional(RecordedErrorSchema)
|
|
646
|
+
error: Schema.optional(RecordedErrorSchema),
|
|
647
|
+
skipped: Schema.optional(Schema.Literal(true))
|
|
275
648
|
});
|
|
276
649
|
const CheckpointResultSchema = Schema.Struct({
|
|
277
650
|
step: Schema.Number,
|
|
@@ -317,6 +690,7 @@ const RunSummarySchema = Schema.Struct({
|
|
|
317
690
|
trialCount: Schema.Number,
|
|
318
691
|
passed: Schema.Number,
|
|
319
692
|
failed: Schema.Number,
|
|
693
|
+
cancelled: Schema.optional(Schema.Number),
|
|
320
694
|
error: Schema.optional(RecordedErrorSchema)
|
|
321
695
|
});
|
|
322
696
|
const autEvent = {
|
|
@@ -385,6 +759,7 @@ const runnerEvent = {
|
|
|
385
759
|
source: Schema.Literal("runner"),
|
|
386
760
|
kind: Schema.Literal("transcript-step-started"),
|
|
387
761
|
step: Schema.Number,
|
|
762
|
+
message: Schema.optional(Schema.String),
|
|
388
763
|
timestamp: Schema.String
|
|
389
764
|
}),
|
|
390
765
|
stepCompleted: Schema.Struct({
|
|
@@ -410,7 +785,7 @@ const runnerEvent = {
|
|
|
410
785
|
source: Schema.Literal("runner"),
|
|
411
786
|
kind: Schema.Literal("checkpoint-completed"),
|
|
412
787
|
step: Schema.Number,
|
|
413
|
-
status: Schema.Literal("passed", "failed"),
|
|
788
|
+
status: Schema.Literal("passed", "failed", "skipped"),
|
|
414
789
|
timestamp: Schema.String
|
|
415
790
|
}),
|
|
416
791
|
checkpointError: Schema.Struct({
|
|
@@ -430,7 +805,8 @@ const runnerEvent = {
|
|
|
430
805
|
source: Schema.Literal("runner"),
|
|
431
806
|
kind: Schema.Literal("scorer-completed"),
|
|
432
807
|
scorer: Schema.String,
|
|
433
|
-
value: Schema.Number,
|
|
808
|
+
value: Schema.optional(Schema.Number),
|
|
809
|
+
skipped: Schema.optional(Schema.Literal(true)),
|
|
434
810
|
timestamp: Schema.String
|
|
435
811
|
}),
|
|
436
812
|
scorerFailed: Schema.Struct({
|
|
@@ -474,52 +850,20 @@ function parseTrajectoryJsonl(contents) {
|
|
|
474
850
|
}
|
|
475
851
|
//#endregion
|
|
476
852
|
//#region ../core/src/index.ts
|
|
853
|
+
internalModule(import.meta.url);
|
|
854
|
+
/** Used when an agent declares no runtimes. */
|
|
855
|
+
const DEFAULT_AGENT_RUNTIMES = { local: { kind: "in-process" } };
|
|
856
|
+
/** The runtimes an agent can run in, applying the default. */
|
|
857
|
+
function agentRuntimes(agent) {
|
|
858
|
+
return agent.runtimes && Object.keys(agent.runtimes).length ? agent.runtimes : DEFAULT_AGENT_RUNTIMES;
|
|
859
|
+
}
|
|
477
860
|
/**
|
|
478
861
|
* Defines an Agent Under Test without coupling it to a runtime or transport.
|
|
479
862
|
* It preserves the adapter's concrete type for application-specific helpers.
|
|
480
863
|
*/
|
|
481
864
|
function defineAgent(agent) {
|
|
482
865
|
if (agent.identity) authoringId(agent.identity);
|
|
483
|
-
return agent;
|
|
484
|
-
}
|
|
485
|
-
function defaultFixtureDestination(src) {
|
|
486
|
-
const normalized = src.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
487
|
-
const destination = normalized.slice(normalized.lastIndexOf("/") + 1);
|
|
488
|
-
if (!destination || destination === "." || destination === "..") throw new Error(`Fixture source needs a basename: ${src}`);
|
|
489
|
-
return destination;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* Declares a directory relative to the invoking project's working directory.
|
|
493
|
-
* The short form is candidate-visible and copies beneath the source basename.
|
|
494
|
-
*/
|
|
495
|
-
function directory(src, options = {}) {
|
|
496
|
-
return {
|
|
497
|
-
kind: "directory",
|
|
498
|
-
src,
|
|
499
|
-
dst: options.dst ?? defaultFixtureDestination(src),
|
|
500
|
-
visibility: options.visibility ?? "candidate"
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
function file(src, options) {
|
|
504
|
-
return {
|
|
505
|
-
kind: "file",
|
|
506
|
-
src,
|
|
507
|
-
...options
|
|
508
|
-
};
|
|
509
|
-
}
|
|
510
|
-
function inlineFile(file, data, visibility) {
|
|
511
|
-
return {
|
|
512
|
-
kind: "inline",
|
|
513
|
-
file,
|
|
514
|
-
data,
|
|
515
|
-
visibility
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
function dynamic(create) {
|
|
519
|
-
return {
|
|
520
|
-
kind: "dynamic",
|
|
521
|
-
create
|
|
522
|
-
};
|
|
866
|
+
return markDefinitionSite(agent);
|
|
523
867
|
}
|
|
524
868
|
/** Observes a tool call in the preceding turn; never invokes a tool. */
|
|
525
869
|
function expectToolCall(expected) {
|
|
@@ -542,30 +886,51 @@ function agent(expectation) {
|
|
|
542
886
|
expectation
|
|
543
887
|
};
|
|
544
888
|
}
|
|
545
|
-
|
|
889
|
+
/**
|
|
890
|
+
* Marks a scorer as not applicable to this trial. A skipped result neither
|
|
891
|
+
* passes nor fails the trial and is left out of score averages.
|
|
892
|
+
*/
|
|
893
|
+
function skip(reason) {
|
|
894
|
+
if (!reason.trim()) throw new Error("skip() needs a reason");
|
|
546
895
|
return {
|
|
896
|
+
skipped: true,
|
|
897
|
+
reason
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
function predicate(name, run, options = {}) {
|
|
901
|
+
if (!name.trim()) throw new Error("Predicate name must not be empty");
|
|
902
|
+
if (options.passAt !== void 0 && !(Number.isFinite(options.passAt) && options.passAt >= 0 && options.passAt <= 1)) throw new Error(`Predicate ${name} passAt must be a number from 0 to 1; received ${options.passAt}`);
|
|
903
|
+
return markDefinitionSite({
|
|
547
904
|
kind: "predicate",
|
|
548
905
|
name,
|
|
549
906
|
run,
|
|
550
907
|
...options
|
|
551
|
-
};
|
|
908
|
+
});
|
|
552
909
|
}
|
|
553
910
|
function judge(name, options) {
|
|
554
911
|
if (!name.trim() || !options.rubric.trim()) throw new Error("Judge name and rubric must not be empty");
|
|
555
|
-
return {
|
|
912
|
+
return markDefinitionSite({
|
|
556
913
|
kind: "judge",
|
|
557
914
|
name,
|
|
558
915
|
...options
|
|
559
|
-
};
|
|
916
|
+
});
|
|
560
917
|
}
|
|
561
918
|
function defineEval(definition) {
|
|
562
919
|
authoringId(definition);
|
|
920
|
+
if ("fixtures" in definition) throw new Error(`Eval ${definition.id} uses fixtures, which were replaced by datasets: [defineDataset(...)]`);
|
|
921
|
+
if (definition.metadata !== void 0) toJsonObject(definition.metadata, `${definition.id}.metadata`);
|
|
922
|
+
const datasetIds = /* @__PURE__ */ new Set();
|
|
923
|
+
for (const [index, dataset] of (definition.datasets ?? []).entries()) {
|
|
924
|
+
if (!isDataset(dataset)) throw new Error(`Eval ${definition.id} datasets[${index}] is not a dataset; create it with defineDataset(...)`);
|
|
925
|
+
if (datasetIds.has(dataset.id)) throw new Error(`Eval ${definition.id} uses dataset ${dataset.id} more than once`);
|
|
926
|
+
datasetIds.add(dataset.id);
|
|
927
|
+
}
|
|
563
928
|
let hasUser = false;
|
|
564
929
|
for (const step of definition.transcript) if (step.kind === "user") hasUser = true;
|
|
565
930
|
else if (step.kind !== "agent" && !hasUser) throw new Error("Checkpoint requires a preceding user step");
|
|
566
931
|
if ((definition.transcript.some((step) => step.kind === "judge") || definition.scoring.some((rule) => rule.kind === "judge")) && !definition.judge) throw new Error("Judge rules require an eval judge agent");
|
|
567
932
|
if (definition.judge && definition.judge === definition.agent) throw new Error("Judge agent must be distinct from the agent under test");
|
|
568
|
-
return definition;
|
|
933
|
+
return markDefinitionSite(definition);
|
|
569
934
|
}
|
|
570
935
|
function defineSuite(suite) {
|
|
571
936
|
authoringId(suite);
|
|
@@ -633,45 +998,7 @@ function registerEvals(registrations) {
|
|
|
633
998
|
evalIds: suite.evals.map(authoringId),
|
|
634
999
|
...suite.name ? { name: suite.name } : {}
|
|
635
1000
|
})),
|
|
636
|
-
catalog: () => evals.map((evaluation) =>
|
|
637
|
-
const suite = suiteIdByEvalId.get(authoringId(evaluation));
|
|
638
|
-
const identity = evaluation.agent.identity;
|
|
639
|
-
return {
|
|
640
|
-
id: evaluation.id,
|
|
641
|
-
path: suite ? `${suite.id}#${evaluation.id}` : evaluation.id,
|
|
642
|
-
...evaluation.name ? { name: evaluation.name } : {},
|
|
643
|
-
...suite ? { suiteId: suite.id } : {},
|
|
644
|
-
agent: {
|
|
645
|
-
...identity?.name ? { name: identity.name } : {},
|
|
646
|
-
kind: identity?.kind ?? "adapter",
|
|
647
|
-
...identity?.id ? { id: identity.id } : {},
|
|
648
|
-
...identity?.version ? { version: identity.version } : {},
|
|
649
|
-
runtimes: Object.entries(evaluation.agent.runtimes ?? {}).map(([name, runtime]) => ({
|
|
650
|
-
name,
|
|
651
|
-
kind: runtime.kind
|
|
652
|
-
}))
|
|
653
|
-
},
|
|
654
|
-
fixtures: (evaluation.fixtures ?? []).map((fixture) => fixture.kind === "dynamic" ? {
|
|
655
|
-
kind: "dynamic",
|
|
656
|
-
source: "dynamic"
|
|
657
|
-
} : fixture.kind === "inline" ? {
|
|
658
|
-
kind: "inline",
|
|
659
|
-
source: fixture.file,
|
|
660
|
-
destination: fixture.file,
|
|
661
|
-
visibility: fixture.visibility
|
|
662
|
-
} : {
|
|
663
|
-
kind: fixture.kind,
|
|
664
|
-
source: fixture.src,
|
|
665
|
-
destination: fixture.dst,
|
|
666
|
-
visibility: fixture.visibility
|
|
667
|
-
}),
|
|
668
|
-
trialCount: evaluation.policy?.trials ?? 1,
|
|
669
|
-
scorers: evaluation.scoring.map(({ name, kind }) => ({
|
|
670
|
-
name,
|
|
671
|
-
kind
|
|
672
|
-
}))
|
|
673
|
-
};
|
|
674
|
-
})
|
|
1001
|
+
catalog: (options) => evals.map((evaluation) => catalogEntry(evaluation, suiteIdByEvalId.get(authoringId(evaluation)), options))
|
|
675
1002
|
};
|
|
676
1003
|
}
|
|
677
1004
|
function recordError(error) {
|
|
@@ -686,6 +1013,4 @@ function recordError(error) {
|
|
|
686
1013
|
};
|
|
687
1014
|
}
|
|
688
1015
|
//#endregion
|
|
689
|
-
export {
|
|
690
|
-
|
|
691
|
-
//# sourceMappingURL=src-ButXPY8P.mjs.map
|
|
1016
|
+
export { resourceUriSchema as $, TrialManifestSchema as A, NotJsonError as B, RunManifestSchema as C, RunSummarySchema as D, RunStatusSchema as E, normalizeAutEvent as F, relativeDatasetPath as G, toJsonObject as H, turnResultEvents as I, ResourceUriSchema as J, definitionSite as K, defineEvalMatrix as L, TrialScoringSchema as M, TrialSummarySchema as N, ScoreResultSchema as O, UsageSchema as P, resourceUri as Q, canonicalParameters as R, RecordedErrorSchema as S, RunSourceSchema as T, defineDataset as U, toJson as V, isDataset as W, authorId as X, UuidSchema as Y, parseResourceUri as Z, ArtifactEntrySchema as _, defineAgent as a, JsonValueSchema as b, expectToolCall as c, recordError as d, resourceUuid as et, registerEvals as f, ApiErrorSchema as g, parseTrajectoryJsonl as h, authoringId as i, TrialMetadataSchema as j, TrajectoryEventSchema as k, judge as l, user as m, agent as n, defineEval as o, skip as p, ResourceKindSchema as q, agentRuntimes as r, defineSuite as s, DEFAULT_AGENT_RUNTIMES as t, predicate as u, AutIdentitySchema as v, RunMetadataSchema as w, JudgeRunInfoSchema as x, CheckpointResultSchema as y, catalogEntry as z };
|