Fix output vuoto: usa --output-format json per catturare la risposta quando piped (bug #76)
This commit is contained in:
+50
-6
@@ -104,14 +104,27 @@ async function runAgy(
|
|||||||
signal?: AbortSignal,
|
signal?: AbortSignal,
|
||||||
): Promise<RunResult> {
|
): Promise<RunResult> {
|
||||||
const bin = findAgy();
|
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 {
|
try {
|
||||||
const { stdout, stderr } = await execFileAsync(bin, args, {
|
const { stdout, stderr } = await execFileAsync(bin, fullArgs, {
|
||||||
timeout: timeoutMs,
|
timeout: timeoutMs,
|
||||||
maxBuffer: 20 * 1024 * 1024,
|
maxBuffer: 20 * 1024 * 1024,
|
||||||
signal,
|
signal,
|
||||||
env: { ...process.env, PATH: `${path.join(os.homedir(), ".local", "bin")}:${process.env.PATH ?? ""}` },
|
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) {
|
} catch (err: any) {
|
||||||
const code = typeof err.code === "number" ? err.code : 1;
|
const code = typeof err.code === "number" ? err.code : 1;
|
||||||
return {
|
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 {
|
function extractText(content: any): string {
|
||||||
if (typeof content === "string") return content;
|
if (typeof content === "string") return content;
|
||||||
if (Array.isArray(content)) {
|
if (Array.isArray(content)) {
|
||||||
@@ -871,17 +910,22 @@ export default function agyExtension(pi: ExtensionAPI) {
|
|||||||
return;
|
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 context = getConversationContext(ctx);
|
||||||
const res = await executeAgy({
|
const res = await executeAgy({
|
||||||
prompt:
|
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\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",
|
mode: "analyze",
|
||||||
stateless: true,
|
stateless: true,
|
||||||
filePaths: [file],
|
filePaths: [optimized],
|
||||||
yolo: true,
|
yolo: true,
|
||||||
|
model: "Gemini 3.6 Flash (Medium)",
|
||||||
|
effort: "low",
|
||||||
});
|
});
|
||||||
ctx.ui.setStatus("agy-rec", "");
|
ctx.ui.setStatus("agy-rec", "");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user