diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..07bd68f --- /dev/null +++ b/.gitignore @@ -0,0 +1,92 @@ +# === CF_Zero_V1 .gitignore === + +# AI Assistant Logs (contain conversation history and token usage) +.bits_logs/ +.bugsy_logs/ +.deepbit_logs/ +.dumbo_logs/ +.eule_logs/ +.funkfox_logs/ +.pepper_logs/ +.schnecki_logs/ +.schnippsi_logs/ +.schraubaer_logs/ +.snake_logs/ +.stage_logs/ +.taube_logs/ +.templatus_logs/ +.tobi_logs/ +.missionstage_log/ +.bugsy_log/ + +# Individual log files +*.jsonl +*_log.json +*.log +mission_log_*.log + +# Environment variables (API keys!) +.env +.env.local +*.key + +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +env/ +venv/ +ENV/ +*.egg-info/ +dist/ +build/ + +# Camera/Video temp files +*.mp4 +*.avi +*.mov + +# Backups +*.zip +*.bak +*.backup +*_backup_*.zip +.pp_backup/ + +# Personal/Secret directories +geheimversteck/ +usr/ + +# MacOS +.DS_Store +.AppleDouble +.LSOverride + +# Cache +.cache/ +*.cache + +# Node modules (for ttyd/html) +node_modules/ +package-lock.json +yarn.lock + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Config directories that may contain keys +.config/ +.local/ +.crumbair/ +.dotnet/ + +# Temporary files +/tmp/ +*.tmp +*.temp diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f61b995 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,247 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## CF_Zero_V1 Project Overview + +CF_Zero_V1 is an educational Bash learning platform called "Crumbforest" that uses character-based AI assistants to teach command-line concepts through interactive missions. The project combines shell scripting, Python-based computer vision, and OpenRouter API integration to create an immersive learning experience. + +## Key Commands + +### Mission System +```bash +# Launch the interactive mission selector +./crumb-mission-selector.sh + +# Run individual missions directly +bash missions/basics/fridolin.sh # Navigation basics +bash missions/basics/balu.sh # File creation +bash missions/basics/noko.sh # File reading +bash missions/advanced/dns_mission.sh # DNS tools +bash missions/advanced/ssh_security.sh # SSH basics +``` + +### AI Character Assistants (Crumbforest Roles) +All roles require `OPENROUTER_API_KEY` environment variable: +```bash +export OPENROUTER_API_KEY="your-key-here" + +# Character-based CLI assistants +./crumbforest_roles/deepbit_zero.sh "How do I use grep?" +./crumbforest_roles/bugsy_zero.sh "Explain loops in bash" +./crumbforest_roles/schnippsi_zero.sh "What is curl?" +./crumbforest_roles/tobi_zero.sh "How to use jq?" +``` + +### Camera Vision System (SnakeCam) +```bash +# Start the Flask-based gesture recognition app +cd snake_camera_vision_v2 +python app.py +# Access at http://localhost:5000 + +# View gesture detection module +python gestures/gestures_v4.py +``` + +### Token Usage Monitoring +```bash +# View token usage across all AI assistants +./log_tokens_viewer_v4.sh + +# Clean up malformed token logs +./fix_token_logs.sh + +# Check individual agent logs +cat ~/.deepbit_logs/token_log.json +cat ~/.bugsy_logs/token_log.json +``` + +## Architecture Overview + +### Mission System Architecture + +**Metadata-Driven Design:** +- Each mission consists of two files: `mission_name.sh` (executable) and `mission_name.meta.json` (metadata) +- The mission selector (`crumb-mission-selector.sh`) dynamically loads missions by scanning directories +- Metadata structure: + ```json + { + "icon": "🦊", + "title": "Mission Title", + "description": "What this teaches", + "category": "basics|advanced|challenges", + "enabled": true + } + ``` + +**Mission Categories:** +- `missions/basics/` - Beginner missions (navigation, file operations) +- `missions/advanced/` - Advanced topics (DNS, SSH, networking) +- `missions/challenges/` - Interactive challenges (future) + +### AI Assistant Architecture + +**Character-Based Learning Roles:** +Each role is a specialized bash script that wraps OpenRouter API calls with distinct personalities: + +- **Deepbit** (octopus) - Explains Bash concepts poetically to children +- **Bugsy** - Debugging and troubleshooting assistant +- **Schnippsi** - General shell command helper +- **Tobi** - JSON/data processing expert +- **Templatus** - HTML architecture assistant + +**Common Pattern:** +1. Accept question as command-line argument +2. Store conversation history in `~/.{role}_logs/{role}_history.json` +3. Track token usage in `~/.{role}_logs/token_log.json` +4. Use OpenRouter API with `openai/gpt-3.5-turbo` model +5. Respond in the same language as the input question + +**API Flow:** +```bash +Question → JSON Payload → OpenRouter API → Response → Log History → Display +``` + +**Log Structure:** +- Request: `~/.{role}_logs/{role}_request.json` +- Response: `~/.{role}_logs/{role}_response.json` +- History: `~/.{role}_logs/{role}_history.json` +- Token usage: `~/.{role}_logs/token_log.json` + +### Camera Vision System (SnakeCam) + +**Technology Stack:** +- Flask web server with MJPEG video streaming +- OpenCV for camera capture and image processing +- Custom gesture detection using HSV color space and contour analysis + +**Key Components:** +- `app.py` - Flask application with video streaming endpoints +- `gestures/gestures_v4.py` - Hand gesture detection algorithm +- Detection method: Skin color detection → Contour analysis → Convexity defects → Gesture classification +- Current gestures: "wave" detection based on defect count, area, and aspect ratio + +**Endpoints:** +- `/` - Main camera interface +- `/video_feed` - MJPEG stream +- `/log_answer` - Log user responses with mood and gesture +- `/shutdown` - Clean camera release + +## Project Structure + +``` +CF_Zero_V1/ +├── crumb-mission-selector.sh # Main mission launcher (metadata-driven) +├── missions/ # Educational missions +│ ├── basics/ # Beginner tutorials +│ │ ├── fridolin.sh/meta.json # Navigation (pwd, ls, cd) +│ │ ├── balu.sh/meta.json # File creation (mkdir, touch, echo) +│ │ └── noko.sh/meta.json # File reading (cat, grep) +│ └── advanced/ # Advanced topics +│ ├── dns_mission.sh/meta.json # DNS tools (dig, nslookup, host) +│ └── ssh_security.sh/meta.json # SSH basics +├── crumbforest_roles/ # AI character assistants +│ ├── deepbit_zero.sh # Poetic Bash explainer +│ ├── bugsy_zero.sh # Debugging helper +│ ├── schnippsi_zero.sh # Shell command assistant +│ └── tobi_zero.sh # JSON/data expert +├── snake_camera_vision_v2/ # Flask gesture recognition app +│ ├── app.py # Main Flask server +│ └── gestures/ # Gesture detection modules +│ ├── gestures_v4.py # Hand detection algorithm +│ └── gestures_debug_test.py # Debug version with visualization +├── log_tokens_viewer_v4.sh # Token usage viewer +└── fix_token_logs.sh # Clean malformed logs +``` + +## Important Implementation Notes + +### Adding New Missions + +1. Create two files in appropriate category folder: + ```bash + touch missions/basics/new_mission.sh + touch missions/basics/new_mission.meta.json + chmod +x missions/basics/new_mission.sh + ``` + +2. Metadata must include: + - `icon`: Emoji for menu display + - `title`: Human-readable name + - `description`: What the mission teaches + - `category`: basics/advanced/challenges + - `enabled`: true/false + +3. Mission script should: + - Use `cat << 'EOF'` for multi-line instructions + - Include interactive prompts with `read -p` + - Provide examples before asking user to try + - End with success message + +### Creating New AI Assistants + +1. Copy template from existing role (e.g., `deepbit_zero.sh`) +2. Update these variables: + - `LOGDIR` - Log directory path + - System prompt in `jq -n` command + - Character name in echo statements +3. Create log directory structure automatically via `mkdir -p` +4. Initialize empty JSON arrays for history and token logs + +### Token Log Format + +Each role logs API usage in this format: +```json +{ + "zeit": "2025-06-18 19:05:33", + "rolle": "deepbit", + "usage": { + "prompt_tokens": 45, + "completion_tokens": 123, + "total_tokens": 168 + } +} +``` + +### Gesture Detection Tuning + +Located in `snake_camera_vision_v2/gestures/gestures_v4.py`: +- **HSV Range**: `lower_skin=[0,30,60]`, `upper_skin=[20,150,255]` +- **ROI**: Fixed at (100,100) with 150x150 size +- **Area Threshold**: 2500-15000 pixels for valid hand detection +- **Defect Count**: 3-10 convexity defects for "wave" gesture +- **Aspect Ratio**: 1.3-2.3 for hand shape validation + +## Environment Requirements + +### AI Assistants +- `OPENROUTER_API_KEY` must be exported +- `jq` for JSON processing +- `curl` for API calls + +### Camera System +- Python 3.x +- Flask (`pip install flask`) +- OpenCV (`pip install opencv-python`) +- Webcam at `/dev/video0` or default camera index 0 + +### Mission System +- Bash 4.0+ +- `jq` for metadata parsing +- Standard Unix tools (ls, cat, grep, etc.) + +## Philosophy and Design Principles + +**"Waldwächter" (Forest Guardian) Philosophy:** +- Transparency over magic +- Metadata-driven extensibility +- Educational and interactive +- No code changes required to add new content +- Multilingual support (responds in input language) + +**Character-Based Learning:** +- Each AI assistant has distinct personality and teaching style +- Poetic and metaphorical explanations for complex concepts +- Designed for children and beginners +- Conversational history maintained across sessions diff --git a/backup_zero.sh b/backup_zero.sh new file mode 100755 index 0000000..ab45a4a --- /dev/null +++ b/backup_zero.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +echo "📦 Starte Backup des Crumbforest Zero Systems..." + +# Zielname +BACKUP_NAME="crumbforest_zero_backup_$(date +%Y%m%d_%H%M%S).zip" +DEST_DIR="/home/zero" +FULL_PATH="$DEST_DIR/$BACKUP_NAME" + +# Verzeichnisse und Dateien sammeln +INCLUDE_PATHS=( + "/usr/local/bin/crumbmission" + "/home/zero/crumbforest_backup" + "/home/zero/.bits_logs" + "/home/zero/.eule_logs" + "/home/zero/.snake_logs" + "/home/zero/.pepper_logs" + "/home/zero/.bugsy_logs" + "/home/zero/.deepbit_logs" + "/home/zero/.dumbo_logs" + "/home/zero/.funkfox_logs" + "/home/zero/.schnecki_logs" + "/home/zero/.schnippsi_logs" + "/home/zero/.schraubaer_logs" + "/home/zero/.stage_logs" + "/home/zero/.taube_logs" + "/home/zero/.templatus_logs" + "/home/zero/.tobi_logs" + "/home/zero/.missionstage_log" + +) + +# Existierende Pfade prüfen und nur diese einfügen +EXISTING_PATHS=() +for path in "${INCLUDE_PATHS[@]}"; do + if [ -e "$path" ]; then + echo "✅ Hinzufügen: $path" + EXISTING_PATHS+=("$path") + else + echo "⚠️ Nicht gefunden (wird übersprungen): $path" + fi +done + +# Archiv erstellen +cd / +zip -r "$FULL_PATH" "${EXISTING_PATHS[@]}" > /dev/null + +if [ $? -eq 0 ]; then + echo "🎉 Backup erfolgreich erstellt: $FULL_PATH" +else + echo "❌ Fehler beim Erstellen des Backups." +fi diff --git a/crumb-mission-selector.sh b/crumb-mission-selector.sh new file mode 100755 index 0000000..c6dd46f --- /dev/null +++ b/crumb-mission-selector.sh @@ -0,0 +1,184 @@ +#!/bin/bash + +# ============================================================ +# 🌲 Crumb Mission Selector - Lernpfade im Crumbforest +# ============================================================ +# Inspiriert von CF_Zero_V1 dynamic_mission_selector.sh +# Metadata-driven, erweiterbar, bildungsfreundlich +# ============================================================ + +set -euo pipefail + +# === KONFIGURATION === +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MISSION_DIR="${SCRIPT_DIR}/missions" +DEFAULT_CATEGORY="basics" + +# === FARBEN (optional, für bessere UX) === +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# === DATENSTRUKTUREN === +declare -a MISSION_OPTIONS +declare -A MISSION_MAP +declare -a MISSION_SCRIPTS + +# ============================================================ +# FUNKTIONEN +# ============================================================ + +show_intro() { + clear + echo -e "${GREEN}" + cat << 'EOF' + 🌟 Willkommen im Crumbforest Missionszentrum! 🌟 + + Hier kannst du auf Lern-Abenteuer gehen: + - 🦊 Fridolin zeigt dir die Pfade (Navigation) + - 🛠️ Balu hilft beim Bauen (Dateien & Ordner) + - 🐈🦉 Noko liest die Botschaften (Logs & Inhalte) + + ... und viele mehr! Wähle deine Mission: +EOF + echo -e "${NC}" + sleep 1 +} + +load_missions() { + local category="${1:-$DEFAULT_CATEGORY}" + local search_dir="${MISSION_DIR}/${category}" + + if [[ ! -d "$search_dir" ]]; then + echo "⚠️ Kategorie '$category' nicht gefunden. Nutze Basis-Missionen." + search_dir="${MISSION_DIR}/basics" + fi + + echo -e "${BLUE}🔍 Lade Missionen aus: ${search_dir}${NC}" + + # Alle .sh Dateien finden + mapfile -t MISSION_SCRIPTS < <(find "$search_dir" -maxdepth 1 -type f -name "*.sh" | sort) + + if [[ ${#MISSION_SCRIPTS[@]} -eq 0 ]]; then + echo "❗ Keine Missionen gefunden!" + exit 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 description enabled + icon=$(jq -r '.icon // "🛸"' "$meta_file" 2>/dev/null) + title=$(jq -r '.title // "Unknown"' "$meta_file" 2>/dev/null) + description=$(jq -r '.description // ""' "$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 + + # Mapping für späteren Zugriff + MISSION_MAP["$mission_name"]="$mission_file" + done + + echo -e "${GREEN}✅ ${#MISSION_OPTIONS[@]} Missionen geladen.${NC}" + echo "" +} + +show_mission_menu() { + # Beenden-Option hinzufügen + local exit_option="🚪 Zurück zum Terminal" + MISSION_OPTIONS+=("$exit_option") + + while true; do + echo "🌲 Wähle deine Mission:" + echo "======================" + + PS3="Gib die Zahl deiner Wahl ein: " + select opt in "${MISSION_OPTIONS[@]}"; do + local choice=$((REPLY - 1)) + + # Beenden gewählt + if [[ "$opt" == "$exit_option" ]]; then + echo "👋 Auf bald, kleiner Krümel!" + exit 0 + 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 "✅ Mission abgeschlossen!" + read -p "Drücke Enter für das Hauptmenü..." -r + echo "" + break + else + echo "❗ Ungültige Eingabe. Bitte wähle eine Zahl zwischen 1 und ${#MISSION_OPTIONS[@]}." + fi + done + done +} + +show_category_selector() { + echo "🗂️ Wähle eine Kategorie:" + echo "========================" + + PS3="Kategorie wählen: " + categories=("📚 Basics" "🚀 Advanced" "🏆 Challenges" "🎯 Alle anzeigen") + + select cat in "${categories[@]}"; do + case $REPLY in + 1) load_missions "basics" ;; + 2) load_missions "advanced" ;; + 3) load_missions "challenges" ;; + 4) + # Alle Kategorien durchsuchen + for dir in "$MISSION_DIR"/*; do + [[ -d "$dir" ]] && load_missions "$(basename "$dir")" + done + ;; + *) + echo "❗ Ungültige Auswahl" + continue + ;; + esac + break + done +} + +# ============================================================ +# MAIN +# ============================================================ + +main() { + show_intro + + # Einfach - lade immer basics + load_missions "basics" + + # Erweitert - Kategorie-Auswahl (uncomment für Kategorie-Menü) + # show_category_selector + + show_mission_menu +} + +# Start! +main diff --git a/crumbforest_roles/bugsy_zero.sh b/crumbforest_roles/bugsy_zero.sh new file mode 100755 index 0000000..a68eb52 --- /dev/null +++ b/crumbforest_roles/bugsy_zero.sh @@ -0,0 +1,55 @@ +#!/bin/bash +QUESTION="$*" +MODEL="openai/gpt-3.5-turbo" +API_KEY="${OPENROUTER_API_KEY}" + +LOGDIR="$HOME/.bugsy_logs" +mkdir -p "$LOGDIR" + +HISTORY_FILE="$LOGDIR/bugsy_history.json" +TMP_REQUEST="$LOGDIR/bugsy_request.json" +TMP_RESPONSE="$LOGDIR/bugsy_response.json" +LOG_FILE="$LOGDIR/token_log.json" + +[ ! -f "$HISTORY_FILE" ] && echo "[]" > "$HISTORY_FILE" +[ ! -f "$LOG_FILE" ] && echo "[]" > "$LOG_FILE" + +echo "🌍 Bugsy responds based on language of input: $QUESTION" + +if [ -z "$API_KEY" ]; then + echo "❗ No API key set. Use: export OPENROUTER_API_KEY=..." + exit 1 +fi + +jq -n \ + --arg model "$MODEL" \ + --arg system_prompt "You are Bugsy – a friendly bug who helps children understand error messages in a simple, kind and encouraging way. You always respond in the language of the question." \ + --arg user "$QUESTION" \ + '{"model": $model, "temperature": 0.5, "messages": [{"role": "system", "content": $system_prompt}, {"role": "user", "content": $user}]}' > "$TMP_REQUEST" + +curl -s https://openrouter.ai/api/v1/chat/completions \ + -H "Authorization: Bearer $API_KEY" \ + -H "Content-Type: application/json" \ + -d @"$TMP_REQUEST" > "$TMP_RESPONSE" + +RESPONSE_TEXT=$(jq -r '.choices[0].message.content // empty' "$TMP_RESPONSE") + +if [[ -z "$RESPONSE_TEXT" ]]; then + echo "🚫 No response from model." + exit 1 +else + echo -e "$RESPONSE_TEXT" + jq -n --arg role "assistant" --arg content "$RESPONSE_TEXT" \ + '{"role": $role, "content": $content}' > "$LOGDIR/new_entry.json" + jq -s '.[0] + [.[1]]' "$HISTORY_FILE" "$LOGDIR/new_entry.json" > "$LOGDIR/new_history.json" && \ + cp "$LOGDIR/new_history.json" "$HISTORY_FILE" && rm "$LOGDIR/new_history.json" +fi + +if jq -e '.usage' "$TMP_RESPONSE" > /dev/null; then + TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") + jq -n \ + --arg zeit "$TIMESTAMP" \ + --arg rolle "bugsy" \ + --arg usage "$(jq -c '.usage' "$TMP_RESPONSE")" \ + '{zeit: $zeit, rolle: $rolle, usage: $usage}' >> "$LOG_FILE" +fi diff --git a/crumbforest_roles/deepbit_zero.sh b/crumbforest_roles/deepbit_zero.sh new file mode 100755 index 0000000..0946bb7 --- /dev/null +++ b/crumbforest_roles/deepbit_zero.sh @@ -0,0 +1,55 @@ +#!/bin/bash +QUESTION="$*" +MODEL="openai/gpt-3.5-turbo" +API_KEY="${OPENROUTER_API_KEY}" + +LOGDIR="$HOME/.deepbit_logs" +mkdir -p "$LOGDIR" + +HISTORY_FILE="$LOGDIR/deepbit_history.json" +TMP_REQUEST="$LOGDIR/deepbit_request.json" +TMP_RESPONSE="$LOGDIR/deepbit_response.json" +LOG_FILE="$LOGDIR/token_log.json" + +[ ! -f "$HISTORY_FILE" ] && echo "[]" > "$HISTORY_FILE" +[ ! -f "$LOG_FILE" ] && echo "[]" > "$LOG_FILE" + +echo "🌍 Deepbit responds based on language of input: $QUESTION" + +if [ -z "$API_KEY" ]; then + echo "❗ No API key set. Use: export OPENROUTER_API_KEY=..." + exit 1 +fi + +jq -n \ + --arg model "$MODEL" \ + --arg system_prompt "You are Deepbit – a poetic octopus who explains Bash shell concepts to children using loops, images, and metaphors. Respond in the language the question is asked." \ + --arg user "$QUESTION" \ + '{"model": $model, "temperature": 0.5, "messages": [{"role": "system", "content": $system_prompt}, {"role": "user", "content": $user}]}' > "$TMP_REQUEST" + +curl -s https://openrouter.ai/api/v1/chat/completions \ + -H "Authorization: Bearer $API_KEY" \ + -H "Content-Type: application/json" \ + -d @"$TMP_REQUEST" > "$TMP_RESPONSE" + +RESPONSE_TEXT=$(jq -r '.choices[0].message.content // empty' "$TMP_RESPONSE") + +if [[ -z "$RESPONSE_TEXT" ]]; then + echo "🚫 No response from model." + exit 1 +else + echo -e "$RESPONSE_TEXT" + jq -n --arg role "assistant" --arg content "$RESPONSE_TEXT" \ + '{"role": $role, "content": $content}' > "$LOGDIR/new_entry.json" + jq -s '.[0] + [.[1]]' "$HISTORY_FILE" "$LOGDIR/new_entry.json" > "$LOGDIR/new_history.json" && \ + cp "$LOGDIR/new_history.json" "$HISTORY_FILE" && rm "$LOGDIR/new_history.json" +fi + +if jq -e '.usage' "$TMP_RESPONSE" > /dev/null; then + TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") + jq -n \ + --arg zeit "$TIMESTAMP" \ + --arg rolle "deepbit" \ + --arg usage "$(jq -c '.usage' "$TMP_RESPONSE")" \ + '{zeit: $zeit, rolle: $rolle, usage: $usage}' >> "$LOG_FILE" +fi diff --git a/crumbforest_roles/schnippsi_zero.sh b/crumbforest_roles/schnippsi_zero.sh new file mode 100755 index 0000000..8a90b58 --- /dev/null +++ b/crumbforest_roles/schnippsi_zero.sh @@ -0,0 +1,55 @@ +#!/bin/bash +QUESTION="$*" +MODEL="openai/gpt-3.5-turbo" +API_KEY="${OPENROUTER_API_KEY}" + +LOGDIR="$HOME/.schnippsi_logs" +mkdir -p "$LOGDIR" + +HISTORY_FILE="$LOGDIR/schnippsi_history.json" +TMP_REQUEST="$LOGDIR/schnippsi_request.json" +TMP_RESPONSE="$LOGDIR/schnippsi_response.json" +LOG_FILE="$LOGDIR/token_log.json" + +[ ! -f "$HISTORY_FILE" ] && echo "[]" > "$HISTORY_FILE" +[ ! -f "$LOG_FILE" ] && echo "[]" > "$LOG_FILE" + +echo "🌍 Schnippsi responds based on language of input: $QUESTION" + +if [ -z "$API_KEY" ]; then + echo "❗ No API key set. Use: export OPENROUTER_API_KEY=..." + exit 1 +fi + +jq -n \ + --arg model "$MODEL" \ + --arg system_prompt "You are Schnippsi – a playful UI/UX ninja who explains HTML, CSS, and accessibility to children. Always answer in the child's language, based on the input." \ + --arg user "$QUESTION" \ + '{"model": $model, "temperature": 0.5, "messages": [{"role": "system", "content": $system_prompt}, {"role": "user", "content": $user}]}' > "$TMP_REQUEST" + +curl -s https://openrouter.ai/api/v1/chat/completions \ + -H "Authorization: Bearer $API_KEY" \ + -H "Content-Type: application/json" \ + -d @"$TMP_REQUEST" > "$TMP_RESPONSE" + +RESPONSE_TEXT=$(jq -r '.choices[0].message.content // empty' "$TMP_RESPONSE") + +if [[ -z "$RESPONSE_TEXT" ]]; then + echo "🚫 No response from model." + exit 1 +else + echo -e "$RESPONSE_TEXT" + jq -n --arg role "assistant" --arg content "$RESPONSE_TEXT" \ + '{"role": $role, "content": $content}' > "$LOGDIR/new_entry.json" + jq -s '.[0] + [.[1]]' "$HISTORY_FILE" "$LOGDIR/new_entry.json" > "$LOGDIR/new_history.json" && \ + cp "$LOGDIR/new_history.json" "$HISTORY_FILE" && rm "$LOGDIR/new_history.json" +fi + +if jq -e '.usage' "$TMP_RESPONSE" > /dev/null; then + TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") + jq -n \ + --arg zeit "$TIMESTAMP" \ + --arg rolle "schnippsi" \ + --arg usage "$(jq -c '.usage' "$TMP_RESPONSE")" \ + '{zeit: $zeit, rolle: $rolle, usage: $usage}' >> "$LOG_FILE" +fi diff --git a/crumbforest_roles/templatus_zero.sh b/crumbforest_roles/templatus_zero.sh new file mode 100755 index 0000000..95a4c65 --- /dev/null +++ b/crumbforest_roles/templatus_zero.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# === Templatus – HTML-Architekt === +QUESTION="$*" +API_KEY="$OPENROUTER_API_KEY" +MODEL="openai/gpt-3.5-turbo" + +# Verzeichnisse +LOG_DIR="/home/zero/.templatus_logs" +HISTORY_FILE="$LOG_DIR/templatus_history.json" +TOKEN_LOG="$LOG_DIR/token_log.json" +TMP_REQUEST="/tmp/templatus_request.json" +TMP_RESPONSE="/tmp/templatus_response.json" + +mkdir -p "$LOG_DIR" + +# JSON Payload vorbereiten +cat < "$TMP_REQUEST" +{ + "model": "$MODEL", + "temperature": 0.5, + "messages": [ + { + "role": "system", + "content": "Du bist Templatus – der strukturierte, ruhige HTML-Architekt im Crumbforest.\nDu arbeitest eng mit Schnippsi (CSS/JS) und PepperPHP (Backend) zusammen.\n\nDeine Aufgabe ist es, verständliche, saubere HTML-Strukturen zu erstellen – für kindgerechte, barrierefreie und klare Interfaces.\nDu nutzt semantische Tags (wie
,