diff --git a/app.py b/app.py index 40ee757..34fcd21 100644 --- a/app.py +++ b/app.py @@ -686,6 +686,25 @@ def get_tasks(status=None, limit=None): return [dict(row) for row in rows] +def add_orchestrator_notification(message_type, message, agent_key=None): + """Fügt eine System-Benachrichtigung zum Orchestrator-Chat hinzu.""" + try: + if 'orchestrator_chat' not in session: + session['orchestrator_chat'] = [] + + session['orchestrator_chat'].insert(0, { # Insert at top (newest first) + 'timestamp': datetime.now().strftime('%d.%m.%Y %H:%M:%S'), + 'type': message_type, + 'message': message, + 'agent': AGENTS.get(agent_key, {}).get('name', agent_key) if agent_key else 'System', + 'agent_key': agent_key, + 'is_notification': True + }) + session['orchestrator_chat'] = session['orchestrator_chat'][:50] # Keep last 50 + session.modified = True + except: + pass # Session might not be available in background threads + def create_task(title, description, agent_key='orchestrator', task_type='manual', created_by='user', **kwargs): """Erstellt einen neuen Task in der Datenbank.""" con = sqlite3.connect(EMAIL_JOURNAL_DB) @@ -709,6 +728,15 @@ def create_task(title, description, agent_key='orchestrator', task_type='manual' con.close() logging.info(f"[DB] Task #{task_id} erstellt: {title[:50]}") + + # Orchestrator-Notification hinzufügen + if created_by != 'user': # Nur bei Agent-erstellten Tasks + add_orchestrator_notification( + 'task_created', + f'📋 Task #{task_id} erstellt: {title}', + agent_key=created_by + ) + return task_id @@ -2432,14 +2460,15 @@ def orchestrator(): response = execute_agent_task(selected_agent, prompt) orchestrator_chat = session.get('orchestrator_chat', []) - orchestrator_chat.append({ - 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M'), + orchestrator_chat.insert(0, { # Insert at top (newest first) + 'timestamp': datetime.now().strftime('%d.%m.%Y %H:%M:%S'), 'user_prompt': prompt, 'agent': agent_name, 'agent_key': selected_agent, - 'response': response + 'response': response, + 'is_notification': False }) - session['orchestrator_chat'] = orchestrator_chat[-30:] + session['orchestrator_chat'] = orchestrator_chat[:30] # Keep first 30 chat_display = session.get('orchestrator_chat', []) return render_template('orchestrator.html', @@ -2447,6 +2476,13 @@ def orchestrator(): chat_history=chat_display, knowledge_loaded=bool(session.get('orchestrator_kb'))) +@app.route('/orchestrator/clear', methods=['POST']) +def orchestrator_clear(): + """Löscht den Orchestrator Chat-Verlauf.""" + session['orchestrator_chat'] = [] + session.modified = True + return jsonify({'success': True}) + @app.route('/agents', methods=['GET', 'POST']) def agents(): agents_dir = os.path.join(os.path.dirname(__file__), 'agents') diff --git a/templates/orchestrator.html b/templates/orchestrator.html index 301f532..66402ac 100644 --- a/templates/orchestrator.html +++ b/templates/orchestrator.html @@ -42,19 +42,35 @@
Orchestrator-Chat
- Automatische Agenten-Delegation +
+ Automatische Agenten-Delegation + {% if chat_history %} + + {% endif %} +
{% if chat_history %} {% for chat in chat_history %} -
-
- {{ chat.timestamp }} · - {{ chat.agent }} + {% if chat.is_notification %} + +
+
+ {{ chat.message }} + {{ chat.timestamp }} +
-
Sie: {{ chat.user_prompt }}
-
Orchestrator: {{ chat.response }}
-
+ {% else %} + +
+
+ {{ chat.timestamp }} · + {{ chat.agent }} +
+
Sie: {{ chat.user_prompt }}
+
Orchestrator: {{ chat.response }}
+
+ {% endif %} {% endfor %} {% else %}
@@ -89,7 +105,7 @@ function sendPromptWithStream() { const msgDiv = document.createElement('div'); msgDiv.className = 'chat-message'; msgDiv.innerHTML = ` -
${new Date().toLocaleTimeString()} · wird ausgewählt…
+
${formatTimestamp()} · wird ausgewählt…
Sie: ${escapeHtml(prompt)}
Orchestrator: ⏳ Agent arbeitet…
`; @@ -186,5 +202,34 @@ function escapeHtml(text) { div.textContent = text; return div.innerHTML; } + +function clearOrchestratorChat() { + if (!confirm('Möchten Sie den gesamten Chat-Verlauf löschen?')) return; + + fetch('/orchestrator/clear', { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + location.reload(); + } + }) + .catch(err => { + alert('Fehler beim Löschen: ' + err.message); + }); +} + +function formatTimestamp() { + const now = new Date(); + const day = String(now.getDate()).padStart(2, '0'); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const year = now.getFullYear(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`; +} {% endblock %}