/**
 * Constants and types shared across evaluation steps.
 *
 * Extracted from pipeline/steps/eval-step.ts so that the legacy step
 * files can be deleted while tests and other modules retain access
 * to these shared definitions.
 */
import { existsSync, readFileSync } from "fs";
// ---------------------------------------------------------------------------
// Config / results file naming — unified across all modes
// ---------------------------------------------------------------------------
/** Literacy variant names that map to legacy config file naming */
const LITERACY_CONFIG_FILES = {
    agentic: "promptfooconfig.agentic.yaml",
    baseline: "promptfooconfig.yaml",
    observed: "promptfooconfig.observed.yaml",
};
/** Literacy variant names that map to legacy results file naming */
const LITERACY_RESULTS_FILES = {
    agentic: "results/latest/eval-results-agentic.json",
    baseline: "results/latest/eval-results.json",
    observed: "results/latest/eval-results-observed.json",
};
/**
 * Get the Promptfoo config file path for a given mode.
 *
 * Literacy variants use legacy naming for backward compatibility.
 * All other modes use the pattern: `promptfooconfig.<mode>.yaml`
 */
export function configFileForMode(mode) {
    return LITERACY_CONFIG_FILES[mode] ?? `promptfooconfig.${mode}.yaml`;
}
/**
 * Get the results file path for a given mode.
 *
 * Literacy variants use legacy naming for backward compatibility.
 * All other modes use: `results/latest/eval-results-<mode>.json`
 */
export function resultsFileForMode(mode) {
    return (LITERACY_RESULTS_FILES[mode] ?? `results/latest/eval-results-${mode}.json`);
}
/**
 * Build promptfoo filter flags from debug options.
 */
export function buildFilterFlags(debug) {
    if (!debug?.enabled)
        return "";
    const flags = [];
    if (debug.pattern) {
        flags.push(`--filter-pattern '${debug.pattern}'`);
    }
    if (debug.sample) {
        flags.push(`--filter-sample ${debug.sample}`);
    }
    if (debug.firstN) {
        flags.push(`--filter-first-n ${debug.firstN}`);
    }
    // Default: first 2 tests when no other filters specified
    if (flags.length === 0) {
        flags.push("--filter-first-n 2");
    }
    return " " + flags.join(" ");
}
/**
 * Extract the Promptfoo share URL from the eval results JSON.
 *
 * Promptfoo writes a `shareableUrl` field into the results file when
 * `PROMPTFOO_API_KEY` is set.
 */
export function extractShareUrl(resultsPath) {
    if (!existsSync(resultsPath))
        return undefined;
    try {
        const raw = readFileSync(resultsPath, "utf-8");
        const data = JSON.parse(raw);
        return data.shareableUrl ?? undefined;
    }
    catch {
        return undefined;
    }
}
/**
 * Read the eval results JSON and produce a human-readable summary of any
 * errored or failed tests.
 *
 * Returns null if there are no errors/failures worth reporting.
 */
export function scanResultsForErrors(resultsPath) {
    if (!existsSync(resultsPath))
        return null;
    let file;
    try {
        const raw = readFileSync(resultsPath, "utf-8");
        file = JSON.parse(raw);
    }
    catch {
        return null;
    }
    const results = file?.results?.results;
    if (!Array.isArray(results))
        return null;
    const errored = [];
    for (const r of results) {
        if (r.gradingResult !== null)
            continue;
        const desc = r.testCase?.description ?? r.description ?? "unknown";
        const provider = r.provider?.label ?? r.provider?.id ?? "unknown";
        const errorMsg = r.error
            ? (typeof r.error === "string" ? r.error : JSON.stringify(r.error)).slice(0, 200)
            : "Provider returned no scorable result";
        errored.push({ description: desc, error: errorMsg, provider });
    }
    if (errored.length === 0)
        return null;
    const total = results.length;
    const lines = [];
    lines.push(`  ┌─────────────────────────────────────────────────────────────`);
    lines.push(`  │ ⚠️  ${errored.length} of ${total} eval result(s) errored (no gradingResult)`);
    lines.push(`  │`);
    for (const e of errored) {
        lines.push(`  │   ✗ [${e.provider}] ${e.description}`);
        lines.push(`  │     → ${e.error}`);
    }
    const errorRate = Math.round((errored.length / total) * 100);
    if (errorRate >= 25) {
        lines.push(`  │`);
        lines.push(`  │ 🔥 High error rate (${errorRate}%) — check API keys, rate limits,`);
        lines.push(`  │   or model availability. Errored results are excluded from scoring.`);
    }
    lines.push(`  └─────────────────────────────────────────────────────────────`);
    return lines.join("\n");
}
