Ampel / ampel (push) Successful in 23s
Erster echter Lauf am 22.08. schickte den Bericht zweimal (07:01:42 und 07:02:14). Ursache: Hermes' terminal-Werkzeug bricht nach 30 s ab, die Sprachsynthese dauert laenger, der Agent hielt den Aufruf fuer gescheitert und wiederholte ihn - der Text war da laengst raus. Jetzt: Text senden, Stimme per setsid abgekoppelt, Rueckkehr nach 1,1 s. Dazu eine Doppelversand-Sperre ueber den Text-Hash, die jede Wiederholung innerhalb von zwei Stunden abweist - egal aus welchem Grund. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
90 lines
3.8 KiB
Bash
90 lines
3.8 KiB
Bash
#!/usr/bin/env bash
|
|
# news-melden.sh — schickt den fertigen Nachrichtenbericht als TEXT und als
|
|
# SPRACHNACHRICHT an den Commander (21.08.2026, überarbeitet 22.08.).
|
|
#
|
|
# Der Agent ruft genau EINEN Befehl auf. Alles danach ist deterministisch —
|
|
# Zustellung darf nicht davon abhaengen, ob ein Modell die Reihenfolge einhaelt.
|
|
#
|
|
# ‼️ WARUM DAS SKRIPT SOFORT ZURUECKKEHRT (Fund vom 22.08., erster echter Lauf):
|
|
# Hermes' terminal-Werkzeug bricht nach 30 s ab. Die Sprachsynthese dauert
|
|
# laenger. Der Agent sah den Timeout, hielt den Aufruf fuer gescheitert und
|
|
# rief das Skript ein zweites Mal auf — der Text ging DOPPELT raus
|
|
# (07:01:42 und 07:02:14).
|
|
# Deshalb: Text senden, Stimme abgekoppelt im Hintergrund, sofort raus.
|
|
# Dazu eine Doppelversand-Sperre, die auch kuenftige Wiederholungen abfaengt.
|
|
#
|
|
# Erwartet zwei Dateien, die der Agent vorher geschrieben hat:
|
|
# $1 Textfassung (mit Emojis, Links, Formatierung — geht nach Telegram)
|
|
# $2 Sprechfassung (kurz, ohne Links/Emojis — wird vorgelesen)
|
|
#
|
|
# ‼️ STIMME: :8021, nicht :8650.
|
|
# :8021 = lucy-stimme.service — Kyutai pocket-tts, Modell `german_24l`,
|
|
# Stimme geklont aus ref.mp3. DAS ist Lucy. Lokal, auf der CPU.
|
|
# :8650 = MC2s voice-service. Dort sind nur `elevenlabs` und `edge` geladen —
|
|
# beides CLOUD, und die Vorgabe ist die ElevenLabs-Stimme
|
|
# "Artoria/Saber", also HERMES' Stimme, nicht Lucys.
|
|
set -uo pipefail
|
|
|
|
NOTIFY="${NOTIFY:-$HOME/mission-control-v2/deploy/notify.sh}"
|
|
VOICE="${VOICE_URL:-http://127.0.0.1:8021}"
|
|
HERMES="${HERMES_BIN:-$HOME/.local/bin/hermes}"
|
|
TON="/tmp/news-stimme.wav"
|
|
TON_OGG="/tmp/news-stimme.ogg"
|
|
|
|
# ---------------------------------------------- Zweiter Durchgang: Stimme ---
|
|
# Wird vom ersten Durchgang abgekoppelt neu gestartet. Laeuft beliebig lange,
|
|
# ohne dass irgendein Werkzeug-Timeout hineinredet.
|
|
if [ "${1:-}" = "--nur-stimme" ]; then
|
|
SPRECHDATEI="${2:-/tmp/news-sprich.txt}"
|
|
[ -s "$SPRECHDATEI" ] || exit 0
|
|
|
|
CODE=$(curl -s -m 600 -X POST "$VOICE/tts" \
|
|
-H 'Content-Type: application/json' \
|
|
--data "$(python3 -c 'import json,sys; print(json.dumps({"text": open(sys.argv[1], encoding="utf-8").read()[:1500]}))' "$SPRECHDATEI")" \
|
|
-o "$TON" -w '%{http_code}' 2>/dev/null)
|
|
|
|
[ "$CODE" = "200" ] && [ -s "$TON" ] || exit 0
|
|
|
|
# Telegram zeigt eine ECHTE Sprachnachricht (runde Blase, Wellenform) nur bei
|
|
# OGG/Opus. Eine WAV kaeme als Dateianhang an. Mono/48k ist das erwartete Format.
|
|
if ! ffmpeg -y -loglevel error -i "$TON" -c:a libopus -b:a 32k -ar 48000 -ac 1 "$TON_OGG" 2>/dev/null; then
|
|
TON_OGG="$TON"
|
|
fi
|
|
"$HERMES" send --to telegram "MEDIA:$TON_OGG" >/dev/null 2>&1
|
|
exit 0
|
|
fi
|
|
|
|
# ------------------------------------------- Erster Durchgang: Text + Start ---
|
|
TEXTDATEI="${1:-/tmp/news-text.md}"
|
|
SPRECHDATEI="${2:-/tmp/news-sprich.txt}"
|
|
|
|
if [ ! -s "$TEXTDATEI" ]; then
|
|
bash "$NOTIFY" -s "[News]" "Der Nachrichtenbericht ist leer geblieben ($TEXTDATEI). Da lief etwas schief."
|
|
exit 1
|
|
fi
|
|
|
|
# Doppelversand-Sperre. Greift, egal WARUM ein zweiter Aufruf kommt —
|
|
# Timeout, Modell-Wiederholung, versehentlicher Handstart.
|
|
MARKE="/tmp/.news-gesendet-$(sha256sum "$TEXTDATEI" | cut -c1-16)"
|
|
if [ -f "$MARKE" ]; then
|
|
ALTER=$(( $(date +%s) - $(stat -c %Y "$MARKE" 2>/dev/null || echo 0) ))
|
|
if [ "$ALTER" -lt 7200 ]; then
|
|
echo "gemeldet (dieser Bericht ging vor ${ALTER}s bereits raus — nicht doppelt geschickt)"
|
|
exit 0
|
|
fi
|
|
fi
|
|
: > "$MARKE"
|
|
find /tmp -maxdepth 1 -name '.news-gesendet-*' -mtime +2 -delete 2>/dev/null
|
|
|
|
bash "$NOTIFY" -s "" "$(cat "$TEXTDATEI")"
|
|
|
|
# Stimme abkoppeln: eigene Sitzung, kein Elternprozess, keine offenen Deskriptoren.
|
|
# Damit ueberlebt sie das Ende dieses Skripts und blockiert es nicht.
|
|
if [ -s "$SPRECHDATEI" ]; then
|
|
setsid nohup bash "$0" --nur-stimme "$SPRECHDATEI" >/dev/null 2>&1 < /dev/null &
|
|
disown 2>/dev/null || true
|
|
fi
|
|
|
|
echo "gemeldet"
|
|
exit 0
|