#!/bin/bash # 🌲 WaldwΓ€chter Library - AI Assistants for Crumbforest Missions # Source this file to make all AI characters available as commands # Determine the repo root directory (lib/ is inside repo root) # Support both bash and zsh if [[ -n "$BASH_VERSION" ]]; then # Bash: use BASH_SOURCE SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" elif [[ -n "$ZSH_VERSION" ]]; then # Zsh: use ${(%):-%x} to get the script path SCRIPT_DIR="$(cd "$(dirname "${(%):-%x}")" && pwd)" else # Fallback: use $0 (may not work when sourced) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" fi WALDWAECHTER_DIR="$(dirname "$SCRIPT_DIR")" ROLES_DIR="${WALDWAECHTER_DIR}/crumbforest_roles" # Set logs directory in repo export CRUMB_LOGS_DIR="${WALDWAECHTER_DIR}/logs" mkdir -p "${CRUMB_LOGS_DIR}" # Load .env if it exists ENV_FILE="${WALDWAECHTER_DIR}/.env" if [[ -f "${ENV_FILE}" ]]; then set -a source "${ENV_FILE}" set +a fi # πŸ¦‰ Maya-Eule - Die weise Eule mit GedΓ€chtnis function mayaeule() { "${ROLES_DIR}/mayaeule_zero.sh" "$@" } # πŸ”§ Deepbit - Bash-ErklΓ€rer function deepbit() { "${ROLES_DIR}/deepbit_zero.sh" "$@" } # πŸ› Bugsy - Debugging-Helfer function bugsy() { "${ROLES_DIR}/bugsy_zero.sh" "$@" } # βœ‚οΈ Schnippsi - Shell-Helfer function schnippsi() { "${ROLES_DIR}/schnippsi_zero.sh" "$@" } # πŸ“„ Templatus - HTML/Template-Helfer function templatus() { "${ROLES_DIR}/templatus_zero.sh" "$@" } # πŸ“Š Tobi - JSON/Daten-Helfer function tobi() { "${ROLES_DIR}/tobi_zero.sh" "$@" } # πŸ”§ SchraubbΓ€r - Schweres GerΓ€t, Schweißen, Werkzeug function schraubaer() { "${ROLES_DIR}/schraubaer_zero_final.sh" "$@" } # 🐌 Schnecki - Elektronik-Bastler function schnecki() { "${ROLES_DIR}/schnecki_zero.sh" "$@" } # === DAS DREIECK === # 🐘 DumboSQL - Nie vergessend function dumbosql() { "${ROLES_DIR}/dumbosql_zero.sh" "$@" } # 🦊 FunkFox - Bash Rapper function funkfox() { "${ROLES_DIR}/funkfox_zero.sh" "$@" } # πŸ•ŠοΈ Taichi Taube - Balance & Spirale function taichitaube() { "${ROLES_DIR}/taichitaube_zero.sh" "$@" } # === DIE RESTLICHEN WALDWΓ„CHTER === # 🐍 SnakePy - Python Guide function snakepy() { "${ROLES_DIR}/snakepy_zero.sh" "$@" } # πŸ§“ PepperPHP - Structure Mentor function pepperphp() { "${ROLES_DIR}/pepperphp_zero.sh" "$@" } # πŸ¦€ CrabbyRust - Security Guardian function crabbyrust() { "${ROLES_DIR}/crabbyrust_zero.sh" "$@" } # πŸ•·οΈ Spider - Network Feeler function spider() { "${ROLES_DIR}/spider_zero.sh" "$@" } # 🧭 Vektor - Point-to-Point Guide function vektor() { "${ROLES_DIR}/vektor_zero.sh" "$@" } # πŸ‘Ύ ASCII-Monster - Terminal Artist function asciimonster() { "${ROLES_DIR}/asciimonster_zero.sh" "$@" } # === CREW COMMANDS === # πŸ“Š crew_tokens - Token-Verbrauch aller WaldwΓ€chter function crew_tokens() { # Force C locale for consistent number formatting export LC_NUMERIC=C echo "πŸ“Š CrumbCrew Token-Verbrauch" echo "" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" local total_tokens=0 local total_cost=0 local crew_count=0 # Alle token_log.json Dateien finden und auswerten for token_file in "${CRUMB_LOGS_DIR}"/*/token_log.json; do if [[ -f "$token_file" ]]; then local character=$(basename "$(dirname "$token_file")") # Tokens und Kosten aus JSON extrahieren (skip erste Zeile falls es [] ist) local char_tokens=$(grep -v '^\[\]$' "$token_file" | jq -s 'map(.usage.total_tokens // 0) | add // 0' 2>/dev/null || echo 0) local char_cost=$(grep -v '^\[\]$' "$token_file" | jq -s 'map(.usage.cost // 0) | add // 0' 2>/dev/null || echo 0) if [[ $char_tokens -gt 0 ]]; then printf " %-15s %8d tokens (~\$%.6f)\n" "$character:" "$char_tokens" "$char_cost" total_tokens=$((total_tokens + char_tokens)) total_cost=$(echo "$total_cost + $char_cost" | bc -l) crew_count=$((crew_count + 1)) fi fi done echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [[ $total_tokens -gt 0 ]]; then printf " Gesamt: %d Tokens (~\$%.6f)\n" "$total_tokens" "$total_cost" printf " %d WaldwΓ€chter aktiv 🌲\n" "$crew_count" else echo " Gesamt: 0 Tokens" echo " Jede Frage ist wertvoll 🌲" fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" # Restore locale unset LC_NUMERIC } # πŸ“‹ crew_status - Status aller WaldwΓ€chter function crew_status() { echo "πŸ“‹ CrumbCrew Status (17 WaldwΓ€chter)" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" local chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster") for char in "${chars[@]}"; do local token_file="${CRUMB_LOGS_DIR}/${char}/token_log.json" if [[ -f "$token_file" ]] && grep -q -v '^\[\]$' "$token_file" 2>/dev/null; then local last_used=$(grep -v '^\[\]$' "$token_file" | tail -1 | jq -r '.zeit // "unknown"' 2>/dev/null || echo "unknown") printf " βœ… %-15s (zuletzt: %s)\n" "$char" "$last_used" else printf " βšͺ %-15s (noch nicht genutzt)\n" "$char" fi done echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" } # 🧠 crew_memory - Erinnerungen durchsuchen function crew_memory() { local query="$1" if [[ -z "$query" ]]; then echo "🧠 Crew Memory - Log-basiertes GedΓ€chtnis" echo "" echo "Verwendung: crew_memory " echo "" echo "Beispiele:" echo " crew_memory 'LED'" echo " crew_memory 'sensor'" echo "" echo "Durchsucht alle WaldwΓ€chter-Logs nach dem Begriff." return fi echo "🧠 Suche nach: '$query'" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" local found=0 for history_file in "${CRUMB_LOGS_DIR}"/*/$(basename "${history_file}" | grep '_history.json$'); do if [[ -f "$history_file" ]]; then local character=$(basename "$(dirname "$history_file")") local matches=$(grep -i "$query" "$history_file" 2>/dev/null) if [[ -n "$matches" ]]; then echo "" echo "πŸ“ $character:" echo "$matches" | jq -r '.content' 2>/dev/null | head -3 found=$((found + 1)) fi fi done echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [[ $found -gt 0 ]]; then echo " Gefunden in $found WaldwΓ€chter-Logs" else echo " Keine Treffer gefunden" fi } # 🩺 crew_doctor - System-Diagnose function crew_doctor() { echo "🩺 CrumbCrew System-Diagnose" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" local issues=0 # 1. Waldwaechter.sh Version Check echo "πŸ“‹ Checking waldwaechter.sh..." local lib_file="${WALDWAECHTER_DIR}/lib/waldwaechter.sh" if [[ -f "$lib_file" ]]; then local lib_mtime=$(stat -f "%m" "$lib_file" 2>/dev/null || stat -c "%Y" "$lib_file" 2>/dev/null) local loaded_check_var="WALDWAECHTER_LOADED_${lib_mtime}" # Indirect variable expansion (bash: ${!var}, zsh: ${(P)var}) local loaded_value="" if [[ -n "$BASH_VERSION" ]]; then loaded_value="${!loaded_check_var}" elif [[ -n "$ZSH_VERSION" ]]; then loaded_value="${(P)loaded_check_var}" fi if [[ -z "$loaded_value" ]]; then echo " ⚠️ waldwaechter.sh wurde aktualisiert!" echo " β†’ Bitte neu laden: source lib/waldwaechter.sh" issues=$((issues + 1)) else echo " βœ… waldwaechter.sh ist aktuell" fi else echo " ❌ waldwaechter.sh nicht gefunden!" issues=$((issues + 1)) fi # 2. CRUMB_LOGS_DIR Check echo "" echo "πŸ“‚ Checking CRUMB_LOGS_DIR..." if [[ -d "$CRUMB_LOGS_DIR" ]]; then echo " βœ… $CRUMB_LOGS_DIR existiert" # PrΓΌfe ob es der richtige Pfad ist (sollte im Repo sein) if [[ "$CRUMB_LOGS_DIR" == *"CF_Zero_V1/logs"* ]]; then echo " βœ… Pfad sieht korrekt aus" else echo " ⚠️ Pfad sieht ungewΓΆhnlich aus: $CRUMB_LOGS_DIR" echo " Erwartet: .../CF_Zero_V1/logs" issues=$((issues + 1)) fi else echo " ❌ $CRUMB_LOGS_DIR existiert nicht!" issues=$((issues + 1)) fi # 3. Character Scripts Check echo "" echo "🌲 Checking 17 WaldwΓ€chter Scripts..." local expected_chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster") local missing_count=0 for char in "${expected_chars[@]}"; do local script="${ROLES_DIR}/${char}_zero.sh" [[ "$char" == "schraubaer" ]] && script="${ROLES_DIR}/schraubaer_zero_final.sh" if [[ ! -f "$script" ]]; then echo " ❌ $char Script fehlt!" missing_count=$((missing_count + 1)) fi done if [[ $missing_count -eq 0 ]]; then echo " βœ… Alle 17 WaldwΓ€chter Scripts vorhanden" else echo " ❌ $missing_count Scripts fehlen!" issues=$((issues + 1)) fi # 4. Dependencies Check echo "" echo "πŸ”§ Checking Dependencies..." local deps_ok=0 for cmd in jq bc curl; do if command -v "$cmd" &> /dev/null; then echo " βœ… $cmd verfΓΌgbar" deps_ok=$((deps_ok + 1)) else echo " ❌ $cmd fehlt!" issues=$((issues + 1)) fi done # 5. Token-Logging Check echo "" echo "πŸ“Š Checking Token-Logging..." local scripts_with_logging=$(grep -l "token_log.json" "${ROLES_DIR}"/*.sh 2>/dev/null | wc -l | tr -d ' ') if [[ $scripts_with_logging -eq 17 ]]; then echo " βœ… Alle 17 Scripts haben Token-Logging" else echo " ⚠️ Nur $scripts_with_logging/17 Scripts haben Token-Logging" issues=$((issues + 1)) fi # 6. API Key Check echo "" echo "πŸ”‘ Checking API Key..." if [[ -n "$OPENROUTER_API_KEY" ]]; then echo " βœ… OPENROUTER_API_KEY gesetzt" else echo " ⚠️ OPENROUTER_API_KEY nicht gesetzt" echo " β†’ Bitte in .env konfigurieren" issues=$((issues + 1)) fi # Summary echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [[ $issues -eq 0 ]]; then echo " βœ… Alle Checks bestanden! System gesund πŸ’š" else echo " ⚠️ $issues Problem(e) gefunden" echo " Bitte oben genannte Punkte beheben" fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" } # πŸ” crew_syntax - Syntax Check aller Scripts function crew_syntax() { echo "πŸ” CrumbCrew Syntax Check" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "" local errors=0 local checked=0 echo "PrΓΌfe WaldwΓ€chter Scripts..." echo "" # Check lib/waldwaechter.sh if bash -n "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null; then echo " βœ… lib/waldwaechter.sh" else echo " ❌ lib/waldwaechter.sh - SYNTAX ERROR!" bash -n "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" errors=$((errors + 1)) fi checked=$((checked + 1)) # Check all character scripts for script in "${ROLES_DIR}"/*_zero*.sh; do if [[ -f "$script" ]]; then local name=$(basename "$script") if bash -n "$script" 2>/dev/null; then echo " βœ… $name" else echo " ❌ $name - SYNTAX ERROR!" echo "" bash -n "$script" 2>&1 | sed 's/^/ /' echo "" errors=$((errors + 1)) fi checked=$((checked + 1)) fi done # Check mission scripts (optional) echo "" echo "PrΓΌfe Mission Scripts..." echo "" for script in "${WALDWAECHTER_DIR}/missions"/*/*.sh; do if [[ -f "$script" ]]; then local name=$(basename "$script") if bash -n "$script" 2>/dev/null; then echo " βœ… $name" else echo " ❌ $name - SYNTAX ERROR!" errors=$((errors + 1)) fi checked=$((checked + 1)) fi done echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" if [[ $errors -eq 0 ]]; then echo " βœ… $checked Scripts geprΓΌft - Keine Syntax-Fehler! πŸ’š" else echo " ❌ $errors von $checked Scripts haben Syntax-Fehler" fi echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" } # ❓ crew_help - Hilfe fΓΌr Crew-Befehle function crew_help() { cat << 'EOF' 🌲 CrumbCrew Befehle ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Crew-Verwaltung: crew_help Diese Hilfe anzeigen crew_status Status aller 17 WaldwΓ€chter crew_tokens Token-Verbrauch ALLER Charaktere crew_memory Erinnerungen durchsuchen crew_doctor System-Diagnose (Version, Pfade, Dependencies) crew_syntax Syntax Check aller Scripts Einzelne WaldwΓ€chter: πŸ”Ί Das Dreieck (Foundation): dumbosql SQL & Datenstrukturen funkfox Bash im Beat taichitaube Balance & Spirale πŸ”§ Hardware-Team: tobi Elektronik-Theorie (CapaciTobi) schnecki Elektronik-Basteln schraubaer Mechanik & Werkzeug πŸ’» Code-Team: snakepy Python Guide pepperphp Structure Mentor crabbyrust Security Guardian spider Network Feeler 🎨 UI-Team: schnippsi CSS & Styling templatus Template-Master asciimonster Terminal Artist 🧭 System-Team: mayaeule Weise Eule deepbit Bash-ErklΓ€rer bugsy Debugging-Helfer vektor Navigation ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Beispiele: funkfox "ErklΓ€re mir Pipes im Flow!" crew_tokens crew_memory "LED" "Was kostet die Frage eines Kindes?" πŸ’š EOF } # Export functions so they're available in subshells # Note: export -f works in bash, but not in zsh # In zsh, functions are automatically available in the current shell # For bash compatibility, we still do export -f, but it's optional in zsh if [[ -n "$BASH_VERSION" ]]; then # Bash: use export -f export -f mayaeule export -f deepbit export -f bugsy export -f schnippsi export -f templatus export -f tobi export -f schraubaer export -f schnecki export -f dumbosql export -f funkfox export -f taichitaube export -f snakepy export -f pepperphp export -f crabbyrust export -f spider export -f vektor export -f asciimonster export -f crew_tokens export -f crew_status export -f crew_memory export -f crew_doctor export -f crew_syntax export -f crew_help fi # In zsh, functions are available without export -f # Set version marker for crew_doctor to detect reloads if [[ -f "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" ]]; then WALDWAECHTER_LIB_MTIME=$(stat -f "%m" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null || stat -c "%Y" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null) export "WALDWAECHTER_LOADED_${WALDWAECHTER_LIB_MTIME}=1" fi