import { resolveEffectiveProviderOptions } from '../../../infra/config/providerOptions.js';
import { resolveWorkflowCallProviderModel } from '../provider-resolution.js';
import { getResumePointWorkflowReference, getWorkflowReference, } from '../workflow-reference.js';
import { WorkflowCallExecutor, applyWorkflowCallOverridesToPersonaProviders, } from './WorkflowCallExecutor.js';
export class WorkflowCallRunner {
    deps;
    executor;
    constructor(deps) {
        this.deps = deps;
        this.executor = new WorkflowCallExecutor(deps);
    }
    resolveParentWorkflowProviderContext() {
        const options = this.deps.getOptions();
        const parentConfig = this.deps.getConfig();
        const providerInfo = resolveWorkflowCallProviderModel({
            workflow: parentConfig,
            provider: this.deps.getOptions().provider,
            model: this.deps.getOptions().model,
        });
        const providerOptions = resolveEffectiveProviderOptions(options.providerOptionsSource, options.providerOptionsOriginResolver, options.providerOptions, parentConfig.providerOptions);
        return {
            provider: providerInfo.provider,
            model: providerInfo.model,
            providerOptions,
        };
    }
    resolveChildProviderModel(step) {
        const parentProviderInfo = this.resolveParentWorkflowProviderContext();
        if (!step.overrides) {
            return {
                provider: parentProviderInfo.provider,
                model: parentProviderInfo.model,
            };
        }
        return {
            provider: step.overrides.provider ?? parentProviderInfo.provider,
            model: step.overrides.model ?? (step.overrides.provider !== undefined ? undefined : parentProviderInfo.model),
        };
    }
    resolveRuntime(step) {
        return {
            providerInfo: this.resolveChildProviderModel(step),
        };
    }
    buildChildPersonaProviders(step) {
        return applyWorkflowCallOverridesToPersonaProviders(this.deps.getOptions().personaProviders, step.overrides);
    }
    buildWorkflowCallResponse(step, childState, abortKind, abortReason, returnValue) {
        const terminalStatus = childState.status === 'completed' ? 'COMPLETE' : 'ABORT';
        const matchedCondition = returnValue ?? terminalStatus;
        const finalContent = returnValue !== undefined
            ? childState.lastOutput?.content ?? returnValue
            : terminalStatus === 'COMPLETE'
                ? childState.lastOutput?.content ?? terminalStatus
                : abortKind === 'step_transition'
                    ? childState.lastOutput?.content ?? abortReason ?? terminalStatus
                    : abortReason ?? terminalStatus;
        const matchedRuleIndex = step.rules?.findIndex((rule) => rule.condition === matchedCondition);
        return {
            persona: step.name,
            status: 'done',
            content: finalContent,
            timestamp: new Date(),
            ...(matchedRuleIndex !== undefined && matchedRuleIndex >= 0 ? { matchedRuleIndex } : {}),
        };
    }
    async run(step, runtime = this.resolveRuntime(step)) {
        const parentConfig = this.deps.getConfig();
        const childWorkflow = this.deps.resolveWorkflowCall({
            parentWorkflow: parentConfig,
            identifier: step.call,
            stepName: step.name,
            projectCwd: this.deps.projectCwd,
            lookupCwd: this.deps.getCwd(),
        });
        if (!childWorkflow) {
            throw new Error(`workflow_call step "${step.name}" references unknown workflow "${step.call}"`);
        }
        if (childWorkflow.subworkflow?.callable !== true) {
            throw new Error(`workflow "${childWorkflow.name}" is not callable`);
        }
        const workflowChain = [
            ...this.deps.resumeStackPrefix.map((entry) => getResumePointWorkflowReference(entry)),
            getWorkflowReference(parentConfig),
        ];
        const childWorkflowRef = getWorkflowReference(childWorkflow);
        if (workflowChain.includes(childWorkflowRef)) {
            throw new Error(`Detected workflow_call cycle: ${[...workflowChain, childWorkflow.name].join(' -> ')}`);
        }
        const currentDepth = this.deps.resumeStackPrefix.length + 1;
        const nextDepth = currentDepth + 1;
        if (nextDepth > 5) {
            throw new Error(`workflow_call depth exceeds limit (5): ${childWorkflow.name}`);
        }
        const childProviderInfo = runtime.providerInfo ?? this.resolveRuntime(step).providerInfo;
        if (!childProviderInfo) {
            throw new Error(`workflow_call step "${step.name}" could not resolve provider context`);
        }
        const parentProviderContext = this.resolveParentWorkflowProviderContext();
        const childResult = await this.executor.execute({
            step,
            childWorkflow,
            childProviderInfo,
            parentProviderOptions: parentProviderContext.providerOptions,
            personaProviders: this.buildChildPersonaProviders(step),
        });
        const response = this.buildWorkflowCallResponse(step, childResult, childResult.abortKind, childResult.abortReason, childResult.returnValue);
        this.deps.state.stepOutputs.set(step.name, response);
        this.deps.state.lastOutput = response;
        this.deps.state.previousResponseSourcePath = undefined;
        return { response, instruction: '', providerInfo: childProviderInfo };
    }
}
//# sourceMappingURL=WorkflowCallRunner.js.map