1028 lines
32 KiB
Bash
Executable File
1028 lines
32 KiB
Bash
Executable File
#!/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)"
|
|
REPO_ROOT="${SCRIPT_DIR}" # Save repo root before sourcing waldwaechter.sh
|
|
MISSION_DIR="${SCRIPT_DIR}/missions"
|
|
ENV_FILE="${SCRIPT_DIR}/.env"
|
|
|
|
# === LADE WALDWÄCHTER LIBRARY ===
|
|
# Macht alle Crew-Befehle verfügbar: crew_tokens, crew_doctor, etc.
|
|
if [[ -f "${SCRIPT_DIR}/lib/waldwaechter.sh" ]]; then
|
|
source "${SCRIPT_DIR}/lib/waldwaechter.sh"
|
|
fi
|
|
|
|
# === 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="${REPO_ROOT}/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() {
|
|
# Use the new crew_tokens function from waldwaechter.sh
|
|
# All logs are now in the repo logs/ directory
|
|
if command -v crew_tokens &> /dev/null; then
|
|
crew_tokens
|
|
else
|
|
# Fallback if waldwaechter.sh not loaded
|
|
LOGDIR="${REPO_ROOT}/logs"
|
|
echo -e "\${CYAN}📊 Token-Verbrauch:\${NC}"
|
|
echo ""
|
|
|
|
if [[ -d "\$LOGDIR" ]]; then
|
|
local total_tokens=0
|
|
local found_any=false
|
|
|
|
for token_file in "\$LOGDIR"/*/token_log.json; do
|
|
if [[ -f "\$token_file" ]]; then
|
|
local character=\$(basename "\$(dirname "\$token_file")")
|
|
local char_tokens=\$(grep -v '^\[\]\$' "\$token_file" | jq -s 'map(.usage.total_tokens // 0) | add // 0' 2>/dev/null || echo 0)
|
|
|
|
if [[ \$char_tokens -gt 0 ]]; then
|
|
echo " \$character: \$char_tokens Tokens"
|
|
total_tokens=\$((total_tokens + char_tokens))
|
|
found_any=true
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
if [[ \$found_any == true ]]; then
|
|
echo -e "\${GREEN}Gesamt: \$total_tokens Tokens\${NC}"
|
|
else
|
|
echo "Noch keine Token-Logs vorhanden"
|
|
fi
|
|
else
|
|
echo "Log-Verzeichnis nicht gefunden: \$LOGDIR"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "\${YELLOW}Token Budget & Philosophie:\${NC}"
|
|
echo " \"Was kostet die Frage eines Kindes?\""
|
|
echo " Im Wald unbezahlbar - Token lehren achtsames Fragen."
|
|
echo ""
|
|
if [[ -n "\${DAILY_TOKEN_BUDGET}" ]] && [[ "\${DAILY_TOKEN_BUDGET}" != "0" ]]; then
|
|
echo " Tages-Budget: \${DAILY_TOKEN_BUDGET} Tokens"
|
|
else
|
|
echo " Tages-Budget: Unbegrenzt"
|
|
fi
|
|
if [[ "\${ENABLE_TOKEN_TRACKING}" == "true" ]]; then
|
|
echo " Token-Tracking: Aktiviert"
|
|
fi
|
|
echo ""
|
|
echo -e "\${CYAN}Waldwächter (AI Charaktere):\${NC}"
|
|
echo ""
|
|
echo -e "\${YELLOW}Token-Logs:\${NC}"
|
|
if [[ \$found_any == false ]]; then
|
|
echo " Noch keine Logs vorhanden"
|
|
fi
|
|
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="${REPO_ROOT}/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\]"
|
|
|
|
# Repo Root und Pfade
|
|
REPO_ROOT="${REPO_ROOT}"
|
|
CREW_DIR="${CREW_DIR}"
|
|
|
|
# Lade Waldwächter Library für crew_tokens, crew_status, etc.
|
|
if [[ -f "\${REPO_ROOT}/lib/waldwaechter.sh" ]]; then
|
|
source "\${REPO_ROOT}/lib/waldwaechter.sh"
|
|
fi
|
|
|
|
# === 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 templatus() {
|
|
if [[ -z "\$1" ]]; then
|
|
echo -e "\${YELLOW}Verwendung: templatus \"Deine Frage\"\${NC}"
|
|
return
|
|
fi
|
|
echo -e "\${BLUE}📄 Templatus strukturiert...\${NC}"
|
|
"\$CREW_DIR/templatus_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 " \${BLUE}📄 templatus\${NC} - Der Template-Master (HTML, Struktur)"
|
|
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 " templatus \"Erstelle eine HTML5 Struktur\""
|
|
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" "templatus:📄:Templatus" "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
|
|
}
|
|
|
|
# crew_tokens, crew_memory, crew_status, crew_doctor, crew_syntax, crew_help
|
|
# sind bereits in waldwaechter.sh definiert und werden automatisch geladen
|
|
|
|
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
|