import { join } from "node:path";
import { createHarnessTaskRunner, } from "../harness/create-harness-task-runner.js";
import { executeHarnessRun, } from "../harness/execute-harness-run.js";
import { createLoopState, evaluateLoopDecision, } from "./loop-controller.js";
import { persistLoopArtifacts, } from "./loop-artifacts.js";
export async function executeCompiledDag(input) {
    const runId = input.runId ?? input.compiled.runId;
    const eventRunDir = input.eventRunDir ?? join(input.root, ".omk", "runs", runId);
    const env = buildCompiledDagEnv(input, runId);
    const runner = input.runner ??
        (await createHarnessTaskRunner({
            root: input.root,
            runId,
            mode: input.mode ?? "parallel",
            providerPolicy: input.providerPolicy ?? "auto",
            env,
            useRuntimeBacked: input.useRuntimeBacked,
            runtimeOptions: input.runtimeOptions,
            providerOptions: {
                ...(input.providerOptions ?? {}),
                model: input.model ?? input.providerOptions?.model,
                mcpScope: input.mcpScope ?? input.providerOptions?.mcpScope ?? "project",
                skillsScope: input.skillsScope ?? input.providerOptions?.skillsScope ?? "project",
                hooksScope: input.hooksScope ?? input.providerOptions?.hooksScope ?? "project",
                eventRunDir,
            },
            factories: input.factories,
        }));
    const run = await executeHarnessRun({
        root: input.root,
        runId,
        dag: input.compiled.dag,
        runner,
        env,
        workers: input.compiled.workerCount,
        approvalPolicy: input.approvalPolicy ?? "block",
        timeoutPreset: input.timeoutPreset,
        nodeTimeoutMs: input.nodeTimeoutMs,
        runTimeoutMs: input.runTimeoutMs,
        heartbeatIntervalMs: input.heartbeatIntervalMs,
        resumeFromState: input.resumeFromState,
        eventRunDir,
        ensemble: input.ensemble,
        signal: input.signal,
        onStateChange: input.onStateChange,
        onNodeStart: input.onNodeStart,
        onNodeComplete: input.onNodeComplete,
    });
    const loopDecision = evaluateLoopDecision({
        runId,
        inputId: input.compiled.inputId,
        runState: run.state,
        requestedAction: input.loop?.requestedAction,
        iteration: input.loop?.iteration,
        maxIterations: input.loop?.maxIterations,
        now: input.loop?.now,
    });
    const loopState = createLoopState({
        runId,
        inputId: input.compiled.inputId,
        runState: run.state,
        decision: loopDecision,
        parentRunId: input.loop?.parentRunId,
        maxIterations: input.loop?.maxIterations,
        now: input.loop?.now,
    });
    const shouldPersistLoop = input.loop?.persist ?? true;
    const loopArtifacts = shouldPersistLoop
        ? await persistLoopArtifacts(loopState, loopDecision, {
            root: input.root,
            nextInputEnvelope: input.loop?.nextInputEnvelope,
        })
        : undefined;
    return { run, loopDecision, loopState, loopArtifacts };
}
function buildCompiledDagEnv(input, runId) {
    return {
        ...(input.env ?? {}),
        OMK_RUN_ID: runId,
        OMK_INPUT_ID: input.compiled.inputId,
        OMK_FLOW: input.env?.OMK_FLOW ?? "compiled-dag",
        OMK_DAG_EXECUTION_STRATEGY: input.compiled.executionStrategy,
        OMK_DAG_COMPILED_AT: input.compiled.compiledAt,
        OMK_WORKERS: String(input.compiled.workerCount),
        ...(input.model ? { OMK_PROVIDER_MODEL: input.model } : {}),
        ...(input.mcpScope ? { OMK_MCP_SCOPE: input.mcpScope } : {}),
    };
}
