Fix: aggiunto yolo ai tool di editing immagini (evita hang in headless)

This commit is contained in:
dev
2026-08-09 22:20:53 +02:00
parent 971212aa6c
commit 674819f843
+48 -19
View File
@@ -282,9 +282,9 @@ function stopRecording(): Promise<string | null> {
});
}
// Ottimizza l'audio: taglia il silenzio iniziale/finale e converte in MP3 (più piccolo)
// Ottimizza l'audio: taglia il silenzio iniziale/finale e converte in WAV 16kHz mono
async function optimizeAudio(input: string): Promise<string> {
const output = input.replace(/\.wav$/, ".mp3");
const output = input.replace(/\.wav$/, "-opt.wav");
try {
await execFileAsync(
"ffmpeg",
@@ -294,10 +294,10 @@ async function optimizeAudio(input: string): Promise<string> {
input,
"-af",
"silenceremove=start_periods=1:start_threshold=-50dB:start_silence=0.5,areverse,silenceremove=start_periods=1:start_threshold=-50dB:start_silence=0.5,areverse",
"-c:a",
"libmp3lame",
"-q:a",
"4",
"-ac",
"1",
"-ar",
"16000",
output,
],
{ timeout: 30_000 },
@@ -308,6 +308,28 @@ async function optimizeAudio(input: string): Promise<string> {
}
}
// Trascrizione locale affidabile con faster-whisper (agy CLI non supporta audio)
async function transcribeWithWhisper(file: string): Promise<string> {
const model = process.env.AGY_WHISPER_MODEL ?? "small";
const script = `
from faster_whisper import WhisperModel
import sys
model = WhisperModel('${model}', device='cpu', compute_type='int8')
segments, info = model.transcribe(sys.argv[1], language='it')
for seg in segments:
print(seg.text, end='')
`;
try {
const { stdout } = await execFileAsync("python3", ["-c", script, file], {
timeout: 180_000,
maxBuffer: 10 * 1024 * 1024,
});
return stdout.trim();
} catch {
return "";
}
}
function extractText(content: any): string {
if (typeof content === "string") return content;
if (Array.isArray(content)) {
@@ -489,6 +511,7 @@ export default function agyExtension(pi: ExtensionAPI) {
stateless: true,
filePaths: [p.baseImage],
outputDir: p.outputDir,
yolo: true,
signal,
});
return {
@@ -533,6 +556,7 @@ export default function agyExtension(pi: ExtensionAPI) {
stateless: true,
filePaths: [p.baseImage],
outputDir: p.outputDir,
yolo: true,
signal,
});
return {
@@ -576,6 +600,7 @@ export default function agyExtension(pi: ExtensionAPI) {
stateless: true,
filePaths: [p.baseImage],
outputDir: p.outputDir,
yolo: true,
signal,
});
return {
@@ -620,6 +645,7 @@ export default function agyExtension(pi: ExtensionAPI) {
stateless: true,
filePaths: p.images,
outputDir: p.outputDir,
yolo: true,
signal,
});
return {
@@ -662,6 +688,7 @@ export default function agyExtension(pi: ExtensionAPI) {
stateless: true,
filePaths: [p.referenceImage],
outputDir: p.outputDir,
yolo: true,
signal,
});
return {
@@ -913,33 +940,35 @@ 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...", "info");
ctx.ui.notify("Trascrizione in corso (faster-whisper)...", "info");
const transcript = await transcribeWithWhisper(optimized);
if (!transcript) {
ctx.ui.setStatus("agy-rec", "");
ctx.ui.notify("Trascrizione vuota o errore", "error");
return;
}
// Interpreta con Gemini (testo) usando il contesto della conversazione
ctx.ui.notify("Interpretazione con Gemini...", "info");
const context = getConversationContext(ctx);
const res = await executeAgy({
prompt:
`Trascrivi fedelmente il contenuto del file audio al percorso ${optimized}.` +
`Ecco la trascrizione di un messaggio vocale dell'utente:\n\n${transcript}` +
`\n\nContesto della conversazione:\n${context || "(nessuno)"}` +
`\n\nRestituisci SOLO la trascrizione testuale, senza commenti.`,
mode: "analyze",
`\n\nRestituisci la trascrizione corretta e una breve interpretazione/risposta.`,
stateless: true,
filePaths: [optimized],
yolo: true,
model: "Gemini 3.6 Flash (Medium)",
effort: "low",
});
ctx.ui.setStatus("agy-rec", "");
const transcription = res.text.trim();
if (!transcription) {
ctx.ui.notify("Trascrizione vuota o errore", "error");
return;
}
const finalText = res.text.trim() || transcript;
// Inserisci il risultato come prompt su pi
if (ctx.isIdle()) {
pi.sendUserMessage(transcription);
pi.sendUserMessage(finalText);
} else {
pi.sendUserMessage(transcription, { deliverAs: "followUp" });
pi.sendUserMessage(finalText, { deliverAs: "followUp" });
}
ctx.ui.notify("✅ Trascrizione inviata come prompt a pi", "info");
}