import { DEFAULT_OPENAI_REALTIME_TRANSCRIPTION_MODEL, DEFAULT_OPENAI_TTS_MODEL, } from "./config.js";
import { OpenAIRealtimeTranscriptionSession } from "./realtime-transcription-session.js";
import { OpenAISTT } from "./stt.js";
import { OpenAITTS } from "./tts.js";
function resolveOpenAiCredentials(openaiConfig) {
    const openaiApiKey = openaiConfig?.apiKey;
    // Dictation override is a unit: when a custom baseURL is set, the
    // matching apiKey must come from the same block. Never pair a custom
    // dictation baseURL (e.g. Groq) with the top-level voice apiKey
    // (Seawork/OpenAI) — that would 401 against the wrong endpoint.
    const dictationApiKey = openaiConfig?.dictation?.baseURL
        ? openaiConfig?.dictation?.apiKey
        : (openaiConfig?.dictation?.apiKey ?? openaiApiKey);
    return {
        openaiSttApiKey: openaiConfig?.stt?.apiKey ?? openaiApiKey,
        openaiTtsApiKey: openaiConfig?.tts?.apiKey ?? openaiApiKey,
        openaiDictationApiKey: dictationApiKey,
    };
}
export function getOpenAiSpeechAvailability(openaiConfig) {
    const credentials = resolveOpenAiCredentials(openaiConfig);
    return {
        stt: Boolean(credentials.openaiSttApiKey),
        tts: Boolean(credentials.openaiTtsApiKey),
        dictationStt: Boolean(credentials.openaiDictationApiKey),
    };
}
export function validateOpenAiCredentialRequirements(params) {
    const { providers, logger, openaiConfig } = params;
    const openAiCredentials = resolveOpenAiCredentials(openaiConfig);
    const missingOpenAiCredentialsFor = [];
    if (providers.voiceStt.enabled !== false &&
        providers.voiceStt.provider === "openai" &&
        !openAiCredentials.openaiSttApiKey) {
        missingOpenAiCredentialsFor.push("voice.stt");
    }
    if (providers.voiceTts.enabled !== false &&
        providers.voiceTts.provider === "openai" &&
        !openAiCredentials.openaiTtsApiKey) {
        missingOpenAiCredentialsFor.push("voice.tts");
    }
    if (providers.dictationStt.enabled !== false &&
        providers.dictationStt.provider === "openai" &&
        !openAiCredentials.openaiDictationApiKey) {
        missingOpenAiCredentialsFor.push("dictation.stt");
    }
    if (missingOpenAiCredentialsFor.length > 0) {
        logger.error({
            requestedProviders: {
                dictationStt: providers.dictationStt.provider,
                voiceStt: providers.voiceStt.provider,
                voiceTts: providers.voiceTts.provider,
            },
            missingOpenAiCredentialsFor,
        }, "Invalid speech configuration: OpenAI provider selected but credentials are missing");
        throw new Error(`Missing OpenAI credentials for configured speech features: ${missingOpenAiCredentialsFor.join(", ")}`);
    }
}
export function initializeOpenAiSpeechServices(params) {
    const { providers, openaiConfig, existing, logger } = params;
    const openAiCredentials = resolveOpenAiCredentials(openaiConfig);
    let sttService = existing.sttService;
    let ttsService = existing.ttsService;
    let dictationSttService = existing.dictationSttService;
    const turnDetectionService = existing.turnDetectionService;
    const needsOpenAiStt = !sttService && providers.voiceStt.enabled !== false && providers.voiceStt.provider === "openai";
    const needsOpenAiTts = !ttsService && providers.voiceTts.enabled !== false && providers.voiceTts.provider === "openai";
    const needsOpenAiDictation = !dictationSttService &&
        providers.dictationStt.enabled !== false &&
        providers.dictationStt.provider === "openai";
    if ((needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation) &&
        (openAiCredentials.openaiSttApiKey ||
            openAiCredentials.openaiTtsApiKey ||
            openAiCredentials.openaiDictationApiKey)) {
        logger.info("OpenAI speech provider initialized");
        if (needsOpenAiStt && openAiCredentials.openaiSttApiKey) {
            const { apiKey: _sttApiKey, ...sttConfig } = openaiConfig?.stt ?? {};
            sttService = new OpenAISTT({
                apiKey: openAiCredentials.openaiSttApiKey,
                ...sttConfig,
            }, logger);
        }
        if (needsOpenAiTts && openAiCredentials.openaiTtsApiKey) {
            const { apiKey: _ttsApiKey, ...ttsConfig } = openaiConfig?.tts ?? {};
            ttsService = new OpenAITTS({
                apiKey: openAiCredentials.openaiTtsApiKey,
                voice: "alloy",
                model: DEFAULT_OPENAI_TTS_MODEL,
                responseFormat: "pcm",
                ...ttsConfig,
            }, logger);
        }
        const dictationApiKey = openAiCredentials.openaiDictationApiKey;
        if (needsOpenAiDictation && dictationApiKey) {
            // Dictation override scope: only openaiConfig.dictation.* applies here.
            // voiceStt / voiceTts / Realtime never see this baseURL or this model.
            const dictationBaseURL = openaiConfig?.dictation?.baseURL;
            const dictationModel = openaiConfig?.dictation?.model;
            // confidenceThreshold lives on the dictation block so it survives
            // the dictation-only deployment case (no top-level voice apiKey
            // means openaiConfig.stt is undefined).
            const dictationConfidenceThreshold = openaiConfig?.dictation?.confidenceThreshold;
            // When a custom baseURL is configured (e.g. Groq), the OpenAI Realtime
            // WebSocket endpoint is unavailable. Fall back to the REST
            // /audio/transcriptions path via OpenAISTT, which buffers PCM and
            // transcribes on commit.
            if (dictationBaseURL) {
                dictationSttService = new OpenAISTT({
                    apiKey: dictationApiKey,
                    baseURL: dictationBaseURL,
                    ...(dictationModel ? { model: dictationModel } : {}),
                    ...(dictationConfidenceThreshold !== undefined
                        ? { confidenceThreshold: dictationConfidenceThreshold }
                        : {}),
                }, logger);
            }
            else {
                dictationSttService = {
                    id: "openai",
                    createSession: ({ logger: sessionLogger, language, prompt }) => new OpenAIRealtimeTranscriptionSession({
                        apiKey: dictationApiKey,
                        logger: sessionLogger,
                        transcriptionModel: openaiConfig?.realtimeTranscriptionModel ??
                            DEFAULT_OPENAI_REALTIME_TRANSCRIPTION_MODEL,
                        ...(language ? { language } : {}),
                        ...(prompt ? { prompt } : {}),
                        turnDetection: null,
                    }),
                };
            }
        }
    }
    else if (needsOpenAiStt || needsOpenAiTts || needsOpenAiDictation) {
        logger.warn("OpenAI speech providers are configured but credentials are missing");
    }
    return {
        turnDetectionService,
        sttService,
        ttsService,
        dictationSttService,
    };
}
//# sourceMappingURL=runtime.js.map