@leostera/evalkit 0.0.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/LICENSE +21 -0
- package/README.md +51 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +9062 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/dashboard/assets/index-B2P48MWY.css +1 -0
- package/dist/dashboard/assets/index-Z5UamLUC.js +261 -0
- package/dist/dashboard/index.html +13 -0
- package/dist/index-BwNYw4-_.d.mts +939 -0
- package/dist/index-BwNYw4-_.d.mts.map +1 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +79 -0
- package/dist/index.mjs.map +1 -0
- package/dist/runner.d.mts +290 -0
- package/dist/runner.d.mts.map +1 -0
- package/dist/runner.mjs +2 -0
- package/dist/src-CopGdrwX.mjs +674 -0
- package/dist/src-CopGdrwX.mjs.map +1 -0
- package/dist/src-DJDem6nZ.mjs +995 -0
- package/dist/src-DJDem6nZ.mjs.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
//#region ../core/src/identity.ts
|
|
3
|
+
const ResourceKindSchema = Schema.Literal("run", "trial", "artifact");
|
|
4
|
+
/** Human-authored project-local identifier; never a generated resource URI. */
|
|
5
|
+
function authorId(value) {
|
|
6
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value)) throw new Error(`ID must be lowercase kebab-case: ${value}`);
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
/** RFC 4122 textual UUID. EvalKit accepts v4/v7 and other valid UUID versions. */
|
|
10
|
+
const UuidSchema = Schema.String.pipe(Schema.pattern(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i));
|
|
11
|
+
const ResourceUriSchema = Schema.String.pipe(Schema.pattern(/^evalkit:(run|trial|artifact):[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i));
|
|
12
|
+
function resourceUriSchema(kind) {
|
|
13
|
+
return Schema.String.pipe(Schema.pattern(new RegExp(`^evalkit:${kind}:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$`, "i")));
|
|
14
|
+
}
|
|
15
|
+
function resourceUri(kind, uuid) {
|
|
16
|
+
return `evalkit:${kind}:${uuid}`;
|
|
17
|
+
}
|
|
18
|
+
function parseResourceUri(value, expectedKind) {
|
|
19
|
+
const match = /^evalkit:(run|trial|artifact):(.+)$/.exec(value);
|
|
20
|
+
if (!match) throw new Error(`Invalid EvalKit resource URI: ${value}`);
|
|
21
|
+
const kind = match[1];
|
|
22
|
+
if (expectedKind && kind !== expectedKind) throw new Error(`Expected an EvalKit ${expectedKind} URI; received ${value}`);
|
|
23
|
+
const uuid = Schema.decodeUnknownSync(UuidSchema)(match[2]);
|
|
24
|
+
return {
|
|
25
|
+
kind,
|
|
26
|
+
uuid,
|
|
27
|
+
uri: resourceUri(kind, uuid)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function resourceUuid(value, expectedKind) {
|
|
31
|
+
return parseResourceUri(value, expectedKind).uuid;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region ../core/src/matrix.ts
|
|
35
|
+
/** Canonical JSON: keys sorted recursively, array order preserved. Rejects non-JSON inputs. */
|
|
36
|
+
function canonicalParameters(value) {
|
|
37
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
|
|
38
|
+
if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value);
|
|
39
|
+
if (Array.isArray(value)) return `[${value.map(canonicalParameters).join(",")}]`;
|
|
40
|
+
if (typeof value === "object" && Object.getPrototypeOf(value) === Object.prototype) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalParameters(value[key])}`).join(",")}}`;
|
|
41
|
+
throw new Error("Matrix parameters must be finite JSON values");
|
|
42
|
+
}
|
|
43
|
+
const COUNT_BUDGET = 1e5;
|
|
44
|
+
const equal = (a, b) => canonicalParameters(a) === canonicalParameters(b);
|
|
45
|
+
const matches = (pattern, values) => Object.entries(pattern).every(([key, value]) => Object.hasOwn(values, key) && equal(values[key], value));
|
|
46
|
+
function defineEvalMatrix(definition) {
|
|
47
|
+
authoringId(definition);
|
|
48
|
+
const identities = /* @__PURE__ */ new Set();
|
|
49
|
+
for (const evaluation of definition.evals) {
|
|
50
|
+
const id = authoringId(evaluation);
|
|
51
|
+
if (identities.has(id)) throw new Error(`Duplicate matrix eval: ${id}`);
|
|
52
|
+
identities.add(id);
|
|
53
|
+
}
|
|
54
|
+
const axes = Object.entries(definition.parameters).sort(([a], [b]) => a.localeCompare(b));
|
|
55
|
+
for (const [axis, choices] of axes) {
|
|
56
|
+
if (!axis || !choices.length) throw new Error(`Matrix axis ${axis} must have at least one value`);
|
|
57
|
+
const keys = choices.map(canonicalParameters);
|
|
58
|
+
if (new Set(keys).size !== keys.length) throw new Error(`Duplicate values for matrix axis: ${axis}`);
|
|
59
|
+
}
|
|
60
|
+
canonicalParameters(definition.defaults ?? {});
|
|
61
|
+
if (definition.cases && !definition.cases.length) throw new Error("Matrix cases must have at least one assignment");
|
|
62
|
+
const cases = definition.cases ?? [{}];
|
|
63
|
+
const caseKeys = Object.keys(cases[0]).sort();
|
|
64
|
+
const caseSignatures = /* @__PURE__ */ new Set();
|
|
65
|
+
for (const assignment of cases) {
|
|
66
|
+
canonicalParameters(assignment);
|
|
67
|
+
if (Object.keys(assignment).sort().join("\0") !== caseKeys.join("\0")) throw new Error("Matrix cases must have the same dimensions");
|
|
68
|
+
for (const key of caseKeys) if (Object.hasOwn(definition.parameters, key) || Object.hasOwn(definition.defaults ?? {}, key)) throw new Error(`Matrix case dimension conflicts with axis or default: ${key}`);
|
|
69
|
+
const signature = canonicalParameters(assignment);
|
|
70
|
+
if (caseSignatures.has(signature)) throw new Error("Duplicate matrix case");
|
|
71
|
+
caseSignatures.add(signature);
|
|
72
|
+
}
|
|
73
|
+
const declared = /* @__PURE__ */ new Set([...caseKeys, ...axes.map(([key]) => key)]);
|
|
74
|
+
const exclusions = definition.exclude ?? [];
|
|
75
|
+
for (const [index, pattern] of exclusions.entries()) {
|
|
76
|
+
canonicalParameters(pattern);
|
|
77
|
+
if (!Object.keys(pattern).length) throw new Error(`Matrix exclude[${index}] must specify a dimension`);
|
|
78
|
+
for (const key of Object.keys(pattern)) if (!declared.has(key)) throw new Error(`Unknown matrix exclude dimension: ${key}`);
|
|
79
|
+
if (!cases.some((assignment) => Object.entries(pattern).every(([key, value]) => !Object.hasOwn(assignment, key) || equal(assignment[key], value))) || !axes.every(([key, choices]) => !Object.hasOwn(pattern, key) || choices.some((choice) => equal(choice, pattern[key])))) throw new Error(`Matrix exclude[${index}] matches no declared cell`);
|
|
80
|
+
}
|
|
81
|
+
const caseChoices = new Map(caseKeys.map((key) => [key, cases.map((assignment) => assignment[key])]));
|
|
82
|
+
function select(selection = {}) {
|
|
83
|
+
for (const key of Object.keys(selection.parameters ?? {})) if (!declared.has(key)) throw new Error(`Unknown matrix axis: ${key}`);
|
|
84
|
+
for (const key of Object.keys(selection.overrides ?? {})) if (declared.has(key)) throw new Error(`Select axis ${key}; do not override it`);
|
|
85
|
+
canonicalParameters(selection.overrides ?? {});
|
|
86
|
+
for (const name of selection.evals ?? []) if (!definition.evals.some((e) => e.id === name)) throw new Error(`Unknown matrix eval: ${name}`);
|
|
87
|
+
const evals = definition.evals.filter((e) => !selection.evals || selection.evals.includes(e.id));
|
|
88
|
+
const selected = /* @__PURE__ */ new Map();
|
|
89
|
+
for (const [key, values] of Object.entries(selection.parameters ?? {})) {
|
|
90
|
+
const available = definition.parameters[key] ?? caseChoices.get(key);
|
|
91
|
+
const keys = new Set(values.map(canonicalParameters));
|
|
92
|
+
for (const value of keys) if (!available.some((choice) => canonicalParameters(choice) === value)) throw new Error(`Unknown ${key} value: ${value}`);
|
|
93
|
+
selected.set(key, keys);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
evals,
|
|
97
|
+
cases: cases.filter((assignment) => caseKeys.every((key) => !selected.has(key) || selected.get(key).has(canonicalParameters(assignment[key])))),
|
|
98
|
+
axes: axes.map(([axis, choices]) => [axis, choices.filter((choice) => !selected.has(axis) || selected.get(axis).has(canonicalParameters(choice)))]),
|
|
99
|
+
defaults: {
|
|
100
|
+
...definition.defaults,
|
|
101
|
+
...selection.overrides
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/** Inclusion/exclusion counts sparse forbidden patterns without expanding the product. */
|
|
106
|
+
function countCase(assignment, selectedAxes, budget) {
|
|
107
|
+
const patterns = exclusions.filter((pattern) => Object.entries(pattern).every(([key, value]) => !Object.hasOwn(assignment, key) || equal(assignment[key], value))).map((pattern) => Object.fromEntries(Object.entries(pattern).filter(([key]) => !Object.hasOwn(assignment, key))));
|
|
108
|
+
const product = selectedAxes.reduce((count, [, values]) => count * values.length, 1);
|
|
109
|
+
if (!patterns.length) return product;
|
|
110
|
+
if (patterns.some((pattern) => !Object.keys(pattern).length)) return 0;
|
|
111
|
+
function intersection(pattern) {
|
|
112
|
+
return selectedAxes.reduce((count, [axis, choices]) => count * (Object.hasOwn(pattern, axis) ? Number(choices.some((choice) => equal(choice, pattern[axis]))) : choices.length), 1);
|
|
113
|
+
}
|
|
114
|
+
let eligible = product;
|
|
115
|
+
function visit(start, combined, sign) {
|
|
116
|
+
for (let index = start; index < patterns.length; index++) {
|
|
117
|
+
if (--budget.remaining < 0) throw new Error("Exact matrix count exceeds planning budget; narrow the selection or exclusions");
|
|
118
|
+
const pattern = patterns[index];
|
|
119
|
+
if (Object.entries(pattern).some(([key, value]) => Object.hasOwn(combined, key) && !equal(combined[key], value))) continue;
|
|
120
|
+
const merged = {
|
|
121
|
+
...combined,
|
|
122
|
+
...pattern
|
|
123
|
+
};
|
|
124
|
+
const matches = intersection(merged);
|
|
125
|
+
if (!matches) continue;
|
|
126
|
+
eligible += sign * matches;
|
|
127
|
+
visit(index + 1, merged, -sign);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
visit(0, {}, -1);
|
|
131
|
+
return eligible;
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
...definition,
|
|
135
|
+
kind: "matrix",
|
|
136
|
+
count(selection) {
|
|
137
|
+
const selected = select(selection);
|
|
138
|
+
const budget = { remaining: COUNT_BUDGET };
|
|
139
|
+
const count = selected.cases.reduce((count, assignment) => count + countCase(assignment, selected.axes, budget), 0) * selected.evals.length;
|
|
140
|
+
if (!Number.isSafeInteger(count)) throw new Error("Matrix exceeds safe cell count");
|
|
141
|
+
return count;
|
|
142
|
+
},
|
|
143
|
+
*cells(selection) {
|
|
144
|
+
const selected = select(selection);
|
|
145
|
+
function* expand(index, values) {
|
|
146
|
+
if (index === selected.axes.length) {
|
|
147
|
+
yield values;
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const [axis, choices] = selected.axes[index];
|
|
151
|
+
for (const choice of choices) yield* expand(index + 1, {
|
|
152
|
+
...values,
|
|
153
|
+
[axis]: choice
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
for (const evaluation of selected.evals) for (const assignment of selected.cases) for (const dimensions of expand(0, assignment)) {
|
|
157
|
+
if (exclusions.some((pattern) => matches(pattern, dimensions))) continue;
|
|
158
|
+
const parameters = {
|
|
159
|
+
...selected.defaults,
|
|
160
|
+
...dimensions
|
|
161
|
+
};
|
|
162
|
+
yield {
|
|
163
|
+
matrixId: definition.id,
|
|
164
|
+
eval: evaluation,
|
|
165
|
+
parameters,
|
|
166
|
+
key: canonicalParameters({
|
|
167
|
+
matrix: authoringId(definition),
|
|
168
|
+
eval: authoringId(evaluation),
|
|
169
|
+
parameters
|
|
170
|
+
})
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region ../core/src/schema.ts
|
|
178
|
+
/** Runtime schemas for serialized EvalKit report and API boundaries. */
|
|
179
|
+
const RunStatusSchema = Schema.Literal("running", "completed", "failed", "cancelled");
|
|
180
|
+
const RecordedErrorSchema = Schema.Struct({
|
|
181
|
+
name: Schema.String,
|
|
182
|
+
message: Schema.String,
|
|
183
|
+
stack: Schema.optional(Schema.String)
|
|
184
|
+
});
|
|
185
|
+
const AutIdentitySchema = Schema.Struct({
|
|
186
|
+
name: Schema.optional(Schema.String),
|
|
187
|
+
kind: Schema.String,
|
|
188
|
+
id: Schema.String,
|
|
189
|
+
version: Schema.optional(Schema.String)
|
|
190
|
+
});
|
|
191
|
+
const JsonValueSchema = Schema.suspend(() => Schema.Union(Schema.Null, Schema.Boolean, Schema.Number, Schema.String, Schema.mutable(Schema.Array(JsonValueSchema)), Schema.Record({
|
|
192
|
+
key: Schema.String,
|
|
193
|
+
value: JsonValueSchema
|
|
194
|
+
})));
|
|
195
|
+
const ParametersSchema = Schema.Record({
|
|
196
|
+
key: Schema.String,
|
|
197
|
+
value: JsonValueSchema
|
|
198
|
+
});
|
|
199
|
+
const MatrixCellSchema = Schema.Struct({
|
|
200
|
+
id: Schema.String,
|
|
201
|
+
cellKey: Schema.String
|
|
202
|
+
});
|
|
203
|
+
const RunMetadataSchema = Schema.Struct({
|
|
204
|
+
schemaVersion: Schema.Literal(2, 3),
|
|
205
|
+
runUri: resourceUriSchema("run"),
|
|
206
|
+
evalId: Schema.String,
|
|
207
|
+
suiteId: Schema.optional(Schema.String),
|
|
208
|
+
parameters: Schema.optional(ParametersSchema),
|
|
209
|
+
matrix: Schema.optional(MatrixCellSchema),
|
|
210
|
+
aut: Schema.optional(AutIdentitySchema),
|
|
211
|
+
startedAt: Schema.String
|
|
212
|
+
});
|
|
213
|
+
const TrialMetadataSchema = Schema.Struct({
|
|
214
|
+
schemaVersion: Schema.Literal(2, 3),
|
|
215
|
+
runUri: resourceUriSchema("run"),
|
|
216
|
+
trialUri: resourceUriSchema("trial"),
|
|
217
|
+
trialIndex: Schema.Number,
|
|
218
|
+
evalId: Schema.String,
|
|
219
|
+
parameters: Schema.optional(ParametersSchema),
|
|
220
|
+
matrix: Schema.optional(MatrixCellSchema),
|
|
221
|
+
aut: Schema.optional(AutIdentitySchema),
|
|
222
|
+
startedAt: Schema.String
|
|
223
|
+
});
|
|
224
|
+
/** On-disk manifests include a lifecycle status; older finalized manifests may still say running. */
|
|
225
|
+
const RunManifestSchema = Schema.Struct({
|
|
226
|
+
...RunMetadataSchema.fields,
|
|
227
|
+
status: Schema.optional(RunStatusSchema)
|
|
228
|
+
});
|
|
229
|
+
const TrialManifestSchema = Schema.Struct({
|
|
230
|
+
...TrialMetadataSchema.fields,
|
|
231
|
+
status: Schema.optional(RunStatusSchema)
|
|
232
|
+
});
|
|
233
|
+
const UsageSchema = Schema.Struct({
|
|
234
|
+
inputTokens: Schema.optional(Schema.Number),
|
|
235
|
+
outputTokens: Schema.optional(Schema.Number),
|
|
236
|
+
totalTokens: Schema.optional(Schema.Number)
|
|
237
|
+
});
|
|
238
|
+
const JudgeRunInfoSchema = Schema.Struct({
|
|
239
|
+
agent: Schema.optional(Schema.Struct({
|
|
240
|
+
id: Schema.String,
|
|
241
|
+
kind: Schema.String,
|
|
242
|
+
name: Schema.optional(Schema.String),
|
|
243
|
+
version: Schema.optional(Schema.String)
|
|
244
|
+
})),
|
|
245
|
+
usage: Schema.optional(UsageSchema),
|
|
246
|
+
events: Schema.optional(Schema.mutable(Schema.Array(JsonValueSchema)))
|
|
247
|
+
});
|
|
248
|
+
const ScoreResultSchema = Schema.Struct({
|
|
249
|
+
name: Schema.String,
|
|
250
|
+
kind: Schema.Literal("predicate", "judge"),
|
|
251
|
+
value: Schema.optional(Schema.Number),
|
|
252
|
+
passed: Schema.optional(Schema.Boolean),
|
|
253
|
+
explanation: Schema.optional(Schema.String),
|
|
254
|
+
evidence: Schema.optional(JsonValueSchema),
|
|
255
|
+
judge: Schema.optional(JudgeRunInfoSchema),
|
|
256
|
+
durationMs: Schema.Number,
|
|
257
|
+
error: Schema.optional(RecordedErrorSchema)
|
|
258
|
+
});
|
|
259
|
+
const CheckpointResultSchema = Schema.Struct({
|
|
260
|
+
step: Schema.Number,
|
|
261
|
+
kind: Schema.Literal("predicate", "judge", "expect-tool-call"),
|
|
262
|
+
name: Schema.String,
|
|
263
|
+
status: Schema.Literal("passed", "failed", "error", "skipped"),
|
|
264
|
+
value: Schema.optional(Schema.Number),
|
|
265
|
+
passed: Schema.optional(Schema.Boolean),
|
|
266
|
+
explanation: Schema.optional(Schema.String),
|
|
267
|
+
evidence: Schema.optional(JsonValueSchema),
|
|
268
|
+
judge: Schema.optional(JudgeRunInfoSchema),
|
|
269
|
+
durationMs: Schema.optional(Schema.Number),
|
|
270
|
+
error: Schema.optional(RecordedErrorSchema),
|
|
271
|
+
matchedToolCall: Schema.optional(Schema.Struct({
|
|
272
|
+
eventIndex: Schema.Number,
|
|
273
|
+
id: Schema.String
|
|
274
|
+
}))
|
|
275
|
+
});
|
|
276
|
+
const TrialScoringSchema = Schema.Struct({
|
|
277
|
+
results: Schema.mutable(Schema.Array(ScoreResultSchema)),
|
|
278
|
+
checkpoints: Schema.optional(Schema.mutable(Schema.Array(CheckpointResultSchema))),
|
|
279
|
+
skippedScorers: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
|
|
280
|
+
overall: Schema.optional(Schema.Number),
|
|
281
|
+
passed: Schema.Boolean
|
|
282
|
+
});
|
|
283
|
+
const ArtifactEntrySchema = Schema.Struct({
|
|
284
|
+
path: Schema.String,
|
|
285
|
+
kind: Schema.Literal("file", "directory"),
|
|
286
|
+
size: Schema.optional(Schema.Number)
|
|
287
|
+
});
|
|
288
|
+
const TrialSummarySchema = Schema.Struct({
|
|
289
|
+
status: RunStatusSchema,
|
|
290
|
+
endedAt: Schema.String,
|
|
291
|
+
durationMs: Schema.optional(Schema.Number),
|
|
292
|
+
scoring: Schema.optional(TrialScoringSchema),
|
|
293
|
+
artifacts: Schema.optional(Schema.mutable(Schema.Array(ArtifactEntrySchema))),
|
|
294
|
+
error: Schema.optional(RecordedErrorSchema)
|
|
295
|
+
});
|
|
296
|
+
const RunSummarySchema = Schema.Struct({
|
|
297
|
+
status: RunStatusSchema,
|
|
298
|
+
endedAt: Schema.String,
|
|
299
|
+
durationMs: Schema.optional(Schema.Number),
|
|
300
|
+
trialCount: Schema.Number,
|
|
301
|
+
passed: Schema.Number,
|
|
302
|
+
failed: Schema.Number,
|
|
303
|
+
error: Schema.optional(RecordedErrorSchema)
|
|
304
|
+
});
|
|
305
|
+
const autEvent = {
|
|
306
|
+
started: Schema.Struct({
|
|
307
|
+
source: Schema.Literal("aut"),
|
|
308
|
+
kind: Schema.Literal("started"),
|
|
309
|
+
timestamp: Schema.String
|
|
310
|
+
}),
|
|
311
|
+
message: Schema.Struct({
|
|
312
|
+
source: Schema.Literal("aut"),
|
|
313
|
+
kind: Schema.Literal("message"),
|
|
314
|
+
role: Schema.Literal("system", "user", "assistant", "tool"),
|
|
315
|
+
content: JsonValueSchema,
|
|
316
|
+
timestamp: Schema.String
|
|
317
|
+
}),
|
|
318
|
+
toolCall: Schema.Struct({
|
|
319
|
+
source: Schema.Literal("aut"),
|
|
320
|
+
kind: Schema.Literal("tool-call"),
|
|
321
|
+
id: Schema.String,
|
|
322
|
+
name: Schema.String,
|
|
323
|
+
arguments: JsonValueSchema,
|
|
324
|
+
timestamp: Schema.String
|
|
325
|
+
}),
|
|
326
|
+
toolResult: Schema.Struct({
|
|
327
|
+
source: Schema.Literal("aut"),
|
|
328
|
+
kind: Schema.Literal("tool-result"),
|
|
329
|
+
id: Schema.String,
|
|
330
|
+
name: Schema.optional(Schema.String),
|
|
331
|
+
result: JsonValueSchema,
|
|
332
|
+
timestamp: Schema.String
|
|
333
|
+
}),
|
|
334
|
+
turnStarted: Schema.Struct({
|
|
335
|
+
source: Schema.Literal("aut"),
|
|
336
|
+
kind: Schema.Literal("turn-started"),
|
|
337
|
+
turn: Schema.Number,
|
|
338
|
+
timestamp: Schema.String
|
|
339
|
+
}),
|
|
340
|
+
turnCompleted: Schema.Struct({
|
|
341
|
+
source: Schema.Literal("aut"),
|
|
342
|
+
kind: Schema.Literal("turn-completed"),
|
|
343
|
+
turn: Schema.Number,
|
|
344
|
+
timestamp: Schema.String,
|
|
345
|
+
latencyMs: Schema.optional(Schema.Number),
|
|
346
|
+
usage: Schema.optional(UsageSchema)
|
|
347
|
+
}),
|
|
348
|
+
completed: Schema.Struct({
|
|
349
|
+
source: Schema.Literal("aut"),
|
|
350
|
+
kind: Schema.Literal("completed"),
|
|
351
|
+
output: Schema.optional(JsonValueSchema),
|
|
352
|
+
timestamp: Schema.String
|
|
353
|
+
}),
|
|
354
|
+
error: Schema.Struct({
|
|
355
|
+
source: Schema.Literal("aut"),
|
|
356
|
+
kind: Schema.Literal("error"),
|
|
357
|
+
error: RecordedErrorSchema,
|
|
358
|
+
timestamp: Schema.String
|
|
359
|
+
})
|
|
360
|
+
};
|
|
361
|
+
const runnerEvent = {
|
|
362
|
+
trialStarted: Schema.Struct({
|
|
363
|
+
source: Schema.Literal("runner"),
|
|
364
|
+
kind: Schema.Literal("trial-started"),
|
|
365
|
+
timestamp: Schema.String
|
|
366
|
+
}),
|
|
367
|
+
stepStarted: Schema.Struct({
|
|
368
|
+
source: Schema.Literal("runner"),
|
|
369
|
+
kind: Schema.Literal("transcript-step-started"),
|
|
370
|
+
step: Schema.Number,
|
|
371
|
+
timestamp: Schema.String
|
|
372
|
+
}),
|
|
373
|
+
stepCompleted: Schema.Struct({
|
|
374
|
+
source: Schema.Literal("runner"),
|
|
375
|
+
kind: Schema.Literal("transcript-step-completed"),
|
|
376
|
+
step: Schema.Number,
|
|
377
|
+
timestamp: Schema.String
|
|
378
|
+
}),
|
|
379
|
+
stepSkipped: Schema.Struct({
|
|
380
|
+
source: Schema.Literal("runner"),
|
|
381
|
+
kind: Schema.Literal("transcript-step-skipped"),
|
|
382
|
+
step: Schema.Number,
|
|
383
|
+
timestamp: Schema.String
|
|
384
|
+
}),
|
|
385
|
+
checkpointStarted: Schema.Struct({
|
|
386
|
+
source: Schema.Literal("runner"),
|
|
387
|
+
kind: Schema.Literal("checkpoint-started"),
|
|
388
|
+
step: Schema.Number,
|
|
389
|
+
name: Schema.String,
|
|
390
|
+
timestamp: Schema.String
|
|
391
|
+
}),
|
|
392
|
+
checkpointCompleted: Schema.Struct({
|
|
393
|
+
source: Schema.Literal("runner"),
|
|
394
|
+
kind: Schema.Literal("checkpoint-completed"),
|
|
395
|
+
step: Schema.Number,
|
|
396
|
+
status: Schema.Literal("passed", "failed"),
|
|
397
|
+
timestamp: Schema.String
|
|
398
|
+
}),
|
|
399
|
+
checkpointError: Schema.Struct({
|
|
400
|
+
source: Schema.Literal("runner"),
|
|
401
|
+
kind: Schema.Literal("checkpoint-error"),
|
|
402
|
+
step: Schema.Number,
|
|
403
|
+
error: RecordedErrorSchema,
|
|
404
|
+
timestamp: Schema.String
|
|
405
|
+
}),
|
|
406
|
+
scorerStarted: Schema.Struct({
|
|
407
|
+
source: Schema.Literal("runner"),
|
|
408
|
+
kind: Schema.Literal("scorer-started"),
|
|
409
|
+
scorer: Schema.String,
|
|
410
|
+
timestamp: Schema.String
|
|
411
|
+
}),
|
|
412
|
+
scorerCompleted: Schema.Struct({
|
|
413
|
+
source: Schema.Literal("runner"),
|
|
414
|
+
kind: Schema.Literal("scorer-completed"),
|
|
415
|
+
scorer: Schema.String,
|
|
416
|
+
value: Schema.Number,
|
|
417
|
+
timestamp: Schema.String
|
|
418
|
+
}),
|
|
419
|
+
scorerFailed: Schema.Struct({
|
|
420
|
+
source: Schema.Literal("runner"),
|
|
421
|
+
kind: Schema.Literal("scorer-failed"),
|
|
422
|
+
scorer: Schema.String,
|
|
423
|
+
error: RecordedErrorSchema,
|
|
424
|
+
timestamp: Schema.String
|
|
425
|
+
}),
|
|
426
|
+
trialCompleted: Schema.Struct({
|
|
427
|
+
source: Schema.Literal("runner"),
|
|
428
|
+
kind: Schema.Literal("trial-completed"),
|
|
429
|
+
timestamp: Schema.String
|
|
430
|
+
}),
|
|
431
|
+
error: Schema.Struct({
|
|
432
|
+
source: Schema.Literal("runner"),
|
|
433
|
+
kind: Schema.Literal("error"),
|
|
434
|
+
error: RecordedErrorSchema,
|
|
435
|
+
timestamp: Schema.String
|
|
436
|
+
})
|
|
437
|
+
};
|
|
438
|
+
const TrajectoryEventSchema = Schema.Union(...Object.values(autEvent), ...Object.values(runnerEvent));
|
|
439
|
+
const ApiErrorSchema = Schema.Struct({
|
|
440
|
+
error: Schema.String,
|
|
441
|
+
message: Schema.String
|
|
442
|
+
});
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region ../core/src/trajectory.ts
|
|
445
|
+
/** Decode one private report's JSONL trajectory; reject malformed/non-event lines with their line number. */
|
|
446
|
+
function parseTrajectoryJsonl(contents) {
|
|
447
|
+
const events = [];
|
|
448
|
+
for (const [index, line] of contents.split(/\r?\n/).entries()) {
|
|
449
|
+
if (!line.trim()) continue;
|
|
450
|
+
try {
|
|
451
|
+
events.push(Schema.decodeUnknownSync(TrajectoryEventSchema)(JSON.parse(line)));
|
|
452
|
+
} catch (cause) {
|
|
453
|
+
throw new Error(`Invalid trajectory JSONL at line ${index + 1}`, { cause });
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return events;
|
|
457
|
+
}
|
|
458
|
+
//#endregion
|
|
459
|
+
//#region ../core/src/index.ts
|
|
460
|
+
/**
|
|
461
|
+
* Defines an Agent Under Test without coupling it to a runtime or transport.
|
|
462
|
+
* It preserves the adapter's concrete type for application-specific helpers.
|
|
463
|
+
*/
|
|
464
|
+
function defineAgent(agent) {
|
|
465
|
+
if (agent.identity) authoringId(agent.identity);
|
|
466
|
+
return agent;
|
|
467
|
+
}
|
|
468
|
+
function defaultFixtureDestination(src) {
|
|
469
|
+
const normalized = src.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
470
|
+
const destination = normalized.slice(normalized.lastIndexOf("/") + 1);
|
|
471
|
+
if (!destination || destination === "." || destination === "..") throw new Error(`Fixture source needs a basename: ${src}`);
|
|
472
|
+
return destination;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Declares a directory relative to the invoking project's working directory.
|
|
476
|
+
* The short form is candidate-visible and copies beneath the source basename.
|
|
477
|
+
*/
|
|
478
|
+
function directory(src, options = {}) {
|
|
479
|
+
return {
|
|
480
|
+
kind: "directory",
|
|
481
|
+
src,
|
|
482
|
+
dst: options.dst ?? defaultFixtureDestination(src),
|
|
483
|
+
visibility: options.visibility ?? "candidate"
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
function file(src, options) {
|
|
487
|
+
return {
|
|
488
|
+
kind: "file",
|
|
489
|
+
src,
|
|
490
|
+
...options
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function inlineFile(file, data, visibility) {
|
|
494
|
+
return {
|
|
495
|
+
kind: "inline",
|
|
496
|
+
file,
|
|
497
|
+
data,
|
|
498
|
+
visibility
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function dynamic(create) {
|
|
502
|
+
return {
|
|
503
|
+
kind: "dynamic",
|
|
504
|
+
create
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/** Observes a tool call in the preceding turn; never invokes a tool. */
|
|
508
|
+
function expectToolCall(expected) {
|
|
509
|
+
if (!expected.name.trim()) throw new Error("Expected tool name must not be empty");
|
|
510
|
+
return {
|
|
511
|
+
kind: "expect-tool-call",
|
|
512
|
+
name: expected.name,
|
|
513
|
+
expected
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
function user(message) {
|
|
517
|
+
return {
|
|
518
|
+
kind: "user",
|
|
519
|
+
message
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function agent(expectation) {
|
|
523
|
+
return {
|
|
524
|
+
kind: "agent",
|
|
525
|
+
expectation
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function predicate(name, run, options = {}) {
|
|
529
|
+
return {
|
|
530
|
+
kind: "predicate",
|
|
531
|
+
name,
|
|
532
|
+
run,
|
|
533
|
+
...options
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
function judge(name, options) {
|
|
537
|
+
if (!name.trim() || !options.rubric.trim()) throw new Error("Judge name and rubric must not be empty");
|
|
538
|
+
return {
|
|
539
|
+
kind: "judge",
|
|
540
|
+
name,
|
|
541
|
+
...options
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function defineEval(definition) {
|
|
545
|
+
authoringId(definition);
|
|
546
|
+
let hasUser = false;
|
|
547
|
+
for (const step of definition.transcript) if (step.kind === "user") hasUser = true;
|
|
548
|
+
else if (step.kind !== "agent" && !hasUser) throw new Error("Checkpoint requires a preceding user step");
|
|
549
|
+
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");
|
|
550
|
+
if (definition.judge && definition.judge === definition.agent) throw new Error("Judge agent must be distinct from the agent under test");
|
|
551
|
+
return definition;
|
|
552
|
+
}
|
|
553
|
+
function defineSuite(suite) {
|
|
554
|
+
authoringId(suite);
|
|
555
|
+
return suite;
|
|
556
|
+
}
|
|
557
|
+
function authoringId(value) {
|
|
558
|
+
if ("uri" in value || "uuid" in value || "slug" in value) throw new Error("Authored resources use id, not uri, uuid, or slug");
|
|
559
|
+
return authorId(value.id);
|
|
560
|
+
}
|
|
561
|
+
function isEvalMatrix(registration) {
|
|
562
|
+
return "kind" in registration && registration.kind === "matrix";
|
|
563
|
+
}
|
|
564
|
+
function isEvalSuite(registration) {
|
|
565
|
+
return !isEvalMatrix(registration) && "evals" in registration;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Creates an explicit, statically imported eval registry. A suite is a
|
|
569
|
+
* path-like grouping of evals; nesting is presentation derived from its ID.
|
|
570
|
+
*/
|
|
571
|
+
function registerEvals(registrations) {
|
|
572
|
+
const byId = /* @__PURE__ */ new Map();
|
|
573
|
+
const suiteById = /* @__PURE__ */ new Map();
|
|
574
|
+
const suiteIdByEvalId = /* @__PURE__ */ new Map();
|
|
575
|
+
const standalone = [];
|
|
576
|
+
const matrices = [];
|
|
577
|
+
for (const registration of registrations) {
|
|
578
|
+
if (isEvalMatrix(registration)) {
|
|
579
|
+
const id = authoringId(registration);
|
|
580
|
+
if (matrices.some((matrix) => authoringId(matrix) === id)) throw new Error(`Eval registry contains duplicate matrix ID: ${id}`);
|
|
581
|
+
matrices.push(registration);
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
const suite = isEvalSuite(registration) ? registration : void 0;
|
|
585
|
+
if (suite) {
|
|
586
|
+
const id = authoringId(suite);
|
|
587
|
+
if (suiteById.has(id)) throw new Error(`Eval registry contains duplicate suite ID: ${id}`);
|
|
588
|
+
suiteById.set(id, suite);
|
|
589
|
+
}
|
|
590
|
+
const evaluations = suite ? suite.evals : [registration];
|
|
591
|
+
for (const evaluation of evaluations) {
|
|
592
|
+
const id = authoringId(evaluation);
|
|
593
|
+
if (byId.has(id)) throw new Error(`Eval registry contains duplicate eval ID: ${id}`);
|
|
594
|
+
byId.set(id, evaluation);
|
|
595
|
+
if (suite) suiteIdByEvalId.set(id, suite);
|
|
596
|
+
else standalone.push(evaluation);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
const evals = [...standalone, ...Array.from(suiteById.values()).flatMap((suite) => suite.evals)];
|
|
600
|
+
return {
|
|
601
|
+
evals,
|
|
602
|
+
suites: [...suiteById.values()],
|
|
603
|
+
matrices,
|
|
604
|
+
get: (id) => byId.get(id),
|
|
605
|
+
getSuite: (id) => suiteById.get(id),
|
|
606
|
+
metadata: () => evals.map((evaluation) => {
|
|
607
|
+
const suite = suiteIdByEvalId.get(authoringId(evaluation));
|
|
608
|
+
return {
|
|
609
|
+
id: evaluation.id,
|
|
610
|
+
...evaluation.name ? { name: evaluation.name } : {},
|
|
611
|
+
...suite ? { suiteId: suite.id } : {}
|
|
612
|
+
};
|
|
613
|
+
}),
|
|
614
|
+
suiteMetadata: () => [...suiteById.values()].map((suite) => ({
|
|
615
|
+
id: suite.id,
|
|
616
|
+
evalIds: suite.evals.map(authoringId),
|
|
617
|
+
...suite.name ? { name: suite.name } : {}
|
|
618
|
+
})),
|
|
619
|
+
catalog: () => evals.map((evaluation) => {
|
|
620
|
+
const suite = suiteIdByEvalId.get(authoringId(evaluation));
|
|
621
|
+
const identity = evaluation.agent.identity;
|
|
622
|
+
return {
|
|
623
|
+
id: evaluation.id,
|
|
624
|
+
path: suite ? `${suite.id}#${evaluation.id}` : evaluation.id,
|
|
625
|
+
...evaluation.name ? { name: evaluation.name } : {},
|
|
626
|
+
...suite ? { suiteId: suite.id } : {},
|
|
627
|
+
agent: {
|
|
628
|
+
...identity?.name ? { name: identity.name } : {},
|
|
629
|
+
kind: identity?.kind ?? "adapter",
|
|
630
|
+
...identity?.id ? { id: identity.id } : {},
|
|
631
|
+
...identity?.version ? { version: identity.version } : {},
|
|
632
|
+
runtimes: Object.entries(evaluation.agent.runtimes ?? {}).map(([name, runtime]) => ({
|
|
633
|
+
name,
|
|
634
|
+
kind: runtime.kind
|
|
635
|
+
}))
|
|
636
|
+
},
|
|
637
|
+
fixtures: (evaluation.fixtures ?? []).map((fixture) => fixture.kind === "dynamic" ? {
|
|
638
|
+
kind: "dynamic",
|
|
639
|
+
source: "dynamic"
|
|
640
|
+
} : fixture.kind === "inline" ? {
|
|
641
|
+
kind: "inline",
|
|
642
|
+
source: fixture.file,
|
|
643
|
+
destination: fixture.file,
|
|
644
|
+
visibility: fixture.visibility
|
|
645
|
+
} : {
|
|
646
|
+
kind: fixture.kind,
|
|
647
|
+
source: fixture.src,
|
|
648
|
+
destination: fixture.dst,
|
|
649
|
+
visibility: fixture.visibility
|
|
650
|
+
}),
|
|
651
|
+
trialCount: evaluation.policy?.trials ?? 1,
|
|
652
|
+
scorers: evaluation.scoring.map(({ name, kind }) => ({
|
|
653
|
+
name,
|
|
654
|
+
kind
|
|
655
|
+
}))
|
|
656
|
+
};
|
|
657
|
+
})
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
function recordError(error) {
|
|
661
|
+
if (error instanceof Error) return {
|
|
662
|
+
name: error.name,
|
|
663
|
+
message: error.message,
|
|
664
|
+
...error.stack ? { stack: error.stack } : {}
|
|
665
|
+
};
|
|
666
|
+
return {
|
|
667
|
+
name: "Error",
|
|
668
|
+
message: String(error)
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
//#endregion
|
|
672
|
+
export { TrialManifestSchema as A, authorId as B, RecordedErrorSchema as C, RunSummarySchema as D, RunStatusSchema as E, canonicalParameters as F, resourceUri as H, defineEvalMatrix as I, ResourceKindSchema as L, TrialScoringSchema as M, TrialSummarySchema as N, ScoreResultSchema as O, UsageSchema as P, ResourceUriSchema as R, JudgeRunInfoSchema as S, RunMetadataSchema as T, resourceUriSchema as U, parseResourceUri as V, resourceUuid as W, ApiErrorSchema as _, defineSuite as a, CheckpointResultSchema as b, expectToolCall as c, judge as d, predicate as f, parseTrajectoryJsonl as g, user as h, defineEval as i, TrialMetadataSchema as j, TrajectoryEventSchema as k, file as l, registerEvals as m, authoringId as n, directory as o, recordError as p, defineAgent as r, dynamic as s, agent as t, inlineFile as u, ArtifactEntrySchema as v, RunManifestSchema as w, JsonValueSchema as x, AutIdentitySchema as y, UuidSchema as z };
|
|
673
|
+
|
|
674
|
+
//# sourceMappingURL=src-CopGdrwX.mjs.map
|