@agentv/core 0.22.1 → 0.23.0
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.map +1 -1
- package/dist/evaluation/validation/index.js.map +1 -1
- package/dist/index.cjs +595 -252
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -22
- package/dist/index.d.ts +61 -22
- package/dist/index.js +594 -251
- package/dist/index.js.map +1 -1
- package/package.json +4 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/evaluation/validation/index.ts","../../../src/evaluation/validation/file-type.ts","../../../src/evaluation/validation/eval-validator.ts","../../../src/evaluation/validation/targets-validator.ts","../../../src/evaluation/providers/targets.ts","../../../src/evaluation/providers/types.ts","../../../src/evaluation/validation/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts","../../../src/evaluation/file-utils.ts"],"sourcesContent":["/**\n * Validation module for AgentV eval and targets files.\n */\n\nexport { detectFileType, isValidSchema, getExpectedSchema } from './file-type.js';\nexport { validateEvalFile } from './eval-validator.js';\nexport { validateTargetsFile } from './targets-validator.js';\nexport { validateConfigFile } from './config-validator.js';\nexport { validateFileReferences } from './file-reference-validator.js';\nexport type {\n FileType,\n ValidationSeverity,\n ValidationError,\n ValidationResult,\n ValidationSummary,\n} from './types.js';\n","import { readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\nimport { parse } from 'yaml';\r\n\r\nimport type { FileType } from './types.js';\r\n\r\nconst SCHEMA_EVAL_V2 = 'agentv-eval-v2';\r\nconst SCHEMA_TARGETS_V2 = 'agentv-targets-v2.2';\r\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\r\n\r\n/**\r\n * Detect file type by reading $schema field from YAML file.\r\n * If $schema is missing, infers type from filename/path:\r\n * - config.yaml under .agentv folder → 'config'\r\n * - targets.yaml under .agentv folder → 'targets'\r\n * - All other YAML files → 'eval' (default)\r\n */\r\nexport async function detectFileType(filePath: string): Promise<FileType> {\r\n try {\r\n const content = await readFile(filePath, 'utf8');\r\n const parsed = parse(content) as unknown;\r\n\r\n if (typeof parsed !== 'object' || parsed === null) {\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n const schema = record.$schema;\r\n\r\n if (typeof schema !== 'string') {\r\n // No $schema field - infer from path\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n\r\n switch (schema) {\r\n case SCHEMA_EVAL_V2:\r\n return 'eval';\r\n case SCHEMA_TARGETS_V2:\r\n return 'targets';\r\n case SCHEMA_CONFIG_V2:\r\n return 'config';\r\n default:\r\n // Unknown schema - infer from path\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n } catch {\r\n return inferFileTypeFromPath(filePath);\r\n }\r\n}\r\n\r\n/**\r\n * Infer file type from filename and directory path.\r\n */\r\nfunction inferFileTypeFromPath(filePath: string): FileType {\r\n const normalized = path.normalize(filePath).replace(/\\\\/g, '/');\r\n const basename = path.basename(filePath);\r\n\r\n // Check if file is under .agentv folder\r\n if (normalized.includes('/.agentv/')) {\r\n if (basename === 'config.yaml' || basename === 'config.yml') {\r\n return 'config';\r\n }\r\n if (basename === 'targets.yaml' || basename === 'targets.yml') {\r\n return 'targets';\r\n }\r\n }\r\n\r\n // Default to eval file\r\n return 'eval';\r\n}\r\n\r\n/**\r\n * Check if a schema value is a valid AgentV schema identifier.\r\n */\r\nexport function isValidSchema(schema: unknown): boolean {\r\n return schema === SCHEMA_EVAL_V2 || schema === SCHEMA_TARGETS_V2 || schema === SCHEMA_CONFIG_V2;\r\n}\r\n\r\n/**\r\n * Get the expected schema for a file type.\r\n */\r\nexport function getExpectedSchema(fileType: FileType): string | undefined {\r\n switch (fileType) {\r\n case 'eval':\r\n return SCHEMA_EVAL_V2;\r\n case 'targets':\r\n return SCHEMA_TARGETS_V2;\r\n case 'config':\r\n return SCHEMA_CONFIG_V2;\r\n default:\r\n return undefined;\r\n }\r\n}\r\n","import { readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { parse } from 'yaml';\n\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/**\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 = 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: '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 evalcases array\n const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'evalcases',\n message: \"Missing or invalid 'evalcases' field (must be an array)\",\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 < evalcases.length; i++) {\n const evalCase = evalcases[i];\n const location = `evalcases[${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_messages, expected_messages\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: expected_outcome or outcome for backward compatibility\n const expectedOutcome = evalCase.expected_outcome ?? evalCase.outcome;\n if (\n expectedOutcome !== undefined &&\n (typeof expectedOutcome !== 'string' || expectedOutcome.trim().length === 0)\n ) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_outcome`,\n message:\n \"Invalid 'expected_outcome' or 'outcome' field (must be a non-empty string if provided)\",\n });\n }\n\n const inputMessages = evalCase.input_messages;\n if (!Array.isArray(inputMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input_messages`,\n message: \"Missing or invalid 'input_messages' field (must be an array)\",\n });\n } else {\n validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);\n }\n\n // expected_messages is optional - for outcome-only evaluation\n const expectedMessages = evalCase.expected_messages;\n if (expectedMessages !== undefined && !Array.isArray(expectedMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_messages`,\n message: \"Invalid 'expected_messages' field (must be an array if provided)\",\n });\n } else if (Array.isArray(expectedMessages)) {\n validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);\n }\n }\n\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\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 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, TARGETS_SCHEMA_V2 } 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 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 '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]);\n\nconst VSCODE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'workspace_template',\n 'workspaceTemplate',\n 'vscode_cmd',\n 'command',\n 'wait',\n 'dry_run',\n 'dryRun',\n 'subagent_root',\n 'subagentRoot',\n]);\n\nconst MOCK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'response',\n 'delayMs',\n 'delayMinMs',\n 'delayMaxMs',\n]);\n\nconst CLI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'command_template',\n 'commandTemplate',\n 'files_format',\n 'filesFormat',\n 'attachments_format',\n 'attachmentsFormat',\n 'cwd',\n 'env',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'healthcheck',\n]);\n\nfunction getKnownSettings(provider: string): Set<string> | null {\n const normalizedProvider = provider.toLowerCase();\n switch (normalizedProvider) {\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 'vscode':\n case 'vscode-insiders':\n return VSCODE_SETTINGS;\n case 'mock':\n return MOCK_SETTINGS;\n case 'cli':\n return CLI_SETTINGS;\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 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(['name', 'provider', 'judge_target', 'workers', '$schema', 'targets']);\n\n for (const key of Object.keys(target)) {\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 function validateCliSettings(\n target: JsonObject,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const commandTemplate = target.command_template ?? target.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: \"CLI provider requires 'commandTemplate' as a non-empty string\",\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\n }\n\n const attachmentsFormat = target.attachments_format ?? target.attachmentsFormat;\n if (attachmentsFormat !== undefined && typeof attachmentsFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.attachmentsFormat`,\n message: \"'attachmentsFormat' must be a string when provided\",\n });\n }\n\n const filesFormat = target.files_format ?? target.filesFormat;\n if (filesFormat !== undefined && typeof filesFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.filesFormat`,\n message: \"'filesFormat' must be a string when provided\",\n });\n }\n\n const cwd = target.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: \"'cwd' must be a string when provided\",\n });\n }\n\n const timeoutSeconds = target.timeout_seconds ?? target.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: \"'timeoutSeconds' must be a positive number when provided\",\n });\n }\n }\n\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 type = healthcheck.type;\n if (type !== 'http' && type !== 'command') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.type`,\n message: \"healthcheck.type must be either 'http' or 'command'\",\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 if (type === 'http') {\n const url = healthcheck.url;\n if (typeof url !== 'string' || url.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.url`,\n message: 'healthcheck.url must be a non-empty string for http checks',\n });\n }\n return;\n }\n\n const commandTemplate = healthcheck.command_template ?? healthcheck.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: 'healthcheck.commandTemplate must be a non-empty string for command checks',\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\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 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 (!knownProviders.includes(provider)) {\n // Warning for unknown providers (non-fatal)\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') {\n validateUnknownSettings(target, provider, absolutePath, location, errors);\n }\n\n // Optional field: judge_target (must be string if present)\n const judgeTarget = target.judge_target;\n if (judgeTarget !== undefined && typeof judgeTarget !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.judge_target`,\n message: \"Invalid 'judge_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 { z } from 'zod';\n\nimport type { EnvLookup, TargetDefinition } from './types.js';\n\nexport const CLI_PLACEHOLDERS = new Set([\n 'PROMPT',\n 'GUIDELINES',\n 'EVAL_ID',\n 'ATTEMPT',\n 'FILES',\n 'OUTPUT_FILE',\n]);\n\nexport interface RetryConfig {\n readonly maxRetries?: number;\n readonly initialDelayMs?: number;\n readonly maxDelayMs?: number;\n readonly backoffFactor?: number;\n readonly retryableStatusCodes?: readonly number[];\n}\n\n/**\n * Azure OpenAI settings used by the Vercel AI SDK.\n */\nexport interface AzureResolvedConfig {\n readonly resourceName: string;\n readonly deploymentName: string;\n readonly apiKey: string;\n readonly version?: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly retry?: RetryConfig;\n}\n\n/**\n * Anthropic Claude settings used by the Vercel AI SDK.\n */\nexport interface AnthropicResolvedConfig {\n readonly apiKey: string;\n readonly model: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly thinkingBudget?: number;\n readonly retry?: RetryConfig;\n}\n\n/**\n * Google Gemini settings used by the Vercel AI SDK.\n */\nexport interface GeminiResolvedConfig {\n readonly apiKey: string;\n readonly model: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly retry?: RetryConfig;\n}\n\nexport interface CodexResolvedConfig {\n readonly executable: string;\n readonly args?: readonly string[];\n readonly cwd?: string;\n readonly timeoutMs?: number;\n readonly logDir?: string;\n readonly logFormat?: 'summary' | 'json';\n}\n\nexport interface MockResolvedConfig {\n readonly response?: string;\n readonly delayMs?: number;\n readonly delayMinMs?: number;\n readonly delayMaxMs?: number;\n}\n\nexport interface VSCodeResolvedConfig {\n readonly command: string;\n readonly waitForResponse: boolean;\n readonly dryRun: boolean;\n readonly subagentRoot?: string;\n readonly workspaceTemplate?: string;\n}\n\nexport type CliHealthcheck =\n | {\n readonly type: 'http';\n readonly url: string;\n readonly timeoutMs?: number;\n }\n | {\n readonly type: 'command';\n readonly commandTemplate: string;\n readonly timeoutMs?: number;\n readonly cwd?: string;\n };\n\nexport interface CliResolvedConfig {\n readonly commandTemplate: string;\n readonly filesFormat?: string;\n readonly cwd?: string;\n readonly timeoutMs?: number;\n readonly healthcheck?: CliHealthcheck;\n readonly verbose?: boolean;\n}\n\nexport type ResolvedTarget =\n | {\n readonly kind: 'azure';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: AzureResolvedConfig;\n }\n | {\n readonly kind: 'anthropic';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: AnthropicResolvedConfig;\n }\n | {\n readonly kind: 'gemini';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: GeminiResolvedConfig;\n }\n | {\n readonly kind: 'codex';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: CodexResolvedConfig;\n }\n | {\n readonly kind: 'mock';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: MockResolvedConfig;\n }\n | {\n readonly kind: 'vscode' | 'vscode-insiders';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: VSCodeResolvedConfig;\n }\n | {\n readonly kind: 'cli';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: CliResolvedConfig;\n };\n\nconst BASE_TARGET_SCHEMA = z\n .object({\n name: z.string().min(1, 'target name is required'),\n provider: z.string().min(1, 'provider is required'),\n judge_target: z.string().optional(),\n workers: z.number().int().min(1).optional(),\n })\n .passthrough();\n\nconst DEFAULT_AZURE_API_VERSION = '2024-10-01-preview';\n\nfunction normalizeAzureApiVersion(value: string | undefined): string {\n if (!value) {\n return DEFAULT_AZURE_API_VERSION;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return DEFAULT_AZURE_API_VERSION;\n }\n\n const withoutPrefix = trimmed.replace(/^api[-_]?version\\s*=\\s*/i, '').trim();\n return withoutPrefix.length > 0 ? withoutPrefix : DEFAULT_AZURE_API_VERSION;\n}\n\nfunction resolveRetryConfig(target: z.infer<typeof BASE_TARGET_SCHEMA>): RetryConfig | undefined {\n const maxRetries = resolveOptionalNumber(\n target.max_retries ?? target.maxRetries,\n `${target.name} max retries`,\n );\n const initialDelayMs = resolveOptionalNumber(\n target.retry_initial_delay_ms ?? target.retryInitialDelayMs,\n `${target.name} retry initial delay`,\n );\n const maxDelayMs = resolveOptionalNumber(\n target.retry_max_delay_ms ?? target.retryMaxDelayMs,\n `${target.name} retry max delay`,\n );\n const backoffFactor = resolveOptionalNumber(\n target.retry_backoff_factor ?? target.retryBackoffFactor,\n `${target.name} retry backoff factor`,\n );\n const retryableStatusCodes = resolveOptionalNumberArray(\n target.retry_status_codes ?? target.retryStatusCodes,\n `${target.name} retry status codes`,\n );\n\n // Only return retry config if at least one field is set\n if (\n maxRetries === undefined &&\n initialDelayMs === undefined &&\n maxDelayMs === undefined &&\n backoffFactor === undefined &&\n retryableStatusCodes === undefined\n ) {\n return undefined;\n }\n\n return {\n maxRetries,\n initialDelayMs,\n maxDelayMs,\n backoffFactor,\n retryableStatusCodes,\n };\n}\n\nexport function resolveTargetDefinition(\n definition: TargetDefinition,\n env: EnvLookup = process.env,\n): ResolvedTarget {\n const parsed = BASE_TARGET_SCHEMA.parse(definition);\n const provider = parsed.provider.toLowerCase();\n const providerBatching = resolveOptionalBoolean(\n parsed.provider_batching ?? parsed.providerBatching,\n );\n\n switch (provider) {\n case 'azure':\n case 'azure-openai':\n return {\n kind: 'azure',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveAzureConfig(parsed, env),\n };\n case 'anthropic':\n return {\n kind: 'anthropic',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveAnthropicConfig(parsed, env),\n };\n case 'gemini':\n case 'google':\n case 'google-gemini':\n return {\n kind: 'gemini',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveGeminiConfig(parsed, env),\n };\n case 'codex':\n case 'codex-cli':\n return {\n kind: 'codex',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveCodexConfig(parsed, env),\n };\n case 'mock':\n return {\n kind: 'mock',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveMockConfig(parsed),\n };\n case 'vscode':\n case 'vscode-insiders':\n return {\n kind: provider as 'vscode' | 'vscode-insiders',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveVSCodeConfig(parsed, env, provider === 'vscode-insiders'),\n };\n case 'cli':\n return {\n kind: 'cli',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveCliConfig(parsed, env),\n };\n default:\n throw new Error(`Unsupported provider '${parsed.provider}' in target '${parsed.name}'`);\n }\n}\n\nfunction resolveAzureConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): AzureResolvedConfig {\n const endpointSource = target.endpoint ?? target.resource ?? target.resourceName;\n const apiKeySource = target.api_key ?? target.apiKey;\n const deploymentSource = target.deployment ?? target.deploymentName ?? target.model;\n const versionSource = target.version ?? target.api_version;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n\n const resourceName = resolveString(endpointSource, env, `${target.name} endpoint`);\n const apiKey = resolveString(apiKeySource, env, `${target.name} api key`);\n const deploymentName = resolveString(deploymentSource, env, `${target.name} deployment`);\n const version = normalizeAzureApiVersion(\n resolveOptionalString(versionSource, env, `${target.name} api version`),\n );\n const temperature = resolveOptionalNumber(temperatureSource, `${target.name} temperature`);\n const maxOutputTokens = resolveOptionalNumber(\n maxTokensSource,\n `${target.name} max output tokens`,\n );\n const retry = resolveRetryConfig(target);\n\n return {\n resourceName,\n deploymentName,\n apiKey,\n version,\n temperature,\n maxOutputTokens,\n retry,\n };\n}\n\nfunction resolveAnthropicConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): AnthropicResolvedConfig {\n const apiKeySource = target.api_key ?? target.apiKey;\n const modelSource = target.model ?? target.deployment ?? target.variant;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n const thinkingBudgetSource = target.thinking_budget ?? target.thinkingBudget;\n\n const apiKey = resolveString(apiKeySource, env, `${target.name} Anthropic api key`);\n const model = resolveString(modelSource, env, `${target.name} Anthropic model`);\n const retry = resolveRetryConfig(target);\n\n return {\n apiKey,\n model,\n temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),\n maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),\n thinkingBudget: resolveOptionalNumber(thinkingBudgetSource, `${target.name} thinking budget`),\n retry,\n };\n}\n\nfunction resolveGeminiConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): GeminiResolvedConfig {\n const apiKeySource = target.api_key ?? target.apiKey;\n const modelSource = target.model ?? target.deployment ?? target.variant;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n\n const apiKey = resolveString(apiKeySource, env, `${target.name} Google API key`);\n const model =\n resolveOptionalString(modelSource, env, `${target.name} Gemini model`, {\n allowLiteral: true,\n optionalEnv: true,\n }) ?? 'gemini-2.5-flash';\n const retry = resolveRetryConfig(target);\n\n return {\n apiKey,\n model,\n temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),\n maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),\n retry,\n };\n}\n\nfunction resolveCodexConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): CodexResolvedConfig {\n const executableSource = target.executable ?? target.command ?? target.binary;\n const argsSource = target.args ?? target.arguments;\n const cwdSource = target.cwd;\n const timeoutSource = target.timeout_seconds ?? target.timeoutSeconds;\n const logDirSource =\n target.log_dir ?? target.logDir ?? target.log_directory ?? target.logDirectory;\n const logFormatSource =\n target.log_format ??\n target.logFormat ??\n target.log_output_format ??\n target.logOutputFormat ??\n env.AGENTV_CODEX_LOG_FORMAT;\n\n const executable =\n resolveOptionalString(executableSource, env, `${target.name} codex executable`, {\n allowLiteral: true,\n optionalEnv: true,\n }) ?? 'codex';\n\n const args = resolveOptionalStringArray(argsSource, env, `${target.name} codex args`);\n\n const cwd = resolveOptionalString(cwdSource, env, `${target.name} codex cwd`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const timeoutMs = resolveTimeoutMs(timeoutSource, `${target.name} codex timeout`);\n const logDir = resolveOptionalString(logDirSource, env, `${target.name} codex log directory`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const logFormat = normalizeCodexLogFormat(logFormatSource);\n\n return {\n executable,\n args,\n cwd,\n timeoutMs,\n logDir,\n logFormat,\n };\n}\n\nfunction normalizeCodexLogFormat(value: unknown): 'summary' | 'json' | undefined {\n if (value === undefined || value === null) {\n return undefined;\n }\n if (typeof value !== 'string') {\n throw new Error(\"codex log format must be 'summary' or 'json'\");\n }\n const normalized = value.trim().toLowerCase();\n if (normalized === 'json' || normalized === 'summary') {\n return normalized;\n }\n throw new Error(\"codex log format must be 'summary' or 'json'\");\n}\n\nfunction resolveMockConfig(target: z.infer<typeof BASE_TARGET_SCHEMA>): MockResolvedConfig {\n const response = typeof target.response === 'string' ? target.response : undefined;\n return { response };\n}\n\nfunction resolveVSCodeConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n insiders: boolean,\n): VSCodeResolvedConfig {\n const workspaceTemplateEnvVar = resolveOptionalLiteralString(\n target.workspace_template ?? target.workspaceTemplate,\n );\n const workspaceTemplate = workspaceTemplateEnvVar\n ? resolveOptionalString(\n workspaceTemplateEnvVar,\n env,\n `${target.name} workspace template path`,\n {\n allowLiteral: false,\n optionalEnv: true,\n },\n )\n : undefined;\n\n const commandSource = target.vscode_cmd ?? target.command;\n const waitSource = target.wait;\n const dryRunSource = target.dry_run ?? target.dryRun;\n const subagentRootSource = target.subagent_root ?? target.subagentRoot;\n\n const defaultCommand = insiders ? 'code-insiders' : 'code';\n const command = resolveOptionalLiteralString(commandSource) ?? defaultCommand;\n\n return {\n command,\n waitForResponse: resolveOptionalBoolean(waitSource) ?? true,\n dryRun: resolveOptionalBoolean(dryRunSource) ?? false,\n subagentRoot: resolveOptionalString(subagentRootSource, env, `${target.name} subagent root`, {\n allowLiteral: true,\n optionalEnv: true,\n }),\n workspaceTemplate,\n };\n}\n\nfunction resolveCliConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): CliResolvedConfig {\n const commandTemplateSource = target.command_template ?? target.commandTemplate;\n const filesFormat = resolveOptionalLiteralString(\n target.files_format ??\n target.filesFormat ??\n target.attachments_format ??\n target.attachmentsFormat,\n );\n const cwd = resolveOptionalString(target.cwd, env, `${target.name} working directory`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const timeoutMs = resolveTimeoutMs(\n target.timeout_seconds ?? target.timeoutSeconds,\n `${target.name} timeout`,\n );\n const healthcheck = resolveCliHealthcheck(target.healthcheck, env, target.name);\n\n const commandTemplate = resolveString(\n commandTemplateSource,\n env,\n `${target.name} CLI command template`,\n true,\n );\n assertSupportedCliPlaceholders(commandTemplate, `${target.name} CLI command template`);\n\n return {\n commandTemplate,\n filesFormat,\n cwd,\n timeoutMs,\n healthcheck,\n };\n}\n\nfunction resolveTimeoutMs(source: unknown, description: string): number | undefined {\n const seconds = resolveOptionalNumber(source, `${description} (seconds)`);\n if (seconds === undefined) {\n return undefined;\n }\n if (seconds <= 0) {\n throw new Error(`${description} must be greater than zero seconds`);\n }\n return Math.floor(seconds * 1000);\n}\n\nfunction resolveCliHealthcheck(\n source: unknown,\n env: EnvLookup,\n targetName: string,\n): CliHealthcheck | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'object' || Array.isArray(source)) {\n throw new Error(`${targetName} healthcheck must be an object`);\n }\n\n const candidate = source as Record<string, unknown>;\n const type = candidate.type;\n const timeoutMs = resolveTimeoutMs(\n candidate.timeout_seconds ?? candidate.timeoutSeconds,\n `${targetName} healthcheck timeout`,\n );\n\n if (type === 'http') {\n const url = resolveString(candidate.url, env, `${targetName} healthcheck URL`);\n return {\n type: 'http',\n url,\n timeoutMs,\n };\n }\n\n if (type === 'command') {\n const commandTemplate = resolveString(\n candidate.command_template ?? candidate.commandTemplate,\n env,\n `${targetName} healthcheck command template`,\n true,\n );\n assertSupportedCliPlaceholders(commandTemplate, `${targetName} healthcheck command template`);\n const cwd = resolveOptionalString(candidate.cwd, env, `${targetName} healthcheck cwd`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n return {\n type: 'command',\n commandTemplate,\n timeoutMs,\n cwd,\n };\n }\n\n throw new Error(`${targetName} healthcheck type must be 'http' or 'command'`);\n}\n\nfunction assertSupportedCliPlaceholders(template: string, description: string): void {\n const placeholders = extractCliPlaceholders(template);\n for (const placeholder of placeholders) {\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\n throw new Error(\n `${description} includes unsupported placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\n );\n }\n }\n}\n\nfunction extractCliPlaceholders(template: string): string[] {\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\n const results: string[] = [];\n for (const match of matches) {\n if (match[1]) {\n results.push(match[1]);\n }\n }\n return results;\n}\n\nfunction resolveString(\n source: unknown,\n env: EnvLookup,\n description: string,\n allowLiteral = false,\n): string {\n const value = resolveOptionalString(source, env, description, {\n allowLiteral,\n optionalEnv: false,\n });\n if (value === undefined) {\n throw new Error(`${description} is required`);\n }\n return value;\n}\n\nfunction resolveOptionalString(\n source: unknown,\n env: EnvLookup,\n description: string,\n options?: { allowLiteral?: boolean; optionalEnv?: boolean },\n): string | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'string') {\n throw new Error(`${description} must be a string`);\n }\n const trimmed = source.trim();\n if (trimmed.length === 0) {\n return undefined;\n }\n\n // Check for ${{ variable }} syntax\n const envVarMatch = trimmed.match(/^\\$\\{\\{\\s*([A-Z0-9_]+)\\s*\\}\\}$/i);\n if (envVarMatch) {\n const varName = envVarMatch[1];\n const envValue = env[varName];\n if (envValue !== undefined) {\n if (envValue.trim().length === 0) {\n throw new Error(`Environment variable '${varName}' for ${description} is empty`);\n }\n return envValue;\n }\n const optionalEnv = options?.optionalEnv ?? false;\n if (optionalEnv) {\n return undefined;\n }\n throw new Error(`Environment variable '${varName}' required for ${description} is not set`);\n }\n\n // Return as literal value\n const allowLiteral = options?.allowLiteral ?? false;\n if (!allowLiteral) {\n throw new Error(\n `${description} must use \\${{ VARIABLE_NAME }} syntax for environment variables or be marked as allowing literals`,\n );\n }\n return trimmed;\n}\n\nfunction resolveOptionalLiteralString(source: unknown): string | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'string') {\n throw new Error('expected string value');\n }\n const trimmed = source.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction resolveOptionalNumber(source: unknown, description: string): number | undefined {\n if (source === undefined || source === null || source === '') {\n return undefined;\n }\n if (typeof source === 'number') {\n return Number.isFinite(source) ? source : undefined;\n }\n if (typeof source === 'string') {\n const numeric = Number(source);\n if (Number.isFinite(numeric)) {\n return numeric;\n }\n }\n throw new Error(`${description} must be a number`);\n}\n\nfunction resolveOptionalBoolean(source: unknown): boolean | undefined {\n if (source === undefined || source === null || source === '') {\n return undefined;\n }\n if (typeof source === 'boolean') {\n return source;\n }\n if (typeof source === 'string') {\n const lowered = source.trim().toLowerCase();\n if (lowered === 'true' || lowered === '1') {\n return true;\n }\n if (lowered === 'false' || lowered === '0') {\n return false;\n }\n }\n throw new Error('expected boolean value');\n}\n\nfunction resolveOptionalStringArray(\n source: unknown,\n env: EnvLookup,\n description: string,\n): readonly string[] | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (!Array.isArray(source)) {\n throw new Error(`${description} must be an array of strings`);\n }\n if (source.length === 0) {\n return undefined;\n }\n const resolved: string[] = [];\n for (let i = 0; i < source.length; i++) {\n const item = source[i];\n if (typeof item !== 'string') {\n throw new Error(`${description}[${i}] must be a string`);\n }\n const trimmed = item.trim();\n if (trimmed.length === 0) {\n throw new Error(`${description}[${i}] cannot be empty`);\n }\n\n // Check for ${{ variable }} syntax\n const envVarMatch = trimmed.match(/^\\$\\{\\{\\s*([A-Z0-9_]+)\\s*\\}\\}$/i);\n if (envVarMatch) {\n const varName = envVarMatch[1];\n const envValue = env[varName];\n if (envValue !== undefined) {\n if (envValue.trim().length === 0) {\n throw new Error(`Environment variable '${varName}' for ${description}[${i}] is empty`);\n }\n resolved.push(envValue);\n continue;\n }\n throw new Error(`Environment variable '${varName}' for ${description}[${i}] is not set`);\n }\n\n // Treat as literal value\n resolved.push(trimmed);\n }\n return resolved.length > 0 ? resolved : undefined;\n}\n\nfunction resolveOptionalNumberArray(\n source: unknown,\n description: string,\n): readonly number[] | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (!Array.isArray(source)) {\n throw new Error(`${description} must be an array of numbers`);\n }\n if (source.length === 0) {\n return undefined;\n }\n const resolved: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const item = source[i];\n if (typeof item !== 'number' || !Number.isFinite(item)) {\n throw new Error(`${description}[${i}] must be a number`);\n }\n resolved.push(item);\n }\n return resolved.length > 0 ? resolved : undefined;\n}\n","import type { JsonObject } from '../types.js';\n\nexport type ChatMessageRole = 'system' | 'user' | 'assistant' | 'tool' | 'function';\n\nexport interface ChatMessage {\n readonly role: ChatMessageRole;\n readonly content: string;\n readonly name?: string;\n}\n\nexport type ChatPrompt = readonly ChatMessage[];\n\nexport type ProviderKind =\n | 'azure'\n | 'anthropic'\n | 'gemini'\n | 'codex'\n | 'cli'\n | 'mock'\n | 'vscode'\n | 'vscode-insiders';\n\n/**\n * Agent providers that have filesystem access and don't need unwrapped guidelines.\n * These providers read files directly from the filesystem using file:// URIs.\n */\nexport const AGENT_PROVIDER_KINDS: readonly ProviderKind[] = [\n 'codex',\n 'vscode',\n 'vscode-insiders',\n] as const;\n\n/**\n * List of all supported provider kinds.\n * This is the source of truth for provider validation.\n */\nexport const KNOWN_PROVIDERS: readonly ProviderKind[] = [\n 'azure',\n 'anthropic',\n 'gemini',\n 'codex',\n 'cli',\n 'mock',\n 'vscode',\n 'vscode-insiders',\n] as const;\n\n/**\n * Provider aliases that are accepted in target definitions.\n * These map to the canonical ProviderKind values.\n */\nexport const PROVIDER_ALIASES: readonly string[] = [\n 'azure-openai', // alias for \"azure\"\n 'google', // alias for \"gemini\"\n 'google-gemini', // alias for \"gemini\"\n 'codex-cli', // alias for \"codex\"\n 'openai', // legacy/future support\n 'bedrock', // legacy/future support\n 'vertex', // legacy/future support\n] as const;\n\n/**\n * Schema identifier for targets.yaml files (version 2).\n */\nexport const TARGETS_SCHEMA_V2 = 'agentv-targets-v2.2';\n\nexport interface ProviderRequest {\n readonly question: string;\n readonly systemPrompt?: string;\n readonly guidelines?: string;\n readonly guideline_patterns?: readonly string[];\n readonly chatPrompt?: ChatPrompt;\n readonly inputFiles?: readonly string[];\n readonly evalCaseId?: string;\n readonly attempt?: number;\n readonly maxOutputTokens?: number;\n readonly temperature?: number;\n readonly metadata?: JsonObject;\n readonly signal?: AbortSignal;\n}\n\nexport interface ProviderResponse {\n readonly text: string;\n readonly reasoning?: string;\n readonly raw?: unknown;\n readonly usage?: JsonObject;\n}\n\n/**\n * Type guard to check if a provider is an agent provider with filesystem access.\n * Agent providers read files directly and don't need unwrapped guideline content.\n */\nexport function isAgentProvider(provider: Provider | undefined): boolean {\n return provider ? AGENT_PROVIDER_KINDS.includes(provider.kind) : false;\n}\n\nexport interface Provider {\n readonly id: string;\n readonly kind: ProviderKind;\n readonly targetName: string;\n invoke(request: ProviderRequest): Promise<ProviderResponse>;\n /**\n * Optional capability marker for provider-managed batching (single session handling multiple requests).\n */\n readonly supportsBatch?: boolean;\n /**\n * Optional batch invocation hook. When defined alongside supportsBatch=true,\n * the orchestrator may send multiple requests in a single provider session.\n */\n invokeBatch?(requests: readonly ProviderRequest[]): Promise<readonly ProviderResponse[]>;\n /**\n * Optional method to get a Vercel AI SDK LanguageModel instance for structured output generation.\n * Used by evaluators that need generateObject/generateText from the AI SDK.\n */\n asLanguageModel?(): import('ai').LanguageModel;\n}\n\nexport type EnvLookup = Readonly<Record<string, string | undefined>>;\n\nexport interface TargetDefinition {\n readonly name: string;\n readonly provider: ProviderKind | string;\n readonly judge_target?: string | undefined;\n readonly workers?: number | undefined;\n // Provider batching\n readonly provider_batching?: boolean | undefined;\n readonly providerBatching?: boolean | undefined;\n // Azure fields\n readonly endpoint?: string | unknown | undefined;\n readonly resource?: string | unknown | undefined;\n readonly resourceName?: string | unknown | undefined;\n readonly api_key?: string | unknown | undefined;\n readonly apiKey?: string | unknown | undefined;\n readonly deployment?: string | unknown | undefined;\n readonly deploymentName?: string | unknown | undefined;\n readonly model?: string | unknown | undefined;\n readonly version?: string | unknown | undefined;\n readonly api_version?: string | unknown | undefined;\n // Anthropic fields\n readonly variant?: string | unknown | undefined;\n readonly thinking_budget?: number | unknown | undefined;\n readonly thinkingBudget?: number | unknown | undefined;\n // Common fields\n readonly temperature?: number | unknown | undefined;\n readonly max_output_tokens?: number | unknown | undefined;\n readonly maxTokens?: number | unknown | undefined;\n // Codex fields\n readonly executable?: string | unknown | undefined;\n readonly command?: string | unknown | undefined;\n readonly binary?: string | unknown | undefined;\n readonly args?: unknown | undefined;\n readonly arguments?: unknown | undefined;\n readonly cwd?: string | unknown | undefined;\n readonly timeout_seconds?: number | unknown | undefined;\n readonly timeoutSeconds?: number | unknown | undefined;\n readonly log_dir?: string | unknown | undefined;\n readonly logDir?: string | unknown | undefined;\n readonly log_directory?: string | unknown | undefined;\n readonly logDirectory?: string | unknown | undefined;\n readonly log_format?: string | unknown | undefined;\n readonly logFormat?: string | unknown | undefined;\n readonly log_output_format?: string | unknown | undefined;\n readonly logOutputFormat?: string | unknown | undefined;\n // Mock fields\n readonly response?: string | unknown | undefined;\n readonly delayMs?: number | unknown | undefined;\n readonly delayMinMs?: number | unknown | undefined;\n readonly delayMaxMs?: number | unknown | undefined;\n // VSCode fields\n readonly vscode_cmd?: string | unknown | undefined;\n readonly wait?: boolean | unknown | undefined;\n readonly dry_run?: boolean | unknown | undefined;\n readonly dryRun?: boolean | unknown | undefined;\n readonly subagent_root?: string | unknown | undefined;\n readonly subagentRoot?: string | unknown | undefined;\n readonly workspace_template?: string | unknown | undefined;\n readonly workspaceTemplate?: string | unknown | undefined;\n // CLI fields\n readonly command_template?: string | unknown | undefined;\n readonly commandTemplate?: string | unknown | undefined;\n readonly files_format?: string | unknown | undefined;\n readonly filesFormat?: string | unknown | undefined;\n readonly attachments_format?: string | unknown | undefined;\n readonly attachmentsFormat?: string | unknown | undefined;\n readonly env?: unknown | undefined;\n readonly healthcheck?: unknown | undefined;\n // Retry configuration fields\n readonly max_retries?: number | unknown | undefined;\n readonly maxRetries?: number | unknown | undefined;\n readonly retry_initial_delay_ms?: number | unknown | undefined;\n readonly retryInitialDelayMs?: number | unknown | undefined;\n readonly retry_max_delay_ms?: number | unknown | undefined;\n readonly retryMaxDelayMs?: number | unknown | undefined;\n readonly retry_backoff_factor?: number | unknown | undefined;\n readonly retryBackoffFactor?: number | unknown | undefined;\n readonly retry_status_codes?: unknown | undefined;\n readonly retryStatusCodes?: unknown | undefined;\n}\n","import { readFile } from 'node:fs/promises';\r\nimport { parse } from 'yaml';\r\n\r\nimport type { ValidationError, ValidationResult } from './types.js';\r\n\r\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\r\n\r\n/**\r\n * Validate a config.yaml file for schema compliance and structural correctness.\r\n */\r\nexport async function validateConfigFile(filePath: string): Promise<ValidationResult> {\r\n const errors: ValidationError[] = [];\r\n\r\n try {\r\n const content = await readFile(filePath, 'utf8');\r\n const parsed = parse(content) as unknown;\r\n\r\n // Check if parsed content is an object\r\n if (typeof parsed !== 'object' || parsed === null) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n message: 'Config file must contain a valid YAML object',\r\n });\r\n return { valid: false, filePath, fileType: 'config', errors };\r\n }\r\n\r\n const config = parsed as Record<string, unknown>;\r\n\r\n // Validate $schema field (optional, but if present must be correct)\r\n const schema = config.$schema;\r\n if (schema !== undefined && schema !== SCHEMA_CONFIG_V2) {\r\n const message = `Invalid $schema value '${schema}'. Expected '${SCHEMA_CONFIG_V2}' or omit the field.`;\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: '$schema',\r\n message,\r\n });\r\n }\r\n\r\n // Validate guideline_patterns if present\r\n const guidelinePatterns = config.guideline_patterns;\r\n if (guidelinePatterns !== undefined) {\r\n if (!Array.isArray(guidelinePatterns)) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"Field 'guideline_patterns' must be an array\",\r\n });\r\n } else if (!guidelinePatterns.every((p) => typeof p === 'string')) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"All entries in 'guideline_patterns' must be strings\",\r\n });\r\n } else if (guidelinePatterns.length === 0) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath,\r\n location: 'guideline_patterns',\r\n message: \"Field 'guideline_patterns' is empty. Consider removing it or adding patterns.\",\r\n });\r\n }\r\n }\r\n\r\n // Check for unexpected fields\r\n const allowedFields = new Set(['$schema', 'guideline_patterns']);\r\n const unexpectedFields = Object.keys(config).filter((key) => !allowedFields.has(key));\r\n\r\n if (unexpectedFields.length > 0) {\r\n errors.push({\r\n severity: 'warning',\r\n filePath,\r\n message: `Unexpected fields: ${unexpectedFields.join(', ')}`,\r\n });\r\n }\r\n\r\n return {\r\n valid: errors.filter((e) => e.severity === 'error').length === 0,\r\n filePath,\r\n fileType: 'config',\r\n errors,\r\n };\r\n } catch (error) {\r\n errors.push({\r\n severity: 'error',\r\n filePath,\r\n message: `Failed to parse config file: ${(error as Error).message}`,\r\n });\r\n return { valid: false, filePath, fileType: 'config', errors };\r\n }\r\n}\r\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 const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n return errors;\n }\n\n for (let i = 0; i < evalcases.length; i++) {\n const evalCase = evalcases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input_messages\n const inputMessages = evalCase.input_messages;\n if (Array.isArray(inputMessages)) {\n await validateMessagesFileRefs(\n inputMessages,\n `evalcases[${i}].input_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_messages\n const expectedMessages = evalCase.expected_messages;\n if (Array.isArray(expectedMessages)) {\n await validateMessagesFileRefs(\n expectedMessages,\n `evalcases[${i}].expected_messages`,\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","import { constants } from 'node:fs';\nimport { access, readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Normalize line endings to LF (\\n).\n * This ensures consistent behavior across Windows (CRLF) and Unix (LF) systems.\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n');\n}\n\n/**\n * Read a text file and normalize line endings to LF (\\n).\n * This ensures consistent behavior across Windows (CRLF) and Unix (LF) systems.\n */\nexport async function readTextFile(filePath: string): Promise<string> {\n const content = await readFile(filePath, 'utf8');\n return normalizeLineEndings(content);\n}\n\n/**\n * Find git repository root by walking up the directory tree.\n */\nexport async function findGitRoot(startPath: string): Promise<string | null> {\n let currentDir = path.dirname(path.resolve(startPath));\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const gitPath = path.join(currentDir, '.git');\n if (await fileExists(gitPath)) {\n return currentDir;\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n break;\n }\n currentDir = parentDir;\n }\n\n return null;\n}\n\n/**\n * Build a chain of directories walking from a file's location up to repo root.\n * Used for discovering configuration files like targets.yaml or config.yaml.\n */\nexport function buildDirectoryChain(filePath: string, repoRoot: string): readonly string[] {\n const directories: string[] = [];\n const seen = new Set<string>();\n const boundary = path.resolve(repoRoot);\n let current: string | undefined = path.resolve(path.dirname(filePath));\n\n while (current !== undefined) {\n if (!seen.has(current)) {\n directories.push(current);\n seen.add(current);\n }\n if (current === boundary) {\n break;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n if (!seen.has(boundary)) {\n directories.push(boundary);\n }\n\n return directories;\n}\n\n/**\n * Build search roots for file resolution, matching yaml-parser behavior.\n * Searches from eval file directory up to repo root.\n */\nexport function buildSearchRoots(evalPath: string, repoRoot: string): readonly string[] {\n const uniqueRoots: string[] = [];\n const addRoot = (root: string): void => {\n const normalized = path.resolve(root);\n if (!uniqueRoots.includes(normalized)) {\n uniqueRoots.push(normalized);\n }\n };\n\n let currentDir = path.dirname(evalPath);\n let reachedBoundary = false;\n while (!reachedBoundary) {\n addRoot(currentDir);\n const parentDir = path.dirname(currentDir);\n if (currentDir === repoRoot || parentDir === currentDir) {\n reachedBoundary = true;\n } else {\n currentDir = parentDir;\n }\n }\n\n addRoot(repoRoot);\n addRoot(process.cwd());\n return uniqueRoots;\n}\n\n/**\n * Trim leading path separators for display.\n */\nfunction trimLeadingSeparators(value: string): string {\n const trimmed = value.replace(/^[/\\\\]+/, '');\n return trimmed.length > 0 ? trimmed : value;\n}\n\n/**\n * Resolve a file reference using search roots, matching yaml-parser behavior.\n */\nexport async function resolveFileReference(\n rawValue: string,\n searchRoots: readonly string[],\n): Promise<{\n readonly displayPath: string;\n readonly resolvedPath?: string;\n readonly attempted: readonly string[];\n}> {\n const displayPath = trimLeadingSeparators(rawValue);\n const potentialPaths: string[] = [];\n\n if (path.isAbsolute(rawValue)) {\n potentialPaths.push(path.normalize(rawValue));\n }\n\n for (const base of searchRoots) {\n potentialPaths.push(path.resolve(base, displayPath));\n }\n\n const attempted: string[] = [];\n const seen = new Set<string>();\n for (const candidate of potentialPaths) {\n const absoluteCandidate = path.resolve(candidate);\n if (seen.has(absoluteCandidate)) {\n continue;\n }\n seen.add(absoluteCandidate);\n attempted.push(absoluteCandidate);\n if (await fileExists(absoluteCandidate)) {\n return { displayPath, resolvedPath: absoluteCandidate, attempted };\n }\n }\n\n return { displayPath, attempted };\n}\n"],"mappings":"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","names":["path","import_promises","import_node_path","import_yaml","path","import_promises","import_node_path","import_yaml","isObject","path","absolutePath","errors","import_promises","import_yaml","SCHEMA_CONFIG_V2","import_promises","import_node_path","import_yaml","import_promises","import_node_path","path","path","isObject","path"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/evaluation/validation/index.ts","../../../src/evaluation/validation/file-type.ts","../../../src/evaluation/validation/eval-validator.ts","../../../src/evaluation/validation/targets-validator.ts","../../../src/evaluation/providers/targets.ts","../../../src/evaluation/providers/types.ts","../../../src/evaluation/validation/config-validator.ts","../../../src/evaluation/validation/file-reference-validator.ts","../../../src/evaluation/file-utils.ts"],"sourcesContent":["/**\n * Validation module for AgentV eval and targets files.\n */\n\nexport { detectFileType, isValidSchema, getExpectedSchema } from './file-type.js';\nexport { validateEvalFile } from './eval-validator.js';\nexport { validateTargetsFile } from './targets-validator.js';\nexport { validateConfigFile } from './config-validator.js';\nexport { validateFileReferences } from './file-reference-validator.js';\nexport type {\n FileType,\n ValidationSeverity,\n ValidationError,\n ValidationResult,\n ValidationSummary,\n} from './types.js';\n","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 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/**\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 = 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: '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 evalcases array\n const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: 'evalcases',\n message: \"Missing or invalid 'evalcases' field (must be an array)\",\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 < evalcases.length; i++) {\n const evalCase = evalcases[i];\n const location = `evalcases[${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_messages, expected_messages\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: expected_outcome or outcome for backward compatibility\n const expectedOutcome = evalCase.expected_outcome ?? evalCase.outcome;\n if (\n expectedOutcome !== undefined &&\n (typeof expectedOutcome !== 'string' || expectedOutcome.trim().length === 0)\n ) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_outcome`,\n message:\n \"Invalid 'expected_outcome' or 'outcome' field (must be a non-empty string if provided)\",\n });\n }\n\n const inputMessages = evalCase.input_messages;\n if (!Array.isArray(inputMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.input_messages`,\n message: \"Missing or invalid 'input_messages' field (must be an array)\",\n });\n } else {\n validateMessages(inputMessages, `${location}.input_messages`, absolutePath, errors);\n }\n\n // expected_messages is optional - for outcome-only evaluation\n const expectedMessages = evalCase.expected_messages;\n if (expectedMessages !== undefined && !Array.isArray(expectedMessages)) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.expected_messages`,\n message: \"Invalid 'expected_messages' field (must be an array if provided)\",\n });\n } else if (Array.isArray(expectedMessages)) {\n validateMessages(expectedMessages, `${location}.expected_messages`, absolutePath, errors);\n }\n }\n\n return {\n valid: errors.length === 0,\n filePath: absolutePath,\n fileType: 'eval',\n errors,\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 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, TARGETS_SCHEMA_V2 } 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 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 '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]);\n\nconst VSCODE_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'workspace_template',\n 'workspaceTemplate',\n 'vscode_cmd',\n 'command',\n 'wait',\n 'dry_run',\n 'dryRun',\n 'subagent_root',\n 'subagentRoot',\n]);\n\nconst MOCK_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'response',\n 'delayMs',\n 'delayMinMs',\n 'delayMaxMs',\n]);\n\nconst CLI_SETTINGS = new Set([\n ...COMMON_SETTINGS,\n 'command_template',\n 'commandTemplate',\n 'files_format',\n 'filesFormat',\n 'attachments_format',\n 'attachmentsFormat',\n 'cwd',\n 'env',\n 'timeout_seconds',\n 'timeoutSeconds',\n 'healthcheck',\n]);\n\nfunction getKnownSettings(provider: string): Set<string> | null {\n const normalizedProvider = provider.toLowerCase();\n switch (normalizedProvider) {\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 'vscode':\n case 'vscode-insiders':\n return VSCODE_SETTINGS;\n case 'mock':\n return MOCK_SETTINGS;\n case 'cli':\n return CLI_SETTINGS;\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 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(['name', 'provider', 'judge_target', 'workers', '$schema', 'targets']);\n\n for (const key of Object.keys(target)) {\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 function validateCliSettings(\n target: JsonObject,\n absolutePath: string,\n location: string,\n errors: ValidationError[],\n ): void {\n const commandTemplate = target.command_template ?? target.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: \"CLI provider requires 'commandTemplate' as a non-empty string\",\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\n }\n\n const attachmentsFormat = target.attachments_format ?? target.attachmentsFormat;\n if (attachmentsFormat !== undefined && typeof attachmentsFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.attachmentsFormat`,\n message: \"'attachmentsFormat' must be a string when provided\",\n });\n }\n\n const filesFormat = target.files_format ?? target.filesFormat;\n if (filesFormat !== undefined && typeof filesFormat !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.filesFormat`,\n message: \"'filesFormat' must be a string when provided\",\n });\n }\n\n const cwd = target.cwd;\n if (cwd !== undefined && typeof cwd !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.cwd`,\n message: \"'cwd' must be a string when provided\",\n });\n }\n\n const timeoutSeconds = target.timeout_seconds ?? target.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: \"'timeoutSeconds' must be a positive number when provided\",\n });\n }\n }\n\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 type = healthcheck.type;\n if (type !== 'http' && type !== 'command') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.type`,\n message: \"healthcheck.type must be either 'http' or 'command'\",\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 if (type === 'http') {\n const url = healthcheck.url;\n if (typeof url !== 'string' || url.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.url`,\n message: 'healthcheck.url must be a non-empty string for http checks',\n });\n }\n return;\n }\n\n const commandTemplate = healthcheck.command_template ?? healthcheck.commandTemplate;\n if (typeof commandTemplate !== 'string' || commandTemplate.trim().length === 0) {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.commandTemplate`,\n message: 'healthcheck.commandTemplate must be a non-empty string for command checks',\n });\n } else {\n recordUnknownPlaceholders(\n commandTemplate,\n absolutePath,\n `${location}.commandTemplate`,\n errors,\n );\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 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 (!knownProviders.includes(provider)) {\n // Warning for unknown providers (non-fatal)\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') {\n validateUnknownSettings(target, provider, absolutePath, location, errors);\n }\n\n // Optional field: judge_target (must be string if present)\n const judgeTarget = target.judge_target;\n if (judgeTarget !== undefined && typeof judgeTarget !== 'string') {\n errors.push({\n severity: 'error',\n filePath: absolutePath,\n location: `${location}.judge_target`,\n message: \"Invalid 'judge_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 { z } from 'zod';\n\nimport type { EnvLookup, TargetDefinition } from './types.js';\n\nexport const CLI_PLACEHOLDERS = new Set([\n 'PROMPT',\n 'GUIDELINES',\n 'EVAL_ID',\n 'ATTEMPT',\n 'FILES',\n 'OUTPUT_FILE',\n]);\n\nexport interface RetryConfig {\n readonly maxRetries?: number;\n readonly initialDelayMs?: number;\n readonly maxDelayMs?: number;\n readonly backoffFactor?: number;\n readonly retryableStatusCodes?: readonly number[];\n}\n\n/**\n * Azure OpenAI settings used by the Vercel AI SDK.\n */\nexport interface AzureResolvedConfig {\n readonly resourceName: string;\n readonly deploymentName: string;\n readonly apiKey: string;\n readonly version?: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly retry?: RetryConfig;\n}\n\n/**\n * Anthropic Claude settings used by the Vercel AI SDK.\n */\nexport interface AnthropicResolvedConfig {\n readonly apiKey: string;\n readonly model: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly thinkingBudget?: number;\n readonly retry?: RetryConfig;\n}\n\n/**\n * Google Gemini settings used by the Vercel AI SDK.\n */\nexport interface GeminiResolvedConfig {\n readonly apiKey: string;\n readonly model: string;\n readonly temperature?: number;\n readonly maxOutputTokens?: number;\n readonly retry?: RetryConfig;\n}\n\nexport interface CodexResolvedConfig {\n readonly executable: string;\n readonly args?: readonly string[];\n readonly cwd?: string;\n readonly timeoutMs?: number;\n readonly logDir?: string;\n readonly logFormat?: 'summary' | 'json';\n}\n\nexport interface MockResolvedConfig {\n readonly response?: string;\n readonly delayMs?: number;\n readonly delayMinMs?: number;\n readonly delayMaxMs?: number;\n}\n\nexport interface VSCodeResolvedConfig {\n readonly command: string;\n readonly waitForResponse: boolean;\n readonly dryRun: boolean;\n readonly subagentRoot?: string;\n readonly workspaceTemplate?: string;\n}\n\nexport type CliHealthcheck =\n | {\n readonly type: 'http';\n readonly url: string;\n readonly timeoutMs?: number;\n }\n | {\n readonly type: 'command';\n readonly commandTemplate: string;\n readonly timeoutMs?: number;\n readonly cwd?: string;\n };\n\nexport interface CliResolvedConfig {\n readonly commandTemplate: string;\n readonly filesFormat?: string;\n readonly cwd?: string;\n readonly timeoutMs?: number;\n readonly healthcheck?: CliHealthcheck;\n readonly verbose?: boolean;\n}\n\nexport type ResolvedTarget =\n | {\n readonly kind: 'azure';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: AzureResolvedConfig;\n }\n | {\n readonly kind: 'anthropic';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: AnthropicResolvedConfig;\n }\n | {\n readonly kind: 'gemini';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: GeminiResolvedConfig;\n }\n | {\n readonly kind: 'codex';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: CodexResolvedConfig;\n }\n | {\n readonly kind: 'mock';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: MockResolvedConfig;\n }\n | {\n readonly kind: 'vscode' | 'vscode-insiders';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: VSCodeResolvedConfig;\n }\n | {\n readonly kind: 'cli';\n readonly name: string;\n readonly judgeTarget?: string;\n readonly workers?: number;\n readonly providerBatching?: boolean;\n readonly config: CliResolvedConfig;\n };\n\nconst BASE_TARGET_SCHEMA = z\n .object({\n name: z.string().min(1, 'target name is required'),\n provider: z.string().min(1, 'provider is required'),\n judge_target: z.string().optional(),\n workers: z.number().int().min(1).optional(),\n })\n .passthrough();\n\nconst DEFAULT_AZURE_API_VERSION = '2024-10-01-preview';\n\nfunction normalizeAzureApiVersion(value: string | undefined): string {\n if (!value) {\n return DEFAULT_AZURE_API_VERSION;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return DEFAULT_AZURE_API_VERSION;\n }\n\n const withoutPrefix = trimmed.replace(/^api[-_]?version\\s*=\\s*/i, '').trim();\n return withoutPrefix.length > 0 ? withoutPrefix : DEFAULT_AZURE_API_VERSION;\n}\n\nfunction resolveRetryConfig(target: z.infer<typeof BASE_TARGET_SCHEMA>): RetryConfig | undefined {\n const maxRetries = resolveOptionalNumber(\n target.max_retries ?? target.maxRetries,\n `${target.name} max retries`,\n );\n const initialDelayMs = resolveOptionalNumber(\n target.retry_initial_delay_ms ?? target.retryInitialDelayMs,\n `${target.name} retry initial delay`,\n );\n const maxDelayMs = resolveOptionalNumber(\n target.retry_max_delay_ms ?? target.retryMaxDelayMs,\n `${target.name} retry max delay`,\n );\n const backoffFactor = resolveOptionalNumber(\n target.retry_backoff_factor ?? target.retryBackoffFactor,\n `${target.name} retry backoff factor`,\n );\n const retryableStatusCodes = resolveOptionalNumberArray(\n target.retry_status_codes ?? target.retryStatusCodes,\n `${target.name} retry status codes`,\n );\n\n // Only return retry config if at least one field is set\n if (\n maxRetries === undefined &&\n initialDelayMs === undefined &&\n maxDelayMs === undefined &&\n backoffFactor === undefined &&\n retryableStatusCodes === undefined\n ) {\n return undefined;\n }\n\n return {\n maxRetries,\n initialDelayMs,\n maxDelayMs,\n backoffFactor,\n retryableStatusCodes,\n };\n}\n\nexport function resolveTargetDefinition(\n definition: TargetDefinition,\n env: EnvLookup = process.env,\n): ResolvedTarget {\n const parsed = BASE_TARGET_SCHEMA.parse(definition);\n const provider = parsed.provider.toLowerCase();\n const providerBatching = resolveOptionalBoolean(\n parsed.provider_batching ?? parsed.providerBatching,\n );\n\n switch (provider) {\n case 'azure':\n case 'azure-openai':\n return {\n kind: 'azure',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveAzureConfig(parsed, env),\n };\n case 'anthropic':\n return {\n kind: 'anthropic',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveAnthropicConfig(parsed, env),\n };\n case 'gemini':\n case 'google':\n case 'google-gemini':\n return {\n kind: 'gemini',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveGeminiConfig(parsed, env),\n };\n case 'codex':\n case 'codex-cli':\n return {\n kind: 'codex',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveCodexConfig(parsed, env),\n };\n case 'mock':\n return {\n kind: 'mock',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveMockConfig(parsed),\n };\n case 'vscode':\n case 'vscode-insiders':\n return {\n kind: provider as 'vscode' | 'vscode-insiders',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveVSCodeConfig(parsed, env, provider === 'vscode-insiders'),\n };\n case 'cli':\n return {\n kind: 'cli',\n name: parsed.name,\n judgeTarget: parsed.judge_target,\n workers: parsed.workers,\n providerBatching,\n config: resolveCliConfig(parsed, env),\n };\n default:\n throw new Error(`Unsupported provider '${parsed.provider}' in target '${parsed.name}'`);\n }\n}\n\nfunction resolveAzureConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): AzureResolvedConfig {\n const endpointSource = target.endpoint ?? target.resource ?? target.resourceName;\n const apiKeySource = target.api_key ?? target.apiKey;\n const deploymentSource = target.deployment ?? target.deploymentName ?? target.model;\n const versionSource = target.version ?? target.api_version;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n\n const resourceName = resolveString(endpointSource, env, `${target.name} endpoint`);\n const apiKey = resolveString(apiKeySource, env, `${target.name} api key`);\n const deploymentName = resolveString(deploymentSource, env, `${target.name} deployment`);\n const version = normalizeAzureApiVersion(\n resolveOptionalString(versionSource, env, `${target.name} api version`),\n );\n const temperature = resolveOptionalNumber(temperatureSource, `${target.name} temperature`);\n const maxOutputTokens = resolveOptionalNumber(\n maxTokensSource,\n `${target.name} max output tokens`,\n );\n const retry = resolveRetryConfig(target);\n\n return {\n resourceName,\n deploymentName,\n apiKey,\n version,\n temperature,\n maxOutputTokens,\n retry,\n };\n}\n\nfunction resolveAnthropicConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): AnthropicResolvedConfig {\n const apiKeySource = target.api_key ?? target.apiKey;\n const modelSource = target.model ?? target.deployment ?? target.variant;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n const thinkingBudgetSource = target.thinking_budget ?? target.thinkingBudget;\n\n const apiKey = resolveString(apiKeySource, env, `${target.name} Anthropic api key`);\n const model = resolveString(modelSource, env, `${target.name} Anthropic model`);\n const retry = resolveRetryConfig(target);\n\n return {\n apiKey,\n model,\n temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),\n maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),\n thinkingBudget: resolveOptionalNumber(thinkingBudgetSource, `${target.name} thinking budget`),\n retry,\n };\n}\n\nfunction resolveGeminiConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): GeminiResolvedConfig {\n const apiKeySource = target.api_key ?? target.apiKey;\n const modelSource = target.model ?? target.deployment ?? target.variant;\n const temperatureSource = target.temperature;\n const maxTokensSource = target.max_output_tokens ?? target.maxTokens;\n\n const apiKey = resolveString(apiKeySource, env, `${target.name} Google API key`);\n const model =\n resolveOptionalString(modelSource, env, `${target.name} Gemini model`, {\n allowLiteral: true,\n optionalEnv: true,\n }) ?? 'gemini-2.5-flash';\n const retry = resolveRetryConfig(target);\n\n return {\n apiKey,\n model,\n temperature: resolveOptionalNumber(temperatureSource, `${target.name} temperature`),\n maxOutputTokens: resolveOptionalNumber(maxTokensSource, `${target.name} max output tokens`),\n retry,\n };\n}\n\nfunction resolveCodexConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): CodexResolvedConfig {\n const executableSource = target.executable ?? target.command ?? target.binary;\n const argsSource = target.args ?? target.arguments;\n const cwdSource = target.cwd;\n const timeoutSource = target.timeout_seconds ?? target.timeoutSeconds;\n const logDirSource =\n target.log_dir ?? target.logDir ?? target.log_directory ?? target.logDirectory;\n const logFormatSource =\n target.log_format ??\n target.logFormat ??\n target.log_output_format ??\n target.logOutputFormat ??\n env.AGENTV_CODEX_LOG_FORMAT;\n\n const executable =\n resolveOptionalString(executableSource, env, `${target.name} codex executable`, {\n allowLiteral: true,\n optionalEnv: true,\n }) ?? 'codex';\n\n const args = resolveOptionalStringArray(argsSource, env, `${target.name} codex args`);\n\n const cwd = resolveOptionalString(cwdSource, env, `${target.name} codex cwd`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const timeoutMs = resolveTimeoutMs(timeoutSource, `${target.name} codex timeout`);\n const logDir = resolveOptionalString(logDirSource, env, `${target.name} codex log directory`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const logFormat = normalizeCodexLogFormat(logFormatSource);\n\n return {\n executable,\n args,\n cwd,\n timeoutMs,\n logDir,\n logFormat,\n };\n}\n\nfunction normalizeCodexLogFormat(value: unknown): 'summary' | 'json' | undefined {\n if (value === undefined || value === null) {\n return undefined;\n }\n if (typeof value !== 'string') {\n throw new Error(\"codex log format must be 'summary' or 'json'\");\n }\n const normalized = value.trim().toLowerCase();\n if (normalized === 'json' || normalized === 'summary') {\n return normalized;\n }\n throw new Error(\"codex log format must be 'summary' or 'json'\");\n}\n\nfunction resolveMockConfig(target: z.infer<typeof BASE_TARGET_SCHEMA>): MockResolvedConfig {\n const response = typeof target.response === 'string' ? target.response : undefined;\n return { response };\n}\n\nfunction resolveVSCodeConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n insiders: boolean,\n): VSCodeResolvedConfig {\n const workspaceTemplateEnvVar = resolveOptionalLiteralString(\n target.workspace_template ?? target.workspaceTemplate,\n );\n const workspaceTemplate = workspaceTemplateEnvVar\n ? resolveOptionalString(\n workspaceTemplateEnvVar,\n env,\n `${target.name} workspace template path`,\n {\n allowLiteral: false,\n optionalEnv: true,\n },\n )\n : undefined;\n\n const commandSource = target.vscode_cmd ?? target.command;\n const waitSource = target.wait;\n const dryRunSource = target.dry_run ?? target.dryRun;\n const subagentRootSource = target.subagent_root ?? target.subagentRoot;\n\n const defaultCommand = insiders ? 'code-insiders' : 'code';\n const command = resolveOptionalLiteralString(commandSource) ?? defaultCommand;\n\n return {\n command,\n waitForResponse: resolveOptionalBoolean(waitSource) ?? true,\n dryRun: resolveOptionalBoolean(dryRunSource) ?? false,\n subagentRoot: resolveOptionalString(subagentRootSource, env, `${target.name} subagent root`, {\n allowLiteral: true,\n optionalEnv: true,\n }),\n workspaceTemplate,\n };\n}\n\nfunction resolveCliConfig(\n target: z.infer<typeof BASE_TARGET_SCHEMA>,\n env: EnvLookup,\n): CliResolvedConfig {\n const commandTemplateSource = target.command_template ?? target.commandTemplate;\n const filesFormat = resolveOptionalLiteralString(\n target.files_format ??\n target.filesFormat ??\n target.attachments_format ??\n target.attachmentsFormat,\n );\n const cwd = resolveOptionalString(target.cwd, env, `${target.name} working directory`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n const timeoutMs = resolveTimeoutMs(\n target.timeout_seconds ?? target.timeoutSeconds,\n `${target.name} timeout`,\n );\n const healthcheck = resolveCliHealthcheck(target.healthcheck, env, target.name);\n\n const commandTemplate = resolveString(\n commandTemplateSource,\n env,\n `${target.name} CLI command template`,\n true,\n );\n assertSupportedCliPlaceholders(commandTemplate, `${target.name} CLI command template`);\n\n return {\n commandTemplate,\n filesFormat,\n cwd,\n timeoutMs,\n healthcheck,\n };\n}\n\nfunction resolveTimeoutMs(source: unknown, description: string): number | undefined {\n const seconds = resolveOptionalNumber(source, `${description} (seconds)`);\n if (seconds === undefined) {\n return undefined;\n }\n if (seconds <= 0) {\n throw new Error(`${description} must be greater than zero seconds`);\n }\n return Math.floor(seconds * 1000);\n}\n\nfunction resolveCliHealthcheck(\n source: unknown,\n env: EnvLookup,\n targetName: string,\n): CliHealthcheck | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'object' || Array.isArray(source)) {\n throw new Error(`${targetName} healthcheck must be an object`);\n }\n\n const candidate = source as Record<string, unknown>;\n const type = candidate.type;\n const timeoutMs = resolveTimeoutMs(\n candidate.timeout_seconds ?? candidate.timeoutSeconds,\n `${targetName} healthcheck timeout`,\n );\n\n if (type === 'http') {\n const url = resolveString(candidate.url, env, `${targetName} healthcheck URL`);\n return {\n type: 'http',\n url,\n timeoutMs,\n };\n }\n\n if (type === 'command') {\n const commandTemplate = resolveString(\n candidate.command_template ?? candidate.commandTemplate,\n env,\n `${targetName} healthcheck command template`,\n true,\n );\n assertSupportedCliPlaceholders(commandTemplate, `${targetName} healthcheck command template`);\n const cwd = resolveOptionalString(candidate.cwd, env, `${targetName} healthcheck cwd`, {\n allowLiteral: true,\n optionalEnv: true,\n });\n return {\n type: 'command',\n commandTemplate,\n timeoutMs,\n cwd,\n };\n }\n\n throw new Error(`${targetName} healthcheck type must be 'http' or 'command'`);\n}\n\nfunction assertSupportedCliPlaceholders(template: string, description: string): void {\n const placeholders = extractCliPlaceholders(template);\n for (const placeholder of placeholders) {\n if (!CLI_PLACEHOLDERS.has(placeholder)) {\n throw new Error(\n `${description} includes unsupported placeholder '{${placeholder}}'. Supported placeholders: ${Array.from(CLI_PLACEHOLDERS).join(', ')}`,\n );\n }\n }\n}\n\nfunction extractCliPlaceholders(template: string): string[] {\n const matches = template.matchAll(/\\{([A-Z_]+)\\}/g);\n const results: string[] = [];\n for (const match of matches) {\n if (match[1]) {\n results.push(match[1]);\n }\n }\n return results;\n}\n\nfunction resolveString(\n source: unknown,\n env: EnvLookup,\n description: string,\n allowLiteral = false,\n): string {\n const value = resolveOptionalString(source, env, description, {\n allowLiteral,\n optionalEnv: false,\n });\n if (value === undefined) {\n throw new Error(`${description} is required`);\n }\n return value;\n}\n\nfunction resolveOptionalString(\n source: unknown,\n env: EnvLookup,\n description: string,\n options?: { allowLiteral?: boolean; optionalEnv?: boolean },\n): string | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'string') {\n throw new Error(`${description} must be a string`);\n }\n const trimmed = source.trim();\n if (trimmed.length === 0) {\n return undefined;\n }\n\n // Check for ${{ variable }} syntax\n const envVarMatch = trimmed.match(/^\\$\\{\\{\\s*([A-Z0-9_]+)\\s*\\}\\}$/i);\n if (envVarMatch) {\n const varName = envVarMatch[1];\n const envValue = env[varName];\n if (envValue !== undefined) {\n if (envValue.trim().length === 0) {\n throw new Error(`Environment variable '${varName}' for ${description} is empty`);\n }\n return envValue;\n }\n const optionalEnv = options?.optionalEnv ?? false;\n if (optionalEnv) {\n return undefined;\n }\n throw new Error(`Environment variable '${varName}' required for ${description} is not set`);\n }\n\n // Return as literal value\n const allowLiteral = options?.allowLiteral ?? false;\n if (!allowLiteral) {\n throw new Error(\n `${description} must use \\${{ VARIABLE_NAME }} syntax for environment variables or be marked as allowing literals`,\n );\n }\n return trimmed;\n}\n\nfunction resolveOptionalLiteralString(source: unknown): string | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (typeof source !== 'string') {\n throw new Error('expected string value');\n }\n const trimmed = source.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction resolveOptionalNumber(source: unknown, description: string): number | undefined {\n if (source === undefined || source === null || source === '') {\n return undefined;\n }\n if (typeof source === 'number') {\n return Number.isFinite(source) ? source : undefined;\n }\n if (typeof source === 'string') {\n const numeric = Number(source);\n if (Number.isFinite(numeric)) {\n return numeric;\n }\n }\n throw new Error(`${description} must be a number`);\n}\n\nfunction resolveOptionalBoolean(source: unknown): boolean | undefined {\n if (source === undefined || source === null || source === '') {\n return undefined;\n }\n if (typeof source === 'boolean') {\n return source;\n }\n if (typeof source === 'string') {\n const lowered = source.trim().toLowerCase();\n if (lowered === 'true' || lowered === '1') {\n return true;\n }\n if (lowered === 'false' || lowered === '0') {\n return false;\n }\n }\n throw new Error('expected boolean value');\n}\n\nfunction resolveOptionalStringArray(\n source: unknown,\n env: EnvLookup,\n description: string,\n): readonly string[] | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (!Array.isArray(source)) {\n throw new Error(`${description} must be an array of strings`);\n }\n if (source.length === 0) {\n return undefined;\n }\n const resolved: string[] = [];\n for (let i = 0; i < source.length; i++) {\n const item = source[i];\n if (typeof item !== 'string') {\n throw new Error(`${description}[${i}] must be a string`);\n }\n const trimmed = item.trim();\n if (trimmed.length === 0) {\n throw new Error(`${description}[${i}] cannot be empty`);\n }\n\n // Check for ${{ variable }} syntax\n const envVarMatch = trimmed.match(/^\\$\\{\\{\\s*([A-Z0-9_]+)\\s*\\}\\}$/i);\n if (envVarMatch) {\n const varName = envVarMatch[1];\n const envValue = env[varName];\n if (envValue !== undefined) {\n if (envValue.trim().length === 0) {\n throw new Error(`Environment variable '${varName}' for ${description}[${i}] is empty`);\n }\n resolved.push(envValue);\n continue;\n }\n throw new Error(`Environment variable '${varName}' for ${description}[${i}] is not set`);\n }\n\n // Treat as literal value\n resolved.push(trimmed);\n }\n return resolved.length > 0 ? resolved : undefined;\n}\n\nfunction resolveOptionalNumberArray(\n source: unknown,\n description: string,\n): readonly number[] | undefined {\n if (source === undefined || source === null) {\n return undefined;\n }\n if (!Array.isArray(source)) {\n throw new Error(`${description} must be an array of numbers`);\n }\n if (source.length === 0) {\n return undefined;\n }\n const resolved: number[] = [];\n for (let i = 0; i < source.length; i++) {\n const item = source[i];\n if (typeof item !== 'number' || !Number.isFinite(item)) {\n throw new Error(`${description}[${i}] must be a number`);\n }\n resolved.push(item);\n }\n return resolved.length > 0 ? resolved : undefined;\n}\n","import type { JsonObject } from '../types.js';\n\nexport type ChatMessageRole = 'system' | 'user' | 'assistant' | 'tool' | 'function';\n\nexport interface ChatMessage {\n readonly role: ChatMessageRole;\n readonly content: string;\n readonly name?: string;\n}\n\nexport type ChatPrompt = readonly ChatMessage[];\n\nexport type ProviderKind =\n | 'azure'\n | 'anthropic'\n | 'gemini'\n | 'codex'\n | 'cli'\n | 'mock'\n | 'vscode'\n | 'vscode-insiders';\n\n/**\n * Agent providers that have filesystem access and don't need unwrapped guidelines.\n * These providers read files directly from the filesystem using file:// URIs.\n */\nexport const AGENT_PROVIDER_KINDS: readonly ProviderKind[] = [\n 'codex',\n 'vscode',\n 'vscode-insiders',\n] as const;\n\n/**\n * List of all supported provider kinds.\n * This is the source of truth for provider validation.\n */\nexport const KNOWN_PROVIDERS: readonly ProviderKind[] = [\n 'azure',\n 'anthropic',\n 'gemini',\n 'codex',\n 'cli',\n 'mock',\n 'vscode',\n 'vscode-insiders',\n] as const;\n\n/**\n * Provider aliases that are accepted in target definitions.\n * These map to the canonical ProviderKind values.\n */\nexport const PROVIDER_ALIASES: readonly string[] = [\n 'azure-openai', // alias for \"azure\"\n 'google', // alias for \"gemini\"\n 'google-gemini', // alias for \"gemini\"\n 'codex-cli', // alias for \"codex\"\n 'openai', // legacy/future support\n 'bedrock', // legacy/future support\n 'vertex', // legacy/future support\n] as const;\n\n/**\n * Schema identifier for targets.yaml files (version 2).\n */\nexport const TARGETS_SCHEMA_V2 = 'agentv-targets-v2.2';\n\nexport interface ProviderRequest {\n readonly question: string;\n readonly systemPrompt?: string;\n readonly guidelines?: string;\n readonly guideline_patterns?: readonly string[];\n readonly chatPrompt?: ChatPrompt;\n readonly inputFiles?: readonly string[];\n readonly evalCaseId?: string;\n readonly attempt?: number;\n readonly maxOutputTokens?: number;\n readonly temperature?: number;\n readonly metadata?: JsonObject;\n readonly signal?: AbortSignal;\n}\n\nexport interface ProviderResponse {\n readonly text: string;\n readonly reasoning?: string;\n readonly raw?: unknown;\n readonly usage?: JsonObject;\n}\n\n/**\n * Type guard to check if a provider is an agent provider with filesystem access.\n * Agent providers read files directly and don't need unwrapped guideline content.\n */\nexport function isAgentProvider(provider: Provider | undefined): boolean {\n return provider ? AGENT_PROVIDER_KINDS.includes(provider.kind) : false;\n}\n\nexport interface Provider {\n readonly id: string;\n readonly kind: ProviderKind;\n readonly targetName: string;\n invoke(request: ProviderRequest): Promise<ProviderResponse>;\n /**\n * Optional capability marker for provider-managed batching (single session handling multiple requests).\n */\n readonly supportsBatch?: boolean;\n /**\n * Optional batch invocation hook. When defined alongside supportsBatch=true,\n * the orchestrator may send multiple requests in a single provider session.\n */\n invokeBatch?(requests: readonly ProviderRequest[]): Promise<readonly ProviderResponse[]>;\n /**\n * Optional method to get a Vercel AI SDK LanguageModel instance for structured output generation.\n * Used by evaluators that need generateObject/generateText from the AI SDK.\n */\n asLanguageModel?(): import('ai').LanguageModel;\n}\n\nexport type EnvLookup = Readonly<Record<string, string | undefined>>;\n\nexport interface TargetDefinition {\n readonly name: string;\n readonly provider: ProviderKind | string;\n readonly judge_target?: string | undefined;\n readonly workers?: number | undefined;\n // Provider batching\n readonly provider_batching?: boolean | undefined;\n readonly providerBatching?: boolean | undefined;\n // Azure fields\n readonly endpoint?: string | unknown | undefined;\n readonly resource?: string | unknown | undefined;\n readonly resourceName?: string | unknown | undefined;\n readonly api_key?: string | unknown | undefined;\n readonly apiKey?: string | unknown | undefined;\n readonly deployment?: string | unknown | undefined;\n readonly deploymentName?: string | unknown | undefined;\n readonly model?: string | unknown | undefined;\n readonly version?: string | unknown | undefined;\n readonly api_version?: string | unknown | undefined;\n // Anthropic fields\n readonly variant?: string | unknown | undefined;\n readonly thinking_budget?: number | unknown | undefined;\n readonly thinkingBudget?: number | unknown | undefined;\n // Common fields\n readonly temperature?: number | unknown | undefined;\n readonly max_output_tokens?: number | unknown | undefined;\n readonly maxTokens?: number | unknown | undefined;\n // Codex fields\n readonly executable?: string | unknown | undefined;\n readonly command?: string | unknown | undefined;\n readonly binary?: string | unknown | undefined;\n readonly args?: unknown | undefined;\n readonly arguments?: unknown | undefined;\n readonly cwd?: string | unknown | undefined;\n readonly timeout_seconds?: number | unknown | undefined;\n readonly timeoutSeconds?: number | unknown | undefined;\n readonly log_dir?: string | unknown | undefined;\n readonly logDir?: string | unknown | undefined;\n readonly log_directory?: string | unknown | undefined;\n readonly logDirectory?: string | unknown | undefined;\n readonly log_format?: string | unknown | undefined;\n readonly logFormat?: string | unknown | undefined;\n readonly log_output_format?: string | unknown | undefined;\n readonly logOutputFormat?: string | unknown | undefined;\n // Mock fields\n readonly response?: string | unknown | undefined;\n readonly delayMs?: number | unknown | undefined;\n readonly delayMinMs?: number | unknown | undefined;\n readonly delayMaxMs?: number | unknown | undefined;\n // VSCode fields\n readonly vscode_cmd?: string | unknown | undefined;\n readonly wait?: boolean | unknown | undefined;\n readonly dry_run?: boolean | unknown | undefined;\n readonly dryRun?: boolean | unknown | undefined;\n readonly subagent_root?: string | unknown | undefined;\n readonly subagentRoot?: string | unknown | undefined;\n readonly workspace_template?: string | unknown | undefined;\n readonly workspaceTemplate?: string | unknown | undefined;\n // CLI fields\n readonly command_template?: string | unknown | undefined;\n readonly commandTemplate?: string | unknown | undefined;\n readonly files_format?: string | unknown | undefined;\n readonly filesFormat?: string | unknown | undefined;\n readonly attachments_format?: string | unknown | undefined;\n readonly attachmentsFormat?: string | unknown | undefined;\n readonly env?: unknown | undefined;\n readonly healthcheck?: unknown | undefined;\n // Retry configuration fields\n readonly max_retries?: number | unknown | undefined;\n readonly maxRetries?: number | unknown | undefined;\n readonly retry_initial_delay_ms?: number | unknown | undefined;\n readonly retryInitialDelayMs?: number | unknown | undefined;\n readonly retry_max_delay_ms?: number | unknown | undefined;\n readonly retryMaxDelayMs?: number | unknown | undefined;\n readonly retry_backoff_factor?: number | unknown | undefined;\n readonly retryBackoffFactor?: number | unknown | undefined;\n readonly retry_status_codes?: unknown | undefined;\n readonly retryStatusCodes?: unknown | undefined;\n}\n","import { readFile } from 'node:fs/promises';\nimport { parse } from 'yaml';\n\nimport type { ValidationError, ValidationResult } from './types.js';\n\nconst SCHEMA_CONFIG_V2 = 'agentv-config-v2';\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 $schema field (optional, but if present must be correct)\n const schema = config.$schema;\n if (schema !== undefined && schema !== SCHEMA_CONFIG_V2) {\n const message = `Invalid $schema value '${schema}'. Expected '${SCHEMA_CONFIG_V2}' or omit the field.`;\n errors.push({\n severity: 'error',\n filePath,\n location: '$schema',\n message,\n });\n }\n\n // Validate guideline_patterns if present\n const guidelinePatterns = config.guideline_patterns;\n if (guidelinePatterns !== undefined) {\n if (!Array.isArray(guidelinePatterns)) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'guideline_patterns',\n message: \"Field 'guideline_patterns' must be an array\",\n });\n } else if (!guidelinePatterns.every((p) => typeof p === 'string')) {\n errors.push({\n severity: 'error',\n filePath,\n location: 'guideline_patterns',\n message: \"All entries in 'guideline_patterns' must be strings\",\n });\n } else if (guidelinePatterns.length === 0) {\n errors.push({\n severity: 'warning',\n filePath,\n location: 'guideline_patterns',\n message: \"Field 'guideline_patterns' is empty. Consider removing it or adding patterns.\",\n });\n }\n }\n\n // Check for unexpected fields\n const allowedFields = new Set(['$schema', 'guideline_patterns']);\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 const evalcases = parsed.evalcases;\n if (!Array.isArray(evalcases)) {\n return errors;\n }\n\n for (let i = 0; i < evalcases.length; i++) {\n const evalCase = evalcases[i];\n if (!isObject(evalCase)) {\n continue;\n }\n\n // Check input_messages\n const inputMessages = evalCase.input_messages;\n if (Array.isArray(inputMessages)) {\n await validateMessagesFileRefs(\n inputMessages,\n `evalcases[${i}].input_messages`,\n searchRoots,\n absolutePath,\n errors,\n );\n }\n\n // Check expected_messages\n const expectedMessages = evalCase.expected_messages;\n if (Array.isArray(expectedMessages)) {\n await validateMessagesFileRefs(\n expectedMessages,\n `evalcases[${i}].expected_messages`,\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","import { constants } from 'node:fs';\nimport { access, readFile } from 'node:fs/promises';\nimport path from 'node:path';\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Normalize line endings to LF (\\n).\n * This ensures consistent behavior across Windows (CRLF) and Unix (LF) systems.\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n');\n}\n\n/**\n * Read a text file and normalize line endings to LF (\\n).\n * This ensures consistent behavior across Windows (CRLF) and Unix (LF) systems.\n */\nexport async function readTextFile(filePath: string): Promise<string> {\n const content = await readFile(filePath, 'utf8');\n return normalizeLineEndings(content);\n}\n\n/**\n * Find git repository root by walking up the directory tree.\n */\nexport async function findGitRoot(startPath: string): Promise<string | null> {\n let currentDir = path.dirname(path.resolve(startPath));\n const root = path.parse(currentDir).root;\n\n while (currentDir !== root) {\n const gitPath = path.join(currentDir, '.git');\n if (await fileExists(gitPath)) {\n return currentDir;\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n break;\n }\n currentDir = parentDir;\n }\n\n return null;\n}\n\n/**\n * Build a chain of directories walking from a file's location up to repo root.\n * Used for discovering configuration files like targets.yaml or config.yaml.\n */\nexport function buildDirectoryChain(filePath: string, repoRoot: string): readonly string[] {\n const directories: string[] = [];\n const seen = new Set<string>();\n const boundary = path.resolve(repoRoot);\n let current: string | undefined = path.resolve(path.dirname(filePath));\n\n while (current !== undefined) {\n if (!seen.has(current)) {\n directories.push(current);\n seen.add(current);\n }\n if (current === boundary) {\n break;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n\n if (!seen.has(boundary)) {\n directories.push(boundary);\n }\n\n return directories;\n}\n\n/**\n * Build search roots for file resolution, matching yaml-parser behavior.\n * Searches from eval file directory up to repo root.\n */\nexport function buildSearchRoots(evalPath: string, repoRoot: string): readonly string[] {\n const uniqueRoots: string[] = [];\n const addRoot = (root: string): void => {\n const normalized = path.resolve(root);\n if (!uniqueRoots.includes(normalized)) {\n uniqueRoots.push(normalized);\n }\n };\n\n let currentDir = path.dirname(evalPath);\n let reachedBoundary = false;\n while (!reachedBoundary) {\n addRoot(currentDir);\n const parentDir = path.dirname(currentDir);\n if (currentDir === repoRoot || parentDir === currentDir) {\n reachedBoundary = true;\n } else {\n currentDir = parentDir;\n }\n }\n\n addRoot(repoRoot);\n addRoot(process.cwd());\n return uniqueRoots;\n}\n\n/**\n * Trim leading path separators for display.\n */\nfunction trimLeadingSeparators(value: string): string {\n const trimmed = value.replace(/^[/\\\\]+/, '');\n return trimmed.length > 0 ? trimmed : value;\n}\n\n/**\n * Resolve a file reference using search roots, matching yaml-parser behavior.\n */\nexport async function resolveFileReference(\n rawValue: string,\n searchRoots: readonly string[],\n): Promise<{\n readonly displayPath: string;\n readonly resolvedPath?: string;\n readonly attempted: readonly string[];\n}> {\n const displayPath = trimLeadingSeparators(rawValue);\n const potentialPaths: string[] = [];\n\n if (path.isAbsolute(rawValue)) {\n potentialPaths.push(path.normalize(rawValue));\n }\n\n for (const base of searchRoots) {\n potentialPaths.push(path.resolve(base, displayPath));\n }\n\n const attempted: string[] = [];\n const seen = new Set<string>();\n for (const candidate of potentialPaths) {\n const absoluteCandidate = path.resolve(candidate);\n if (seen.has(absoluteCandidate)) {\n continue;\n }\n seen.add(absoluteCandidate);\n attempted.push(absoluteCandidate);\n if (await fileExists(absoluteCandidate)) {\n return { displayPath, resolvedPath: absoluteCandidate, attempted };\n }\n }\n\n return { displayPath, attempted };\n}\n"],"mappings":"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","names":["path","import_promises","import_node_path","import_yaml","path","import_promises","import_node_path","import_yaml","isObject","path","absolutePath","errors","import_promises","import_yaml","SCHEMA_CONFIG_V2","import_promises","import_node_path","import_yaml","import_promises","import_node_path","path","path","isObject","path"]}
|