From eebf21a8fc97e25a4933c0232b1126ea952e47a7 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sun, 21 Jun 2026 23:25:17 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20BSN=20Hermes=20Onboarding-Script=20f?= =?UTF-8?q?=C3=BCr=20lokale=20Installation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/bsn-onboarding.sh | 287 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100755 docs/bsn-onboarding.sh diff --git a/docs/bsn-onboarding.sh b/docs/bsn-onboarding.sh new file mode 100755 index 0000000..824f74b --- /dev/null +++ b/docs/bsn-onboarding.sh @@ -0,0 +1,287 @@ +#!/usr/bin/env bash +# ============================================================================ +# BSN Hermes Onboarding — Lokale Installation vollständig einrichten +# ============================================================================ +# Führt ALLE Schritte aus, damit dein lokaler Hermes Agent Zugang zu allen +# BSN-Projekten, Coding-Standards und Git-Repositories hat. +# +# Ausführung: +# chmod +x bsn-onboarding.sh +# ./bsn-onboarding.sh +# ============================================================================ +set -euo pipefail + +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m' +info() { echo -e "${BLUE}ℹ${NC} $*"; } +ok() { echo -e "${GREEN}✅${NC} $*"; } +warn() { echo -e "${YELLOW}⚠️${NC} $*"; } +err() { echo -e "${RED}❌${NC} $*"; } +step() { echo -e "\n${BLUE}━━━${NC} $* ${BLUE}━━━${NC}"; } + +echo -e "${BLUE}" +echo " ╔══════════════════════════════════════════════════╗" +echo " ║ BSN Hermes Agent — Onboarding ║" +echo " ║ Brettspiel-News Community Projekt ║" +echo " ╚══════════════════════════════════════════════════╝" +echo -e "${NC}" + +# ── Schritt 0: Basis-Checks ────────────────────────────────────────── +step "Schritt 0/7: Basis-Checks" + +# Python +if command -v python3 &>/dev/null; then + PY=$(python3 --version 2>&1) + ok "Python: $PY" +else + err "python3 nicht gefunden — bitte installieren" + exit 1 +fi + +# Hermes +if command -v hermes &>/dev/null; then + HERMES_VER=$(hermes --version 2>&1 | head -1) + ok "Hermes: $HERMES_VER" +elif [ -f "$HOME/venv/bin/hermes" ]; then + export PATH="$HOME/venv/bin:$PATH" + ok "Hermes gefunden unter ~/venv/bin/hermes" +elif [ -f "$HOME/hermes-agent/hermes" ]; then + warn "Hermes nur als Source-Repo gefunden — installiere..." + curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash + export PATH="$HOME/.local/bin:$PATH" + ok "Hermes installiert" +else + err "Hermes nicht gefunden — installiere von https://github.com/NousResearch/hermes-agent" + exit 1 +fi + +# Git +if command -v git &>/dev/null; then + ok "Git: $(git --version)" +else + err "git nicht gefunden" + exit 1 +fi + +# ── Schritt 1: Python-Abhängigkeiten ────────────────────────────────── +step "Schritt 1/7: Python-Toolchain installieren" + +pip install --quiet ruff mypy pre-commit pytest pytest-cov 2>&1 | tail -1 +ok "ruff $(ruff --version 2>&1 | head -1 | cut -d' ' -f2)" +ok "mypy $(mypy --version 2>&1 | head -1 | cut -d' ' -f2)" +ok "pre-commit $(pre-commit --version 2>&1)" +ok "pytest $(pytest --version 2>&1 | head -1 | cut -d' ' -f2)" + +# ── Schritt 2: SSH-Key für Gitea ───────────────────────────────────── +step "Schritt 2/7: SSH-Zugang zu git.datenhimmel.work" + +if [ -f "$HOME/.ssh/id_ed25519.pub" ]; then + ok "SSH-Key vorhanden: $(cat $HOME/.ssh/id_ed25519.pub | cut -d' ' -f1-2)..." +else + warn "Kein SSH-Key gefunden — erstelle einen..." + ssh-keygen -t ed25519 -C "hermes@bsn-local" -f "$HOME/.ssh/id_ed25519" -N "" >/dev/null 2>&1 + ok "SSH-Key erstellt: $(cat $HOME/.ssh/id_ed25519.pub | cut -d' ' -f1-2)..." + echo -e "${YELLOW}" + echo " ╔══════════════════════════════════════════════════════════╗" + echo " ║ 🔑 DIESEN KEY in Gitea hinterlegen: ║" + echo " ║ https://git.datenhimmel.work/user/settings/keys ║" + echo " ║ ║" + cat "$HOME/.ssh/id_ed25519.pub" + echo " ║ ║" + echo " ╚══════════════════════════════════════════════════════════╝" + echo -e "${NC}" +fi + +# ── Schritt 3: Git-Repositories klonen ─────────────────────────────── +step "Schritt 3/7: BSN-Repositories klonen" + +WORKSPACE="$HOME/workspace" +mkdir -p "$WORKSPACE" + +clone_repo() { + local name=$1 repo=$2 dir="$WORKSPACE/$3" + if [ -d "$dir/.git" ]; then + ok "$name bereits vorhanden — pull..." + (cd "$dir" && git pull --ff-only 2>/dev/null) || warn "$name: pull fehlgeschlagen" + else + info "Klone $name..." + git clone "$repo" "$dir" 2>/dev/null && ok "$name geklont" || warn "$name: clone fehlgeschlagen (SSH-Key in Gitea hinterlegt?)" + fi +} + +clone_repo "BSN-Chatsystem" "git@git.datenhimmel.work:danielkrause/BSN-Chatsystem.git" "bsn-chatbot" + +# ── Schritt 4: Coding-Standards-Skill installieren ──────────────────── +step "Schritt 4/7: BSN Coding Standards Skill einrichten" + +PROFILE_DIR="$HOME/.hermes/profiles/cody" +SKILL_DIR="$PROFILE_DIR/skills/software-development/bsn-coding-standards" + +if [ -d "$SKILL_DIR" ] && [ -f "$SKILL_DIR/SKILL.md" ]; then + ok "bsn-coding-standards Skill bereits installiert" +else + # Vom Server kopieren oder lokal aus dem Repo nehmen + if [ -f "$WORKSPACE/bsn-chatbot/docs/bsn-coding-standards.html" ]; then + info "Skill aus lokalem Repo erstellen..." + mkdir -p "$SKILL_DIR/references" + + # Skill-MD aus dem Repo kopieren (falls vorhanden) oder neu erstellen + if [ -f "$WORKSPACE/bsn-chatbot/CODING_STANDARDS.md" ]; then + # Erstelle SKILL.md aus CODING_STANDARDS.md + cat > "$SKILL_DIR/SKILL.md" << 'SKILLEOF' +--- +name: bsn-coding-standards +description: Verbindliche Coding-Regeln für ALLE BSN-Projekte +version: 1.0.0 +category: software-development +--- +# BSN Coding Standards + +> Geltungsbereich: Sämtlicher Python-Code im Brettspiel-News-Community-Projekt. +> Durchsetzung: Gitea Actions (.gitea/workflows/quality.yml) + pre-commit. +> Vollständiges Dokument: docs/bsn-coding-standards.html + +## 🔴 KRITISCHE REGELN + +1. **Typ-Annotationen** — JEDE Funktion. `X | None`, nicht `Optional[X]`. +2. **Docstrings** — DEUTSCH, Google-Style. +3. **Secrets** — NIE im Code. `.env` + `.db` in `.gitignore`. +4. **Keine God-Files** — Max 500 Zeilen/Modul, max 50 Statements/Funktion. + +## 🟡 CODE-STIL +- Zeilenlänge max 100, 4 Leerzeichen, double quotes +- Import-Reihenfolge: stdlib → third-party → projekt +- Trailing Commas bei mehrzeiligen Collections + +## 🟡 NAMEN +- snake_case (Module, Funktionen, Variablen) +- PascalCase (Klassen), UPPER_SNAKE_CASE (Konstanten) + +## 🟡 SICHERHEIT +- Keine asserts in Produktion, kein pickle, bcrypt/argon2 +- Input-Validierung, parameterisierte Queries + +## 🟡 FLASK +- methods=[...] explizit, get_json(silent=True) mit None-Check +- Response mit Statuscode, CSS immer inline, BSN-Blau #20228a + +## 🟡 GIT +- Conventional Commits: feat, fix, docs, chore, security +- Vor jedem Commit: ruff check + mypy + pytest + +## 🟢 TOOLS +- ruff check . --fix && ruff format . +- mypy . (im venv!) +- pytest --cov --cov-fail-under=80 +- Gitea Actions CI: .gitea/workflows/quality.yml +SKILLEOF + ok "Skill aus CODING_STANDARDS.md erstellt" + else + warn "CODING_STANDARDS.md nicht gefunden — Skill muss manuell erstellt werden" + warn "Kopiere die SKILL.md vom Server: ~/.hermes/profiles/cody/skills/software-development/bsn-coding-standards/SKILL.md" + fi + fi +fi + +# ── Schritt 5: Hermes-Profil konfigurieren ─────────────────────────── +step "Schritt 5/7: Profil-Konfiguration" + +# Prüfen ob das cody-Profil existiert +if [ -f "$PROFILE_DIR/config.yaml" ]; then + ok "Profil 'cody' existiert" + + # Environment-Hint setzen + HINT="Befolge die BSN Coding Standards. Lade sie mit skill_view('bsn-coding-standards'). Durchsetzung: Gitea Actions (.gitea/workflows/quality.yml) + pre-commit. Volles Regelwerk: docs/bsn-coding-standards.html" + + CURRENT=$(python3 -c " +import yaml +try: + with open('$PROFILE_DIR/config.yaml') as f: + c = yaml.safe_load(f) + print(c.get('agent',{}).get('environment_hint','')) +except: pass +" 2>/dev/null) + + if [ "$CURRENT" = "$HINT" ]; then + ok "environment_hint bereits korrekt" + else + hermes config set agent.environment_hint "$HINT" 2>/dev/null && \ + ok "environment_hint gesetzt" || \ + warn "environment_hint konnte nicht gesetzt werden — manuell in $PROFILE_DIR/config.yaml eintragen" + fi +else + warn "Profil 'cody' existiert nicht — erstelle es mit: hermes profile create cody" + warn "Dann diesen Schritt wiederholen" +fi + +# ── Schritt 6: .env-Variablen prüfen ────────────────────────────────── +step "Schritt 6/7: Umgebungsvariablen" + +ENV_FILE="$HOME/.hermes/.env" +REQUIRED_VARS=("DEEPSEEK_API_KEY" "META_TOKEN" "TELEGRAM_TOKEN" "TAVILY_API_KEY") + +if [ -f "$ENV_FILE" ]; then + ok ".env-Datei vorhanden: $ENV_FILE" + + for var in "${REQUIRED_VARS[@]}"; do + if grep -q "^$var=" "$ENV_FILE" 2>/dev/null; then + ok "$var gesetzt" + else + warn "$var FEHLT in .env" + fi + done +else + warn "Keine .env-Datei gefunden. Erstelle $ENV_FILE mit:" + echo "" + for var in "${REQUIRED_VARS[@]}"; do + echo " $var=dein_key_hier" + done + echo "" +fi + +# ── Schritt 7: Verifikation ────────────────────────────────────────── +step "Schritt 7/7: Verifikation — alles grün?" + +FAILS=0 + +echo "" +info "Prüfe: Hermes erreichbar..." +hermes --version >/dev/null 2>&1 && ok "Hermes CLI" || { err "Hermes CLI"; FAILS=$((FAILS+1)); } + +info "Prüfe: Git-Zugang zu Gitea..." +ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 -T git@git.datenhimmel.work 2>&1 | grep -q "successfully authenticated" && \ + ok "SSH zu Gitea" || { warn "SSH zu Gitea — Key in Gitea hinterlegen: https://git.datenhimmel.work/user/settings/keys"; } + +info "Prüfe: Python-Tools..." +ruff --version >/dev/null 2>&1 && ok "ruff" || { err "ruff"; FAILS=$((FAILS+1)); } +mypy --version >/dev/null 2>&1 && ok "mypy" || { err "mypy"; FAILS=$((FAILS+1)); } +pytest --version >/dev/null 2>&1 && ok "pytest" || { err "pytest"; FAILS=$((FAILS+1)); } + +info "Prüfe: BSN-Skill..." +python3 -c " +import os, sys +skill_path = os.path.expanduser('$SKILL_DIR/SKILL.md') +if os.path.exists(skill_path): + sys.exit(0) +else: + sys.exit(1) +" 2>/dev/null && ok "bsn-coding-standards Skill" || { warn "Skill fehlt — Schritt 4 wiederholen"; } + +echo "" +if [ $FAILS -eq 0 ]; then + echo -e "${GREEN} ✅✅✅ ALLE CHECKS BESTANDEN — Hermes ist BSN-bereit! ✅✅✅${NC}" +else + echo -e "${YELLOW} ⚠️ $FAILS Check(s) fehlgeschlagen — siehe oben.${NC}" +fi + +echo "" +echo -e "${BLUE} 🚀 Nächster Schritt:${NC}" +echo " hermes # Interaktiver Chat" +echo " hermes chat -q \"Bearbeite Aufgabe X\"" +echo " hermes -s bsn-coding-standards # Mit BSN-Regeln starten" +echo "" + +echo -e "${BLUE} 📚 Referenzen:${NC}" +echo " Skill: skill_view('bsn-coding-standards')" +echo " Volles Regelwerk: docs/bsn-coding-standards.html" +echo " Testaufgabe: docs/bsn-agent-testaufgabe.md" +echo " CI-Workflow: .gitea/workflows/quality.yml"