import { WorkflowEngine, createDenyAskUserQuestionHandler } from '../../../core/workflow/index.js';
import { detectRuleIndex } from '../../../shared/utils/ruleIndex.js';
import { createDefaultSystemStepServices } from '../../../infra/workflow/system/DefaultSystemStepServices.js';
import { createDefaultStructuredOutputNormalizers } from '../../../infra/workflow/structured-output/followup-task-normalizer.js';
import { AbortHandler } from './abortHandler.js';
import { createIterationLimitHandler, createUserInputHandler } from './iterationLimitHandler.js';
import { createWorkflowExecutionBootstrap } from './workflowExecutionBootstrap.js';
import { createWorkflowExecutionContext, createWorkflowCallResolver } from './workflowExecutionContext.js';
import { bindWorkflowExecutionEvents } from './workflowExecutionEvents.js';
import { createLogger } from '../../../shared/utils/index.js';
const log = createLogger('workflow-execution');
function resolveCurrentTaskContext(options, runSlug) {
    return {
        issueNumber: options.currentTaskIssueNumber,
        runSlug,
    };
}
function requireFiniteWorkflowMaxSteps(workflowConfig) {
    if (typeof workflowConfig.maxSteps !== 'number') {
        throw new Error('Iteration limit handling requires finite workflow maxSteps');
    }
    return workflowConfig.maxSteps;
}
function resolvePhase1ProcessSafetyByStep(workflowConfig, parentRunPid) {
    if (workflowConfig.name !== 'takt-default'
        || !workflowConfig.steps.some((step) => step.name === 'implement')) {
        return undefined;
    }
    return {
        implement: {
            protectedParentRunPid: parentRunPid,
        },
    };
}
export async function executeWorkflow(workflowConfig, task, cwd, options) {
    return executeWorkflowInternal(workflowConfig, task, cwd, options);
}
export async function executeWorkflowForRun(workflowConfig, task, cwd, options, runContext) {
    return executeWorkflowInternal(workflowConfig, task, cwd, options, runContext);
}
async function executeWorkflowInternal(workflowConfig, task, cwd, options, runContext) {
    const parentRunPid = process.pid;
    const bootstrap = await createWorkflowExecutionBootstrap(workflowConfig, task, cwd, options);
    const workflowExecutionContext = createWorkflowExecutionContext(workflowConfig, options.projectCwd);
    const phase1ProcessSafetyByStep = resolvePhase1ProcessSafetyByStep(workflowConfig, parentRunPid);
    let engine = null;
    let eventBridge;
    const getCurrentWorkflowStack = () => {
        if (!engine || typeof engine.getResumePoint !== 'function') {
            return undefined;
        }
        return engine.getResumePoint()?.stack;
    };
    const buildResumePointForStep = (stepName) => {
        if (!engine || typeof engine.buildResumePointForStepName !== 'function') {
            return undefined;
        }
        return engine.buildResumePointForStepName(stepName);
    };
    const getLatestResumePoint = () => {
        if (!engine || typeof engine.getResumePoint !== 'function') {
            return undefined;
        }
        return engine.getResumePoint();
    };
    const iterationLimitHandler = createIterationLimitHandler(bootstrap.out, bootstrap.displayRef, bootstrap.shouldNotifyIterationLimit, (request) => {
        const workflowMaxSteps = requireFiniteWorkflowMaxSteps(bootstrap.effectiveWorkflowConfig);
        const resumePoint = getLatestResumePoint()
            ?? buildResumePointForStep(request.currentStep)
            ?? eventBridge?.state.lastResumePoint;
        eventBridge.state.exceededInfo = {
            currentStep: request.currentStep,
            newMaxSteps: request.maxSteps + workflowMaxSteps,
            currentIteration: request.currentIteration,
            ...(resumePoint ? { resumePoint } : {}),
        };
    });
    const onIterationLimit = runContext?.ignoreIterationLimit === true
        ? undefined
        : iterationLimitHandler;
    const onUserInput = bootstrap.interactiveUserInput
        ? createUserInputHandler(bootstrap.out, bootstrap.displayRef)
        : undefined;
    const runAbortController = new AbortController();
    const abortHandler = new AbortHandler({
        externalSignal: options.abortSignal,
        internalController: runAbortController,
        getEngine: () => engine,
    });
    try {
        engine = new WorkflowEngine(bootstrap.effectiveWorkflowConfig, cwd, task, {
            abortSignal: runAbortController.signal,
            onStream: bootstrap.providerEventLogger.wrapCallback(bootstrap.streamHandler),
            onUserInput,
            initialSessions: bootstrap.savedSessions,
            onSessionUpdate: bootstrap.sessionUpdateHandler,
            onIterationLimit,
            onAskUserQuestion: createDenyAskUserQuestionHandler(),
            ignoreIterationLimit: runContext?.ignoreIterationLimit === true,
            projectCwd: options.projectCwd,
            observability: bootstrap.observability,
            observabilityRunId: bootstrap.runSlug,
            sanitizeObservabilityText: bootstrap.sanitizeObservabilityText,
            language: options.language,
            provider: bootstrap.currentProvider,
            providerSource: bootstrap.currentProviderSource,
            model: bootstrap.configuredModel,
            modelSource: bootstrap.configuredModelSource,
            rateLimitFallback: bootstrap.effectiveWorkflowConfig.rateLimitFallback,
            providerOptions: options.providerOptions,
            providerOptionsSource: options.providerOptionsSource,
            providerOptionsOriginResolver: options.providerOptionsOriginResolver,
            personaProviders: options.personaProviders,
            providerProfiles: options.providerProfiles,
            interactive: bootstrap.interactiveUserInput,
            detectRuleIndex,
            structuredCaller: bootstrap.structuredCaller,
            structuredOutputNormalizers: createDefaultStructuredOutputNormalizers(),
            startStep: options.startStep,
            retryNote: options.retryNote,
            resumePoint: options.resumePoint,
            reportDirName: bootstrap.runSlug,
            taskPrefix: options.taskPrefix,
            taskColorIndex: options.taskColorIndex,
            initialIteration: options.initialIterationOverride,
            currentTask: resolveCurrentTaskContext(options, bootstrap.runSlug),
            phase1ProcessSafetyByStep,
            systemStepServicesFactory: createDefaultSystemStepServices,
            workflowCallResolver: createWorkflowCallResolver(workflowExecutionContext),
        });
        eventBridge = bindWorkflowExecutionEvents({
            engine,
            workflowConfig: bootstrap.effectiveWorkflowConfig,
            task,
            projectCwd: options.projectCwd,
            currentProvider: bootstrap.currentProvider,
            configuredModel: bootstrap.configuredModel,
            out: bootstrap.out,
            prefixWriter: bootstrap.prefixWriter,
            displayRef: bootstrap.displayRef,
            handlerRef: bootstrap.handlerRef,
            providerEventLogger: bootstrap.providerEventLogger,
            usageEventLogger: bootstrap.usageEventLogger,
            analyticsEmitter: bootstrap.analyticsEmitter,
            sessionLogger: bootstrap.sessionLogger,
            runMetaManager: bootstrap.runMetaManager,
            ndjsonLogPath: bootstrap.ndjsonLogPath,
            shouldNotifyWorkflowComplete: bootstrap.shouldNotifyWorkflowComplete,
            shouldNotifyWorkflowAbort: bootstrap.shouldNotifyWorkflowAbort,
            writeTraceReportOnce: bootstrap.writeTraceReportOnce,
            getCurrentWorkflowStack,
            initialResumePoint: options.resumePoint,
            sessionLog: bootstrap.sessionLog,
        });
        abortHandler.install();
        const finalState = await engine.run();
        return {
            success: finalState.status === 'completed',
            reason: eventBridge.state.abortReason,
            lastStep: eventBridge.state.lastStepName,
            lastMessage: eventBridge.state.lastStepContent,
            exceeded: eventBridge.state.exceededInfo != null,
            ...(eventBridge.state.exceededInfo ? { exceededInfo: eventBridge.state.exceededInfo } : {}),
        };
    }
    catch (error) {
        if (!bootstrap.runMetaManager.isFinalized) {
            eventBridge?.syncLatestResumePoint();
            bootstrap.runMetaManager.finalize('aborted');
        }
        throw error;
    }
    finally {
        bootstrap.prefixWriter?.flush();
        abortHandler.cleanup();
        try {
            await bootstrap.observabilityHandle.shutdown();
        }
        catch (error) {
            log.warn('Observability shutdown failed', {
                error: error instanceof Error ? error.message : String(error),
            });
        }
    }
}
//# sourceMappingURL=workflowExecution.js.map