mirror of
https://github.com/R0m1k3/EveFlow.git
synced 2026-10-16 11:47:55 +02:00
fix: liaison « dégradé », réponses vides, transcriptions parasites, voix masculine (v2.4.0.1) (#15)
- Liaison Hermes : l'échec de l'API des crons (/api/jobs absente ou refusée) ne fait plus passer la liaison en « dégradé » ; l'onglet Crons affiche la raison. Les états « healthy / ready / ok » sont reconnus et un état « degraded » détaille les contrôles en échec. - Chat completions : une réponse sans fragment n'affiche plus « … » ; le corps est relu (JSON non streamé, erreur renvoyée en HTTP 200) et sinon l'erreur explicite « Réponse vide de Hermes » est affichée avec le début du corps. - Voix : transcriptions parasites de Whisper (« (cliquant) », « *Claire* », « [Musique] », génériques de sous-titres) ignorées au lieu d'être envoyées. - Préférence de voix masculine / féminine (Paramètres → Voix), appliquée à tous les moteurs : Piper Tom / Pierre en local (téléchargement automatique), onyx / nova en API OpenAI, Paul / Hortense en voix Windows. Genre des voix du catalogue déduit des libellés. Tests : 42 tests unitaires (santé, récupération de réponse, filtre de bruit, préférence de voix) ; e2e Electron inchangé et vert. Claude-Session: https://claude.ai/code/session_017Wn5VX9HNbJ7N54hR24u9Y Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
6fc38d335b
commit
6d3073b083
19 files changed
+350
-14
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import { Fragment, useEffect, useState } from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import {
|
||||
AlertTriangle,
|
||||
Wrench, CalendarClock, Sparkles, Layers, History, Play, Pause, Trash2, Pencil, Plus, Save, X, RefreshCw,
|
||||
CheckCircle2, XCircle, Loader2, Bot, Cpu, GitBranch, Webhook, FolderOpen
|
||||
} from 'lucide-react';
|
||||
@@ -41,6 +42,7 @@ function ActivityTab() {
|
||||
|
||||
function JobsTab() {
|
||||
const jobs = useHermes((s) => s.jobs);
|
||||
const jobsError = useHermes((s) => s.jobsError);
|
||||
const busy = useHermes((s) => s.busy);
|
||||
const lastSyncAt = useHermes((s) => s.lastSyncAt);
|
||||
const refreshJobs = useHermes((s) => s.refreshJobs);
|
||||
@@ -95,8 +97,9 @@ function JobsTab() {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{jobsError && <div className="test-result fail" style={{ marginBottom: 8 }}><AlertTriangle size={13} /> Crons indisponibles : {jobsError}</div>}
|
||||
{jobs.length === 0 ? (
|
||||
<div className="empty">Aucun cron Hermes. Créez une mission planifiée en langage naturel.</div>
|
||||
<div className="empty">{jobsError ? 'La liaison Hermes reste utilisable ; seule la planification est indisponible.' : 'Aucun cron Hermes. Créez une mission planifiée en langage naturel.'}</div>
|
||||
) : (
|
||||
<div className="list">
|
||||
{jobs.map((job) => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { bridge } from '../../lib/bridge';
|
||||
import { HermesClient } from '../../services/hermes/client';
|
||||
import { listSystemVoices } from '../../services/voice/tts';
|
||||
import { speech } from '../../services/voice/speech';
|
||||
import { ensurePreferredVoice } from '../../services/voice/voicePreference';
|
||||
import { listMicrophones } from '../../services/voice/capture';
|
||||
import { transcribeWav } from '../../services/voice/stt';
|
||||
import { encodeWav } from '../../services/voice/wav';
|
||||
@@ -357,6 +358,14 @@ export function SettingsDrawer({ onClose }: Props) {
|
||||
|
||||
{section === 'speech' && (
|
||||
<div className="card">
|
||||
<div className="field">
|
||||
<label>Voix</label>
|
||||
<div className="segmented">
|
||||
<button className={(settings.speech.voiceGender ?? 'male') === 'male' ? 'active' : ''} onClick={() => { update({ speech: { voiceGender: 'male' } }); void ensurePreferredVoice().then((m) => m && setTtsTest({ status: 'ok', message: m })); }}>Masculine</button>
|
||||
<button className={settings.speech.voiceGender === 'female' ? 'active' : ''} onClick={() => { update({ speech: { voiceGender: 'female' } }); void ensurePreferredVoice().then((m) => m && setTtsTest({ status: 'ok', message: m })); }}>Féminine</button>
|
||||
</div>
|
||||
<span className="hint">S’applique à tous les moteurs : voix locale (Piper Tom ou Pierre pour le masculin, téléchargée automatiquement si besoin), voix OpenAI (onyx / nova), voix système Windows (Paul / Hortense).</span>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Moteur de synthèse</label>
|
||||
<select className="select" value={settings.speech.provider} onChange={(e) => update({ speech: { provider: e.target.value as typeof settings.speech.provider } })}>
|
||||
|
||||
Reference in new issue
Block a user