@agentv/core 4.20.0 → 4.21.0-next.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.
@@ -260,6 +260,63 @@ async function loadCasesFromFile(filePath) {
260
260
  `Unsupported external test file format '${ext}': ${filePath}. Supported: .yaml, .yml, .jsonl`
261
261
  );
262
262
  }
263
+ async function loadCasesFromDirectory(dirPath) {
264
+ const entries = await (0, import_promises2.readdir)(dirPath, { withFileTypes: true });
265
+ const subdirs = entries.filter((e) => e.isDirectory()).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
266
+ const results = [];
267
+ for (const subdir of subdirs) {
268
+ const subdirPath = import_node_path2.default.join(dirPath, subdir.name);
269
+ let caseFilePath;
270
+ for (const filename of ["case.yaml", "case.yml"]) {
271
+ const candidate = import_node_path2.default.join(subdirPath, filename);
272
+ try {
273
+ const s = await (0, import_promises2.stat)(candidate);
274
+ if (s.isFile()) {
275
+ caseFilePath = candidate;
276
+ break;
277
+ }
278
+ } catch {
279
+ }
280
+ }
281
+ if (!caseFilePath) {
282
+ console.warn(
283
+ `${ANSI_YELLOW}Warning: Skipping directory '${subdir.name}' \u2014 no case.yaml found${ANSI_RESET}`
284
+ );
285
+ continue;
286
+ }
287
+ let content;
288
+ try {
289
+ content = await (0, import_promises2.readFile)(caseFilePath, "utf8");
290
+ } catch (error) {
291
+ const message = error instanceof Error ? error.message : String(error);
292
+ throw new Error(`Cannot read case file: ${caseFilePath}
293
+ ${message}`);
294
+ }
295
+ const raw = (0, import_yaml2.parse)(content);
296
+ const parsed = interpolateEnv(raw, process.env);
297
+ if (!isJsonObject(parsed)) {
298
+ throw new Error(
299
+ `Case file must contain a YAML object, got ${typeof parsed}: ${caseFilePath}`
300
+ );
301
+ }
302
+ const caseObj = { ...parsed };
303
+ if (caseObj.id === void 0 || caseObj.id === null) {
304
+ caseObj.id = subdir.name;
305
+ }
306
+ if (!caseObj.workspace) {
307
+ const workspaceDirPath = import_node_path2.default.join(subdirPath, "workspace");
308
+ try {
309
+ const s = await (0, import_promises2.stat)(workspaceDirPath);
310
+ if (s.isDirectory()) {
311
+ caseObj.workspace = { template: workspaceDirPath };
312
+ }
313
+ } catch {
314
+ }
315
+ }
316
+ results.push(caseObj);
317
+ }
318
+ return results;
319
+ }
263
320
 
264
321
  // src/evaluation/validation/eval-validator.ts
265
322
  var ASSERTION_TYPES_WITH_STRING_VALUE = /* @__PURE__ */ new Set([
@@ -432,17 +489,21 @@ async function validateEvalFile(filePath) {
432
489
  }
433
490
  const cases = parsed.tests;
434
491
  if (typeof cases === "string") {
435
- validateTestsStringPath(cases, absolutePath, errors);
436
492
  await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, "workspace");
437
- const ext = import_node_path3.default.extname(cases).toLowerCase();
438
- if (VALID_TEST_FILE_EXTENSIONS.has(ext)) {
439
- const externalCasesPath = import_node_path3.default.resolve(import_node_path3.default.dirname(absolutePath), cases);
493
+ const externalCasesPath = import_node_path3.default.resolve(import_node_path3.default.dirname(absolutePath), cases);
494
+ let isDir = false;
495
+ try {
496
+ const pathStat = await (0, import_promises3.stat)(externalCasesPath);
497
+ isDir = pathStat.isDirectory();
498
+ } catch {
499
+ }
500
+ if (isDir) {
440
501
  try {
441
- const externalCases = await loadCasesFromFile(externalCasesPath);
442
- for (let i = 0; i < externalCases.length; i++) {
443
- const externalCase = externalCases[i];
502
+ const dirCases = await loadCasesFromDirectory(externalCasesPath);
503
+ for (let i = 0; i < dirCases.length; i++) {
504
+ const dirCase = dirCases[i];
444
505
  await validateWorkspaceConfig(
445
- externalCase.workspace,
506
+ dirCase.workspace,
446
507
  absolutePath,
447
508
  errors,
448
509
  `tests[${i}].workspace`
@@ -457,6 +518,31 @@ async function validateEvalFile(filePath) {
457
518
  message
458
519
  });
459
520
  }
521
+ } else {
522
+ validateTestsStringPath(cases, absolutePath, errors);
523
+ const ext = import_node_path3.default.extname(cases).toLowerCase();
524
+ if (VALID_TEST_FILE_EXTENSIONS.has(ext)) {
525
+ try {
526
+ const externalCases = await loadCasesFromFile(externalCasesPath);
527
+ for (let i = 0; i < externalCases.length; i++) {
528
+ const externalCase = externalCases[i];
529
+ await validateWorkspaceConfig(
530
+ externalCase.workspace,
531
+ absolutePath,
532
+ errors,
533
+ `tests[${i}].workspace`
534
+ );
535
+ }
536
+ } catch (error) {
537
+ const message = error instanceof Error ? error.message : String(error);
538
+ errors.push({
539
+ severity: "error",
540
+ filePath: absolutePath,
541
+ location: "tests",
542
+ message
543
+ });
544
+ }
545
+ }
460
546
  }
461
547
  return {
462
548
  valid: errors.filter((e) => e.severity === "error").length === 0,