fix(cli): only prefix voice-transcribed messages with the voice-input instruction (#65827)
Typed messages sent while voice mode was active were also getting the '[Voice input — respond concisely...]' API-local prefix, because the gate checked only self._voice_mode. Route STT transcripts through a _VoiceInputMessage sentinel in _pending_input (both the PTT/continuous transcription path and the barge-in utterance path), unwrap it in process_loop, and thread voice_input= through chat() so the prefix applies only to genuinely voice-transcribed messages. Re-cut of PR #65961 (@webtecnica) — the original diff had the sentinel class embedded inside __init__'s docstring. Credit also to the earliest route-by-origin attempt in PR #11744 (@KeroZelvin). Fixes #65827 Closes #65961 Closes #11744
This commit is contained in:
parent
3524b20728
commit
0062107094
37
cli.py
37
cli.py
|
|
@ -4075,6 +4075,23 @@ def _normalize_moa_model(model: Optional[str]) -> tuple[Optional[str], Optional[
|
|||
return None, model
|
||||
|
||||
|
||||
class _VoiceInputMessage:
|
||||
"""Sentinel wrapper for voice-transcribed messages in ``_pending_input``.
|
||||
|
||||
Distinguishes STT output from manually typed text while voice mode is
|
||||
active, so the concise-voice-response prefix is applied only to messages
|
||||
that actually came from the microphone (#65827).
|
||||
"""
|
||||
|
||||
__slots__ = ("text",)
|
||||
|
||||
def __init__(self, text: str):
|
||||
self.text = text
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.text
|
||||
|
||||
|
||||
class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
||||
"""
|
||||
Interactive CLI for the Hermes Agent.
|
||||
|
|
@ -11928,7 +11945,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
self._attached_images.clear()
|
||||
if hasattr(self, '_app') and self._app:
|
||||
self._app.invalidate()
|
||||
self._pending_input.put(transcript)
|
||||
self._pending_input.put(_VoiceInputMessage(transcript))
|
||||
submitted = True
|
||||
elif result.get("success"):
|
||||
_cprint(f"{_DIM}No speech detected.{_RST}")
|
||||
|
|
@ -12116,7 +12133,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
_cprint(f"\n{_DIM}Stop phrase detected — ending voice chat.{_RST}")
|
||||
self._disable_voice_mode()
|
||||
return
|
||||
self._pending_input.put(transcript)
|
||||
self._pending_input.put(_VoiceInputMessage(transcript))
|
||||
submitted = True
|
||||
elif not result.get("success"):
|
||||
_cprint(f"\n{_DIM}Transcription failed: {result.get('error', 'Unknown error')}{_RST}")
|
||||
|
|
@ -12820,7 +12837,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
except Exception:
|
||||
pass
|
||||
|
||||
def chat(self, message, images: list = None) -> Optional[str]:
|
||||
def chat(self, message, images: list = None, voice_input: bool = False) -> Optional[str]:
|
||||
"""
|
||||
Send a message to the agent and get a response.
|
||||
|
||||
|
|
@ -12835,6 +12852,8 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
Args:
|
||||
message: The user's message (str or multimodal content list)
|
||||
images: Optional list of Path objects for attached images
|
||||
voice_input: True when the message came from voice transcription
|
||||
(gates the concise voice-response prefix, #65827)
|
||||
|
||||
Returns:
|
||||
The agent's response, or None on error
|
||||
|
|
@ -13062,7 +13081,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
# model responds concisely. The prefix is API-call-local only —
|
||||
# run_conversation persists the original clean user message.
|
||||
_voice_prefix = ""
|
||||
if self._voice_mode and isinstance(message, str):
|
||||
if voice_input and isinstance(message, str):
|
||||
_voice_prefix = (
|
||||
"[Voice input — respond concisely and conversationally, "
|
||||
"2-3 sentences max. No code blocks or markdown.] "
|
||||
|
|
@ -16226,7 +16245,13 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
except Exception:
|
||||
pass
|
||||
continue
|
||||
|
||||
|
||||
# Voice-transcribed messages arrive wrapped in a sentinel
|
||||
# so only genuine STT output gets the voice prefix (#65827).
|
||||
is_voice_input = isinstance(user_input, _VoiceInputMessage)
|
||||
if is_voice_input:
|
||||
user_input = user_input.text
|
||||
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
|
|
@ -16322,7 +16347,7 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin, CLIBillingMixin):
|
|||
app.invalidate() # Refresh status line
|
||||
|
||||
try:
|
||||
self.chat(user_input, images=submit_images or None)
|
||||
self.chat(user_input, images=submit_images or None, voice_input=is_voice_input)
|
||||
finally:
|
||||
self._agent_running = False
|
||||
self._spinner_text = ""
|
||||
|
|
|
|||
Loading…
Reference in New Issue