pi-system/install.sh
Raimund Bauer c2056599e6 feat: Pi-Starter-Skripte und models.json ins Repo — maschinenübergreifend deploybar
GlmPi, MiniPi, FlashPi, OrchestratorPi, DeepSeekFlashPi und models.json
hinzugefügt. install.sh: alle bin/-Skripte gehen nach /usr/local/bin/
(nicht nur Sub*), agent/-Dateien werden vollständig deployt.
2026-06-02 12:24:58 +02:00

177 lines
7.1 KiB
Bash

#!/bin/bash
# PiSystem install.sh — Deterministisches Setup für alle Maschinen
#
# Installiert alle Pi-Orchestrator-Infrastrukturkomponenten:
# - bin/Sub* → ~/bin/ + /usr/local/bin/
# - extensions/ → ~/.pi/agent/extensions/
# - memory/ → ~/.pi/agent/memory/
# - agent/AGENTS.md → ~/.pi/agent/AGENTS.md
#
# Idempotent: Kann beliebig oft ausgeführt werden.
# Erstellt Backups mit Timestamp vor jedem Überschreiben.
#
# Voraussetzungen:
# - pi (Pi Agent CLI) installiert
# - tmux installiert
# - intercom (pi-intercom npm package) installiert
#
# Nutzung:
# ./install.sh # Vollinstallation
# ./install.sh --dry-run # Zeigt was getan würde ohne Änderungen
set -euo pipefail
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
DRY_RUN=false
[ "${1:-}" = "--dry-run" ] && DRY_RUN=true
TS=$(date '+%Y-%m-%d-%H-%M')
BACKUP_SUFFIX=".bak-v${TS}"
green() { echo -e "\033[0;32m✓ $*\033[0m"; }
yellow() { echo -e "\033[0;33m⚠ $*\033[0m"; }
red() { echo -e "\033[0;31m✗ $*\033[0m"; }
info() { echo -e " $*"; }
install_file() {
local src="$1"
local dst="$2"
local executable="${3:-false}"
if [ ! -f "$src" ]; then
red "Quelldatei fehlt: $src"
return 1
fi
local dst_dir
dst_dir="$(dirname "$dst")"
if $DRY_RUN; then
info "[DRY-RUN] $src$dst"
return 0
fi
mkdir -p "$dst_dir"
# Backup falls Ziel existiert und sich unterscheidet
if [ -f "$dst" ] && ! diff -q "$src" "$dst" &>/dev/null; then
cp "$dst" "${dst}${BACKUP_SUFFIX}"
info "Backup: ${dst}${BACKUP_SUFFIX}"
fi
cp "$src" "$dst"
[ "$executable" = "true" ] && chmod +x "$dst"
green "$dst"
}
echo ""
echo "═══════════════════════════════════════════════════════"
echo " PiSystem Installation — $(date '+%Y-%m-%d %H:%M')"
$DRY_RUN && echo " MODUS: DRY-RUN (keine Änderungen)"
echo "═══════════════════════════════════════════════════════"
echo ""
# ─── Voraussetzungen prüfen ─────────────────────────────────
echo "── Voraussetzungen ────────────────────────────────────"
check_cmd() {
if command -v "$1" &>/dev/null; then
green "$1 vorhanden ($(command -v "$1"))"
else
red "$1 FEHLT — Installation erforderlich: $2"
MISSING=true
fi
}
MISSING=false
check_cmd "tmux" "apt install tmux"
check_cmd "pi" "Siehe CrowdBrain neue-maschine.md für Pi-Installation"
check_cmd "zenity" "apt install zenity (für Desktop-Notifications von SubConfirm)"
$MISSING && { echo ""; red "Fehlende Voraussetzungen — Abbruch."; exit 1; }
# pi-intercom als Pi-Package prüfen (kein Shell-Binary, daher separat)
if pi list-packages 2>/dev/null | grep -q "pi-intercom"; then
green "pi-intercom installiert"
else
yellow "pi-intercom nicht gefunden — in Pi ausführen: pi install npm:pi-intercom"
fi
echo ""
# ─── bin/ → ~/bin/ ──────────────────────────────────────────
echo "── bin/ → ~/bin/ ──────────────────────────────────────"
mkdir -p "$HOME/bin"
for f in "$REPO_DIR"/bin/*; do
[ -f "$f" ] || continue
install_file "$f" "$HOME/bin/$(basename "$f")" true
done
echo ""
# ─── bin/ → /usr/local/bin/ (alle Skripte) ──────────────────
echo "── bin/ → /usr/local/bin/ ──────────────────────────────"
for f in "$REPO_DIR"/bin/*; do
[ -f "$f" ] || continue
DST="/usr/local/bin/$(basename "$f")"
if $DRY_RUN; then
info "[DRY-RUN] $f$DST (sudo)"
elif sudo -n true 2>/dev/null; then
sudo cp "$f" "$DST" && sudo chmod +x "$DST"
green "$DST"
else
yellow "/usr/local/bin: sudo nötig — übersprungen (~/bin reicht)"
break
fi
done
echo ""
# ─── Extensions ─────────────────────────────────────────────
echo "── extensions/ → ~/.pi/agent/extensions/ ──────────────"
mkdir -p "$HOME/.pi/agent/extensions"
for f in "$REPO_DIR"/extensions/*; do
[ -f "$f" ] || continue
install_file "$f" "$HOME/.pi/agent/extensions/$(basename "$f")"
done
echo ""
# ─── Memory ─────────────────────────────────────────────────
echo "── memory/ → ~/.pi/agent/memory/ ──────────────────────"
mkdir -p "$HOME/.pi/agent/memory"
for f in "$REPO_DIR"/memory/*; do
[ -f "$f" ] || continue
install_file "$f" "$HOME/.pi/agent/memory/$(basename "$f")"
done
echo ""
# ─── agent/ → ~/.pi/agent/ ──────────────────────────────────
echo "── agent/ → ~/.pi/agent/ ───────────────────────────────"
for f in "$REPO_DIR"/agent/*; do
[ -f "$f" ] || continue
install_file "$f" "$HOME/.pi/agent/$(basename "$f")"
done
echo ""
# ─── PATH prüfen ────────────────────────────────────────────
echo "── PATH-Check ──────────────────────────────────────────"
if echo "$PATH" | grep -q "$HOME/bin"; then
green "~/bin ist im PATH"
else
yellow "~/bin ist NICHT im PATH"
info "Folgendes in ~/.bashrc oder ~/.zshrc eintragen:"
info ' export PATH="$HOME/bin:$PATH"'
fi
echo ""
# ─── SubConfirm-Autostart Hinweis ───────────────────────────
echo "── SubConfirm ──────────────────────────────────────────"
if pgrep -f SubConfirm &>/dev/null; then
green "SubConfirm läuft bereits (PID: $(pgrep -f SubConfirm))"
else
yellow "SubConfirm läuft nicht"
info "Starten mit: SubConfirm --skip \"\$(tmux display-message -p '#S')\" &"
info "Für Autostart beim Pi-Session-Start: in AGENTS.md ist das bereits eingetragen."
fi
echo ""
echo "═══════════════════════════════════════════════════════"
$DRY_RUN && echo " DRY-RUN abgeschlossen — keine Änderungen vorgenommen" || echo " Installation abgeschlossen ✓"
echo "═══════════════════════════════════════════════════════"
echo ""