@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/api.ts +11512 -4890
- package/dist/api.d.ts +7686 -2370
- package/dist/api.js +346 -313
- package/dist/vapi.d.ts +5 -2
- package/dist/vapi.js +32 -11
- package/package.json +1 -1
- package/vapi.ts +46 -15
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
|
-
|
|
134
|
+
}
|
|
135
|
+
if (e.participant?.local) {
|
|
141
136
|
return;
|
|
142
|
-
|
|
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
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)
|
|
256
|
-
|
|
257
|
-
|
|
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)
|
|
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)
|
|
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
|
}
|