fix(stt): better error logging and smarter DM when STT install fails

Three improvements to the voice-transcription setup flow:

1. tools/transcription_tools.py - Log lazy-install failures at WARNING
   instead of DEBUG, and include actionable guidance about venv
   permission issues (the most common cause of silent STT failures).

2. gateway/run.py - Smart DM message: check the actual stt config
   before sending setup instructions. If stt.enabled is already true
   and provider is 'local', skip the redundant 'set stt.enabled'
   advice and show a permission-aware install hint instead.

3. gateway/run.py - Agent note now includes a config-aware hint
   about why STT is unavailable (e.g. 'provider is local but
   faster-whisper failed to install').
This commit is contained in:
Damian Kluk 2026-06-14 12:12:39 +00:00
parent ab22317d09
commit d3e07bdaaa
2 changed files with 79 additions and 10 deletions

View file

@ -8616,15 +8616,50 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
_stt_meta = self._thread_metadata_for_source(source, self._reply_anchor_for_event(event))
if _stt_adapter:
try:
_stt_msg = (
# Build a smarter DM — check what the user has already configured
_stt_msg_parts = [
"🎤 I received your voice message but can't transcribe it — "
"no speech-to-text provider is configured.\n\n"
"To enable voice: install faster-whisper "
"(`uv pip install faster-whisper` in the Hermes venv; "
"`pip install faster-whisper` also works if pip is on PATH) "
"and set `stt.enabled: true` in config.yaml, "
"then /restart the gateway."
)
"no speech-to-text provider is available."
]
try:
from tools.transcription_tools import _load_stt_config, is_stt_enabled
_cfg = _load_stt_config()
_enabled = is_stt_enabled(_cfg)
_provider = _cfg.get("provider", "auto")
if not _enabled:
_stt_msg_parts.append(
"✅ **STT is disabled** in your config "
"(`stt.enabled: false`). Set it to `true` "
"and /restart the gateway."
)
elif _provider in ("local", "auto"):
_stt_msg_parts.append(
"To enable local voice transcription:\n"
"1. Install faster-whisper:\n"
" `VIRTUAL_ENV=/opt/hermes/.venv uv pip install \"faster-whisper==1.2.1\"`\n"
"2. If you get a **permission denied** error, the venv is owned by "
"a different user. Run the install command as the venv owner:\n"
" `su - $(stat -c '%U' /opt/hermes/.venv) -c 'VIRTUAL_ENV=/opt/hermes/.venv "
"uv pip install \"faster-whisper==1.2.1\"'`\n"
"3. Then /restart the gateway."
)
else:
# Cloud provider — API key may be missing
_stt_msg_parts.append(
f"Your configured STT provider is **{_provider}**. "
"Make sure the required API key is set in your `.env` file, "
"then /restart the gateway."
)
except Exception:
# Fallback if the config check itself fails
_stt_msg_parts.append(
"To enable voice: install faster-whisper "
"(`uv pip install faster-whisper` in the Hermes venv; "
"`pip install faster-whisper` also works if pip is on PATH) "
"and set `stt.enabled: true` in config.yaml, "
"then /restart the gateway."
)
_stt_msg = "\n\n".join(_stt_msg_parts)
if self._has_setup_skill():
_stt_msg += "\n\nFor full setup instructions, type: `/skill hermes-agent-setup`"
await _stt_adapter.send(
@ -12876,9 +12911,31 @@ class GatewayRunner(GatewayAuthorizationMixin, GatewayKanbanWatchersMixin, Gatew
"No STT provider" in error
or error.startswith("Neither VOICE_TOOLS_OPENAI_KEY nor OPENAI_API_KEY is set")
):
# Check if STT is actually configured — helps the agent
# give a better response than the generic "not configured".
_stt_config_hint = ""
try:
from tools.transcription_tools import _load_stt_config, is_stt_enabled
_cfg = _load_stt_config()
if is_stt_enabled(_cfg):
_provider = _cfg.get("provider", "auto")
if _provider == "local":
_stt_config_hint = (
" (Note: stt.enabled is true and provider is 'local', "
"but faster-whisper failed to install — likely a venv "
"write-permission issue)"
)
else:
_stt_config_hint = (
f" (Note: stt.enabled is true, provider is '{_provider}', "
"but the provider is unavailable)"
)
except Exception:
pass
_no_stt_note = (
"[The user sent a voice message but I can't listen "
"to it right now — no STT provider is configured. "
"to it right now — no STT provider is available."
f"{_stt_config_hint} "
"A direct message has already been sent to the user "
"with setup instructions."
)

View file

@ -223,8 +223,20 @@ def _try_lazy_install_stt() -> bool:
import importlib.util as _iu
if _iu.find_spec("faster_whisper"):
return True
logger.warning(
"faster-whisper was installed but importlib still cannot find it "
"(may require Python restart)"
)
except Exception as exc:
logger.debug("Lazy install of faster-whisper failed: %s", exc)
logger.warning(
"Lazy install of faster-whisper failed: %s. "
"This is often a permission issue: the Hermes process user cannot "
"write to the virtual environment. Try running manually as the "
"venv owner: `stat -c '%%u' '$(dirname $(dirname $(which python3)))'` "
"then `su - <owner> -c 'VIRTUAL_ENV=/opt/hermes/.venv "
"uv pip install faster-whisper==1.2.1'`",
exc,
)
return False