MC2 wird Updater, Waechter und Modell-Radar (Konzept „MC2 als Box-Wart“, 23.09.2026). - Neuer Waechter (services/waechter.py) loest sentry.py ab: Dienste, Timer-Laeufe, Hermes-Jobs samt Werkzeugfehlern, Kern-HTTP-Proben, Platte. Abgestuerzte Dienste startet er selbst neu (max. 2/h), rote Hinweise gehen an Telegram und Lucy. Laeuft im mc2-steward; waehrend eines Updates haelt er still. - Neue Schnittstellen (routers/boxwart.py): /api/start, /api/hinweise (+ Aktionen), /api/modelle/nutzung, /api/zeitplan. - Modell-Nutzung aus dem llama-swap-Journal (wer fragt wie oft, 24 h je Stunde). - Entfernt: Ideen, Wissen, Chronik, Skills, Verbinden, Konsolen-Proxy, /api/events; Lucys Werkzeug idee_notieren; box_status nennt jetzt die offenen Hinweise. - Behoben: projekte-sync ueberspringt leere Gitea-Repos (lief seit 07.09. stuendlich rot); Motor-Version kam aus dem verwaisten /opt/llamacpp statt /opt/llamacpp-vulkan. - Erste Backend-Tests (8) fuer Waechter und Modell-Nutzung. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
135 lines
5.1 KiB
Bash
135 lines
5.1 KiB
Bash
#!/usr/bin/env bash
|
|
# Projekte-Sync (20.08.2026): haelt ~/projekte mit Gitea deckungsgleich.
|
|
#
|
|
# Warum: Der Hermes-Desktop laeuft gegen das Box-Backend, sein Ordner-Waehler zeigt
|
|
# also das Dateisystem der BOX. Damit dort alle Projekte auftauchen, muessen sie hier
|
|
# liegen — und aktuell sein.
|
|
#
|
|
# Regeln (bewusst konservativ — dieses Skript laeuft unbeaufsichtigt):
|
|
# • NUR fast-forward (`--ff-only`). Kein merge, kein rebase, kein reset, kein force.
|
|
# • Repos mit lokalen Aenderungen werden UEBERSPRUNGEN, nicht ueberfahren.
|
|
# • Live-Deployments werden NIE gezogen (mission-control-v2 wird aus dem Deploy
|
|
# bedient und pusht selbst) — sie bekommen nur eine Verknuepfung, damit sie im
|
|
# Waehler auftauchen.
|
|
# • Bestehende Checkouts in ~ bleiben, wo sie sind; ~/projekte bekommt eine
|
|
# Verknuepfung darauf statt eines zweiten Klons.
|
|
# • Interne Gitea-IP, NICHT die DDNS-Domain: die ist nachts durch die
|
|
# Zwangstrennung zeitweise tot (Lehre vom 24.07.).
|
|
#
|
|
# Aufruf: projekte-sync.sh [--dry-run]
|
|
# Exit: 0 = alles gut · 1 = mindestens ein Repo hatte ein Problem
|
|
set -uo pipefail
|
|
|
|
GITEA="${GITEA_URL:-http://192.168.178.153:3000}"
|
|
ZIEL="${PROJEKTE_DIR:-$HOME/projekte}"
|
|
LOG="${PROJEKTE_SYNC_LOG:-$HOME/.hermes/logs/projekte-sync.log}"
|
|
DRY=0
|
|
[ "${1:-}" = "--dry-run" ] && DRY=1
|
|
|
|
# Repos, die NICHT nach ~/projekte geklont werden (Live-Deployment oder Altlast).
|
|
# mission-control-v2: laeuft aus ~/mission-control-v2, Dienste arbeiten daraus.
|
|
# mission-control: archivierte v1.
|
|
NIE_ZIEHEN="mission-control-v2"
|
|
UEBERSPRINGEN="mission-control"
|
|
|
|
mkdir -p "$ZIEL" "$(dirname "$LOG")"
|
|
FEHLER=0
|
|
|
|
log() { printf '%s %s\n' "$(date '+%F %T')" "$*" | tee -a "$LOG"; }
|
|
|
|
TOKEN=""
|
|
for f in "$HOME/.config/gitea/create-token"; do
|
|
[ -r "$f" ] && TOKEN="$(tr -d '[:space:]' < "$f")" && break
|
|
done
|
|
if [ -z "$TOKEN" ]; then
|
|
log "ABBRUCH: kein Gitea-Token unter ~/.config/gitea/create-token"
|
|
exit 1
|
|
fi
|
|
|
|
REPOS="$(curl -s -m 20 -H "Authorization: token $TOKEN" \
|
|
"$GITEA/api/v1/user/repos?limit=100" \
|
|
| python3 -c 'import sys,json; [print(r["name"]) for r in json.load(sys.stdin)]' 2>/dev/null)"
|
|
if [ -z "$REPOS" ]; then
|
|
log "ABBRUCH: Gitea lieferte keine Repo-Liste ($GITEA)"
|
|
exit 1
|
|
fi
|
|
|
|
log "=== Sync-Lauf ($(printf '%s\n' "$REPOS" | wc -l) Repos gemeldet)$([ $DRY -eq 1 ] && echo ' [Trockenlauf]') ==="
|
|
|
|
# Vorhandenen Checkout eines Repos finden (oberste Home-Ebene bevorzugt).
|
|
finde_checkout() {
|
|
local name="$1" d
|
|
for d in "$HOME/$name" "$ZIEL/$name"; do
|
|
[ -d "$d/.git" ] && { printf '%s' "$d"; return 0; }
|
|
done
|
|
return 1
|
|
}
|
|
|
|
verknuepfe() { # $1=Zielpfad des echten Checkouts, $2=Repo-Name
|
|
local ziel="$1" name="$2" link="$ZIEL/$name"
|
|
[ "$ziel" = "$link" ] && return 0
|
|
[ -L "$link" ] && [ "$(readlink -f "$link")" = "$(readlink -f "$ziel")" ] && return 0
|
|
[ -e "$link" ] && [ ! -L "$link" ] && { log " ! $name: $link existiert und ist keine Verknuepfung — nichts getan"; return 1; }
|
|
[ $DRY -eq 1 ] && { log " ~ $name: wuerde verknuepfen -> $ziel"; return 0; }
|
|
ln -sfn "$ziel" "$link" && log " ~ $name: verknuepft -> ${ziel/$HOME/\~}"
|
|
}
|
|
|
|
for name in $REPOS; do
|
|
case " $UEBERSPRINGEN " in *" $name "*) log " - $name: uebersprungen (Altlast)"; continue;; esac
|
|
|
|
if checkout="$(finde_checkout "$name")"; then
|
|
case " $NIE_ZIEHEN " in
|
|
*" $name "*)
|
|
log " = $name: Live-Deployment, kein Pull"
|
|
verknuepfe "$checkout" "$name"
|
|
continue;;
|
|
esac
|
|
|
|
if [ -n "$(git -C "$checkout" status --porcelain 2>/dev/null)" ]; then
|
|
log " ! $name: lokale Aenderungen — uebersprungen (nichts ueberfahren)"
|
|
verknuepfe "$checkout" "$name"
|
|
continue
|
|
fi
|
|
|
|
# Leeres Repo auf Gitea (angelegt, aber nie etwas gepusht): Es gibt keinen Branch, also
|
|
# scheitert jeder Pull mit „no such ref was fetched“. So lief projekte-sync ab dem
|
|
# 07.09.2026 stuendlich rot (TTT2-Toolbox_ClaudeEdition). Leer ist kein Fehler.
|
|
# Scheitert ls-remote selbst (Netz weg), geht es normal weiter und der Pull meldet es.
|
|
if kopf="$(git -C "$checkout" ls-remote --heads origin 2>/dev/null)" && [ -z "$kopf" ]; then
|
|
log " - $name: auf Gitea noch leer — nichts zu holen"
|
|
verknuepfe "$checkout" "$name"
|
|
continue
|
|
fi
|
|
|
|
if [ $DRY -eq 1 ]; then
|
|
log " ~ $name: wuerde pullen (${checkout/$HOME/\~})"
|
|
else
|
|
vorher="$(git -C "$checkout" rev-parse --short HEAD 2>/dev/null)"
|
|
if out="$(git -C "$checkout" pull --ff-only 2>&1)"; then
|
|
nachher="$(git -C "$checkout" rev-parse --short HEAD 2>/dev/null)"
|
|
if [ "$vorher" = "$nachher" ]; then
|
|
log " = $name: aktuell ($vorher)"
|
|
else
|
|
log " + $name: $vorher -> $nachher"
|
|
fi
|
|
else
|
|
log " ! $name: Pull fehlgeschlagen — $(printf '%s' "$out" | tail -1)"
|
|
FEHLER=1
|
|
fi
|
|
fi
|
|
verknuepfe "$checkout" "$name"
|
|
else
|
|
if [ $DRY -eq 1 ]; then
|
|
log " ~ $name: wuerde klonen nach ${ZIEL/$HOME/\~}/$name"
|
|
elif out="$(git clone -q "$GITEA/Hitonabi/$name.git" "$ZIEL/$name" 2>&1)"; then
|
|
log " + $name: neu geklont"
|
|
else
|
|
log " ! $name: Klonen fehlgeschlagen — $(printf '%s' "$out" | tail -1)"
|
|
FEHLER=1
|
|
fi
|
|
fi
|
|
done
|
|
|
|
log "=== Ende (Fehler: $FEHLER) ==="
|
|
exit $FEHLER
|