fix(autosend): invio dettatura robusto e visibile (v0.3.1)

L'auto-invio poteva non scattare senza alcun segnale. Cause eliminate:
- il testo viene passato esplicitamente (sendText) invece di rileggerlo
  dal campo; il focus tastiera non viene piu' forzato prima dell'invio
- l'opzione vale "on" salvo disattivazione esplicita (undefined -> on)
- ChatModel::send non rifiuta piu' in silenzio: avviso a schermo
  ("No session open" / "Wait for the current reply") + log [chat]
- log [hermes] sul percorso trascrizione/auto-invio per la diagnosi
  dal terminale
This commit is contained in:
2026-09-12 13:49:20 +02:00
parent a5932f0025
commit fa2aafa9dd
6 changed files with 56 additions and 20 deletions
+1 -1
View File
@@ -48,6 +48,6 @@ speaks (validated live against a real instance).
## Status ## Status
Version 0.3.0 — protocol and C++ core validated against a real `hermes-webui` Version 0.3.1 — protocol and C++ core validated against a real `hermes-webui`
(login, sessions, streaming chat, TTS, STT, voice dialog); on-device testing (login, sessions, streaming chat, TTS, STT, voice dialog); on-device testing
still ongoing. still ongoing.
+3 -3
View File
@@ -76,12 +76,12 @@ richiede il probe WebUI su :8899). Esito 12/09/2026: unit 9/9, live completo OK.
```bash ```bash
cd ~/workspace cd ~/workspace
tar czf harbour-hermes-0.3.0.tar.gz \ tar czf harbour-hermes-0.3.1.tar.gz \
--transform 's,^harbour-hermes,harbour-hermes-0.3.0,' \ --transform 's,^harbour-hermes,harbour-hermes-0.3.1,' \
--exclude='.git' harbour-hermes --exclude='.git' harbour-hermes
``` ```
Lo spec si aspetta la directory `harbour-hermes-0.3.0/` (pattern degli altri Lo spec si aspetta la directory `harbour-hermes-0.3.1/` (pattern degli altri
progetti: cercato in modo robusto anche per i sorgenti live di sfdk). progetti: cercato in modo robusto anche per i sorgenti live di sfdk).
## 5. Dipendenze lato server (WebUI) ## 5. Dipendenze lato server (WebUI)
+29 -12
View File
@@ -227,7 +227,10 @@ Page {
} }
return return
} }
if (appSettings.ttsAutoRead) var autoRead = appSettings.ttsAutoRead
if (autoRead === undefined || autoRead === null)
autoRead = false
if (autoRead)
page.readLast() page.readLast()
} }
onNotice: page.showNotice(text) onNotice: page.showNotice(text)
@@ -237,20 +240,28 @@ Page {
target: api target: api
onTranscriptionReady: { onTranscriptionReady: {
page.voiceErrors = 0 page.voiceErrors = 0
var t = (text === undefined || text === null) ? "" : String(text)
var autoSend = appSettings.dictationAutoSend
if (autoSend === undefined || autoSend === null)
autoSend = true
console.log("[hermes] trascrizione: " + t.length + " char, voiceMode="
+ page.voiceMode + ", autoSend=" + autoSend)
if (page.voiceMode) { if (page.voiceMode) {
if (text.trim().length === 0) { if (t.trim().length === 0) {
voiceRetry.restart() voiceRetry.restart()
return return
} }
input.text = text
page.voiceState = "sending" page.voiceState = "sending"
page.doSend() page.sendText(t)
return return
} }
input.text = text input.text = t
input.focus = true if (autoSend) {
if (appSettings.dictationAutoSend) console.log("[hermes] auto-invio dettatura")
page.doSend() page.sendText(t)
} else {
input.focus = true
}
} }
onTranscriptionFailed: { onTranscriptionFailed: {
page.showNotice(error) page.showNotice(error)
@@ -372,15 +383,21 @@ Page {
return qsTr("Voice mode on") return qsTr("Voice mode on")
} }
function doSend() { // Invio del testo esplicito (non rilegge il campo: nessuna race con la UI).
var t = input.text function sendText(t) {
if (t.trim().length === 0) var s = String(t).trim()
if (s.length === 0)
return return
input.text = "" input.text = ""
chat.send(t) console.log("[hermes] sendText: " + s.length + " char, chat.busy=" + chat.busy)
chat.send(s)
scrollDebounce.restart() scrollDebounce.restart()
} }
function doSend() {
sendText(input.text)
}
function readLast() { function readLast() {
var t = chat.lastAssistantText() var t = chat.lastAssistantText()
if (t.length === 0) { if (t.length === 0) {
+6 -1
View File
@@ -1,6 +1,6 @@
Name: harbour-hermes Name: harbour-hermes
Summary: Client for the Hermes Web UI with voice Summary: Client for the Hermes Web UI with voice
Version: 0.3.0 Version: 0.3.1
Release: 1 Release: 1
Group: Qt/Qt Group: Qt/Qt
License: MIT License: MIT
@@ -24,6 +24,11 @@ Sessions list, chat with live streaming replies, voice dictation
(server-side TTS), plus a hands-free conversation mode. (server-side TTS), plus a hands-free conversation mode.
%changelog %changelog
* Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.3.1-1
- Auto-invio dettatura piu' robusto: il testo viene passato esplicitamente
(niente rilettura del campo), l'opzione vale "on" salvo disattivazione
esplicita, niente focus tastiera prima dell'invio; i rifiuti di invio
ora sono visibili (avviso a schermo + log [chat]/[hermes])
* Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.3.0-1 * Sat Sep 12 2026 Carlo Baratto <carlo@carlobaratto.it> - 0.3.0-1
- Nessuna configurazione cablata nel binario: indirizzo server, voce, - Nessuna configurazione cablata nel binario: indirizzo server, voce,
engine e preset sono impostazioni dell'app (default neutri; vuoto = engine e preset sono impostazioni dell'app (default neutri; vuoto =
+15 -1
View File
@@ -1,5 +1,6 @@
#include "chatmodel.h" #include "chatmodel.h"
#include <QDebug>
#include <QTimer> #include <QTimer>
ChatModel::ChatModel(ApiClient *api, QObject *parent) ChatModel::ChatModel(ApiClient *api, QObject *parent)
@@ -81,8 +82,21 @@ void ChatModel::resync()
void ChatModel::send(const QString &text) void ChatModel::send(const QString &text)
{ {
const QString trimmed = text.trimmed(); const QString trimmed = text.trimmed();
if (trimmed.isEmpty() || m_sessionId.isEmpty() || m_busy) if (trimmed.isEmpty())
return; return;
// Rifiuti VISIBILI: prima erano silenziosi, e l'invio automatico poteva
// "non fare nulla" senza che si capisse il perché.
if (m_sessionId.isEmpty()) {
qDebug() << "[chat] send rifiutato: nessuna sessione aperta";
emit notice(QStringLiteral("No session open"));
return;
}
if (m_busy) {
qDebug() << "[chat] send rifiutato: un turno e' gia' in corso";
emit notice(QStringLiteral("Wait for the current reply"));
return;
}
qDebug() << "[chat] invio:" << trimmed.size() << "caratteri";
m_finalizedThisRun = false; m_finalizedThisRun = false;
appendMessage(QStringLiteral("user"), trimmed, false); appendMessage(QStringLiteral("user"), trimmed, false);
beginAssistant(); beginAssistant();
+2 -2
View File
@@ -19,9 +19,9 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
// AppConfigLocation = ~/.config/harbour/hermes (zona persistente della sandbox). // AppConfigLocation = ~/.config/harbour/hermes (zona persistente della sandbox).
app->setOrganizationName(QStringLiteral("harbour")); app->setOrganizationName(QStringLiteral("harbour"));
app->setApplicationName(QStringLiteral("hermes")); app->setApplicationName(QStringLiteral("hermes"));
app->setApplicationVersion(QStringLiteral("0.3.0")); app->setApplicationVersion(QStringLiteral("0.3.1"));
qDebug() << "harbour-hermes v0.3.0 build" << __DATE__ << __TIME__; qDebug() << "harbour-hermes v0.3.1 build" << __DATE__ << __TIME__;
Settings settings; Settings settings;
ApiClient api(&settings); ApiClient api(&settings);