@vapi-ai/web 2.1.7 → 2.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vapi.d.ts CHANGED
@@ -44,6 +44,8 @@ export default class Vapi extends VapiEventEmitter {
44
44
  private dailyCallObject;
45
45
  constructor(apiToken: string, apiBaseUrl?: string, dailyCallConfig?: Pick<DailyAdvancedConfig, 'avoidEval' | 'alwaysIncludeMicInPermissionPrompt'>, dailyCallObject?: Pick<DailyFactoryOptions, 'audioSource'>);
46
46
  private cleanup;
47
+ private isMobileDevice;
48
+ private sleep;
47
49
  start(assistant?: CreateAssistantDTO | string, assistantOverrides?: AssistantOverrides, squad?: CreateSquadDTO | string): Promise<Call | null>;
48
50
  private onAppMessage;
49
51
  private handleRemoteParticipantsAudioLevel;
package/dist/vapi.js CHANGED
@@ -75,6 +75,16 @@ class Vapi extends VapiEventEmitter {
75
75
  this.call = null;
76
76
  this.speakingTimeout = null;
77
77
  }
78
+ isMobileDevice() {
79
+ if (typeof navigator === 'undefined') {
80
+ return false;
81
+ }
82
+ const userAgent = navigator.userAgent;
83
+ return /android|iphone|ipad|ipod|iemobile|blackberry|bada/i.test(userAgent.toLowerCase());
84
+ }
85
+ async sleep(ms) {
86
+ return new Promise((resolve) => setTimeout(resolve, ms));
87
+ }
78
88
  async start(assistant, assistantOverrides, squad) {
79
89
  if (!assistant && !squad) {
80
90
  throw new Error('Assistant or Squad must be provided.');
@@ -95,7 +105,6 @@ class Vapi extends VapiEventEmitter {
95
105
  this.cleanup();
96
106
  }
97
107
  const isVideoRecordingEnabled = webCall?.artifactPlan?.videoRecordingEnabled ?? false;
98
- // @ts-expect-error This exists
99
108
  const isVideoEnabled = webCall.transport?.assistantVideoEnabled ?? false;
100
109
  this.call = daily_js_1.default.createCallObject({
101
110
  audioSource: this.dailyCallObject.audioSource ?? true,
@@ -144,7 +153,13 @@ class Vapi extends VapiEventEmitter {
144
153
  return;
145
154
  subscribeToTracks(e, this.call, isVideoRecordingEnabled, isVideoEnabled);
146
155
  });
156
+ // Allow mobile devices to finish processing the microphone permissions
157
+ // request before joining the call and playing the assistant's audio
158
+ if (this.isMobileDevice()) {
159
+ await this.sleep(1000);
160
+ }
147
161
  await this.call.join({
162
+ // @ts-expect-error This exists
148
163
  url: webCall.webCallUrl,
149
164
  subscribeToTracksAutomatically: false,
150
165
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vapi-ai/web",
3
- "version": "2.1.7",
3
+ "version": "2.1.9",
4
4
  "description": "",
5
5
  "main": "dist/vapi.js",
6
6
  "types": "dist/vapi.d.ts",
@@ -23,7 +23,6 @@
23
23
  "homepage": "https://github.com/VapiAI/web#readme",
24
24
  "dependencies": {
25
25
  "@daily-co/daily-js": "^0.72.1",
26
- "@vapi-ai/web": "^2.1.5",
27
26
  "events": "^3.3.0"
28
27
  },
29
28
  "devDependencies": {
package/vapi.ts CHANGED
@@ -18,6 +18,49 @@ import {
18
18
  } from './api';
19
19
  import { client } from './client';
20
20
 
21
+ export interface AddMessageMessage {
22
+ type: 'add-message';
23
+ message: ChatCompletionMessageParam;
24
+ }
25
+
26
+ export interface ControlMessages {
27
+ type: 'control';
28
+ control: 'mute-assistant' | 'unmute-assistant' | 'say-first-message';
29
+ videoRecordingStartDelaySeconds?: number;
30
+ }
31
+
32
+ export interface SayMessage {
33
+ type: 'say';
34
+ message: string;
35
+ endCallAfterSpoken?: boolean;
36
+ }
37
+
38
+ type VapiClientToServerMessage =
39
+ | AddMessageMessage
40
+ | ControlMessages
41
+ | SayMessage;
42
+
43
+ type VapiEventNames =
44
+ | 'call-end'
45
+ | 'call-start'
46
+ | 'volume-level'
47
+ | 'speech-start'
48
+ | 'speech-end'
49
+ | 'message'
50
+ | 'video'
51
+ | 'error';
52
+
53
+ type VapiEventListeners = {
54
+ 'call-end': () => void;
55
+ 'call-start': () => void;
56
+ 'volume-level': (volume: number) => void;
57
+ 'speech-start': () => void;
58
+ 'speech-end': () => void;
59
+ video: (track: MediaStreamTrack) => void;
60
+ message: (message: any) => void;
61
+ error: (error: any) => void;
62
+ };
63
+
21
64
  async function startAudioPlayer(
22
65
  player: HTMLAudioElement,
23
66
  track: MediaStreamTrack,
@@ -64,49 +107,6 @@ function subscribeToTracks(
64
107
  });
65
108
  }
66
109
 
67
- export interface AddMessageMessage {
68
- type: 'add-message';
69
- message: ChatCompletionMessageParam;
70
- }
71
-
72
- export interface ControlMessages {
73
- type: 'control';
74
- control: 'mute-assistant' | 'unmute-assistant' | 'say-first-message';
75
- videoRecordingStartDelaySeconds?: number;
76
- }
77
-
78
- export interface SayMessage {
79
- type: 'say';
80
- message: string;
81
- endCallAfterSpoken?: boolean;
82
- }
83
-
84
- type VapiClientToServerMessage =
85
- | AddMessageMessage
86
- | ControlMessages
87
- | SayMessage;
88
-
89
- type VapiEventNames =
90
- | 'call-end'
91
- | 'call-start'
92
- | 'volume-level'
93
- | 'speech-start'
94
- | 'speech-end'
95
- | 'message'
96
- | 'video'
97
- | 'error';
98
-
99
- type VapiEventListeners = {
100
- 'call-end': () => void;
101
- 'call-start': () => void;
102
- 'volume-level': (volume: number) => void;
103
- 'speech-start': () => void;
104
- 'speech-end': () => void;
105
- video: (track: MediaStreamTrack) => void;
106
- message: (message: any) => void;
107
- error: (error: any) => void;
108
- };
109
-
110
110
  class VapiEventEmitter extends EventEmitter {
111
111
  on<E extends VapiEventNames>(
112
112
  event: E,
@@ -171,6 +171,20 @@ export default class Vapi extends VapiEventEmitter {
171
171
  this.speakingTimeout = null;
172
172
  }
173
173
 
174
+ private isMobileDevice() {
175
+ if (typeof navigator === 'undefined') {
176
+ return false;
177
+ }
178
+ const userAgent = navigator.userAgent;
179
+ return /android|iphone|ipad|ipod|iemobile|blackberry|bada/i.test(
180
+ userAgent.toLowerCase(),
181
+ );
182
+ }
183
+
184
+ private async sleep(ms: number) {
185
+ return new Promise((resolve) => setTimeout(resolve, ms));
186
+ }
187
+
174
188
  async start(
175
189
  assistant?: CreateAssistantDTO | string,
176
190
  assistantOverrides?: AssistantOverrides,
@@ -203,7 +217,6 @@ export default class Vapi extends VapiEventEmitter {
203
217
  const isVideoRecordingEnabled =
204
218
  webCall?.artifactPlan?.videoRecordingEnabled ?? false;
205
219
 
206
- // @ts-expect-error This exists
207
220
  const isVideoEnabled = webCall.transport?.assistantVideoEnabled ?? false;
208
221
 
209
222
  this.call = DailyIframe.createCallObject({
@@ -263,7 +276,14 @@ export default class Vapi extends VapiEventEmitter {
263
276
  );
264
277
  });
265
278
 
279
+ // Allow mobile devices to finish processing the microphone permissions
280
+ // request before joining the call and playing the assistant's audio
281
+ if (this.isMobileDevice()) {
282
+ await this.sleep(1000);
283
+ }
284
+
266
285
  await this.call.join({
286
+ // @ts-expect-error This exists
267
287
  url: webCall.webCallUrl,
268
288
  subscribeToTracksAutomatically: false,
269
289
  });