/**
 * Agent harness task compilation — core compilation logic.
 *
 * Maps agent harness task definitions to Promptfoo configuration with:
 * - Claude Agent SDK / OpenAI Codex SDK providers
 * - Tool permission configuration (preset/allowed/disallowed)
 * - Sandbox setup/teardown via Promptfoo extensions
 * - Fixture provisioning into sandbox working directory
 */
import { mapAgentAssertion } from "./assertions.js";
import { buildLifecycleExtensions, buildSandboxConfig } from "./sandbox.js";
import { TOOL_PRESETS } from "./tool-presets.js";
import { validateAgentHarnessTask } from "./validation.js";
/**
 * Compile an agent harness task definition into Promptfoo configuration.
 */
export function compileAgentHarnessTask(task, options) {
    const warnings = [];
    // Validate
    const validationErrors = validateAgentHarnessTask(task);
    for (const err of validationErrors) {
        warnings.push(`Agent harness task "${task.id}": ${err.field} — ${err.message}`);
    }
    // Build provider
    const providers = buildAgentProvider(task, warnings);
    // Build prompts
    const prompts = buildAgentPrompts(task);
    // Build test cases
    const tests = buildAgentTestCases(task, options, warnings);
    // Build sandbox extensions — resolve fixture paths at compile time using
    // the caller's cwd (monorepo root), not the eval package rootDir.
    const callerCwd = process.env.AILF_CALLER_CWD ?? process.cwd();
    const sandboxConfig = buildSandboxConfig(task, callerCwd);
    const extensions = buildLifecycleExtensions(task, sandboxConfig);
    return { providers, tests, prompts, extensions, sandboxConfig, warnings };
}
// ---------------------------------------------------------------------------
// Provider assembly
// ---------------------------------------------------------------------------
export function buildAgentProvider(task, _warnings) {
    const tools = resolveToolPermissions(task.tools);
    // Claude Agent SDK config.
    // working_dir is set by the YAML writer to the sandbox path it creates.
    // @see https://www.promptfoo.dev/docs/providers/claude-agent-sdk/
    const config = {
        model: "claude-sonnet-4-20250514",
        max_turns: 25,
        max_budget_usd: 1.0,
        permission_mode: "bypassPermissions",
        allow_dangerously_skip_permissions: true,
    };
    // Map AILF tool names to Claude Agent SDK tool config.
    // Claude SDK uses custom_allowed_tools to replace defaults.
    if (tools.length > 0) {
        config.custom_allowed_tools = tools;
    }
    return [
        {
            id: "anthropic:claude-agent-sdk",
            label: `Agent Harness: ${task.title}`,
            config,
        },
    ];
}
/**
 * Resolve tool permissions from task config.
 *
 * Handles:
 * - Preset names ("coding", "read-only", "full-access")
 * - Explicit tool names ("Bash", "Read", "Write")
 * - Mixed arrays ["coding", "WebSearch"] → preset expansion + extras
 */
function resolveToolPermissions(tools) {
    if (!tools || tools.length === 0)
        return [];
    const resolved = new Set();
    for (const tool of tools) {
        const preset = TOOL_PRESETS[tool];
        if (preset) {
            for (const t of preset)
                resolved.add(t);
        }
        else {
            resolved.add(tool);
        }
    }
    return [...resolved];
}
// ---------------------------------------------------------------------------
// Prompt assembly
// ---------------------------------------------------------------------------
export function buildAgentPrompts(task) {
    const promptText = task.prompt?.text ??
        task.prompt?.vars?.task ??
        task.description ??
        `Agent task: ${task.title}`;
    return [
        {
            id: "agent-harness",
            label: `Agent: ${task.title}`,
            raw: String(promptText),
        },
    ];
}
// ---------------------------------------------------------------------------
// Test case assembly
// ---------------------------------------------------------------------------
export function buildAgentTestCases(task, options, warnings) {
    const assertions = [];
    if (task.assertions) {
        for (const assertion of task.assertions) {
            const mapped = mapAgentAssertion(assertion, options, warnings);
            if (mapped)
                assertions.push(mapped);
        }
    }
    const vars = {
        task: task.prompt?.vars?.task ?? task.description ?? `Complete: ${task.title}`,
        ...(task.prompt?.vars ?? {}),
        // Internal metadata for sandbox lifecycle hooks.
        // Fixture paths are plain strings (no file:// prefix) because
        // promptfoo auto-resolves file:// in vars by reading file content.
        __sandboxType: task.sandbox?.type ?? "tempdir",
        __fixtures: (task.fixtures ?? []).map((f) => f.startsWith("file://") ? f.slice(7) : f),
    };
    const tests = [
        {
            description: `${task.id} — ${task.title}`,
            vars,
            ...(assertions.length > 0 ? { assert: assertions } : {}),
        },
    ];
    // Multi-turn support
    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;
}
