diff --git a/modules/features/commcoach/serviceCommcoach.py b/modules/features/commcoach/serviceCommcoach.py index 24c23044..8151d343 100644 --- a/modules/features/commcoach/serviceCommcoach.py +++ b/modules/features/commcoach/serviceCommcoach.py @@ -86,6 +86,27 @@ def cleanupSessionEvents(sessionId: str): CHUNK_WORD_SIZE = 4 CHUNK_DELAY_SECONDS = 0.05 +def _wrapEmailHtml(contentHtml: str) -> str: + """Wrap AI-generated HTML content in a styled email shell.""" + return f""" + + + +
+
+
+

Coaching-Session Zusammenfassung

+

PowerOn CommCoach

+
+
{contentHtml}
+
+

Diese Zusammenfassung wurde automatisch erstellt.

+
+
+
+ +""" + DOC_INTENT_MAX_DOCS = 3 DOC_CONTENT_MAX_CHARS = 3000 @@ -634,14 +655,21 @@ class CommcoachService: }) return session - # Generate summary + # Generate summary (AI returns JSON with summary + emailHtml) + summary = None + emailHtml = None try: summaryPrompt = aiPrompts.buildSummaryPrompt(messages, context.get("title", "Coaching")) - summaryResponse = await self._callAi("Du bist ein präziser Zusammenfasser.", summaryPrompt) - summary = summaryResponse.content.strip() if summaryResponse and summaryResponse.errorCount == 0 else None + summaryResponse = await self._callAi("Du bist ein präziser Zusammenfasser. Antworte NUR als JSON.", summaryPrompt) + if summaryResponse and summaryResponse.errorCount == 0 and summaryResponse.content: + parsed = aiPrompts.parseJsonResponse(summaryResponse.content.strip(), None) + if isinstance(parsed, dict): + summary = parsed.get("summary") or parsed.get("text") + emailHtml = parsed.get("emailHtml") + else: + summary = summaryResponse.content.strip() except Exception as e: logger.warning(f"Summary generation failed: {e}") - summary = None keyTopics = None if summary: @@ -782,7 +810,8 @@ class CommcoachService: # Send email summary if summary: - await self._sendSessionEmail(session, summary, interface) + contextTitle = context.get("title", "Coaching") if context else "Coaching" + await self._sendSessionEmail(session, summary, emailHtml, contextTitle, interface) await emitSessionEvent(sessionId, "sessionState", { "status": "completed", @@ -833,8 +862,8 @@ class CommcoachService: except Exception as e: logger.warning(f"Failed to update streak: {e}") - async def _sendSessionEmail(self, session: Dict[str, Any], summary: str, interface): - """Send session summary via email if enabled.""" + async def _sendSessionEmail(self, session: Dict[str, Any], summary: str, emailHtml: str, contextTitle: str, interface): + """Send session summary via email if enabled. Uses AI-generated HTML directly.""" try: profile = interface.getProfile(self.userId, self.instanceId) if profile and not profile.get("emailSummaryEnabled", True): @@ -849,13 +878,10 @@ class CommcoachService: return messaging = getMessagingInterface() - subject = f"Coaching-Session Zusammenfassung: {session.get('contextId', 'Session')}" - htmlMessage = f""" -

Coaching-Session Zusammenfassung

-

{summary.replace(chr(10), '
')}

-
-

Diese Zusammenfassung wurde automatisch erstellt.

- """ + subject = f"Coaching-Session Zusammenfassung: {contextTitle}" + + contentHtml = emailHtml if emailHtml else f"

{summary}

" + htmlMessage = _wrapEmailHtml(contentHtml) messaging.send("email", user.email, subject, htmlMessage) interface.updateSession(session.get("id"), {"emailSent": True}) diff --git a/modules/features/commcoach/serviceCommcoachAi.py b/modules/features/commcoach/serviceCommcoachAi.py index 11844c28..8db9e61c 100644 --- a/modules/features/commcoach/serviceCommcoachAi.py +++ b/modules/features/commcoach/serviceCommcoachAi.py @@ -260,24 +260,35 @@ Fuer ein NEUES Dokument: {"title": "...", "content": "...Inhalt..."}""" def buildSummaryPrompt(messages: List[Dict[str, Any]], contextTitle: str) -> str: - """Build a prompt to generate a session summary.""" + """Build a prompt to generate a session summary as JSON with plain text and styled HTML email.""" conversation = "" for msg in messages: role = "Benutzer" if msg.get("role") == "user" else "Coach" conversation += f"\n{role}: {msg.get('content', '')}" - return f"""Erstelle eine kompakte Zusammenfassung dieser Coaching-Session zum Thema "{contextTitle}". + return f"""Erstelle eine Zusammenfassung dieser Coaching-Session zum Thema "{contextTitle}". -Struktur: -1. **Kernthema**: Was wurde besprochen (1-2 Sätze) -2. **Erkenntnisse**: Was wurde erkannt/gelernt (Stichpunkte) -3. **Nächste Schritte**: Konkrete Aufgaben für den Benutzer (Stichpunkte) -4. **Fortschritt**: Einschätzung des Fortschritts +Antworte AUSSCHLIESSLICH als JSON mit zwei Feldern: + +{{ + "summary": "Kompakte Zusammenfassung als Plaintext (fuer Anzeige in der App). Struktur: 1. Kernthema, 2. Erkenntnisse, 3. Naechste Schritte, 4. Fortschritt.", + "emailHtml": "
...
" +}} + +Fuer "emailHtml": Erstelle ein professionell formatiertes HTML-Fragment (KEIN vollstaendiges HTML-Dokument, nur der Inhalt-Block). +Verwende inline CSS fuer schoene Darstellung in E-Mail-Clients: +- Verwende

fuer Abschnitte (color: #1e40af; margin: 20px 0 8px; font-size: 16px) +- Verwende