#!/bin/bash # 🌲 Crumbforest Mission Doktor v2.0 # Metadata-driven, erweiterbar, Bash 3.2+ kompatibel # Inspiriert vom crumbpages-doktor.sh Konzept set -euo pipefail # === FARBEN === GREEN='\033[0;32m' BLUE='\033[0;34m' RED='\033[0;31m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color # === KONFIGURATION === SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" MISSION_DIR="${SCRIPT_DIR}/missions" ENV_FILE="${SCRIPT_DIR}/.env" # === ENVIRONMENT LOADER === function load_env() { if [[ -f "${ENV_FILE}" ]]; then # Lade .env, aber nur nicht-kommentierte Zeilen while IFS='=' read -r key value; do # Skip Kommentare und leere Zeilen [[ "$key" =~ ^#.*$ ]] && continue [[ -z "$key" ]] && continue # Entferne Quotes value="${value%\"}" value="${value#\"}" # Exportiere Variable export "$key=$value" done < <(grep -v '^#' "${ENV_FILE}" | grep -v '^$') return 0 else return 1 fi } # Versuche .env zu laden if ! load_env; then # Keine .env gefunden - das ist OK, AI Features sind dann deaktiviert AI_AVAILABLE=false else AI_AVAILABLE=true fi # ============================================================ # HILFSFUNKTIONEN # ============================================================ function show_header() { clear echo -e "${GREEN}" cat << 'EOF' 🌲 Crumbforest Mission Doktor 🌲 Willkommen im Waldlern-System! Wähle deine Kategorie: EOF echo -e "${NC}" } function load_missions_from_category() { local category="$1" local search_dir="${MISSION_DIR}/${category}" if [[ ! -d "$search_dir" ]]; then echo -e "${RED}Kategorie '$category' nicht gefunden.${NC}" return 1 fi # Arrays für Missionen (Bash 3.2+ kompatibel) MISSION_OPTIONS=() MISSION_SCRIPTS=() # Alle .sh Dateien finden while IFS= read -r file; do [[ -n "$file" ]] && MISSION_SCRIPTS+=("$file") done < <(find "$search_dir" -maxdepth 1 -type f -name "*.sh" | sort) if [[ ${#MISSION_SCRIPTS[@]} -eq 0 ]]; then echo -e "${YELLOW}Keine Missionen in dieser Kategorie gefunden.${NC}" return 1 fi # Metadaten laden for mission_file in "${MISSION_SCRIPTS[@]}"; do local mission_name mission_name="$(basename "$mission_file" .sh)" local meta_file="${search_dir}/${mission_name}.meta.json" if [[ -f "$meta_file" ]]; then local icon title enabled icon=$(jq -r '.icon // "🛸"' "$meta_file" 2>/dev/null) title=$(jq -r '.title // "Unknown"' "$meta_file" 2>/dev/null) enabled=$(jq -r '.enabled // true' "$meta_file" 2>/dev/null) # Ignoriere deaktivierte Missionen [[ "$enabled" == "false" ]] && continue MISSION_OPTIONS+=("${icon} ${title}") else # Fallback ohne Metadaten MISSION_OPTIONS+=("🛸 ${mission_name}") fi done return 0 } # ============================================================ # MISSION RUNNER # ============================================================ function run_mission_menu() { local category="$1" local category_name="$2" if ! load_missions_from_category "$category"; then read -p "Drücke Enter..." -r return fi while true; do clear echo -e "${BLUE}=== ${category_name} ===${NC}" echo "" # Beenden-Option hinzufügen MISSION_OPTIONS+=("🚪 Zurück zum Hauptmenü") PS3="Gib die Zahl deiner Wahl ein: " select opt in "${MISSION_OPTIONS[@]}"; do local choice=$((REPLY - 1)) # Beenden gewählt if [[ "$opt" == "🚪 Zurück zum Hauptmenü" ]]; then return fi # Mission starten if (( choice >= 0 && choice < ${#MISSION_OPTIONS[@]} - 1 )); then local selected_script="${MISSION_SCRIPTS[$choice]}" echo "" echo -e "${YELLOW}▶️ Starte Mission: $(basename "$selected_script")${NC}" echo "" # Mission ausführen bash "$selected_script" # Nach Mission: Zurück zum Menü echo "" echo -e "${GREEN}✅ Mission abgeschlossen!${NC}" read -p "Drücke Enter für das Menü..." -r break else echo -e "${RED}❗ Ungültige Eingabe.${NC}" fi done # Reload für nächste Iteration if ! load_missions_from_category "$category"; then return fi done } # ============================================================ # DOKTOR SYSTEM-CHECK # ============================================================ function system_doktor() { clear echo -e "${BLUE}=== 🖥️ System Doktor ===${NC}" echo "" if [[ "$OSTYPE" == "linux-gnu"* ]]; then echo -e "${CYAN}🐧 Linux System${NC}" hostnamectl 2>/dev/null || hostname echo "" uname -r echo "" free -h 2>/dev/null || echo "free: nicht verfügbar" echo "" df -h / 2>/dev/null elif [[ "$OSTYPE" == "darwin"* ]]; then echo -e "${CYAN}🍏 macOS System${NC}" hostname echo "" sw_vers 2>/dev/null echo "" echo "Memory:" vm_stat | head -n 5 echo "" echo "Disk:" df -h / else echo -e "${YELLOW}Unbekanntes System: $OSTYPE${NC}" fi echo "" echo -e "${GREEN}Bash Version: $BASH_VERSION${NC}" echo "" read -p "Drücke Enter..." -r } # ============================================================ # TOOLS CHECK (Interactive Shell) # ============================================================ function tools_doktor() { echo -e "${BLUE}--- 🛠️ Crumbforest Werkzeugkasten ---${NC}" # Temporäres RC File für die Shell TOOL_RC="/tmp/crumb_tools_$$.rc" cat > "${TOOL_RC}" << 'EOF' if [ -f /etc/bashrc ]; then source /etc/bashrc; fi if [ -f ~/.bashrc ]; then source ~/.bashrc; fi # Farben GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' # Prompt im Crumbforest-Style export PS1="\[\033[0;33m\](🛠️ Werkzeug) \u@\h:\w$ \[\033[0m\]" function tool_check() { echo -e "${YELLOW}=== Werkzeug-Verfügbarkeit ===${NC}" echo "" TOOLS="jq git curl wget python3 nano vim htop ncdu tree" for tool in $TOOLS; do if command -v "$tool" &> /dev/null; then echo -e "${GREEN}✅ $tool${NC} - $(command -v "$tool")" else echo -e "${RED}❌ $tool${NC} - Nicht installiert" fi done echo "" echo -e "${YELLOW}Mission System Requirements:${NC}" if command -v jq &> /dev/null; then echo -e "${GREEN}✅ jq verfügbar${NC} - Mission Selector funktioniert" else echo -e "${RED}⚠️ jq fehlt${NC} - Bitte installieren!" fi } alias check="tool_check" alias logs="tail -f /var/log/syslog 2>/dev/null || tail -f /var/log/system.log 2>/dev/null || echo 'Keine Standard-Logs gefunden'" echo "" echo "🌲 Willkommen im Crumbforest Werkzeugkasten!" echo "" echo "Befehle:" echo " check - Werkzeug-Verfügbarkeit prüfen" echo " logs - System-Logs anzeigen" echo " exit - Zurück zum Hauptmenü" echo "" tool_check EOF bash --rcfile "${TOOL_RC}" rm -f "${TOOL_RC}" } # ============================================================ # GIT DOKTOR (Interactive Shell) # ============================================================ function git_doktor() { echo -e "${BLUE}--- 🌲 Crumbforest Git Workstation ---${NC}" if [[ ! -d ".git" ]]; then echo -e "${RED}❌ Kein Git Repository gefunden.${NC}" read -p "Drücke Enter..." -r return fi # Temporäres RC File für die Shell GIT_RC="/tmp/crumb_git_$$.rc" cat > "${GIT_RC}" << 'EOF' if [ -f /etc/bashrc ]; then source /etc/bashrc; fi if [ -f ~/.bashrc ]; then source ~/.bashrc; fi # Farben GREEN='\033[0;32m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # Prompt im Crumbforest-Style export PS1="\[\033[0;34m\](🌲 Git) \u@\h:\w$ \[\033[0m\]" function check_health() { echo -e "${YELLOW}=== Repository Gesundheit ===${NC}" echo "" if [ ! -d ".git" ]; then echo -e "${RED}❌ Kein Git Repo!${NC}" return fi # Remote Info echo -e "${YELLOW}Remote:${NC}" git remote -v 2>/dev/null || echo "Keine Remotes" echo "" # Branch Info echo -e "${YELLOW}Current Branch:${NC}" git branch --show-current 2>/dev/null || git branch | grep '*' echo "" # Sync Check git remote update > /dev/null 2>&1 LOCAL=$(git rev-parse @ 2>/dev/null) REMOTE=$(git rev-parse @{u} 2>/dev/null) if [ "$LOCAL" = "$REMOTE" ]; then echo -e "${GREEN}✅ Synchron mit Remote${NC}" else echo -e "${YELLOW}⚠️ Nicht synchron / Push needed${NC}" fi echo "" # Status echo -e "${YELLOW}Status:${NC}" git status --short echo "" # Letzter Commit echo -e "${YELLOW}Letzter Commit:${NC}" git log -1 --oneline --decorate 2>/dev/null } # Praktische Aliases alias gst="git status" alias gd="git diff" alias gl="git log --oneline --graph --decorate --all -n 10" alias ga="git add" alias gc="git commit" alias gp="git push" alias health="check_health" echo "" echo "🌲 Willkommen in der Crumbforest Git Workstation!" echo "" echo "Befehle:" echo " health - Repository Gesundheit prüfen" echo " gst - git status" echo " gd - git diff" echo " gl - git log (graphisch)" echo " ga - git add" echo " gc - git commit" echo " gp - git push" echo " exit - Zurück zum Hauptmenü" echo "" check_health EOF bash --rcfile "${GIT_RC}" rm -f "${GIT_RC}" } # ============================================================ # AI DOKTOR (Token-Tracking & Status) # ============================================================ function ai_doktor() { clear echo -e "${BLUE}=== 🤖 AI Assistenten & Token-Tracking ===${NC}" echo "" if [[ "$AI_AVAILABLE" == "false" ]]; then echo -e "${YELLOW}⚠️ Keine .env Datei gefunden${NC}" echo "" echo "Um AI-Assistenten zu nutzen:" echo "1. Kopiere .env.template zu .env" echo " ${CYAN}cp .env.template .env${NC}" echo "" echo "2. Füge deine API-Keys ein" echo " ${CYAN}nano .env${NC}" echo "" echo "3. Starte Mission Doktor neu" echo "" read -p "Drücke Enter..." -r return fi echo -e "${CYAN}🌲 Crumbforest AI Status${NC}" echo "" # Check welche APIs konfiguriert sind echo -e "${YELLOW}Konfigurierte APIs:${NC}" [[ -n "$OPENROUTER_API_KEY" ]] && echo -e " ${GREEN}✅ OpenRouter${NC} (Model: ${OPENROUTER_MODEL:-nicht gesetzt})" [[ -n "$CLAUDE_API_KEY" ]] && echo -e " ${GREEN}✅ Claude API${NC} (Model: ${CLAUDE_MODEL:-nicht gesetzt})" [[ -n "$OPENAI_API_KEY" ]] && echo -e " ${GREEN}✅ OpenAI${NC} (Model: ${OPENAI_MODEL:-nicht gesetzt})" if [[ "$USE_OLLAMA" == "true" ]]; then echo -e " ${GREEN}✅ Ollama (Local)${NC} (Model: ${OLLAMA_MODEL:-nicht gesetzt})" fi if [[ -z "$OPENROUTER_API_KEY" ]] && [[ -z "$CLAUDE_API_KEY" ]] && [[ -z "$OPENAI_API_KEY" ]] && [[ "$USE_OLLAMA" != "true" ]]; then echo -e " ${RED}❌ Keine API-Keys konfiguriert${NC}" fi echo "" # Qdrant Status echo -e "${YELLOW}Vector Database (Qdrant):${NC}" if [[ -n "$QDRANT_URL" ]]; then echo -e " ${GREEN}✅ Konfiguriert${NC} (URL: ${QDRANT_URL})" else echo -e " ${YELLOW}⚠️ Nicht konfiguriert${NC}" fi echo "" # Token Budget echo -e "${YELLOW}Token Budget & Philosophie:${NC}" echo -e " ${CYAN}\"Was kostet die Frage eines Kindes?\"${NC}" echo -e " ${CYAN}Im Wald unbezahlbar - Token lehren achtsames Fragen.${NC}" echo "" if [[ "${DAILY_TOKEN_BUDGET:-0}" -gt 0 ]]; then echo -e " Tages-Budget: ${GREEN}${DAILY_TOKEN_BUDGET} Tokens${NC}" else echo -e " Tages-Budget: ${GREEN}Unbegrenzt${NC}" fi if [[ "${ENABLE_TOKEN_TRACKING}" == "true" ]]; then echo -e " Token-Tracking: ${GREEN}Aktiviert${NC}" else echo -e " Token-Tracking: ${YELLOW}Deaktiviert${NC}" fi echo "" # Aktivierte Charaktere echo -e "${YELLOW}Waldwächter (AI Charaktere):${NC}" [[ "${ENABLE_MAYAEULE}" == "true" ]] && echo -e " ${GREEN}✅ Maya-Eule${NC} (Weisheit)" [[ "${ENABLE_DEEPBIT}" == "true" ]] && echo -e " ${GREEN}✅ Deepbit${NC} (Bash-Erklärer)" [[ "${ENABLE_BUGSY}" == "true" ]] && echo -e " ${GREEN}✅ Bugsy${NC} (Debugging)" [[ "${ENABLE_SCHNIPPSI}" == "true" ]] && echo -e " ${GREEN}✅ Schnippsi${NC} (Shell-Helfer)" [[ "${ENABLE_TOBI}" == "true" ]] && echo -e " ${GREEN}✅ Tobi${NC} (JSON/Daten)" echo "" # Token Logs anzeigen (wenn vorhanden) if [[ "${ENABLE_TOKEN_TRACKING}" == "true" ]]; then echo -e "${YELLOW}Token-Logs:${NC}" LOG_DIR="${LOG_DIR:-$HOME/.crumbforest_logs}" if [[ -d "$LOG_DIR" ]]; then TOKEN_COUNT=$(find "$LOG_DIR" -name "token_log.json" 2>/dev/null | wc -l | tr -d ' ') echo -e " Gefunden: ${GREEN}${TOKEN_COUNT} Log-Dateien${NC}" echo "" echo -e " Ansehen mit: ${CYAN}./log_tokens_viewer_v4.sh${NC}" else echo -e " ${YELLOW}Noch keine Logs vorhanden${NC}" fi fi echo "" read -p "Drücke Enter..." -r } # ============================================================ # MAYA-EULE DOKTOR (Interactive Wisdom Shell) # ============================================================ function mayaeule_doktor() { echo -e "${BLUE}--- 🦉 Maya-Eule Weisheitsportal ---${NC}" if [[ "$AI_AVAILABLE" == "false" ]] || [[ -z "$OPENROUTER_API_KEY" ]]; then echo -e "${YELLOW}⚠️ Maya-Eule braucht einen API-Key${NC}" echo "" echo "Bitte konfiguriere .env mit OPENROUTER_API_KEY" read -p "Drücke Enter..." -r return fi # Temporäres RC File für die Shell EULE_RC="/tmp/crumb_eule_$$.rc" # Absoluter Pfad zum Maya-Eule Script MAYAEULE_PATH="${SCRIPT_DIR}/crumbforest_roles/mayaeule_zero.sh" cat > "${EULE_RC}" << EOF # Load .bashrc if exists if [ -f /etc/bashrc ]; then source /etc/bashrc; fi if [ -f ~/.bashrc ]; then source ~/.bashrc; fi # Farben GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BLUE='\033[0;34m' RED='\033[0;31m' NC='\033[0m' # Prompt im Crumbforest-Style export PS1="\[\033[1;35m\](🦉 Maya-Eule) \u@\h:\w\$ \[\033[0m\]" # Pfad zum Maya-Eule Script MAYAEULE_SCRIPT="${MAYAEULE_PATH}" function eule() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: eule \"Deine Frage\"\${NC}" return fi if [[ -x "\$MAYAEULE_SCRIPT" ]]; then "\$MAYAEULE_SCRIPT" "\$@" else echo -e "\${RED}Maya-Eule Script nicht gefunden: \$MAYAEULE_SCRIPT\${NC}" fi } function eule_help() { echo -e "\${CYAN}🦉 Maya-Eule Weisheitsportal\${NC}" echo "" echo -e "\${YELLOW}Philosophie:\${NC}" echo " \"Was kostet die Frage eines Kindes?\"" echo " Im Wald unbezahlbar - Token lehren achtsames Fragen." echo "" echo -e "\${YELLOW}Befehle:\${NC}" echo " eule \"Frage\" - Stelle Maya-Eule eine Frage" echo " eule_memory - Zeige Erinnerungen" echo " eule_tokens - Zeige Token-Verbrauch" echo " exit - Zurück zum Hauptmenü" echo "" echo -e "\${CYAN}Beispiele:\${NC}" echo " eule \"Was ist Zeit?\"" echo " eule \"Warum ist der Himmel blau?\"" echo " eule \"Was bedeutet Freundschaft?\"" } function eule_memory() { LOGDIR="\$HOME/.eule_logs" if [[ -f "\$LOGDIR/eule_history.json" ]]; then echo -e "\${CYAN}📜 Erinnerungen der Eule:\${NC}" jq -r '.[] | " \(.role): \(.content | .[0:100])..."' "\$LOGDIR/eule_history.json" 2>/dev/null || \ echo "Noch keine Erinnerungen." else echo "Noch keine Gespräche mit Maya-Eule." fi } function eule_tokens() { LOGDIR="\$HOME/.eule_logs" if [[ -f "\$LOGDIR/token_log.json" ]]; then echo -e "\${CYAN}📊 Token-Verbrauch:\${NC}" echo "" TOTAL=0 while IFS= read -r line; do zeit=\$(echo "\$line" | jq -r '.zeit') tokens=\$(echo "\$line" | jq -r '.usage.total_tokens') TOTAL=\$((TOTAL + tokens)) echo " \$zeit: \$tokens Tokens" done < "\$LOGDIR/token_log.json" echo "" echo -e "\${GREEN}Gesamt: \$TOTAL Tokens\${NC}" echo -e "\${YELLOW}Jede Frage ist wertvoll 🌲\${NC}" else echo "Noch keine Token-Logs." fi } alias help="eule_help" echo "" echo "🌲 Willkommen im Maya-Eule Weisheitsportal!" echo "" eule_help EOF bash --rcfile "${EULE_RC}" rm -f "${EULE_RC}" } # ============================================================ # CRUMBCREW COMMAND CENTRAL (Alle Waldwächter) # ============================================================ function crumbcrew_doktor() { echo -e "${GREEN}--- 🌲 CrumbCrew Command Central ---${NC}" echo -e "${CYAN}Alle Waldwächter versammeln sich!${NC}" echo "" if [[ "$AI_AVAILABLE" == "false" ]] || [[ -z "$OPENROUTER_API_KEY" ]]; then echo -e "${YELLOW}⚠️ CrumbCrew braucht einen API-Key${NC}" echo "" echo "Bitte konfiguriere .env mit OPENROUTER_API_KEY" read -p "Drücke Enter..." -r return fi # Temporäres RC File für die Shell CREW_RC="/tmp/crumb_crew_$$.rc" # Pfade zu allen Charakteren CREW_DIR="${SCRIPT_DIR}/crumbforest_roles" cat > "${CREW_RC}" << EOF # Load .bashrc if exists if [ -f /etc/bashrc ]; then source /etc/bashrc; fi if [ -f ~/.bashrc ]; then source ~/.bashrc; fi # Farben GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BLUE='\033[0;34m' RED='\033[0;31m' MAGENTA='\033[1;35m' NC='\033[0m' # Prompt im CrumbCrew-Style export PS1="\[\033[1;32m\](🌲 CrumbCrew) \u@\h:\w\$ \[\033[0m\]" # Pfad zu den Charakteren CREW_DIR="${CREW_DIR}" # === WALDWÄCHTER FUNKTIONEN === function mayaeule() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: mayaeule \"Deine Frage\"\${NC}" return fi echo -e "\${MAGENTA}🦉 Maya-Eule erwacht...\${NC}" "\$CREW_DIR/mayaeule_zero.sh" "\$@" } function deepbit() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: deepbit \"Deine Frage\"\${NC}" return fi echo -e "\${BLUE}🐙 Deepbit taucht auf...\${NC}" "\$CREW_DIR/deepbit_zero.sh" "\$@" } function bugsy() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: bugsy \"Deine Frage\"\${NC}" return fi echo -e "\${RED}🐞 Bugsy analysiert...\${NC}" "\$CREW_DIR/bugsy_zero.sh" "\$@" } function schnippsi() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: schnippsi \"Deine Frage\"\${NC}" return fi echo -e "\${CYAN}✂️ Schnippsi schnippelt...\${NC}" "\$CREW_DIR/schnippsi_zero.sh" "\$@" } function tobi() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: tobi \"Deine Frage\"\${NC}" return fi echo -e "\${GREEN}🤖 Tobi rechnet...\${NC}" "\$CREW_DIR/tobi_zero.sh" "\$@" } function schraubaer() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: schraubaer \"Deine Frage\"\${NC}" return fi echo -e "\${CYAN}🔧 Schraubbär holt das Werkzeug...\${NC}" "\$CREW_DIR/schraubaer_zero_final.sh" "\$@" } function schnecki() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: schnecki \"Deine Frage\"\${NC}" return fi echo -e "\${GREEN}🐌 Schnecki kriecht heran...\${NC}" "\$CREW_DIR/schnecki_zero.sh" "\$@" } # === DAS DREIECK === function dumbosql() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: dumbosql \"Deine Frage\"\${NC}" return fi echo -e "\${CYAN}🐘 Dumbo schlägt die Segelohren auf...\${NC}" "\$CREW_DIR/dumbosql_zero.sh" "\$@" } function funkfox() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: funkfox \"Deine Frage\"\${NC}" return fi echo -e "\${MAGENTA}🦊 FunkFox droppt in den Beat...\${NC}" "\$CREW_DIR/funkfox_zero.sh" "\$@" } function taichitaube() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: taichitaube \"Deine Frage\"\${NC}" return fi echo -e "\${CYAN}🕊️ Taube gleitet in Spiralen herab...\${NC}" "\$CREW_DIR/taichitaube_zero.sh" "\$@" } # === DIE KOMPLETTE CREW === function snakepy() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: snakepy \"Deine Frage\"\${NC}" return fi echo -e "\${GREEN}🐍 Snake gleitet durch den Code...\${NC}" "\$CREW_DIR/snakepy_zero.sh" "\$@" } function pepperphp() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: pepperphp \"Deine Frage\"\${NC}" return fi echo -e "\${YELLOW}🧓 Pepper backt ein Rezept...\${NC}" "\$CREW_DIR/pepperphp_zero.sh" "\$@" } function crabbyrust() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: crabbyrust \"Deine Frage\"\${NC}" return fi echo -e "\${RED}🦀 Crabby kneift in den Code...\${NC}" "\$CREW_DIR/crabbyrust_zero.sh" "\$@" } function spider() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: spider \"Deine Frage\"\${NC}" return fi echo -e "\${BLUE}🕷️ Spider spürt das Netz...\${NC}" "\$CREW_DIR/spider_zero.sh" "\$@" } function vektor() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: vektor \"Deine Frage\"\${NC}" return fi echo -e "\${CYAN}🧭 Vektor richtet den Kompass...\${NC}" "\$CREW_DIR/vektor_zero.sh" "\$@" } function asciimonster() { if [[ -z "\$1" ]]; then echo -e "\${YELLOW}Verwendung: asciimonster \"Deine Frage\"\${NC}" return fi echo -e "\${MAGENTA}👾 ASCII-Monster malt...\${NC}" "\$CREW_DIR/asciimonster_zero.sh" "\$@" } # === CREW MANAGEMENT === function crew_help() { echo -e "\${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}" echo -e "\${GREEN} 🌲 CrumbCrew Command Central 🌲 \${NC}" echo -e "\${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}" echo "" echo -e "\${CYAN}Die Waldwächter (Verfügbare Charaktere):\${NC}" echo "" echo -e " \${MAGENTA}🦉 mayaeule\${NC} - Die weise Eule (Philosophie, Weisheit)" echo -e " \${BLUE}🐙 deepbit\${NC} - Der poetische Oktopus (Bash-Konzepte)" echo -e " \${RED}🐞 bugsy\${NC} - Der Debugging-Clown (Fehlersuche)" echo -e " \${CYAN}✂️ schnippsi\${NC} - Der Shell-Helfer (Kommandos)" echo -e " \${GREEN}🤖 tobi\${NC} - Der Daten-Experte (JSON, Daten)" echo -e " \${CYAN}🔧 schraubaer\${NC} - Der Handwerker (Werkzeug, Schweißen)" echo -e " \${GREEN}🐌 schnecki\${NC} - Der Elektronik-Bastler (Löten, Sensoren)" echo "" echo -e "\${YELLOW}🔺 Das Dreieck (Listen-Rhythm-Guide):\${NC}" echo -e " \${CYAN}🐘 dumbosql\${NC} - Der nie vergessende Elefant (SQL, Daten)" echo -e " \${MAGENTA}🦊 funkfox\${NC} - Der Bash Rapper (Rhythm, Flow)" echo -e " \${CYAN}🕊️ taichitaube\${NC} - Die Balance-Bringerin (Spirale, Weg)" echo "" echo -e "\${GREEN}🌲 Die komplette Crew:\${NC}" echo -e " \${GREEN}🐍 snakepy\${NC} - Python Guide (Loops, Geduld)" echo -e " \${YELLOW}🧓 pepperphp\${NC} - Structure Mentor (MVC, Rezepte)" echo -e " \${RED}🦀 crabbyrust\${NC} - Security Guardian (Ownership)" echo -e " \${BLUE}🕷️ spider\${NC} - Network Feeler (Vibrationen)" echo -e " \${CYAN}🧭 vektor\${NC} - Point-to-Point Guide (Navigation)" echo -e " \${MAGENTA}👾 asciimonster\${NC} - Terminal Artist (8-bit Art)" echo "" echo -e "\${YELLOW}Crew-Befehle:\${NC}" echo " crew_status - Status aller Waldwächter" echo " crew_tokens - Token-Verbrauch aller Charaktere" echo " crew_memory - Erinnerungen aller Charaktere" echo " crew_help - Diese Hilfe" echo " exit - Zurück zum Hauptmenü" echo "" echo -e "\${CYAN}Beispiele:\${NC}" echo " mayaeule \"Was ist das Leben?\"" echo " deepbit \"Erkläre Pipes und Redirects\"" echo " bugsy \"Warum funktioniert mein Script nicht?\"" echo " schnippsi \"Wie nutze ich grep?\"" echo " tobi \"Parse dieses JSON\"" echo " schraubaer \"Welches Werkzeug brauche ich zum Löten?\"" echo " schnecki \"Wie löte ich eine LED an einen Widerstand?\"" echo "" echo -e "\${YELLOW}🔺 Das Dreieck:\${NC}" echo " dumbosql \"Wie strukturiere ich Sensor-Daten?\"" echo " funkfox \"Erkläre mir Pipes im Flow\"" echo " taichitaube \"Hilf mir, dieses Chaos zu strukturieren\"" echo "" echo -e "\${GREEN}Die komplette Crew:\${NC}" echo " snakepy \"Zeig mir 3 Wege, eine Liste zu sortieren\"" echo " pepperphp \"Erkläre MVC als Rezept\"" echo " crabbyrust \"Was bedeutet Ownership?\"" echo " spider \"Wie funktioniert eine REST API?\"" echo " vektor \"Wie navigiert ein Roboter?\"" echo " asciimonster \"Mach mir einen coolen Header\"" echo "" echo -e "\${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}" } function crew_status() { echo -e "\${CYAN}🌲 CrumbCrew Status\${NC}" echo "" CHARS=("mayaeule:🦉:Maya-Eule" "deepbit:🐙:Deepbit" "bugsy:🐞:Bugsy" "schnippsi:✂️:Schnippsi" "tobi:🤖:Tobi" "schraubaer:🔧:Schraubbär" "schnecki:🐌:Schnecki" "dumbosql:🐘:DumboSQL" "funkfox:🦊:FunkFox" "taichitaube:🕊️:TaichiTaube" "snakepy:🐍:SnakePy" "pepperphp:🧓:PepperPHP" "crabbyrust:🦀:CrabbyRust" "spider:🕷️:Spider" "vektor:🧭:Vektor" "asciimonster:👾:ASCII-Monster") for char_info in "\${CHARS[@]}"; do IFS=: read -r name icon display <<< "\$char_info" # Schraubbär has special filename if [[ "\$name" == "schraubaer" ]]; then script_name="\${name}_zero_final.sh" elif [[ "\$name" == "schnecki" ]]; then script_name="\${name}_zero.sh" else script_name="\${name}_zero.sh" fi if [[ -x "\$CREW_DIR/\$script_name" ]]; then echo -e " \${GREEN}✅ \$icon \$display\${NC} - Bereit" else echo -e " \${RED}❌ \$icon \$display\${NC} - Nicht verfügbar" fi done echo "" echo -e "\${YELLOW}API Status:\${NC}" if [[ -n "\$OPENROUTER_API_KEY" ]]; then echo -e " \${GREEN}✅ OpenRouter API\${NC} - Konfiguriert" else echo -e " \${RED}❌ Kein API-Key\${NC}" fi } function crew_tokens() { echo -e "\${CYAN}📊 CrumbCrew Token-Verbrauch\${NC}" echo "" TOTAL=0 for logdir in ~/.{mayaeule,eule,deepbit,bugsy,schnippsi,tobi,schraubaer,schnecki,dumbosql,funkfox,taichitaube,snakepy,pepperphp,crabbyrust,spider,vektor,asciimonster}_logs; do if [[ -d "\$logdir" ]] && [[ -f "\$logdir/token_log.json" ]]; then char_name=\$(basename "\$logdir" | sed 's/_logs//') char_tokens=0 while IFS= read -r line; do tokens=\$(echo "\$line" | jq -r '.usage.total_tokens' 2>/dev/null) if [[ "\$tokens" != "null" ]] && [[ -n "\$tokens" ]]; then char_tokens=\$((char_tokens + tokens)) fi done < "\$logdir/token_log.json" if [[ \$char_tokens -gt 0 ]]; then echo -e " \${GREEN}\$char_name:\${NC} \$char_tokens Tokens" TOTAL=\$((TOTAL + char_tokens)) fi fi done echo "" echo -e "\${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}" echo -e " \${GREEN}Gesamt: \$TOTAL Tokens\${NC}" echo -e " \${CYAN}Jede Frage ist wertvoll 🌲\${NC}" echo -e "\${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}" } function crew_memory() { echo -e "\${CYAN}📜 CrumbCrew Erinnerungen\${NC}" echo "" for logdir in ~/.{mayaeule,eule,deepbit,bugsy,schnippsi,tobi,schraubaer,schnecki,dumbosql,funkfox,taichitaube,snakepy,pepperphp,crabbyrust,spider,vektor,asciimonster}_logs; do if [[ -d "\$logdir" ]] && [[ -f "\$logdir/*_history.json" ]]; then char_name=\$(basename "\$logdir" | sed 's/_logs//') count=\$(jq '. | length' "\$logdir/*_history.json" 2>/dev/null) if [[ "\$count" != "null" ]] && [[ \$count -gt 0 ]]; then echo -e " \${GREEN}\$char_name:\${NC} \$count Gespräche" fi fi done } alias help="crew_help" alias status="crew_status" alias tokens="crew_tokens" alias memory="crew_memory" # Willkommensnachricht clear echo -e "\${GREEN}" cat << 'CREWEOF' 🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲 CrumbCrew Command Central Alle Waldwächter vereint! 🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲 CREWEOF echo -e "\${NC}" echo "" crew_help EOF bash --rcfile "${CREW_RC}" rm -f "${CREW_RC}" } # ============================================================ # HAUPTMENÜ # ============================================================ function main_menu() { while true; do show_header echo "1) 📚 Basics - Einsteiger Missionen" echo "2) 🚀 Advanced - Fortgeschrittene Missionen" echo "3) 🏆 Challenges - Herausforderungen" echo "4) 🤖 Robots - Roboter bauen mit der Crew" echo "" echo "--- Doktor Tools ---" echo "5) 🖥️ System Doktor" echo "6) 🛠️ Werkzeug-Check" echo "7) 🌲 Git Doktor" echo "8) 🤖 AI & Token-Tracking" echo "9) 🦉 Maya-Eule Weisheit" echo "10) 🌲 CrumbCrew - Alle Waldwächter" echo "" echo "11) 👋 Beenden" echo "" read -p "Auswahl [1-11]: " CHOICE case $CHOICE in 1) run_mission_menu "basics" "📚 Basics - Einsteiger" ;; 2) run_mission_menu "advanced" "🚀 Advanced - Fortgeschrittene" ;; 3) run_mission_menu "challenges" "🏆 Challenges" ;; 4) run_mission_menu "robots" "🤖 Robots - Roboter bauen" ;; 5) system_doktor ;; 6) tools_doktor ;; 7) git_doktor ;; 8) ai_doktor ;; 9) mayaeule_doktor ;; 10) crumbcrew_doktor ;; 11) clear echo -e "${GREEN}" echo "👋 Auf bald im Crumbforest!" echo -e "${NC}" exit 0 ;; *) echo -e "${RED}Bitte 1-10 wählen.${NC}" sleep 1 ;; esac done } # ============================================================ # START # ============================================================ main_menu