@vapi-ai/web 2.1.8 → 2.2.0

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
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import type { ChatCompletionMessageParam } from 'openai/resources';
3
- import { DailyCall, DailyAdvancedConfig, DailyFactoryOptions } from '@daily-co/daily-js';
3
+ import { DailyCall, DailyAdvancedConfig, DailyFactoryOptions, DailyParticipant, DailyVideoSendSettings } from '@daily-co/daily-js';
4
4
  import EventEmitter from 'events';
5
5
  import { Call, CreateSquadDTO, CreateAssistantDTO, AssistantOverrides } from './api';
6
6
  export interface AddMessageMessage {
@@ -18,7 +18,7 @@ export interface SayMessage {
18
18
  endCallAfterSpoken?: boolean;
19
19
  }
20
20
  type VapiClientToServerMessage = AddMessageMessage | ControlMessages | SayMessage;
21
- type VapiEventNames = 'call-end' | 'call-start' | 'volume-level' | 'speech-start' | 'speech-end' | 'message' | 'video' | 'error';
21
+ type VapiEventNames = 'call-end' | 'call-start' | 'volume-level' | 'speech-start' | 'speech-end' | 'message' | 'video' | 'error' | 'daily-participant-updated';
22
22
  type VapiEventListeners = {
23
23
  'call-end': () => void;
24
24
  'call-start': () => void;
@@ -28,6 +28,7 @@ type VapiEventListeners = {
28
28
  video: (track: MediaStreamTrack) => void;
29
29
  message: (message: any) => void;
30
30
  error: (error: any) => void;
31
+ 'daily-participant-updated': (participant: DailyParticipant) => void;
31
32
  };
32
33
  declare class VapiEventEmitter extends EventEmitter {
33
34
  on<E extends VapiEventNames>(event: E, listener: VapiEventListeners[E]): this;
@@ -57,5 +58,7 @@ export default class Vapi extends VapiEventEmitter {
57
58
  setInputDevicesAsync(options: Parameters<DailyCall['setInputDevicesAsync']>[0]): void;
58
59
  setOutputDeviceAsync(options: Parameters<DailyCall['setOutputDeviceAsync']>[0]): void;
59
60
  getDailyCallObject(): DailyCall | null;
61
+ startScreenSharing(displayMediaOptions?: DisplayMediaStreamOptions, screenVideoSendSettings?: DailyVideoSendSettings): void;
62
+ stopScreenSharing(): void;
60
63
  }
61
64
  export {};
package/dist/vapi.js CHANGED
@@ -105,7 +105,6 @@ class Vapi extends VapiEventEmitter {
105
105
  this.cleanup();
106
106
  }
107
107
  const isVideoRecordingEnabled = webCall?.artifactPlan?.videoRecordingEnabled ?? false;
108
- // @ts-expect-error This exists
109
108
  const isVideoEnabled = webCall.transport?.assistantVideoEnabled ?? false;
110
109
  this.call = daily_js_1.default.createCallObject({
111
110
  audioSource: this.dailyCallObject.audioSource ?? true,
@@ -120,11 +119,6 @@ class Vapi extends VapiEventEmitter {
120
119
  }
121
120
  this.cleanup();
122
121
  });
123
- this.call.on('participant-left', (e) => {
124
- if (!e)
125
- return;
126
- destroyAudioPlayer(e.participant.session_id);
127
- });
128
122
  this.call.on('error', (error) => {
129
123
  this.emit('error', error);
130
124
  if (isVideoRecordingEnabled) {
@@ -135,12 +129,15 @@ class Vapi extends VapiEventEmitter {
135
129
  this.emit('error', error);
136
130
  });
137
131
  this.call.on('track-started', async (e) => {
138
- if (!e || !e.participant)
132
+ if (!e || !e.participant) {
139
133
  return;
140
- if (e.participant?.local)
134
+ }
135
+ if (e.participant?.local) {
141
136
  return;
142
- if (e.participant?.user_name !== 'Vapi Speaker')
137
+ }
138
+ if (e.participant?.user_name !== 'Vapi Speaker') {
143
139
  return;
140
+ }
144
141
  if (e.track.kind === 'video') {
145
142
  this.emit('video', e.track);
146
143
  }
@@ -154,12 +151,25 @@ class Vapi extends VapiEventEmitter {
154
151
  return;
155
152
  subscribeToTracks(e, this.call, isVideoRecordingEnabled, isVideoEnabled);
156
153
  });
154
+ this.call.on('participant-updated', (e) => {
155
+ if (!e) {
156
+ return;
157
+ }
158
+ this.emit('daily-participant-updated', e.participant);
159
+ });
160
+ this.call.on('participant-left', (e) => {
161
+ if (!e) {
162
+ return;
163
+ }
164
+ destroyAudioPlayer(e.participant.session_id);
165
+ });
157
166
  // Allow mobile devices to finish processing the microphone permissions
158
167
  // request before joining the call and playing the assistant's audio
159
168
  if (this.isMobileDevice()) {
160
169
  await this.sleep(1000);
161
170
  }
162
171
  await this.call.join({
172
+ // @ts-expect-error This exists
163
173
  url: webCall.webCallUrl,
164
174
  subscribeToTracksAutomatically: false,
165
175
  });
@@ -220,8 +230,9 @@ class Vapi extends VapiEventEmitter {
220
230
  }
221
231
  }
222
232
  onAppMessage(e) {
223
- if (!e)
233
+ if (!e) {
224
234
  return;
235
+ }
225
236
  try {
226
237
  if (e.data === 'listening') {
227
238
  return this.emit('call-start');
@@ -244,8 +255,9 @@ class Vapi extends VapiEventEmitter {
244
255
  const speechLevel = Object.values(e.participantsAudioLevel).reduce((a, b) => a + b, 0);
245
256
  this.emit('volume-level', Math.min(1, speechLevel / 0.15));
246
257
  const isSpeaking = speechLevel > 0.01;
247
- if (!isSpeaking)
258
+ if (!isSpeaking) {
248
259
  return;
260
+ }
249
261
  if (this.speakingTimeout) {
250
262
  clearTimeout(this.speakingTimeout);
251
263
  this.speakingTimeout = null;
@@ -294,5 +306,14 @@ class Vapi extends VapiEventEmitter {
294
306
  getDailyCallObject() {
295
307
  return this.call;
296
308
  }
309
+ startScreenSharing(displayMediaOptions, screenVideoSendSettings) {
310
+ this.call?.startScreenShare({
311
+ displayMediaOptions,
312
+ screenVideoSendSettings,
313
+ });
314
+ }
315
+ stopScreenSharing() {
316
+ this.call?.stopScreenShare();
317
+ }
297
318
  }
298
319
  exports.default = Vapi;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vapi-ai/web",
3
- "version": "2.1.8",
3
+ "version": "2.2.0",
4
4
  "description": "",
5
5
  "main": "dist/vapi.js",
6
6
  "types": "dist/vapi.d.ts",
package/vapi.ts CHANGED
@@ -7,6 +7,8 @@ import DailyIframe, {
7
7
  DailyEventObjectAppMessage,
8
8
  DailyEventObjectParticipant,
9
9
  DailyEventObjectRemoteParticipantsAudioLevel,
10
+ DailyParticipant,
11
+ DailyVideoSendSettings,
10
12
  } from '@daily-co/daily-js';
11
13
  import EventEmitter from 'events';
12
14
 
@@ -48,7 +50,8 @@ type VapiEventNames =
48
50
  | 'speech-end'
49
51
  | 'message'
50
52
  | 'video'
51
- | 'error';
53
+ | 'error'
54
+ | 'daily-participant-updated';
52
55
 
53
56
  type VapiEventListeners = {
54
57
  'call-end': () => void;
@@ -59,6 +62,7 @@ type VapiEventListeners = {
59
62
  video: (track: MediaStreamTrack) => void;
60
63
  message: (message: any) => void;
61
64
  error: (error: any) => void;
65
+ 'daily-participant-updated': (participant: DailyParticipant) => void;
62
66
  };
63
67
 
64
68
  async function startAudioPlayer(
@@ -217,7 +221,6 @@ export default class Vapi extends VapiEventEmitter {
217
221
  const isVideoRecordingEnabled =
218
222
  webCall?.artifactPlan?.videoRecordingEnabled ?? false;
219
223
 
220
- // @ts-expect-error This exists
221
224
  const isVideoEnabled = webCall.transport?.assistantVideoEnabled ?? false;
222
225
 
223
226
  this.call = DailyIframe.createCallObject({
@@ -235,11 +238,6 @@ export default class Vapi extends VapiEventEmitter {
235
238
  this.cleanup();
236
239
  });
237
240
 
238
- this.call.on('participant-left', (e) => {
239
- if (!e) return;
240
- destroyAudioPlayer(e.participant.session_id);
241
- });
242
-
243
241
  this.call.on('error', (error: any) => {
244
242
  this.emit('error', error);
245
243
  if (isVideoRecordingEnabled) {
@@ -252,18 +250,21 @@ export default class Vapi extends VapiEventEmitter {
252
250
  });
253
251
 
254
252
  this.call.on('track-started', async (e) => {
255
- if (!e || !e.participant) return;
256
- if (e.participant?.local) return;
257
- if (e.participant?.user_name !== 'Vapi Speaker') return;
258
-
253
+ if (!e || !e.participant) {
254
+ return;
255
+ }
256
+ if (e.participant?.local) {
257
+ return;
258
+ }
259
+ if (e.participant?.user_name !== 'Vapi Speaker') {
260
+ return;
261
+ }
259
262
  if (e.track.kind === 'video') {
260
263
  this.emit('video', e.track);
261
264
  }
262
-
263
265
  if (e.track.kind === 'audio') {
264
266
  await buildAudioPlayer(e.track, e.participant.session_id);
265
267
  }
266
-
267
268
  this.call?.sendAppMessage('playable');
268
269
  });
269
270
 
@@ -277,6 +278,20 @@ export default class Vapi extends VapiEventEmitter {
277
278
  );
278
279
  });
279
280
 
281
+ this.call.on('participant-updated', (e) => {
282
+ if (!e) {
283
+ return;
284
+ }
285
+ this.emit('daily-participant-updated', e.participant);
286
+ });
287
+
288
+ this.call.on('participant-left', (e) => {
289
+ if (!e) {
290
+ return;
291
+ }
292
+ destroyAudioPlayer(e.participant.session_id);
293
+ });
294
+
280
295
  // Allow mobile devices to finish processing the microphone permissions
281
296
  // request before joining the call and playing the assistant's audio
282
297
  if (this.isMobileDevice()) {
@@ -284,6 +299,7 @@ export default class Vapi extends VapiEventEmitter {
284
299
  }
285
300
 
286
301
  await this.call.join({
302
+ // @ts-expect-error This exists
287
303
  url: webCall.webCallUrl,
288
304
  subscribeToTracksAutomatically: false,
289
305
  });
@@ -353,7 +369,9 @@ export default class Vapi extends VapiEventEmitter {
353
369
  }
354
370
 
355
371
  private onAppMessage(e?: DailyEventObjectAppMessage) {
356
- if (!e) return;
372
+ if (!e) {
373
+ return;
374
+ }
357
375
  try {
358
376
  if (e.data === 'listening') {
359
377
  return this.emit('call-start');
@@ -382,7 +400,9 @@ export default class Vapi extends VapiEventEmitter {
382
400
 
383
401
  const isSpeaking = speechLevel > 0.01;
384
402
 
385
- if (!isSpeaking) return;
403
+ if (!isSpeaking) {
404
+ return;
405
+ }
386
406
 
387
407
  if (this.speakingTimeout) {
388
408
  clearTimeout(this.speakingTimeout);
@@ -444,4 +464,15 @@ export default class Vapi extends VapiEventEmitter {
444
464
  public getDailyCallObject(): DailyCall | null {
445
465
  return this.call;
446
466
  }
467
+
468
+ public startScreenSharing(displayMediaOptions?: DisplayMediaStreamOptions, screenVideoSendSettings?: DailyVideoSendSettings) {
469
+ this.call?.startScreenShare({
470
+ displayMediaOptions,
471
+ screenVideoSendSettings,
472
+ });
473
+ }
474
+
475
+ public stopScreenSharing() {
476
+ this.call?.stopScreenShare();
477
+ }
447
478
  }