Files
agy-pi/docs/vocal-workflow.md
enne2 e1acad4a27 fix: rimappa shortcut annulla registrazione da Esc a Ctrl+Esc
Esc è riservato alla built-in app.interrupt di pi: la shortcut veniva
scartata con warning 'conflicts with built-in shortcut'. Rimossa anche
la registrazione ridondante 'esc' (stesso tasto fisico). Aggiornati
messaggi di stato e documentazione.
2026-08-11 22:33:07 +02:00

123 lines
5.7 KiB
Markdown

# Workflow Vocale (Registrazione F12)
L'estensione `agy-pi` trasforma `pi` in un assistente multimodale completo grazie all'integrazione di un workflow di input vocale nativo attivabile con il tasto **F12** o tramite il comando `/agy:record`.
---
## Diagramma di Flusso della Registrazione Vocale
```mermaid
flowchart TD
A[Pressione F12] --> B{Recording in corso?}
B -- No --> C[startRecording: Spawn ffmpeg]
C --> D[Play Sound: Start PowerUp]
C --> E[Avvia Timer TUI Status]
B -- Yes --> F[stopRecording: Send SIGINT]
F --> G[Play Sound: Stop Deactivate]
F --> H[optimizeAudio: silenceremove ffmpeg]
H --> I[audioHasSpeech: volumedetect check]
I -- Parlato Assente --> J[Errore: Silenzio o volume basso]
I -- Parlato Presente --> K[transcribeAudio: API Gemini / enne2]
K --> L[Legge editorText da TUI]
L --> M[Unisce Voce + Testo Editor + Contesto]
M --> N[executeAgy: plan-first, genera PIANO]
N --> N1{vocalPlanningMode?}
N1 -- true --> N2[Overlay TUI: trascrizione + piano]
N2 --> N3[Enter=Esegui | Esc=Annulla | E=Modifica | F12=Registra]
N3 -- Enter --> O[Svuota editorText TUI]
N3 -- Esc --> X[Annulla: playSound cancel]
N1 -- false --> O
O --> P[sendUserMessage prompt a pi]
P --> Q[Play Sound: Done Chime & TTS Notify]
```
---
## Fasi del Workflow Vocale
### 1. Avvio & Cattura dell'Audio (`startRecording`)
Alla pressione del tasto **F12**:
- Viene avviato un sottoprocesso `ffmpeg` che cattura dal dispositivo PulseAudio predefinito (`-f pulse -i default`).
- L'audio viene campionato a 16.000 Hz in mono (`-ac 1 -ar 16000`).
- Viene attivato un timer TUI che aggiorna dinamicamente lo stato di `pi`:
`🔴 REGISTRAZIONE... 00:14 / 02:00 (Ctrl+Esc per annullare)`
### 2. Feedback Acustici Sci-Fi Procedurali (`playSound`)
Per non dipendere da file audio esterni, i suoni di feedback vengono generati proceduralmente usando il filtro `aevalsrc` di `ffmpeg` e riprodotti tramite `paplay` (fallback su `aplay` o `ffplay`):
- **`start`**: Sweep di frequenza ascendente ($440 \text{ Hz} \to 1760 \text{ Hz}$).
- **`stop`**: Sweep di frequenza discendente ($1200 \text{ Hz} \to 300 \text{ Hz}$).
- **`cancel`**: Suono modulato a bassa frequenza ($350 \text{ Hz} \to 200 \text{ Hz}$).
- **`timeout`**: Pulsazione bi-tono di avviso radar.
- **`done`**: Arpeggio scintillante acuto ($C_5 - E_5 - G_5$).
### 3. Ottimizzazione & Rilevamento del Parlato
Prima della trascrizione:
- **`optimizeAudio()`**: Utilizza il filtro `silenceremove` di `ffmpeg` per eliminare il silenzio iniziale e finale con soglia a `-50dB`.
- **`audioHasSpeech()`**: Esegue una passata `volumedetect`. Se `max_volume` è inferiore a `-35dB` o `mean_volume` è sotto a `-45dB`, la registrazione viene classificata come silenzio, evitando di effettuare chiamate API inutili ed evitando allucinazioni da parte del modello STT.
### 4. Compressione & Inizio Trascrizione
- L'audio ottimizzato WAV viene convertito al volo in formato **Opus/OGG** (`libopus` a 16kbps). Questo riduce il payload di oltre il 60%, evitando errori `HTTP 413 Payload Too Large`.
- Invio della richiesta alle API Gemini (`gemini-3.5-flash`) o al server `enne2`.
### 5. Multimodalità Ibrida (Voce + Testo Editor)
Una funzionalità distintiva di `agy-pi` è la capacità di fondere il testo digitato dall'utente prima di premere F12 con l'audio registrato:
```typescript
const editorText = (ctx.ui.getEditorText?.() ?? "").trim();
```
Se l'utente ha scritto una nota o del codice nell'editor di `pi` e poi preme **F12** per aggiungere un commento vocale, l'estensione unisce i due input in un unico prompt interpretativo per Gemini:
$$\text{Prompt Finale} = \text{Trascrizione Vocale} + \text{Testo Editor} + \text{Contesto Conversazione}$$
Dopo l'invio riuscito, l'editor dell'interfaccia TUI viene svuotato automaticamente (`setEditorText("")`) per evitare duplicazioni.
### 6. Invio del Prompt all'Agente `pi`
Se `pi` è in stato di attesa (`isIdle()`), l'input viene inviato immediatamente tramite `sendUserMessage(finalText)`. Se `pi` sta eseguendo un altro task, viene accodato come `followUp`.
### 7. Workflow a 2 Fasi con Piano + Conferma (`vocalPlanningMode`)
Con `vocalPlanningMode=true` (default) il flusso di interpretazione vocale è
**plan-first**: Gemini produce **solo** la trascrizione corretta e un **piano
d'azione sintetico** (nessuna esecuzione). Questo evita che l'interpretazione
avvii autonomamente loop agentici o modifiche a sorpresa a causa di errori di STT.
L'interpretazione usa un **framing inter-agent**: Gemini agisce come **analista
tecnico/middleware** che scrive un briefing per l'orchestratore (NON risponde
all'utente), in **JSON strutturato**:
```json
{
"trascrizione_corretta": "...",
"intent_analisi": "...",
"note_per_agent": "...",
"azioni_raccomandate": ["..."],
"prompt_utente_pulito": "...",
"ricerca_necessaria": true/false,
"suggerimenti_ricerca": ["..."]
}
```
Il campo `prompt_utente_pulito` diventa il prompt finale per l'orchestratore. Se
`ricerca_necessaria=true`, al prompt finale viene aggiunta una **nota che
indica all'agente successivo di usare la ricerca web (Perplexity)** per
verificare best practices, versioni o documentazione aggiornate.
Poi un **overlay TUI** mostra trascrizione + piano e attende la conferma:
```
🎙️ Conferma vocale
Trascrizione: "Aggiorna i docs..."
📋 Piano proposto: ...
Enter esegui • Esc annulla • E modifica • F12 registra di nuovo
```
- **Enter** → esegue (invia il risultato a pi)
- **Esc** → annulla, nessuna azione
- **E** → modifica il testo del piano manualmente
- **F12** → registra di nuovo
Per tornare all'esecuzione diretta (autonomia piena):
`/agy:config set vocalPlanningMode false`.