#!/bin/sh set -eu target=/opt/hermes/cron/scheduler_delivery.py broken='env.pop("HERMES_HOME", None)' if [ -f "$target" ] && grep -Fq "$broken" "$target"; then sed -i '/^[[:space:]]*env\.pop("HERMES_HOME", None)[[:space:]]*$/d' "$target" echo "[cron-profile-root-fix] preserved HERMES_HOME for named-profile delivery" else echo "[cron-profile-root-fix] upstream code already fixed or layout changed; no action" fi cli_dir="${HERMES_HOME:-/opt/data}/.local/bin" mkdir -p "$cli_dir" ln -sfn /opt/hermes/.venv/bin/hermes "$cli_dir/hermes" ln -sfn /opt/hermes/.venv/bin/hermes /usr/local/bin/hermes # Hermes' generic sentence splitter treats periods in German abbreviations as # sentence ends. It also submits every sentence as a separate generative TTS # request, which creates long gaps with local Qwen3-TTS. Keep the first sentence # immediate, then group following complete sentences into modest ~240-character # chunks so playback remains responsive but substantially more continuous. tts_target=/opt/hermes/tools/tts_streaming.py if [ -f "$tts_target" ] && grep -Fq 'self.buf = _THINK_BLOCK_RE.sub("", self.buf + delta)' "$tts_target"; then TTS_TARGET="$tts_target" python3 <<'PY' import os from pathlib import Path p = Path(os.environ["TTS_TARGET"]) s = p.read_text() base_feed = ' self.buf = _THINK_BLOCK_RE.sub("", self.buf + delta)' abbr_lines = [ ' self.buf = re.sub(r"\\bca\\.(?=\\s)", "circa", self.buf, flags=re.IGNORECASE)', ' self.buf = re.sub(r"\\bv\\.\\s*a\\.(?=\\s)", "vor allem", self.buf, flags=re.IGNORECASE)', ' self.buf = re.sub(r"\\bmax\\.(?=\\s)", "maximal", self.buf, flags=re.IGNORECASE)', ] for line in abbr_lines: s = s.replace("\n" + line, "") init_old = ' self.buf = ""' init_extra = ( '\n self.followup_target_len = 240' '\n self._emitted_first = False' ) s = s.replace(init_old + init_extra, init_old) threshold_old = ' if len(head.strip()) < self.min_len:' threshold_new = ( ' threshold = (self.min_len if not self._emitted_first ' 'else self.followup_target_len)\n' ' if len(head.strip()) < threshold:' ) s = s.replace(threshold_new, threshold_old) append_old = ' out.append(head)' append_new = append_old + '\n self._emitted_first = True' s = s.replace(append_new, append_old) s = s.replace(base_feed, base_feed + "\n" + "\n".join(abbr_lines), 1) s = s.replace(init_old, init_old + init_extra, 1) s = s.replace(threshold_old, threshold_new, 1) s = s.replace(append_old, append_new, 1) p.write_text(s) PY echo "[tts-streaming-fix] enabled German normalization and adaptive sentence grouping" else echo "[tts-streaming-fix] upstream code already fixed or layout changed; no action" fi