@vapi-ai/web 2.3.10 → 2.5.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 +2293 -504
- package/dist/api.d.ts +1515 -212
- package/dist/api.js +156 -2
- package/dist/vapi.d.ts +71 -3
- package/dist/vapi.js +403 -10
- package/package.json +4 -3
- package/vapi.ts +491 -10
package/dist/vapi.js
CHANGED
|
@@ -71,11 +71,13 @@ class Vapi extends VapiEventEmitter {
|
|
|
71
71
|
this.dailyCallConfig = (0, daily_guards_1.createSafeDailyConfig)(dailyCallConfig);
|
|
72
72
|
this.dailyCallObject = (0, daily_guards_1.createSafeDailyFactoryOptions)(dailyCallObject);
|
|
73
73
|
}
|
|
74
|
-
cleanup() {
|
|
74
|
+
async cleanup() {
|
|
75
75
|
this.started = false;
|
|
76
76
|
this.hasEmittedCallEndedStatus = false;
|
|
77
|
-
this.call
|
|
78
|
-
|
|
77
|
+
if (this.call) {
|
|
78
|
+
await this.call.destroy();
|
|
79
|
+
this.call = null;
|
|
80
|
+
}
|
|
79
81
|
this.speakingTimeout = null;
|
|
80
82
|
}
|
|
81
83
|
isMobileDevice() {
|
|
@@ -88,7 +90,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
88
90
|
async sleep(ms) {
|
|
89
91
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
90
92
|
}
|
|
91
|
-
async start(assistant, assistantOverrides, squad, workflow, workflowOverrides) {
|
|
93
|
+
async start(assistant, assistantOverrides, squad, workflow, workflowOverrides, options) {
|
|
92
94
|
const startTime = Date.now();
|
|
93
95
|
// Input validation with detailed error messages
|
|
94
96
|
if (!assistant && !squad && !workflow) {
|
|
@@ -138,6 +140,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
138
140
|
workflow: typeof workflow === 'string' ? undefined : workflow,
|
|
139
141
|
workflowId: typeof workflow === 'string' ? workflow : undefined,
|
|
140
142
|
workflowOverrides,
|
|
143
|
+
roomDeleteOnUserLeaveEnabled: options?.roomDeleteOnUserLeaveEnabled,
|
|
141
144
|
})).data;
|
|
142
145
|
const webCallDuration = Date.now() - webCallStartTime;
|
|
143
146
|
this.emit('call-start-progress', {
|
|
@@ -158,7 +161,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
158
161
|
timestamp: new Date().toISOString(),
|
|
159
162
|
metadata: { action: 'cleanup-existing' }
|
|
160
163
|
});
|
|
161
|
-
this.cleanup();
|
|
164
|
+
await this.cleanup();
|
|
162
165
|
}
|
|
163
166
|
const isVideoRecordingEnabled = webCall?.artifactPlan?.videoRecordingEnabled ?? false;
|
|
164
167
|
const isVideoEnabled = webCall?.assistant?.voice?.provider === 'tavus';
|
|
@@ -220,7 +223,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
220
223
|
if (isVideoRecordingEnabled) {
|
|
221
224
|
this.call?.stopRecording();
|
|
222
225
|
}
|
|
223
|
-
this.cleanup();
|
|
226
|
+
this.cleanup().catch(console.error);
|
|
224
227
|
});
|
|
225
228
|
this.call.on('error', (error) => {
|
|
226
229
|
this.emit('error', error);
|
|
@@ -537,7 +540,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
537
540
|
isMobile: this.isMobileDevice()
|
|
538
541
|
}
|
|
539
542
|
});
|
|
540
|
-
this.cleanup();
|
|
543
|
+
await this.cleanup();
|
|
541
544
|
return null;
|
|
542
545
|
}
|
|
543
546
|
}
|
|
@@ -585,11 +588,25 @@ class Vapi extends VapiEventEmitter {
|
|
|
585
588
|
this.speakingTimeout = null;
|
|
586
589
|
}, 1000);
|
|
587
590
|
}
|
|
588
|
-
|
|
591
|
+
/**
|
|
592
|
+
* Stops the call by destroying the Daily call object.
|
|
593
|
+
*
|
|
594
|
+
* If `roomDeleteOnUserLeaveEnabled` is set to `false`, the Vapi call will be kept alive, allowing reconnections to the same call using the `reconnect` method.
|
|
595
|
+
* If `roomDeleteOnUserLeaveEnabled` is set to `true`, the Vapi call will also be destroyed, preventing any reconnections.
|
|
596
|
+
*/
|
|
597
|
+
async stop() {
|
|
589
598
|
this.started = false;
|
|
590
|
-
this.call
|
|
591
|
-
|
|
599
|
+
if (this.call) {
|
|
600
|
+
await this.call.destroy();
|
|
601
|
+
this.call = null;
|
|
602
|
+
}
|
|
603
|
+
this.speakingTimeout = null;
|
|
592
604
|
}
|
|
605
|
+
/**
|
|
606
|
+
* Sends a Live Call Control message to the Vapi server.
|
|
607
|
+
*
|
|
608
|
+
* Docs: https://docs.vapi.ai/calls/call-features
|
|
609
|
+
*/
|
|
593
610
|
send(message) {
|
|
594
611
|
this.call?.sendAppMessage(JSON.stringify(message));
|
|
595
612
|
}
|
|
@@ -611,6 +628,17 @@ class Vapi extends VapiEventEmitter {
|
|
|
611
628
|
interruptAssistantEnabled: interruptAssistantEnabled ?? false,
|
|
612
629
|
});
|
|
613
630
|
}
|
|
631
|
+
/**
|
|
632
|
+
* Ends the call immediately by sending a `end-call` message using Live Call Control, and destroys the Daily call object.
|
|
633
|
+
*
|
|
634
|
+
* This method always ends the call, regardless of the `roomDeleteOnUserLeaveEnabled` option.
|
|
635
|
+
*/
|
|
636
|
+
end() {
|
|
637
|
+
this.send({
|
|
638
|
+
type: 'end-call',
|
|
639
|
+
});
|
|
640
|
+
this.stop();
|
|
641
|
+
}
|
|
614
642
|
setInputDevicesAsync(options) {
|
|
615
643
|
return (0, daily_guards_1.safeSetInputDevicesAsync)(this.call, options);
|
|
616
644
|
}
|
|
@@ -649,5 +677,370 @@ class Vapi extends VapiEventEmitter {
|
|
|
649
677
|
stopScreenSharing() {
|
|
650
678
|
this.call?.stopScreenShare();
|
|
651
679
|
}
|
|
680
|
+
/**
|
|
681
|
+
* Reconnects to an active call.
|
|
682
|
+
*
|
|
683
|
+
*
|
|
684
|
+
* @param webCall
|
|
685
|
+
*/
|
|
686
|
+
async reconnect(webCall) {
|
|
687
|
+
const startTime = Date.now();
|
|
688
|
+
if (this.started) {
|
|
689
|
+
throw new Error('Cannot reconnect while a call is already in progress. Call stop() first.');
|
|
690
|
+
}
|
|
691
|
+
if (!webCall.webCallUrl) {
|
|
692
|
+
throw new Error('webCallUrl is required for reconnection.');
|
|
693
|
+
}
|
|
694
|
+
this.emit('call-start-progress', {
|
|
695
|
+
stage: 'reconnect-initialization',
|
|
696
|
+
status: 'started',
|
|
697
|
+
timestamp: new Date().toISOString(),
|
|
698
|
+
metadata: {
|
|
699
|
+
callId: webCall.id || 'unknown',
|
|
700
|
+
hasVideoRecording: !!webCall?.artifactPlan?.videoRecordingEnabled,
|
|
701
|
+
voiceProvider: webCall?.assistant?.voice?.provider || 'unknown'
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
this.started = true;
|
|
705
|
+
try {
|
|
706
|
+
// Clean up any existing call object
|
|
707
|
+
if (this.call) {
|
|
708
|
+
this.emit('call-start-progress', {
|
|
709
|
+
stage: 'cleanup-existing-call',
|
|
710
|
+
status: 'started',
|
|
711
|
+
timestamp: new Date().toISOString()
|
|
712
|
+
});
|
|
713
|
+
await this.cleanup();
|
|
714
|
+
this.emit('call-start-progress', {
|
|
715
|
+
stage: 'cleanup-existing-call',
|
|
716
|
+
status: 'completed',
|
|
717
|
+
timestamp: new Date().toISOString()
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
const isVideoRecordingEnabled = webCall?.artifactPlan?.videoRecordingEnabled ?? false;
|
|
721
|
+
const isVideoEnabled = webCall?.assistant?.voice?.provider === 'tavus';
|
|
722
|
+
// Stage 1: Create Daily call object
|
|
723
|
+
this.emit('call-start-progress', {
|
|
724
|
+
stage: 'daily-call-object-creation',
|
|
725
|
+
status: 'started',
|
|
726
|
+
timestamp: new Date().toISOString(),
|
|
727
|
+
metadata: {
|
|
728
|
+
audioSource: this.dailyCallObject.audioSource ?? true,
|
|
729
|
+
videoSource: this.dailyCallObject.videoSource ?? isVideoRecordingEnabled,
|
|
730
|
+
isVideoRecordingEnabled,
|
|
731
|
+
isVideoEnabled
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
const dailyCallStartTime = Date.now();
|
|
735
|
+
this.call = daily_js_1.default.createCallObject({
|
|
736
|
+
audioSource: this.dailyCallObject.audioSource ?? true,
|
|
737
|
+
videoSource: this.dailyCallObject.videoSource ?? isVideoRecordingEnabled,
|
|
738
|
+
dailyConfig: this.dailyCallConfig,
|
|
739
|
+
});
|
|
740
|
+
const dailyCallDuration = Date.now() - dailyCallStartTime;
|
|
741
|
+
this.emit('call-start-progress', {
|
|
742
|
+
stage: 'daily-call-object-creation',
|
|
743
|
+
status: 'completed',
|
|
744
|
+
duration: dailyCallDuration,
|
|
745
|
+
timestamp: new Date().toISOString()
|
|
746
|
+
});
|
|
747
|
+
this.call.iframe()?.style.setProperty('display', 'none');
|
|
748
|
+
// Set up event listeners
|
|
749
|
+
this.call.on('left-meeting', () => {
|
|
750
|
+
this.emit('call-end');
|
|
751
|
+
if (!this.hasEmittedCallEndedStatus) {
|
|
752
|
+
this.emit('message', {
|
|
753
|
+
type: 'status-update',
|
|
754
|
+
status: 'ended',
|
|
755
|
+
'endedReason': 'customer-ended-call',
|
|
756
|
+
});
|
|
757
|
+
this.hasEmittedCallEndedStatus = true;
|
|
758
|
+
}
|
|
759
|
+
if (isVideoRecordingEnabled) {
|
|
760
|
+
this.call?.stopRecording();
|
|
761
|
+
}
|
|
762
|
+
this.cleanup().catch(console.error);
|
|
763
|
+
});
|
|
764
|
+
this.call.on('error', (error) => {
|
|
765
|
+
this.emit('error', error);
|
|
766
|
+
if (isVideoRecordingEnabled) {
|
|
767
|
+
this.call?.stopRecording();
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
this.call.on('camera-error', (error) => {
|
|
771
|
+
this.emit('camera-error', error);
|
|
772
|
+
});
|
|
773
|
+
this.call.on('network-quality-change', (event) => {
|
|
774
|
+
this.emit('network-quality-change', event);
|
|
775
|
+
});
|
|
776
|
+
this.call.on('network-connection', (event) => {
|
|
777
|
+
this.emit('network-connection', event);
|
|
778
|
+
});
|
|
779
|
+
this.call.on('track-started', async (e) => {
|
|
780
|
+
if (!e || !e.participant) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
if (e.participant?.local) {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (e.participant?.user_name !== 'Vapi Speaker') {
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
if (e.track.kind === 'video') {
|
|
790
|
+
this.emit('video', e.track);
|
|
791
|
+
}
|
|
792
|
+
if (e.track.kind === 'audio') {
|
|
793
|
+
await buildAudioPlayer(e.track, e.participant.session_id);
|
|
794
|
+
}
|
|
795
|
+
this.call?.sendAppMessage('playable');
|
|
796
|
+
});
|
|
797
|
+
this.call.on('participant-joined', (e) => {
|
|
798
|
+
if (!e || !this.call)
|
|
799
|
+
return;
|
|
800
|
+
subscribeToTracks(e, this.call, isVideoRecordingEnabled, isVideoEnabled);
|
|
801
|
+
});
|
|
802
|
+
this.call.on('participant-updated', (e) => {
|
|
803
|
+
if (!e) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
this.emit('daily-participant-updated', e.participant);
|
|
807
|
+
});
|
|
808
|
+
this.call.on('participant-left', (e) => {
|
|
809
|
+
if (!e) {
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
destroyAudioPlayer(e.participant.session_id);
|
|
813
|
+
});
|
|
814
|
+
this.call.on('remote-participants-audio-level', (e) => {
|
|
815
|
+
if (e)
|
|
816
|
+
this.handleRemoteParticipantsAudioLevel(e);
|
|
817
|
+
});
|
|
818
|
+
this.call.on('app-message', (e) => this.onAppMessage(e));
|
|
819
|
+
this.call.on('nonfatal-error', (e) => {
|
|
820
|
+
// https://docs.daily.co/reference/daily-js/events/meeting-events#type-audio-processor-error
|
|
821
|
+
if (e?.type === 'audio-processor-error') {
|
|
822
|
+
this.call
|
|
823
|
+
?.updateInputSettings({
|
|
824
|
+
audio: {
|
|
825
|
+
processor: {
|
|
826
|
+
type: 'none',
|
|
827
|
+
},
|
|
828
|
+
},
|
|
829
|
+
})
|
|
830
|
+
.then(() => {
|
|
831
|
+
(0, daily_guards_1.safeSetLocalAudio)(this.call, true);
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
// Stage 2: Mobile device handling and permissions
|
|
836
|
+
const isMobile = this.isMobileDevice();
|
|
837
|
+
this.emit('call-start-progress', {
|
|
838
|
+
stage: 'mobile-permissions',
|
|
839
|
+
status: 'started',
|
|
840
|
+
timestamp: new Date().toISOString(),
|
|
841
|
+
metadata: { isMobile }
|
|
842
|
+
});
|
|
843
|
+
if (isMobile) {
|
|
844
|
+
const mobileWaitStartTime = Date.now();
|
|
845
|
+
await this.sleep(1000);
|
|
846
|
+
const mobileWaitDuration = Date.now() - mobileWaitStartTime;
|
|
847
|
+
this.emit('call-start-progress', {
|
|
848
|
+
stage: 'mobile-permissions',
|
|
849
|
+
status: 'completed',
|
|
850
|
+
duration: mobileWaitDuration,
|
|
851
|
+
timestamp: new Date().toISOString(),
|
|
852
|
+
metadata: { action: 'permissions-wait' }
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
this.emit('call-start-progress', {
|
|
857
|
+
stage: 'mobile-permissions',
|
|
858
|
+
status: 'completed',
|
|
859
|
+
timestamp: new Date().toISOString(),
|
|
860
|
+
metadata: { action: 'skipped-not-mobile' }
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
// Stage 3: Join the call
|
|
864
|
+
this.emit('call-start-progress', {
|
|
865
|
+
stage: 'daily-call-join',
|
|
866
|
+
status: 'started',
|
|
867
|
+
timestamp: new Date().toISOString()
|
|
868
|
+
});
|
|
869
|
+
const joinStartTime = Date.now();
|
|
870
|
+
await this.call.join({
|
|
871
|
+
url: webCall.webCallUrl,
|
|
872
|
+
subscribeToTracksAutomatically: false,
|
|
873
|
+
});
|
|
874
|
+
const joinDuration = Date.now() - joinStartTime;
|
|
875
|
+
this.emit('call-start-progress', {
|
|
876
|
+
stage: 'daily-call-join',
|
|
877
|
+
status: 'completed',
|
|
878
|
+
duration: joinDuration,
|
|
879
|
+
timestamp: new Date().toISOString()
|
|
880
|
+
});
|
|
881
|
+
// Stage 4: Video recording setup (if enabled)
|
|
882
|
+
if (isVideoRecordingEnabled) {
|
|
883
|
+
this.emit('call-start-progress', {
|
|
884
|
+
stage: 'video-recording-setup',
|
|
885
|
+
status: 'started',
|
|
886
|
+
timestamp: new Date().toISOString()
|
|
887
|
+
});
|
|
888
|
+
const recordingStartTime = Date.now();
|
|
889
|
+
const recordingRequestedTime = new Date().getTime();
|
|
890
|
+
try {
|
|
891
|
+
this.call.startRecording({
|
|
892
|
+
width: 1280,
|
|
893
|
+
height: 720,
|
|
894
|
+
backgroundColor: '#FF1F2D3D',
|
|
895
|
+
layout: {
|
|
896
|
+
preset: 'default',
|
|
897
|
+
},
|
|
898
|
+
});
|
|
899
|
+
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
900
|
+
this.emit('call-start-progress', {
|
|
901
|
+
stage: 'video-recording-setup',
|
|
902
|
+
status: 'completed',
|
|
903
|
+
duration: recordingSetupDuration,
|
|
904
|
+
timestamp: new Date().toISOString()
|
|
905
|
+
});
|
|
906
|
+
this.call.on('recording-started', () => {
|
|
907
|
+
const totalRecordingDelay = (new Date().getTime() - recordingRequestedTime) / 1000;
|
|
908
|
+
this.emit('call-start-progress', {
|
|
909
|
+
stage: 'video-recording-started',
|
|
910
|
+
status: 'completed',
|
|
911
|
+
timestamp: new Date().toISOString(),
|
|
912
|
+
metadata: { delaySeconds: totalRecordingDelay }
|
|
913
|
+
});
|
|
914
|
+
this.send({
|
|
915
|
+
type: 'control',
|
|
916
|
+
control: 'say-first-message',
|
|
917
|
+
videoRecordingStartDelaySeconds: totalRecordingDelay,
|
|
918
|
+
});
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
catch (error) {
|
|
922
|
+
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
923
|
+
this.emit('call-start-progress', {
|
|
924
|
+
stage: 'video-recording-setup',
|
|
925
|
+
status: 'failed',
|
|
926
|
+
duration: recordingSetupDuration,
|
|
927
|
+
timestamp: new Date().toISOString(),
|
|
928
|
+
metadata: { error: error?.toString() }
|
|
929
|
+
});
|
|
930
|
+
// Don't throw here, video recording is optional
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
this.emit('call-start-progress', {
|
|
935
|
+
stage: 'video-recording-setup',
|
|
936
|
+
status: 'completed',
|
|
937
|
+
timestamp: new Date().toISOString(),
|
|
938
|
+
metadata: { action: 'skipped-not-enabled' }
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
// Stage 5: Audio level observer setup
|
|
942
|
+
this.emit('call-start-progress', {
|
|
943
|
+
stage: 'audio-observer-setup',
|
|
944
|
+
status: 'started',
|
|
945
|
+
timestamp: new Date().toISOString()
|
|
946
|
+
});
|
|
947
|
+
const audioObserverStartTime = Date.now();
|
|
948
|
+
try {
|
|
949
|
+
this.call.startRemoteParticipantsAudioLevelObserver(100);
|
|
950
|
+
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
951
|
+
this.emit('call-start-progress', {
|
|
952
|
+
stage: 'audio-observer-setup',
|
|
953
|
+
status: 'completed',
|
|
954
|
+
duration: audioObserverDuration,
|
|
955
|
+
timestamp: new Date().toISOString()
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
catch (error) {
|
|
959
|
+
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
960
|
+
this.emit('call-start-progress', {
|
|
961
|
+
stage: 'audio-observer-setup',
|
|
962
|
+
status: 'failed',
|
|
963
|
+
duration: audioObserverDuration,
|
|
964
|
+
timestamp: new Date().toISOString(),
|
|
965
|
+
metadata: { error: error?.toString() }
|
|
966
|
+
});
|
|
967
|
+
// Don't throw here, this is non-critical
|
|
968
|
+
}
|
|
969
|
+
// Stage 6: Audio processing setup
|
|
970
|
+
this.emit('call-start-progress', {
|
|
971
|
+
stage: 'audio-processing-setup',
|
|
972
|
+
status: 'started',
|
|
973
|
+
timestamp: new Date().toISOString()
|
|
974
|
+
});
|
|
975
|
+
const audioProcessingStartTime = Date.now();
|
|
976
|
+
try {
|
|
977
|
+
this.call.updateInputSettings({
|
|
978
|
+
audio: {
|
|
979
|
+
processor: {
|
|
980
|
+
type: 'noise-cancellation',
|
|
981
|
+
},
|
|
982
|
+
},
|
|
983
|
+
});
|
|
984
|
+
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
985
|
+
this.emit('call-start-progress', {
|
|
986
|
+
stage: 'audio-processing-setup',
|
|
987
|
+
status: 'completed',
|
|
988
|
+
duration: audioProcessingDuration,
|
|
989
|
+
timestamp: new Date().toISOString()
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
catch (error) {
|
|
993
|
+
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
994
|
+
this.emit('call-start-progress', {
|
|
995
|
+
stage: 'audio-processing-setup',
|
|
996
|
+
status: 'failed',
|
|
997
|
+
duration: audioProcessingDuration,
|
|
998
|
+
timestamp: new Date().toISOString(),
|
|
999
|
+
metadata: { error: error?.toString() }
|
|
1000
|
+
});
|
|
1001
|
+
// Don't throw here, this is non-critical
|
|
1002
|
+
}
|
|
1003
|
+
const totalDuration = Date.now() - startTime;
|
|
1004
|
+
this.emit('call-start-success', {
|
|
1005
|
+
totalDuration,
|
|
1006
|
+
callId: webCall?.id || 'unknown',
|
|
1007
|
+
timestamp: new Date().toISOString()
|
|
1008
|
+
});
|
|
1009
|
+
this.emit('call-start');
|
|
1010
|
+
}
|
|
1011
|
+
catch (e) {
|
|
1012
|
+
const totalDuration = Date.now() - startTime;
|
|
1013
|
+
this.emit('call-start-failed', {
|
|
1014
|
+
stage: 'reconnect',
|
|
1015
|
+
totalDuration,
|
|
1016
|
+
error: e?.toString() || 'Unknown error occurred',
|
|
1017
|
+
errorStack: e instanceof Error ? e.stack : 'No stack trace available',
|
|
1018
|
+
timestamp: new Date().toISOString(),
|
|
1019
|
+
context: {
|
|
1020
|
+
isReconnect: true,
|
|
1021
|
+
callId: webCall?.id || 'unknown',
|
|
1022
|
+
hasVideoRecording: !!webCall?.artifactPlan?.videoRecordingEnabled,
|
|
1023
|
+
voiceProvider: webCall?.assistant?.voice?.provider || 'unknown',
|
|
1024
|
+
isMobile: this.isMobileDevice()
|
|
1025
|
+
}
|
|
1026
|
+
});
|
|
1027
|
+
// Also emit the generic error event for backward compatibility
|
|
1028
|
+
this.emit('error', {
|
|
1029
|
+
type: 'reconnect-error',
|
|
1030
|
+
error: e,
|
|
1031
|
+
totalDuration,
|
|
1032
|
+
timestamp: new Date().toISOString(),
|
|
1033
|
+
context: {
|
|
1034
|
+
isReconnect: true,
|
|
1035
|
+
callId: webCall?.id || 'unknown',
|
|
1036
|
+
hasVideoRecording: !!webCall?.artifactPlan?.videoRecordingEnabled,
|
|
1037
|
+
voiceProvider: webCall?.assistant?.voice?.provider || 'unknown',
|
|
1038
|
+
isMobile: this.isMobileDevice()
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
await this.cleanup();
|
|
1042
|
+
throw e;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
652
1045
|
}
|
|
653
1046
|
exports.default = Vapi;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vapi-ai/web",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/vapi.js",
|
|
6
6
|
"types": "dist/vapi.d.ts",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"test:example": "npm run pack:local && cd example && npm install && npm run build",
|
|
15
15
|
"pack:local": "./scripts/build-latest.sh",
|
|
16
16
|
"clean-builds": "rm -f vapi-ai-web-*.tgz && echo '🧹 Cleaned up all build tarballs'",
|
|
17
|
-
"dev:example": "npm run pack:local && cd example && npm install && npm run dev"
|
|
17
|
+
"dev:example": "npm run pack:local && cd example && npm install && npm run dev",
|
|
18
|
+
"re-build-local-example": "./scripts/re-build-local-example.sh"
|
|
18
19
|
},
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"node": ">=18.0.0"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@daily-co/daily-js": "^0.
|
|
34
|
+
"@daily-co/daily-js": "^0.84.0",
|
|
34
35
|
"events": "^3.3.0"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|