Files
crumbmissions/crumbforest_roles/schraubaer_zero_final.sh
Branko May Trinkwald 4005bb9b18 🔒 Security: Token-Budget-Enforcement für Kinderschutz
KRITISCHES SICHERHEITSUPDATE für alle 17 Waldwächter-Scripts.

Problem behoben:
- Token-Budget wurde nur angezeigt, aber NICHT durchgesetzt
- Kinder konnten unbegrenzt API-Calls machen → Kostenrisiko

Implementierung:
1. check_token_budget() Funktion in lib/waldwaechter.sh
   - Berechnet täglichen Token-Verbrauch
   - Vergleicht mit DAILY_TOKEN_BUDGET aus .env
   - Budget = 0 oder leer → unbegrenzt
   - Budget überschritten → freundliche Blockierung

2. Budget-Check in ALLEN 17 Waldwächter-Scripts:
   - Prüfung VOR jedem API-Call
   - Kinderfreundliche Nachricht bei Limit
   - Warnung bei knappem Budget

Philosophie: "Was kostet die Frage eines Kindes?"
→ Im Wald unbezahlbar, im System achtsam begrenzt.

Scripts aktualisiert:
 mayaeule, deepbit, bugsy, schnippsi, templatus, tobi
 schraubaer, schnecki, dumbosql, funkfox, taichitaube
 snakepy, pepperphp, crabbyrust, spider, vektor, asciimonster

Test-Ergebnisse:
- Syntax-Check: 17/17 bestanden
- Funktionstest: Budget-Enforcement funktioniert
- Unbegrenzt-Modus: funktioniert
- Limit-Modus: blockiert korrekt

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 00:01:15 +01:00

