@hivegpt/hiveai-angular 0.0.593 → 0.0.596

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.
Files changed (97) hide show
  1. package/environments/environment.d.ts.map +1 -1
  2. package/esm2020/environments/environment.mjs +15 -0
  3. package/esm2020/hivegpt-hiveai-angular.mjs +5 -0
  4. package/esm2020/lib/components/NotificationSocket.mjs +45 -0
  5. package/esm2020/lib/components/bot-html-editor/bot-html-editor.component.mjs +113 -0
  6. package/esm2020/lib/components/bot.service.mjs +45 -0
  7. package/esm2020/lib/components/chat-drawer/chat-drawer.component.mjs +3904 -0
  8. package/esm2020/lib/components/chatbot/chatbot.component.mjs +95 -0
  9. package/esm2020/lib/components/conversation.service.mjs +58 -0
  10. package/esm2020/lib/components/socket-service.service.mjs +65 -0
  11. package/esm2020/lib/components/translations/translation.service.mjs +244 -0
  12. package/esm2020/lib/components/video-player/video-player.component.mjs +131 -0
  13. package/esm2020/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.mjs +187 -0
  14. package/esm2020/lib/components/voice-agent/services/audio-analyzer.service.mjs +127 -0
  15. package/esm2020/lib/components/voice-agent/services/voice-agent.service.mjs +352 -0
  16. package/esm2020/lib/components/voice-agent/voice-agent.module.mjs +37 -0
  17. package/esm2020/lib/components/voice-agent/voice-modal-tokens.mjs +4 -0
  18. package/esm2020/lib/hivegpt.module.mjs +28 -0
  19. package/esm2020/lib/models/video.mjs +2 -0
  20. package/esm2020/lib/pipes/safe-html.pipe.mjs +20 -0
  21. package/esm2020/lib/services/platform-token-refresh.service.mjs +177 -0
  22. package/esm2020/lib/utils/utils.mjs +36 -0
  23. package/esm2020/public-api.mjs +15 -0
  24. package/fesm2015/hivegpt-hiveai-angular.mjs +5605 -0
  25. package/fesm2015/hivegpt-hiveai-angular.mjs.map +1 -0
  26. package/fesm2020/hivegpt-hiveai-angular.mjs +5606 -0
  27. package/fesm2020/hivegpt-hiveai-angular.mjs.map +1 -0
  28. package/hivegpt-hiveai-angular.d.ts.map +1 -1
  29. package/index.d.ts +6 -0
  30. package/lib/components/NotificationSocket.d.ts +6 -1
  31. package/lib/components/NotificationSocket.d.ts.map +1 -1
  32. package/lib/components/bot-html-editor/bot-html-editor.component.d.ts +3 -0
  33. package/lib/components/bot-html-editor/bot-html-editor.component.d.ts.map +1 -1
  34. package/lib/components/bot.service.d.ts +5 -1
  35. package/lib/components/bot.service.d.ts.map +1 -1
  36. package/lib/components/chat-drawer/chat-drawer.component.d.ts +7 -3
  37. package/lib/components/chat-drawer/chat-drawer.component.d.ts.map +1 -1
  38. package/lib/components/chatbot/chatbot.component.d.ts +3 -0
  39. package/lib/components/chatbot/chatbot.component.d.ts.map +1 -1
  40. package/lib/components/conversation.service.d.ts +3 -0
  41. package/lib/components/conversation.service.d.ts.map +1 -1
  42. package/lib/components/socket-service.service.d.ts +7 -3
  43. package/lib/components/socket-service.service.d.ts.map +1 -1
  44. package/lib/components/translations/translation.service.d.ts +3 -0
  45. package/lib/components/translations/translation.service.d.ts.map +1 -1
  46. package/lib/components/video-player/video-player.component.d.ts +3 -0
  47. package/lib/components/video-player/video-player.component.d.ts.map +1 -1
  48. package/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.d.ts +3 -0
  49. package/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.d.ts.map +1 -1
  50. package/lib/components/voice-agent/services/audio-analyzer.service.d.ts +3 -0
  51. package/lib/components/voice-agent/services/audio-analyzer.service.d.ts.map +1 -1
  52. package/lib/components/voice-agent/services/voice-agent.service.d.ts +4 -1
  53. package/lib/components/voice-agent/services/voice-agent.service.d.ts.map +1 -1
  54. package/lib/components/voice-agent/voice-agent.module.d.ts +6 -0
  55. package/lib/components/voice-agent/voice-agent.module.d.ts.map +1 -1
  56. package/lib/components/voice-agent/voice-modal-tokens.d.ts.map +1 -1
  57. package/lib/hivegpt.module.d.ts +16 -0
  58. package/lib/hivegpt.module.d.ts.map +1 -1
  59. package/lib/models/video.d.ts.map +1 -1
  60. package/lib/pipes/safe-html.pipe.d.ts +3 -0
  61. package/lib/pipes/safe-html.pipe.d.ts.map +1 -1
  62. package/lib/services/platform-token-refresh.service.d.ts +3 -0
  63. package/lib/services/platform-token-refresh.service.d.ts.map +1 -1
  64. package/lib/utils/utils.d.ts.map +1 -1
  65. package/package.json +24 -12
  66. package/public-api.d.ts +2 -0
  67. package/public-api.d.ts.map +1 -1
  68. package/bundles/hivegpt-hiveai-angular.umd.js +0 -6285
  69. package/bundles/hivegpt-hiveai-angular.umd.js.map +0 -1
  70. package/bundles/hivegpt-hiveai-angular.umd.min.js +0 -2
  71. package/bundles/hivegpt-hiveai-angular.umd.min.js.map +0 -1
  72. package/esm2015/environments/environment.js +0 -15
  73. package/esm2015/hivegpt-hiveai-angular.js +0 -13
  74. package/esm2015/lib/components/NotificationSocket.js +0 -39
  75. package/esm2015/lib/components/bot-html-editor/bot-html-editor.component.js +0 -112
  76. package/esm2015/lib/components/bot.service.js +0 -50
  77. package/esm2015/lib/components/chat-drawer/chat-drawer.component.js +0 -3809
  78. package/esm2015/lib/components/chatbot/chatbot.component.js +0 -57
  79. package/esm2015/lib/components/conversation.service.js +0 -57
  80. package/esm2015/lib/components/socket-service.service.js +0 -79
  81. package/esm2015/lib/components/translations/translation.service.js +0 -244
  82. package/esm2015/lib/components/video-player/video-player.component.js +0 -123
  83. package/esm2015/lib/components/voice-agent/components/voice-agent-modal/voice-agent-modal.component.js +0 -192
  84. package/esm2015/lib/components/voice-agent/services/audio-analyzer.service.js +0 -125
  85. package/esm2015/lib/components/voice-agent/services/voice-agent.service.js +0 -364
  86. package/esm2015/lib/components/voice-agent/voice-agent.module.js +0 -29
  87. package/esm2015/lib/components/voice-agent/voice-modal-tokens.js +0 -4
  88. package/esm2015/lib/hivegpt.module.js +0 -23
  89. package/esm2015/lib/models/video.js +0 -2
  90. package/esm2015/lib/pipes/safe-html.pipe.js +0 -19
  91. package/esm2015/lib/services/platform-token-refresh.service.js +0 -173
  92. package/esm2015/lib/utils/utils.js +0 -38
  93. package/esm2015/public-api.js +0 -13
  94. package/fesm2015/hivegpt-hiveai-angular.js +0 -5484
  95. package/fesm2015/hivegpt-hiveai-angular.js.map +0 -1
  96. package/hivegpt-hiveai-angular.d.ts +0 -13
  97. package/hivegpt-hiveai-angular.metadata.json +0 -1
