BSD - OSX - LINUX :D

This commit is contained in:
sysop
2026-01-08 19:50:17 +01:00
parent cc98b7015b
commit e9b8e9f5a4
10 changed files with 124 additions and 208 deletions

View File

@@ -1,80 +0,0 @@
# ============================================================
# 🌲 Crumbforest Mission System - Environment Configuration
# ============================================================
#
# Philosophie: "Was kostet die Frage eines Kindes?"
# Im Wald unbezahlbar - aber Token helfen beim achtsamen Fragen.
# Jede Frage ist wertvoll, Token-Messung lehrt bewusstes Denken.
#
# ============================================================
# === API KEYS ===
# OpenRouter (Multi-Model Gateway)
OPENROUTER_API_KEY=""
OPENROUTER_MODEL="openai/gpt-3.5-turbo" # oder anthropic/claude-3-haiku
# Claude API (Anthropic)
CLAUDE_API_KEY=""
CLAUDE_MODEL="claude-3-haiku-20240307"
# OpenAI
OPENAI_API_KEY=""
OPENAI_MODEL="gpt-3.5-turbo"
# === LOCAL AI (Optional) ===
# Ollama (Local AI - kostenlos!)
OLLAMA_URL="http://localhost:11434"
OLLAMA_MODEL="llama3.2:3b"
USE_OLLAMA="false" # true = nutze Ollama statt API
# === VECTOR DATABASE ===
# Qdrant (für Maya-Eule Memory)
QDRANT_URL="http://localhost:6333"
QDRANT_COLLECTION="crumbforest_memory"
QDRANT_API_KEY="" # Optional, meist leer bei local
# === TOKEN BUDGET (Crumb Codex: Machen statt Lernen) ===
# Tages-Budget für bewusstes Fragen (in Tokens)
# 0 = unbegrenzt, >0 = Limit (z.B. 10000 = ~20 Fragen)
DAILY_TOKEN_BUDGET="0"
# Warnung bei hohem Token-Verbrauch
TOKEN_WARNING_THRESHOLD="1000"
# === LOGGING ===
# Token-Log speichern?
ENABLE_TOKEN_TRACKING="true"
# Log-Verzeichnis
LOG_DIR="${HOME}/.crumbforest_logs"
# === CHARAKTERE (AI Assistenten) ===
# Welche Charaktere sind aktiviert?
ENABLE_MAYAEULE="true" # Maya-Eule (Weisheit)
ENABLE_DEEPBIT="true" # Deepbit (Bash-Erklärer)
ENABLE_BUGSY="true" # Bugsy (Debugging)
ENABLE_SCHNIPPSI="true" # Schnippsi (Shell-Helfer)
ENABLE_TOBI="true" # Tobi (JSON/Daten)
# === SICHERHEIT ===
# Eltern-PIN für Einstellungen (Optional)
PARENT_PIN=""
# Automatische Token-Reports an Eltern?
SEND_TOKEN_REPORTS="false"
PARENT_EMAIL=""
# ============================================================
# HINWEISE:
# - Kopiere diese Datei zu .env und fülle deine Keys ein
# - .env wird NICHT ins Git committed (siehe .gitignore)
# - Mindestens einen API-Key ODER Ollama konfigurieren
# - Qdrant ist optional (für Maya-Eule Memory)
# ============================================================

2
.gitignore vendored
View File

@@ -71,6 +71,8 @@ build/
*.bak
*.backup
*_backup_*.zip
*.snapshot
.pp_backup/
# Personal/Secret directories

58
INSTALL_DEBIAN.md Normal file
View File

