import { createLogger } from "../../utils/logger/index.js";
import { init_logger } from "../../utils/logger.js";
import { getDefaultModelSync, init_providers, resolveModel } from "../../providers/index.js";
import { truncateAtSentenceBoundary } from "./sentence-boundary.js";
import { complete } from "@earendil-works/pi-ai";
//#region src/voice/tts/summarize.ts
init_providers();
init_logger();
const log = createLogger("TTS:Summarize");
const SUMMARIZE_TIMEOUT_MS = 45e3;
const SUMMARIZE_SYSTEM_PROMPT = `You are a text summarizer for a text-to-speech system.
Your task is to condense the given text while preserving the key information and meaning.

Rules:
1. Output ONLY the summarized text, no explanations or meta-commentary
2. Keep the summary in the same language as the input
3. Preserve key facts, numbers, names, and conclusions
4. Use natural, spoken language suitable for audio playback
5. Remove code blocks, URLs, markdown formatting, and technical syntax where possible
6. Keep the summary under the specified character limit
7. End with a complete sentence, never mid-sentence`;
function resolveSummarizeModel(config, modelRef) {
	const envRef = process.env.XOPC_TTS_SUMMARIZE_MODEL?.trim();
	const ref = modelRef?.trim() || envRef;
	if (ref) try {
		return resolveModel(ref);
	} catch {}
	for (const candidate of ["openai/gpt-4o-mini", "google/gemini-2.0-flash"]) try {
		return resolveModel(candidate);
	} catch {}
	return resolveModel(getDefaultModelSync(config));
}
function fallbackTruncate(text, maxLength) {
	const truncated = truncateAtSentenceBoundary(text, maxLength);
	return {
		summary: truncated,
		originalLength: text.length,
		summaryLength: truncated.length,
		wasSummarized: false
	};
}
/**
* Condense text for TTS using a small LLM pass; falls back to sentence-boundary truncation.
*/
async function summarizeForTts(options) {
	const { text, targetLength, config, modelRef, signal } = options;
	if (text.length <= targetLength) return {
		summary: text,
		originalLength: text.length,
		summaryLength: text.length,
		wasSummarized: false
	};
	const startTime = Date.now();
	try {
		const model = resolveSummarizeModel(config, modelRef);
		const userMsg = {
			role: "user",
			content: `${SUMMARIZE_SYSTEM_PROMPT}\n\n---\n\n${[
				`Summarize the following text to fit within ${targetLength} characters.`,
				`The summary will be read aloud by a text-to-speech system, so use natural spoken language.`,
				"",
				"---",
				"",
				text
			].join("\n")}`,
			timestamp: Date.now()
		};
		const timeoutSignal = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(SUMMARIZE_TIMEOUT_MS) : void 0;
		const mergedSignal = signal && timeoutSignal && typeof AbortSignal.any === "function" ? AbortSignal.any([signal, timeoutSignal]) : signal ?? timeoutSignal;
		const result = await complete(model, { messages: [userMsg] }, {
			maxTokens: Math.min(Math.ceil(targetLength / 2), 4096),
			temperature: .3,
			signal: mergedSignal
		});
		let out = "";
		if (Array.isArray(result.content)) {
			for (const c of result.content) if (c && typeof c === "object" && c.type === "text") out += String(c.text || "");
		}
		const summary = out.trim();
		if (!summary) {
			log.warn("Empty summary returned, falling back to truncation");
			return fallbackTruncate(text, targetLength);
		}
		const finalSummary = summary.length > targetLength ? truncateAtSentenceBoundary(summary, targetLength) : summary;
		log.info({
			originalLength: text.length,
			summaryLength: finalSummary.length,
			durationMs: Date.now() - startTime
		}, "Text summarized for TTS");
		return {
			summary: finalSummary,
			originalLength: text.length,
			summaryLength: finalSummary.length,
			wasSummarized: true
		};
	} catch (error) {
		const em = error instanceof Error ? error.message : String(error);
		log.warn({ errorMessage: em }, "Summarization failed, falling back to truncation");
		return fallbackTruncate(text, targetLength);
	}
}
//#endregion
export { summarizeForTts };

//# sourceMappingURL=summarize.js.map