import { decodeInboundAttachmentBase64, resolveSafeInboundFilePath } from "./inbound-persist.js";
import { DEFAULT_STT_CONFIG } from "../../voice/stt/types.js";
import { transcribe } from "../../voice/stt/transcribe-core.js";
import { isSTTAvailable } from "../../voice/stt/availability.js";
import "../../voice/stt/index.js";
import { readFile } from "fs/promises";
//#region src/channels/attachments/voice-stt-webchat.ts
/**
* STT for webchat voice attachments: merge transcripts into user text and track inbound voice for TTS trigger.
*/
const STT_MAX_BYTES = 25 * 1024 * 1024;
function mergeSttProviders(base, patch) {
	if (!base && !patch) return void 0;
	const merged = { ...base ?? {} };
	for (const [id, slice] of Object.entries(patch ?? {})) merged[id] = {
		...merged[id] ?? {},
		...slice
	};
	return merged;
}
function mergeSttConfigFromAppConfig(stt, toolsMedia) {
	const p = stt ?? {};
	return {
		...DEFAULT_STT_CONFIG,
		...p,
		providers: mergeSttProviders(DEFAULT_STT_CONFIG.providers, p.providers),
		fallback: {
			...DEFAULT_STT_CONFIG.fallback,
			...p.fallback
		},
		...toolsMedia?.models?.length ? { sharedModels: toolsMedia.models } : {}
	};
}
function isVoiceLikeAttachment(att) {
	if (att.type === "voice") return true;
	return (att.mimeType?.toLowerCase() ?? "").startsWith("audio/");
}
async function mergeVoiceTranscriptsIntoUserText(attachmentRoots, prepared, userText, sttConfig, opts) {
	if (!prepared?.length) return {
		text: userText,
		inboundVoice: false,
		voiceTranscripts: []
	};
	if (!prepared.some(isVoiceLikeAttachment)) return {
		text: userText,
		inboundVoice: false,
		voiceTranscripts: []
	};
	if (opts?.skipVoiceTranscription === true) return {
		text: userText,
		inboundVoice: true,
		voiceTranscripts: []
	};
	if (!isSTTAvailable(sttConfig)) return {
		text: userText,
		inboundVoice: true,
		voiceTranscripts: []
	};
	const transcripts = [];
	for (const att of prepared) {
		if (!isVoiceLikeAttachment(att)) continue;
		let buf = null;
		if (att.workspaceRelativePath) {
			const abs = resolveSafeInboundFilePath(attachmentRoots, att.workspaceRelativePath);
			if (abs) try {
				buf = await readFile(abs);
			} catch {
				buf = null;
			}
		} else if (att.data) try {
			buf = decodeInboundAttachmentBase64(att.data);
		} catch {
			buf = null;
		}
		if (!buf || buf.length === 0) {
			transcripts.push("[Voice: empty]");
			continue;
		}
		if (buf.length > STT_MAX_BYTES) {
			transcripts.push("[Voice: file too large]");
			continue;
		}
		try {
			const r = await transcribe(buf, sttConfig, { language: sttConfig.provider === "alibaba" ? "zh" : void 0 });
			transcripts.push(r.text.trim() || "[Voice: no speech detected]");
		} catch {
			transcripts.push("[STT failed]");
		}
	}
	return {
		text: [transcripts.filter(Boolean).join("\n"), userText.trim()].filter(Boolean).join("\n\n") || userText,
		inboundVoice: true,
		voiceTranscripts: transcripts
	};
}
//#endregion
export { isVoiceLikeAttachment, mergeSttConfigFromAppConfig, mergeVoiceTranscriptsIntoUserText };

//# sourceMappingURL=voice-stt-webchat.js.map