/**
 * MCP server task compilation — core compiler logic.
 *
 * Produces Promptfoo configuration from MCP server task definitions:
 * 1. A provider config pointing to the MCP server
 * 2. Test cases with tool-call assertions
 * 3. Appropriate prompts for the evaluation
 */
import { buildMCPAssertions } from "./assertions.js";
import { buildMCPProvider } from "./provider-config.js";
import { validateMCPTask } from "./validation.js";
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Compile an MCP server task definition into Promptfoo configuration.
 *
 * This is the core of the MCP mode handler. It produces:
 * 1. A provider config pointing to the MCP server
 * 2. Test cases with tool-call assertions
 * 3. Appropriate prompts for the evaluation
 */
export function compileMCPTask(task, options) {
    const warnings = [];
    // Validate
    const validationErrors = validateMCPTask(task);
    if (validationErrors.length > 0) {
        for (const err of validationErrors) {
            warnings.push(`MCP task "${task.id}": ${err.field} — ${err.message}`);
        }
    }
    // Build providers (one LLM provider per model, each with MCP config)
    const providers = buildMCPProvider(task, options?.models ?? [], warnings);
    // Build prompts
    const prompts = buildMCPPrompts(task);
    // Build test cases
    const tests = buildMCPTestCases(task, options, warnings);
    return { providers, tests, prompts, warnings };
}
// ---------------------------------------------------------------------------
// Prompt assembly
// ---------------------------------------------------------------------------
function buildMCPPrompts(task) {
    // MCP mode uses a single prompt — the task description
    const promptText = task.prompt?.text ??
        task.prompt?.vars?.task ??
        task.description ??
        `Test MCP server: ${task.title}`;
    return [
        {
            id: "mcp-test",
            label: `MCP: ${task.title}`,
            raw: String(promptText),
        },
    ];
}
// ---------------------------------------------------------------------------
// Test case assembly
// ---------------------------------------------------------------------------
function buildMCPTestCases(task, options, warnings) {
    const tests = [];
    // Build assertion context
    const assertionContext = {
        capabilities: task.capabilities ?? [],
        graderProvider: options?.graderProvider,
        rubricConfig: options?.rubricConfig,
        taskId: task.id,
    };
    // Compile assertions
    // Cast GeneralizedAssertionDefinition[] → AssertionInput[] (structurally compatible)
    const assertions = [];
    if (task.assertions) {
        const rawAssertions = task.assertions;
        const { assertions: mapped, warnings: assertionWarnings } = buildMCPAssertions(rawAssertions, assertionContext);
        assertions.push(...mapped);
        warnings.push(...assertionWarnings);
    }
    // Build test case vars
    const vars = {
        task: task.prompt?.vars?.task ?? task.description ?? `Test: ${task.title}`,
        ...(task.prompt?.vars ?? {}),
        // Group scoring by the task's declared area. Set after the prompt-vars
        // spread so it is canonical (mirrors literacy). Without it, scoring falls
        // back to detectFeatureArea on the description, which mis-derives areas
        // like "groq" from prompt text.
        __featureArea: task.area,
    };
    // Primary test case
    tests.push({
        description: `${task.id} — ${task.title}`,
        vars,
        ...(assertions.length > 0 ? { assert: assertions } : {}),
    });
    // Multi-turn test cases
    if (task.multiTurn?.turns && task.multiTurn.turns.length > 0) {
        tests.push({
            description: `${task.id} — ${task.title} [multi-turn]`,
            vars: {
                ...vars,
                __multiTurn: task.multiTurn.turns,
            },
            ...(assertions.length > 0 ? { assert: assertions } : {}),
        });
    }
    return tests;
}
