From a3b771b12a8f25dae1e27d005e0129f181be7c0e Mon Sep 17 00:00:00 2001
From: patrick-motsch
Date: Wed, 18 Feb 2026 00:32:16 +0100
Subject: [PATCH] fix: derive botName from system bot email, robust
responseChannel comparison
Co-authored-by: Cursor
---
.../features/teamsbot/routeFeatureTeamsbot.py | 14 +++++++--
modules/features/teamsbot/service.py | 31 +++++++++++--------
2 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/modules/features/teamsbot/routeFeatureTeamsbot.py b/modules/features/teamsbot/routeFeatureTeamsbot.py
index b185528a..a441d461 100644
--- a/modules/features/teamsbot/routeFeatureTeamsbot.py
+++ b/modules/features/teamsbot/routeFeatureTeamsbot.py
@@ -212,8 +212,18 @@ async def startSession(
if systemBot:
if not effectiveBotName:
- effectiveBotName = systemBot.get("name") or effectiveConfig.botName
- logger.info(f"System bot found: {systemBot.get('name')} ({systemBot.get('email')})")
+ effectiveBotName = systemBot.get("name")
+ # Derive display name from email if system bot has no explicit name
+ # e.g. "nyla.larsson@poweron.swiss" → "Nyla Larsson"
+ if not effectiveBotName:
+ sbEmail = systemBot.get("email", "")
+ if sbEmail and "@" in sbEmail:
+ emailPrefix = sbEmail.split("@")[0]
+ effectiveBotName = " ".join(part.capitalize() for part in emailPrefix.split("."))
+ logger.info(f"Bot name derived from email: {effectiveBotName}")
+ if not effectiveBotName:
+ effectiveBotName = effectiveConfig.botName
+ logger.info(f"System bot found: {systemBot.get('name')} ({systemBot.get('email')}), effectiveBotName={effectiveBotName}")
# Load and decrypt credentials for authenticated join
botAccountEmail = systemBot.get("email")
diff --git a/modules/features/teamsbot/service.py b/modules/features/teamsbot/service.py
index 7251741e..83e7a251 100644
--- a/modules/features/teamsbot/service.py
+++ b/modules/features/teamsbot/service.py
@@ -519,9 +519,9 @@ class TeamsbotService:
def _isBotSpeaker(self, speaker: str) -> bool:
"""Check if a transcript speaker is the bot itself.
- Teams captions show the bot as e.g. "Shelly Miller (Unverified)" or
+ Teams captions show the bot as e.g. "BotName (Unverified)" or
"Nyla Larsson" depending on auth/anonymous join. We match against:
- - The configured bot name (e.g. "Shelly Miller")
+ - The configured/derived bot name
- The bot account display name if authenticated
"""
if not speaker:
@@ -714,18 +714,22 @@ class TeamsbotService:
return
# Determine response channel (voice, chat, or both)
- channel = self.config.responseChannel
- responseType = TeamsbotResponseType.BOTH
+ # Normalize to string for reliable comparison (model_copy may skip enum coercion)
+ channelStr = str(self.config.responseChannel).lower().strip()
+ logger.info(f"Response channel: '{channelStr}' (raw={self.config.responseChannel!r})")
- if channel == TeamsbotResponseChannel.VOICE:
- responseType = TeamsbotResponseType.AUDIO
- elif channel == TeamsbotResponseChannel.CHAT:
- responseType = TeamsbotResponseType.CHAT
- else:
+ sendVoice = channelStr in ("voice", "both")
+ sendChat = channelStr in ("chat", "both")
+
+ if sendVoice and sendChat:
responseType = TeamsbotResponseType.BOTH
+ elif sendVoice:
+ responseType = TeamsbotResponseType.AUDIO
+ else:
+ responseType = TeamsbotResponseType.CHAT
# 4a: Voice response (TTS -> Audio to bot)
- if channel in (TeamsbotResponseChannel.VOICE, TeamsbotResponseChannel.BOTH):
+ if sendVoice:
try:
ttsResult = await voiceInterface.textToSpeech(
text=speechResult.responseText,
@@ -748,11 +752,11 @@ class TeamsbotService:
logger.info(f"TTS audio generated for session {sessionId} (HTTP mode - no WebSocket for playback)")
except Exception as ttsErr:
logger.warning(f"TTS failed for session {sessionId}: {ttsErr}")
- if responseType == TeamsbotResponseType.AUDIO:
- responseType = TeamsbotResponseType.CHAT # Fallback to chat only
+ if not sendChat:
+ sendChat = True # Fallback to chat if voice-only and TTS failed
# 4b: Chat response (send text message to meeting chat)
- if channel in (TeamsbotResponseChannel.CHAT, TeamsbotResponseChannel.BOTH):
+ if sendChat:
try:
if websocket:
await websocket.send_text(json.dumps({
@@ -760,6 +764,7 @@ class TeamsbotService:
"sessionId": sessionId,
"text": speechResult.responseText,
}))
+ logger.info(f"Chat response sent for session {sessionId}")
except Exception as chatErr:
logger.warning(f"Chat message send failed for session {sessionId}: {chatErr}")