Initial commit: Crumbforest Architecture Refinement v1 (Clean)
This commit is contained in:
718
ARCHITECTURE_ROLES_GROUPS.md
Normal file
718
ARCHITECTURE_ROLES_GROUPS.md
Normal file
@@ -0,0 +1,718 @@
|
||||
# 🎨 Crumbforest Roles & Groups Architecture
|
||||
|
||||
## 🎯 Vision
|
||||
|
||||
**Statt 8x .sh Files → 1x JSON Config mit Rollen, Gruppen & Themes**
|
||||
|
||||
### Ziele:
|
||||
1. ✅ **Unified Role System** - Ein JSON statt vieler Shell Scripts
|
||||
2. ✅ **Group-based Theming** - CSS/Template per Gruppe (#barrierefrei)
|
||||
3. ✅ **Module Loading** - Zusätzliche Features per Gruppe
|
||||
4. ✅ **Separation** - home/demo/admin mit eigenen Designs
|
||||
5. ✅ **Web UI** - HTML Interface für Roles (nicht nur Terminal)
|
||||
|
||||
---
|
||||
|
||||
## 📋 JSON Schema: `crumbforest_config.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"groups": {
|
||||
"home": {
|
||||
"name": "Home (Öffentlich)",
|
||||
"theme": "pico-default",
|
||||
"template_base": "base_public.html",
|
||||
"css_files": ["pico.min.css", "crumbforest_public.css"],
|
||||
"features": ["info", "contact"],
|
||||
"navbar": ["home", "about", "contact"],
|
||||
"description": "Neutrale öffentliche Ansicht"
|
||||
},
|
||||
"demo": {
|
||||
"name": "Demo User",
|
||||
"theme": "pico-accessible",
|
||||
"template_base": "base_demo.html",
|
||||
"css_files": ["pico.min.css", "crumbforest_accessible.css"],
|
||||
"features": ["roles_web", "search", "chat"],
|
||||
"navbar": ["dashboard", "roles", "search"],
|
||||
"description": "Demo-Zugang mit Role-Chat UI"
|
||||
},
|
||||
"admin": {
|
||||
"name": "Admin",
|
||||
"theme": "pico-admin",
|
||||
"template_base": "base_admin.html",
|
||||
"css_files": ["pico.min.css", "crumbforest_admin.css"],
|
||||
"features": ["roles_web", "roles_terminal", "search", "rag_admin", "user_management"],
|
||||
"navbar": ["dashboard", "roles", "rag", "users", "settings"],
|
||||
"description": "Vollzugriff mit Terminal-Zugang"
|
||||
},
|
||||
"accessible": {
|
||||
"name": "Barrierefrei",
|
||||
"theme": "pico-high-contrast",
|
||||
"template_base": "base_accessible.html",
|
||||
"css_files": ["pico.min.css", "crumbforest_high_contrast.css", "screen_reader.css"],
|
||||
"features": ["roles_web", "search", "tts", "high_contrast"],
|
||||
"navbar": ["dashboard", "roles", "search", "settings"],
|
||||
"font_size": "large",
|
||||
"contrast": "high",
|
||||
"description": "Hochkontrast, große Schrift, TTS"
|
||||
}
|
||||
},
|
||||
|
||||
"roles": {
|
||||
"dumbo": {
|
||||
"id": "dumbo",
|
||||
"name": "🐘 DumboSQL",
|
||||
"title": "SQL Translator",
|
||||
"description": "A kind and patient SQL translator in the Crumbforest",
|
||||
"model": "openai/gpt-3.5-turbo",
|
||||
"temperature": 0.4,
|
||||
"system_prompt": "You are DumboSQL – a kind and patient SQL translator in the Crumbforest. You speak to children like a gentle teacher with a big heart. You remember previous questions when helpful, and always respond in a friendly, encouraging, and clear way.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "sql_formatting"],
|
||||
"icon": "🐘",
|
||||
"color": "#6c757d",
|
||||
"tags": ["sql", "database", "beginner-friendly"]
|
||||
},
|
||||
|
||||
"snakepy": {
|
||||
"id": "snakepy",
|
||||
"name": "🐍 SnakePy",
|
||||
"title": "Python Expert",
|
||||
"description": "A wise python who teaches programming with patience",
|
||||
"model": "openai/gpt-4o-mini",
|
||||
"temperature": 0.3,
|
||||
"system_prompt": "You are SnakePy – a wise and friendly Python expert in the Crumbforest. You explain Python concepts clearly, provide working code examples, and encourage learners. You are patient and adapt to the user's skill level.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "code_execution", "syntax_highlighting"],
|
||||
"icon": "🐍",
|
||||
"color": "#3776ab",
|
||||
"tags": ["python", "coding", "teaching"]
|
||||
},
|
||||
|
||||
"pepperphp": {
|
||||
"id": "pepperphp",
|
||||
"name": "🌶️ PepperPHP",
|
||||
"title": "PHP Specialist",
|
||||
"description": "A spicy PHP expert with a passion for web development",
|
||||
"model": "openai/gpt-4o-mini",
|
||||
"temperature": 0.3,
|
||||
"system_prompt": "You are PepperPHP – a passionate PHP expert in the Crumbforest. You love web development, know all PHP versions, and can help with frameworks like Laravel, Symfony. You're enthusiastic but also practical.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "code_execution", "composer_help"],
|
||||
"icon": "🌶️",
|
||||
"color": "#777bb4",
|
||||
"tags": ["php", "web", "backend"]
|
||||
},
|
||||
|
||||
"templatus": {
|
||||
"id": "templatus",
|
||||
"name": "📄 Templatus",
|
||||
"title": "Template Master",
|
||||
"description": "Expert for Jinja2, HTML, and frontend templating",
|
||||
"model": "anthropic/claude-3-5-sonnet",
|
||||
"temperature": 0.3,
|
||||
"system_prompt": "You are Templatus – a meticulous template expert in the Crumbforest. You master Jinja2, HTML, CSS, and creating beautiful, accessible web interfaces. You value clean code and user experience.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "template_preview", "html_validator"],
|
||||
"icon": "📄",
|
||||
"color": "#e44d26",
|
||||
"tags": ["templates", "html", "jinja2", "frontend"]
|
||||
},
|
||||
|
||||
"funkfox": {
|
||||
"id": "funkfox",
|
||||
"name": "🦊 FunkFox",
|
||||
"title": "JavaScript Wizard",
|
||||
"description": "A clever fox who makes JavaScript fun and functional",
|
||||
"model": "openai/gpt-4o-mini",
|
||||
"temperature": 0.4,
|
||||
"system_prompt": "You are FunkFox – a clever and playful JavaScript expert in the Crumbforest. You make JS fun, teach functional programming, and help with modern frameworks like React, Vue. You're enthusiastic about clean code.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "code_execution", "npm_help"],
|
||||
"icon": "🦊",
|
||||
"color": "#f7df1e",
|
||||
"tags": ["javascript", "frontend", "functional"]
|
||||
},
|
||||
|
||||
"schraubaer": {
|
||||
"id": "schraubaer",
|
||||
"name": "🔧 Schraubaer",
|
||||
"title": "Hardware Helper",
|
||||
"description": "A handy bear who knows everything about Raspberry Pi and hardware",
|
||||
"model": "openai/gpt-4o-mini",
|
||||
"temperature": 0.3,
|
||||
"system_prompt": "You are Schraubaer – a practical hardware expert in the Crumbforest. You know Raspberry Pi, Arduino, electronics, and Linux systems. You give clear, hands-on advice for building and fixing things.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "gpio_help", "circuit_diagrams"],
|
||||
"icon": "🔧",
|
||||
"color": "#c51a4a",
|
||||
"tags": ["hardware", "raspberry-pi", "electronics"]
|
||||
},
|
||||
|
||||
"schnecki": {
|
||||
"id": "schnecki",
|
||||
"name": "🐌 Schnecki",
|
||||
"title": "Slow Tech Guide",
|
||||
"description": "A gentle snail who teaches mindful, sustainable technology",
|
||||
"model": "anthropic/claude-3-5-sonnet",
|
||||
"temperature": 0.6,
|
||||
"system_prompt": "You are Schnecki – a gentle and wise slow-tech advocate in the Crumbforest. You teach mindful technology use, sustainability, energy efficiency, and the value of taking time. You encourage breaks and reflection.",
|
||||
"group_access": ["demo", "admin"],
|
||||
"features": ["chat", "history", "mindfulness_tips", "green_tech"],
|
||||
"icon": "🐌",
|
||||
"color": "#8b4513",
|
||||
"tags": ["slow-tech", "sustainability", "mindfulness"]
|
||||
},
|
||||
|
||||
"kungfutaube": {
|
||||
"id": "kungfutaube",
|
||||
"name": "🕊️ KungfuTaube",
|
||||
"title": "Security Sensei",
|
||||
"description": "A peaceful but vigilant dove teaching web security",
|
||||
"model": "anthropic/claude-3-5-sonnet",
|
||||
"temperature": 0.2,
|
||||
"system_prompt": "You are KungfuTaube – a calm but alert security expert in the Crumbforest. You teach web security, DSGVO compliance, safe coding practices, and encryption. You balance protection with usability.",
|
||||
"group_access": ["admin"],
|
||||
"features": ["chat", "history", "security_scan", "dsgvo_check"],
|
||||
"icon": "🕊️",
|
||||
"color": "#6f42c1",
|
||||
"tags": ["security", "dsgvo", "encryption", "admin-only"]
|
||||
}
|
||||
},
|
||||
|
||||
"theme_variants": {
|
||||
"pico-default": {
|
||||
"name": "Standard",
|
||||
"css": "pico.min.css",
|
||||
"colors": {
|
||||
"primary": "#1095c1",
|
||||
"secondary": "#6c757d",
|
||||
"contrast": "#000000"
|
||||
}
|
||||
},
|
||||
"pico-accessible": {
|
||||
"name": "Barrierefrei",
|
||||
"css": "pico.min.css",
|
||||
"custom_css": "accessible.css",
|
||||
"colors": {
|
||||
"primary": "#0066cc",
|
||||
"secondary": "#333333",
|
||||
"contrast": "#ffffff"
|
||||
},
|
||||
"font_size_base": "18px",
|
||||
"line_height": "1.8"
|
||||
},
|
||||
"pico-high-contrast": {
|
||||
"name": "Hochkontrast",
|
||||
"css": "pico.min.css",
|
||||
"custom_css": "high_contrast.css",
|
||||
"colors": {
|
||||
"primary": "#ffff00",
|
||||
"secondary": "#ffffff",
|
||||
"contrast": "#000000",
|
||||
"background": "#000000",
|
||||
"text": "#ffffff"
|
||||
},
|
||||
"font_size_base": "20px",
|
||||
"line_height": "2.0",
|
||||
"border_width": "3px"
|
||||
},
|
||||
"pico-admin": {
|
||||
"name": "Admin Dark",
|
||||
"css": "pico.min.css",
|
||||
"custom_css": "admin_dark.css",
|
||||
"colors": {
|
||||
"primary": "#00d4aa",
|
||||
"secondary": "#6c757d",
|
||||
"contrast": "#ffffff",
|
||||
"background": "#1a1a1a",
|
||||
"text": "#e0e0e0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architektur-Komponenten
|
||||
|
||||
### 1. FastAPI Router: `/routers/crumbforest_roles.py`
|
||||
|
||||
```python
|
||||
from fastapi import APIRouter, Depends, Request, Form
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
import httpx
|
||||
from typing import Optional
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# Load config
|
||||
import json
|
||||
with open('crumbforest_config.json') as f:
|
||||
config = json.load(f)
|
||||
|
||||
@router.get("/roles", response_class=HTMLResponse)
|
||||
async def roles_dashboard(req: Request, user = Depends(current_user)):
|
||||
"""
|
||||
Show available roles based on user's group.
|
||||
"""
|
||||
user_group = user.get('group', 'demo')
|
||||
|
||||
# Filter roles by group access
|
||||
available_roles = {
|
||||
rid: role for rid, role in config['roles'].items()
|
||||
if user_group in role['group_access']
|
||||
}
|
||||
|
||||
return req.app.state.render(
|
||||
req,
|
||||
"crumbforest/roles_dashboard.html",
|
||||
roles=available_roles,
|
||||
user_group=user_group
|
||||
)
|
||||
|
||||
@router.get("/roles/{role_id}", response_class=HTMLResponse)
|
||||
async def role_chat(req: Request, role_id: str, user = Depends(current_user)):
|
||||
"""
|
||||
Chat interface for a specific role.
|
||||
"""
|
||||
role = config['roles'].get(role_id)
|
||||
if not role:
|
||||
raise HTTPException(404, "Role not found")
|
||||
|
||||
user_group = user.get('group', 'demo')
|
||||
if user_group not in role['group_access']:
|
||||
raise HTTPException(403, "Access denied")
|
||||
|
||||
return req.app.state.render(
|
||||
req,
|
||||
"crumbforest/role_chat.html",
|
||||
role=role
|
||||
)
|
||||
|
||||
@router.post("/roles/{role_id}/ask")
|
||||
async def ask_role(
|
||||
req: Request,
|
||||
role_id: str,
|
||||
question: str = Form(...),
|
||||
user = Depends(current_user)
|
||||
):
|
||||
"""
|
||||
Send question to role and get AI response.
|
||||
"""
|
||||
role = config['roles'].get(role_id)
|
||||
if not role:
|
||||
raise HTTPException(404, "Role not found")
|
||||
|
||||
# Get conversation history from session
|
||||
history = req.session.get(f'role_history_{role_id}', [])
|
||||
|
||||
# Build messages
|
||||
messages = [
|
||||
{"role": "system", "content": role['system_prompt']}
|
||||
] + history + [
|
||||
{"role": "user", "content": question}
|
||||
]
|
||||
|
||||
# Call OpenRouter API
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
"https://openrouter.ai/api/v1/chat/completions",
|
||||
headers={
|
||||
"Authorization": f"Bearer {settings.openrouter_api_key}",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
json={
|
||||
"model": role['model'],
|
||||
"temperature": role['temperature'],
|
||||
"messages": messages
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
|
||||
answer = result['choices'][0]['message']['content']
|
||||
|
||||
# Update history
|
||||
history.append({"role": "user", "content": question})
|
||||
history.append({"role": "assistant", "content": answer})
|
||||
req.session[f'role_history_{role_id}'] = history[-10:] # Keep last 10
|
||||
|
||||
return JSONResponse({
|
||||
"role": role_id,
|
||||
"question": question,
|
||||
"answer": answer,
|
||||
"usage": result.get('usage', {})
|
||||
})
|
||||
```
|
||||
|
||||
### 2. Template: `templates/crumbforest/roles_dashboard.html`
|
||||
|
||||
```html
|
||||
{% extends group_config.template_base %}
|
||||
|
||||
{% block title %}Crumbforest Roles{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="container">
|
||||
<hgroup>
|
||||
<h1>🌲 Crumbforest Characters</h1>
|
||||
<p>Choose your learning companion!</p>
|
||||
</hgroup>
|
||||
|
||||
<div class="grid">
|
||||
{% for role_id, role in roles.items() %}
|
||||
<article>
|
||||
<header>
|
||||
<h3>
|
||||
<span style="font-size: 2em;">{{ role.icon }}</span>
|
||||
{{ role.name }}
|
||||
</h3>
|
||||
<p><small>{{ role.title }}</small></p>
|
||||
</header>
|
||||
|
||||
<p>{{ role.description }}</p>
|
||||
|
||||
<footer>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
{% for tag in role.tags %}
|
||||
<span class="badge" style="background: {{ role.color }}20; color: {{ role.color }};">
|
||||
#{{ tag }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<a href="/crumbforest/roles/{{ role_id }}" role="button">
|
||||
Chat with {{ role.name }}
|
||||
</a>
|
||||
</footer>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
### 3. Template: `templates/crumbforest/role_chat.html`
|
||||
|
||||
```html
|
||||
{% extends group_config.template_base %}
|
||||
|
||||
{% block title %}{{ role.name }} - Chat{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="container">
|
||||
<hgroup>
|
||||
<h1>{{ role.icon }} {{ role.name }}</h1>
|
||||
<p>{{ role.description }}</p>
|
||||
</hgroup>
|
||||
|
||||
<article id="chat-container">
|
||||
<div id="messages" style="max-height: 500px; overflow-y: auto; padding: 1rem;">
|
||||
<!-- Messages will be added here via JS -->
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<form id="chat-form">
|
||||
<div class="grid">
|
||||
<input
|
||||
type="text"
|
||||
name="question"
|
||||
id="question-input"
|
||||
placeholder="Ask {{ role.name }} something..."
|
||||
required
|
||||
autofocus
|
||||
>
|
||||
<button type="submit">Send</button>
|
||||
</div>
|
||||
</form>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const roleId = "{{ role.id }}";
|
||||
const chatForm = document.getElementById('chat-form');
|
||||
const messagesDiv = document.getElementById('messages');
|
||||
const questionInput = document.getElementById('question-input');
|
||||
|
||||
chatForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const question = questionInput.value;
|
||||
if (!question.trim()) return;
|
||||
|
||||
// Add user message
|
||||
addMessage('user', question);
|
||||
questionInput.value = '';
|
||||
|
||||
// Show loading
|
||||
const loadingId = addMessage('assistant', '{{ role.icon }} thinking...');
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('question', question);
|
||||
|
||||
const response = await fetch(`/crumbforest/roles/${roleId}/ask`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Remove loading, add real response
|
||||
document.getElementById(loadingId).remove();
|
||||
addMessage('assistant', data.answer);
|
||||
|
||||
} catch (error) {
|
||||
document.getElementById(loadingId).remove();
|
||||
addMessage('error', 'Oops! Something went wrong.');
|
||||
}
|
||||
});
|
||||
|
||||
function addMessage(role, content) {
|
||||
const msgId = 'msg-' + Date.now();
|
||||
const div = document.createElement('div');
|
||||
div.id = msgId;
|
||||
div.style.marginBottom = '1rem';
|
||||
div.style.padding = '1rem';
|
||||
div.style.borderRadius = '8px';
|
||||
|
||||
if (role === 'user') {
|
||||
div.style.background = '#e3f2fd';
|
||||
div.style.textAlign = 'right';
|
||||
div.innerHTML = `<strong>You:</strong><br>${content}`;
|
||||
} else if (role === 'assistant') {
|
||||
div.style.background = '#f5f5f5';
|
||||
div.innerHTML = `<strong>{{ role.name }}:</strong><br>${content}`;
|
||||
} else {
|
||||
div.style.background = '#ffebee';
|
||||
div.innerHTML = `<strong>Error:</strong><br>${content}`;
|
||||
}
|
||||
|
||||
messagesDiv.appendChild(div);
|
||||
messagesDiv.scrollTop = messagesDiv.scrollHeight;
|
||||
|
||||
return msgId;
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
```
|
||||
|
||||
### 4. User Model Extension: `app/models/user.py`
|
||||
|
||||
```python
|
||||
# Extend users table
|
||||
"""
|
||||
ALTER TABLE users
|
||||
ADD COLUMN user_group VARCHAR(50) DEFAULT 'demo',
|
||||
ADD COLUMN theme VARCHAR(50) DEFAULT 'pico-default',
|
||||
ADD COLUMN accessibility JSON DEFAULT NULL;
|
||||
"""
|
||||
|
||||
# Example accessibility JSON:
|
||||
{
|
||||
"font_size": "large",
|
||||
"high_contrast": true,
|
||||
"screen_reader": true,
|
||||
"animation_reduced": true
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Base Template with Group Support: `templates/base_demo.html`
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ lang }}" data-theme="{{ user.theme or 'auto' }}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Crumbforest{% endblock %}</title>
|
||||
|
||||
<!-- Load CSS based on group config -->
|
||||
{% for css_file in group_config.css_files %}
|
||||
<link rel="stylesheet" href="/static/css/{{ css_file }}">
|
||||
{% endfor %}
|
||||
|
||||
{% if user.accessibility %}
|
||||
<style>
|
||||
:root {
|
||||
{% if user.accessibility.font_size == 'large' %}
|
||||
font-size: 120%;
|
||||
{% endif %}
|
||||
|
||||
{% if user.accessibility.high_contrast %}
|
||||
--primary: #ffff00;
|
||||
--background-color: #000000;
|
||||
--color: #ffffff;
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
{% if user.accessibility.animation_reduced %}
|
||||
* {
|
||||
animation: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
{% endif %}
|
||||
</style>
|
||||
{% endif %}
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><strong>🌲 Crumbforest</strong></li>
|
||||
</ul>
|
||||
<ul>
|
||||
{% for nav_item in group_config.navbar %}
|
||||
{% if nav_item == 'dashboard' %}
|
||||
<li><a href="/dashboard">Dashboard</a></li>
|
||||
{% elif nav_item == 'roles' %}
|
||||
<li><a href="/crumbforest/roles">Characters</a></li>
|
||||
{% elif nav_item == 'search' %}
|
||||
<li><a href="/search">Search</a></li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<li>
|
||||
<details class="dropdown">
|
||||
<summary>{{ user.email }}</summary>
|
||||
<ul dir="rtl">
|
||||
<li><a href="/settings">Settings</a></li>
|
||||
<li>
|
||||
<form action="/logout" method="post" style="margin:0;">
|
||||
<button type="submit" class="contrast">Logout</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
<footer>
|
||||
<small>
|
||||
Group: {{ group_config.name }} |
|
||||
Theme: {{ user.theme }} |
|
||||
Made with 💚 in the Crumbforest
|
||||
</small>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Implementierungs-Phasen
|
||||
|
||||
### Phase 1: Foundation (Tag 1-2)
|
||||
- [ ] `crumbforest_config.json` erstellen
|
||||
- [ ] User-Model erweitern (group, theme, accessibility)
|
||||
- [ ] Config-Loader Service
|
||||
- [ ] Base Templates für Gruppen (home, demo, admin, accessible)
|
||||
|
||||
### Phase 2: Role System (Tag 3-4)
|
||||
- [ ] `/routers/crumbforest_roles.py` implementieren
|
||||
- [ ] Roles Dashboard Template
|
||||
- [ ] Chat Interface Template
|
||||
- [ ] Session-based History
|
||||
- [ ] OpenRouter API Integration
|
||||
|
||||
### Phase 3: Theme System (Tag 5-6)
|
||||
- [ ] CSS Variants (default, accessible, high-contrast, admin)
|
||||
- [ ] Theme Switcher UI
|
||||
- [ ] User Settings Page
|
||||
- [ ] Accessibility Controls (font size, contrast, TTS)
|
||||
|
||||
### Phase 4: Migration (Tag 7)
|
||||
- [ ] Shell Scripts → JSON Config migrieren
|
||||
- [ ] Testing aller 8 Roles
|
||||
- [ ] Demo User einrichten
|
||||
- [ ] Branko.de Integration (Static pages)
|
||||
|
||||
### Phase 5: Features (Tag 8-10)
|
||||
- [ ] Code Execution (für SnakePy, PepperPHP)
|
||||
- [ ] Syntax Highlighting
|
||||
- [ ] Role-spezifische Features
|
||||
- [ ] Export Chat History
|
||||
- [ ] Token Usage Tracking
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Vorteile dieser Architektur
|
||||
|
||||
### ✅ Wartbarkeit
|
||||
- **Ein JSON** statt 8 Shell Scripts
|
||||
- Zentralisierte Konfiguration
|
||||
- Einfaches Hinzufügen neuer Roles
|
||||
|
||||
### ✅ Flexibilität
|
||||
- Gruppen-basiertes Theming
|
||||
- Modul-basierte Features
|
||||
- Multi-Tenant fähig
|
||||
|
||||
### ✅ Barrierefreiheit
|
||||
- High-Contrast Theme
|
||||
- Große Schrift
|
||||
- Screen Reader Support
|
||||
- Animation-Reduktion
|
||||
|
||||
### ✅ Separation of Concerns
|
||||
- **Home**: Öffentlich, neutral, Info
|
||||
- **Demo**: Role-Chat, Read-Only
|
||||
- **Admin**: Voller Zugriff, Terminal, RAG
|
||||
|
||||
### ✅ Extensibility
|
||||
- Neue Roles via JSON
|
||||
- Neue Gruppen ohne Code-Änderung
|
||||
- Theme-Varianten einfach hinzufügen
|
||||
- Features als Plugins
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Quick Start (Nach Implementierung)
|
||||
|
||||
```python
|
||||
# 1. User mit Gruppe erstellen
|
||||
user = {
|
||||
"email": "demo@crumb.local",
|
||||
"group": "demo",
|
||||
"theme": "pico-accessible"
|
||||
}
|
||||
|
||||
# 2. Role-Chat öffnen
|
||||
GET /crumbforest/roles/dumbo
|
||||
|
||||
# 3. Frage stellen
|
||||
POST /crumbforest/roles/dumbo/ask
|
||||
{
|
||||
"question": "Wie erstelle ich eine SQL-Tabelle?"
|
||||
}
|
||||
|
||||
# 4. Theme wechseln
|
||||
POST /settings/theme
|
||||
{
|
||||
"theme": "pico-high-contrast",
|
||||
"accessibility": {
|
||||
"font_size": "large",
|
||||
"high_contrast": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🦉 Fazit
|
||||
|
||||
Diese Architektur:
|
||||
- ✅ Ersetzt 8 Shell Scripts durch 1 JSON
|
||||
- ✅ Ermöglicht Web UI für Roles
|
||||
- ✅ Unterstützt Barrierefreiheit
|
||||
- ✅ Trennt home/demo/admin sauber
|
||||
- ✅ Ist erweiterbar & wartbar
|
||||
- ✅ Behält Pico CSS bei
|
||||
- ✅ Funktioniert mit bestehendem FastAPI Setup
|
||||
|
||||
**Ready to implement?** 🌲
|
||||
Reference in New Issue
Block a user