Skip to content

Commit 3bd94dc

Browse files
authored
Fix chrome-140 breaking changes (#138)
1 parent 410bd1c commit 3bd94dc

File tree

4 files changed

+98
-14
lines changed

4 files changed

+98
-14
lines changed

daily-guards.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import type {
2+
DailyCall,
3+
DailyAdvancedConfig,
4+
DailyFactoryOptions,
5+
} from '@daily-co/daily-js';
6+
7+
export interface SafeDailyAdvancedConfig extends Omit<DailyAdvancedConfig, 'alwaysIncludeMicInPermissionPrompt'> {
8+
alwaysIncludeMicInPermissionPrompt?: true; // Only allow true
9+
}
10+
11+
export interface SafeDailyFactoryOptions extends Omit<DailyFactoryOptions, 'audioSource'> {
12+
audioSource?: string | boolean | MediaStreamTrack;
13+
}
14+
15+
export function createSafeDailyConfig(
16+
config?: Pick<DailyAdvancedConfig, 'avoidEval' | 'alwaysIncludeMicInPermissionPrompt'>
17+
): SafeDailyAdvancedConfig {
18+
if (!config) return {};
19+
20+
const { alwaysIncludeMicInPermissionPrompt, ...rest } = config;
21+
22+
// Force true or remove the property entirely. This can cause Chrome 140+ issues
23+
if (alwaysIncludeMicInPermissionPrompt === false) {
24+
console.warn(
25+
'[Vapi] alwaysIncludeMicInPermissionPrompt:false detected. ' +
26+
'This can cause Chrome 140+ issues. Removing the property.'
27+
);
28+
return rest;
29+
}
30+
31+
return config as SafeDailyAdvancedConfig;
32+
}
33+
34+
export function safeSetLocalAudio(call: DailyCall | null, enabled: boolean): void {
35+
if (!call) {
36+
throw new Error('Call object is not available.');
37+
}
38+
39+
// Never use forceDiscardTrack. This can cause Chrome 140+ issues
40+
call.setLocalAudio(enabled);
41+
}
42+
43+
export async function safeSetInputDevicesAsync(
44+
call: DailyCall | null,
45+
options: Parameters<DailyCall['setInputDevicesAsync']>[0]
46+
): Promise<void> {
47+
if (!call) {
48+
throw new Error('Call object is not available.');
49+
}
50+
51+
// Validate audioSource
52+
if ('audioSource' in options && options.audioSource === false) {
53+
console.warn(
54+
'[Vapi] setInputDevicesAsync with audioSource:false detected. ' +
55+
'This can cause Chrome 140+ issues. Using default device instead.'
56+
);
57+
58+
const { audioSource, ...safeOptions } = options;
59+
await call.setInputDevicesAsync(safeOptions);
60+
return;
61+
}
62+
63+
await call.setInputDevicesAsync(options);
64+
}
65+
66+
export function createSafeDailyFactoryOptions(
67+
options?: Pick<DailyFactoryOptions, 'audioSource' | 'startAudioOff'>
68+
): SafeDailyFactoryOptions {
69+
if (!options) return {};
70+
71+
// Ensure audioSource is never false
72+
if (options.audioSource === false) {
73+
console.warn(
74+
'[Vapi] audioSource:false detected in factory options. ' +
75+
'This can cause Chrome 140+ issues. Defaulting to true.'
76+
);
77+
return { ...options, audioSource: true };
78+
}
79+
80+
return options;
81+
}

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"node": ">=18.0.0"
3131
},
3232
"dependencies": {
33-
"@daily-co/daily-js": "^0.80.0",
33+
"@daily-co/daily-js": "^0.83.1",
3434
"events": "^3.3.0"
3535
},
3636
"devDependencies": {

vapi.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ import {
2121
WorkflowOverrides,
2222
} from './api';
2323
import { client } from './client';
24+
import {
25+
createSafeDailyConfig,
26+
createSafeDailyFactoryOptions,
27+
safeSetLocalAudio,
28+
safeSetInputDevicesAsync,
29+
} from './daily-guards';
2430

2531
export interface AddMessageMessage {
2632
type: 'add-message';
@@ -206,8 +212,8 @@ export default class Vapi extends VapiEventEmitter {
206212
super();
207213
client.baseUrl = apiBaseUrl ?? 'https://api.vapi.ai';
208214
client.setSecurityData(apiToken);
209-
this.dailyCallConfig = dailyCallConfig ?? {};
210-
this.dailyCallObject = dailyCallObject ?? {};
215+
this.dailyCallConfig = createSafeDailyConfig(dailyCallConfig);
216+
this.dailyCallObject = createSafeDailyFactoryOptions(dailyCallObject);
211217
}
212218

213219
private cleanup() {
@@ -649,7 +655,7 @@ export default class Vapi extends VapiEventEmitter {
649655
},
650656
})
651657
.then(() => {
652-
this.call?.setLocalAudio(true);
658+
safeSetLocalAudio(this.call, true);
653659
});
654660
}
655661
});
@@ -805,10 +811,7 @@ export default class Vapi extends VapiEventEmitter {
805811
}
806812

807813
public setMuted(mute: boolean) {
808-
if (!this.call) {
809-
throw new Error('Call object is not available.');
810-
}
811-
this.call.setLocalAudio(!mute);
814+
safeSetLocalAudio(this.call, !mute);
812815
}
813816

814817
public isMuted() {
@@ -832,7 +835,7 @@ export default class Vapi extends VapiEventEmitter {
832835
public setInputDevicesAsync(
833836
options: Parameters<DailyCall['setInputDevicesAsync']>[0],
834837
) {
835-
this.call?.setInputDevicesAsync(options);
838+
return safeSetInputDevicesAsync(this.call, options);
836839
}
837840

838841
public async increaseMicLevel(gain: number) {
@@ -855,7 +858,7 @@ export default class Vapi extends VapiEventEmitter {
855858
gainNode.connect(destination);
856859

857860
const [boostedTrack] = destination.stream.getAudioTracks();
858-
await this.call.setInputDevicesAsync({ audioSource: boostedTrack });
861+
await safeSetInputDevicesAsync(this.call, { audioSource: boostedTrack });
859862
} catch (error) {
860863
console.error("Error adjusting microphone level:", error);
861864
}

0 commit comments

Comments
 (0)