fix: derive botName from system bot email, robust responseChannel comparison

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
patrick-motsch 2026-02-18 00:32:16 +01:00
parent 33daa8dc74
commit a3b771b12a
2 changed files with 30 additions and 15 deletions

View file

@ -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")

View file

@ -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}")