@agentv/core 3.10.1 → 3.10.2
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/dist/evaluation/validation/index.cjs +19 -21
- package/dist/evaluation/validation/index.cjs.map +1 -1
- package/dist/evaluation/validation/index.js +19 -21
- package/dist/evaluation/validation/index.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -143,25 +143,7 @@ async function validateEvalFile(filePath) {
|
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
if (cases === void 0 && "eval_cases" in parsed) {
|
|
148
|
-
cases = parsed.eval_cases;
|
|
149
|
-
errors.push({
|
|
150
|
-
severity: "warning",
|
|
151
|
-
filePath: absolutePath,
|
|
152
|
-
location: "eval_cases",
|
|
153
|
-
message: "'eval_cases' is deprecated. Use 'tests' instead."
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
if (cases === void 0 && "evalcases" in parsed) {
|
|
157
|
-
cases = parsed.evalcases;
|
|
158
|
-
errors.push({
|
|
159
|
-
severity: "warning",
|
|
160
|
-
filePath: absolutePath,
|
|
161
|
-
location: "evalcases",
|
|
162
|
-
message: "'evalcases' is deprecated. Use 'tests' instead."
|
|
163
|
-
});
|
|
164
|
-
}
|
|
146
|
+
const cases = parsed.tests;
|
|
165
147
|
if (typeof cases === "string") {
|
|
166
148
|
validateTestsStringPath(cases, absolutePath, errors);
|
|
167
149
|
await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, "workspace");
|
|
@@ -213,6 +195,19 @@ async function validateEvalFile(filePath) {
|
|
|
213
195
|
for (let i = 0; i < cases.length; i++) {
|
|
214
196
|
const evalCase = cases[i];
|
|
215
197
|
const location = `tests[${i}]`;
|
|
198
|
+
if (typeof evalCase === "string") {
|
|
199
|
+
if (evalCase.startsWith("file://")) {
|
|
200
|
+
validateTestsStringPath(evalCase, absolutePath, errors);
|
|
201
|
+
} else {
|
|
202
|
+
errors.push({
|
|
203
|
+
severity: "error",
|
|
204
|
+
filePath: absolutePath,
|
|
205
|
+
location,
|
|
206
|
+
message: "Test case string must be a file reference (file://...)"
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
216
211
|
if (!isObject(evalCase)) {
|
|
217
212
|
errors.push({
|
|
218
213
|
severity: "error",
|
|
@@ -426,7 +421,9 @@ function validateMessages(messages, location, filePath, errors) {
|
|
|
426
421
|
});
|
|
427
422
|
}
|
|
428
423
|
const content = message.content;
|
|
429
|
-
|
|
424
|
+
const hasToolCalls = "tool_calls" in message;
|
|
425
|
+
if (content === void 0 && hasToolCalls) {
|
|
426
|
+
} else if (typeof content === "string") {
|
|
430
427
|
validateContentForRoleMarkers(content, `${msgLocation}.content`, filePath, errors);
|
|
431
428
|
} else if (Array.isArray(content)) {
|
|
432
429
|
for (let j = 0; j < content.length; j++) {
|
|
@@ -466,12 +463,13 @@ function validateMessages(messages, location, filePath, errors) {
|
|
|
466
463
|
});
|
|
467
464
|
}
|
|
468
465
|
}
|
|
466
|
+
} else if (isObject(content)) {
|
|
469
467
|
} else {
|
|
470
468
|
errors.push({
|
|
471
469
|
severity: "error",
|
|
472
470
|
filePath,
|
|
473
471
|
location: `${msgLocation}.content`,
|
|
474
|
-
message: "Missing or invalid 'content' field (must be a string or
|
|
472
|
+
message: "Missing or invalid 'content' field (must be a string, array, or object)"
|
|
475
473
|
});
|
|
476
474
|
}
|
|
477
475
|
}
|
|
@@ -1 +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/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport type { FileType } from './types.js';\n\nconst SCHEMA_EVAL_V2 = 'agentv-eval-v2';\nconst SCHEMA_TARGETS_V2 = 'agentv-targets-v2.2';\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\n\n/**\n * Detect file type by reading $schema field from YAML file.\n * If $schema is missing, infers type from filename/path:\n * - config.yaml under .agentv folder → 'config'\n * - targets.yaml under .agentv folder → 'targets'\n * - All other YAML files → 'eval' (default)\n */\nexport async function detectFileType(filePath: string): Promise<FileType> {\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n if (typeof parsed !== 'object' || parsed === null) {\n return inferFileTypeFromPath(filePath);\n }\n\n const record = parsed as Record<string, unknown>;\n const schema = record.$schema;\n\n if (typeof schema !== 'string') {\n // No $schema field - infer from path\n return inferFileTypeFromPath(filePath);\n }\n\n switch (schema) {\n case SCHEMA_EVAL_V2:\n return 'eval';\n case SCHEMA_TARGETS_V2:\n return 'targets';\n case SCHEMA_CONFIG_V2:\n return 'config';\n default:\n // Unknown schema - infer from path\n return inferFileTypeFromPath(filePath);\n }\n } catch {\n return inferFileTypeFromPath(filePath);\n }\n}\n\n/**\n * Infer file type from filename and directory path.\n */\nfunction inferFileTypeFromPath(filePath: string): FileType {\n const normalized = path.normalize(filePath).replace(/\\\\/g, '/');\n const basename = path.basename(filePath);\n\n // Check if file is under .agentv folder\n if (normalized.includes('/.agentv/')) {\n if (basename === 'config.yaml' || basename === 'config.yml') {\n return 'config';\n }\n if (basename === 'targets.yaml' || basename === 'targets.yml') {\n return 'targets';\n }\n }\n\n // Default to eval file\n return 'eval';\n}\n\n/**\n * Check if a schema value is a valid AgentV schema identifier.\n */\nexport function isValidSchema(schema: unknown): boolean {\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2 || schema === SCHEMA_CONFIG_V2;\n}\n\n/**\n * Get the expected schema for a file type.\n */\nexport function getExpectedSchema(fileType: FileType): string | undefined {\n switch (fileType) {\n case 'eval':\n return SCHEMA_EVAL_V2;\n case 'targets':\n return SCHEMA_TARGETS_V2;\n case 'config':\n return SCHEMA_CONFIG_V2;\n default:\n return undefined;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { interpolateEnv } from '../interpolation.js';\nimport { loadCasesFromFile } from '../loaders/case-file-loader.js';\nimport { isEvaluatorKind } from '../types.js';\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\n/** Assertion evaluator types that require a string `value` field. */\nconst ASSERTION_TYPES_WITH_STRING_VALUE = new Set([\n 'contains',\n 'icontains',\n 'starts-with',\n 'ends-with',\n 'equals',\n 'regex',\n]);\n/** Assertion evaluator types that require a string[] `value` field. */\nconst ASSERTION_TYPES_WITH_ARRAY_VALUE = new Set([\n 'contains-any',\n 'contains-all',\n 'icontains-any',\n 'icontains-all',\n]);\n\n/** Valid file extensions for external test files. */\nconst VALID_TEST_FILE_EXTENSIONS = new Set(['.yaml', '.yml', '.jsonl']);\n\n/** Name field pattern: lowercase alphanumeric with hyphens. */\nconst NAME_PATTERN = /^[a-z0-9-]+$/;\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate an eval file (agentv-eval-v2 schema).\n */\nexport async function validateEvalFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = interpolateEnv(parse(content), process.env);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate metadata fields\n validateMetadata(parsed, absolutePath, errors);\n\n // Validate suite-level input (optional: string shorthand or message array)\n const suiteInput = parsed.input;\n if (suiteInput !== undefined) {\n if (typeof suiteInput === 'string') {\n // String shorthand is valid\n } else if (Array.isArray(suiteInput)) {\n validateMessages(suiteInput, 'input', absolutePath, errors);\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'input',\n message: \"Invalid suite-level 'input' field (must be a string or array of messages)\",\n });\n }\n }\n\n // Resolve tests with backward-compat aliases\n let cases: JsonValue | undefined = parsed.tests;\n if (cases === undefined && 'eval_cases' in parsed) {\n cases = parsed.eval_cases;\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: 'eval_cases',\n message: \"'eval_cases' is deprecated. Use 'tests' instead.\",\n });\n }\n if (cases === undefined && 'evalcases' in parsed) {\n cases = parsed.evalcases;\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: 'evalcases',\n message: \"'evalcases' is deprecated. Use 'tests' instead.\",\n });\n }\n\n // tests can be a string path (external file reference) or an array\n if (typeof cases === 'string') {\n validateTestsStringPath(cases, absolutePath, errors);\n await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, 'workspace');\n\n const ext = path.extname(cases).toLowerCase();\n if (VALID_TEST_FILE_EXTENSIONS.has(ext)) {\n const externalCasesPath = path.resolve(path.dirname(absolutePath), cases);\n try {\n const externalCases = await loadCasesFromFile(externalCasesPath);\n for (let i = 0; i < externalCases.length; i++) {\n const externalCase = externalCases[i];\n await validateWorkspaceConfig(\n externalCase.workspace,\n absolutePath,\n errors,\n `tests[${i}].workspace`,\n );\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'tests',\n message,\n });\n }\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n if (!Array.isArray(cases)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'tests',\n message: \"Missing or invalid 'tests' field (must be an array or a file path string)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate each eval case\n for (let i = 0; i < cases.length; i++) {\n const evalCase = cases[i];\n const location = `tests[${i}]`;\n\n if (!isObject(evalCase)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Eval case must be an object',\n });\n continue;\n }\n\n // Required fields: id, input\n const id = evalCase.id;\n if (typeof id !== 'string' || id.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.id`,\n message: \"Missing or invalid 'id' field (must be a non-empty string)\",\n });\n }\n\n // Optional: criteria (with backward-compat alias expected_outcome)\n let criteria: JsonValue | undefined = evalCase.criteria;\n if (criteria === undefined && 'expected_outcome' in evalCase) {\n criteria = evalCase.expected_outcome;\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.expected_outcome`,\n message: \"'expected_outcome' is deprecated. Use 'criteria' instead.\",\n });\n }\n if (criteria !== undefined && (typeof criteria !== 'string' || criteria.trim().length === 0)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.criteria`,\n message: \"Invalid 'criteria' field (must be a non-empty string if provided)\",\n });\n }\n\n // input field (string shorthand or message array)\n const inputField = evalCase.input;\n if (inputField !== undefined) {\n if (typeof inputField === 'string') {\n // String shorthand is valid - no further validation needed\n } else if (Array.isArray(inputField)) {\n validateMessages(inputField, `${location}.input`, absolutePath, errors);\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input`,\n message: \"Invalid 'input' field (must be a string or array of messages)\",\n });\n }\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input`,\n message: \"Missing 'input' field (must be a string or array of messages)\",\n });\n }\n\n // expected_output field (string/object shorthand or message array)\n const expectedOutputField = evalCase.expected_output;\n if (expectedOutputField !== undefined) {\n if (typeof expectedOutputField === 'string') {\n // String shorthand is valid - no further validation needed\n } else if (Array.isArray(expectedOutputField)) {\n // Check if it looks like a message array (first element has 'role')\n if (\n expectedOutputField.length > 0 &&\n isObject(expectedOutputField[0]) &&\n 'role' in expectedOutputField[0]\n ) {\n validateMessages(\n expectedOutputField,\n `${location}.expected_output`,\n absolutePath,\n errors,\n );\n }\n // Otherwise it's treated as structured array content - valid\n } else if (isObject(expectedOutputField)) {\n // Object shorthand or single message - both are valid\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_output`,\n message: \"Invalid 'expected_output' field (must be a string, object, or array)\",\n });\n }\n }\n\n // assertions field (array of assertion objects); also accept legacy `assert`\n const assertField = evalCase.assertions ?? evalCase.assert;\n if (assertField !== undefined) {\n validateAssertArray(assertField, location, absolutePath, errors);\n }\n\n await validateWorkspaceConfig(\n evalCase.workspace,\n absolutePath,\n errors,\n `${location}.workspace`,\n );\n }\n\n await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, 'workspace');\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n}\n\nasync function validateWorkspaceConfig(\n workspace: JsonValue | undefined,\n evalFilePath: string,\n errors: ValidationError[],\n location: string,\n): Promise<void> {\n if (workspace === undefined) {\n return;\n }\n\n if (isObject(workspace)) {\n validateWorkspaceRepoConfig(workspace, evalFilePath, errors);\n return;\n }\n\n if (typeof workspace !== 'string') {\n return;\n }\n\n const workspacePath = path.resolve(path.dirname(evalFilePath), workspace);\n\n try {\n const workspaceContent = await readFile(workspacePath, 'utf8');\n const parsedWorkspace = interpolateEnv(parse(workspaceContent), process.env);\n if (!isObject(parsedWorkspace)) {\n errors.push({\n severity: 'error',\n filePath: evalFilePath,\n location,\n message: `External workspace file must contain a YAML object: ${workspace}`,\n });\n return;\n }\n\n validateWorkspaceRepoConfig(parsedWorkspace, workspacePath, errors);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push({\n severity: 'error',\n filePath: evalFilePath,\n location,\n message: `Failed to load external workspace file '${workspace}': ${message}`,\n });\n }\n}\n\nfunction validateWorkspaceRepoConfig(\n workspace: JsonObject,\n filePath: string,\n errors: ValidationError[],\n): void {\n const repos = workspace.repos;\n const hooks = workspace.hooks;\n const afterEachHook = isObject(hooks) ? hooks.after_each : undefined;\n const isolation = workspace.isolation;\n\n // Depth vs ancestor warning\n if (Array.isArray(repos)) {\n for (const repo of repos) {\n if (!isObject(repo)) continue;\n const source = repo.source;\n const checkout = repo.checkout;\n const clone = repo.clone;\n\n if (isObject(source) && isObject(checkout)) {\n const sourceType = source.type;\n const resolve = checkout.resolve;\n if (sourceType === 'local' && typeof resolve === 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `workspace.repos[path=${repo.path}]`,\n message:\n 'checkout.resolve has no effect for a local source. ' +\n 'Use source.type to choose where the repo comes from; keep checkout.ref or checkout.ancestor only when pinning a local source.',\n });\n }\n }\n\n if (isObject(checkout) && isObject(clone)) {\n const ancestor = checkout.ancestor;\n const depth = clone.depth;\n if (typeof ancestor === 'number' && typeof depth === 'number' && depth < ancestor + 1) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `workspace.repos[path=${repo.path}]`,\n message:\n `clone.depth (${depth}) may be insufficient for checkout.ancestor (${ancestor}). ` +\n `Recommend depth >= ${ancestor + 1}.`,\n });\n }\n }\n }\n }\n\n // Reset without repos warning\n if (isObject(afterEachHook) && afterEachHook.reset && afterEachHook.reset !== 'none') {\n if (!Array.isArray(repos) || repos.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'workspace.hooks.after_each',\n message: `hooks.after_each.reset '${afterEachHook.reset}' has no effect without repos.`,\n });\n }\n }\n\n // after_each reset with per_test isolation warning\n if (isObject(afterEachHook) && afterEachHook.reset && isolation === 'per_test') {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'workspace.hooks.after_each',\n message:\n 'hooks.after_each.reset is redundant with isolation: per_test (each test gets a fresh workspace).',\n });\n }\n}\n\nfunction validateMessages(\n messages: JsonArray,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n const msgLocation = `${location}[${i}]`;\n\n if (!isObject(message)) {\n errors.push({\n severity: 'error',\n filePath,\n location: msgLocation,\n message: 'Message must be an object',\n });\n continue;\n }\n\n // Validate role field\n const role = message.role;\n const validRoles = ['system', 'user', 'assistant'];\n if (!validRoles.includes(role as string)) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.role`,\n message: `Invalid role '${role}'. Must be one of: ${validRoles.join(', ')}`,\n });\n }\n\n // Validate content field (can be string or array)\n const content = message.content;\n if (typeof content === 'string') {\n validateContentForRoleMarkers(content, `${msgLocation}.content`, filePath, errors);\n } else if (Array.isArray(content)) {\n // Array content - validate each element\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n const contentLocation = `${msgLocation}.content[${j}]`;\n\n if (typeof contentItem === 'string') {\n validateContentForRoleMarkers(contentItem, contentLocation, filePath, errors);\n } else if (isObject(contentItem)) {\n const type = contentItem.type;\n if (typeof type !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.type`,\n message: \"Content object must have a 'type' field\",\n });\n }\n\n // For 'file' type, we'll validate existence later in file-reference-validator\n // For 'text' type, require 'value' field\n if (type === 'text') {\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.value`,\n message: \"Content with type 'text' must have a 'value' field\",\n });\n } else {\n validateContentForRoleMarkers(value, `${contentLocation}.value`, filePath, errors);\n }\n }\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: contentLocation,\n message: 'Content array items must be strings or objects',\n });\n }\n }\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.content`,\n message: \"Missing or invalid 'content' field (must be a string or array)\",\n });\n }\n }\n}\n\nfunction validateMetadata(parsed: JsonObject, filePath: string, errors: ValidationError[]): void {\n const name = parsed.name;\n if (name !== undefined) {\n if (typeof name === 'string') {\n if (!NAME_PATTERN.test(name)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'name',\n message: `Invalid 'name' format '${name}'. Must match pattern /^[a-z0-9-]+$/ (lowercase alphanumeric with hyphens).`,\n });\n }\n }\n\n // Warn if name is present but description is missing\n if (!('description' in parsed) || parsed.description === undefined) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'name',\n message: \"When 'name' is present, 'description' should also be provided.\",\n });\n }\n }\n}\n\nfunction validateTestsStringPath(\n testsPath: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n const ext = path.extname(testsPath);\n if (!VALID_TEST_FILE_EXTENSIONS.has(ext)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'tests',\n message: `Unsupported file extension '${ext}' for tests path '${testsPath}'. Supported extensions: ${[...VALID_TEST_FILE_EXTENSIONS].join(', ')}`,\n });\n }\n}\n\nfunction validateAssertArray(\n assertField: JsonValue,\n parentLocation: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n if (!Array.isArray(assertField)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions`,\n message: \"'assertions' must be an array of assertion objects.\",\n });\n return;\n }\n\n // String items in the assertions array are valid shorthand — the parser collects them\n // into a single rubrics/llm-grader evaluator. Filter them out before object validation.\n const objectItems: { item: JsonObject; index: number }[] = [];\n for (let i = 0; i < assertField.length; i++) {\n const item = assertField[i];\n if (typeof item === 'string') {\n if (item.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions[${i}]`,\n message: 'Empty string assertion item will be ignored.',\n });\n }\n continue; // Valid shorthand — skip object validation\n }\n if (!isObject(item)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions[${i}]`,\n message: 'Assertion item must be a string or an object with a type field.',\n });\n continue;\n }\n objectItems.push({ item, index: i });\n }\n\n for (const { item, index } of objectItems) {\n const location = `${parentLocation}.assertions[${index}]`;\n\n // Validate type field\n const rawTypeValue = item.type;\n if (rawTypeValue === undefined || typeof rawTypeValue !== 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.type`,\n message: \"Assertion item is missing a 'type' field.\",\n });\n continue;\n }\n\n // Normalize snake_case to kebab-case for backward compatibility\n const typeValue = rawTypeValue.replace(/_/g, '-');\n\n if (!isEvaluatorKind(typeValue)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.type`,\n message: `Unknown assertion type '${rawTypeValue}'.`,\n });\n continue;\n }\n\n // Validate value field for types that require a string value\n if (ASSERTION_TYPES_WITH_STRING_VALUE.has(typeValue)) {\n const value = item.value;\n if (value === undefined || typeof value !== 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Assertion type '${typeValue}' requires a 'value' field (string).`,\n });\n continue;\n }\n\n // For regex type, validate that the pattern is valid\n if (typeValue === 'regex') {\n try {\n new RegExp(value);\n } catch {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Invalid regex pattern '${value}': not a valid regular expression.`,\n });\n }\n }\n }\n\n // Validate value field for types that require a string array value\n if (ASSERTION_TYPES_WITH_ARRAY_VALUE.has(typeValue)) {\n const value = item.value;\n if (!Array.isArray(value) || value.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Assertion type '${typeValue}' requires a 'value' field (non-empty string array).`,\n });\n continue;\n }\n }\n\n // Validate required field if present\n const required = item.required;\n if (required !== undefined) {\n validateRequiredField(required, location, filePath, errors);\n }\n }\n}\n\nfunction validateRequiredField(\n required: JsonValue,\n parentLocation: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n if (typeof required === 'boolean') {\n return; // Valid\n }\n if (typeof required === 'number') {\n if (required <= 0 || required > 1) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.required`,\n message: `Invalid 'required' value ${required}. When a number, it must be between 0 (exclusive) and 1 (inclusive).`,\n });\n }\n return;\n }\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.required`,\n message: `Invalid 'required' value. Must be a boolean or a number between 0 (exclusive) and 1 (inclusive).`,\n });\n}\n\nfunction validateContentForRoleMarkers(\n content: string,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n // Check for standard role markers that might confuse agentic providers\n const markers = ['@[System]:', '@[User]:', '@[Assistant]:', '@[Tool]:'];\n for (const marker of markers) {\n if (content.toLowerCase().includes(marker.toLowerCase())) {\n errors.push({\n severity: 'warning',\n filePath,\n location,\n message: `Content contains potential role marker '${marker}'. This may confuse agentic providers or cause prompt injection.`,\n });\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { CLI_PLACEHOLDERS } from '../providers/targets.js';\nimport { KNOWN_PROVIDERS, PROVIDER_ALIASES } from '../providers/types.js';\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// Known settings properties for each provider type\nconst COMMON_SETTINGS = new Set(['provider_batching', 'providerBatching']);\n\nconst RETRY_SETTINGS = new Set([\n 'max_retries',\n 'maxRetries',\n 'retry_initial_delay_ms',\n 'retryInitialDelayMs',\n 'retry_max_delay_ms',\n 'retryMaxDelayMs',\n 'retry_backoff_factor',\n 'retryBackoffFactor',\n 'retry_status_codes',\n 'retryStatusCodes',\n]);\n\nconst AZURE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'endpoint',\n 'resource',\n 'resourceName',\n 'api_key',\n 'apiKey',\n 'deployment',\n 'deploymentName',\n 'model',\n 'version',\n 'api_version',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst OPENAI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'endpoint',\n 'base_url',\n 'baseUrl',\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst OPENROUTER_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst ANTHROPIC_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n 'thinking_budget',\n 'thinkingBudget',\n]);\n\nconst GEMINI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst CODEX_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'model',\n 'executable',\n 'command',\n 'binary',\n 'args',\n 'arguments',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_directory',\n 'logDirectory',\n 'log_format',\n 'logFormat',\n 'log_output_format',\n 'logOutputFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst COPILOT_SDK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'cli_url',\n 'cliUrl',\n 'cli_path',\n 'cliPath',\n 'github_token',\n 'githubToken',\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_format',\n 'logFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst COPILOT_CLI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'executable',\n 'command',\n 'binary',\n 'args',\n 'arguments',\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_format',\n 'logFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst VSCODE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'executable',\n 'workspace_template',\n 'workspaceTemplate',\n 'wait',\n 'dry_run',\n 'dryRun',\n 'subagent_root',\n 'subagentRoot',\n 'timeout_seconds',\n 'timeoutSeconds',\n]);\n\nconst MOCK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'response',\n 'delayMs',\n 'delayMinMs',\n 'delayMaxMs',\n 'trace', // For testing tool-trajectory evaluator\n]);\n\n// CLI_SETTINGS removed - Zod schema validation now handles CLI provider settings validation\n// in resolveCliConfig() via CliTargetInputSchema\n\nconst CLAUDE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_directory',\n 'logDirectory',\n 'log_format',\n 'logFormat',\n 'log_output_format',\n 'logOutputFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n 'max_turns',\n 'maxTurns',\n 'max_budget_usd',\n 'maxBudgetUsd',\n]);\n\nfunction getKnownSettings(provider: string): Set<string> | null {\n const normalizedProvider = provider.toLowerCase();\n switch (normalizedProvider) {\n case 'openai':\n return OPENAI_SETTINGS;\n case 'openrouter':\n return OPENROUTER_SETTINGS;\n case 'azure':\n case 'azure-openai':\n return AZURE_SETTINGS;\n case 'anthropic':\n return ANTHROPIC_SETTINGS;\n case 'gemini':\n case 'google':\n case 'google-gemini':\n return GEMINI_SETTINGS;\n case 'codex':\n case 'codex-cli':\n return CODEX_SETTINGS;\n case 'copilot-sdk':\n case 'copilot_sdk':\n return COPILOT_SDK_SETTINGS;\n case 'copilot':\n case 'copilot-cli':\n return COPILOT_CLI_SETTINGS;\n case 'claude':\n case 'claude-code':\n case 'claude-cli':\n case 'claude-sdk':\n return CLAUDE_SETTINGS;\n case 'vscode':\n case 'vscode-insiders':\n return VSCODE_SETTINGS;\n case 'mock':\n return MOCK_SETTINGS;\n case 'cli':\n // CLI provider validation is now handled by Zod schema in resolveCliConfig()\n // Return null to skip duplicate validation in validateUnknownSettings()\n return null;\n default:\n return null; // Unknown provider, can't validate settings\n }\n}\n\nfunction validateUnknownSettings(\n target: JsonObject,\n provider: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n): void {\n const removedTargetFields = new Set(['workspace_template', 'workspaceTemplate']);\n const knownSettings = getKnownSettings(provider);\n if (!knownSettings) {\n // Unknown provider, skip settings validation\n return;\n }\n\n // Known base target fields that aren't settings\n const baseFields = new Set([\n 'name',\n 'provider',\n 'grader_target',\n 'judge_target',\n 'workers',\n '$schema',\n 'targets',\n ]);\n\n for (const key of Object.keys(target)) {\n if (removedTargetFields.has(key)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.${key}`,\n message:\n 'target-level workspace_template has been removed. Use eval-level workspace.template.',\n });\n continue;\n }\n\n if (!baseFields.has(key) && !knownSettings.has(key)) {\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.${key}`,\n message: `Unknown setting '${key}' for ${provider} provider. This property will be ignored.`,\n });\n }\n }\n}\n\n/**\n * Validate a targets file (agentv-targets-v2.1 schema).\n */\nexport async function validateTargetsFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n /**\n * Simplified CLI settings validation for early file validation.\n * Detailed type checking is now handled by Zod schema validation in resolveCliConfig().\n * This function focuses on critical early checks: command template presence and placeholder validation.\n */\n function validateCliSettings(\n target: JsonObject,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n // Critical check: command is required\n const command = target.command;\n if (typeof command !== 'string' || command.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.command`,\n message: \"CLI provider requires 'command' as a non-empty string\",\n });\n } else {\n // Validate CLI placeholders early to give helpful feedback\n recordUnknownPlaceholders(command, absolutePath, `${location}.command`, errors);\n }\n\n // Early validation of healthcheck structure and placeholders\n const healthcheck = target.healthcheck;\n if (healthcheck !== undefined) {\n validateCliHealthcheck(healthcheck, absolutePath, `${location}.healthcheck`, errors);\n }\n }\n\n function validateCliHealthcheck(\n healthcheck: unknown,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n if (!isObject(healthcheck)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: \"'healthcheck' must be an object when provided\",\n });\n return;\n }\n\n const timeoutSeconds = healthcheck.timeout_seconds ?? healthcheck.timeoutSeconds;\n if (timeoutSeconds !== undefined) {\n const numericTimeout = Number(timeoutSeconds);\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.timeoutSeconds`,\n message: 'healthcheck.timeoutSeconds must be a positive number when provided',\n });\n }\n }\n\n // Determine healthcheck type by presence of url or command\n const hasUrl = typeof healthcheck.url === 'string' && healthcheck.url.trim().length > 0;\n const hasCommand =\n typeof healthcheck.command === 'string' && healthcheck.command.trim().length > 0;\n\n if (!hasUrl && !hasCommand) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: \"healthcheck must have either 'url' (HTTP) or 'command' (command)\",\n });\n return;\n }\n\n if (hasUrl) {\n // HTTP healthcheck — url already validated above\n return;\n }\n\n // Command healthcheck\n recordUnknownPlaceholders(\n healthcheck.command as string,\n absolutePath,\n `${location}.command`,\n errors,\n );\n\n const cwd = healthcheck.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: 'healthcheck.cwd must be a string when provided',\n });\n }\n }\n\n function recordUnknownPlaceholders(\n template: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const placeholders = extractPlaceholders(template);\n for (const placeholder of placeholders) {\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: `Unknown CLI placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\n });\n }\n }\n }\n\n function extractPlaceholders(template: string): string[] {\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\n const result: string[] = [];\n for (const match of matches) {\n const placeholder = match[1];\n if (placeholder) {\n result.push(placeholder);\n }\n }\n return result;\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate targets array\n const targets = parsed.targets;\n if (!Array.isArray(targets)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'targets',\n message: \"Missing or invalid 'targets' field (must be an array)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate each target definition\n const knownProviders = [...KNOWN_PROVIDERS, ...PROVIDER_ALIASES];\n\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i];\n const location = `targets[${i}]`;\n\n if (!isObject(target)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Target must be an object',\n });\n continue;\n }\n\n // Required field: name\n const name = target.name;\n if (typeof name !== 'string' || name.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.name`,\n message: \"Missing or invalid 'name' field (must be a non-empty string)\",\n });\n }\n\n // Required field: provider\n const provider = target.provider;\n const providerValue = typeof provider === 'string' ? provider.trim().toLowerCase() : undefined;\n const isTemplated = typeof provider === 'string' && /^\\$\\{\\{.+\\}\\}$/.test(provider.trim());\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: \"Missing or invalid 'provider' field (must be a non-empty string)\",\n });\n } else if (!isTemplated && !knownProviders.includes(provider)) {\n // Warning for unknown providers (non-fatal); skip when provider uses ${{ VAR }}\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(', ')}`,\n });\n }\n\n // Validate CLI provider fields\n if (providerValue === 'cli') {\n validateCliSettings(target, absolutePath, location, errors);\n }\n\n // Check for unknown settings properties on target object\n if (typeof provider === 'string' && !isTemplated) {\n validateUnknownSettings(target, provider, absolutePath, location, errors);\n }\n\n // Optional field: grader_target / judge_target (must be string if present)\n const graderTarget = target.grader_target ?? target.judge_target;\n if (graderTarget !== undefined && typeof graderTarget !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.grader_target`,\n message: \"Invalid 'grader_target' field (must be a string)\",\n });\n }\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse } from 'yaml';\n\nimport type { ValidationError, ValidationResult } from './types.js';\n\n/**\n * Validate a config.yaml file for schema compliance and structural correctness.\n */\nexport async function validateConfigFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n // Check if parsed content is an object\n if (typeof parsed !== 'object' || parsed === null) {\n errors.push({\n severity: 'error',\n filePath,\n message: 'Config file must contain a valid YAML object',\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n\n const config = parsed as Record<string, unknown>;\n\n // Validate eval_patterns if present\n const evalPatterns = config.eval_patterns;\n if (evalPatterns !== undefined) {\n if (!Array.isArray(evalPatterns)) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'eval_patterns',\n message: \"Field 'eval_patterns' must be an array\",\n });\n } else if (!evalPatterns.every((p) => typeof p === 'string')) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'eval_patterns',\n message: \"All entries in 'eval_patterns' must be strings\",\n });\n } else if (evalPatterns.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'eval_patterns',\n message: \"Field 'eval_patterns' is empty. Consider removing it or adding patterns.\",\n });\n }\n }\n\n // Check for unexpected fields\n // Validate required_version if present\n const requiredVersion = config.required_version;\n if (requiredVersion !== undefined) {\n if (typeof requiredVersion !== 'string' || requiredVersion.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'required_version',\n message: 'Field \\'required_version\\' must be a non-empty string (e.g. \">=3.1.0\")',\n });\n }\n }\n\n const allowedFields = new Set(['$schema', 'eval_patterns', 'required_version', 'execution']);\n const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));\n\n if (unexpectedFields.length > 0) {\n errors.push({\n severity: 'warning',\n filePath,\n message: `Unexpected fields: ${unexpectedFields.join(', ')}`,\n });\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath,\n fileType: 'config',\n errors,\n };\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n message: `Failed to parse config file: ${(error as Error).message}`,\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { buildSearchRoots, findGitRoot, resolveFileReference } from '../file-utils.js';\nimport type { ValidationError } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate that file references in eval file content exist.\n * Checks content blocks with type: \"file\" and validates the referenced file exists.\n * Also checks that referenced files are not empty.\n */\nexport async function validateFileReferences(\n evalFilePath: string,\n): Promise<readonly ValidationError[]> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(evalFilePath);\n\n // Find git root and build search roots (same as yaml-parser does at runtime)\n const gitRoot = await findGitRoot(absolutePath);\n if (!gitRoot) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'Cannot validate file references: git repository root not found',\n });\n return errors;\n }\n\n const searchRoots = buildSearchRoots(absolutePath, gitRoot);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch {\n // Parse errors are already caught by eval-validator\n return errors;\n }\n\n if (!isObject(parsed)) {\n return errors;\n }\n\n let cases: JsonValue | undefined = parsed.tests;\n if (cases === undefined && 'eval_cases' in parsed) {\n cases = parsed.eval_cases;\n }\n if (cases === undefined && 'evalcases' in parsed) {\n cases = parsed.evalcases;\n }\n if (!Array.isArray(cases)) {\n return errors;\n }\n\n for (let i = 0; i < cases.length; i++) {\n const evalCase = cases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input\n const inputField = evalCase.input;\n if (Array.isArray(inputField)) {\n await validateMessagesFileRefs(\n inputField,\n `tests[${i}].input`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_output\n const expectedOutputField = evalCase.expected_output;\n if (Array.isArray(expectedOutputField)) {\n await validateMessagesFileRefs(\n expectedOutputField,\n `tests[${i}].expected_output`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n }\n\n return errors;\n}\n\nasync function validateMessagesFileRefs(\n messages: JsonArray,\n location: string,\n searchRoots: readonly string[],\n filePath: string,\n errors: ValidationError[],\n): Promise<void> {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (!isObject(message)) {\n continue;\n }\n\n const content = message.content;\n if (typeof content === 'string') {\n continue;\n }\n\n if (!Array.isArray(content)) {\n continue;\n }\n\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n if (!isObject(contentItem)) {\n continue;\n }\n\n const type = contentItem.type;\n if (type !== 'file') {\n continue;\n }\n\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}].value`,\n message: \"File reference must have a 'value' field with the file path\",\n });\n continue;\n }\n\n // Use the same file resolution logic as yaml-parser at runtime\n const { resolvedPath } = await resolveFileReference(value, searchRoots);\n\n if (!resolvedPath) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file not found: ${value}`,\n });\n } else {\n // Check that file is not empty\n try {\n const fileContent = await readFile(resolvedPath, 'utf8');\n if (fileContent.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file is empty: ${value}`,\n });\n }\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Cannot read referenced file: ${value} (${(error as Error).message})`,\n });\n }\n }\n }\n }\n}\n"],"mappings":"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","names":["readFile","path","parse","path","readFile","parse","readFile","path","parse","isObject","path","readFile","parse","absolutePath","errors","readFile","parse","readFile","path","parse","isObject","path","readFile","parse"]}
|
|
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/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport type { FileType } from './types.js';\n\nconst SCHEMA_EVAL_V2 = 'agentv-eval-v2';\nconst SCHEMA_TARGETS_V2 = 'agentv-targets-v2.2';\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\n\n/**\n * Detect file type by reading $schema field from YAML file.\n * If $schema is missing, infers type from filename/path:\n * - config.yaml under .agentv folder → 'config'\n * - targets.yaml under .agentv folder → 'targets'\n * - All other YAML files → 'eval' (default)\n */\nexport async function detectFileType(filePath: string): Promise<FileType> {\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n if (typeof parsed !== 'object' || parsed === null) {\n return inferFileTypeFromPath(filePath);\n }\n\n const record = parsed as Record<string, unknown>;\n const schema = record.$schema;\n\n if (typeof schema !== 'string') {\n // No $schema field - infer from path\n return inferFileTypeFromPath(filePath);\n }\n\n switch (schema) {\n case SCHEMA_EVAL_V2:\n return 'eval';\n case SCHEMA_TARGETS_V2:\n return 'targets';\n case SCHEMA_CONFIG_V2:\n return 'config';\n default:\n // Unknown schema - infer from path\n return inferFileTypeFromPath(filePath);\n }\n } catch {\n return inferFileTypeFromPath(filePath);\n }\n}\n\n/**\n * Infer file type from filename and directory path.\n */\nfunction inferFileTypeFromPath(filePath: string): FileType {\n const normalized = path.normalize(filePath).replace(/\\\\/g, '/');\n const basename = path.basename(filePath);\n\n // Check if file is under .agentv folder\n if (normalized.includes('/.agentv/')) {\n if (basename === 'config.yaml' || basename === 'config.yml') {\n return 'config';\n }\n if (basename === 'targets.yaml' || basename === 'targets.yml') {\n return 'targets';\n }\n }\n\n // Default to eval file\n return 'eval';\n}\n\n/**\n * Check if a schema value is a valid AgentV schema identifier.\n */\nexport function isValidSchema(schema: unknown): boolean {\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2 || schema === SCHEMA_CONFIG_V2;\n}\n\n/**\n * Get the expected schema for a file type.\n */\nexport function getExpectedSchema(fileType: FileType): string | undefined {\n switch (fileType) {\n case 'eval':\n return SCHEMA_EVAL_V2;\n case 'targets':\n return SCHEMA_TARGETS_V2;\n case 'config':\n return SCHEMA_CONFIG_V2;\n default:\n return undefined;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { interpolateEnv } from '../interpolation.js';\nimport { loadCasesFromFile } from '../loaders/case-file-loader.js';\nimport { isEvaluatorKind } from '../types.js';\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\n/** Assertion evaluator types that require a string `value` field. */\nconst ASSERTION_TYPES_WITH_STRING_VALUE = new Set([\n 'contains',\n 'icontains',\n 'starts-with',\n 'ends-with',\n 'equals',\n 'regex',\n]);\n/** Assertion evaluator types that require a string[] `value` field. */\nconst ASSERTION_TYPES_WITH_ARRAY_VALUE = new Set([\n 'contains-any',\n 'contains-all',\n 'icontains-any',\n 'icontains-all',\n]);\n\n/** Valid file extensions for external test files. */\nconst VALID_TEST_FILE_EXTENSIONS = new Set(['.yaml', '.yml', '.jsonl']);\n\n/** Name field pattern: lowercase alphanumeric with hyphens. */\nconst NAME_PATTERN = /^[a-z0-9-]+$/;\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate an eval file (agentv-eval-v2 schema).\n */\nexport async function validateEvalFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = interpolateEnv(parse(content), process.env);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate metadata fields\n validateMetadata(parsed, absolutePath, errors);\n\n // Validate suite-level input (optional: string shorthand or message array)\n const suiteInput = parsed.input;\n if (suiteInput !== undefined) {\n if (typeof suiteInput === 'string') {\n // String shorthand is valid\n } else if (Array.isArray(suiteInput)) {\n validateMessages(suiteInput, 'input', absolutePath, errors);\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'input',\n message: \"Invalid suite-level 'input' field (must be a string or array of messages)\",\n });\n }\n }\n\n const cases: JsonValue | undefined = parsed.tests;\n\n // tests can be a string path (external file reference) or an array\n if (typeof cases === 'string') {\n validateTestsStringPath(cases, absolutePath, errors);\n await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, 'workspace');\n\n const ext = path.extname(cases).toLowerCase();\n if (VALID_TEST_FILE_EXTENSIONS.has(ext)) {\n const externalCasesPath = path.resolve(path.dirname(absolutePath), cases);\n try {\n const externalCases = await loadCasesFromFile(externalCasesPath);\n for (let i = 0; i < externalCases.length; i++) {\n const externalCase = externalCases[i];\n await validateWorkspaceConfig(\n externalCase.workspace,\n absolutePath,\n errors,\n `tests[${i}].workspace`,\n );\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'tests',\n message,\n });\n }\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n if (!Array.isArray(cases)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'tests',\n message: \"Missing or invalid 'tests' field (must be an array or a file path string)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n }\n\n // Validate each eval case\n for (let i = 0; i < cases.length; i++) {\n const evalCase = cases[i];\n const location = `tests[${i}]`;\n\n // Tests array items can be file references (e.g., \"file://cases/accuracy.yaml\")\n if (typeof evalCase === 'string') {\n if (evalCase.startsWith('file://')) {\n validateTestsStringPath(evalCase, absolutePath, errors);\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Test case string must be a file reference (file://...)',\n });\n }\n continue;\n }\n\n if (!isObject(evalCase)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Eval case must be an object',\n });\n continue;\n }\n\n // Required fields: id, input\n const id = evalCase.id;\n if (typeof id !== 'string' || id.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.id`,\n message: \"Missing or invalid 'id' field (must be a non-empty string)\",\n });\n }\n\n // Optional: criteria (with backward-compat alias expected_outcome)\n let criteria: JsonValue | undefined = evalCase.criteria;\n if (criteria === undefined && 'expected_outcome' in evalCase) {\n criteria = evalCase.expected_outcome;\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.expected_outcome`,\n message: \"'expected_outcome' is deprecated. Use 'criteria' instead.\",\n });\n }\n if (criteria !== undefined && (typeof criteria !== 'string' || criteria.trim().length === 0)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.criteria`,\n message: \"Invalid 'criteria' field (must be a non-empty string if provided)\",\n });\n }\n\n // input field (string shorthand or message array)\n const inputField = evalCase.input;\n if (inputField !== undefined) {\n if (typeof inputField === 'string') {\n // String shorthand is valid - no further validation needed\n } else if (Array.isArray(inputField)) {\n validateMessages(inputField, `${location}.input`, absolutePath, errors);\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input`,\n message: \"Invalid 'input' field (must be a string or array of messages)\",\n });\n }\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input`,\n message: \"Missing 'input' field (must be a string or array of messages)\",\n });\n }\n\n // expected_output field (string/object shorthand or message array)\n const expectedOutputField = evalCase.expected_output;\n if (expectedOutputField !== undefined) {\n if (typeof expectedOutputField === 'string') {\n // String shorthand is valid - no further validation needed\n } else if (Array.isArray(expectedOutputField)) {\n // Check if it looks like a message array (first element has 'role')\n if (\n expectedOutputField.length > 0 &&\n isObject(expectedOutputField[0]) &&\n 'role' in expectedOutputField[0]\n ) {\n validateMessages(\n expectedOutputField,\n `${location}.expected_output`,\n absolutePath,\n errors,\n );\n }\n // Otherwise it's treated as structured array content - valid\n } else if (isObject(expectedOutputField)) {\n // Object shorthand or single message - both are valid\n } else {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_output`,\n message: \"Invalid 'expected_output' field (must be a string, object, or array)\",\n });\n }\n }\n\n // assertions field (array of assertion objects); also accept legacy `assert`\n const assertField = evalCase.assertions ?? evalCase.assert;\n if (assertField !== undefined) {\n validateAssertArray(assertField, location, absolutePath, errors);\n }\n\n await validateWorkspaceConfig(\n evalCase.workspace,\n absolutePath,\n errors,\n `${location}.workspace`,\n );\n }\n\n await validateWorkspaceConfig(parsed.workspace, absolutePath, errors, 'workspace');\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\n };\n}\n\nasync function validateWorkspaceConfig(\n workspace: JsonValue | undefined,\n evalFilePath: string,\n errors: ValidationError[],\n location: string,\n): Promise<void> {\n if (workspace === undefined) {\n return;\n }\n\n if (isObject(workspace)) {\n validateWorkspaceRepoConfig(workspace, evalFilePath, errors);\n return;\n }\n\n if (typeof workspace !== 'string') {\n return;\n }\n\n const workspacePath = path.resolve(path.dirname(evalFilePath), workspace);\n\n try {\n const workspaceContent = await readFile(workspacePath, 'utf8');\n const parsedWorkspace = interpolateEnv(parse(workspaceContent), process.env);\n if (!isObject(parsedWorkspace)) {\n errors.push({\n severity: 'error',\n filePath: evalFilePath,\n location,\n message: `External workspace file must contain a YAML object: ${workspace}`,\n });\n return;\n }\n\n validateWorkspaceRepoConfig(parsedWorkspace, workspacePath, errors);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push({\n severity: 'error',\n filePath: evalFilePath,\n location,\n message: `Failed to load external workspace file '${workspace}': ${message}`,\n });\n }\n}\n\nfunction validateWorkspaceRepoConfig(\n workspace: JsonObject,\n filePath: string,\n errors: ValidationError[],\n): void {\n const repos = workspace.repos;\n const hooks = workspace.hooks;\n const afterEachHook = isObject(hooks) ? hooks.after_each : undefined;\n const isolation = workspace.isolation;\n\n // Depth vs ancestor warning\n if (Array.isArray(repos)) {\n for (const repo of repos) {\n if (!isObject(repo)) continue;\n const source = repo.source;\n const checkout = repo.checkout;\n const clone = repo.clone;\n\n if (isObject(source) && isObject(checkout)) {\n const sourceType = source.type;\n const resolve = checkout.resolve;\n if (sourceType === 'local' && typeof resolve === 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `workspace.repos[path=${repo.path}]`,\n message:\n 'checkout.resolve has no effect for a local source. ' +\n 'Use source.type to choose where the repo comes from; keep checkout.ref or checkout.ancestor only when pinning a local source.',\n });\n }\n }\n\n if (isObject(checkout) && isObject(clone)) {\n const ancestor = checkout.ancestor;\n const depth = clone.depth;\n if (typeof ancestor === 'number' && typeof depth === 'number' && depth < ancestor + 1) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `workspace.repos[path=${repo.path}]`,\n message:\n `clone.depth (${depth}) may be insufficient for checkout.ancestor (${ancestor}). ` +\n `Recommend depth >= ${ancestor + 1}.`,\n });\n }\n }\n }\n }\n\n // Reset without repos warning\n if (isObject(afterEachHook) && afterEachHook.reset && afterEachHook.reset !== 'none') {\n if (!Array.isArray(repos) || repos.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'workspace.hooks.after_each',\n message: `hooks.after_each.reset '${afterEachHook.reset}' has no effect without repos.`,\n });\n }\n }\n\n // after_each reset with per_test isolation warning\n if (isObject(afterEachHook) && afterEachHook.reset && isolation === 'per_test') {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'workspace.hooks.after_each',\n message:\n 'hooks.after_each.reset is redundant with isolation: per_test (each test gets a fresh workspace).',\n });\n }\n}\n\nfunction validateMessages(\n messages: JsonArray,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n const msgLocation = `${location}[${i}]`;\n\n if (!isObject(message)) {\n errors.push({\n severity: 'error',\n filePath,\n location: msgLocation,\n message: 'Message must be an object',\n });\n continue;\n }\n\n // Validate role field\n const role = message.role;\n const validRoles = ['system', 'user', 'assistant'];\n if (!validRoles.includes(role as string)) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.role`,\n message: `Invalid role '${role}'. Must be one of: ${validRoles.join(', ')}`,\n });\n }\n\n // Validate content field (can be string, array, or object)\n // Messages with tool_calls may omit content entirely (e.g., assistant tool-call messages).\n const content = message.content;\n const hasToolCalls = 'tool_calls' in message;\n if (content === undefined && hasToolCalls) {\n // Valid: assistant message with tool_calls but no content\n } else if (typeof content === 'string') {\n validateContentForRoleMarkers(content, `${msgLocation}.content`, filePath, errors);\n } else if (Array.isArray(content)) {\n // Array content - validate each element\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n const contentLocation = `${msgLocation}.content[${j}]`;\n\n if (typeof contentItem === 'string') {\n validateContentForRoleMarkers(contentItem, contentLocation, filePath, errors);\n } else if (isObject(contentItem)) {\n const type = contentItem.type;\n if (typeof type !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.type`,\n message: \"Content object must have a 'type' field\",\n });\n }\n\n // For 'file' type, we'll validate existence later in file-reference-validator\n // For 'text' type, require 'value' field\n if (type === 'text') {\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${contentLocation}.value`,\n message: \"Content with type 'text' must have a 'value' field\",\n });\n } else {\n validateContentForRoleMarkers(value, `${contentLocation}.value`, filePath, errors);\n }\n }\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: contentLocation,\n message: 'Content array items must be strings or objects',\n });\n }\n }\n } else if (isObject(content)) {\n // Structured content objects (e.g., { decision: \"CLEAR\" }) are valid\n // — the runtime accepts them for expected_output and input messages.\n } else {\n errors.push({\n severity: 'error',\n filePath,\n location: `${msgLocation}.content`,\n message: \"Missing or invalid 'content' field (must be a string, array, or object)\",\n });\n }\n }\n}\n\nfunction validateMetadata(parsed: JsonObject, filePath: string, errors: ValidationError[]): void {\n const name = parsed.name;\n if (name !== undefined) {\n if (typeof name === 'string') {\n if (!NAME_PATTERN.test(name)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'name',\n message: `Invalid 'name' format '${name}'. Must match pattern /^[a-z0-9-]+$/ (lowercase alphanumeric with hyphens).`,\n });\n }\n }\n\n // Warn if name is present but description is missing\n if (!('description' in parsed) || parsed.description === undefined) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'name',\n message: \"When 'name' is present, 'description' should also be provided.\",\n });\n }\n }\n}\n\nfunction validateTestsStringPath(\n testsPath: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n const ext = path.extname(testsPath);\n if (!VALID_TEST_FILE_EXTENSIONS.has(ext)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'tests',\n message: `Unsupported file extension '${ext}' for tests path '${testsPath}'. Supported extensions: ${[...VALID_TEST_FILE_EXTENSIONS].join(', ')}`,\n });\n }\n}\n\nfunction validateAssertArray(\n assertField: JsonValue,\n parentLocation: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n if (!Array.isArray(assertField)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions`,\n message: \"'assertions' must be an array of assertion objects.\",\n });\n return;\n }\n\n // String items in the assertions array are valid shorthand — the parser collects them\n // into a single rubrics/llm-grader evaluator. Filter them out before object validation.\n const objectItems: { item: JsonObject; index: number }[] = [];\n for (let i = 0; i < assertField.length; i++) {\n const item = assertField[i];\n if (typeof item === 'string') {\n if (item.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions[${i}]`,\n message: 'Empty string assertion item will be ignored.',\n });\n }\n continue; // Valid shorthand — skip object validation\n }\n if (!isObject(item)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.assertions[${i}]`,\n message: 'Assertion item must be a string or an object with a type field.',\n });\n continue;\n }\n objectItems.push({ item, index: i });\n }\n\n for (const { item, index } of objectItems) {\n const location = `${parentLocation}.assertions[${index}]`;\n\n // Validate type field\n const rawTypeValue = item.type;\n if (rawTypeValue === undefined || typeof rawTypeValue !== 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.type`,\n message: \"Assertion item is missing a 'type' field.\",\n });\n continue;\n }\n\n // Normalize snake_case to kebab-case for backward compatibility\n const typeValue = rawTypeValue.replace(/_/g, '-');\n\n if (!isEvaluatorKind(typeValue)) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.type`,\n message: `Unknown assertion type '${rawTypeValue}'.`,\n });\n continue;\n }\n\n // Validate value field for types that require a string value\n if (ASSERTION_TYPES_WITH_STRING_VALUE.has(typeValue)) {\n const value = item.value;\n if (value === undefined || typeof value !== 'string') {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Assertion type '${typeValue}' requires a 'value' field (string).`,\n });\n continue;\n }\n\n // For regex type, validate that the pattern is valid\n if (typeValue === 'regex') {\n try {\n new RegExp(value);\n } catch {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Invalid regex pattern '${value}': not a valid regular expression.`,\n });\n }\n }\n }\n\n // Validate value field for types that require a string array value\n if (ASSERTION_TYPES_WITH_ARRAY_VALUE.has(typeValue)) {\n const value = item.value;\n if (!Array.isArray(value) || value.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}.value`,\n message: `Assertion type '${typeValue}' requires a 'value' field (non-empty string array).`,\n });\n continue;\n }\n }\n\n // Validate required field if present\n const required = item.required;\n if (required !== undefined) {\n validateRequiredField(required, location, filePath, errors);\n }\n }\n}\n\nfunction validateRequiredField(\n required: JsonValue,\n parentLocation: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n if (typeof required === 'boolean') {\n return; // Valid\n }\n if (typeof required === 'number') {\n if (required <= 0 || required > 1) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.required`,\n message: `Invalid 'required' value ${required}. When a number, it must be between 0 (exclusive) and 1 (inclusive).`,\n });\n }\n return;\n }\n errors.push({\n severity: 'warning',\n filePath,\n location: `${parentLocation}.required`,\n message: `Invalid 'required' value. Must be a boolean or a number between 0 (exclusive) and 1 (inclusive).`,\n });\n}\n\nfunction validateContentForRoleMarkers(\n content: string,\n location: string,\n filePath: string,\n errors: ValidationError[],\n): void {\n // Check for standard role markers that might confuse agentic providers\n const markers = ['@[System]:', '@[User]:', '@[Assistant]:', '@[Tool]:'];\n for (const marker of markers) {\n if (content.toLowerCase().includes(marker.toLowerCase())) {\n errors.push({\n severity: 'warning',\n filePath,\n location,\n message: `Content contains potential role marker '${marker}'. This may confuse agentic providers or cause prompt injection.`,\n });\n }\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { CLI_PLACEHOLDERS } from '../providers/targets.js';\nimport { KNOWN_PROVIDERS, PROVIDER_ALIASES } from '../providers/types.js';\nimport type { ValidationError, ValidationResult } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// Known settings properties for each provider type\nconst COMMON_SETTINGS = new Set(['provider_batching', 'providerBatching']);\n\nconst RETRY_SETTINGS = new Set([\n 'max_retries',\n 'maxRetries',\n 'retry_initial_delay_ms',\n 'retryInitialDelayMs',\n 'retry_max_delay_ms',\n 'retryMaxDelayMs',\n 'retry_backoff_factor',\n 'retryBackoffFactor',\n 'retry_status_codes',\n 'retryStatusCodes',\n]);\n\nconst AZURE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'endpoint',\n 'resource',\n 'resourceName',\n 'api_key',\n 'apiKey',\n 'deployment',\n 'deploymentName',\n 'model',\n 'version',\n 'api_version',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst OPENAI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'endpoint',\n 'base_url',\n 'baseUrl',\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst OPENROUTER_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst ANTHROPIC_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n 'thinking_budget',\n 'thinkingBudget',\n]);\n\nconst GEMINI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n ...RETRY_SETTINGS,\n 'api_key',\n 'apiKey',\n 'model',\n 'deployment',\n 'variant',\n 'temperature',\n 'max_output_tokens',\n 'maxTokens',\n]);\n\nconst CODEX_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'model',\n 'executable',\n 'command',\n 'binary',\n 'args',\n 'arguments',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_directory',\n 'logDirectory',\n 'log_format',\n 'logFormat',\n 'log_output_format',\n 'logOutputFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst COPILOT_SDK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'cli_url',\n 'cliUrl',\n 'cli_path',\n 'cliPath',\n 'github_token',\n 'githubToken',\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_format',\n 'logFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst COPILOT_CLI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'executable',\n 'command',\n 'binary',\n 'args',\n 'arguments',\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_format',\n 'logFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n]);\n\nconst VSCODE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'executable',\n 'workspace_template',\n 'workspaceTemplate',\n 'wait',\n 'dry_run',\n 'dryRun',\n 'subagent_root',\n 'subagentRoot',\n 'timeout_seconds',\n 'timeoutSeconds',\n]);\n\nconst MOCK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'response',\n 'delayMs',\n 'delayMinMs',\n 'delayMaxMs',\n 'trace', // For testing tool-trajectory evaluator\n]);\n\n// CLI_SETTINGS removed - Zod schema validation now handles CLI provider settings validation\n// in resolveCliConfig() via CliTargetInputSchema\n\nconst CLAUDE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'model',\n 'cwd',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'log_dir',\n 'logDir',\n 'log_directory',\n 'logDirectory',\n 'log_format',\n 'logFormat',\n 'log_output_format',\n 'logOutputFormat',\n 'system_prompt',\n 'systemPrompt',\n 'workspace_template',\n 'workspaceTemplate',\n 'max_turns',\n 'maxTurns',\n 'max_budget_usd',\n 'maxBudgetUsd',\n]);\n\nfunction getKnownSettings(provider: string): Set<string> | null {\n const normalizedProvider = provider.toLowerCase();\n switch (normalizedProvider) {\n case 'openai':\n return OPENAI_SETTINGS;\n case 'openrouter':\n return OPENROUTER_SETTINGS;\n case 'azure':\n case 'azure-openai':\n return AZURE_SETTINGS;\n case 'anthropic':\n return ANTHROPIC_SETTINGS;\n case 'gemini':\n case 'google':\n case 'google-gemini':\n return GEMINI_SETTINGS;\n case 'codex':\n case 'codex-cli':\n return CODEX_SETTINGS;\n case 'copilot-sdk':\n case 'copilot_sdk':\n return COPILOT_SDK_SETTINGS;\n case 'copilot':\n case 'copilot-cli':\n return COPILOT_CLI_SETTINGS;\n case 'claude':\n case 'claude-code':\n case 'claude-cli':\n case 'claude-sdk':\n return CLAUDE_SETTINGS;\n case 'vscode':\n case 'vscode-insiders':\n return VSCODE_SETTINGS;\n case 'mock':\n return MOCK_SETTINGS;\n case 'cli':\n // CLI provider validation is now handled by Zod schema in resolveCliConfig()\n // Return null to skip duplicate validation in validateUnknownSettings()\n return null;\n default:\n return null; // Unknown provider, can't validate settings\n }\n}\n\nfunction validateUnknownSettings(\n target: JsonObject,\n provider: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n): void {\n const removedTargetFields = new Set(['workspace_template', 'workspaceTemplate']);\n const knownSettings = getKnownSettings(provider);\n if (!knownSettings) {\n // Unknown provider, skip settings validation\n return;\n }\n\n // Known base target fields that aren't settings\n const baseFields = new Set([\n 'name',\n 'provider',\n 'grader_target',\n 'judge_target',\n 'workers',\n '$schema',\n 'targets',\n ]);\n\n for (const key of Object.keys(target)) {\n if (removedTargetFields.has(key)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.${key}`,\n message:\n 'target-level workspace_template has been removed. Use eval-level workspace.template.',\n });\n continue;\n }\n\n if (!baseFields.has(key) && !knownSettings.has(key)) {\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.${key}`,\n message: `Unknown setting '${key}' for ${provider} provider. This property will be ignored.`,\n });\n }\n }\n}\n\n/**\n * Validate a targets file (agentv-targets-v2.1 schema).\n */\nexport async function validateTargetsFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(filePath);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n /**\n * Simplified CLI settings validation for early file validation.\n * Detailed type checking is now handled by Zod schema validation in resolveCliConfig().\n * This function focuses on critical early checks: command template presence and placeholder validation.\n */\n function validateCliSettings(\n target: JsonObject,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n // Critical check: command is required\n const command = target.command;\n if (typeof command !== 'string' || command.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.command`,\n message: \"CLI provider requires 'command' as a non-empty string\",\n });\n } else {\n // Validate CLI placeholders early to give helpful feedback\n recordUnknownPlaceholders(command, absolutePath, `${location}.command`, errors);\n }\n\n // Early validation of healthcheck structure and placeholders\n const healthcheck = target.healthcheck;\n if (healthcheck !== undefined) {\n validateCliHealthcheck(healthcheck, absolutePath, `${location}.healthcheck`, errors);\n }\n }\n\n function validateCliHealthcheck(\n healthcheck: unknown,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n if (!isObject(healthcheck)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: \"'healthcheck' must be an object when provided\",\n });\n return;\n }\n\n const timeoutSeconds = healthcheck.timeout_seconds ?? healthcheck.timeoutSeconds;\n if (timeoutSeconds !== undefined) {\n const numericTimeout = Number(timeoutSeconds);\n if (!Number.isFinite(numericTimeout) || numericTimeout <= 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.timeoutSeconds`,\n message: 'healthcheck.timeoutSeconds must be a positive number when provided',\n });\n }\n }\n\n // Determine healthcheck type by presence of url or command\n const hasUrl = typeof healthcheck.url === 'string' && healthcheck.url.trim().length > 0;\n const hasCommand =\n typeof healthcheck.command === 'string' && healthcheck.command.trim().length > 0;\n\n if (!hasUrl && !hasCommand) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: \"healthcheck must have either 'url' (HTTP) or 'command' (command)\",\n });\n return;\n }\n\n if (hasUrl) {\n // HTTP healthcheck — url already validated above\n return;\n }\n\n // Command healthcheck\n recordUnknownPlaceholders(\n healthcheck.command as string,\n absolutePath,\n `${location}.command`,\n errors,\n );\n\n const cwd = healthcheck.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: 'healthcheck.cwd must be a string when provided',\n });\n }\n }\n\n function recordUnknownPlaceholders(\n template: string,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const placeholders = extractPlaceholders(template);\n for (const placeholder of placeholders) {\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: `Unknown CLI placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\n });\n }\n }\n }\n\n function extractPlaceholders(template: string): string[] {\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\n const result: string[] = [];\n for (const match of matches) {\n const placeholder = match[1];\n if (placeholder) {\n result.push(placeholder);\n }\n }\n return result;\n }\n\n if (!isObject(parsed)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'File must contain a YAML object',\n });\n return {\n valid: false,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate targets array\n const targets = parsed.targets;\n if (!Array.isArray(targets)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'targets',\n message: \"Missing or invalid 'targets' field (must be an array)\",\n });\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n }\n\n // Validate each target definition\n const knownProviders = [...KNOWN_PROVIDERS, ...PROVIDER_ALIASES];\n\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i];\n const location = `targets[${i}]`;\n\n if (!isObject(target)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location,\n message: 'Target must be an object',\n });\n continue;\n }\n\n // Required field: name\n const name = target.name;\n if (typeof name !== 'string' || name.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.name`,\n message: \"Missing or invalid 'name' field (must be a non-empty string)\",\n });\n }\n\n // Required field: provider\n const provider = target.provider;\n const providerValue = typeof provider === 'string' ? provider.trim().toLowerCase() : undefined;\n const isTemplated = typeof provider === 'string' && /^\\$\\{\\{.+\\}\\}$/.test(provider.trim());\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: \"Missing or invalid 'provider' field (must be a non-empty string)\",\n });\n } else if (!isTemplated && !knownProviders.includes(provider)) {\n // Warning for unknown providers (non-fatal); skip when provider uses ${{ VAR }}\n errors.push({\n severity: 'warning',\n filePath: absolutePath,\n location: `${location}.provider`,\n message: `Unknown provider '${provider}'. Known providers: ${knownProviders.join(', ')}`,\n });\n }\n\n // Validate CLI provider fields\n if (providerValue === 'cli') {\n validateCliSettings(target, absolutePath, location, errors);\n }\n\n // Check for unknown settings properties on target object\n if (typeof provider === 'string' && !isTemplated) {\n validateUnknownSettings(target, provider, absolutePath, location, errors);\n }\n\n // Optional field: grader_target / judge_target (must be string if present)\n const graderTarget = target.grader_target ?? target.judge_target;\n if (graderTarget !== undefined && typeof graderTarget !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.grader_target`,\n message: \"Invalid 'grader_target' field (must be a string)\",\n });\n }\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath: absolutePath,\n fileType: 'targets',\n errors,\n };\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse } from 'yaml';\n\nimport type { ValidationError, ValidationResult } from './types.js';\n\n/**\n * Validate a config.yaml file for schema compliance and structural correctness.\n */\nexport async function validateConfigFile(filePath: string): Promise<ValidationResult> {\n const errors: ValidationError[] = [];\n\n try {\n const content = await readFile(filePath, 'utf8');\n const parsed = parse(content) as unknown;\n\n // Check if parsed content is an object\n if (typeof parsed !== 'object' || parsed === null) {\n errors.push({\n severity: 'error',\n filePath,\n message: 'Config file must contain a valid YAML object',\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n\n const config = parsed as Record<string, unknown>;\n\n // Validate eval_patterns if present\n const evalPatterns = config.eval_patterns;\n if (evalPatterns !== undefined) {\n if (!Array.isArray(evalPatterns)) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'eval_patterns',\n message: \"Field 'eval_patterns' must be an array\",\n });\n } else if (!evalPatterns.every((p) => typeof p === 'string')) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'eval_patterns',\n message: \"All entries in 'eval_patterns' must be strings\",\n });\n } else if (evalPatterns.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'eval_patterns',\n message: \"Field 'eval_patterns' is empty. Consider removing it or adding patterns.\",\n });\n }\n }\n\n // Check for unexpected fields\n // Validate required_version if present\n const requiredVersion = config.required_version;\n if (requiredVersion !== undefined) {\n if (typeof requiredVersion !== 'string' || requiredVersion.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'required_version',\n message: 'Field \\'required_version\\' must be a non-empty string (e.g. \">=3.1.0\")',\n });\n }\n }\n\n const allowedFields = new Set(['$schema', 'eval_patterns', 'required_version', 'execution']);\n const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));\n\n if (unexpectedFields.length > 0) {\n errors.push({\n severity: 'warning',\n filePath,\n message: `Unexpected fields: ${unexpectedFields.join(', ')}`,\n });\n }\n\n return {\n valid: errors.filter((e) => e.severity === 'error').length === 0,\n filePath,\n fileType: 'config',\n errors,\n };\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n message: `Failed to parse config file: ${(error as Error).message}`,\n });\n return { valid: false, filePath, fileType: 'config', errors };\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\nimport { buildSearchRoots, findGitRoot, resolveFileReference } from '../file-utils.js';\nimport type { ValidationError } from './types.js';\n\ntype JsonValue = string | number | boolean | null | JsonObject | JsonArray;\ntype JsonObject = { readonly [key: string]: JsonValue };\ntype JsonArray = readonly JsonValue[];\n\nfunction isObject(value: unknown): value is JsonObject {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Validate that file references in eval file content exist.\n * Checks content blocks with type: \"file\" and validates the referenced file exists.\n * Also checks that referenced files are not empty.\n */\nexport async function validateFileReferences(\n evalFilePath: string,\n): Promise<readonly ValidationError[]> {\n const errors: ValidationError[] = [];\n const absolutePath = path.resolve(evalFilePath);\n\n // Find git root and build search roots (same as yaml-parser does at runtime)\n const gitRoot = await findGitRoot(absolutePath);\n if (!gitRoot) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n message: 'Cannot validate file references: git repository root not found',\n });\n return errors;\n }\n\n const searchRoots = buildSearchRoots(absolutePath, gitRoot);\n\n let parsed: unknown;\n try {\n const content = await readFile(absolutePath, 'utf8');\n parsed = parse(content);\n } catch {\n // Parse errors are already caught by eval-validator\n return errors;\n }\n\n if (!isObject(parsed)) {\n return errors;\n }\n\n let cases: JsonValue | undefined = parsed.tests;\n if (cases === undefined && 'eval_cases' in parsed) {\n cases = parsed.eval_cases;\n }\n if (cases === undefined && 'evalcases' in parsed) {\n cases = parsed.evalcases;\n }\n if (!Array.isArray(cases)) {\n return errors;\n }\n\n for (let i = 0; i < cases.length; i++) {\n const evalCase = cases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input\n const inputField = evalCase.input;\n if (Array.isArray(inputField)) {\n await validateMessagesFileRefs(\n inputField,\n `tests[${i}].input`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_output\n const expectedOutputField = evalCase.expected_output;\n if (Array.isArray(expectedOutputField)) {\n await validateMessagesFileRefs(\n expectedOutputField,\n `tests[${i}].expected_output`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n }\n\n return errors;\n}\n\nasync function validateMessagesFileRefs(\n messages: JsonArray,\n location: string,\n searchRoots: readonly string[],\n filePath: string,\n errors: ValidationError[],\n): Promise<void> {\n for (let i = 0; i < messages.length; i++) {\n const message = messages[i];\n if (!isObject(message)) {\n continue;\n }\n\n const content = message.content;\n if (typeof content === 'string') {\n continue;\n }\n\n if (!Array.isArray(content)) {\n continue;\n }\n\n for (let j = 0; j < content.length; j++) {\n const contentItem = content[j];\n if (!isObject(contentItem)) {\n continue;\n }\n\n const type = contentItem.type;\n if (type !== 'file') {\n continue;\n }\n\n const value = contentItem.value;\n if (typeof value !== 'string') {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}].value`,\n message: \"File reference must have a 'value' field with the file path\",\n });\n continue;\n }\n\n // Use the same file resolution logic as yaml-parser at runtime\n const { resolvedPath } = await resolveFileReference(value, searchRoots);\n\n if (!resolvedPath) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file not found: ${value}`,\n });\n } else {\n // Check that file is not empty\n try {\n const fileContent = await readFile(resolvedPath, 'utf8');\n if (fileContent.trim().length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Referenced file is empty: ${value}`,\n });\n }\n } catch (error) {\n errors.push({\n severity: 'error',\n filePath,\n location: `${location}[${i}].content[${j}]`,\n message: `Cannot read referenced file: ${value} (${(error as Error).message})`,\n });\n }\n }\n }\n }\n}\n"],"mappings":"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","names":["readFile","path","parse","path","readFile","parse","readFile","path","parse","isObject","path","readFile","parse","absolutePath","errors","readFile","parse","readFile","path","parse","isObject","path","readFile","parse"]}
|
package/dist/index.cjs
CHANGED
|
@@ -17838,7 +17838,7 @@ async function runEvaluation(options) {
|
|
|
17838
17838
|
setupLog(
|
|
17839
17839
|
`sharedWorkspace=${hasSharedWorkspace} perTestIsolation=${isPerTestIsolation} usePool=${usePool} workers=${workers}`
|
|
17840
17840
|
);
|
|
17841
|
-
if (hasSharedWorkspace && !usePool && workers > 1) {
|
|
17841
|
+
if (hasSharedWorkspace && !usePool && workers > 1 && filteredEvalCases.length > 1) {
|
|
17842
17842
|
console.warn(
|
|
17843
17843
|
[
|
|
17844
17844
|
`Warning: This eval uses a shared workspace with ${workers} workers.`,
|