Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions apps/cli/src/commands/results/studio-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import path from 'node:path';

import { DEFAULT_THRESHOLD } from '@agentv/core';
import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
import { DEFAULT_THRESHOLD, parseYamlValue } from '@agentv/core';
import { stringify as stringifyYaml } from 'yaml';

export interface StudioConfig {
threshold: number;
Expand All @@ -47,7 +47,7 @@ export function loadStudioConfig(agentvDir: string): StudioConfig {
}

const raw = readFileSync(configPath, 'utf-8');
const parsed = parseYaml(raw);
const parsed = parseYamlValue(raw);

if (!parsed || typeof parsed !== 'object') {
return { ...DEFAULTS };
Expand Down Expand Up @@ -89,7 +89,7 @@ export function saveStudioConfig(agentvDir: string, config: StudioConfig): void
let existing: Record<string, unknown> = {};
if (existsSync(configPath)) {
const raw = readFileSync(configPath, 'utf-8');
const parsed = parseYaml(raw);
const parsed = parseYamlValue(raw);
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
existing = parsed as Record<string, unknown>;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/benchmarks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
import path from 'node:path';

import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
import { stringify as stringifyYaml } from 'yaml';

import { parseYamlValue } from './evaluation/yaml-loader.js';
import { getAgentvConfigDir } from './paths.js';

// ── Types ───────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -101,7 +102,7 @@ export function loadBenchmarkRegistry(): BenchmarkRegistry {
}
try {
const raw = readFileSync(registryPath, 'utf-8');
const parsed = parseYaml(raw);
const parsed = parseYamlValue(raw) as { benchmarks?: unknown } | null | undefined;
if (!parsed || typeof parsed !== 'object') {
return { benchmarks: [] };
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/evaluation/loaders/case-file-loader.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { readFile, readdir, stat } from 'node:fs/promises';
import path from 'node:path';
import fg from 'fast-glob';
import { parse as parseYaml } from 'yaml';

import { interpolateEnv } from '../interpolation.js';
import type { JsonObject, JsonValue } from '../types.js';
import { isJsonObject } from '../types.js';
import { parseYamlValue } from '../yaml-loader.js';

const ANSI_YELLOW = '\u001b[33m';
const ANSI_RESET = '\u001b[0m';
Expand Down Expand Up @@ -38,7 +38,7 @@ function isGlobPattern(filePath: string): boolean {
* Expects the file to contain an array of test objects.
*/
function parseYamlCases(content: string, filePath: string): JsonObject[] {
const raw = parseYaml(content) as unknown;
const raw = parseYamlValue(content);
const parsed = interpolateEnv(raw, process.env);
if (!Array.isArray(parsed)) {
throw new Error(
Expand Down Expand Up @@ -206,7 +206,7 @@ export async function loadCasesFromDirectory(dirPath: string): Promise<JsonObjec
throw new Error(`Cannot read case file: ${caseFilePath}\n ${message}`);
}

const raw = parseYaml(content) as unknown;
const raw = parseYamlValue(content);
const parsed = interpolateEnv(raw, process.env);
if (!isJsonObject(parsed)) {
throw new Error(
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/loaders/config-loader.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { interpolateEnv } from '../interpolation.js';
import { parseYamlValue } from '../yaml-loader.js';
import type {
EvalTargetRef,
FailOnError,
Expand Down Expand Up @@ -77,7 +77,7 @@ export async function loadConfig(

try {
const rawConfig = await readFile(configPath, 'utf8');
const parsed = interpolateEnv(parse(rawConfig), process.env) as unknown;
const parsed = interpolateEnv(parseYamlValue(rawConfig), process.env) as unknown;

if (!isJsonObject(parsed)) {
logWarning(`Invalid .agentv/config.yaml format at ${configPath}`);
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/evaluation/loaders/eval-yaml-transpiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

import { readFileSync } from 'node:fs';
import path from 'node:path';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';

// ---------------------------------------------------------------------------
// evals.json output types
Expand Down Expand Up @@ -510,7 +511,7 @@ export function transpileEvalYaml(suite: unknown, source = 'EVAL.yaml'): Transpi
*/
export function transpileEvalYamlFile(evalYamlPath: string): TranspileResult {
const content = readFileSync(evalYamlPath, 'utf8');
const parsed = parse(content) as unknown;
const parsed = parseYamlValue(content);
return transpileEvalYaml(parsed, path.basename(evalYamlPath));
}

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/loaders/grader-parser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { normalizePreprocessorType } from '../content-preprocessor.js';
import { interpolateEnv } from '../interpolation.js';
import { parseYamlValue } from '../yaml-loader.js';
import type { ToolTrajectoryExpectedItem, ToolTrajectoryGraderConfig } from '../trace.js';
import type {
ContentPreprocessorConfig,
Expand Down Expand Up @@ -183,7 +183,7 @@ async function loadAssertionTemplateEntries(
}

const content = await readFile(resolved.resolvedPath, 'utf8');
const parsed = interpolateEnv(parse(content), process.env) as unknown;
const parsed = interpolateEnv(parseYamlValue(content), process.env) as unknown;
if (!isJsonObject(parsed)) {
throw new Error(
`Invalid assertion template file in '${evalId}': ${resolved.resolvedPath} (expected a YAML object with an assertions array)`,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/loaders/jsonl-parser.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import micromatch from 'micromatch';
import { parse as parseYaml } from 'yaml';

import { collectResolvedInputFilePaths } from '../input-message-utils.js';
import { interpolateEnv } from '../interpolation.js';
import type { EvalTest, JsonObject, JsonValue, TestMessage } from '../types.js';
import { isJsonObject, isTestMessage } from '../types.js';
import { parseYamlValue } from '../yaml-loader.js';
import { buildSearchRoots, fileExists, resolveToAbsolutePath } from './file-resolver.js';
import {
coerceEvaluator,
Expand Down Expand Up @@ -92,7 +92,7 @@ async function loadSidecarMetadata(jsonlPath: string, verbose: boolean): Promise

try {
const content = await readFile(sidecarPath, 'utf8');
const parsed = interpolateEnv(parseYaml(content), process.env) as unknown;
const parsed = interpolateEnv(parseYamlValue(content), process.env) as unknown;

if (!isJsonObject(parsed)) {
logWarning(`Invalid sidecar metadata format in ${sidecarPath}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import { readFile, readdir, stat } from 'node:fs/promises';
import { homedir } from 'node:os';
import path from 'node:path';
import { parse as parseYaml } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';

export interface CopilotSession {
readonly sessionId: string;
Expand Down Expand Up @@ -60,7 +61,7 @@ export async function discoverCopilotSessions(opts?: DiscoverOptions): Promise<C

try {
const workspaceContent = await readFile(workspacePath, 'utf8');
const workspace = (parseYaml(workspaceContent) ?? {}) as Record<string, unknown>;
const workspace = (parseYamlValue(workspaceContent) ?? {}) as Record<string, unknown>;

const cwd = String(workspace.cwd ?? '');

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/providers/targets-file.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { constants } from 'node:fs';
import { access, readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';
import { TARGETS_SCHEMA_V2 } from './types.js';
import type { TargetDefinition } from './types.js';

Expand Down Expand Up @@ -62,7 +62,7 @@ export async function readTargetDefinitions(
}

const raw = await readFile(absolutePath, 'utf8');
const parsed = parse(raw) as unknown;
const parsed = parseYamlValue(raw);

if (!isRecord(parsed)) {
throw new Error(`targets.yaml at ${absolutePath} must be a YAML object with a 'targets' field`);
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/validation/cases-validator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError, ValidationResult } from './types.js';

type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
Expand All @@ -26,7 +26,7 @@ export async function validateCasesFile(filePath: string): Promise<ValidationRes
let parsed: unknown;
try {
const content = await readFile(absolutePath, 'utf8');
parsed = parse(content);
parsed = parseYamlValue(content);
} catch (error) {
errors.push({
severity: 'error',
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/validation/config-validator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFile } from 'node:fs/promises';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError, ValidationResult } from './types.js';

/**
Expand All @@ -11,7 +11,7 @@ export async function validateConfigFile(filePath: string): Promise<ValidationRe

try {
const content = await readFile(filePath, 'utf8');
const parsed = parse(content) as unknown;
const parsed = parseYamlValue(content);

// Check if parsed content is an object
if (typeof parsed !== 'object' || parsed === null) {
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/evaluation/validation/eval-validator.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { readFile, readdir, stat } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { interpolateEnv } from '../interpolation.js';
import { loadCasesFromDirectory, loadCasesFromFile } from '../loaders/case-file-loader.js';
import { isGraderKind } from '../types.js';
import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError, ValidationResult } from './types.js';

type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
Expand Down Expand Up @@ -165,7 +165,7 @@ export async function validateEvalFile(filePath: string): Promise<ValidationResu
let parsed: unknown;
try {
const content = await readFile(absolutePath, 'utf8');
parsed = interpolateEnv(parse(content), process.env);
parsed = interpolateEnv(parseYamlValue(content), process.env);
} catch (error) {
errors.push({
severity: 'error',
Expand Down Expand Up @@ -514,7 +514,7 @@ async function validateWorkspaceConfig(

try {
const workspaceContent = await readFile(workspacePath, 'utf8');
const parsedWorkspace = interpolateEnv(parse(workspaceContent), process.env);
const parsedWorkspace = interpolateEnv(parseYamlValue(workspaceContent), process.env);
if (!isObject(parsedWorkspace)) {
errors.push({
severity: 'error',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { buildSearchRoots, findGitRoot, resolveFileReference } from '../file-utils.js';
import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError } from './types.js';

type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
Expand Down Expand Up @@ -40,7 +40,7 @@ export async function validateFileReferences(
let parsed: unknown;
try {
const content = await readFile(absolutePath, 'utf8');
parsed = parse(content);
parsed = parseYamlValue(content);
} catch {
// Parse errors are already caught by eval-validator
return errors;
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/validation/file-type.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';
import type { FileType } from './types.js';

const SCHEMA_EVAL_V2 = 'agentv-eval-v2';
Expand All @@ -18,7 +18,7 @@ const SCHEMA_CONFIG_V2 = 'agentv-config-v2';
export async function detectFileType(filePath: string): Promise<FileType> {
try {
const content = await readFile(filePath, 'utf8');
const parsed = parse(content) as unknown;
const parsed = parseYamlValue(content);

// YAML array root → cases file (array of test case objects)
if (Array.isArray(parsed)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/evaluation/validation/targets-validator.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import {
CLI_PLACEHOLDERS,
COMMON_TARGET_SETTINGS,
findDeprecatedCamelCaseTargetWarnings,
} from '../providers/targets.js';
import { KNOWN_PROVIDERS, PROVIDER_ALIASES } from '../providers/types.js';
import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError, ValidationResult } from './types.js';

type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
Expand Down Expand Up @@ -280,7 +280,7 @@ export async function validateTargetsFile(filePath: string): Promise<ValidationR
let parsed: unknown;
try {
const content = await readFile(absolutePath, 'utf8');
parsed = parse(content);
parsed = parseYamlValue(content);
} catch (error) {
errors.push({
severity: 'error',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { access, readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { parseYamlValue } from '../yaml-loader.js';
import type { ValidationError } from './types.js';

type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
Expand Down Expand Up @@ -38,7 +38,7 @@ export async function validateWorkspacePaths(
let parsed: unknown;
try {
const content = await readFile(absolutePath, 'utf8');
parsed = parse(content);
parsed = parseYamlValue(content);
} catch {
// Parse errors are already caught by eval-validator
return errors;
Expand All @@ -55,7 +55,7 @@ export async function validateWorkspacePaths(
const workspaceFilePath = path.resolve(evalDir, workspaceRaw);
try {
const wsContent = await readFile(workspaceFilePath, 'utf8');
const wsParsed = parse(wsContent);
const wsParsed = parseYamlValue(wsContent);
if (isObject(wsParsed)) {
const wsDir = path.dirname(workspaceFilePath);
await validateWorkspaceObject(wsParsed, wsDir, absolutePath, 'workspace', errors);
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/evaluation/workspace/deps-scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
*/
import { readFile } from 'node:fs/promises';
import path from 'node:path';
import { parse } from 'yaml';

import { interpolateEnv } from '../interpolation.js';
import type { RepoCheckout, RepoClone, RepoSource } from '../types.js';
import { parseYamlValue } from '../yaml-loader.js';
import { parseRepoCheckout, parseRepoClone, parseRepoSource } from './repo-config-parser.js';

/** A single git repo dependency discovered from eval files. */
Expand Down Expand Up @@ -115,7 +115,7 @@ interface RawRepo {

async function extractReposFromEvalFile(filePath: string): Promise<RawRepo[]> {
const content = await readFile(filePath, 'utf8');
const parsed = interpolateEnv(parse(content), process.env);
const parsed = interpolateEnv(parseYamlValue(content), process.env);
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return [];
const obj = parsed as Record<string, unknown>;
const evalFileDir = path.dirname(path.resolve(filePath));
Expand Down Expand Up @@ -148,7 +148,7 @@ async function extractReposFromWorkspaceRaw(raw: unknown, evalFileDir: string):
// External workspace file reference
const workspaceFilePath = path.resolve(evalFileDir, raw);
const content = await readFile(workspaceFilePath, 'utf8');
const parsed = interpolateEnv(parse(content), process.env);
const parsed = interpolateEnv(parseYamlValue(content), process.env);
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return [];
return extractReposFromObject(parsed as Record<string, unknown>);
}
Expand Down
Loading
Loading