@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.
Files changed (45) hide show
  1. package/CHANGELOG.md +70 -6
  2. package/README.md +10 -8
  3. package/dist/cli.mjs +1227 -258
  4. package/dist/dashboard/assets/index-CTJpd8q8.js +34 -0
  5. package/dist/dashboard/assets/index-YAabTN3X.css +2 -0
  6. package/dist/dashboard/index.html +2 -2
  7. package/dist/files-C-U0-PWW.mjs +0 -2
  8. package/dist/index-db-vbqEGFaU.mjs +0 -2
  9. package/dist/index.d.mts +1346 -2
  10. package/dist/index.d.mts.map +1 -1
  11. package/dist/index.mjs +2 -4
  12. package/dist/runner.d.mts +809 -11
  13. package/dist/runner.d.mts.map +1 -1
  14. package/dist/runner.mjs +2 -2
  15. package/dist/share-worker.d.mts +76 -1
  16. package/dist/share-worker.d.mts.map +1 -1
  17. package/dist/share-worker.mjs +0 -2
  18. package/dist/share.d.mts +149 -6
  19. package/dist/share.d.mts.map +1 -1
  20. package/dist/share.mjs +1 -1
  21. package/dist/skills/evalkit/SKILL.md +32 -0
  22. package/dist/skills/evalkit-agents/SKILL.md +16 -0
  23. package/dist/skills/evalkit-datasets/SKILL.md +17 -0
  24. package/dist/skills/evalkit-evals/SKILL.md +19 -0
  25. package/dist/skills/evalkit-judges/SKILL.md +17 -0
  26. package/dist/skills/evalkit-matrices/SKILL.md +14 -0
  27. package/dist/skills/evalkit-results/SKILL.md +14 -0
  28. package/dist/{src-DoPs9Yug.mjs → src-CKqOzeBi.mjs} +448 -116
  29. package/dist/{src-ButXPY8P.mjs → src-CZPufWN_.mjs} +419 -94
  30. package/dist/{src-DzZueFn3.mjs → src-CZnDXP1K.mjs} +46 -10
  31. package/package.json +3 -2
  32. package/dist/cli.mjs.map +0 -1
  33. package/dist/dashboard/assets/index-D9NtA46z.css +0 -2
  34. package/dist/dashboard/assets/index-DrBwLKJD.js +0 -30
  35. package/dist/files-C-U0-PWW.mjs.map +0 -1
  36. package/dist/index-db-HdZXelOS.d.mts +0 -142
  37. package/dist/index-db-HdZXelOS.d.mts.map +0 -1
  38. package/dist/index-db-vbqEGFaU.mjs.map +0 -1
  39. package/dist/index-lOw0fmak.d.mts +0 -1028
  40. package/dist/index-lOw0fmak.d.mts.map +0 -1
  41. package/dist/index.mjs.map +0 -1
  42. package/dist/share-worker.mjs.map +0 -1
  43. package/dist/src-ButXPY8P.mjs.map +0 -1
  44. package/dist/src-DoPs9Yug.mjs.map +0 -1
  45. 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
- function predicate(name, run, options = {}) {
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 { TrajectoryEventSchema as A, UuidSchema as B, RecordedErrorSchema as C, RunStatusSchema as D, RunSourceSchema as E, UsageSchema as F, resourceUuid as G, parseResourceUri as H, defineEvalMatrix as I, canonicalParameters as L, TrialMetadataSchema as M, TrialScoringSchema as N, RunSummarySchema as O, TrialSummarySchema as P, ResourceKindSchema as R, JudgeRunInfoSchema as S, RunMetadataSchema as T, resourceUri as U, authorId as V, resourceUriSchema 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, TrialManifestSchema as j, ScoreResultSchema 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, ResourceUriSchema as z };
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 };