180 lines
5.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 🔧 Schraubbär - Der praktische Handwerker mit schwerem Gerät
# Schweißen, Prüfen, Werkzeug - für alles was robust sein muss
# Load .env if exists
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/../.env"
if [[ -f "${ENV_FILE}" ]]; then
# Export environment variables from .env
set -a
source "${ENV_FILE}"
set +a
fi
QUESTION="$*"
API_KEY="${OPENROUTER_API_KEY}"
MODEL="${OPENROUTER_MODEL:-openai/gpt-3.5-turbo}"
# Logs
LOGDIR="${CRUMB_LOGS_DIR:-$HOME/.schraubaer_logs}/schraubaer"
mkdir -p "$LOGDIR"
HISTORY_FILE="$LOGDIR/schraubaer_history.json"
TMP_REQUEST="$LOGDIR/schraubaer_request.json"
TMP_RESPONSE="$LOGDIR/schraubaer_response.json"
LOG_FILE="$LOGDIR/token_log.json"
[ ! -f "$HISTORY_FILE" ] && echo "[]" > "$HISTORY_FILE"
[ ! -f "$LOG_FILE" ] && echo "[]" > "$LOG_FILE"
# === CREW MEMORY FUNCTIONS ===
function read_crew_memory() {
local role="$1"
local role_log="$HOME/.${role}_logs/${role}_history.json"
if [[ -f "$role_log" ]]; then
# Get last 3 conversations from other crew member
jq -r '.[-3:] | .[] | "[\(.role)]: \(.content)"' "$role_log" 2>/dev/null | head -n 3
fi
}
# === MAIN ===
echo "🔧 Schraubbär knackt die Finger und greift zum Werkzeug..."
echo ""
if [ -z "$API_KEY" ]; then
echo "❗ Kein API-Key gefunden. Bitte setze OPENROUTER_API_KEY in .env"
exit 1
fi
# Source waldwaechter library for token budget check
if [[ -f "${SCRIPT_DIR}/../lib/waldwaechter.sh" ]]; then
source "${SCRIPT_DIR}/../lib/waldwaechter.sh"
fi
# 💰 Prüfe Token-Budget (Kinderschutz)
if ! check_token_budget "schraubaer"; then
exit 1
fi
if [ -z "$QUESTION" ]; then
echo "💡 Verwendung: $0 \"Deine Frage an Schraubbär\""
exit 0
fi
echo "🔩 Frage: $QUESTION"
echo ""
# Check if question references other crew members
CREW_CONTEXT=""
if echo "$QUESTION" | grep -qi "tobi\|schnecki\|schnippsi\|templatus"; then
echo "🧠 Schraubbär prüft was die Crew gesagt hat..."
# Read relevant crew member logs
if echo "$QUESTION" | grep -qi "tobi"; then
TOBI_CONTEXT=$(read_crew_memory "tobi")
if [[ -n "$TOBI_CONTEXT" ]]; then
CREW_CONTEXT="${CREW_CONTEXT}\n\nTobi hat kürzlich gesagt:\n${TOBI_CONTEXT}"
fi
fi
if echo "$QUESTION" | grep -qi "schnecki"; then
SCHNECKI_CONTEXT=$(read_crew_memory "schnecki")
if [[ -n "$SCHNECKI_CONTEXT" ]]; then
CREW_CONTEXT="${CREW_CONTEXT}\n\nSchnecki hat kürzlich gesagt:\n${SCHNECKI_CONTEXT}"
fi
fi
fi
# Build system prompt
SYSTEM_PROMPT="Du bist Schraubbär der erfahrene Handwerker im Crumbforest.
Du bist zuständig für schweres Gerät: Schweißen, Werkzeugprüfung, mechanische Systeme.
Du arbeitest eng mit Tobi (Elektronik) und Schnecki (Elektronik-Basteln) zusammen.
Deine Expertise:
- Werkzeugauswahl und Sicherheit
- Schweißen (Löten, Punktschweißen, etc.)
- Mechanische Konstruktion und Stabilität
- Spannungsversorgung und Verkabelung (grob)
- Material-Kunde (Metall, Plastik, Holz)
- Prüfgeräte (Multimeter, Oszilloskop basics)
Deine Art:
- Praktisch, hands-on, keine Theorie ohne Praxis
- Sicherheit geht vor - du warnst vor Gefahren
- Kindgerecht erklären, aber ehrlich über Risiken
- Du nutzt Emojis: 🔧 🔩 ⚡ 🛠️ 🏗️
Du antwortest in der Sprache der Frage (meist Deutsch).
Wenn du mit anderen Crew-Mitgliedern arbeitest, beziehe ihr Wissen ein."
# Add crew context if available
if [[ -n "$CREW_CONTEXT" ]]; then
SYSTEM_PROMPT="${SYSTEM_PROMPT}\n\nKontext von der Crew:${CREW_CONTEXT}"
fi
# Create API request
jq -n \
--arg model "$MODEL" \
--arg system "$SYSTEM_PROMPT" \
--arg user "$QUESTION" \
'{
"model": $model,
"temperature": 0.7,
"messages": [
{"role": "system", "content": $system},
{"role": "user", "content": $user}
]
}' > "$TMP_REQUEST"
# Send request
echo "💭 Schraubbär denkt nach und prüft das Werkzeug..."
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 "🚫 Keine Antwort von Schraubbär."
echo "Debug: $(cat "$TMP_RESPONSE")"
exit 1
else
echo ""
echo "🔧 Schraubbär antwortet:"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$RESPONSE_TEXT"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Store conversation in history
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" && \
mv "$LOGDIR/new_history.json" "$HISTORY_FILE" && rm "$LOGDIR/new_entry.json"
fi
# Token Tracking
if jq -e '.usage' "$TMP_RESPONSE" > /dev/null 2>&1; then
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
TOKENS_USED=$(jq -r '.usage.total_tokens' "$TMP_RESPONSE")
jq -n \
--arg zeit "$TIMESTAMP" \
--arg rolle "schraubaer" \
--arg model "$MODEL" \
--argjson usage "$(jq '.usage' "$TMP_RESPONSE")" \
'{zeit: $zeit, rolle: $rolle, model: $model, usage: $usage}' >> "$LOG_FILE"
echo "📊 Token-Verbrauch: $TOKENS_USED Tokens"
echo "💡 Gutes Werkzeug braucht Zeit - Token zeigen den Aufwand."
fi
echo ""
echo "🔩 Schraubbär legt das Werkzeug zurück in die Kiste..."