Fix output vuoto: usa --output-format json per catturare la risposta quando piped (bug #76)

This commit is contained in:
dev
2026-08-09 21:04:15 +02:00
parent ef7071cea5
commit 971212aa6c
+50 -6
View File
@@ -104,14 +104,27 @@ async function runAgy(
signal?: AbortSignal,
): Promise<RunResult> {
const bin = findAgy();
// --output-format json: agy non scrive nulla su stdout quando è piped/redirected
// (bug #76). Il formato json emette un oggetto con la risposta in .response.
const fullArgs = [...args, "--output-format", "json"];
try {
const { stdout, stderr } = await execFileAsync(bin, args, {
const { stdout, stderr } = await execFileAsync(bin, fullArgs, {
timeout: timeoutMs,
maxBuffer: 20 * 1024 * 1024,
signal,
env: { ...process.env, PATH: `${path.join(os.homedir(), ".local", "bin")}:${process.env.PATH ?? ""}` },
});
return { output: stdout, error: stderr || null, exitCode: 0 };
// estrai la risposta dal JSON
let output = stdout;
try {
const parsed = JSON.parse(stdout);
if (parsed && typeof parsed.response === "string") {
output = parsed.response;
}
} catch {
/* non-JSON: usa stdout grezzo */
}
return { output, error: stderr || null, exitCode: 0 };
} catch (err: any) {
const code = typeof err.code === "number" ? err.code : 1;
return {
@@ -269,6 +282,32 @@ function stopRecording(): Promise<string | null> {
});
}
// Ottimizza l'audio: taglia il silenzio iniziale/finale e converte in MP3 (più piccolo)
async function optimizeAudio(input: string): Promise<string> {
const output = input.replace(/\.wav$/, ".mp3");
try {
await execFileAsync(
"ffmpeg",
[
"-y",
"-i",
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",
output,
],
{ timeout: 30_000 },
);
return output;
} catch {
return input; // fallback al file originale
}
}
function extractText(content: any): string {
if (typeof content === "string") return content;
if (Array.isArray(content)) {
@@ -871,17 +910,22 @@ export default function agyExtension(pi: ExtensionAPI) {
return;
}
ctx.ui.notify("Registrazione fermata, trascrizione in corso...", "info");
ctx.ui.notify("Registrazione fermata, ottimizzazione audio...", "info");
const optimized = await optimizeAudio(file);
ctx.ui.notify("Trascrizione in corso...", "info");
const context = getConversationContext(ctx);
const res = await executeAgy({
prompt:
`Trascrivi e interpreta il file audio al percorso ${file}.` +
`Trascrivi fedelmente il contenuto del file audio al percorso ${optimized}.` +
`\n\nContesto della conversazione:\n${context || "(nessuno)"}` +
`\n\nRestituisci la trascrizione fedele e una breve interpretazione.`,
`\n\nRestituisci SOLO la trascrizione testuale, senza commenti.`,
mode: "analyze",
stateless: true,
filePaths: [file],
filePaths: [optimized],
yolo: true,
model: "Gemini 3.6 Flash (Medium)",
effort: "low",
});
ctx.ui.setStatus("agy-rec", "");