refactor(tui_gateway): W4 wave2 pass 8 — split prompt/personality/skin setters, nest single-use voice helpers
This commit is contained in:
@@ -419,32 +419,34 @@ def _set_cwd(rid, params, key, value, session):
|
||||
|
||||
|
||||
@_cfgset_guarded
|
||||
def _set_prompt_like(rid, params, key, value, session):
|
||||
cfg = _load_cfg_raw() # write-back round-trip ("prompt" saves cfg)
|
||||
resp = {"key": key, "value": value}
|
||||
if key == "prompt":
|
||||
if value == "clear":
|
||||
cfg.pop("custom_prompt", None)
|
||||
resp["value"] = ""
|
||||
else:
|
||||
cfg["custom_prompt"] = value
|
||||
_save_cfg(cfg)
|
||||
elif key == "personality":
|
||||
pname, new_prompt = _validate_personality(str(value or ""), cfg)
|
||||
# Persists via hermes_cli.personality (single owner), never the user-owned system prompt.
|
||||
from hermes_cli.personality import persist_personality
|
||||
persist_personality(pname)
|
||||
resp["value"] = str(value or "none")
|
||||
history_reset, info = _apply_personality_to_session(params.get("session_id", ""), session, new_prompt, pname)
|
||||
resp["history_reset"] = history_reset
|
||||
if info is not None:
|
||||
resp["info"] = info
|
||||
def _set_prompt(rid, params, key, value, session):
|
||||
cfg = _load_cfg_raw() # write-back round-trip
|
||||
if value == "clear":
|
||||
cfg.pop("custom_prompt", None)
|
||||
else:
|
||||
_write_config_key(f"display.{key}", value)
|
||||
if key == "skin": # every surface repaints; sync the watcher baseline (no re-broadcast)
|
||||
_broadcast_global_event("skin.changed", resolve_skin())
|
||||
_note_skin_broadcast()
|
||||
return _ok(rid, resp)
|
||||
cfg["custom_prompt"] = value
|
||||
_save_cfg(cfg)
|
||||
return _kv(rid, key, "" if value == "clear" else value)
|
||||
|
||||
|
||||
@_cfgset_guarded
|
||||
def _set_personality(rid, params, key, value, session):
|
||||
pname, new_prompt = _validate_personality(str(value or ""), _load_cfg_raw())
|
||||
# Persists via hermes_cli.personality (single owner), never the user-owned system prompt.
|
||||
from hermes_cli.personality import persist_personality
|
||||
persist_personality(pname)
|
||||
history_reset, info = _apply_personality_to_session(params.get("session_id", ""), session, new_prompt, pname)
|
||||
return _kv(rid, key, str(value or "none"), history_reset=history_reset,
|
||||
**({"info": info} if info is not None else {}))
|
||||
|
||||
|
||||
@_cfgset_guarded
|
||||
def _set_skin(rid, params, key, value, session):
|
||||
_write_config_key("display.skin", value)
|
||||
# Every surface repaints; sync the watcher baseline so the poll loop doesn't re-broadcast.
|
||||
_broadcast_global_event("skin.changed", resolve_skin())
|
||||
_note_skin_broadcast()
|
||||
return _kv(rid, key, value)
|
||||
|
||||
|
||||
def _set_display_toggle(rid, params, key, value, session):
|
||||
@@ -464,7 +466,7 @@ _CONFIG_SETTERS = {
|
||||
"density": _set_display_bool, "battery": _set_display_bool, "theme": _set_theme,
|
||||
"statusbar": _set_statusbar, "mouse": _set_mouse, "indicator": _set_indicator,
|
||||
"cwd": _set_cwd, "terminal.cwd": _set_cwd, "workdir": _set_cwd,
|
||||
"prompt": _set_prompt_like, "personality": _set_prompt_like, "skin": _set_prompt_like}
|
||||
"prompt": _set_prompt, "personality": _set_personality, "skin": _set_skin}
|
||||
|
||||
|
||||
@method("config.set")
|
||||
|
||||
@@ -217,28 +217,24 @@ def _fd_barge_params(cfg: dict) -> tuple[float, int]:
|
||||
return mult, max(0, num(lambda v: int(float(v) * 1000), "barge_in_grace_seconds", 0.5))
|
||||
|
||||
|
||||
def _cut_all_tts() -> None:
|
||||
"""Cut streaming TTS, every fallback speak pipeline, and the file player."""
|
||||
from tools.voice_mode import stop_playback
|
||||
_tts_stream_stop(user_barge=True)
|
||||
with _fd_listener_lock:
|
||||
for _stop, _done in _fd_speak_pipelines:
|
||||
_stop.set()
|
||||
stop_playback()
|
||||
|
||||
|
||||
def _fd_trip(phase: str) -> None:
|
||||
"""Listener tripped: latch the interruption, cut TTS FIRST (so a stale reply can never
|
||||
speak), and during generation also interrupt every running turn (the ``agent.interrupt()``
|
||||
seam ``session.interrupt`` uses)."""
|
||||
from tools.tts_streaming import mark_speech_interrupted
|
||||
from tools.voice_mode import stop_playback
|
||||
mark_speech_interrupted()
|
||||
if phase == "playback":
|
||||
logger.debug("TTS CUT: full-duplex listener tripped during playback")
|
||||
else:
|
||||
logger.debug("full-duplex listener tripped during generation — "
|
||||
"interrupting running turn(s)")
|
||||
_cut_all_tts()
|
||||
# Cut streaming TTS, every fallback speak pipeline, and the file player.
|
||||
_tts_stream_stop(user_barge=True)
|
||||
with _fd_listener_lock:
|
||||
for _stop, _done in _fd_speak_pipelines:
|
||||
_stop.set()
|
||||
stop_playback()
|
||||
if phase != "playback":
|
||||
try:
|
||||
for s in _running_sessions():
|
||||
@@ -300,9 +296,8 @@ def _voice_status_payload(**extra) -> dict:
|
||||
"""``{enabled, record_key, tts, **extra}``: record_key (default ``ctrl+b``) rides every voice.toggle
|
||||
branch so a tts toggle never resets a custom binding."""
|
||||
record_key = _voice_cfg_dict().get("record_key")
|
||||
record_key = str(record_key) if isinstance(record_key, str) and record_key else "ctrl+b"
|
||||
return {"enabled": _voice_mode_enabled(), "record_key": record_key, "tts": _voice_tts_enabled(),
|
||||
**extra}
|
||||
record_key = record_key if isinstance(record_key, str) and record_key else "ctrl+b"
|
||||
return {"enabled": _voice_mode_enabled(), "record_key": record_key, "tts": _voice_tts_enabled(), **extra}
|
||||
|
||||
|
||||
# ── Wake word ("Hey Hermes"): process-global detector (one mic). The first eligible transport
|
||||
@@ -678,8 +673,8 @@ def _(rid, params: dict) -> dict:
|
||||
return handler(rid, params)
|
||||
|
||||
|
||||
# voice.record callbacks (module-level: they touch only process-global state). Each terminal
|
||||
# capture event resumes the wake detector so wake-triggered and manual captures coexist.
|
||||
# voice.record callbacks: each terminal capture event resumes the wake detector so wake-triggered
|
||||
# and manual captures coexist.
|
||||
def _vr_transcript(payload: dict) -> None:
|
||||
_voice_emit("voice.transcript", payload)
|
||||
_resume_voice_wake()
|
||||
|
||||
Reference in New Issue
Block a user