From 003e21efcd2807c9af74038e594cfb8a7cff3b43 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Wed, 18 Feb 2026 22:32:45 +0100
Subject: [PATCH] fix: use resolveLaunchUrl to put suppress params on launcher
URL, not inside encoded meeting URL
Co-authored-by: Cursor
---
src/bot/orchestrator.ts | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/bot/orchestrator.ts b/src/bot/orchestrator.ts
index 8749100..1c80fae 100644
--- a/src/bot/orchestrator.ts
+++ b/src/bot/orchestrator.ts
@@ -15,7 +15,7 @@ import { AudioCaptureProcedure } from './audioCaptureProcedure';
import { ChatProcedure, ChatMessageEntry } from './chatProcedure';
import { AuthProcedure } from './authProcedure';
import { TeamsActionsService } from './teamsActionsService';
-import { isValidMeetingUrl, getMeetingLaunchUrl } from './meetingUrlParser';
+import { isValidMeetingUrl, getMeetingLaunchUrl, resolveLaunchUrl } from './meetingUrlParser';
// Camera / fake video injection is disabled for now to focus on stability.
// The Y4M fake video file was causing browser crashes when audio started flowing.
@@ -264,11 +264,21 @@ export class BotOrchestrator {
}
await this._takeScreenshot('step3-teams-loaded', true);
- // STEP 4: Navigate to the meeting URL with launch params
- // Add suppressPrompt, msLaunch=false, directDl=true to skip the native
- // "Open in Teams app?" dialog that blocks Playwright (invisible native prompt).
- // For auth join we strip anon=true since the user is authenticated.
- let launchUrl = getMeetingLaunchUrl(this._meetingUrl);
+ // STEP 4: Navigate to the meeting URL with proper launch params.
+ // CRITICAL: The suppress params (msLaunch, suppressPrompt, directDl) must
+ // be on the LAUNCHER URL itself, NOT inside the encoded meeting URL parameter.
+ // resolveLaunchUrl follows redirects first (meeting URL → launcher URL),
+ // then adds the params to the RESOLVED launcher URL. getMeetingLaunchUrl
+ // adds params to the raw meeting URL — they end up encoded inside the
+ // launcher's url= parameter and have no effect on the launcher behavior.
+ let launchUrl: string;
+ try {
+ launchUrl = await resolveLaunchUrl(this._meetingUrl);
+ } catch (error) {
+ this._logger.warn(`Could not resolve launch URL, using fallback: ${error}`);
+ launchUrl = getMeetingLaunchUrl(this._meetingUrl);
+ }
+ // Remove anon=true since the user is authenticated
try {
const urlObj = new URL(launchUrl);
urlObj.searchParams.delete('anon');