diff --git a/extensions/index.ts b/extensions/index.ts index a020b45..4c7aa44 100644 --- a/extensions/index.ts +++ b/extensions/index.ts @@ -386,6 +386,48 @@ function getConversationContext(ctx: any, maxEntries = 8): string { } } +// Trascrizione via server locale ai.enne2.net (gemma4:E4B supporta audio) +async function transcribeWithEnne2(file: string): Promise { + const baseUrl = process.env.AGY_STT_URL ?? "https://ai.enne2.net"; + const model = process.env.AGY_STT_MODEL ?? "gemma4:E4B"; + try { + const b64 = fs.readFileSync(file).toString("base64"); + const body = { + model, + messages: [ + { + role: "user", + content: [ + { type: "text", text: "Trascrivi fedelmente il parlato in questo audio. Rispondi solo con la trascrizione." }, + { type: "input_audio", input_audio: { data: b64, format: "wav" } }, + ], + }, + ], + max_tokens: 500, + }; + const res = await fetch(`${baseUrl}/v1/chat/completions`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + signal: AbortSignal.timeout(90_000), + }); + if (!res.ok) return ""; + const data: any = await res.json(); + return data?.choices?.[0]?.message?.content?.trim() ?? ""; + } catch { + return ""; + } +} + +// Dispatcher: sceglie il backend di trascrizione (gemini | enne2) +async function transcribeAudio(file: string): Promise { + const backend = process.env.AGY_STT_BACKEND ?? "gemini"; + if (backend === "enne2" || backend === "local") { + return transcribeWithEnne2(file); + } + return transcribeWithGeminiAPI(file); +} + // --------------------------------------------------------------------------- // TTS via Gemini API (nessun engine esterno) // --------------------------------------------------------------------------- @@ -843,7 +885,7 @@ export default function agyExtension(pi: ExtensionAPI) { async execute(toolCallId, params, signal, onUpdate, ctx) { const p = params as any; onUpdate?.("agy_transcribe: trascrizione audio..."); - const transcript = await transcribeWithGeminiAPI(p.filePath); + const transcript = await transcribeAudio(p.filePath); if (!transcript) { return { content: [{ type: "text", text: "Trascrizione fallita: key Gemini mancante o errore API." }], @@ -1057,8 +1099,8 @@ export default function agyExtension(pi: ExtensionAPI) { ctx.ui.notify("Registrazione fermata, ottimizzazione audio...", "info"); const optimized = await optimizeAudio(file); - ctx.ui.notify("Trascrizione in corso (Gemini API)...", "info"); - const transcript = await transcribeWithGeminiAPI(optimized); + ctx.ui.notify("Trascrizione in corso...", "info"); + const transcript = await transcribeAudio(optimized); if (!transcript) { ctx.ui.setStatus("agy-rec", ""); ctx.ui.notify("Trascrizione vuota o errore (key Gemini mancante?)", "error");