@@ -0,0 +1,58 @@
# 🌲 Crumbforest Debian Setup Guide (Raspi Ready)
This guide documents the specific setup steps for Debian-based systems (including Raspberry Pi and Ubuntu). It supplements the standard `README.md`.
## 1. System Services (Headless / Persistent)
On Debian/Raspi, we use Systemd User Services to keep components running in the background without needing open terminal windows.
### Qdrant (Vector DB)
- **Service**: `~/.config/systemd/user/qdrant.service`
- **Port**: 6333
- **Usage**: Stores the RAG knowledge (CrumbCodex).
- **Note**: The native binary often excludes the Web Dashboard (`/dashboard`) to save resources. Use API or Snapshot Export for visualization.
### Ollama (AI Model Server)
- **Service**: `~/.config/systemd/user/ollama.service`
- **Port**: 11434
- **Usage**: Serves local AI models (e.g. `tinyllama` or embedding models).
**Enable Services:**
```bash
systemctl --user enable --now qdrant ollama
systemctl --user status qdrant ollama
```
## 2. RAG Knowledge Setup (Nullfeld)
The "Nullfeld" (Zero Field) is the vector database containing our documentation.
### Ingestion Sources
1. **CrumbCodex**: `~/Documents/crumbdocs/CrumbCodex`
2. **OZM-Keks-Handbuch**: `~/Documents/crumbdocs/OZM-Keks-Handbuch-v1`
### Running Ingestion
If you add new Markdown files, run:
```bash
python3 missions/tools/terminal_dojo/scripts/ingest_knowledge.py ~/Documents/crumbdocs
```
*Embedding Model used: `all-minilm` (384 dimensions).*
### Data Visualization
Since the native Qdrant has no dashboard:
1. **Create Snapshot**: `curl -X POST http://localhost:6333/collections/crumbforest_knowledge/snapshots`
2. **Export**: Find file in `~/.terminal_dojo/qdrant/snapshots/`.
3. **View**: Import into a Dockerized Qdrant instance on your Desktop.
## 3. Crew Shell Resilience
The `crew` command (`~/.terminal_dojo/crew.sh`) is patched for robustness:
- **Local Mode**: If `ollama` is running with a valid chat model (e.g., `tinyllama`, `llama3`), it runs locally.
- **Cloud Fallback**: If local models fail (common on low-power devices), it automatically falls back to the **OpenRouter API** (via `waldwaechter.sh`).
**Check Status**:
```bash
crew_doctor
```
Should return `✅ Alle Checks bestanden! System gesund 💚`.

View File

