@vapi-ai/web 2.5.1 → 2.5.2
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 +380 -414
- package/dist/api.d.ts +2004 -2034
- package/dist/api.js +17 -28
- package/dist/vapi.js +101 -24
- package/package.json +1 -1
- package/vapi.ts +117 -24
package/dist/api.js
CHANGED
|
@@ -72,15 +72,20 @@ class HttpClient {
|
|
|
72
72
|
[ContentType.Text]: (input) => input !== null && typeof input !== "string"
|
|
73
73
|
? JSON.stringify(input)
|
|
74
74
|
: input,
|
|
75
|
-
[ContentType.FormData]: (input) =>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
[ContentType.FormData]: (input) => {
|
|
76
|
+
if (input instanceof FormData) {
|
|
77
|
+
return input;
|
|
78
|
+
}
|
|
79
|
+
return Object.keys(input || {}).reduce((formData, key) => {
|
|
80
|
+
const property = input[key];
|
|
81
|
+
formData.append(key, property instanceof Blob
|
|
82
|
+
? property
|
|
83
|
+
: typeof property === "object" && property !== null
|
|
84
|
+
? JSON.stringify(property)
|
|
85
|
+
: `${property}`);
|
|
86
|
+
return formData;
|
|
87
|
+
}, new FormData());
|
|
88
|
+
},
|
|
84
89
|
[ContentType.UrlEncoded]: (input) => this.toQueryString(input),
|
|
85
90
|
};
|
|
86
91
|
mergeRequestParams(params1, params2) {
|
|
@@ -138,12 +143,13 @@ class HttpClient {
|
|
|
138
143
|
? null
|
|
139
144
|
: payloadFormatter(body),
|
|
140
145
|
}).then(async (response) => {
|
|
141
|
-
const r = response
|
|
146
|
+
const r = response;
|
|
142
147
|
r.data = null;
|
|
143
148
|
r.error = null;
|
|
149
|
+
const responseToParse = responseFormat ? response.clone() : response;
|
|
144
150
|
const data = !responseFormat
|
|
145
151
|
? r
|
|
146
|
-
: await
|
|
152
|
+
: await responseToParse[responseFormat]()
|
|
147
153
|
.then((data) => {
|
|
148
154
|
if (r.ok) {
|
|
149
155
|
r.data = data;
|
|
@@ -1489,23 +1495,6 @@ class Api extends HttpClient {
|
|
|
1489
1495
|
format: "json",
|
|
1490
1496
|
...params,
|
|
1491
1497
|
}),
|
|
1492
|
-
/**
|
|
1493
|
-
* @description Analyzes assistant configuration and generates contextual structured output recommendations
|
|
1494
|
-
*
|
|
1495
|
-
* @tags Structured Outputs
|
|
1496
|
-
* @name StructuredOutputControllerSuggest
|
|
1497
|
-
* @summary Generate AI-Powered Structured Output Suggestions
|
|
1498
|
-
* @request POST:/structured-output/suggest
|
|
1499
|
-
* @secure
|
|
1500
|
-
*/
|
|
1501
|
-
structuredOutputControllerSuggest: (data, params = {}) => this.request({
|
|
1502
|
-
path: `/structured-output/suggest`,
|
|
1503
|
-
method: "POST",
|
|
1504
|
-
body: data,
|
|
1505
|
-
secure: true,
|
|
1506
|
-
type: ContentType.Json,
|
|
1507
|
-
...params,
|
|
1508
|
-
}),
|
|
1509
1498
|
};
|
|
1510
1499
|
testSuite = {
|
|
1511
1500
|
/**
|
package/dist/vapi.js
CHANGED
|
@@ -7,6 +7,57 @@ const daily_js_1 = __importDefault(require("@daily-co/daily-js"));
|
|
|
7
7
|
const events_1 = __importDefault(require("events"));
|
|
8
8
|
const client_1 = require("./client");
|
|
9
9
|
const daily_guards_1 = require("./daily-guards");
|
|
10
|
+
/**
|
|
11
|
+
* Extracts error details into a plain object that serializes properly to JSON.
|
|
12
|
+
* Error objects don't serialize well because their properties (message, stack, name)
|
|
13
|
+
* are not enumerable and get lost when using JSON.stringify().
|
|
14
|
+
*/
|
|
15
|
+
function serializeError(error) {
|
|
16
|
+
if (error === null || error === undefined) {
|
|
17
|
+
return { message: 'Unknown error (null or undefined)' };
|
|
18
|
+
}
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
const serialized = {
|
|
21
|
+
message: error.message,
|
|
22
|
+
name: error.name,
|
|
23
|
+
stack: error.stack,
|
|
24
|
+
};
|
|
25
|
+
// Include any additional properties that might be on the error
|
|
26
|
+
const errorAsAny = error;
|
|
27
|
+
if (errorAsAny.code !== undefined) {
|
|
28
|
+
serialized.code = errorAsAny.code;
|
|
29
|
+
}
|
|
30
|
+
if (errorAsAny.cause !== undefined) {
|
|
31
|
+
serialized.cause = String(errorAsAny.cause);
|
|
32
|
+
}
|
|
33
|
+
if (errorAsAny.reason !== undefined) {
|
|
34
|
+
serialized.reason = errorAsAny.reason;
|
|
35
|
+
}
|
|
36
|
+
if (errorAsAny.details !== undefined) {
|
|
37
|
+
serialized.details = errorAsAny.details;
|
|
38
|
+
}
|
|
39
|
+
// Daily.co specific error properties
|
|
40
|
+
if (errorAsAny.errorMsg !== undefined) {
|
|
41
|
+
serialized.errorMsg = errorAsAny.errorMsg;
|
|
42
|
+
}
|
|
43
|
+
if (errorAsAny.error !== undefined && typeof errorAsAny.error === 'string') {
|
|
44
|
+
serialized.errorDetail = errorAsAny.error;
|
|
45
|
+
}
|
|
46
|
+
return serialized;
|
|
47
|
+
}
|
|
48
|
+
if (typeof error === 'string') {
|
|
49
|
+
return { message: error };
|
|
50
|
+
}
|
|
51
|
+
if (typeof error === 'object') {
|
|
52
|
+
// It's already a plain object, but let's ensure message exists
|
|
53
|
+
const errorObj = error;
|
|
54
|
+
return {
|
|
55
|
+
message: errorObj.message || errorObj.error || JSON.stringify(error),
|
|
56
|
+
...errorObj
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return { message: String(error) };
|
|
60
|
+
}
|
|
10
61
|
async function startAudioPlayer(player, track) {
|
|
11
62
|
player.muted = false;
|
|
12
63
|
player.autoplay = true;
|
|
@@ -98,7 +149,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
98
149
|
this.emit('error', {
|
|
99
150
|
type: 'validation-error',
|
|
100
151
|
stage: 'input-validation',
|
|
101
|
-
|
|
152
|
+
error: serializeError(error),
|
|
102
153
|
timestamp: new Date().toISOString()
|
|
103
154
|
});
|
|
104
155
|
throw error;
|
|
@@ -194,17 +245,18 @@ class Vapi extends VapiEventEmitter {
|
|
|
194
245
|
}
|
|
195
246
|
catch (error) {
|
|
196
247
|
const dailyCallDuration = Date.now() - dailyCallStartTime;
|
|
248
|
+
const serializedError = serializeError(error);
|
|
197
249
|
this.emit('call-start-progress', {
|
|
198
250
|
stage: 'daily-call-object-creation',
|
|
199
251
|
status: 'failed',
|
|
200
252
|
duration: dailyCallDuration,
|
|
201
253
|
timestamp: new Date().toISOString(),
|
|
202
|
-
metadata: { error:
|
|
254
|
+
metadata: { error: serializedError.message }
|
|
203
255
|
});
|
|
204
256
|
this.emit('error', {
|
|
205
257
|
type: 'daily-call-object-creation-error',
|
|
206
258
|
stage: 'daily-call-object-creation',
|
|
207
|
-
error,
|
|
259
|
+
error: serializedError,
|
|
208
260
|
timestamp: new Date().toISOString()
|
|
209
261
|
});
|
|
210
262
|
throw error;
|
|
@@ -226,13 +278,21 @@ class Vapi extends VapiEventEmitter {
|
|
|
226
278
|
this.cleanup().catch(console.error);
|
|
227
279
|
});
|
|
228
280
|
this.call.on('error', (error) => {
|
|
229
|
-
this.emit('error',
|
|
281
|
+
this.emit('error', {
|
|
282
|
+
type: 'daily-error',
|
|
283
|
+
error: serializeError(error),
|
|
284
|
+
timestamp: new Date().toISOString()
|
|
285
|
+
});
|
|
230
286
|
if (isVideoRecordingEnabled) {
|
|
231
287
|
this.call?.stopRecording();
|
|
232
288
|
}
|
|
233
289
|
});
|
|
234
290
|
this.call.on('camera-error', (error) => {
|
|
235
|
-
this.emit('camera-error',
|
|
291
|
+
this.emit('camera-error', {
|
|
292
|
+
type: 'camera-error',
|
|
293
|
+
error: serializeError(error),
|
|
294
|
+
timestamp: new Date().toISOString()
|
|
295
|
+
});
|
|
236
296
|
});
|
|
237
297
|
this.call.on('network-quality-change', (event) => {
|
|
238
298
|
this.emit('network-quality-change', event);
|
|
@@ -326,17 +386,18 @@ class Vapi extends VapiEventEmitter {
|
|
|
326
386
|
}
|
|
327
387
|
catch (error) {
|
|
328
388
|
const joinDuration = Date.now() - joinStartTime;
|
|
389
|
+
const serializedError = serializeError(error);
|
|
329
390
|
this.emit('call-start-progress', {
|
|
330
391
|
stage: 'daily-call-join',
|
|
331
392
|
status: 'failed',
|
|
332
393
|
duration: joinDuration,
|
|
333
394
|
timestamp: new Date().toISOString(),
|
|
334
|
-
metadata: { error:
|
|
395
|
+
metadata: { error: serializedError.message }
|
|
335
396
|
});
|
|
336
397
|
this.emit('error', {
|
|
337
398
|
type: 'daily-call-join-error',
|
|
338
399
|
stage: 'daily-call-join',
|
|
339
|
-
error,
|
|
400
|
+
error: serializedError,
|
|
340
401
|
duration: joinDuration,
|
|
341
402
|
timestamp: new Date().toISOString()
|
|
342
403
|
});
|
|
@@ -384,17 +445,18 @@ class Vapi extends VapiEventEmitter {
|
|
|
384
445
|
}
|
|
385
446
|
catch (error) {
|
|
386
447
|
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
448
|
+
const serializedError = serializeError(error);
|
|
387
449
|
this.emit('call-start-progress', {
|
|
388
450
|
stage: 'video-recording-setup',
|
|
389
451
|
status: 'failed',
|
|
390
452
|
duration: recordingSetupDuration,
|
|
391
453
|
timestamp: new Date().toISOString(),
|
|
392
|
-
metadata: { error:
|
|
454
|
+
metadata: { error: serializedError.message }
|
|
393
455
|
});
|
|
394
456
|
this.emit('error', {
|
|
395
457
|
type: 'video-recording-setup-error',
|
|
396
458
|
stage: 'video-recording-setup',
|
|
397
|
-
error,
|
|
459
|
+
error: serializedError,
|
|
398
460
|
timestamp: new Date().toISOString()
|
|
399
461
|
});
|
|
400
462
|
// Don't throw here, video recording is optional
|
|
@@ -427,17 +489,18 @@ class Vapi extends VapiEventEmitter {
|
|
|
427
489
|
}
|
|
428
490
|
catch (error) {
|
|
429
491
|
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
492
|
+
const serializedError = serializeError(error);
|
|
430
493
|
this.emit('call-start-progress', {
|
|
431
494
|
stage: 'audio-observer-setup',
|
|
432
495
|
status: 'failed',
|
|
433
496
|
duration: audioObserverDuration,
|
|
434
497
|
timestamp: new Date().toISOString(),
|
|
435
|
-
metadata: { error:
|
|
498
|
+
metadata: { error: serializedError.message }
|
|
436
499
|
});
|
|
437
500
|
this.emit('error', {
|
|
438
501
|
type: 'audio-observer-setup-error',
|
|
439
502
|
stage: 'audio-observer-setup',
|
|
440
|
-
error,
|
|
503
|
+
error: serializedError,
|
|
441
504
|
timestamp: new Date().toISOString()
|
|
442
505
|
});
|
|
443
506
|
// Don't throw here, this is non-critical
|
|
@@ -488,17 +551,18 @@ class Vapi extends VapiEventEmitter {
|
|
|
488
551
|
}
|
|
489
552
|
catch (error) {
|
|
490
553
|
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
554
|
+
const serializedError = serializeError(error);
|
|
491
555
|
this.emit('call-start-progress', {
|
|
492
556
|
stage: 'audio-processing-setup',
|
|
493
557
|
status: 'failed',
|
|
494
558
|
duration: audioProcessingDuration,
|
|
495
559
|
timestamp: new Date().toISOString(),
|
|
496
|
-
metadata: { error:
|
|
560
|
+
metadata: { error: serializedError.message }
|
|
497
561
|
});
|
|
498
562
|
this.emit('error', {
|
|
499
563
|
type: 'audio-processing-setup-error',
|
|
500
564
|
stage: 'audio-processing-setup',
|
|
501
|
-
error,
|
|
565
|
+
error: serializedError,
|
|
502
566
|
timestamp: new Date().toISOString()
|
|
503
567
|
});
|
|
504
568
|
// Don't throw here, this is non-critical
|
|
@@ -513,11 +577,12 @@ class Vapi extends VapiEventEmitter {
|
|
|
513
577
|
}
|
|
514
578
|
catch (e) {
|
|
515
579
|
const totalDuration = Date.now() - startTime;
|
|
580
|
+
const serializedError = serializeError(e);
|
|
516
581
|
this.emit('call-start-failed', {
|
|
517
582
|
stage: 'unknown',
|
|
518
583
|
totalDuration,
|
|
519
|
-
error:
|
|
520
|
-
errorStack:
|
|
584
|
+
error: serializedError.message,
|
|
585
|
+
errorStack: serializedError.stack || 'No stack trace available',
|
|
521
586
|
timestamp: new Date().toISOString(),
|
|
522
587
|
context: {
|
|
523
588
|
hasAssistant: !!assistant,
|
|
@@ -530,7 +595,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
530
595
|
this.emit('error', {
|
|
531
596
|
type: 'start-method-error',
|
|
532
597
|
stage: 'unknown',
|
|
533
|
-
error:
|
|
598
|
+
error: serializedError,
|
|
534
599
|
totalDuration,
|
|
535
600
|
timestamp: new Date().toISOString(),
|
|
536
601
|
context: {
|
|
@@ -762,13 +827,21 @@ class Vapi extends VapiEventEmitter {
|
|
|
762
827
|
this.cleanup().catch(console.error);
|
|
763
828
|
});
|
|
764
829
|
this.call.on('error', (error) => {
|
|
765
|
-
this.emit('error',
|
|
830
|
+
this.emit('error', {
|
|
831
|
+
type: 'daily-error',
|
|
832
|
+
error: serializeError(error),
|
|
833
|
+
timestamp: new Date().toISOString()
|
|
834
|
+
});
|
|
766
835
|
if (isVideoRecordingEnabled) {
|
|
767
836
|
this.call?.stopRecording();
|
|
768
837
|
}
|
|
769
838
|
});
|
|
770
839
|
this.call.on('camera-error', (error) => {
|
|
771
|
-
this.emit('camera-error',
|
|
840
|
+
this.emit('camera-error', {
|
|
841
|
+
type: 'camera-error',
|
|
842
|
+
error: serializeError(error),
|
|
843
|
+
timestamp: new Date().toISOString()
|
|
844
|
+
});
|
|
772
845
|
});
|
|
773
846
|
this.call.on('network-quality-change', (event) => {
|
|
774
847
|
this.emit('network-quality-change', event);
|
|
@@ -920,12 +993,13 @@ class Vapi extends VapiEventEmitter {
|
|
|
920
993
|
}
|
|
921
994
|
catch (error) {
|
|
922
995
|
const recordingSetupDuration = Date.now() - recordingStartTime;
|
|
996
|
+
const serializedError = serializeError(error);
|
|
923
997
|
this.emit('call-start-progress', {
|
|
924
998
|
stage: 'video-recording-setup',
|
|
925
999
|
status: 'failed',
|
|
926
1000
|
duration: recordingSetupDuration,
|
|
927
1001
|
timestamp: new Date().toISOString(),
|
|
928
|
-
metadata: { error:
|
|
1002
|
+
metadata: { error: serializedError.message }
|
|
929
1003
|
});
|
|
930
1004
|
// Don't throw here, video recording is optional
|
|
931
1005
|
}
|
|
@@ -957,12 +1031,13 @@ class Vapi extends VapiEventEmitter {
|
|
|
957
1031
|
}
|
|
958
1032
|
catch (error) {
|
|
959
1033
|
const audioObserverDuration = Date.now() - audioObserverStartTime;
|
|
1034
|
+
const serializedError = serializeError(error);
|
|
960
1035
|
this.emit('call-start-progress', {
|
|
961
1036
|
stage: 'audio-observer-setup',
|
|
962
1037
|
status: 'failed',
|
|
963
1038
|
duration: audioObserverDuration,
|
|
964
1039
|
timestamp: new Date().toISOString(),
|
|
965
|
-
metadata: { error:
|
|
1040
|
+
metadata: { error: serializedError.message }
|
|
966
1041
|
});
|
|
967
1042
|
// Don't throw here, this is non-critical
|
|
968
1043
|
}
|
|
@@ -991,12 +1066,13 @@ class Vapi extends VapiEventEmitter {
|
|
|
991
1066
|
}
|
|
992
1067
|
catch (error) {
|
|
993
1068
|
const audioProcessingDuration = Date.now() - audioProcessingStartTime;
|
|
1069
|
+
const serializedError = serializeError(error);
|
|
994
1070
|
this.emit('call-start-progress', {
|
|
995
1071
|
stage: 'audio-processing-setup',
|
|
996
1072
|
status: 'failed',
|
|
997
1073
|
duration: audioProcessingDuration,
|
|
998
1074
|
timestamp: new Date().toISOString(),
|
|
999
|
-
metadata: { error:
|
|
1075
|
+
metadata: { error: serializedError.message }
|
|
1000
1076
|
});
|
|
1001
1077
|
// Don't throw here, this is non-critical
|
|
1002
1078
|
}
|
|
@@ -1010,11 +1086,12 @@ class Vapi extends VapiEventEmitter {
|
|
|
1010
1086
|
}
|
|
1011
1087
|
catch (e) {
|
|
1012
1088
|
const totalDuration = Date.now() - startTime;
|
|
1089
|
+
const serializedError = serializeError(e);
|
|
1013
1090
|
this.emit('call-start-failed', {
|
|
1014
1091
|
stage: 'reconnect',
|
|
1015
1092
|
totalDuration,
|
|
1016
|
-
error:
|
|
1017
|
-
errorStack:
|
|
1093
|
+
error: serializedError.message,
|
|
1094
|
+
errorStack: serializedError.stack || 'No stack trace available',
|
|
1018
1095
|
timestamp: new Date().toISOString(),
|
|
1019
1096
|
context: {
|
|
1020
1097
|
isReconnect: true,
|
|
@@ -1027,7 +1104,7 @@ class Vapi extends VapiEventEmitter {
|
|
|
1027
1104
|
// Also emit the generic error event for backward compatibility
|
|
1028
1105
|
this.emit('error', {
|
|
1029
1106
|
type: 'reconnect-error',
|
|
1030
|
-
error:
|
|
1107
|
+
error: serializedError,
|
|
1031
1108
|
totalDuration,
|
|
1032
1109
|
timestamp: new Date().toISOString(),
|
|
1033
1110
|
context: {
|