83e5a04735
Systemblick 09.07. abends fand vier Lücken, drei davon hier (die vierte,
blogwatcher-Cron, ist Box-Config):
1. deploy.sh enablete mc2-autoupdate.timer bei JEDEM Deploy — und hat damit
den User-Entscheid vom 04.07. ("Updates nur bestätigt") über die heutige
Annahme-Kaskade still rückgängig gemacht. Zeile raus, Timer manuell
wieder disabled; wer Auto-Updates will, enabled einmalig von Hand.
2. self-smoke.sh prüft jetzt auch das Desktop-Gateway (:9119 /api/status) —
stirbt hermes-builtin-ui, ist die Desktop-App tot, das muss der
Selbst-Test melden statt der User.
3. backup.sh/restore.sh sichern die neue Infrastruktur mit: agent-hooks/
(pre_verify-Gates), shell-hooks-allowlist.json, desktop-gateway-token,
pc-paths.yaml und den systemd-Token-Drop-in (mit chmod 600 + +x beim
Restore). Vorher hätte ein Restore Desktop-Verbindung und Gates STILL
verloren. bash -n auf allen vier Skripten grün.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
98 lines
5.1 KiB
Bash
98 lines
5.1 KiB
Bash
#!/usr/bin/env bash
|
|
# Tägliche Selbst-Smoke-Tests der Box (Autonomie 0d): spielt die drei Kern-Pfade AKTIV durch —
|
|
# auch OHNE Update — und meldet NUR bei Rot (kein tägliches Grün-Rauschen). Ergänzt den passiven
|
|
# Health-Wächter (sentry.py prüft nur Erreichbarkeit) um echte Funktion:
|
|
# 1) Gateway/Hirn: der Agent liefert überhaupt eine Antwort.
|
|
# 2) Tools: ein harmloser terminal-Befehl durch den echten Agenten (fängt kaputte Approval-/
|
|
# Tool-Ketten — Antwort muss kommen und darf nicht in pending_approval hängen).
|
|
# 3) Voice: Lucys Sprech-Pfad (/api/voice/chat) streamt.
|
|
# Bei Fehlschlag → notify.sh (Telegram + Briefkasten) in Lucys Stimme. Läuft als User, kein sudo.
|
|
set -uo pipefail
|
|
|
|
SRC_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
MC_URL="${MC_URL:-http://127.0.0.1:9001}"
|
|
HERMES_URL="${HERMES_API_URL:-http://127.0.0.1:8642}"
|
|
HERMES="${HERMES_HOME:-$HOME/.hermes}"
|
|
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
|
|
|
say(){ echo "[self-smoke] $*"; }
|
|
FAILED=()
|
|
|
|
API_KEY="$(grep -E '^API_SERVER_KEY=' "$HERMES/.env" 2>/dev/null | cut -d= -f2- | tr -d '"' | tr -d "'")"
|
|
|
|
# ── 1) Gateway/Hirn: Agent antwortet ────────────────────────────────────────
|
|
if [ -n "$API_KEY" ]; then
|
|
RESP=$(curl -sf -m 90 -X POST "$HERMES_URL/v1/chat/completions" \
|
|
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
|
|
-H "X-Hermes-Session-Id: selfsmoke-gateway" \
|
|
-d '{"model":"hermes","stream":false,"chat_template_kwargs":{"enable_thinking":false},"messages":[{"role":"user","content":"Antworte NUR mit dem einen Wort: bereit"}]}' 2>/dev/null)
|
|
if echo "$RESP" | grep -qi "bereit"; then
|
|
say "PASS · Gateway/Hirn antwortet"
|
|
else
|
|
say "FAIL · Gateway/Hirn ohne verwertbare Antwort: $(echo "$RESP" | head -c 160)"
|
|
FAILED+=("Gehirn/Gateway (keine Antwort)")
|
|
fi
|
|
else
|
|
say "SKIP · Gateway (kein API_SERVER_KEY in $HERMES/.env)"
|
|
fi
|
|
|
|
# ── 2) Tools: terminal via Agent ─────────────────────────────────────────────
|
|
if [ -n "$API_KEY" ]; then
|
|
TOOL=$(curl -sf -m 90 -X POST "$HERMES_URL/v1/chat/completions" \
|
|
-H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
|
|
-H "X-Hermes-Session-Id: selfsmoke-tool" \
|
|
-d '{"model":"hermes","stream":false,"messages":[{"role":"user","content":"Führe im Terminal exakt den Befehl echo selfsmoke-ok aus und gib mir nur dessen Ausgabe zurück."}]}' 2>/dev/null)
|
|
if echo "$TOOL" | grep -qi "selfsmoke-ok"; then
|
|
say "PASS · Tools (terminal via Agent)"
|
|
elif echo "$TOOL" | grep -qi "pending_approval"; then
|
|
say "FAIL · Tools hängen in pending_approval (approvals.mode prüfen!)"
|
|
FAILED+=("Tools (hängen in Freigabe)")
|
|
else
|
|
say "FAIL · Tool-Smoke ohne Ergebnis: $(echo "$TOOL" | head -c 160)"
|
|
FAILED+=("Tools (kein Ergebnis)")
|
|
fi
|
|
fi
|
|
|
|
# ── 2b) Desktop-Gateway: hermes-builtin-ui antwortet ────────────────────────
|
|
# Seit dem Hermes-Desktop-Umzug (09.07.2026) hängt die Desktop-App an :9119
|
|
# (via MC2-Proxy /hermes-ui/). Stirbt der Dienst, ist die Arbeits-Oberfläche
|
|
# am PC tot — das muss der Selbst-Test melden, nicht erst der User.
|
|
if curl -sf -m 10 "http://127.0.0.1:9119/api/status" | grep -q '"gateway_running"'; then
|
|
say "PASS · Desktop-Gateway (:9119 /api/status)"
|
|
else
|
|
say "FAIL · Desktop-Gateway: :9119/api/status antwortet nicht (hermes-builtin-ui prüfen)"
|
|
FAILED+=("Desktop-Gateway (hermes-builtin-ui :9119)")
|
|
fi
|
|
|
|
# ── 3) Voice: Lucys Sprech-Stream ────────────────────────────────────────────
|
|
# Retry: der erste Turn nach Idle zahlt evtl. den Session-Kaltstart (Prefill).
|
|
# Subshell OHNE pipefail — head -c schließt die Pipe früh (curl endet mit 23/SIGPIPE),
|
|
# das würde einen bestandenen Check sonst als FAIL werten (Lehre aus hermes-postcheck.sh).
|
|
voice_ok=0
|
|
for try in 1 2 3; do
|
|
if ( set +o pipefail; curl -sf -m 45 -N -X POST "$MC_URL/api/voice/chat" -H "Content-Type: application/json" \
|
|
-d '{"text":"Sag nur ok.","session_id":"selfsmoke-voice"}' 2>/dev/null | head -c 50 | grep -q "data:" ); then
|
|
voice_ok=1; break
|
|
fi
|
|
sleep 8
|
|
done
|
|
if [ "$voice_ok" -eq 1 ]; then
|
|
say "PASS · Voice (/api/voice/chat streamt, Versuch $try)"
|
|
else
|
|
say "FAIL · Voice: /api/voice/chat streamt nicht (3 Versuche)"
|
|
FAILED+=("Voice (Lucys Sprech-Pfad)")
|
|
fi
|
|
|
|
# ── Meldung nur bei Rot ──────────────────────────────────────────────────────
|
|
if [ "${#FAILED[@]}" -eq 0 ]; then
|
|
say "Alle Selbst-Tests grün ($(date '+%F %H:%M'))."
|
|
exit 0
|
|
fi
|
|
|
|
MSG="Commander, mein täglicher Selbst-Test hat etwas gefunden — das läuft gerade NICHT rund:
|
|
$(printf '• %s\n' "${FAILED[@]}")
|
|
Der Rest der Box kann trotzdem stehen; magst du kurz draufschauen?"
|
|
bash "$SRC_DIR/notify.sh" -s "[Selbst-Test]" "$MSG" || true
|
|
say "FEHLGESCHLAGEN: ${FAILED[*]}"
|
|
exit 1
|