refactor: add TransferMode, remove backgroundImageUrl and botAccount fields from config
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
5dd3b9f894
commit
de573fd834
5 changed files with 20 additions and 26 deletions
|
|
@ -29,7 +29,6 @@ class BridgeConnector:
|
|||
self,
|
||||
meetingLink: str,
|
||||
botName: str,
|
||||
backgroundImageUrl: Optional[str],
|
||||
sessionId: str,
|
||||
gatewayCallbackUrl: str,
|
||||
gatewayWsUrl: str,
|
||||
|
|
@ -56,7 +55,6 @@ class BridgeConnector:
|
|||
payload = {
|
||||
"meetingLink": meetingLink,
|
||||
"botName": botName,
|
||||
"backgroundImageUrl": backgroundImageUrl,
|
||||
"sessionId": sessionId,
|
||||
"gatewayCallbackUrl": gatewayCallbackUrl,
|
||||
"gatewayWsUrl": gatewayWsUrl,
|
||||
|
|
|
|||
|
|
@ -38,16 +38,16 @@ class BrowserBotConnector:
|
|||
language: str = "de-DE",
|
||||
botAccountEmail: Optional[str] = None,
|
||||
botAccountPassword: Optional[str] = None,
|
||||
backgroundImageUrl: Optional[str] = None,
|
||||
transferMode: str = "auto",
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Send join command to the Browser Bot service.
|
||||
|
||||
The bot will:
|
||||
1. Launch a headless browser
|
||||
1. Launch a browser (headful for auth, headless for anonymous)
|
||||
2. If botAccountEmail/Password provided: authenticate with Microsoft first
|
||||
3. Navigate to Teams web app and join the meeting
|
||||
4. Enable captions and start scraping
|
||||
4. Enable captions/audio capture based on transferMode
|
||||
5. Connect back to Gateway via WebSocket using gatewayWsUrl
|
||||
|
||||
Args:
|
||||
|
|
@ -55,7 +55,7 @@ class BrowserBotConnector:
|
|||
language: BCP-47 language code for captions spoken language
|
||||
botAccountEmail: Microsoft account email for authenticated join (None = anonymous)
|
||||
botAccountPassword: Microsoft account password
|
||||
backgroundImageUrl: URL to background image for virtual background
|
||||
transferMode: How to capture meeting content: caption, audio, or auto
|
||||
|
||||
Returns:
|
||||
Dict with 'success' bool and optional 'error' string.
|
||||
|
|
@ -74,6 +74,7 @@ class BrowserBotConnector:
|
|||
"instanceId": instanceId,
|
||||
"gatewayWsUrl": gatewayWsUrl,
|
||||
"language": language,
|
||||
"transferMode": transferMode,
|
||||
}
|
||||
|
||||
# Add authenticated join credentials if configured
|
||||
|
|
@ -82,10 +83,6 @@ class BrowserBotConnector:
|
|||
payload["botAccountPassword"] = botAccountPassword
|
||||
logger.info(f"Bot will join authenticated as {botAccountEmail}")
|
||||
|
||||
# Add background image if configured
|
||||
if backgroundImageUrl:
|
||||
payload["backgroundImageUrl"] = backgroundImageUrl
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession(timeout=_BOT_TIMEOUT) as session:
|
||||
async with session.post(f"{self.botUrl}/api/bot", json=payload) as resp:
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ class TeamsbotJoinMode(str, Enum):
|
|||
USER_ACCOUNT = "userAccount" # Join with user's own Microsoft account (OAuth)
|
||||
|
||||
|
||||
class TeamsbotTransferMode(str, Enum):
|
||||
"""How meeting audio/transcript is transferred from bot to gateway."""
|
||||
CAPTION = "caption" # Use Teams live captions (text scraping from DOM)
|
||||
AUDIO = "audio" # Capture meeting audio and stream to gateway for STT
|
||||
AUTO = "auto" # Automatic: anonymous → audio, authenticated → caption
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# Database Models (stored in PostgreSQL)
|
||||
# ============================================================================
|
||||
|
|
@ -72,7 +79,6 @@ class TeamsbotSession(BaseModel):
|
|||
mandateId: str = Field(description="Mandate ID (FK)")
|
||||
meetingLink: str = Field(description="Teams meeting join link")
|
||||
botName: str = Field(default="AI Assistant", description="Display name of the bot in the meeting")
|
||||
backgroundImageUrl: Optional[str] = Field(default=None, description="Background image URL for the bot's video feed")
|
||||
status: TeamsbotSessionStatus = Field(default=TeamsbotSessionStatus.PENDING, description="Current session status")
|
||||
startedAt: Optional[str] = Field(default=None, description="ISO timestamp when session started")
|
||||
endedAt: Optional[str] = Field(default=None, description="ISO timestamp when session ended")
|
||||
|
|
@ -147,10 +153,10 @@ class TeamsbotUserSettings(BaseModel):
|
|||
userId: str = Field(description="User ID (FK)")
|
||||
instanceId: str = Field(description="Feature instance ID (FK)")
|
||||
botName: Optional[str] = Field(default=None, description="Bot display name override")
|
||||
backgroundImageUrl: Optional[str] = Field(default=None, description="Background image URL override")
|
||||
aiSystemPrompt: Optional[str] = Field(default=None, description="AI system prompt override")
|
||||
responseMode: Optional[str] = Field(default=None, description="Response mode override: auto, manual, transcribeOnly")
|
||||
responseChannel: Optional[str] = Field(default=None, description="Response channel override: voice, chat, both")
|
||||
transferMode: Optional[str] = Field(default=None, description="Transfer mode override: caption, audio, auto")
|
||||
language: Optional[str] = Field(default=None, description="Language override (e.g. de-DE)")
|
||||
voiceId: Optional[str] = Field(default=None, description="TTS voice ID override")
|
||||
triggerIntervalSeconds: Optional[int] = Field(default=None, description="Trigger interval override")
|
||||
|
|
@ -167,18 +173,16 @@ class TeamsbotUserSettings(BaseModel):
|
|||
class TeamsbotConfig(BaseModel):
|
||||
"""Configuration for a Teams Bot feature instance (serves as default template for new users)."""
|
||||
botName: str = Field(default="AI Assistant", description="Default bot display name")
|
||||
backgroundImageUrl: Optional[str] = Field(default=None, description="Default background image URL")
|
||||
aiSystemPrompt: str = Field(
|
||||
default="Du bist ein hilfreicher Meeting-Assistent. Fasse wichtige Punkte zusammen und beantworte Fragen sachlich.",
|
||||
description="Custom system prompt for the AI analysis"
|
||||
)
|
||||
responseMode: TeamsbotResponseMode = Field(default=TeamsbotResponseMode.AUTO, description="How the bot responds")
|
||||
responseChannel: TeamsbotResponseChannel = Field(default=TeamsbotResponseChannel.VOICE, description="Channel for bot responses: voice, chat, or both")
|
||||
transferMode: TeamsbotTransferMode = Field(default=TeamsbotTransferMode.AUTO, description="How meeting content is captured: caption (Teams captions), audio (stream to gateway STT), or auto")
|
||||
language: str = Field(default="de-DE", description="Primary language for STT/TTS")
|
||||
voiceId: Optional[str] = Field(default=None, description="Google TTS voice ID (e.g., de-DE-Standard-A)")
|
||||
browserBotUrl: Optional[str] = Field(default=None, description="URL of the Browser Bot service. Falls back to TEAMSBOT_BROWSER_BOT_URL env variable if not set per-instance.")
|
||||
botAccountEmail: Optional[str] = Field(default=None, description="Dedicated Microsoft account email for authenticated bot join. Leave empty for anonymous join.")
|
||||
botAccountPassword: Optional[str] = Field(default=None, description="Dedicated Microsoft account password. MFA must be disabled for this account.")
|
||||
triggerIntervalSeconds: int = Field(default=10, ge=3, le=60, description="Seconds between periodic AI analysis triggers")
|
||||
triggerCooldownSeconds: int = Field(default=3, ge=1, le=30, description="Minimum seconds between AI calls")
|
||||
contextWindowSegments: int = Field(default=20, ge=5, le=100, description="Number of transcript segments to include in AI context")
|
||||
|
|
@ -199,7 +203,6 @@ class TeamsbotStartSessionRequest(BaseModel):
|
|||
"""Request to start a new Teams Bot session."""
|
||||
meetingLink: str = Field(description="Teams meeting join link (e.g., https://teams.microsoft.com/l/meetup-join/...)")
|
||||
botName: Optional[str] = Field(default=None, description="Override bot name for this session")
|
||||
backgroundImageUrl: Optional[str] = Field(default=None, description="Override background image for this session")
|
||||
connectionId: Optional[str] = Field(default=None, description="Microsoft connection ID for Graph API access")
|
||||
joinMode: Optional[TeamsbotJoinMode] = Field(default=None, description="How the bot joins: systemBot, anonymous, or userAccount. Defaults to systemBot if credentials configured, else anonymous.")
|
||||
sessionContext: Optional[str] = Field(default=None, description="Custom context/knowledge to provide to the bot for this session (e.g. meeting agenda, documents, background info)")
|
||||
|
|
@ -215,15 +218,13 @@ class TeamsbotSessionResponse(BaseModel):
|
|||
class TeamsbotConfigUpdateRequest(BaseModel):
|
||||
"""Request to update teamsbot configuration."""
|
||||
botName: Optional[str] = None
|
||||
backgroundImageUrl: Optional[str] = None
|
||||
aiSystemPrompt: Optional[str] = None
|
||||
responseMode: Optional[TeamsbotResponseMode] = None
|
||||
responseChannel: Optional[TeamsbotResponseChannel] = None
|
||||
transferMode: Optional[TeamsbotTransferMode] = None
|
||||
language: Optional[str] = None
|
||||
voiceId: Optional[str] = None
|
||||
browserBotUrl: Optional[str] = None
|
||||
botAccountEmail: Optional[str] = None
|
||||
botAccountPassword: Optional[str] = None
|
||||
triggerIntervalSeconds: Optional[int] = None
|
||||
triggerCooldownSeconds: Optional[int] = None
|
||||
contextWindowSegments: Optional[int] = None
|
||||
|
|
@ -249,7 +250,6 @@ class BridgeJoinRequest(BaseModel):
|
|||
"""Request sent to .NET Media Bridge to join a meeting."""
|
||||
meetingLink: str = Field(description="Teams meeting join link")
|
||||
botName: str = Field(description="Bot display name")
|
||||
backgroundImageUrl: Optional[str] = Field(default=None, description="Background image URL")
|
||||
gatewayCallbackUrl: str = Field(description="Gateway URL for bridge callbacks")
|
||||
gatewayWsUrl: str = Field(description="Gateway WebSocket URL for audio streaming")
|
||||
sessionId: str = Field(description="Session ID for correlation")
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@ async def startSession(
|
|||
mandateId=mandateId,
|
||||
meetingLink=cleanMeetingUrl,
|
||||
botName=body.botName or config.botName,
|
||||
backgroundImageUrl=body.backgroundImageUrl or config.backgroundImageUrl,
|
||||
sessionContext=body.sessionContext,
|
||||
status=TeamsbotSessionStatus.PENDING,
|
||||
startedByUserId=str(context.user.id),
|
||||
|
|
@ -449,8 +448,8 @@ def _getEffectiveConfig(instanceId: str, userId: str, interface) -> TeamsbotConf
|
|||
|
||||
# Merge: user settings override instance defaults (only non-None values)
|
||||
overrides = {}
|
||||
for field in ["botName", "backgroundImageUrl", "aiSystemPrompt", "responseMode",
|
||||
"responseChannel", "language", "voiceId",
|
||||
for field in ["botName", "aiSystemPrompt", "responseMode",
|
||||
"responseChannel", "transferMode", "language", "voiceId",
|
||||
"triggerIntervalSeconds", "triggerCooldownSeconds", "contextWindowSegments"]:
|
||||
value = userSettings.get(field)
|
||||
if value is not None:
|
||||
|
|
|
|||
|
|
@ -130,9 +130,9 @@ class TeamsbotService:
|
|||
instanceId=self.instanceId,
|
||||
gatewayWsUrl=fullGatewayWsUrl,
|
||||
language=self.config.language,
|
||||
botAccountEmail=self.config.botAccountEmail,
|
||||
botAccountPassword=self.config.botAccountPassword,
|
||||
backgroundImageUrl=session.get("backgroundImageUrl") or self.config.backgroundImageUrl,
|
||||
botAccountEmail=self.config.botAccountEmail if hasattr(self.config, 'botAccountEmail') else None,
|
||||
botAccountPassword=self.config.botAccountPassword if hasattr(self.config, 'botAccountPassword') else None,
|
||||
transferMode=self.config.transferMode if hasattr(self.config, 'transferMode') else "auto",
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
|
|
|
|||
Loading…
Reference in a new issue