@agentv/core 0.2.3
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 +78 -0
- package/dist/chunk-5REK5RSI.js +86 -0
- package/dist/chunk-5REK5RSI.js.map +1 -0
- package/dist/evaluation/validation/index.cjs +617 -0
- package/dist/evaluation/validation/index.cjs.map +1 -0
- package/dist/evaluation/validation/index.d.cts +56 -0
- package/dist/evaluation/validation/index.d.ts +56 -0
- package/dist/evaluation/validation/index.js +499 -0
- package/dist/evaluation/validation/index.js.map +1 -0
- package/dist/index.cjs +2204 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +406 -0
- package/dist/index.d.ts +406 -0
- package/dist/index.js +2079 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildSearchRoots,
|
|
3
|
+
findGitRoot,
|
|
4
|
+
resolveFileReference
|
|
5
|
+
} from "../../chunk-5REK5RSI.js";
|
|
6
|
+
|
|
7
|
+
// src/evaluation/validation/file-type.ts
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
|
+
import { parse } from "yaml";
|
|
10
|
+
var SCHEMA_EVAL_V2 = "agentv-eval-v2";
|
|
11
|
+
var SCHEMA_TARGETS_V2 = "agentv-targets-v2";
|
|
12
|
+
async function detectFileType(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
const content = await readFile(filePath, "utf8");
|
|
15
|
+
const parsed = parse(content);
|
|
16
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
17
|
+
return "unknown";
|
|
18
|
+
}
|
|
19
|
+
const record = parsed;
|
|
20
|
+
const schema = record["$schema"];
|
|
21
|
+
if (typeof schema !== "string") {
|
|
22
|
+
return "unknown";
|
|
23
|
+
}
|
|
24
|
+
switch (schema) {
|
|
25
|
+
case SCHEMA_EVAL_V2:
|
|
26
|
+
return "eval";
|
|
27
|
+
case SCHEMA_TARGETS_V2:
|
|
28
|
+
return "targets";
|
|
29
|
+
default:
|
|
30
|
+
return "unknown";
|
|
31
|
+
}
|
|
32
|
+
} catch {
|
|
33
|
+
return "unknown";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function isValidSchema(schema) {
|
|
37
|
+
return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2;
|
|
38
|
+
}
|
|
39
|
+
function getExpectedSchema(fileType) {
|
|
40
|
+
switch (fileType) {
|
|
41
|
+
case "eval":
|
|
42
|
+
return SCHEMA_EVAL_V2;
|
|
43
|
+
case "targets":
|
|
44
|
+
return SCHEMA_TARGETS_V2;
|
|
45
|
+
default:
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/evaluation/validation/eval-validator.ts
|
|
51
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
52
|
+
import path from "node:path";
|
|
53
|
+
import { parse as parse2 } from "yaml";
|
|
54
|
+
var SCHEMA_EVAL_V22 = "agentv-eval-v2";
|
|
55
|
+
function isObject(value) {
|
|
56
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
57
|
+
}
|
|
58
|
+
async function validateEvalFile(filePath) {
|
|
59
|
+
const errors = [];
|
|
60
|
+
const absolutePath = path.resolve(filePath);
|
|
61
|
+
let parsed;
|
|
62
|
+
try {
|
|
63
|
+
const content = await readFile2(absolutePath, "utf8");
|
|
64
|
+
parsed = parse2(content);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
errors.push({
|
|
67
|
+
severity: "error",
|
|
68
|
+
filePath: absolutePath,
|
|
69
|
+
message: `Failed to parse YAML: ${error.message}`
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
valid: false,
|
|
73
|
+
filePath: absolutePath,
|
|
74
|
+
fileType: "eval",
|
|
75
|
+
errors
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (!isObject(parsed)) {
|
|
79
|
+
errors.push({
|
|
80
|
+
severity: "error",
|
|
81
|
+
filePath: absolutePath,
|
|
82
|
+
message: "File must contain a YAML object"
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
valid: false,
|
|
86
|
+
filePath: absolutePath,
|
|
87
|
+
fileType: "eval",
|
|
88
|
+
errors
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const schema = parsed["$schema"];
|
|
92
|
+
if (schema !== SCHEMA_EVAL_V22) {
|
|
93
|
+
const message = typeof schema === "string" ? `Invalid $schema value '${schema}'. Expected '${SCHEMA_EVAL_V22}'` : `Missing required field '$schema'. Expected '${SCHEMA_EVAL_V22}'`;
|
|
94
|
+
errors.push({
|
|
95
|
+
severity: "error",
|
|
96
|
+
filePath: absolutePath,
|
|
97
|
+
location: "$schema",
|
|
98
|
+
message
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const evalcases = parsed["evalcases"];
|
|
102
|
+
if (!Array.isArray(evalcases)) {
|
|
103
|
+
errors.push({
|
|
104
|
+
severity: "error",
|
|
105
|
+
filePath: absolutePath,
|
|
106
|
+
location: "evalcases",
|
|
107
|
+
message: "Missing or invalid 'evalcases' field (must be an array)"
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
valid: errors.length === 0,
|
|
111
|
+
filePath: absolutePath,
|
|
112
|
+
fileType: "eval",
|
|
113
|
+
errors
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
for (let i = 0; i < evalcases.length; i++) {
|
|
117
|
+
const evalCase = evalcases[i];
|
|
118
|
+
const location = `evalcases[${i}]`;
|
|
119
|
+
if (!isObject(evalCase)) {
|
|
120
|
+
errors.push({
|
|
121
|
+
severity: "error",
|
|
122
|
+
filePath: absolutePath,
|
|
123
|
+
location,
|
|
124
|
+
message: "Eval case must be an object"
|
|
125
|
+
});
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const id = evalCase["id"];
|
|
129
|
+
if (typeof id !== "string" || id.trim().length === 0) {
|
|
130
|
+
errors.push({
|
|
131
|
+
severity: "error",
|
|
132
|
+
filePath: absolutePath,
|
|
133
|
+
location: `${location}.id`,
|
|
134
|
+
message: "Missing or invalid 'id' field (must be a non-empty string)"
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const outcome = evalCase["outcome"];
|
|
138
|
+
if (typeof outcome !== "string" || outcome.trim().length === 0) {
|
|
139
|
+
errors.push({
|
|
140
|
+
severity: "error",
|
|
141
|
+
filePath: absolutePath,
|
|
142
|
+
location: `${location}.outcome`,
|
|
143
|
+
message: "Missing or invalid 'outcome' field (must be a non-empty string)"
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const inputMessages = evalCase["input_messages"];
|
|
147
|
+
if (!Array.isArray(inputMessages)) {
|
|
148
|
+
errors.push({
|
|
149
|
+
severity: "error",
|
|
150
|
+
filePath: absolutePath,
|
|
151
|
+
location: `${location}.input_messages`,
|
|
152
|
+
message: "Missing or invalid 'input_messages' field (must be an array)"
|
|
153
|
+
});
|
|
154
|
+
} else {
|
|
155
|
+
validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);
|
|
156
|
+
}
|
|
157
|
+
const expectedMessages = evalCase["expected_messages"];
|
|
158
|
+
if (!Array.isArray(expectedMessages)) {
|
|
159
|
+
errors.push({
|
|
160
|
+
severity: "error",
|
|
161
|
+
filePath: absolutePath,
|
|
162
|
+
location: `${location}.expected_messages`,
|
|
163
|
+
message: "Missing or invalid 'expected_messages' field (must be an array)"
|
|
164
|
+
});
|
|
165
|
+
} else {
|
|
166
|
+
validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
valid: errors.length === 0,
|
|
171
|
+
filePath: absolutePath,
|
|
172
|
+
fileType: "eval",
|
|
173
|
+
errors
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function validateMessages(messages, location, filePath, errors) {
|
|
177
|
+
for (let i = 0; i < messages.length; i++) {
|
|
178
|
+
const message = messages[i];
|
|
179
|
+
const msgLocation = `${location}[${i}]`;
|
|
180
|
+
if (!isObject(message)) {
|
|
181
|
+
errors.push({
|
|
182
|
+
severity: "error",
|
|
183
|
+
filePath,
|
|
184
|
+
location: msgLocation,
|
|
185
|
+
message: "Message must be an object"
|
|
186
|
+
});
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const role = message["role"];
|
|
190
|
+
const validRoles = ["system", "user", "assistant"];
|
|
191
|
+
if (!validRoles.includes(role)) {
|
|
192
|
+
errors.push({
|
|
193
|
+
severity: "error",
|
|
194
|
+
filePath,
|
|
195
|
+
location: `${msgLocation}.role`,
|
|
196
|
+
message: `Invalid role '${role}'. Must be one of: ${validRoles.join(", ")}`
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const content = message["content"];
|
|
200
|
+
if (typeof content === "string") {
|
|
201
|
+
} else if (Array.isArray(content)) {
|
|
202
|
+
for (let j = 0; j < content.length; j++) {
|
|
203
|
+
const contentItem = content[j];
|
|
204
|
+
const contentLocation = `${msgLocation}.content[${j}]`;
|
|
205
|
+
if (typeof contentItem === "string") {
|
|
206
|
+
} else if (isObject(contentItem)) {
|
|
207
|
+
const type = contentItem["type"];
|
|
208
|
+
if (typeof type !== "string") {
|
|
209
|
+
errors.push({
|
|
210
|
+
severity: "error",
|
|
211
|
+
filePath,
|
|
212
|
+
location: `${contentLocation}.type`,
|
|
213
|
+
message: "Content object must have a 'type' field"
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
if (type === "text") {
|
|
217
|
+
const value = contentItem["value"];
|
|
218
|
+
if (typeof value !== "string") {
|
|
219
|
+
errors.push({
|
|
220
|
+
severity: "error",
|
|
221
|
+
filePath,
|
|
222
|
+
location: `${contentLocation}.value`,
|
|
223
|
+
message: "Content with type 'text' must have a 'value' field"
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
errors.push({
|
|
229
|
+
severity: "error",
|
|
230
|
+
filePath,
|
|
231
|
+
location: contentLocation,
|
|
232
|
+
message: "Content array items must be strings or objects"
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
errors.push({
|
|
238
|
+
severity: "error",
|
|
239
|
+
filePath,
|
|
240
|
+
location: `${msgLocation}.content`,
|
|
241
|
+
message: "Missing or invalid 'content' field (must be a string or array)"
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/evaluation/validation/targets-validator.ts
|
|
248
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
249
|
+
import path2 from "node:path";
|
|
250
|
+
import { parse as parse3 } from "yaml";
|
|
251
|
+
var SCHEMA_TARGETS_V22 = "agentv-targets-v2";
|
|
252
|
+
function isObject2(value) {
|
|
253
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
254
|
+
}
|
|
255
|
+
async function validateTargetsFile(filePath) {
|
|
256
|
+
const errors = [];
|
|
257
|
+
const absolutePath = path2.resolve(filePath);
|
|
258
|
+
let parsed;
|
|
259
|
+
try {
|
|
260
|
+
const content = await readFile3(absolutePath, "utf8");
|
|
261
|
+
parsed = parse3(content);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
errors.push({
|
|
264
|
+
severity: "error",
|
|
265
|
+
filePath: absolutePath,
|
|
266
|
+
message: `Failed to parse YAML: ${error.message}`
|
|
267
|
+
});
|
|
268
|
+
return {
|
|
269
|
+
valid: false,
|
|
270
|
+
filePath: absolutePath,
|
|
271
|
+
fileType: "targets",
|
|
272
|
+
errors
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
if (!isObject2(parsed)) {
|
|
276
|
+
errors.push({
|
|
277
|
+
severity: "error",
|
|
278
|
+
filePath: absolutePath,
|
|
279
|
+
message: "File must contain a YAML object"
|
|
280
|
+
});
|
|
281
|
+
return {
|
|
282
|
+
valid: false,
|
|
283
|
+
filePath: absolutePath,
|
|
284
|
+
fileType: "targets",
|
|
285
|
+
errors
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const schema = parsed["$schema"];
|
|
289
|
+
if (schema !== SCHEMA_TARGETS_V22) {
|
|
290
|
+
const message = typeof schema === "string" ? `Invalid $schema value '${schema}'. Expected '${SCHEMA_TARGETS_V22}'` : `Missing required field '$schema'. Expected '${SCHEMA_TARGETS_V22}'`;
|
|
291
|
+
errors.push({
|
|
292
|
+
severity: "error",
|
|
293
|
+
filePath: absolutePath,
|
|
294
|
+
location: "$schema",
|
|
295
|
+
message
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
const targets = parsed["targets"];
|
|
299
|
+
if (!Array.isArray(targets)) {
|
|
300
|
+
errors.push({
|
|
301
|
+
severity: "error",
|
|
302
|
+
filePath: absolutePath,
|
|
303
|
+
location: "targets",
|
|
304
|
+
message: "Missing or invalid 'targets' field (must be an array)"
|
|
305
|
+
});
|
|
306
|
+
return {
|
|
307
|
+
valid: errors.length === 0,
|
|
308
|
+
filePath: absolutePath,
|
|
309
|
+
fileType: "targets",
|
|
310
|
+
errors
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const knownProviders = ["azure", "openai", "anthropic", "bedrock", "vertex"];
|
|
314
|
+
for (let i = 0; i < targets.length; i++) {
|
|
315
|
+
const target = targets[i];
|
|
316
|
+
const location = `targets[${i}]`;
|
|
317
|
+
if (!isObject2(target)) {
|
|
318
|
+
errors.push({
|
|
319
|
+
severity: "error",
|
|
320
|
+
filePath: absolutePath,
|
|
321
|
+
location,
|
|
322
|
+
message: "Target must be an object"
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const name = target["name"];
|
|
327
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
328
|
+
errors.push({
|
|
329
|
+
severity: "error",
|
|
330
|
+
filePath: absolutePath,
|
|
331
|
+
location: `${location}.name`,
|
|
332
|
+
message: "Missing or invalid 'name' field (must be a non-empty string)"
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
const provider = target["provider"];
|
|
336
|
+
if (typeof provider !== "string" || provider.trim().length === 0) {
|
|
337
|
+
errors.push({
|
|
338
|
+
severity: "error",
|
|
339
|
+
filePath: absolutePath,
|
|
340
|
+
location: `${location}.provider`,
|
|
341
|
+
message: "Missing or invalid 'provider' field (must be a non-empty string)"
|
|
342
|
+
});
|
|
343
|
+
} else if (!knownProviders.includes(provider)) {
|
|
344
|
+
errors.push({
|
|
345
|
+
severity: "warning",
|
|
346
|
+
filePath: absolutePath,
|
|
347
|
+
location: `${location}.provider`,
|
|
348
|
+
message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(", ")}`
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
const settings = target["settings"];
|
|
352
|
+
if (settings !== void 0 && !isObject2(settings)) {
|
|
353
|
+
errors.push({
|
|
354
|
+
severity: "error",
|
|
355
|
+
filePath: absolutePath,
|
|
356
|
+
location: `${location}.settings`,
|
|
357
|
+
message: "Invalid 'settings' field (must be an object)"
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
const judgeTarget = target["judge_target"];
|
|
361
|
+
if (judgeTarget !== void 0 && typeof judgeTarget !== "string") {
|
|
362
|
+
errors.push({
|
|
363
|
+
severity: "error",
|
|
364
|
+
filePath: absolutePath,
|
|
365
|
+
location: `${location}.judge_target`,
|
|
366
|
+
message: "Invalid 'judge_target' field (must be a string)"
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
valid: errors.filter((e) => e.severity === "error").length === 0,
|
|
372
|
+
filePath: absolutePath,
|
|
373
|
+
fileType: "targets",
|
|
374
|
+
errors
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/evaluation/validation/file-reference-validator.ts
|
|
379
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
380
|
+
import path3 from "node:path";
|
|
381
|
+
import { parse as parse4 } from "yaml";
|
|
382
|
+
function isObject3(value) {
|
|
383
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
384
|
+
}
|
|
385
|
+
async function validateFileReferences(evalFilePath) {
|
|
386
|
+
const errors = [];
|
|
387
|
+
const absolutePath = path3.resolve(evalFilePath);
|
|
388
|
+
const gitRoot = await findGitRoot(absolutePath);
|
|
389
|
+
if (!gitRoot) {
|
|
390
|
+
errors.push({
|
|
391
|
+
severity: "error",
|
|
392
|
+
filePath: absolutePath,
|
|
393
|
+
message: "Cannot validate file references: git repository root not found"
|
|
394
|
+
});
|
|
395
|
+
return errors;
|
|
396
|
+
}
|
|
397
|
+
const searchRoots = buildSearchRoots(absolutePath, gitRoot);
|
|
398
|
+
let parsed;
|
|
399
|
+
try {
|
|
400
|
+
const content = await readFile4(absolutePath, "utf8");
|
|
401
|
+
parsed = parse4(content);
|
|
402
|
+
} catch {
|
|
403
|
+
return errors;
|
|
404
|
+
}
|
|
405
|
+
if (!isObject3(parsed)) {
|
|
406
|
+
return errors;
|
|
407
|
+
}
|
|
408
|
+
const evalcases = parsed["evalcases"];
|
|
409
|
+
if (!Array.isArray(evalcases)) {
|
|
410
|
+
return errors;
|
|
411
|
+
}
|
|
412
|
+
for (let i = 0; i < evalcases.length; i++) {
|
|
413
|
+
const evalCase = evalcases[i];
|
|
414
|
+
if (!isObject3(evalCase)) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const inputMessages = evalCase["input_messages"];
|
|
418
|
+
if (Array.isArray(inputMessages)) {
|
|
419
|
+
await validateMessagesFileRefs(inputMessages, `evalcases[${i}].input_messages`, searchRoots, absolutePath, errors);
|
|
420
|
+
}
|
|
421
|
+
const expectedMessages = evalCase["expected_messages"];
|
|
422
|
+
if (Array.isArray(expectedMessages)) {
|
|
423
|
+
await validateMessagesFileRefs(expectedMessages, `evalcases[${i}].expected_messages`, searchRoots, absolutePath, errors);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return errors;
|
|
427
|
+
}
|
|
428
|
+
async function validateMessagesFileRefs(messages, location, searchRoots, filePath, errors) {
|
|
429
|
+
for (let i = 0; i < messages.length; i++) {
|
|
430
|
+
const message = messages[i];
|
|
431
|
+
if (!isObject3(message)) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const content = message["content"];
|
|
435
|
+
if (typeof content === "string") {
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (!Array.isArray(content)) {
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
for (let j = 0; j < content.length; j++) {
|
|
442
|
+
const contentItem = content[j];
|
|
443
|
+
if (!isObject3(contentItem)) {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const type = contentItem["type"];
|
|
447
|
+
if (type !== "file") {
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
const value = contentItem["value"];
|
|
451
|
+
if (typeof value !== "string") {
|
|
452
|
+
errors.push({
|
|
453
|
+
severity: "error",
|
|
454
|
+
filePath,
|
|
455
|
+
location: `${location}[${i}].content[${j}].value`,
|
|
456
|
+
message: "File reference must have a 'value' field with the file path"
|
|
457
|
+
});
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
const { resolvedPath } = await resolveFileReference(value, searchRoots);
|
|
461
|
+
if (!resolvedPath) {
|
|
462
|
+
errors.push({
|
|
463
|
+
severity: "error",
|
|
464
|
+
filePath,
|
|
465
|
+
location: `${location}[${i}].content[${j}]`,
|
|
466
|
+
message: `Referenced file not found: ${value}`
|
|
467
|
+
});
|
|
468
|
+
} else {
|
|
469
|
+
try {
|
|
470
|
+
const fileContent = await readFile4(resolvedPath, "utf8");
|
|
471
|
+
if (fileContent.trim().length === 0) {
|
|
472
|
+
errors.push({
|
|
473
|
+
severity: "warning",
|
|
474
|
+
filePath,
|
|
475
|
+
location: `${location}[${i}].content[${j}]`,
|
|
476
|
+
message: `Referenced file is empty: ${value}`
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
} catch (error) {
|
|
480
|
+
errors.push({
|
|
481
|
+
severity: "error",
|
|
482
|
+
filePath,
|
|
483
|
+
location: `${location}[${i}].content[${j}]`,
|
|
484
|
+
message: `Cannot read referenced file: ${value} (${error.message})`
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
export {
|
|
492
|
+
detectFileType,
|
|
493
|
+
getExpectedSchema,
|
|
494
|
+
isValidSchema,
|
|
495
|
+
validateEvalFile,
|
|
496
|
+
validateFileReferences,
|
|
497
|
+
validateTargetsFile
|
|
498
|
+
};
|
|
499
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/evaluation/validation/file-type.ts","../../../src/evaluation/validation/eval-validator.ts","../../../src/evaluation/validation/targets-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\r\nimport { parse } from \"yaml\";\r\n\r\nimport type { FileType } from \"./types.js\";\r\n\r\nconst SCHEMA_EVAL_V2 = \"agentv-eval-v2\";\r\nconst SCHEMA_TARGETS_V2 = \"agentv-targets-v2\";\r\n\r\n/**\r\n * Detect file type by reading $schema field from YAML file.\r\n * Returns \"unknown\" if file cannot be read or $schema is missing/invalid.\r\n */\r\nexport async function detectFileType(filePath: string): Promise<FileType> {\r\n try {\r\n const content = await readFile(filePath, \"utf8\");\r\n const parsed = parse(content) as unknown;\r\n\r\n if (typeof parsed !== \"object\" || parsed === null) {\r\n return \"unknown\";\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n const schema = record[\"$schema\"];\r\n\r\n if (typeof schema !== \"string\") {\r\n return \"unknown\";\r\n }\r\n\r\n switch (schema) {\r\n case SCHEMA_EVAL_V2:\r\n return \"eval\";\r\n case SCHEMA_TARGETS_V2:\r\n return \"targets\";\r\n default:\r\n return \"unknown\";\r\n }\r\n } catch {\r\n return \"unknown\";\r\n }\r\n}\r\n\r\n/**\r\n * Check if a schema value is a valid AgentV schema identifier.\r\n */\r\nexport function isValidSchema(schema: unknown): boolean {\r\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2;\r\n}\r\n\r\n/**\r\n * Get the expected schema for a file type.\r\n */\r\nexport function getExpectedSchema(fileType: FileType): string | undefined {\r\n switch (fileType) {\r\n case \"eval\":\r\n return SCHEMA_EVAL_V2;\r\n case \"targets\":\r\n return SCHEMA_TARGETS_V2;\r\n default:\r\n return undefined;\r\n }\r\n}\r\n","import { readFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { parse } from \"yaml\";\r\n\r\nimport type { ValidationError, ValidationResult } from \"./types.js\";\r\n\r\nconst SCHEMA_EVAL_V2 = \"agentv-eval-v2\";\r\n\r\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\r\ntype JsonObject = { readonly [key: string]: JsonValue };\r\ntype JsonArray = readonly JsonValue[];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/**\r\n * Validate an eval file (agentv-eval-v2 schema).\r\n */\r\nexport async function validateEvalFile(\r\n filePath: string,\r\n): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n const absolutePath = path.resolve(filePath);\r\n\r\n let parsed: unknown;\r\n try {\r\n const content = await readFile(absolutePath, \"utf8\");\r\n parsed = parse(content);\r\n } catch (error) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n message: `Failed to parse YAML: ${(error as Error).message}`,\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: \"eval\",\r\n errors,\r\n };\r\n }\r\n\r\n if (!isObject(parsed)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n message: \"File must contain a YAML object\",\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: \"eval\",\r\n errors,\r\n };\r\n }\r\n\r\n // Validate $schema field\r\n const schema = parsed[\"$schema\"];\r\n if (schema !== SCHEMA_EVAL_V2) {\r\n const message =\r\n typeof schema === \"string\"\r\n ? `Invalid $schema value '${schema}'. Expected '${SCHEMA_EVAL_V2}'`\r\n : `Missing required field '$schema'. Expected '${SCHEMA_EVAL_V2}'`;\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: \"$schema\",\r\n message,\r\n });\r\n }\r\n\r\n // Validate evalcases array\r\n const evalcases = parsed[\"evalcases\"];\r\n if (!Array.isArray(evalcases)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: \"evalcases\",\r\n message: \"Missing or invalid 'evalcases' field (must be an array)\",\r\n });\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: \"eval\",\r\n errors,\r\n };\r\n }\r\n\r\n // Validate each eval case\r\n for (let i = 0; i < evalcases.length; i++) {\r\n const evalCase = evalcases[i];\r\n const location = `evalcases[${i}]`;\r\n\r\n if (!isObject(evalCase)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location,\r\n message: \"Eval case must be an object\",\r\n });\r\n continue;\r\n }\r\n\r\n // Required fields: id, outcome, input_messages, expected_messages\r\n const id = evalCase[\"id\"];\r\n if (typeof id !== \"string\" || id.trim().length === 0) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.id`,\r\n message: \"Missing or invalid 'id' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n const outcome = evalCase[\"outcome\"];\r\n if (typeof outcome !== \"string\" || outcome.trim().length === 0) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.outcome`,\r\n message: \"Missing or invalid 'outcome' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n const inputMessages = evalCase[\"input_messages\"];\r\n if (!Array.isArray(inputMessages)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.input_messages`,\r\n message: \"Missing or invalid 'input_messages' field (must be an array)\",\r\n });\r\n } else {\r\n validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);\r\n }\r\n\r\n const expectedMessages = evalCase[\"expected_messages\"];\r\n if (!Array.isArray(expectedMessages)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.expected_messages`,\r\n message: \"Missing or invalid 'expected_messages' field (must be an array)\",\r\n });\r\n } else {\r\n validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: \"eval\",\r\n errors,\r\n };\r\n}\r\n\r\nfunction validateMessages(\r\n messages: JsonArray,\r\n location: string,\r\n filePath: string,\r\n errors: ValidationError[],\r\n): void {\r\n for (let i = 0; i < messages.length; i++) {\r\n const message = messages[i];\r\n const msgLocation = `${location}[${i}]`;\r\n\r\n if (!isObject(message)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: msgLocation,\r\n message: \"Message must be an object\",\r\n });\r\n continue;\r\n }\r\n\r\n // Validate role field\r\n const role = message[\"role\"];\r\n const validRoles = [\"system\", \"user\", \"assistant\"];\r\n if (!validRoles.includes(role as string)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${msgLocation}.role`,\r\n message: `Invalid role '${role}'. Must be one of: ${validRoles.join(\", \")}`,\r\n });\r\n }\r\n\r\n // Validate content field (can be string or array)\r\n const content = message[\"content\"];\r\n if (typeof content === \"string\") {\r\n // String content is valid\r\n } else if (Array.isArray(content)) {\r\n // Array content - validate each element\r\n for (let j = 0; j < content.length; j++) {\r\n const contentItem = content[j];\r\n const contentLocation = `${msgLocation}.content[${j}]`;\r\n\r\n if (typeof contentItem === \"string\") {\r\n // String in array is valid\r\n } else if (isObject(contentItem)) {\r\n const type = contentItem[\"type\"];\r\n if (typeof type !== \"string\") {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${contentLocation}.type`,\r\n message: \"Content object must have a 'type' field\",\r\n });\r\n }\r\n\r\n // For 'file' type, we'll validate existence later in file-reference-validator\r\n // For 'text' type, require 'value' field\r\n if (type === \"text\") {\r\n const value = contentItem[\"value\"];\r\n if (typeof value !== \"string\") {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${contentLocation}.value`,\r\n message: \"Content with type 'text' must have a 'value' field\",\r\n });\r\n }\r\n }\r\n } else {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: contentLocation,\r\n message: \"Content array items must be strings or objects\",\r\n });\r\n }\r\n }\r\n } else {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${msgLocation}.content`,\r\n message: \"Missing or invalid 'content' field (must be a string or array)\",\r\n });\r\n }\r\n }\r\n}\r\n","import { readFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { parse } from \"yaml\";\r\n\r\nimport type { ValidationError, ValidationResult } from \"./types.js\";\r\n\r\nconst SCHEMA_TARGETS_V2 = \"agentv-targets-v2\";\r\n\r\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\r\ntype JsonObject = { readonly [key: string]: JsonValue };\r\ntype JsonArray = readonly JsonValue[];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/**\r\n * Validate a targets file (agentv-targets-v2 schema).\r\n */\r\nexport async function validateTargetsFile(\r\n filePath: string,\r\n): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n const absolutePath = path.resolve(filePath);\r\n\r\n let parsed: unknown;\r\n try {\r\n const content = await readFile(absolutePath, \"utf8\");\r\n parsed = parse(content);\r\n } catch (error) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n message: `Failed to parse YAML: ${(error as Error).message}`,\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: \"targets\",\r\n errors,\r\n };\r\n }\r\n\r\n if (!isObject(parsed)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n message: \"File must contain a YAML object\",\r\n });\r\n return {\r\n valid: false,\r\n filePath: absolutePath,\r\n fileType: \"targets\",\r\n errors,\r\n };\r\n }\r\n\r\n // Validate $schema field\r\n const schema = parsed[\"$schema\"];\r\n if (schema !== SCHEMA_TARGETS_V2) {\r\n const message =\r\n typeof schema === \"string\"\r\n ? `Invalid $schema value '${schema}'. Expected '${SCHEMA_TARGETS_V2}'`\r\n : `Missing required field '$schema'. Expected '${SCHEMA_TARGETS_V2}'`;\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: \"$schema\",\r\n message,\r\n });\r\n }\r\n\r\n // Validate targets array\r\n const targets = parsed[\"targets\"];\r\n if (!Array.isArray(targets)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: \"targets\",\r\n message: \"Missing or invalid 'targets' field (must be an array)\",\r\n });\r\n return {\r\n valid: errors.length === 0,\r\n filePath: absolutePath,\r\n fileType: \"targets\",\r\n errors,\r\n };\r\n }\r\n\r\n // Validate each target definition\r\n const knownProviders = [\"azure\", \"openai\", \"anthropic\", \"bedrock\", \"vertex\"];\r\n \r\n for (let i = 0; i < targets.length; i++) {\r\n const target = targets[i];\r\n const location = `targets[${i}]`;\r\n\r\n if (!isObject(target)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location,\r\n message: \"Target must be an object\",\r\n });\r\n continue;\r\n }\r\n\r\n // Required field: name\r\n const name = target[\"name\"];\r\n if (typeof name !== \"string\" || name.trim().length === 0) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.name`,\r\n message: \"Missing or invalid 'name' field (must be a non-empty string)\",\r\n });\r\n }\r\n\r\n // Required field: provider\r\n const provider = target[\"provider\"];\r\n if (typeof provider !== \"string\" || provider.trim().length === 0) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.provider`,\r\n message: \"Missing or invalid 'provider' field (must be a non-empty string)\",\r\n });\r\n } else if (!knownProviders.includes(provider)) {\r\n // Warning for unknown providers (non-fatal)\r\n errors.push({\r\n severity: \"warning\",\r\n filePath: absolutePath,\r\n location: `${location}.provider`,\r\n message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(\", \")}`,\r\n });\r\n }\r\n\r\n // Optional field: settings (must be object if present)\r\n const settings = target[\"settings\"];\r\n if (settings !== undefined && !isObject(settings)) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.settings`,\r\n message: \"Invalid 'settings' field (must be an object)\",\r\n });\r\n }\r\n\r\n // Optional field: judge_target (must be string if present)\r\n const judgeTarget = target[\"judge_target\"];\r\n if (judgeTarget !== undefined && typeof judgeTarget !== \"string\") {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n location: `${location}.judge_target`,\r\n message: \"Invalid 'judge_target' field (must be a string)\",\r\n });\r\n }\r\n }\r\n\r\n return {\r\n valid: errors.filter((e) => e.severity === \"error\").length === 0,\r\n filePath: absolutePath,\r\n fileType: \"targets\",\r\n errors,\r\n };\r\n}\r\n","import { readFile } from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { parse } from \"yaml\";\r\n\r\nimport { buildSearchRoots, findGitRoot, resolveFileReference } from \"../file-utils.js\";\r\nimport type { ValidationError } from \"./types.js\";\r\n\r\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\r\ntype JsonObject = { readonly [key: string]: JsonValue };\r\ntype JsonArray = readonly JsonValue[];\r\n\r\nfunction isObject(value: unknown): value is JsonObject {\r\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\r\n}\r\n\r\n/**\r\n * Validate that file references in eval file content exist.\r\n * Checks content blocks with type: \"file\" and validates the referenced file exists.\r\n * Also checks that referenced files are not empty.\r\n */\r\nexport async function validateFileReferences(\r\n evalFilePath: string,\r\n): Promise<readonly ValidationError[]> {\r\n const errors: ValidationError[] = [];\r\n const absolutePath = path.resolve(evalFilePath);\r\n\r\n // Find git root and build search roots (same as yaml-parser does at runtime)\r\n const gitRoot = await findGitRoot(absolutePath);\r\n if (!gitRoot) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath: absolutePath,\r\n message: \"Cannot validate file references: git repository root not found\",\r\n });\r\n return errors;\r\n }\r\n\r\n const searchRoots = buildSearchRoots(absolutePath, gitRoot);\r\n\r\n let parsed: unknown;\r\n try {\r\n const content = await readFile(absolutePath, \"utf8\");\r\n parsed = parse(content);\r\n } catch {\r\n // Parse errors are already caught by eval-validator\r\n return errors;\r\n }\r\n\r\n if (!isObject(parsed)) {\r\n return errors;\r\n }\r\n\r\n const evalcases = parsed[\"evalcases\"];\r\n if (!Array.isArray(evalcases)) {\r\n return errors;\r\n }\r\n\r\n for (let i = 0; i < evalcases.length; i++) {\r\n const evalCase = evalcases[i];\r\n if (!isObject(evalCase)) {\r\n continue;\r\n }\r\n\r\n // Check input_messages\r\n const inputMessages = evalCase[\"input_messages\"];\r\n if (Array.isArray(inputMessages)) {\r\n await validateMessagesFileRefs(inputMessages, `evalcases[${i}].input_messages`, searchRoots, absolutePath, errors);\r\n }\r\n\r\n // Check expected_messages\r\n const expectedMessages = evalCase[\"expected_messages\"];\r\n if (Array.isArray(expectedMessages)) {\r\n await validateMessagesFileRefs(expectedMessages, `evalcases[${i}].expected_messages`, searchRoots, absolutePath, errors);\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\nasync function validateMessagesFileRefs(\r\n messages: JsonArray,\r\n location: string,\r\n searchRoots: readonly string[],\r\n filePath: string,\r\n errors: ValidationError[],\r\n): Promise<void> {\r\n for (let i = 0; i < messages.length; i++) {\r\n const message = messages[i];\r\n if (!isObject(message)) {\r\n continue;\r\n }\r\n\r\n const content = message[\"content\"];\r\n if (typeof content === \"string\") {\r\n continue;\r\n }\r\n\r\n if (!Array.isArray(content)) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < content.length; j++) {\r\n const contentItem = content[j];\r\n if (!isObject(contentItem)) {\r\n continue;\r\n }\r\n\r\n const type = contentItem[\"type\"];\r\n if (type !== \"file\") {\r\n continue;\r\n }\r\n\r\n const value = contentItem[\"value\"];\r\n if (typeof value !== \"string\") {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${location}[${i}].content[${j}].value`,\r\n message: \"File reference must have a 'value' field with the file path\",\r\n });\r\n continue;\r\n }\r\n\r\n // Use the same file resolution logic as yaml-parser at runtime\r\n const { resolvedPath } = await resolveFileReference(value, searchRoots);\r\n\r\n if (!resolvedPath) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${location}[${i}].content[${j}]`,\r\n message: `Referenced file not found: ${value}`,\r\n });\r\n } else {\r\n // Check that file is not empty\r\n try {\r\n const fileContent = await readFile(resolvedPath, \"utf8\");\r\n if (fileContent.trim().length === 0) {\r\n errors.push({\r\n severity: \"warning\",\r\n filePath,\r\n location: `${location}[${i}].content[${j}]`,\r\n message: `Referenced file is empty: ${value}`,\r\n });\r\n }\r\n } catch (error) {\r\n errors.push({\r\n severity: \"error\",\r\n filePath,\r\n location: `${location}[${i}].content[${j}]`,\r\n message: `Cannot read referenced file: ${value} (${(error as Error).message})`,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["readFile","parse","SCHEMA_EVAL_V2","readFile","path","parse","SCHEMA_TARGETS_V2","isObject","readFile","path","parse","isObject","path","readFile","parse"]}
|