@vapi-ai/web 2.3.6 → 2.3.8
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 +13044 -9544
- package/dist/api.d.ts +4692 -3038
- package/dist/api.js +447 -256
- package/dist/vapi.d.ts +27 -2
- package/dist/vapi.js +332 -34
- package/package.json +16 -9
- package/vapi.ts +389 -36
- package/.prettierrc +0 -5
- package/__tests__/vapi.test.ts +0 -56
- package/dist/__tests__/vapi.test.d.ts +0 -1
- package/dist/__tests__/vapi.test.js +0 -51
- package/generate-api.sh +0 -11
- package/jest.config.ts +0 -11
- package/tsconfig.json +0 -109
- package/update.sh +0 -1
package/dist/vapi.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import type { ChatCompletionMessageParam } from 'openai/resources';
|
|
3
2
|
import { DailyCall, DailyAdvancedConfig, DailyFactoryOptions, DailyParticipant, DailyVideoSendSettings } from '@daily-co/daily-js';
|
|
4
3
|
import EventEmitter from 'events';
|
|
@@ -20,7 +19,27 @@ export interface SayMessage {
|
|
|
20
19
|
interruptAssistantEnabled?: boolean;
|
|
21
20
|
}
|
|
22
21
|
type VapiClientToServerMessage = AddMessageMessage | ControlMessages | SayMessage;
|
|
23
|
-
type VapiEventNames = 'call-end' | 'call-start' | 'volume-level' | 'speech-start' | 'speech-end' | 'message' | 'video' | 'error' | 'daily-participant-updated';
|
|
22
|
+
type VapiEventNames = 'call-end' | 'call-start' | 'volume-level' | 'speech-start' | 'speech-end' | 'message' | 'video' | 'error' | 'camera-error' | 'network-quality-change' | 'network-connection' | 'daily-participant-updated' | 'call-start-progress' | 'call-start-success' | 'call-start-failed';
|
|
23
|
+
interface CallStartProgressEvent {
|
|
24
|
+
stage: string;
|
|
25
|
+
status: 'started' | 'completed' | 'failed';
|
|
26
|
+
duration?: number;
|
|
27
|
+
timestamp: string;
|
|
28
|
+
metadata?: Record<string, any>;
|
|
29
|
+
}
|
|
30
|
+
interface CallStartSuccessEvent {
|
|
31
|
+
totalDuration: number;
|
|
32
|
+
callId?: string;
|
|
33
|
+
timestamp: string;
|
|
34
|
+
}
|
|
35
|
+
interface CallStartFailedEvent {
|
|
36
|
+
stage: string;
|
|
37
|
+
totalDuration: number;
|
|
38
|
+
error: string;
|
|
39
|
+
errorStack?: string;
|
|
40
|
+
timestamp: string;
|
|
41
|
+
context: Record<string, any>;
|
|
42
|
+
}
|
|
24
43
|
type VapiEventListeners = {
|
|
25
44
|
'call-end': () => void;
|
|
26
45
|
'call-start': () => void;
|
|
@@ -30,7 +49,13 @@ type VapiEventListeners = {
|
|
|
30
49
|
video: (track: MediaStreamTrack) => void;
|
|
31
50
|
message: (message: any) => void;
|
|
32
51
|
error: (error: any) => void;
|
|
52
|
+
'camera-error': (error: any) => void;
|
|
53
|
+
'network-quality-change': (event: any) => void;
|
|
54
|
+
'network-connection': (event: any) => void;
|
|
33
55
|
'daily-participant-updated': (participant: DailyParticipant) => void;
|
|
56
|
+
'call-start-progress': (event: CallStartProgressEvent) => void;
|
|
57
|
+
'call-start-success': (event: CallStartSuccessEvent) => void;
|
|
58
|
+
'call-start-failed': (event: CallStartFailedEvent) => void;
|
|
34
59
|
};
|
|
35
60
|
declare class VapiEventEmitter extends EventEmitter {
|
|
36
61
|
on<E extends VapiEventNames>(event: E, listener: VapiEventListeners[E]): this;
|
package/dist/vapi.js
CHANGED
|
@@ -88,14 +88,46 @@ class Vapi extends VapiEventEmitter {
|
|
|
88
88
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
89
89
|
}
|
|
90
90
|
async start(assistant, assistantOverrides, squad, workflow, workflowOverrides) {
|
|
91
|
+
const startTime = Date.now();
|
|
92
|
+
// Input validation with detailed error messages
|
|
91
93
|
if (!assistant && !squad && !workflow) {
|
|
92
|
-
|
|
94
|
+
const error = new Error('Assistant or Squad or Workflow must be provided.');
|
|
95
|
+
this.emit('error', {
|
|
96
|
+
type: 'validation-error',
|
|
97
|
+
stage: 'input-validation',
|
|
98
|
+
message: error.message,
|
|
99
|
+
timestamp: new Date().toISOString()
|
|
100
|
+
});
|
|
101
|
+
throw error;
|
|
93
102
|
}
|
|
94
103
|
if (this.started) {
|
|
104
|
+
this.emit('call-start-progress', {
|
|
105
|
+
stage: 'validation',
|
|
106
|
+
status: 'failed',
|
|
107
|
+
timestamp: new Date().toISOString(),
|
|
108
|
+
metadata: { reason: 'already-started' }
|
|
109
|
+
});
|
|
95
110
|
return null;
|
|
96
111
|
}
|
|
112
|
+
this.emit('call-start-progress', {
|
|
113
|
+
stage: 'initialization',
|
|
114
|
+
status: 'started',
|
|
115
|
+
timestamp: new Date().toISOString(),
|
|
116
|
+
metadata: {
|
|
117
|
+
hasAssistant: !!assistant,
|
|
118
|
+
hasSquad: !!squad,
|
|
119
|
+
hasWorkflow: !!workflow
|
|
120
|
+
}
|
|
121
|
+
});
|
|
97
122
|
this.started = true;
|
|
98
123
|
try {
|
|
124
|
+
// Stage 1: Create web call
|
|
125
|
+
this.emit('call-start-progress', {
|
|
126
|
+
stage: 'web-call-creation',
|
|
127
|
+
status: 'started',
|
|
128
|
+
timestamp: new Date().toISOString()
|
|
129
|
+
});
|
|
130
|
+
const webCallStartTime = Date.now();
|
|
99
131
|
const webCall = (await client_1.client.call.callControllerCreateWebCall({
|
|
100
132
|
assistant: typeof assistant === 'string' ? undefined : assistant,
|
|
101
133
|
assistantId: typeof assistant === 'string' ? assistant : undefined,
|
|
@@ -106,16 +138,73 @@ class Vapi extends VapiEventEmitter {
|
|
|
106
138
|
workflowId: typeof workflow === 'string' ? workflow : undefined,
|
|
107
139
|
workflowOverrides,
|
|
108
140
|
})).data;
|
|
141
|
+
const webCallDuration = Date.now() - webCallStartTime;
|
|
142
|
+
this.emit('call-start-progress', {
|
|
143
|
+
stage: 'web-call-creation',
|
|
144
|
+
status: 'completed',
|
|
145
|
+
duration: webCallDuration,
|
|
146
|
+
timestamp: new Date().toISOString(),
|
|
147
|
+
metadata: {
|
|
148
|
+
callId: webCall?.id || 'unknown',
|
|
149
|
+
videoRecordingEnabled: webCall?.artifactPlan?.videoRecordingEnabled ?? false,
|
|
150
|
+
voiceProvider: webCall?.assistant?.voice?.provider || 'unknown'
|
|
151
|
+
}
|
|
152
|
+
});
|
|
109
153
|
if (this.call) {
|
|
154
|
+
this.emit('call-start-progress', {
|
|
155
|
+
stage: 'daily-call-object-creation',
|
|
156
|
+
status: 'started',
|
|
157
|
+
timestamp: new Date().toISOString(),
|
|
158
|
+
metadata: { action: 'cleanup-existing' }
|
|
159
|
+
});
|
|
110
160
|
this.cleanup();
|
|
111
161
|
}
|
|
112
162
|
const isVideoRecordingEnabled = webCall?.artifactPlan?.videoRecordingEnabled ?? false;
|
|
113
163
|
const isVideoEnabled = webCall?.assistant?.voice?.provider === 'tavus';
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
164
|
+
// Stage 2: Create Daily call object
|
|
165
|
+
this.emit('call-start-progress', {
|
|
166
|
+
stage: 'daily-call-object-creation',
|
|
167
|
+
status: 'started',
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
metadata: {
|
|
170
|
+
audioSource: this.dailyCallObject.audioSource ?? true,
|
|
171
|
+
videoSource: this.dailyCallObject.videoSource ?? isVideoRecordingEnabled,
|
|
172
|
+
isVideoRecordingEnabled,
|
|
173
|
+
isVideoEnabled
|
|
174
|
+
}
|
|
118
175
|
});
|
|
176
|
+
const dailyCallStartTime = Date.now();
|
|
177
|
+
try {
|
|
178
|
+
this.call = daily_js_1.default.createCallObject({
|
|
179
|
+
audioSource: this.dailyCallObject.audioSource ?? true,
|
|
180
|
+
videoSource: this.dailyCallObject.videoSource ?? isVideoRecordingEnabled,
|
|
181
|
+
dailyConfig: this.dailyCallConfig,
|
|
182
|
+
});
|
|
183
|
+
const dailyCallDuration = Date.now() - dailyCallStartTime;
|
|
184
|
+
this.emit('call-start-progress', {
|
|
185
|
+
stage: 'daily-call-object-creation',
|
|
186
|
+
status: 'completed',
|
|
187
|
+
duration: dailyCallDuration,
|
|
188
|
+
timestamp: new Date().toISOString()
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
const dailyCallDuration = Date.now() - dailyCallStartTime;
|
|
193
|
+
this.emit('call-start-progress', {
|
|
194
|
+
stage: 'daily-call-object-creation',
|
|
195
|
+
status: 'failed',
|
|
196
|
+
duration: dailyCallDuration,
|
|
197
|
+
timestamp: new Date().toISOString(),
|
|
198
|
+
metadata: { error: error?.toString() }
|
|
199
|
+
});
|
|
200
|
+
this.emit('error', {
|
|
201
|
+
type: 'daily-call-object-creation-error',
|
|
202
|
+
stage: 'daily-call-object-creation',
|
|
203
|
+
error,
|
|
204
|
+
timestamp: new Date().toISOString()
|
|
205
|
+
});
|
|
206
|
+
throw error;
|
|
207
|
+
}
|
|
119
208
|
this.call.iframe()?.style.setProperty('display', 'none');
|
|
120
209
|
this.call.on('left-meeting', () => {
|
|
121
210
|
this.emit('call-end');
|
|
@@ -139,7 +228,13 @@ class Vapi extends VapiEventEmitter {
|
|
|
139
228
|
}
|
|
140
229
|
});
|
|
141
230
|
this.call.on('camera-error', (error) => {
|
|
142
|
-
this.emit('error', error);
|
|
231
|
+
this.emit('camera-error', error);
|
|
232
|
+
});
|
|
233
|
+
this.call.on('network-quality-change', (event) => {
|
|
234
|
+
this.emit('network-quality-change', event);
|
|
235
|
+
});
|
|
236
|
+
this.call.on('network-connection', (event) => {
|
|
237
|
+
this.emit('network-connection', event);
|
|
143
238
|
});
|
|
144
239
|
this.call.on('track-started', async (e) => {
|
|
145
240
|
if (!e || !e.participant) {
|
|
@@ -176,35 +271,173 @@ class Vapi extends VapiEventEmitter {
|
|
|
176
271
|
}
|
|
177
272
|
destroyAudioPlayer(e.participant.session_id);
|
|
178
273
|
});
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
274
|
+
// Stage 3: Mobile device handling and permissions
|
|
275
|
+
const isMobile = this.isMobileDevice();
|
|
276
|
+
this.emit('call-start-progress', {
|
|
277
|
+
stage: 'mobile-permissions',
|
|
278
|
+
status: 'started',
|
|
279
|
+
timestamp: new Date().toISOString(),
|
|
280
|
+
metadata: { isMobile }
|
|
281
|
+
});
|
|
282
|
+
if (isMobile) {
|
|
283
|
+
const mobileWaitStartTime = Date.now();
|
|
182
284
|
await this.sleep(1000);
|
|
285
|
+
const mobileWaitDuration = Date.now() - mobileWaitStartTime;
|
|
286
|
+
this.emit('call-start-progress', {
|
|
287
|
+
stage: 'mobile-permissions',
|
|
288
|
+
status: 'completed',
|
|
289
|
+
duration: mobileWaitDuration,
|
|
290
|
+
timestamp: new Date().toISOString(),
|
|
291
|
+
metadata: { action: 'permissions-wait' }
|
|
292
|
+
});
|
|
183
293
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
294
|
+
else {
|
|
295
|
+
this.emit('call-start-progress', {
|
|
296
|
+
stage: 'mobile-permissions',
|
|
297
|
+
status: 'completed',
|
|
298
|
+
timestamp: new Date().toISOString(),
|
|
299
|
+
metadata: { action: 'skipped-not-mobile' }
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
// Stage 4: Join the call
|
|
303
|
+
this.emit('call-start-progress', {
|
|
304
|
+
stage: 'daily-call-join',
|
|
305
|
+
status: 'started',
|
|
306
|
+
timestamp: new Date().toISOString()
|
|
188
307
|
});
|
|
308
|
+
const joinStartTime = Date.now();
|
|
309
|
+
try {
|
|
310
|
+
await this.call.join({
|
|
311
|
+
// @ts-expect-error This exists
|
|
312
|
+
url: webCall.webCallUrl,
|
|
313
|
+
subscribeToTracksAutomatically: false,
|
|
314
|
+
});
|
|
315
|
+
const joinDuration = Date.now() - joinStartTime;
|
|
316
|
+
this.emit('call-start-progress', {
|
|
317
|
+
stage: 'daily-call-join',
|
|
318
|
+
status: 'completed',
|
|
319
|
+
duration: joinDuration,
|
|
320
|
+
timestamp: new Date().toISOString()
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
const joinDuration = Date.now() - joinStartTime;
|
|
325
|
+
this.emit('call-start-progress', {
|
|
326
|
+
stage: 'daily-call-join',
|
|
327
|
+
status: 'failed',
|
|
328
|
+
duration: joinDuration,
|
|
329
|
+
timestamp: new Date().toISOString(),
|
|
330
|
+
metadata: { error: error?.toString() }
|
|
331
|
+
});
|
|
332
|
+
this.emit('error', {
|
|
333
|
+
type: 'daily-call-join-error',
|
|
334
|
+
stage: 'daily-call-join',
|
|
335
|
+
error,
|
|
336
|
+
duration: joinDuration,
|
|
337
|
+
timestamp: new Date().toISOString()
|
|
338
|
+
});
|
|
339
|
+
throw error;
|
|
340
|
+
}
|
|
341
|
+
// Stage 5: Video recording setup (if enabled)
|
|
189
342
|
if (isVideoRecordingEnabled) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
backgroundColor: '#FF1F2D3D',
|
|
195
|
-
layout: {
|
|
196
|
-
preset: 'default',
|
|
197
|
-
},
|
|
343
|
+
this.emit('call-start-progress', {
|
|
344
|
+
stage: 'video-recording-setup',
|
|
345
|
+
status: 'started',
|
|
346
|
+
timestamp: new Date().toISOString()
|
|
198
347
|
});
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
348
|
+
const recordingRequestedTime = new Date().getTime();
|
|
349
|
+
const recordingStartTime = Date.now();
|
|
350
|
+
try {
|
|
351
|
+
this.call.startRecording({
|
|
352
|
+
width: 1280,
|
|
353
|
+
height: 720,
|
|
354
|
+
backgroundColor: '#FF1F2D3D',
|
|
355
|
+
layout: {
|
|
356
|
+
preset: 'default',
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
360
|
+
this.emit('call-start-progress', {
|
|
361
|
+
stage: 'video-recording-setup',
|
|
362
|
+
status: 'completed',
|
|
363
|
+
duration: recordingSetupDuration,
|
|
364
|
+
timestamp: new Date().toISOString()
|
|
365
|
+
});
|
|
366
|
+
this.call.on('recording-started', () => {
|
|
367
|
+
const totalRecordingDelay = (new Date().getTime() - recordingRequestedTime) / 1000;
|
|
368
|
+
this.emit('call-start-progress', {
|
|
369
|
+
stage: 'video-recording-started',
|
|
370
|
+
status: 'completed',
|
|
371
|
+
timestamp: new Date().toISOString(),
|
|
372
|
+
metadata: { delaySeconds: totalRecordingDelay }
|
|
373
|
+
});
|
|
374
|
+
this.send({
|
|
375
|
+
type: 'control',
|
|
376
|
+
control: 'say-first-message',
|
|
377
|
+
videoRecordingStartDelaySeconds: totalRecordingDelay,
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
383
|
+
this.emit('call-start-progress', {
|
|
384
|
+
stage: 'video-recording-setup',
|
|
385
|
+
status: 'failed',
|
|
386
|
+
duration: recordingSetupDuration,
|
|
387
|
+
timestamp: new Date().toISOString(),
|
|
388
|
+
metadata: { error: error?.toString() }
|
|
389
|
+
});
|
|
390
|
+
this.emit('error', {
|
|
391
|
+
type: 'video-recording-setup-error',
|
|
392
|
+
stage: 'video-recording-setup',
|
|
393
|
+
error,
|
|
394
|
+
timestamp: new Date().toISOString()
|
|
204
395
|
});
|
|
396
|
+
// Don't throw here, video recording is optional
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
this.emit('call-start-progress', {
|
|
401
|
+
stage: 'video-recording-setup',
|
|
402
|
+
status: 'completed',
|
|
403
|
+
timestamp: new Date().toISOString(),
|
|
404
|
+
metadata: { action: 'skipped-not-enabled' }
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
// Stage 6: Audio level observer setup
|
|
408
|
+
this.emit('call-start-progress', {
|
|
409
|
+
stage: 'audio-observer-setup',
|
|
410
|
+
status: 'started',
|
|
411
|
+
timestamp: new Date().toISOString()
|
|
412
|
+
});
|
|
413
|
+
const audioObserverStartTime = Date.now();
|
|
414
|
+
try {
|
|
415
|
+
this.call.startRemoteParticipantsAudioLevelObserver(100);
|
|
416
|
+
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
417
|
+
this.emit('call-start-progress', {
|
|
418
|
+
stage: 'audio-observer-setup',
|
|
419
|
+
status: 'completed',
|
|
420
|
+
duration: audioObserverDuration,
|
|
421
|
+
timestamp: new Date().toISOString()
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
426
|
+
this.emit('call-start-progress', {
|
|
427
|
+
stage: 'audio-observer-setup',
|
|
428
|
+
status: 'failed',
|
|
429
|
+
duration: audioObserverDuration,
|
|
430
|
+
timestamp: new Date().toISOString(),
|
|
431
|
+
metadata: { error: error?.toString() }
|
|
432
|
+
});
|
|
433
|
+
this.emit('error', {
|
|
434
|
+
type: 'audio-observer-setup-error',
|
|
435
|
+
stage: 'audio-observer-setup',
|
|
436
|
+
error,
|
|
437
|
+
timestamp: new Date().toISOString()
|
|
205
438
|
});
|
|
439
|
+
// Don't throw here, this is non-critical
|
|
206
440
|
}
|
|
207
|
-
this.call.startRemoteParticipantsAudioLevelObserver(100);
|
|
208
441
|
this.call.on('remote-participants-audio-level', (e) => {
|
|
209
442
|
if (e)
|
|
210
443
|
this.handleRemoteParticipantsAudioLevel(e);
|
|
@@ -226,18 +459,83 @@ class Vapi extends VapiEventEmitter {
|
|
|
226
459
|
});
|
|
227
460
|
}
|
|
228
461
|
});
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
462
|
+
// Stage 7: Audio processing setup
|
|
463
|
+
this.emit('call-start-progress', {
|
|
464
|
+
stage: 'audio-processing-setup',
|
|
465
|
+
status: 'started',
|
|
466
|
+
timestamp: new Date().toISOString()
|
|
467
|
+
});
|
|
468
|
+
const audioProcessingStartTime = Date.now();
|
|
469
|
+
try {
|
|
470
|
+
this.call.updateInputSettings({
|
|
471
|
+
audio: {
|
|
472
|
+
processor: {
|
|
473
|
+
type: 'noise-cancellation',
|
|
474
|
+
},
|
|
233
475
|
},
|
|
234
|
-
}
|
|
476
|
+
});
|
|
477
|
+
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
478
|
+
this.emit('call-start-progress', {
|
|
479
|
+
stage: 'audio-processing-setup',
|
|
480
|
+
status: 'completed',
|
|
481
|
+
duration: audioProcessingDuration,
|
|
482
|
+
timestamp: new Date().toISOString()
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
487
|
+
this.emit('call-start-progress', {
|
|
488
|
+
stage: 'audio-processing-setup',
|
|
489
|
+
status: 'failed',
|
|
490
|
+
duration: audioProcessingDuration,
|
|
491
|
+
timestamp: new Date().toISOString(),
|
|
492
|
+
metadata: { error: error?.toString() }
|
|
493
|
+
});
|
|
494
|
+
this.emit('error', {
|
|
495
|
+
type: 'audio-processing-setup-error',
|
|
496
|
+
stage: 'audio-processing-setup',
|
|
497
|
+
error,
|
|
498
|
+
timestamp: new Date().toISOString()
|
|
499
|
+
});
|
|
500
|
+
// Don't throw here, this is non-critical
|
|
501
|
+
}
|
|
502
|
+
const totalDuration = Date.now() - startTime;
|
|
503
|
+
this.emit('call-start-success', {
|
|
504
|
+
totalDuration,
|
|
505
|
+
callId: webCall?.id || 'unknown',
|
|
506
|
+
timestamp: new Date().toISOString()
|
|
235
507
|
});
|
|
236
508
|
return webCall;
|
|
237
509
|
}
|
|
238
510
|
catch (e) {
|
|
239
|
-
|
|
240
|
-
this.emit('
|
|
511
|
+
const totalDuration = Date.now() - startTime;
|
|
512
|
+
this.emit('call-start-failed', {
|
|
513
|
+
stage: 'unknown',
|
|
514
|
+
totalDuration,
|
|
515
|
+
error: e?.toString() || 'Unknown error occurred',
|
|
516
|
+
errorStack: e instanceof Error ? e.stack : 'No stack trace available',
|
|
517
|
+
timestamp: new Date().toISOString(),
|
|
518
|
+
context: {
|
|
519
|
+
hasAssistant: !!assistant,
|
|
520
|
+
hasSquad: !!squad,
|
|
521
|
+
hasWorkflow: !!workflow,
|
|
522
|
+
isMobile: this.isMobileDevice()
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
// Also emit the generic error event for backward compatibility
|
|
526
|
+
this.emit('error', {
|
|
527
|
+
type: 'start-method-error',
|
|
528
|
+
stage: 'unknown',
|
|
529
|
+
error: e,
|
|
530
|
+
totalDuration,
|
|
531
|
+
timestamp: new Date().toISOString(),
|
|
532
|
+
context: {
|
|
533
|
+
hasAssistant: !!assistant,
|
|
534
|
+
hasSquad: !!squad,
|
|
535
|
+
hasWorkflow: !!workflow,
|
|
536
|
+
isMobile: this.isMobileDevice()
|
|
537
|
+
}
|
|
538
|
+
});
|
|
241
539
|
this.cleanup();
|
|
242
540
|
return null;
|
|
243
541
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vapi-ai/web",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/vapi.js",
|
|
6
6
|
"types": "dist/vapi.d.ts",
|
|
@@ -10,7 +10,11 @@
|
|
|
10
10
|
"start": "npm run generate-api && npm run build && node dist/vapi.js",
|
|
11
11
|
"generate-api": "./generate-api.sh",
|
|
12
12
|
"update": "./update.sh",
|
|
13
|
-
"generate-local-build": "npm install && npm run build && npm pack"
|
|
13
|
+
"generate-local-build": "npm install && npm run build && npm pack",
|
|
14
|
+
"test:example": "npm run pack:local && cd example && npm install && npm run build",
|
|
15
|
+
"pack:local": "./scripts/build-latest.sh",
|
|
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"
|
|
14
18
|
},
|
|
15
19
|
"repository": {
|
|
16
20
|
"type": "git",
|
|
@@ -22,17 +26,20 @@
|
|
|
22
26
|
"url": "https://github.com/VapiAI/web/issues"
|
|
23
27
|
},
|
|
24
28
|
"homepage": "https://github.com/VapiAI/web#readme",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
25
32
|
"dependencies": {
|
|
26
|
-
"@daily-co/daily-js": "^0.
|
|
33
|
+
"@daily-co/daily-js": "^0.80.0",
|
|
27
34
|
"events": "^3.3.0"
|
|
28
35
|
},
|
|
29
36
|
"devDependencies": {
|
|
30
|
-
"@types/jest": "^
|
|
31
|
-
"@types/node": "^
|
|
32
|
-
"jest": "^
|
|
33
|
-
"openai": "^
|
|
34
|
-
"swagger-typescript-api": "^13.
|
|
35
|
-
"ts-jest": "^29.
|
|
37
|
+
"@types/jest": "^30.0.0",
|
|
38
|
+
"@types/node": "^24.0.4",
|
|
39
|
+
"jest": "^30.0.3",
|
|
40
|
+
"openai": "^5.7.0",
|
|
41
|
+
"swagger-typescript-api": "^13.2.7",
|
|
42
|
+
"ts-jest": "^29.4.0",
|
|
36
43
|
"ts-node": "^10.9.2"
|
|
37
44
|
}
|
|
38
45
|
}
|