import { join } from 'node:path';
import { resolveEffectiveProviderOptions, resolveEffectiveTeamLeaderPartProviderOptions, resolvePersonaProviderOptions, resolveProviderOptionsSources, } from '../../../infra/config/providerOptions.js';
import { assertProviderResolvedForCapabilitySensitiveOptions, resolveAllowedToolsForProvider, resolveMcpServersForProvider, resolvePartAllowedToolsForProvider, } from './engine-provider-options.js';
import { providerSupportsMaxTurns, providerSupportsStructuredOutput, } from '../../../infra/providers/provider-capabilities.js';
import { buildSessionKey } from '../session-key.js';
import { resolveStepProviderModel } from '../provider-resolution.js';
import { buildPhase1WorkflowMeta } from './workflow-meta.js';
export class OptionsBuilder {
    engineOptions;
    getCwd;
    getProjectCwd;
    getSessionId;
    getReportDir;
    getLanguage;
    getWorkflowSteps;
    getWorkflowName;
    getWorkflowDescription;
    getCurrentWorkflowStack;
    constructor(engineOptions, getCwd, getProjectCwd, getSessionId, getReportDir, getLanguage, getWorkflowSteps, getWorkflowName, getWorkflowDescription, getCurrentWorkflowStack = () => undefined) {
        this.engineOptions = engineOptions;
        this.getCwd = getCwd;
        this.getProjectCwd = getProjectCwd;
        this.getSessionId = getSessionId;
        this.getReportDir = getReportDir;
        this.getLanguage = getLanguage;
        this.getWorkflowSteps = getWorkflowSteps;
        this.getWorkflowName = getWorkflowName;
        this.getWorkflowDescription = getWorkflowDescription;
        this.getCurrentWorkflowStack = getCurrentWorkflowStack;
    }
    resolveEngineProviderModel() {
        return {
            provider: this.engineOptions.provider,
            providerSource: this.engineOptions.providerSource,
            model: this.engineOptions.model,
            modelSource: this.engineOptions.modelSource,
        };
    }
    resolveStepProviderModel(step, runtime) {
        if (runtime?.providerInfo) {
            return runtime.providerInfo;
        }
        const engineProviderInfo = this.resolveEngineProviderModel();
        const resolved = resolveStepProviderModel({
            step,
            provider: engineProviderInfo.provider,
            providerSource: engineProviderInfo.providerSource,
            model: engineProviderInfo.model,
            modelSource: engineProviderInfo.modelSource,
            personaProviders: this.engineOptions.personaProviders,
        });
        const provider = resolved.provider ?? engineProviderInfo.provider;
        const providerOptions = this.resolveMergedProviderOptions(step, provider, runtime);
        const providerOptionsSources = resolveProviderOptionsSources(step.providerOptions, resolvePersonaProviderOptions(this.engineOptions.personaProviders, step.personaDisplayName), this.engineOptions.providerOptions, this.engineOptions.providerOptionsOriginResolver, this.engineOptions.providerOptionsSource);
        return {
            provider,
            providerSource: resolved.providerSource ?? engineProviderInfo.providerSource,
            model: resolved.model ?? engineProviderInfo.model,
            modelSource: resolved.modelSource ?? engineProviderInfo.modelSource,
            providerOptions,
            providerOptionsSources: Object.keys(providerOptionsSources).length > 0
                ? providerOptionsSources
                : undefined,
        };
    }
    resolveMergedProviderOptions(step, resolvedProvider, runtime) {
        if (runtime?.providerInfo?.providerOptions && !runtime.teamLeaderPart) {
            return runtime.providerInfo.providerOptions;
        }
        const personaProviderOptions = resolvePersonaProviderOptions(this.engineOptions.personaProviders, step.personaDisplayName);
        if (runtime?.teamLeaderPart) {
            return resolveEffectiveTeamLeaderPartProviderOptions(this.engineOptions.providerOptionsSource, this.engineOptions.providerOptionsOriginResolver, this.engineOptions.providerOptions, step.providerOptions, resolvedProvider, runtime.teamLeaderPart.partAllowedTools, personaProviderOptions);
        }
        return resolveEffectiveProviderOptions(this.engineOptions.providerOptionsSource, this.engineOptions.providerOptionsOriginResolver, this.engineOptions.providerOptions, step.providerOptions, personaProviderOptions);
    }
    /** Build common RunAgentOptions shared by all phases */
    buildBaseOptions(step, mergedProviderOptions, runtime) {
        const steps = this.getWorkflowSteps();
        const currentIndex = steps.findIndex((currentStep) => currentStep.name === step.name);
        const currentPosition = currentIndex >= 0 ? `${currentIndex + 1}/${steps.length}` : '?/?';
        const { provider: resolvedProvider, model: resolvedModel } = this.resolveStepProviderModel(step, runtime);
        const providerOptions = mergedProviderOptions
            ?? this.resolveMergedProviderOptions(step, resolvedProvider, runtime);
        const workflowMeta = {
            workflowName: this.getWorkflowName(),
            workflowDescription: this.getWorkflowDescription(),
            currentStep: step.name,
            stepsList: steps,
            currentPosition,
        };
        const baseOptions = {
            cwd: this.getCwd(),
            projectCwd: this.getProjectCwd(),
            abortSignal: this.engineOptions.abortSignal,
            personaPath: step.personaPath,
            resolvedProvider,
            resolvedModel,
            permissionResolution: {
                stepName: step.name,
                requiredPermissionMode: step.requiredPermissionMode,
                providerProfiles: this.engineOptions.providerProfiles,
            },
            providerOptions,
            resolvedProviderOptions: providerOptions,
            language: this.getLanguage(),
            onStream: this.engineOptions.onStream,
            onPermissionRequest: this.engineOptions.onPermissionRequest,
            onAskUserQuestion: this.engineOptions.onAskUserQuestion,
            bypassPermissions: this.engineOptions.bypassPermissions,
            workflowMeta,
        };
        return baseOptions;
    }
    buildPhase1WorkflowMeta(workflowMeta, runtime) {
        if (!workflowMeta) {
            return undefined;
        }
        const processSafety = runtime?.teamLeaderPart?.processSafety
            ?? this.engineOptions.phase1ProcessSafetyByStep?.[workflowMeta.currentStep];
        return buildPhase1WorkflowMeta(workflowMeta, processSafety);
    }
    resolveSupportedMaxTurns(step, maxTurns, runtime) {
        const { provider: resolvedProvider } = this.resolveStepProviderModel(step, runtime);
        return providerSupportsMaxTurns(resolvedProvider) === false ? undefined : maxTurns;
    }
    /** Build RunAgentOptions for Phase 1 (main execution) */
    buildAgentOptions(step, runtime) {
        const { provider: resolvedProvider } = this.resolveStepProviderModel(step, runtime);
        const mergedProviderOptions = this.resolveMergedProviderOptions(step, resolvedProvider, runtime);
        assertProviderResolvedForCapabilitySensitiveOptions(resolvedProvider, {
            stepName: step.name,
            usesStructuredOutput: step.structuredOutput !== undefined,
        });
        const hasOutputContracts = step.outputContracts !== undefined && step.outputContracts.length > 0;
        const resolvedPartAllowedTools = resolvePartAllowedToolsForProvider(runtime?.teamLeaderPart?.partAllowedTools, resolvedProvider);
        const allowedTools = resolvedPartAllowedTools
            ?? resolveAllowedToolsForProvider(mergedProviderOptions, hasOutputContracts, step.edit, resolvedProvider);
        // Skip session resume when cwd !== projectCwd (worktree execution) to avoid cross-directory contamination
        const shouldResumeSession = !runtime?.fallback && step.session !== 'refresh' && this.getCwd() === this.getProjectCwd();
        const supportsStructuredOutput = providerSupportsStructuredOutput(resolvedProvider);
        const baseOptions = this.buildBaseOptions(step, mergedProviderOptions, runtime);
        return {
            ...baseOptions,
            workflowMeta: this.buildPhase1WorkflowMeta(baseOptions.workflowMeta, runtime),
            sessionId: shouldResumeSession ? this.getSessionId(buildSessionKey(step, runtime?.providerInfo?.provider)) : undefined,
            allowedTools,
            mcpServers: resolveMcpServersForProvider(step.mcpServers, resolvedProvider),
            outputSchema: supportsStructuredOutput === false ? undefined : step.structuredOutput?.schema,
        };
    }
    /** Build RunAgentOptions for session-resume phases (Phase 2, Phase 3) */
    buildResumeOptions(step, sessionId, overrides, runtime) {
        const maxTurns = this.resolveSupportedMaxTurns(step, overrides.maxTurns, runtime);
        return {
            ...this.buildBaseOptions(step, undefined, runtime),
            // Report/status phases are read-only regardless of step settings.
            permissionMode: 'readonly',
            sessionId,
            allowedTools: [],
            ...(maxTurns !== undefined ? { maxTurns } : {}),
        };
    }
    /** Build RunAgentOptions for Phase 2 retry with a new session */
    buildNewSessionReportOptions(step, overrides, runtime) {
        const maxTurns = this.resolveSupportedMaxTurns(step, overrides.maxTurns, runtime);
        return {
            ...this.buildBaseOptions(step, undefined, runtime),
            permissionMode: 'readonly',
            allowedTools: overrides.allowedTools,
            ...(maxTurns !== undefined ? { maxTurns } : {}),
        };
    }
    /** Build PhaseRunnerContext for Phase 2/3 execution */
    buildPhaseRunnerContext(state, lastResponse, updatePersonaSession, onPhaseStart, onPhaseComplete, onJudgeStage, iteration, runtime) {
        return {
            cwd: this.getCwd(),
            reportDir: join(this.getCwd(), this.getReportDir()),
            language: this.getLanguage(),
            interactive: this.engineOptions.interactive,
            lastResponse,
            workflowName: this.getWorkflowName(),
            observabilityRunId: this.engineOptions.observabilityRunId,
            observabilityEnabled: this.engineOptions.observability?.enabled === true,
            sanitizeObservabilityText: this.engineOptions.sanitizeObservabilityText,
            getCurrentWorkflowStack: this.getCurrentWorkflowStack,
            onStream: this.engineOptions.onStream,
            structuredCaller: this.requireStructuredCaller(),
            resolveStepProviderModel: (step) => this.resolveStepProviderModel(step, runtime),
            getSessionId: (persona) => state.personaSessions.get(persona),
            resolveSessionKey: (step) => buildSessionKey(step, runtime?.providerInfo?.provider),
            buildResumeOptions: (step, sessionId, overrides) => this.buildResumeOptions(step, sessionId, overrides, runtime),
            buildNewSessionReportOptions: (step, overrides) => this.buildNewSessionReportOptions(step, overrides, runtime),
            updatePersonaSession,
            onPhaseStart,
            onPhaseComplete,
            onJudgeStage,
            iteration,
        };
    }
    requireStructuredCaller() {
        if (!this.engineOptions.structuredCaller) {
            throw new Error('structuredCaller is required for phase runner context');
        }
        return this.engineOptions.structuredCaller;
    }
}
//# sourceMappingURL=OptionsBuilder.js.map