pi-system/bin/SubWatcher

82 lines
2.7 KiB
Text
Raw Permalink Normal View History

#!/bin/bash
# SubWatcher — Hintergrund-Wächter für Subagenten-Aktivität (W02)
#
# Überwacht alle tmux-Sessions alle 15 Sekunden auf neue Ausgabe.
# Bei Änderung: zenity-Desktop-Notification + Alert-Datei für Guard.
# Der Guard zeigt den Alert beim nächsten Tool-Call prominent an.
#
# Nutzung: SubWatcher &
# Oder: SubWatcher --interval 10 (Sekunden)
# Beenden: kill %SubWatcher oder pkill -f SubWatcher
#
# Stoppt automatisch wenn keine tmux-Sessions mehr laufen.
INTERVAL="${2:-15}"
[ "$1" = "--interval" ] && INTERVAL="${2:-15}"
STATE_DIR="/tmp/.pi-subwatcher-state"
ALERT_FILE="/tmp/.pi-subagent-alert"
PID_FILE="/tmp/.pi-subwatcher.pid"
mkdir -p "$STATE_DIR"
echo $$ > "$PID_FILE"
log() {
echo "[SubWatcher $(date '+%H:%M:%S')] $1"
}
notify() {
local msg="$1"
# Alert-Datei für Guard (wird beim nächsten Tool-Call angezeigt)
echo "$(date '+%H:%M:%S') $msg" >> "$ALERT_FILE"
# Desktop-Notification
zenity --notification --text="Pi SubWatcher: $msg" 2>/dev/null &
# Terminal-Bell als Fallback
echo -e "\a" 2>/dev/null || true
}
log "Gestartet (PID $$, Interval: ${INTERVAL}s)"
log "Alert-Datei: $ALERT_FILE"
log "Stopp: kill $$ oder pkill -f SubWatcher"
while true; do
SESSIONS=$(tmux ls -F '#{session_name}' 2>/dev/null || echo "")
# Wenn keine Sessions: kurz warten, dann prüfen ob gestoppt werden soll
if [ -z "$SESSIONS" ]; then
sleep "$INTERVAL"
continue
fi
while IFS= read -r session; do
[ -z "$session" ] && continue
# Aktuellen Output capturen
CURRENT=$(tmux capture-pane -t "$session" -p 2>/dev/null | \
grep -v '^[[:space:]]*$' | tail -5 | tr '\n' '|')
STATE_FILE="${STATE_DIR}/${session}"
# Vorheriger State
PREVIOUS=$(cat "$STATE_FILE" 2>/dev/null || echo "")
if [ "$CURRENT" != "$PREVIOUS" ]; then
# State aktualisieren
echo "$CURRENT" > "$STATE_FILE"
# Wichtige Muster erkennen
LAST_LINE=$(echo "$CURRENT" | tr '|' '\n' | tail -1)
if echo "$CURRENT" | grep -qE "Pi beendet|Fenster kann geschlossen werden"; then
notify "[$session] FERTIG — Fenster kann geschlossen werden"
elif echo "$CURRENT" | grep -qE "contact_supervisor|Waiting for reply|waiting for.*reply"; then
notify "[$session] Wartet auf Antwort vom Orchestrator"
elif echo "$CURRENT" | grep -qE "Error|error:|FEHLER|failed|Failed" && ! echo "$PREVIOUS" | grep -qE "Error|error:|FEHLER|failed|Failed"; then
notify "[$session] Fehler erkannt: $LAST_LINE"
fi
# Einfache Aktivität (kein Spezialfall) — kein Alarm, nur State-Update
fi
done <<< "$SESSIONS"
sleep "$INTERVAL"
done