@@ -33,20 +33,10 @@ 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 '^$')
# Use set -a to automatically export variables defined in .env
set -a
source "${ENV_FILE}"
set +a
return 0
else
return 1
@@ -652,6 +642,10 @@ function crumbcrew_doktor() {
if [ -f /etc/bashrc ]; then source /etc/bashrc; fi
if [ -f ~/.bashrc ]; then source ~/.bashrc; fi
# Unalias potential user aliases that might conflict with our functions
unalias mayaeule deepbit bugsy schnippsi tobi schraubaer schnecki dumbosql funkfox taichitaube snakepy pepperphp crabbyrust spider vektor asciimonster 2>/dev/null || true
# Farben
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
@@ -667,7 +661,13 @@ export PS1="\[\033[1;32m\](🌲 CrumbCrew) \u@\h:\w\$ \[\033[0m\]"
# Pfad zu den Charakteren
CREW_DIR="${CREW_DIR}"
# === WALDWÄCHTER FUNKTIONEN ===
# Lade die Waldwächter-Library (für crew_tokens, crew_status, etc.)
# Wir nutzen die gepatchte Library, die auch korrekte Pfade hat
source "${SCRIPT_DIR}/lib/waldwaechter.sh"
# === WALDWÄCHTER FUNKTIONEN (Wrapper für UI-Output) ===
# Wir behalten diese Wrapper, weil sie schöne "Erwacht..." Nachrichten ausgeben.
# Die eigentliche Logik kommt jetzt aus waldwaechter.sh
function mayaeule() {
if [[ -z "\$1" ]]; then
@@ -818,7 +818,9 @@ function asciimonster() {
}
# === CREW MANAGEMENT ===
# crew_tokens, crew_status etc. kommen jetzt aus der Library!
# Wir definieren nur crew_help neu für den speziellen Kontext
function crew_help() {
echo -e "\${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\${NC}"
echo -e "\${GREEN} 🌲 CrumbCrew Command Central 🌲 \${NC}"
@@ -879,90 +881,11 @@ function crew_help() {
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"
# Aliases tokens/status/memory kommen jetzt von waldwaechter.sh (wenn dort definiert)
# oder Nutzer nutzt direkt crew_tokens
# Willkommensnachricht
clear

View File

@@ -6,16 +6,16 @@
# Support both bash and zsh
if [[ -n "$BASH_VERSION" ]]; then
# Bash: use BASH_SOURCE
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
__WALD_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)"
__WALD_SCRIPT_DIR="$(cd "$(dirname "${(%):-%x}")" && pwd)"
else
# Fallback: use $0 (may not work when sourced)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
__WALD_SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
fi
WALDWAECHTER_DIR="$(dirname "$SCRIPT_DIR")"
WALDWAECHTER_DIR="$(dirname "$__WALD_SCRIPT_DIR")"
ROLES_DIR="${WALDWAECHTER_DIR}/crumbforest_roles"
# Set logs directory in repo
@@ -178,7 +178,7 @@ function crew_status() {
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster")
local chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster" "bashpanda")
for char in "${chars[@]}"; do
local token_file="${CRUMB_LOGS_DIR}/${char}/token_log.json"
@@ -253,7 +253,7 @@ function crew_doctor() {
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 lib_mtime=$(stat -c "%Y" "$lib_file" 2>/dev/null || stat -f "%m" "$lib_file" 2>/dev/null)
local loaded_check_var="WALDWAECHTER_LOADED_${lib_mtime}"
# Indirect variable expansion (bash: ${!var}, zsh: ${(P)var})
@@ -283,12 +283,9 @@ function crew_doctor() {
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))
# Path check relaxed for Crumbmissions
if [[ -d "$CRUMB_LOGS_DIR" ]]; then
echo " ✅ Pfad für Logs gefunden: $CRUMB_LOGS_DIR"
fi
else
echo "$CRUMB_LOGS_DIR existiert nicht!"
@@ -297,8 +294,8 @@ function crew_doctor() {
# 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")
echo "🌲 Checking 18 Waldwächter Scripts..."
local expected_chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster" "bashpanda")
local missing_count=0
for char in "${expected_chars[@]}"; do
@@ -312,7 +309,7 @@ function crew_doctor() {
done
if [[ $missing_count -eq 0 ]]; then
echo " ✅ Alle 17 Waldwächter Scripts vorhanden"
echo " ✅ Alle 18 Waldwächter Scripts vorhanden"
else
echo "$missing_count Scripts fehlen!"
issues=$((issues + 1))
@@ -336,10 +333,10 @@ function crew_doctor() {
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"
if [[ $scripts_with_logging -eq 18 ]]; then
echo " ✅ Alle 18 Scripts haben Token-Logging"
else
echo " ⚠️ Nur $scripts_with_logging/17 Scripts haben Token-Logging"
echo " ⚠️ Nur $scripts_with_logging/18 Scripts haben Token-Logging"
issues=$((issues + 1))
fi
@@ -716,6 +713,6 @@ fi
# 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)
WALDWAECHTER_LIB_MTIME=$(stat -c "%Y" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null || stat -f "%m" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null)
export "WALDWAECHTER_LOADED_${WALDWAECHTER_LIB_MTIME}=1"
fi

View File

@@ -129,11 +129,15 @@ echo ""
# Verify Installation
# ─────────────────────────────────────────────────────────────────────────────
# Reload PATH
export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH"
# Reload PATH for current session
export PATH="$HOME/.opencode/bin:$HOME/.local/bin:$HOME/.npm-global/bin:$PATH"
if command -v opencode &> /dev/null; then
VERSION=$(opencode --version 2>/dev/null | head -n1 || echo "installed")
if command -v opencode &> /dev/null || [[ -f "$HOME/.opencode/bin/opencode" ]]; then
if command -v opencode &> /dev/null; then
VERSION=$(opencode --version 2>/dev/null | head -n1 || echo "installed")
else
VERSION=$("$HOME/.opencode/bin/opencode" --version 2>/dev/null | head -n1 || echo "installed")
fi
echo -e "${GREEN}✓ OpenCode erfolgreich installiert: $VERSION${NC}"
else
echo -e "${RED}❌ OpenCode Installation fehlgeschlagen${NC}"

View File

@@ -206,7 +206,8 @@ case $INSTALL_METHOD in
#!/bin/bash
QDRANT_DIR="$HOME/.terminal_dojo/qdrant"
cd "$QDRANT_DIR"
./qdrant --storage-path ./storage &
export QDRANT__STORAGE__PATH=./storage
./qdrant &
echo $! > "$QDRANT_DIR/qdrant.pid"
echo "Qdrant gestartet (PID: $(cat $QDRANT_DIR/qdrant.pid))"
SCRIPT

View File

@@ -115,6 +115,14 @@ if [[ "$OPENCODE_OK" != true ]]; then
echo ""
if [[ ! $REPLY =~ ^[Nn]$ ]]; then
if [[ -f "${SCRIPT_DIR}/02_opencode_setup.sh" ]]; then
# Ensure system info exists
if [[ ! -f /tmp/terminal_dojo_sysinfo.json ]]; then
echo -e "${YELLOW}⚠️ System-Info fehlt. Starte Vorcheck...${NC}"
if [[ -f "${SCRIPT_DIR}/01_vorcheck.sh" ]]; then
bash "${SCRIPT_DIR}/01_vorcheck.sh"
fi
fi
bash "${SCRIPT_DIR}/02_opencode_setup.sh"
# Re-Check
if command -v opencode &> /dev/null; then OPENCODE_OK=true; fi

View File

@@ -10,7 +10,7 @@ from uuid import uuid4
# Configuration
OLLAMA_BASE_URL = "http://localhost:11434"
QDRANT_BASE_URL = "http://localhost:6333"
EMBEDDING_MODEL = "nomic-embed-text"
EMBEDDING_MODEL = "all-minilm"
COLLECTION_NAME = "crumbforest_knowledge"
def get_embedding(text: str) -> List[float]:
@@ -41,21 +41,21 @@ def create_collection_if_not_exists():
config = response.json().get("result", {}).get("config", {}).get("params", {}).get("vectors", {})
current_size = config.get("size")
if current_size == 768:
print(f"Collection '{COLLECTION_NAME}' exists and has correct dimension (768).")
if current_size == 384:
print(f"Collection '{COLLECTION_NAME}' exists and has correct dimension (384).")
return
else:
print(f"Collection '{COLLECTION_NAME}' has wrong dimension ({current_size}). Recreating for nomic-embed-text (768)...")
print(f"Collection '{COLLECTION_NAME}' has wrong dimension ({current_size}). Recreating for all-minilm (384)...")
requests.delete(url)
except Exception as e:
print(f"Error checking collection: {e}")
# Proceed to try verify/create
print(f"Creating collection '{COLLECTION_NAME}'...")
# Create with 768 dimensions (Nomic Embed Text v1.5)
# Create with 384 dimensions (all-minilm)
payload = {
"vectors": {
"size": 768,
"size": 384,
"distance": "Cosine"
}
}

View File

@@ -20,6 +20,9 @@ NC='\033[0m'
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Ensure we can find tools in common locations
export PATH="$HOME/.opencode/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/usr/local/bin:$PATH"
show_banner() {
clear
echo ""