@@ -1,123 +0,0 @@
1
- import { ChangeDetectorRef, Component, ElementRef, EventEmitter, Inject, Input, Output, ViewChild, } from '@angular/core';
2
- import { DOCUMENT } from '@angular/common';
3
- export class VideoPlayerComponent {
4
- constructor(doc, el, cdr) {
5
- this.doc = doc;
6
- this.el = el;
7
- this.cdr = cdr;
8
- this.isMuted = true;
9
- this.isFullscreen = false;
10
- this.isFullscreenvideoPlaying = false;
11
- this.connectWithUser = new EventEmitter();
12
- this.scheduleMeeting = new EventEmitter();
13
- }
14
- ngOnInit() {
15
- }
16
- toggleSound(isMuted = null) {
17
- this.isMuted = isMuted != null ? isMuted : !this.isMuted;
18
- setTimeout(() => {
19
- const video = this.doc
20
- .getElementById(this.video.id.toString());
21
- if (video) {
22
- video.muted = this.isMuted;
23
- this.video.isMuted = this.isMuted;
24
- }
25
- this.cdr.markForCheck();
26
- //this.muteToggle.emit(this.isMuted);
27
- });
28
- }
29
- togglePlay(playState, videoEl) {
30
- this.videoObj.isPlaying = !this.videoObj.isPlaying;
31
- setTimeout(() => {
32
- if (playState) {
33
- this.videoObj.isPlaying = true;
34
- videoEl.play();
35
- var pauseBtn = document.getElementById('pause-btn');
36
- pauseBtn.classList.add('hide-pause-btn');
37
- this.toggleSound(false);
38
- }
39
- else {
40
- this.videoObj.isPlaying = false;
41
- videoEl.pause();
42
- }
43
- this.cdr.markForCheck();
44
- });
45
- }
46
- ngAfterViewInit() {
47
- if (window.innerWidth <= 576) {
48
- this.observer = new IntersectionObserver((entries) => {
49
- if (entries[0].isIntersecting === true) {
50
- this.video.nativeElement.play();
51
- }
52
- else {
53
- this.video.nativeElement.pause();
54
- }
55
- }, {
56
- threshold: 0.75,
57
- });
58
- this.observer.observe(this.el.nativeElement);
59
- }
60
- }
61
- toggleFullscreen() {
62
- this.isFullscreen = !this.isFullscreen;
63
- if (!this.isFullscreen) {
64
- this.fullscreenvideo.nativeElement.pause();
65
- }
66
- }
67
- toggleFullscreenPlay() {
68
- this.isFullscreenvideoPlaying = !this.isFullscreenvideoPlaying;
69
- if (this.isFullscreenvideoPlaying) {
70
- this.fullscreenvideo.nativeElement.play();
71
- }
72
- else {
73
- this.fullscreenvideo.nativeElement.pause();
74
- }
75
- }
76
- followUser(userId) {
77
- this.connectWithUser.emit(userId);
78
- }
79
- checkPendingSentRequest(userId) {
80
- var _a;
81
- return (_a = this.myPendingSentRequests) === null || _a === void 0 ? void 0 : _a.find(a => a == userId);
82
- }
83
- canUnfollowUser() {
84
- return false;
85
- }
86
- canFollowUser() {
87
- return true;
88
- }
89
- getIniNames(firstName, lastName) {
90
- if (!firstName && !lastName) {
91
- return '';
92
- }
93
- if (firstName && lastName)
94
- return (firstName.charAt(0).toUpperCase() + lastName.charAt(0).toUpperCase());
95
- else
96
- return firstName.charAt(0).toUpperCase();
97
- }
98
- }
99
- VideoPlayerComponent.decorators = [
100
- { type: Component, args: [{
101
- selector: 'app-video-player',
102
- template: "<div class=\"video-wrapper\" >\n <div class=\"overlymask-video\"></div>\n <video (click)=\"toggleFullscreen()\" #video [loop]=\"true\" [muted]=\"isMuted\" [src]=\"videoObj.processedUrls || videoObj.url\" playsinline\n [controls]=\"false\"></video>\n <div class=\"main-controls\" [class.no-opacity]=\"video.isPlaying\">\n <button mat-icon-button *ngIf=\"!videoObj.isPlaying\"\n attr.aria-label=\"Play Video\"\n title=\"Play Video\" class=\"play-pause-btn\"\n (click)=\"togglePlay(true, video)\">\n <!-- <mat-icon alt=\"Play\">play_arrow</mat-icon> -->\n <span class=\"material-icons notranslate \" aria-hidden=\"true\">play_circle_outline</span>\n </button>\n\n <button mat-icon-button id=\"pause-btn\" [hidden]=\"!videoObj.isPlaying\" class=\"pause_btn play-pause-btn playing\"\n title=\"Pause Video\"\n [class.half-opacity]=\"video.isPlaying\" (click)=\"togglePlay(false, video)\">\n <!-- <mat-icon alt=\"Pause\">pause</mat-icon> -->\n <span class=\"material-icons notranslate \" aria-hidden=\"true\">pause_circle_outline</span>\n </button>\n </div>\n <div class=\"video-actions\">\n <button class=\"button-trasparent action\" (click)=\"toggleSound()\" title=\"Mute\" *ngIf=\"isMuted\">\n <span class=\"material-icons notranslate \" aria-hidden=\"true\">volume_off</span>\n </button>\n <button class=\"button-trasparent action\" (click)=\"toggleSound()\" title=\"Unmute\" *ngIf=\"!isMuted\">\n <span class=\"material-icons notranslate \" aria-hidden=\"true\">volume_up</span>\n </button>\n\n </div>\n</div>\n\n<div class=\"full-screen\" *ngIf=\"isFullscreen\" [ngClass]=\"{'show': isFullscreen}\">\n <div class=\"video-wrapper\">\n <video #fullscreenvideo (click)=\"toggleFullscreenPlay()\" [loop]=\"true\" [muted]=\"isMuted\" [src]=\"videoObj.processedUrls || videoObj.url\"\n playsinline [controls]=\"false\"></video>\n <div (click)=\"toggleFullscreen()\" class=\"close-btn\">\n <span class=\"material-icons notranslate \">clear</span>\n </div>\n <div class=\"video-actions\">\n <button *ngIf=\"!video.isPlaying\" title=\"Play\"\n class=\"material-icons notranslate body-text-color fs-h2 play position-absolute transparent-btn\" (click)=\"togglePlay(true, video)\">\n play_circle_outline\n </button>\n <button id=\"pause-btn\" [hidden]=\"!videoObj.isPlaying\" title=\"Pause\"\n class=\"pause_btn material-icons body-text-color fs-h2 play position-absolute transparent-btn\"\n [class.half-opacity]=\"video.isPlaying\" (click)=\"togglePlay(false, video)\">\n pause_circle_outline\n </button>\n </div>\n </div>\n</div>\n",
103
- styles: [".video-wrapper{position:relative}.video-wrapper video{-o-object-fit:cover;border-radius:5px;cursor:pointer;height:330px;object-fit:cover;outline:0;transition:.3s ease-in-out;width:100%}.video-wrapper .video-actions{display:flex;flex-direction:column;position:absolute;right:10px;top:10px}.video-wrapper .video-actions .action{color:#fff;cursor:pointer;margin-bottom:5px}.video-wrapper .author-details{bottom:18px;display:flex;flex-direction:column;justify-content:flex-start;left:12px;position:absolute;right:12px;transition:.3s ease-in-out}.video-wrapper .author-details .author-image{border-radius:50%;height:34px;margin-right:6px;overflow:hidden;width:34px}.video-wrapper .author-details .author-image img{-o-object-fit:cover;height:100%;object-fit:cover;width:100%}.video-wrapper .author-details .author-name,.video-wrapper .author-details .video-title{color:#fff;display:block;font-size:14px;mix-blend-mode:hard-light}.video-wrapper .connect-btn{bottom:20px;opacity:0;outline:0;position:absolute;text-align:center;transition:.3s ease-in-out;width:100%}@media only screen and (max-width:576px){.video-wrapper .connect-btn{opacity:1;right:20px;width:unset}}.video-wrapper .connect-btn button{margin:auto}.video-wrapper:hover .author-details{opacity:0}@media only screen and (max-width:576px){.video-wrapper:hover .author-details{opacity:1}}.video-wrapper:hover .connect-btn{opacity:1}.video-wrapper .half-opacity{opacity:.2}.video-wrapper .no-opacity{background-color:transparent}.like-btn{margin-bottom:20px;text-align:center;transition:.2s ease-in-out}.like-btn .count{font-size:16px;margin-left:3px}.like-btn span{cursor:pointer;font-size:30px}.like-btn:hover{transform:scale(1.1)}.like-btn.like{color:#025be7}.like-btn.dislike{color:#8d8d8d}.like-btn.info{color:#aeae3f}.full-screen.show{align-items:center;background:rgba(27,26,26,.9607843137254902);display:flex;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:9999}.full-screen.show .video-wrapper video{height:270px;transform:none!important;transition:none;width:300px}.full-screen .close-btn{cursor:pointer;left:10px;position:absolute;top:10px}.full-screen .close-btn span{color:#fff}.main-controls{background-color:rgba(0,0,0,.3);bottom:0;left:0;right:0;top:0}.main-controls,.main-controls .play-pause-btn{align-items:center;display:flex;justify-content:center;position:absolute}.main-controls .play-pause-btn{background:none;border:none;color:#fff;line-height:0;top:34%}.main-controls .play-pause-btn.playing{cursor:pointer;left:50%;position:absolute;top:40%;transform:translate(-50%,-50%)}.main-controls .play-pause-btn.playing span{color:#fff;text-shadow:0 0 6px rgba(47,47,47,.36)}.main-controls .play-pause-btn:focus{outline:none}.main-controls .play-pause-btn .material-icons{font-size:40px}.main-controls .play-pause-btn .mat-icon{height:auto;width:auto}.main-controls .half-opacity{opacity:.2}.main-controls .no-opacity{background-color:transparent}button.transparent-btn{background:transparent;border:0!important}.pause_btn{height:100%;opacity:.02!important;width:100%}.pause_btn:hover{background-color:rgba(0,0,0,.7411764705882353);opacity:1!important}.hide-pause-btn{opacity:0!important}.no-photo{align-items:center;display:flex;font-size:14px;height:35px;justify-content:center;width:35px}.overlymask-video{background-image:linear-gradient(hsla(0,0%,100%,.058823529411764705),rgba(0,0,0,.1803921568627451));background-position:0 bottom;height:275px;position:absolute;width:100%;z-index:0}"]
104
- },] }
105
- ];
106
- VideoPlayerComponent.ctorParameters = () => [
107
- { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
108
- { type: ElementRef },
109
- { type: ChangeDetectorRef }
110
- ];
111
- VideoPlayerComponent.propDecorators = {
112
- currentUserId: [{ type: Input }],
113
- user: [{ type: Input }],
114
- eventId: [{ type: Input }],
115
- videoObj: [{ type: Input }],
116
- isDev: [{ type: Input }],
117
- type: [{ type: Input }],
118
- video: [{ type: ViewChild, args: ['video',] }],
119
- fullscreenvideo: [{ type: ViewChild, args: ['fullscreenvideo',] }],
120
- connectWithUser: [{ type: Output }],
121
- scheduleMeeting: [{ type: Output }]
122
- };
123
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlkZW8tcGxheWVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIvVXNlcnMvcm9oaXR0aGFrdXIvaGl2ZS1ncHQvSGl2ZUFJLVBhY2thZ2VzL0FuZ3VsYXIvcHJvamVjdHMvaGl2ZWdwdC9ldmVudHNncHQtYW5ndWxhci9zcmMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy92aWRlby1wbGF5ZXIvdmlkZW8tcGxheWVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBRUwsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFPM0MsTUFBTSxPQUFPLG9CQUFvQjtJQW9CL0IsWUFDNEIsR0FBUSxFQUMxQixFQUFjLEVBQ2QsR0FBc0I7UUFGSixRQUFHLEdBQUgsR0FBRyxDQUFLO1FBQzFCLE9BQUUsR0FBRixFQUFFLENBQVk7UUFDZCxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQWJoQyxZQUFPLEdBQVksSUFBSSxDQUFDO1FBRXhCLGlCQUFZLEdBQVksS0FBSyxDQUFDO1FBRzlCLDZCQUF3QixHQUFZLEtBQUssQ0FBQztRQUVoQyxvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDN0Msb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO0lBT3BELENBQUM7SUFFRCxRQUFRO0lBQ1IsQ0FBQztJQUVELFdBQVcsQ0FBQyxPQUFPLEdBQUcsSUFBSTtRQUN4QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQ3pELFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCxNQUFNLEtBQUss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LHFCQUFxQiwwQ0FBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVELGVBQWU7UUFDYixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsV0FBVyxDQUFDLFNBQVMsRUFBRSxRQUFRO1FBQzdCLElBQUcsQ0FBQyxTQUFTLElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDMUIsT0FBTyxFQUFFLENBQUM7U0FDWDtRQUVELElBQUksU0FBUyxJQUFJLFFBQVE7WUFDdkIsT0FBTyxDQUNMLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FDckUsQ0FBQzs7WUFDQyxPQUFPLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDaEQsQ0FBQzs7O1lBbklGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsa0JBQWtCO2dCQUM1QixtcEZBQTRDOzthQUU3Qzs7OzRDQXNCSSxNQUFNLFNBQUMsUUFBUTtZQXJDbEIsVUFBVTtZQUZWLGlCQUFpQjs7OzRCQW9CaEIsS0FBSzttQkFDTCxLQUFLO3NCQUNMLEtBQUs7dUJBQ0wsS0FBSztvQkFDTCxLQUFLO21CQUdMLEtBQUs7b0JBSUwsU0FBUyxTQUFDLE9BQU87OEJBQ2pCLFNBQVMsU0FBQyxpQkFBaUI7OEJBRzNCLE1BQU07OEJBQ04sTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBJVmlkZW8gfSBmcm9tICcuLi8uLi9tb2RlbHMvdmlkZW8nO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtdmlkZW8tcGxheWVyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3ZpZGVvLXBsYXllci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3ZpZGVvLXBsYXllci5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBWaWRlb1BsYXllckNvbXBvbmVudFxuICBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG4gIEBJbnB1dCgpIGN1cnJlbnRVc2VySWQ6IHN0cmluZztcbiAgQElucHV0KCkgdXNlcjogYW55O1xuICBASW5wdXQoKSBldmVudElkOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHZpZGVvT2JqOiBJVmlkZW87XG4gIEBJbnB1dCgpIGlzRGV2OiBib29sZWFuO1xuICBteUZvbGxvd2luZ0xpc3Q6IEFycmF5PHN0cmluZz47XG4gIG15UGVuZGluZ1NlbnRSZXF1ZXN0czogQXJyYXk8c3RyaW5nPjtcbiAgQElucHV0KCkgdHlwZTogc3RyaW5nO1xuICBpc011dGVkOiBib29sZWFuID0gdHJ1ZTtcbiAgcHJpdmF0ZSBvYnNlcnZlcjogSW50ZXJzZWN0aW9uT2JzZXJ2ZXI7XG4gIGlzRnVsbHNjcmVlbjogYm9vbGVhbiA9IGZhbHNlO1xuICBAVmlld0NoaWxkKCd2aWRlbycpIHZpZGVvOiBhbnk7XG4gIEBWaWV3Q2hpbGQoJ2Z1bGxzY3JlZW52aWRlbycpIGZ1bGxzY3JlZW52aWRlbzogYW55O1xuICBpc0Z1bGxzY3JlZW52aWRlb1BsYXlpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBAT3V0cHV0KCkgY29ubmVjdFdpdGhVc2VyID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIEBPdXRwdXQoKSBzY2hlZHVsZU1lZXRpbmcgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvYzogYW55LFxuICAgIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gIH1cblxuICB0b2dnbGVTb3VuZChpc011dGVkID0gbnVsbCkge1xuICAgIHRoaXMuaXNNdXRlZCA9IGlzTXV0ZWQgIT0gbnVsbCA/IGlzTXV0ZWQgOiAhdGhpcy5pc011dGVkO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29uc3QgdmlkZW86IGFueSA9IHRoaXMuZG9jXG4gICAgICAgIC5nZXRFbGVtZW50QnlJZCh0aGlzLnZpZGVvLmlkLnRvU3RyaW5nKCkpO1xuICAgICAgaWYgKHZpZGVvKSB7XG4gICAgICAgIHZpZGVvLm11dGVkID0gdGhpcy5pc011dGVkO1xuICAgICAgICB0aGlzLnZpZGVvLmlzTXV0ZWQgPSB0aGlzLmlzTXV0ZWQ7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIC8vdGhpcy5tdXRlVG9nZ2xlLmVtaXQodGhpcy5pc011dGVkKTtcbiAgICAgIH0pXG59XG5cbiAgdG9nZ2xlUGxheShwbGF5U3RhdGU6IGJvb2xlYW4sIHZpZGVvRWwpIHtcbiAgICB0aGlzLnZpZGVvT2JqLmlzUGxheWluZyA9ICF0aGlzLnZpZGVvT2JqLmlzUGxheWluZztcbiAgICBzZXRUaW1lb3V0KCgpID0+IHsgICAgIFxuICAgICAgaWYgKHBsYXlTdGF0ZSkgeyAgICAgXG4gICAgICAgIHRoaXMudmlkZW9PYmouaXNQbGF5aW5nID0gIHRydWU7XG4gICAgICAgIHZpZGVvRWwucGxheSgpO1xuICAgICAgICB2YXIgcGF1c2VCdG4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncGF1c2UtYnRuJyk7XG4gICAgICAgIHBhdXNlQnRuLmNsYXNzTGlzdC5hZGQoJ2hpZGUtcGF1c2UtYnRuJyk7XG5cbiAgICAgICAgdGhpcy50b2dnbGVTb3VuZChmYWxzZSk7XG4gICAgICB9XG4gICAgICBlbHNle1xuICAgICAgICB0aGlzLnZpZGVvT2JqLmlzUGxheWluZyA9ICBmYWxzZTtcbiAgICAgICAgdmlkZW9FbC5wYXVzZSgpO1xuICAgICAgfVxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KVxuICB9XG4gIFxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgaWYgKHdpbmRvdy5pbm5lcldpZHRoIDw9IDU3Nikge1xuICAgICAgdGhpcy5vYnNlcnZlciA9IG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihcbiAgICAgICAgKGVudHJpZXMpID0+IHtcbiAgICAgICAgICBpZiAoZW50cmllc1swXS5pc0ludGVyc2VjdGluZyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy52aWRlby5uYXRpdmVFbGVtZW50LnBsYXkoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52aWRlby5uYXRpdmVFbGVtZW50LnBhdXNlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgdGhyZXNob2xkOiAwLjc1LFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICB0aGlzLm9ic2VydmVyLm9ic2VydmUodGhpcy5lbC5uYXRpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50KTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVGdWxsc2NyZWVuKCkge1xuICAgIHRoaXMuaXNGdWxsc2NyZWVuID0gIXRoaXMuaXNGdWxsc2NyZWVuO1xuICAgIGlmICghdGhpcy5pc0Z1bGxzY3JlZW4pIHtcbiAgICAgIHRoaXMuZnVsbHNjcmVlbnZpZGVvLm5hdGl2ZUVsZW1lbnQucGF1c2UoKTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVGdWxsc2NyZWVuUGxheSgpIHtcbiAgICB0aGlzLmlzRnVsbHNjcmVlbnZpZGVvUGxheWluZyA9ICF0aGlzLmlzRnVsbHNjcmVlbnZpZGVvUGxheWluZztcblxuICAgIGlmICh0aGlzLmlzRnVsbHNjcmVlbnZpZGVvUGxheWluZykge1xuICAgICAgdGhpcy5mdWxsc2NyZWVudmlkZW8ubmF0aXZlRWxlbWVudC5wbGF5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZnVsbHNjcmVlbnZpZGVvLm5hdGl2ZUVsZW1lbnQucGF1c2UoKTtcbiAgICB9XG4gIH1cblxuICBmb2xsb3dVc2VyKHVzZXJJZCkge1xuICAgIHRoaXMuY29ubmVjdFdpdGhVc2VyLmVtaXQodXNlcklkKTtcbiAgfVxuXG4gIGNoZWNrUGVuZGluZ1NlbnRSZXF1ZXN0KHVzZXJJZCkge1xuICAgIHJldHVybiB0aGlzLm15UGVuZGluZ1NlbnRSZXF1ZXN0cz8uZmluZChhID0+IGEgPT0gdXNlcklkKTtcbiAgfVxuXG4gIGNhblVuZm9sbG93VXNlcigpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjYW5Gb2xsb3dVc2VyKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgZ2V0SW5pTmFtZXMoZmlyc3ROYW1lLCBsYXN0TmFtZSkge1xuICAgIGlmKCFmaXJzdE5hbWUgJiYgIWxhc3ROYW1lKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIFxuICAgIGlmIChmaXJzdE5hbWUgJiYgbGFzdE5hbWUpXG4gICAgICByZXR1cm4gKFxuICAgICAgICBmaXJzdE5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBsYXN0TmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKVxuICAgICAgKTtcbiAgICBlbHNlIHJldHVybiBmaXJzdE5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCk7XG4gIH1cbn1cbiJdfQ==
@@ -1,192 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { Component, Input, Output, EventEmitter, Injector } from '@angular/core';
3
- import { VoiceAgentService } from '../../services/voice-agent.service';
4
- import { AudioAnalyzerService } from '../../services/audio-analyzer.service';
5
- import { VOICE_MODAL_CONFIG, VOICE_MODAL_CLOSE_CALLBACK } from '../../voice-modal-tokens';
6
- export class VoiceAgentModalComponent {
7
- constructor(voiceAgentService, audioAnalyzer, injector) {
8
- this.voiceAgentService = voiceAgentService;
9
- this.audioAnalyzer = audioAnalyzer;
10
- this.injector = injector;
11
- this.close = new EventEmitter();
12
- this.apiKey = '';
13
- this.eventToken = '';
14
- this.eventId = '';
15
- this.eventUrl = '';
16
- this.domainAuthority = 'prod-lite';
17
- this.agentName = 'AI Assistant';
18
- this.agentRole = 'AI Agent Specialist';
19
- this.usersApiUrl = '';
20
- this.injectedConfig = null;
21
- this.onCloseCallback = null;
22
- /** Hardcoded voice agent avatar (Nia). */
23
- this.displayAvatarUrl = 'https://www.jotform.com/uploads/mehmetkarakasli/form_files/1564593667676a8e85f23758.86945537_icon.png';
24
- this.callState = 'idle';
25
- this.statusText = '';
26
- this.duration = '00:00';
27
- this.isMicMuted = false;
28
- this.isUserSpeaking = false;
29
- this.audioLevels = [];
30
- this.subscriptions = [];
31
- this.isConnecting = false;
32
- }
33
- /** True while the bot is speaking — drives avatar pulse animation and voice visualizer. */
34
- get isBotTalking() { return this.callState === 'talking'; }
35
- /** True while the user is actively speaking — drives waveform active color. */
36
- get isUserActive() { return this.callState === 'listening' && this.isUserSpeaking && !this.isMicMuted; }
37
- /** True during the brief processing pause between user speech and bot response. */
38
- get isProcessing() { return this.callState === 'connected' && this.statusText === 'Processing...'; }
39
- ngOnInit() {
40
- var _a, _b, _c, _d, _e, _f, _g, _h;
41
- // When opened via Overlay, config is provided by injection
42
- this.injectedConfig = this.injector.get(VOICE_MODAL_CONFIG, null);
43
- this.onCloseCallback = this.injector.get(VOICE_MODAL_CLOSE_CALLBACK, null);
44
- if (this.injectedConfig) {
45
- this.apiUrl = this.injectedConfig.apiUrl;
46
- this.token = this.injectedConfig.token;
47
- this.botId = this.injectedConfig.botId;
48
- this.conversationId = this.injectedConfig.conversationId;
49
- this.apiKey = (_a = this.injectedConfig.apiKey) !== null && _a !== void 0 ? _a : '';
50
- this.eventToken = (_b = this.injectedConfig.eventToken) !== null && _b !== void 0 ? _b : '';
51
- this.eventId = (_c = this.injectedConfig.eventId) !== null && _c !== void 0 ? _c : '';
52
- this.eventUrl = (_d = this.injectedConfig.eventUrl) !== null && _d !== void 0 ? _d : '';
53
- this.domainAuthority = (_e = this.injectedConfig.domainAuthority) !== null && _e !== void 0 ? _e : 'prod-lite';
54
- this.agentName = (_f = this.injectedConfig.agentName) !== null && _f !== void 0 ? _f : this.agentName;
55
- this.agentRole = (_g = this.injectedConfig.agentRole) !== null && _g !== void 0 ? _g : this.agentRole;
56
- this.agentAvatar = this.injectedConfig.agentAvatar;
57
- this.usersApiUrl = (_h = this.injectedConfig.usersApiUrl) !== null && _h !== void 0 ? _h : this.usersApiUrl;
58
- }
59
- this.subscriptions.push(this.voiceAgentService.callState$.subscribe(state => {
60
- this.callState = state;
61
- }));
62
- this.subscriptions.push(this.voiceAgentService.statusText$.subscribe(text => {
63
- this.statusText = text;
64
- }));
65
- this.subscriptions.push(this.voiceAgentService.duration$.subscribe(duration => {
66
- this.duration = duration;
67
- }));
68
- this.subscriptions.push(this.voiceAgentService.isMicMuted$.subscribe(muted => {
69
- this.isMicMuted = muted;
70
- }));
71
- this.subscriptions.push(this.voiceAgentService.isUserSpeaking$.subscribe(speaking => {
72
- this.isUserSpeaking = speaking;
73
- }));
74
- this.subscriptions.push(this.voiceAgentService.audioLevels$.subscribe(levels => {
75
- this.audioLevels = levels;
76
- }));
77
- // Always start from a fresh voice session to avoid stale/disconnected state flashes.
78
- void this.openFreshCallSession();
79
- }
80
- ngOnDestroy() {
81
- this.subscriptions.forEach(sub => sub.unsubscribe());
82
- this.disconnect();
83
- }
84
- startCall() {
85
- return __awaiter(this, void 0, void 0, function* () {
86
- if (this.isConnecting || (this.callState !== 'idle' && this.callState !== 'ended'))
87
- return;
88
- this.isConnecting = true;
89
- try {
90
- yield this.voiceAgentService.connect(this.apiUrl, this.token, this.botId, this.conversationId, this.apiKey, this.eventToken, this.eventId, this.eventUrl, this.domainAuthority, this.usersApiUrl || undefined);
91
- }
92
- catch (error) {
93
- console.error('Failed to connect voice agent:', error);
94
- }
95
- finally {
96
- this.isConnecting = false;
97
- }
98
- });
99
- }
100
- disconnect() {
101
- return __awaiter(this, void 0, void 0, function* () {
102
- yield this.voiceAgentService.disconnect();
103
- });
104
- }
105
- openFreshCallSession() {
106
- return __awaiter(this, void 0, void 0, function* () {
107
- yield this.voiceAgentService.prepareFreshSession();
108
- yield this.startCall();
109
- });
110
- }
111
- toggleMic() {
112
- this.voiceAgentService.toggleMic();
113
- }
114
- /**
115
- * Map audio level (0–100) to waveform bar height in px with a gaussian
116
- * bell-curve envelope so centre bars are tallest and edge bars appear
117
- * as tiny dots — matching the audio-waveform reference design.
118
- */
119
- getWaveformHeight(level, index) {
120
- const n = Math.min(100, Math.max(0, level !== null && level !== void 0 ? level : 0));
121
- const total = this.audioLevels.length || 60;
122
- const center = (total - 1) / 2;
123
- const sigma = total / 5;
124
- const envelope = Math.exp(-Math.pow(index - center, 2) / (2 * sigma * sigma));
125
- // Minimum height scales with envelope so edges show as dots even in silence
126
- const minHeight = 2 + envelope * 3;
127
- const maxHeight = 4 + envelope * 38;
128
- return minHeight + (n / 100) * (maxHeight - minHeight);
129
- }
130
- /** Status label for active call — driven by callState + service statusText. */
131
- get statusLabel() {
132
- switch (this.callState) {
133
- case 'connecting': return 'Connecting...';
134
- case 'talking': return 'Talking...';
135
- case 'listening': return 'Listening...';
136
- // 'connected' covers: initial connect, between turns (Listening / Processing)
137
- case 'connected': return this.statusText || 'Connected';
138
- default: return this.statusText || '';
139
- }
140
- }
141
- /** Call Again: reset to idle then start a new call. */
142
- callAgain() {
143
- return __awaiter(this, void 0, void 0, function* () {
144
- yield this.openFreshCallSession();
145
- });
146
- }
147
- /** Back to Chat: close modal and disconnect. */
148
- backToChat() {
149
- this.endCall();
150
- }
151
- /** End call but keep modal open to show Call Ended + Call Again / Back to Chat. */
152
- hangUp() {
153
- this.disconnect();
154
- }
155
- endCall() {
156
- var _a;
157
- return __awaiter(this, void 0, void 0, function* () {
158
- yield this.disconnect();
159
- (_a = this.onCloseCallback) === null || _a === void 0 ? void 0 : _a.call(this);
160
- this.close.emit();
161
- });
162
- }
163
- }
164
- VoiceAgentModalComponent.decorators = [
165
- { type: Component, args: [{
166
- selector: 'hivegpt-voice-agent-modal',
167
- template: "<div class=\"voice-agent-modal-overlay\" (click)=\"endCall()\">\n <div\n class=\"voice-container voice-agent-modal\"\n (click)=\"$event.stopPropagation()\"\n >\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-left\">\n <div class=\"header-icon\">\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 1C8.13 1 5 4.13 5 8V14C5 17.87 8.13 21 12 21C15.87 21 19 17.87 19 14V8C19 4.13 15.87 1 12 1Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M12 23C10.34 23 9 21.66 9 20H15C15 21.66 13.66 23 12 23Z\"\n fill=\"currentColor\"\n />\n </svg>\n </div>\n <span class=\"header-title\">Voice</span>\n </div>\n <button\n class=\"close-button\"\n (click)=\"endCall()\"\n type=\"button\"\n aria-label=\"Close\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M18 6L6 18M6 6L18 18\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </div>\n\n <!-- Avatar Section with glow -->\n <div class=\"avatar-section\">\n <div class=\"avatar-glow\" [class.glow-talking]=\"isBotTalking\" [class.glow-listening]=\"callState === 'listening'\"></div>\n\n <!-- Particle ring \u2014 visible while bot is talking -->\n <div *ngIf=\"isBotTalking\" class=\"particles-container\">\n <span *ngFor=\"let i of [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]\"\n class=\"particle\"\n [style.--i]=\"i\"\n [style.animationDelay]=\"(i * 0.15) + 's'\">\n </span>\n </div>\n\n <div class=\"avatar-wrapper\" [class.speaking]=\"isBotTalking\" [class.listening]=\"callState === 'listening'\">\n <img class=\"avatar-image\" [src]=\"displayAvatarUrl\" alt=\"Nia\" />\n </div>\n </div>\n\n <!-- Agent Info: Nia + Collaboration Manager AI Agent Specialist -->\n <div class=\"agent-info\">\n <div class=\"agent-name\">\n Nia\n <span class=\"ai-badge\">AI</span>\n </div>\n <p class=\"agent-role\">COP30 AI Agent </p>\n </div>\n\n <!-- Start Call (when idle only) -->\n <div *ngIf=\"callState === 'idle'\" class=\"start-call-section\">\n <p *ngIf=\"statusText === 'Connection failed'\" class=\"error-message\">\n {{ statusText }}\n </p>\n <button\n class=\"start-call-button\"\n type=\"button\"\n [disabled]=\"isConnecting\"\n (click)=\"startCall()\"\n >\n <span *ngIf=\"isConnecting\">Connecting...</span>\n <span *ngIf=\"!isConnecting && statusText === 'Connection failed'\"\n >Retry</span\n >\n <span *ngIf=\"!isConnecting && statusText !== 'Connection failed'\"\n >Start Call</span\n >\n </button>\n </div>\n\n <!-- Call Ended: status + Call Again / Back to Chat -->\n <div *ngIf=\"callState === 'ended'\" class=\"call-ended-section\">\n <p class=\"call-ended-status\">\n <span class=\"status-text\">Call Ended</span>\n <span class=\"status-timer\">{{ duration }}</span>\n </p>\n <div class=\"call-ended-controls\">\n <button\n class=\"action-btn\"\n type=\"button\"\n (click)=\"callAgain()\"\n title=\"Call Again\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </svg>\n Call Again\n </button>\n <button\n class=\"action-btn\"\n type=\"button\"\n (click)=\"backToChat()\"\n title=\"Back to Chat\"\n >\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n Back to Chat\n </button>\n </div>\n </div>\n\n <!-- Status (when connecting or in-call: Talking... / Listening / Connected + timer) -->\n <div\n class=\"status-indicator status-inline\"\n *ngIf=\"callState !== 'idle' && callState !== 'ended'\"\n >\n <div *ngIf=\"callState === 'connecting'\" class=\"status-connecting\">\n <svg\n class=\"spinner\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <circle\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-dasharray=\"31.416\"\n stroke-dashoffset=\"31.416\"\n >\n <animate\n attributeName=\"stroke-dasharray\"\n dur=\"2s\"\n values=\"0 31.416;15.708 15.708;0 31.416;0 31.416\"\n repeatCount=\"indefinite\"\n />\n <animate\n attributeName=\"stroke-dashoffset\"\n dur=\"2s\"\n values=\"0;-15.708;-31.416;-31.416\"\n repeatCount=\"indefinite\"\n />\n </circle>\n </svg>\n <span class=\"status-text\">{{ statusText }}</span>\n </div>\n <div\n *ngIf=\"callState !== 'connecting'\"\n class=\"status-connected status-inline-row\"\n >\n <span class=\"status-text\" [class.status-talking]=\"isBotTalking\" [class.status-listening]=\"callState === 'listening'\" [class.status-processing]=\"isProcessing\">\n {{ statusLabel }}\n </span>\n\n <!-- Animated bars \u2014 visible while bot is talking -->\n <div *ngIf=\"isBotTalking\" class=\"voice-visualizer\">\n <div class=\"vbar\"></div>\n <div class=\"vbar\"></div>\n <div class=\"vbar\"></div>\n <div class=\"vbar\"></div>\n </div>\n\n <!-- Bouncing dots \u2014 visible during processing pause -->\n <div *ngIf=\"isProcessing\" class=\"processing-dots\">\n <span></span><span></span><span></span>\n </div>\n\n <span class=\"status-timer\">{{ duration }}</span>\n </div>\n </div>\n\n <!-- Waveform: always visible during an active call, active (coloured) when user speaks -->\n <div\n *ngIf=\"callState === 'connected' || callState === 'listening' || callState === 'talking'\"\n class=\"waveform-container\"\n >\n <div class=\"waveform-bars\">\n <div\n *ngFor=\"let level of audioLevels; let i = index\"\n class=\"waveform-bar\"\n [class.active]=\"isUserActive\"\n [style.height.px]=\"getWaveformHeight(level, i)\"\n ></div>\n </div>\n </div>\n\n <!-- Call Controls (when connected) -->\n <div\n class=\"controls\"\n *ngIf=\"\n callState === 'connecting' ||\n callState === 'connected' ||\n callState === 'listening' ||\n callState === 'talking'\n \"\n >\n <div\n style=\"\n display: flex;\n align-items: center;\n gap: 2px;\n flex-direction: column;\n \"\n >\n <button\n class=\"control-btn mic-btn\"\n [class.muted]=\"isMicMuted\"\n (click)=\"toggleMic()\"\n type=\"button\"\n [title]=\"isMicMuted ? 'Unmute' : 'Mute'\"\n >\n <!-- Microphone icon (unmuted) -->\n <svg\n *ngIf=\"!isMicMuted\"\n width=\"24\"\n height=\"24\"\n viewBox=\"-5 0 32 32\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"currentColor\"\n >\n <g transform=\"translate(-105, -307)\">\n <path\n d=\"M111,314 C111,311.238 113.239,309 116,309 C118.761,309 121,311.238 121,314 L121,324 C121,326.762 118.761,329 116,329 C113.239,329 111,326.762 111,324 L111,314 L111,314 Z M116,331 C119.866,331 123,327.866 123,324 L123,314 C123,310.134 119.866,307 116,307 C112.134,307 109,310.134 109,314 L109,324 C109,327.866 112.134,331 116,331 L116,331 Z M127,326 L125,326 C124.089,330.007 120.282,333 116,333 C111.718,333 107.911,330.007 107,326 L105,326 C105.883,330.799 110.063,334.51 115,334.955 L115,337 L114,337 C113.448,337 113,337.448 113,338 C113,338.553 113.448,339 114,339 L118,339 C118.552,339 119,338.553 119,338 C119,337.448 118.552,337 118,337 L117,337 L117,334.955 C121.937,334.51 126.117,330.799 127,326 L127,326 Z\"\n />\n </g>\n </svg>\n <!-- Microphone icon (muted) -->\n <svg\n *ngIf=\"isMicMuted\"\n width=\"24\"\n height=\"24\"\n viewBox=\"-5 0 32 32\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"currentColor\"\n >\n <g transform=\"translate(-105, -307)\">\n <path\n d=\"M111,314 C111,311.238 113.239,309 116,309 C118.761,309 121,311.238 121,314 L121,324 C121,326.762 118.761,329 116,329 C113.239,329 111,326.762 111,324 L111,314 L111,314 Z M116,331 C119.866,331 123,327.866 123,324 L123,314 C123,310.134 119.866,307 116,307 C112.134,307 109,310.134 109,314 L109,324 C109,327.866 112.134,331 116,331 L116,331 Z M127,326 L125,326 C124.089,330.007 120.282,333 116,333 C111.718,333 107.911,330.007 107,326 L105,326 C105.883,330.799 110.063,334.51 115,334.955 L115,337 L114,337 C113.448,337 113,337.448 113,338 C113,338.553 113.448,339 114,339 L118,339 C118.552,339 119,338.553 119,338 C119,337.448 118.552,337 118,337 L117,337 L117,334.955 C121.937,334.51 126.117,330.799 127,326 L127,326 Z\"\n />\n </g>\n <path\n d=\"M2 2 L30 30\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n <span class=\"control-label\">Mute</span>\n </div>\n\n <div\n style=\"\n display: flex;\n align-items: center;\n gap: 2px;\n flex-direction: column;\n \"\n >\n <button\n class=\"control-btn end-call-btn\"\n (click)=\"hangUp()\"\n type=\"button\"\n title=\"End Call\"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M18 6L6 18M6 6L18 18\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n <span class=\"control-label\">End Call</span>\n </div>\n </div>\n </div>\n</div>\n",
168
- styles: [":host{display:block}.voice-agent-modal-overlay{align-items:flex-end;backdrop-filter:blur(4px);background:rgba(0,0,0,.5);bottom:0;display:flex;font-family:Segoe UI,Tahoma,Geneva,Verdana,sans-serif;justify-content:flex-end;left:0;padding:24px;position:fixed;right:0;top:0;z-index:99999}.voice-container.voice-agent-modal{align-items:center;animation:modalEnter .3s ease-out;background:#fff;border-radius:30px;box-shadow:0 10px 40px rgba(0,0,0,.1);display:flex;flex-direction:column;max-width:440px;min-height:600px;padding:30px;position:relative;text-align:center;width:100%}@keyframes modalEnter{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.header{justify-content:space-between;margin-bottom:5px;width:100%}.header,.header-left{align-items:center;display:flex}.header-left{gap:8px}.header-icon{align-items:center;background:#0f172a;border-radius:50%;color:#fff;display:flex;height:28px;justify-content:center;width:28px}.header-title{color:#0f172a;font-size:18px;font-weight:500}.close-button{align-items:center;background:none;border:none;color:#0f172a;cursor:pointer;display:flex;justify-content:center;padding:8px;transition:color .2s}.close-button:hover{color:#475569}.avatar-section{margin-bottom:24px;position:relative}.avatar-wrapper{align-items:center;background:#0ea5a4;background:linear-gradient(135deg,#ccfbf1,#0ea5a4);border-radius:50%;display:flex;height:180px;justify-content:center;padding:6px;position:relative;width:180px}.avatar-image{-o-object-fit:cover;border:4px solid #fff;border-radius:50%;height:100%;object-fit:cover;width:100%}.avatar-glow{background:radial-gradient(circle,rgba(14,165,164,.2) 0,transparent 70%);height:240px;left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity .4s ease;width:240px;z-index:-1}.avatar-glow.glow-talking{animation:glowPulse 1.5s ease-in-out infinite;background:radial-gradient(circle,rgba(14,165,164,.35) 0,transparent 65%);height:280px;width:280px}.avatar-glow.glow-listening{background:radial-gradient(circle,rgba(99,102,241,.25) 0,transparent 65%)}@keyframes glowPulse{0%,to{opacity:.7;transform:translate(-50%,-50%) scale(1)}50%{opacity:1;transform:translate(-50%,-50%) scale(1.08)}}.avatar-wrapper.speaking{animation:avatarPulse 1.4s ease-in-out infinite}.avatar-wrapper.listening{animation:avatarListenPulse 1.8s ease-in-out infinite}@keyframes avatarPulse{0%,to{box-shadow:0 0 0 0 rgba(14,165,164,.5)}50%{box-shadow:0 0 0 18px rgba(14,165,164,0)}}@keyframes avatarListenPulse{0%,to{box-shadow:0 0 0 0 rgba(99,102,241,.4)}50%{box-shadow:0 0 0 14px rgba(99,102,241,0)}}.particles-container{height:0;left:50%;pointer-events:none;position:absolute;top:50%;width:0;z-index:2}.particle{animation:particleOrbit 2.4s ease-in-out infinite;animation-delay:var(--delay,0s);background:#0ea5a4;border-radius:50%;height:7px;opacity:0;position:absolute;transform-origin:0 0;width:7px}@keyframes particleOrbit{0%{opacity:0;transform:rotate(calc(var(--i, 0)*22.5deg)) translateY(-108px) scale(.4)}25%{opacity:.9}75%{opacity:.9}to{opacity:0;transform:rotate(calc(var(--i, 0)*22.5deg + 45deg)) translateY(-108px) scale(.4)}}.agent-info{margin-bottom:40px}.agent-name{align-items:center;color:#0f172a;display:flex;font-size:24px;font-weight:700;gap:8px;justify-content:center;margin-bottom:8px}.ai-badge{background:#0ea5a4;border-radius:6px;color:#fff;font-size:10px;font-weight:700;padding:2px 6px}.agent-role{color:#0f172a;font-size:16px;font-weight:500;margin:0}.start-call-section{align-items:center;display:flex;flex-direction:column;gap:16px;margin-bottom:24px}.error-message{color:#dc2626;font-size:14px;margin:0}.start-call-button{background:#0ea5a4;border:none;border-radius:12px;color:#fff;cursor:pointer;font-size:16px;font-weight:600;padding:14px 32px;transition:background .2s}.start-call-button:hover:not(:disabled){background:#0d9488}.start-call-button:disabled{cursor:not-allowed!important;opacity:.7}.status-indicator{justify-content:center;margin-bottom:10px}.status-connecting,.status-indicator{align-items:center;display:flex;gap:12px}.spinner{animation:spin 1s linear infinite;color:#0ea5a4}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.status-text{color:#0f172a;font-size:16px;font-weight:400;transition:color .25s ease}.status-text.status-talking{color:#0ea5a4;font-weight:500}.status-text.status-listening{color:#2a2a2c;font-weight:500}.status-text.status-processing{color:#94a3b8}.status-timer{color:#0f172a;font-size:16px;font-weight:500}.voice-visualizer{align-items:center;display:flex;gap:3px;height:18px}.vbar{animation:vbarBounce 1s ease-in-out infinite;background:#0ea5a4;border-radius:2px;height:6px;width:3px}.vbar:first-child{animation-delay:0s}.vbar:nth-child(2){animation-delay:.15s}.vbar:nth-child(3){animation-delay:.3s}.vbar:nth-child(4){animation-delay:.45s}@keyframes vbarBounce{0%,to{height:4px;opacity:.5}50%{height:16px;opacity:1}}.processing-dots{align-items:center;display:flex;gap:4px}.processing-dots span{animation:dotFade 1.2s ease-in-out infinite;background:#94a3b8;border-radius:50%;display:inline-block;height:5px;width:5px}.processing-dots span:first-child{animation-delay:0s}.processing-dots span:nth-child(2){animation-delay:.2s}.processing-dots span:nth-child(3){animation-delay:.4s}@keyframes dotFade{0%,80%,to{opacity:.4;transform:scale(.8)}40%{opacity:1;transform:scale(1.2)}}.status-connected{align-items:center;display:flex;flex-direction:column;gap:4px}.status-inline .status-inline-row{align-items:center;flex-direction:row;gap:8px}.call-ended-section{align-items:center;display:flex;flex-direction:column;gap:16px;margin-bottom:24px}.call-ended-status{align-items:center;color:#0f172a;display:flex;font-size:16px;gap:8px;justify-content:center;margin:0}.call-ended-status .status-text{font-weight:400}.call-ended-status .status-timer{font-weight:500}.call-ended-controls{align-items:center;display:flex;flex-wrap:wrap;gap:16px;justify-content:center}.action-btn{align-items:center;background:#fff;border:1px solid #e2e8f0;border-radius:24px;color:#0f172a;cursor:pointer;display:flex;font-size:14px;font-weight:500;gap:8px;padding:12px 24px;transition:background .2s ease}.action-btn:hover{background:#f8fafc}.waveform-container{margin-bottom:10px;padding:0 8px}.waveform-bars,.waveform-container{align-items:center;display:flex;height:56px;justify-content:center;width:100%}.waveform-bars{gap:2px}.waveform-bar{background:#cbd5e1;border-radius:99px;flex:0 0 2px;min-height:2px;transition:height .1s ease-out;width:2px}.waveform-bar.active{background:linear-gradient(180deg,#0ea5a4,#0d9488);box-shadow:0 0 4px rgba(14,165,164,.5)}.controls{gap:24px;width:100%}.control-btn,.controls{align-items:center;display:flex;justify-content:center}.control-btn{border:none;border-radius:50%;cursor:pointer;flex-direction:column;gap:4px;height:60px;transition:transform .2s ease;width:60px}.control-btn:hover{transform:scale(1.05)}.control-btn:active{transform:scale(.95)}.control-label{color:#0f172a;font-size:12px;font-weight:500}.mic-btn{background:#e2e8f0}.mic-btn,.mic-btn .control-label{color:#475569}.mic-btn.muted{background:#e2e8f0;color:#475569}.end-call-btn{background:#ef4444;color:#fff}.end-call-btn .control-label{color:#fff}.end-call-btn:hover{background:#dc2626}"]
169
- },] }
170
- ];
171
- VoiceAgentModalComponent.ctorParameters = () => [
172
- { type: VoiceAgentService },
173
- { type: AudioAnalyzerService },
174
- { type: Injector }
175
- ];
176
- VoiceAgentModalComponent.propDecorators = {
177
- close: [{ type: Output }],
178
- apiUrl: [{ type: Input }],
179
- token: [{ type: Input }],
180
- botId: [{ type: Input }],
181
- conversationId: [{ type: Input }],
182
- apiKey: [{ type: Input }],
183
- eventToken: [{ type: Input }],
184
- eventId: [{ type: Input }],
185
- eventUrl: [{ type: Input }],
186
- domainAuthority: [{ type: Input }],
187
- agentName: [{ type: Input }],
188
- agentRole: [{ type: Input }],
189
- agentAvatar: [{ type: Input }],
190
- usersApiUrl: [{ type: Input }]
191
- };
192
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidm9pY2UtYWdlbnQtbW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Ii9Vc2Vycy9yb2hpdHRoYWt1ci9oaXZlLWdwdC9IaXZlQUktUGFja2FnZXMvQW5ndWxhci9wcm9qZWN0cy9oaXZlZ3B0L2V2ZW50c2dwdC1hbmd1bGFyL3NyYy8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL3ZvaWNlLWFnZW50L2NvbXBvbmVudHMvdm9pY2UtYWdlbnQtbW9kYWwvdm9pY2UtYWdlbnQtbW9kYWwuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFcEcsT0FBTyxFQUFFLGlCQUFpQixFQUFhLE1BQU0sb0NBQW9DLENBQUM7QUFDbEYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDN0UsT0FBTyxFQUFFLGtCQUFrQixFQUFFLDBCQUEwQixFQUFvQixNQUFNLDBCQUEwQixDQUFDO0FBTzVHLE1BQU0sT0FBTyx3QkFBd0I7SUFtQm5DLFlBQ1MsaUJBQW9DLEVBQ3BDLGFBQW1DLEVBQ2xDLFFBQWtCO1FBRm5CLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFDcEMsa0JBQWEsR0FBYixhQUFhLENBQXNCO1FBQ2xDLGFBQVEsR0FBUixRQUFRLENBQVU7UUFyQmxCLFVBQUssR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBS2xDLFdBQU0sR0FBVyxFQUFFLENBQUM7UUFDcEIsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUN4QixZQUFPLEdBQVcsRUFBRSxDQUFDO1FBQ3JCLGFBQVEsR0FBVyxFQUFFLENBQUM7UUFDdEIsb0JBQWUsR0FBVyxXQUFXLENBQUM7UUFDdEMsY0FBUyxHQUFXLGNBQWMsQ0FBQztRQUNuQyxjQUFTLEdBQVcscUJBQXFCLENBQUM7UUFFMUMsZ0JBQVcs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RGVzdHJveSwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIEluamVjdG9yIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFZvaWNlQWdlbnRTZXJ2aWNlLCBDYWxsU3RhdGUgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy92b2ljZS1hZ2VudC5zZXJ2aWNlJztcbmltcG9ydCB7IEF1ZGlvQW5hbHl6ZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvYXVkaW8tYW5hbHl6ZXIuc2VydmljZSc7XG5pbXBvcnQgeyBWT0lDRV9NT0RBTF9DT05GSUcsIFZPSUNFX01PREFMX0NMT1NFX0NBTExCQUNLLCBWb2ljZU1vZGFsQ29uZmlnIH0gZnJvbSAnLi4vLi4vdm9pY2UtbW9kYWwtdG9rZW5zJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnaGl2ZWdwdC12b2ljZS1hZ2VudC1tb2RhbCcsXG4gIHRlbXBsYXRlVXJsOiAnLi92b2ljZS1hZ2VudC1tb2RhbC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3ZvaWNlLWFnZW50LW1vZGFsLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgVm9pY2VBZ2VudE1vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBAT3V0cHV0KCkgY2xvc2UgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIEBJbnB1dCgpIGFwaVVybCE6IHN0cmluZztcbiAgQElucHV0KCkgdG9rZW4hOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGJvdElkITogc3RyaW5nO1xuICBASW5wdXQoKSBjb252ZXJzYXRpb25JZCE6IHN0cmluZztcbiAgQElucHV0KCkgYXBpS2V5OiBzdHJpbmcgPSAnJztcbiAgQElucHV0KCkgZXZlbnRUb2tlbjogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGV2ZW50SWQ6IHN0cmluZyA9ICcnO1xuICBASW5wdXQoKSBldmVudFVybDogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpIGRvbWFpbkF1dGhvcml0eTogc3RyaW5nID0gJ3Byb2QtbGl0ZSc7XG4gIEBJbnB1dCgpIGFnZW50TmFtZTogc3RyaW5nID0gJ0FJIEFzc2lzdGFudCc7XG4gIEBJbnB1dCgpIGFnZW50Um9sZTogc3RyaW5nID0gJ0FJIEFnZW50IFNwZWNpYWxpc3QnO1xuICBASW5wdXQoKSBhZ2VudEF2YXRhcj86IHN0cmluZztcbiAgQElucHV0KCkgdXNlcnNBcGlVcmw6IHN0cmluZyA9ICcnO1xuXG4gIHByaXZhdGUgaW5qZWN0ZWRDb25maWc6IFZvaWNlTW9kYWxDb25maWcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBvbkNsb3NlQ2FsbGJhY2s6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyB2b2ljZUFnZW50U2VydmljZTogVm9pY2VBZ2VudFNlcnZpY2UsXG4gICAgcHVibGljIGF1ZGlvQW5hbHl6ZXI6IEF1ZGlvQW5hbHl6ZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yXG4gICkge31cblxuICAvKiogSGFyZGNvZGVkIHZvaWNlIGFnZW50IGF2YXRhciAoTmlhKS4gKi9cbiAgcmVhZG9ubHkgZGlzcGxheUF2YXRhclVybCA9ICdodHRwczovL3d3dy5qb3Rmb3JtLmNvbS91cGxvYWRzL21laG1ldGthcmFrYXNsaS9mb3JtX2ZpbGVzLzE1NjQ1OTM2Njc2NzZhOGU4NWYyMzc1OC44Njk0NTUzN19pY29uLnBuZyc7XG5cbiAgY2FsbFN0YXRlOiBDYWxsU3RhdGUgPSAnaWRsZSc7XG4gIHN0YXR1c1RleHQ6IHN0cmluZyA9ICcnO1xuICBkdXJhdGlvbjogc3RyaW5nID0gJzAwOjAwJztcbiAgaXNNaWNNdXRlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBpc1VzZXJTcGVha2luZzogYm9vbGVhbiA9IGZhbHNlO1xuICBhdWRpb0xldmVsczogbnVtYmVyW10gPSBbXTtcblxuICAvKiogVHJ1ZSB3aGlsZSB0aGUgYm90IGlzIHNwZWFraW5nIOKAlCBkcml2ZXMgYXZhdGFyIHB1bHNlIGFuaW1hdGlvbiBhbmQgdm9pY2UgdmlzdWFsaXplci4gKi9cbiAgZ2V0IGlzQm90VGFsa2luZygpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuY2FsbFN0YXRlID09PSAndGFsa2luZyc7IH1cblxuICAvKiogVHJ1ZSB3aGlsZSB0aGUgdXNlciBpcyBhY3RpdmVseSBzcGVha2luZyDigJQgZHJpdmVzIHdhdmVmb3JtIGFjdGl2ZSBjb2xvci4gKi9cbiAgZ2V0IGlzVXNlckFjdGl2ZSgpOiBib29sZWFuIHsgcmV0dXJuIHRoaXMuY2FsbFN0YXRlID09PSAnbGlzdGVuaW5nJyAmJiB0aGlzLmlzVXNlclNwZWFraW5nICYmICF0aGlzLmlzTWljTXV0ZWQ7IH1cblxuICAvKiogVHJ1ZSBkdXJpbmcgdGhlIGJyaWVmIHByb2Nlc3NpbmcgcGF1c2UgYmV0d2VlbiB1c2VyIHNwZWVjaCBhbmQgYm90IHJlc3BvbnNlLiAqL1xuICBnZXQgaXNQcm9jZXNzaW5nKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5jYWxsU3RhdGUgPT09ICdjb25uZWN0ZWQnICYmIHRoaXMuc3RhdHVzVGV4dCA9PT0gJ1Byb2Nlc3NpbmcuLi4nOyB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIFdoZW4gb3BlbmVkIHZpYSBPdmVybGF5LCBjb25maWcgaXMgcHJvdmlkZWQgYnkgaW5qZWN0aW9uXG4gICAgdGhpcy5pbmplY3RlZENvbmZpZyA9IHRoaXMuaW5qZWN0b3IuZ2V0KFZPSUNFX01PREFMX0NPTkZJRywgbnVsbCk7XG4gICAgdGhpcy5vbkNsb3NlQ2FsbGJhY2sgPSB0aGlzLmluamVjdG9yLmdldChWT0lDRV9NT0RBTF9DTE9TRV9DQUxMQkFDSywgbnVsbCk7XG4gICAgaWYgKHRoaXMuaW5qZWN0ZWRDb25maWcpIHtcbiAgICAgIHRoaXMuYXBpVXJsID0gdGhpcy5pbmplY3RlZENvbmZpZy5hcGlVcmw7XG4gICAgICB0aGlzLnRva2VuID0gdGhpcy5pbmplY3RlZENvbmZpZy50b2tlbjtcbiAgICAgIHRoaXMuYm90SWQgPSB0aGlzLmluamVjdGVkQ29uZmlnLmJvdElkO1xuICAgICAgdGhpcy5jb252ZXJzYXRpb25JZCA9IHRoaXMuaW5qZWN0ZWRDb25maWcuY29udmVyc2F0aW9uSWQ7XG4gICAgICB0aGlzLmFwaUtleSA9IHRoaXMuaW5qZWN0ZWRDb25maWcuYXBpS2V5ID8/ICcnO1xuICAgICAgdGhpcy5ldmVudFRva2VuID0gdGhpcy5pbmplY3RlZENvbmZpZy5ldmVudFRva2VuID8/ICcnO1xuICAgICAgdGhpcy5ldmVudElkID0gdGhpcy5pbmplY3RlZENvbmZpZy5ldmVudElkID8/ICcnO1xuICAgICAgdGhpcy5ldmVudFVybCA9IHRoaXMuaW5qZWN0ZWRDb25maWcuZXZlbnRVcmwgPz8gJyc7XG4gICAgICB0aGlzLmRvbWFpbkF1dGhvcml0eSA9IHRoaXMuaW5qZWN0ZWRDb25maWcuZG9tYWluQXV0aG9yaXR5ID8/ICdwcm9kLWxpdGUnO1xuICAgICAgdGhpcy5hZ2VudE5hbWUgPSB0aGlzLmluamVjdGVkQ29uZmlnLmFnZW50TmFtZSA/PyB0aGlzLmFnZW50TmFtZTtcbiAgICAgIHRoaXMuYWdlbnRSb2xlID0gdGhpcy5pbmplY3RlZENvbmZpZy5hZ2VudFJvbGUgPz8gdGhpcy5hZ2VudFJvbGU7XG4gICAgICB0aGlzLmFnZW50QXZhdGFyID0gdGhpcy5pbmplY3RlZENvbmZpZy5hZ2VudEF2YXRhcjtcbiAgICAgIHRoaXMudXNlcnNBcGlVcmwgPSB0aGlzLmluamVjdGVkQ29uZmlnLnVzZXJzQXBpVXJsID8/IHRoaXMudXNlcnNBcGlVcmw7XG4gICAgfVxuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnZvaWNlQWdlbnRTZXJ2aWNlLmNhbGxTdGF0ZSQuc3Vic2NyaWJlKHN0YXRlID0+IHtcbiAgICAgICAgdGhpcy5jYWxsU3RhdGUgPSBzdGF0ZTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy52b2ljZUFnZW50U2VydmljZS5zdGF0dXNUZXh0JC5zdWJzY3JpYmUodGV4dCA9PiB7XG4gICAgICAgIHRoaXMuc3RhdHVzVGV4dCA9IHRleHQ7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMudm9pY2VBZ2VudFNlcnZpY2UuZHVyYXRpb24kLnN1YnNjcmliZShkdXJhdGlvbiA9PiB7XG4gICAgICAgIHRoaXMuZHVyYXRpb24gPSBkdXJhdGlvbjtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy52b2ljZUFnZW50U2VydmljZS5pc01pY011dGVkJC5zdWJzY3JpYmUobXV0ZWQgPT4ge1xuICAgICAgICB0aGlzLmlzTWljTXV0ZWQgPSBtdXRlZDtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy52b2ljZUFnZW50U2VydmljZS5pc1VzZXJTcGVha2luZyQuc3Vic2NyaWJlKHNwZWFraW5nID0+IHtcbiAgICAgICAgdGhpcy5pc1VzZXJTcGVha2luZyA9IHNwZWFraW5nO1xuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnZvaWNlQWdlbnRTZXJ2aWNlLmF1ZGlvTGV2ZWxzJC5zdWJzY3JpYmUobGV2ZWxzID0+IHtcbiAgICAgICAgdGhpcy5hdWRpb0xldmVscyA9IGxldmVscztcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIEFsd2F5cyBzdGFydCBmcm9tIGEgZnJlc2ggdm9pY2Ugc2Vzc2lvbiB0byBhdm9pZCBzdGFsZS9kaXNjb25uZWN0ZWQgc3RhdGUgZmxhc2hlcy5cbiAgICB2b2lkIHRoaXMub3BlbkZyZXNoQ2FsbFNlc3Npb24oKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKHN1YiA9PiBzdWIudW5zdWJzY3JpYmUoKSk7XG4gICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gIH1cblxuICBpc0Nvbm5lY3Rpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBhc3luYyBzdGFydENhbGwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuaXNDb25uZWN0aW5nIHx8ICh0aGlzLmNhbGxTdGF0ZSAhPT0gJ2lkbGUnICYmIHRoaXMuY2FsbFN0YXRlICE9PSAnZW5kZWQnKSkgcmV0dXJuO1xuICAgIHRoaXMuaXNDb25uZWN0aW5nID0gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy52b2ljZUFnZW50U2VydmljZS5jb25uZWN0KFxuICAgICAgICB0aGlzLmFwaVVybCxcbiAgICAgICAgdGhpcy50b2tlbixcbiAgICAgICAgdGhpcy5ib3RJZCxcbiAgICAgICAgdGhpcy5jb252ZXJzYXRpb25JZCxcbiAgICAgICAgdGhpcy5hcGlLZXksXG4gICAgICAgIHRoaXMuZXZlbnRUb2tlbixcbiAgICAgICAgdGhpcy5ldmVudElkLFxuICAgICAgICB0aGlzLmV2ZW50VXJsLFxuICAgICAgICB0aGlzLmRvbWFpbkF1dGhvcml0eSxcbiAgICAgICAgdGhpcy51c2Vyc0FwaVVybCB8fCB1bmRlZmluZWQsXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gY29ubmVjdCB2b2ljZSBhZ2VudDonLCBlcnJvcik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuaXNDb25uZWN0aW5nID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZGlzY29ubmVjdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnZvaWNlQWdlbnRTZXJ2aWNlLmRpc2Nvbm5lY3QoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgb3BlbkZyZXNoQ2FsbFNlc3Npb24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy52b2ljZUFnZW50U2VydmljZS5wcmVwYXJlRnJlc2hTZXNzaW9uKCk7XG4gICAgYXdhaXQgdGhpcy5zdGFydENhbGwoKTtcbiAgfVxuXG4gIHRvZ2dsZU1pYygpOiB2b2lkIHtcbiAgICB0aGlzLnZvaWNlQWdlbnRTZXJ2aWNlLnRvZ2dsZU1pYygpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcCBhdWRpbyBsZXZlbCAoMOKAkzEwMCkgdG8gd2F2ZWZvcm0gYmFyIGhlaWdodCBpbiBweCB3aXRoIGEgZ2F1c3NpYW5cbiAgICogYmVsbC1jdXJ2ZSBlbnZlbG9wZSBzbyBjZW50cmUgYmFycyBhcmUgdGFsbGVzdCBhbmQgZWRnZSBiYXJzIGFwcGVhclxuICAgKiBhcyB0aW55IGRvdHMg4oCUIG1hdGNoaW5nIHRoZSBhdWRpby13YXZlZm9ybSByZWZlcmVuY2UgZGVzaWduLlxuICAgKi9cbiAgZ2V0V2F2ZWZvcm1IZWlnaHQobGV2ZWw6IG51bWJlciwgaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgbiA9IE1hdGgubWluKDEwMCwgTWF0aC5tYXgoMCwgbGV2ZWwgPz8gMCkpO1xuICAgIGNvbnN0IHRvdGFsID0gdGhpcy5hdWRpb0xldmVscy5sZW5ndGggfHwgNjA7XG4gICAgY29uc3QgY2VudGVyID0gKHRvdGFsIC0gMSkgLyAyO1xuICAgIGNvbnN0IHNpZ21hID0gdG90YWwgLyA1O1xuICAgIGNvbnN0IGVudmVsb3BlID0gTWF0aC5leHAoLU1hdGgucG93KGluZGV4IC0gY2VudGVyLCAyKSAvICgyICogc2lnbWEgKiBzaWdtYSkpO1xuICAgIC8vIE1pbmltdW0gaGVpZ2h0IHNjYWxlcyB3aXRoIGVudmVsb3BlIHNvIGVkZ2VzIHNob3cgYXMgZG90cyBldmVuIGluIHNpbGVuY2VcbiAgICBjb25zdCBtaW5IZWlnaHQgPSAyICsgZW52ZWxvcGUgKiAzO1xuICAgIGNvbnN0IG1heEhlaWdodCA9IDQgKyBlbnZlbG9wZSAqIDM4O1xuICAgIHJldHVybiBtaW5IZWlnaHQgKyAobiAvIDEwMCkgKiAobWF4SGVpZ2h0IC0gbWluSGVpZ2h0KTtcbiAgfVxuXG4gIC8qKiBTdGF0dXMgbGFiZWwgZm9yIGFjdGl2ZSBjYWxsIOKAlCBkcml2ZW4gYnkgY2FsbFN0YXRlICsgc2VydmljZSBzdGF0dXNUZXh0LiAqL1xuICBnZXQgc3RhdHVzTGFiZWwoKTogc3RyaW5nIHtcbiAgICBzd2l0Y2ggKHRoaXMuY2FsbFN0YXRlKSB7XG4gICAgICBjYXNlICdjb25uZWN0aW5nJzogcmV0dXJuICdDb25uZWN0aW5nLi4uJztcbiAgICAgIGNhc2UgJ3RhbGtpbmcnOiAgICByZXR1cm4gJ1RhbGtpbmcuLi4nO1xuICAgICAgY2FzZSAnbGlzdGVuaW5nJzogIHJldHVybiAnTGlzdGVuaW5nLi4uJztcbiAgICAgIC8vICdjb25uZWN0ZWQnIGNvdmVyczogaW5pdGlhbCBjb25uZWN0LCBiZXR3ZWVuIHR1cm5zIChMaXN0ZW5pbmcgLyBQcm9jZXNzaW5nKVxuICAgICAgY2FzZSAnY29ubmVjdGVkJzogIHJldHVybiB0aGlzLnN0YXR1c1RleHQgfHwgJ0Nvbm5lY3RlZCc7XG4gICAgICBkZWZhdWx0OiAgICAgICAgICAgcmV0dXJuIHRoaXMuc3RhdHVzVGV4dCB8fCAnJztcbiAgICB9XG4gIH1cblxuICAvKiogQ2FsbCBBZ2FpbjogcmVzZXQgdG8gaWRsZSB0aGVuIHN0YXJ0IGEgbmV3IGNhbGwuICovXG4gIGFzeW5jIGNhbGxBZ2FpbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLm9wZW5GcmVzaENhbGxTZXNzaW9uKCk7XG4gIH1cblxuICAvKiogQmFjayB0byBDaGF0OiBjbG9zZSBtb2RhbCBhbmQgZGlzY29ubmVjdC4gKi9cbiAgYmFja1RvQ2hhdCgpOiB2b2lkIHtcbiAgICB0aGlzLmVuZENhbGwoKTtcbiAgfVxuXG4gIC8qKiBFbmQgY2FsbCBidXQga2VlcCBtb2RhbCBvcGVuIHRvIHNob3cgQ2FsbCBFbmRlZCArIENhbGwgQWdhaW4gLyBCYWNrIHRvIENoYXQuICovXG4gIGhhbmdVcCgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2Nvbm5lY3QoKTtcbiAgfVxuXG4gIGFzeW5jIGVuZENhbGwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgdGhpcy5vbkNsb3NlQ2FsbGJhY2s/LigpO1xuICAgIHRoaXMuY2xvc2UuZW1pdCgpO1xuICB9XG59XG4iXX0=
@@ -1,125 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { BehaviorSubject } from 'rxjs';
3
- import * as i0 from "@angular/core";
4
- /**
5
- * Audio analyzer for waveform visualization and local (mic) speaking detection.
6
- * VoiceAgentService may combine this with WebSocket server events for call state.
7
- */
8
- export class AudioAnalyzerService {
9
- constructor() {
10
- this.audioContext = null;
11
- this.analyserNode = null;
12
- this.dataArray = null;
13
- this.animationFrameId = null;
14
- this.isRunning = false;
15
- this.audioLevelsSubject = new BehaviorSubject([]);
16
- this.isUserSpeakingSubject = new BehaviorSubject(false);
17
- // Adaptive noise floor detection
18
- this.noiseFloor = 0;
19
- this.noiseFloorSamples = [];
20
- this.NOISE_FLOOR_SAMPLE_COUNT = 30;
21
- this.SPEAKING_THRESHOLD_MULTIPLIER = 2.5;
22
- this.WAVEFORM_BAR_COUNT = 60;
23
- // Amplify raw amplitude so normal speech (±10–20 units) maps to visible levels
24
- this.SENSITIVITY_MULTIPLIER = 5;
25
- this.audioLevels$ = this.audioLevelsSubject.asObservable();
26
- this.isUserSpeaking$ = this.isUserSpeakingSubject.asObservable();
27
- }
28
- start(stream) {
29
- if (this.isRunning) {
30
- this.stop();
31
- }
32
- try {
33
- this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
34
- const source = this.audioContext.createMediaStreamSource(stream);
35
- this.analyserNode = this.audioContext.createAnalyser();
36
- this.analyserNode.fftSize = 2048;
37
- this.analyserNode.smoothingTimeConstant = 0.4;
38
- const bufferLength = this.analyserNode.frequencyBinCount;
39
- this.dataArray = new Uint8Array(bufferLength);
40
- source.connect(this.analyserNode);
41
- this.isRunning = true;
42
- this.noiseFloorSamples = [];
43
- this.noiseFloor = 0;
44
- this.analyze();
45
- }
46
- catch (error) {
47
- console.error('Error starting audio analyzer:', error);
48
- this.stop();
49
- }
50
- }
51
- stop() {
52
- this.isRunning = false;
53
- if (this.animationFrameId !== null) {
54
- cancelAnimationFrame(this.animationFrameId);
55
- this.animationFrameId = null;
56
- }
57
- if (this.analyserNode) {
58
- this.analyserNode.disconnect();
59
- this.analyserNode = null;
60
- }
61
- if (this.audioContext && this.audioContext.state !== 'closed') {
62
- this.audioContext.close().catch(console.error);
63
- this.audioContext = null;
64
- }
65
- this.dataArray = null;
66
- this.audioLevelsSubject.next([]);
67
- this.isUserSpeakingSubject.next(false);
68
- }
69
- analyze() {
70
- if (!this.isRunning || !this.analyserNode || !this.dataArray) {
71
- return;
72
- }
73
- this.analyserNode.getByteTimeDomainData(this.dataArray);
74
- // Calculate RMS (Root Mean Square) volume
75
- const rms = this.calculateRMS(this.dataArray);
76
- // Learn noise floor during initial samples
77
- if (this.noiseFloorSamples.length < this.NOISE_FLOOR_SAMPLE_COUNT) {
78
- this.noiseFloorSamples.push(rms);
79
- if (this.noiseFloorSamples.length === this.NOISE_FLOOR_SAMPLE_COUNT) {
80
- // Calculate average noise floor
81
- const sum = this.noiseFloorSamples.reduce((a, b) => a + b, 0);
82
- this.noiseFloor = sum / this.NOISE_FLOOR_SAMPLE_COUNT;
83
- }
84
- }
85
- else {
86
- // Update noise floor adaptively (moving average)
87
- this.noiseFloor = this.noiseFloor * 0.99 + rms * 0.01;
88
- }
89
- // Detect if user is speaking
90
- const threshold = this.noiseFloor * this.SPEAKING_THRESHOLD_MULTIPLIER;
91
- const isSpeaking = rms > threshold;
92
- this.isUserSpeakingSubject.next(isSpeaking);
93
- // Generate waveform bars
94
- const bars = this.generateWaveformBars(this.dataArray);
95
- this.audioLevelsSubject.next(bars);
96
- this.animationFrameId = requestAnimationFrame(() => this.analyze());
97
- }
98
- calculateRMS(data) {
99
- let sum = 0;
100
- for (let i = 0; i < data.length; i++) {
101
- const normalized = (data[i] - 128) / 128;
102
- sum += normalized * normalized;
103
- }
104
- return Math.sqrt(sum / data.length);
105
- }
106
- generateWaveformBars(data) {
107
- const bars = [];
108
- const step = Math.floor(data.length / this.WAVEFORM_BAR_COUNT);
109
- for (let i = 0; i < this.WAVEFORM_BAR_COUNT; i++) {
110
- const index = i * step;
111
- const value = data[index];
112
- // Normalize and amplify so quiet speech produces visible movement
113
- const normalized = Math.abs((value - 128) / 128) * 100 * this.SENSITIVITY_MULTIPLIER;
114
- bars.push(Math.min(100, Math.max(0, normalized)));
115
- }
116
- return bars;
117
- }
118
- }
119
- AudioAnalyzerService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AudioAnalyzerService_Factory() { return new AudioAnalyzerService(); }, token: AudioAnalyzerService, providedIn: "root" });
120
- AudioAnalyzerService.decorators = [
121
- { type: Injectable, args: [{
122
- providedIn: 'root'
123
- },] }
124
- ];
125
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaW8tYW5hbHl6ZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIvVXNlcnMvcm9oaXR0aGFrdXIvaGl2ZS1ncHQvSGl2ZUFJLVBhY2thZ2VzL0FuZ3VsYXIvcHJvamVjdHMvaGl2ZWdwdC9ldmVudHNncHQtYW5ndWxhci9zcmMvIiwic291cmNlcyI6WyJsaWIvY29tcG9uZW50cy92b2ljZS1hZ2VudC9zZXJ2aWNlcy9hdWRpby1hbmFseXplci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBYyxNQUFNLE1BQU0sQ0FBQzs7QUFFbkQ7OztHQUdHO0FBSUgsTUFBTSxPQUFPLG9CQUFvQjtJQUhqQztRQUlVLGlCQUFZLEdBQXdCLElBQUksQ0FBQztRQUN6QyxpQkFBWSxHQUF3QixJQUFJLENBQUM7UUFDekMsY0FBUyxHQUFzQixJQUFJLENBQUM7UUFDcEMscUJBQWdCLEdBQWtCLElBQUksQ0FBQztRQUN2QyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBRWxCLHVCQUFrQixHQUFHLElBQUksZUFBZSxDQUFXLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELDBCQUFxQixHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBRXBFLGlDQUFpQztRQUN6QixlQUFVLEdBQUcsQ0FBQyxDQUFDO1FBQ2Ysc0JBQWlCLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLDZCQUF3QixHQUFHLEVBQUUsQ0FBQztRQUM5QixrQ0FBNkIsR0FBRyxHQUFHLENBQUM7UUFDcEMsdUJBQWtCLEdBQUcsRUFBRSxDQUFDO1FBQ3pDLCtFQUErRTtRQUM5RCwyQkFBc0IsR0FBRyxDQUFDLENBQUM7UUFFNUMsaUJBQVksR0FBeUIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQzVFLG9CQUFlLEdBQXdCLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxZQUFZ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c291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogQXVkaW8gYW5hbHl6ZXIgZm9yIHdhdmVmb3JtIHZpc3VhbGl6YXRpb24gYW5kIGxvY2FsIChtaWMpIHNwZWFraW5nIGRldGVjdGlvbi5cbiAqIFZvaWNlQWdlbnRTZXJ2aWNlIG1heSBjb21iaW5lIHRoaXMgd2l0aCBXZWJTb2NrZXQgc2VydmVyIGV2ZW50cyBmb3IgY2FsbCBzdGF0ZS5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQXVkaW9BbmFseXplclNlcnZpY2Uge1xuICBwcml2YXRlIGF1ZGlvQ29udGV4dDogQXVkaW9Db250ZXh0IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgYW5hbHlzZXJOb2RlOiBBbmFseXNlck5vZGUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBkYXRhQXJyYXk6IFVpbnQ4QXJyYXkgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBhbmltYXRpb25GcmFtZUlkOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBpc1J1bm5pbmcgPSBmYWxzZTtcblxuICBwcml2YXRlIGF1ZGlvTGV2ZWxzU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyW10+KFtdKTtcbiAgcHJpdmF0ZSBpc1VzZXJTcGVha2luZ1N1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAvLyBBZGFwdGl2ZSBub2lzZSBmbG9vciBkZXRlY3Rpb25cbiAgcHJpdmF0ZSBub2lzZUZsb29yID0gMDtcbiAgcHJpdmF0ZSBub2lzZUZsb29yU2FtcGxlczogbnVtYmVyW10gPSBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBOT0lTRV9GTE9PUl9TQU1QTEVfQ09VTlQgPSAzMDtcbiAgcHJpdmF0ZSByZWFkb25seSBTUEVBS0lOR19USFJFU0hPTERfTVVMVElQTElFUiA9IDIuNTtcbiAgcHJpdmF0ZSByZWFkb25seSBXQVZFRk9STV9CQVJfQ09VTlQgPSA2MDtcbiAgLy8gQW1wbGlmeSByYXcgYW1wbGl0dWRlIHNvIG5vcm1hbCBzcGVlY2ggKMKxMTDigJMyMCB1bml0cykgbWFwcyB0byB2aXNpYmxlIGxldmVsc1xuICBwcml2YXRlIHJlYWRvbmx5IFNFTlNJVElWSVRZX01VTFRJUExJRVIgPSA1O1xuXG4gIGF1ZGlvTGV2ZWxzJDogT2JzZXJ2YWJsZTxudW1iZXJbXT4gPSB0aGlzLmF1ZGlvTGV2ZWxzU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgaXNVc2VyU3BlYWtpbmckOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5pc1VzZXJTcGVha2luZ1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG5cbiAgc3RhcnQoc3RyZWFtOiBNZWRpYVN0cmVhbSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzUnVubmluZykge1xuICAgICAgdGhpcy5zdG9wKCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuYXVkaW9Db250ZXh0ID0gbmV3ICh3aW5kb3cuQXVkaW9Db250ZXh0IHx8ICh3aW5kb3cgYXMgYW55KS53ZWJraXRBdWRpb0NvbnRleHQpKCk7XG4gICAgICBjb25zdCBzb3VyY2UgPSB0aGlzLmF1ZGlvQ29udGV4dC5jcmVhdGVNZWRpYVN0cmVhbVNvdXJjZShzdHJlYW0pO1xuICAgICAgXG4gICAgICB0aGlzLmFuYWx5c2VyTm9kZSA9IHRoaXMuYXVkaW9Db250ZXh0LmNyZWF0ZUFuYWx5c2VyKCk7XG4gICAgICB0aGlzLmFuYWx5c2VyTm9kZS5mZnRTaXplID0gMjA0ODtcbiAgICAgIHRoaXMuYW5hbHlzZXJOb2RlLnNtb290aGluZ1RpbWVDb25zdGFudCA9IDAuNDtcbiAgICAgIFxuICAgICAgY29uc3QgYnVmZmVyTGVuZ3RoID0gdGhpcy5hbmFseXNlck5vZGUuZnJlcXVlbmN5QmluQ291bnQ7XG4gICAgICB0aGlzLmRhdGFBcnJheSA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlckxlbmd0aCk7XG4gICAgICBcbiAgICAgIHNvdXJjZS5jb25uZWN0KHRoaXMuYW5hbHlzZXJOb2RlKTtcbiAgICAgIFxuICAgICAgdGhpcy5pc1J1bm5pbmcgPSB0cnVlO1xuICAgICAgdGhpcy5ub2lzZUZsb29yU2FtcGxlcyA9IFtdO1xuICAgICAgdGhpcy5ub2lzZUZsb29yID0gMDtcbiAgICAgIFxuICAgICAgdGhpcy5hbmFseXplKCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHN0YXJ0aW5nIGF1ZGlvIGFuYWx5emVyOicsIGVycm9yKTtcbiAgICAgIHRoaXMuc3RvcCgpO1xuICAgIH1cbiAgfVxuXG4gIHN0b3AoKTogdm9pZCB7XG4gICAgdGhpcy5pc1J1bm5pbmcgPSBmYWxzZTtcbiAgICBcbiAgICBpZiAodGhpcy5hbmltYXRpb25GcmFtZUlkICE9PSBudWxsKSB7XG4gICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLmFuaW1hdGlvbkZyYW1lSWQpO1xuICAgICAgdGhpcy5hbmltYXRpb25GcmFtZUlkID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5hbmFseXNlck5vZGUpIHtcbiAgICAgIHRoaXMuYW5hbHlzZXJOb2RlLmRpc2Nvbm5lY3QoKTtcbiAgICAgIHRoaXMuYW5hbHlzZXJOb2RlID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5hdWRpb0NvbnRleHQgJiYgdGhpcy5hdWRpb0NvbnRleHQuc3RhdGUgIT09ICdjbG9zZWQnKSB7XG4gICAgICB0aGlzLmF1ZGlvQ29udGV4dC5jbG9zZSgpLmNhdGNoKGNvbnNvbGUuZXJyb3IpO1xuICAgICAgdGhpcy5hdWRpb0NvbnRleHQgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZGF0YUFycmF5ID0gbnVsbDtcbiAgICB0aGlzLmF1ZGlvTGV2ZWxzU3ViamVjdC5uZXh0KFtdKTtcbiAgICB0aGlzLmlzVXNlclNwZWFraW5nU3ViamVjdC5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgYW5hbHl6ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNSdW5uaW5nIHx8ICF0aGlzLmFuYWx5c2VyTm9kZSB8fCAhdGhpcy5kYXRhQXJyYXkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmFuYWx5c2VyTm9kZS5nZXRCeXRlVGltZURvbWFpbkRhdGEodGhpcy5kYXRhQXJyYXkpO1xuICAgIFxuICAgIC8vIENhbGN1bGF0ZSBSTVMgKFJvb3QgTWVhbiBTcXVhcmUpIHZvbHVtZVxuICAgIGNvbnN0IHJtcyA9IHRoaXMuY2FsY3VsYXRlUk1TKHRoaXMuZGF0YUFycmF5KTtcbiAgICBcbiAgICAvLyBMZWFybiBub2lzZSBmbG9vciBkdXJpbmcgaW5pdGlhbCBzYW1wbGVzXG4gICAgaWYgKHRoaXMubm9pc2VGbG9vclNhbXBsZXMubGVuZ3RoIDwgdGhpcy5OT0lTRV9GTE9PUl9TQU1QTEVfQ09VTlQpIHtcbiAgICAgIHRoaXMubm9pc2VGbG9vclNhbXBsZXMucHVzaChybXMpO1xuICAgICAgaWYgKHRoaXMubm9pc2VGbG9vclNhbXBsZXMubGVuZ3RoID09PSB0aGlzLk5PSVNFX0ZMT09SX1NBTVBMRV9DT1VOVCkge1xuICAgICAgICAvLyBDYWxjdWxhdGUgYXZlcmFnZSBub2lzZSBmbG9vclxuICAgICAgICBjb25zdCBzdW0gPSB0aGlzLm5vaXNlRmxvb3JTYW1wbGVzLnJlZHVjZSgoYSwgYikgPT4gYSArIGIsIDApO1xuICAgICAgICB0aGlzLm5vaXNlRmxvb3IgPSBzdW0gLyB0aGlzLk5PSVNFX0ZMT09SX1NBTVBMRV9DT1VOVDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVXBkYXRlIG5vaXNlIGZsb29yIGFkYXB0aXZlbHkgKG1vdmluZyBhdmVyYWdlKVxuICAgICAgdGhpcy5ub2lzZUZsb29yID0gdGhpcy5ub2lzZUZsb29yICogMC45OSArIHJtcyAqIDAuMDE7XG4gICAgfVxuXG4gICAgLy8gRGV0ZWN0IGlmIHVzZXIgaXMgc3BlYWtpbmdcbiAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLm5vaXNlRmxvb3IgKiB0aGlzLlNQRUFLSU5HX1RIUkVTSE9MRF9NVUxUSVBMSUVSO1xuICAgIGNvbnN0IGlzU3BlYWtpbmcgPSBybXMgPiB0aHJlc2hvbGQ7XG4gICAgdGhpcy5pc1VzZXJTcGVha2luZ1N1YmplY3QubmV4dChpc1NwZWFraW5nKTtcblxuICAgIC8vIEdlbmVyYXRlIHdhdmVmb3JtIGJhcnNcbiAgICBjb25zdCBiYXJzID0gdGhpcy5nZW5lcmF0ZVdhdmVmb3JtQmFycyh0aGlzLmRhdGFBcnJheSk7XG4gICAgdGhpcy5hdWRpb0xldmVsc1N1YmplY3QubmV4dChiYXJzKTtcblxuICAgIHRoaXMuYW5pbWF0aW9uRnJhbWVJZCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLmFuYWx5emUoKSk7XG4gIH1cblxuICBwcml2YXRlIGNhbGN1bGF0ZVJNUyhkYXRhOiBVaW50OEFycmF5KTogbnVtYmVyIHtcbiAgICBsZXQgc3VtID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSAoZGF0YVtpXSAtIDEyOCkgLyAxMjg7XG4gICAgICBzdW0gKz0gbm9ybWFsaXplZCAqIG5vcm1hbGl6ZWQ7XG4gICAgfVxuICAgIHJldHVybiBNYXRoLnNxcnQoc3VtIC8gZGF0YS5sZW5ndGgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZVdhdmVmb3JtQmFycyhkYXRhOiBVaW50OEFycmF5KTogbnVtYmVyW10ge1xuICAgIGNvbnN0IGJhcnM6IG51bWJlcltdID0gW107XG4gICAgY29uc3Qgc3RlcCA9IE1hdGguZmxvb3IoZGF0YS5sZW5ndGggLyB0aGlzLldBVkVGT1JNX0JBUl9DT1VOVCk7XG4gICAgXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLldBVkVGT1JNX0JBUl9DT1VOVDsgaSsrKSB7XG4gICAgICBjb25zdCBpbmRleCA9IGkgKiBzdGVwO1xuICAgICAgY29uc3QgdmFsdWUgPSBkYXRhW2luZGV4XTtcbiAgICAgIC8vIE5vcm1hbGl6ZSBhbmQgYW1wbGlmeSBzbyBxdWlldCBzcGVlY2ggcHJvZHVjZXMgdmlzaWJsZSBtb3ZlbWVudFxuICAgICAgY29uc3Qgbm9ybWFsaXplZCA9IE1hdGguYWJzKCh2YWx1ZSAtIDEyOCkgLyAxMjgpICogMTAwICogdGhpcy5TRU5TSVRJVklUWV9NVUxUSVBMSUVSO1xuICAgICAgYmFycy5wdXNoKE1hdGgubWluKDEwMCwgTWF0aC5tYXgoMCwgbm9ybWFsaXplZCkpKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGJhcnM7XG4gIH1cbn1cbiJdfQ==