@hivegpt/hiveai-angular 0.0.607 → 0.0.609
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/esm2020/lib/components/chat-drawer/chat-drawer.component.mjs +7 -5
- package/esm2020/lib/components/voice-agent/services/audio-analyzer.service.mjs +6 -1
- package/esm2020/lib/components/voice-agent/services/voice-agent.service.mjs +59 -1
- package/fesm2015/hivegpt-hiveai-angular.mjs +71 -4
- package/fesm2015/hivegpt-hiveai-angular.mjs.map +1 -1
- package/fesm2020/hivegpt-hiveai-angular.mjs +69 -4
- package/fesm2020/hivegpt-hiveai-angular.mjs.map +1 -1
- package/lib/components/chat-drawer/chat-drawer.component.d.ts +1 -1
- package/lib/components/chat-drawer/chat-drawer.component.d.ts.map +1 -1
- package/lib/components/voice-agent/services/audio-analyzer.service.d.ts +1 -0
- package/lib/components/voice-agent/services/audio-analyzer.service.d.ts.map +1 -1
- package/lib/components/voice-agent/services/voice-agent.service.d.ts +9 -2
- package/lib/components/voice-agent/services/voice-agent.service.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -153,6 +153,11 @@ class AudioAnalyzerService {
|
|
|
153
153
|
this.audioLevelsSubject.next([]);
|
|
154
154
|
this.isUserSpeakingSubject.next(false);
|
|
155
155
|
}
|
|
156
|
+
resumeContextIfSuspended() {
|
|
157
|
+
if (!this.audioContext || this.audioContext.state !== 'suspended')
|
|
158
|
+
return;
|
|
159
|
+
this.audioContext.resume().catch((err) => console.warn('[HiveGpt Voice] AudioContext resume failed', err));
|
|
160
|
+
}
|
|
156
161
|
analyze() {
|
|
157
162
|
if (!this.isRunning || !this.analyserNode || !this.dataArray) {
|
|
158
163
|
return;
|
|
@@ -418,6 +423,8 @@ class VoiceAgentService {
|
|
|
418
423
|
this.lifecycleToken = 0;
|
|
419
424
|
this.subscriptions = new Subscription();
|
|
420
425
|
this.pcEventCleanup = [];
|
|
426
|
+
this.pageLifecycleCleanup = [];
|
|
427
|
+
this.wasInActiveCallBeforeHide = false;
|
|
421
428
|
this.callState$ = this.callStateSubject.asObservable();
|
|
422
429
|
this.statusText$ = this.statusTextSubject.asObservable();
|
|
423
430
|
this.duration$ = this.durationSubject.asObservable();
|
|
@@ -427,6 +434,13 @@ class VoiceAgentService {
|
|
|
427
434
|
this.userTranscript$ = this.userTranscriptSubject.asObservable();
|
|
428
435
|
this.botTranscript$ = this.botTranscriptSubject.asObservable();
|
|
429
436
|
this.subscriptions.add(this.audioAnalyzer.audioLevels$.pipe(throttleTime(50)).subscribe((levels) => this.ngZone.run(() => this.audioLevelsSubject.next(levels))));
|
|
437
|
+
this.registerPageLifecycleListeners();
|
|
438
|
+
}
|
|
439
|
+
ngOnDestroy() {
|
|
440
|
+
this.pageLifecycleCleanup.forEach((fn) => fn());
|
|
441
|
+
this.pageLifecycleCleanup = [];
|
|
442
|
+
this.subscriptions.unsubscribe();
|
|
443
|
+
void this.cleanupPipecatClient();
|
|
430
444
|
}
|
|
431
445
|
/** Reset to idle (e.g. when modal re-opens so user can click Start Call). */
|
|
432
446
|
resetToIdle() {
|
|
@@ -447,6 +461,7 @@ class VoiceAgentService {
|
|
|
447
461
|
this.durationSubject.next('00:00');
|
|
448
462
|
this.statusTextSubject.next('');
|
|
449
463
|
this.callStateSubject.next('idle');
|
|
464
|
+
this.wasInActiveCallBeforeHide = false;
|
|
450
465
|
await this.cleanupPipecatClient();
|
|
451
466
|
}
|
|
452
467
|
async connect(apiUrl, token, botId, conversationId, apiKey, eventToken, eventId, eventUrl, domainAuthority, usersApiUrl) {
|
|
@@ -678,6 +693,7 @@ class VoiceAgentService {
|
|
|
678
693
|
this.callStartTime = 0;
|
|
679
694
|
this.audioAnalyzer.stop();
|
|
680
695
|
this.stopBotAudio();
|
|
696
|
+
this.wasInActiveCallBeforeHide = false;
|
|
681
697
|
await this.cleanupPipecatClient();
|
|
682
698
|
this.callStateSubject.next('ended');
|
|
683
699
|
this.statusTextSubject.next('Call Ended');
|
|
@@ -729,6 +745,53 @@ class VoiceAgentService {
|
|
|
729
745
|
this.durationInterval = null;
|
|
730
746
|
}
|
|
731
747
|
}
|
|
748
|
+
registerPageLifecycleListeners() {
|
|
749
|
+
if (!isPlatformBrowser(this.platformId) || typeof window === 'undefined' || typeof document === 'undefined') {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
const onVisibilityChange = () => {
|
|
753
|
+
if (document.hidden) {
|
|
754
|
+
this.wasInActiveCallBeforeHide = this.isCallActiveState(this.callStateSubject.value);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (this.wasInActiveCallBeforeHide) {
|
|
758
|
+
this.wasInActiveCallBeforeHide = false;
|
|
759
|
+
this.recoverAfterPageRestore();
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
const onPageShow = (event) => {
|
|
763
|
+
if (event.persisted && this.isCallActiveState(this.callStateSubject.value)) {
|
|
764
|
+
this.recoverAfterPageRestore();
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
768
|
+
window.addEventListener('pageshow', onPageShow);
|
|
769
|
+
this.pageLifecycleCleanup.push(() => document.removeEventListener('visibilitychange', onVisibilityChange), () => window.removeEventListener('pageshow', onPageShow));
|
|
770
|
+
}
|
|
771
|
+
recoverAfterPageRestore() {
|
|
772
|
+
this.ngZone.run(() => {
|
|
773
|
+
if (!this.pcClient || !this.isCallActiveState(this.callStateSubject.value))
|
|
774
|
+
return;
|
|
775
|
+
// Older cached TS program state may not include this helper yet; call defensively.
|
|
776
|
+
this.audioAnalyzer.resumeContextIfSuspended?.();
|
|
777
|
+
this.startLocalMicAnalyzer();
|
|
778
|
+
this.resumeBotAudioPlayback();
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
resumeBotAudioPlayback() {
|
|
782
|
+
const botTrack = this.pcClient?.tracks()
|
|
783
|
+
?.bot?.audio;
|
|
784
|
+
if (botTrack) {
|
|
785
|
+
this.setupBotAudioTrack(botTrack);
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
if (this.botAudioElement) {
|
|
789
|
+
this.botAudioElement.play().catch((err) => console.warn('[HiveGpt Voice] Bot audio resume blocked', err));
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
isCallActiveState(state) {
|
|
793
|
+
return state === 'connecting' || state === 'connected' || state === 'listening' || state === 'talking';
|
|
794
|
+
}
|
|
732
795
|
}
|
|
733
796
|
VoiceAgentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VoiceAgentService, deps: [{ token: AudioAnalyzerService }, { token: PlatformTokenRefreshService }, { token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
734
797
|
VoiceAgentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: VoiceAgentService, providedIn: 'root' });
|
|
@@ -3674,10 +3737,12 @@ class ChatDrawerComponent {
|
|
|
3674
3737
|
}
|
|
3675
3738
|
this.cdr.detectChanges();
|
|
3676
3739
|
}
|
|
3677
|
-
scrollToBottom() {
|
|
3678
|
-
if (!this.autoScrollOnNewMessage) {
|
|
3740
|
+
scrollToBottom(force = false) {
|
|
3741
|
+
if (!force && !this.autoScrollOnNewMessage) {
|
|
3679
3742
|
return;
|
|
3680
3743
|
}
|
|
3744
|
+
if (!this.chatMain?.nativeElement)
|
|
3745
|
+
return;
|
|
3681
3746
|
let counter = 0;
|
|
3682
3747
|
const interval = setInterval(() => {
|
|
3683
3748
|
this.chatMain.nativeElement.scrollTop =
|
|
@@ -3688,7 +3753,7 @@ class ChatDrawerComponent {
|
|
|
3688
3753
|
}
|
|
3689
3754
|
/** Scrolls the chat container so the top of the AI message with the given id is visible. */
|
|
3690
3755
|
scrollToAiMessage(messageId) {
|
|
3691
|
-
if (!this.
|
|
3756
|
+
if (!this.chatMain?.nativeElement)
|
|
3692
3757
|
return;
|
|
3693
3758
|
const container = this.chatMain.nativeElement;
|
|
3694
3759
|
const el = container.querySelector(`[data-msg-id="${messageId}"]`);
|
|
@@ -4572,8 +4637,8 @@ class ChatDrawerComponent {
|
|
|
4572
4637
|
setTimeout(() => this.scrollToAiMessage(messageId), 30);
|
|
4573
4638
|
}
|
|
4574
4639
|
else {
|
|
4575
|
-
this.scrollToBottom();
|
|
4576
4640
|
this.cdr.markForCheck();
|
|
4641
|
+
setTimeout(() => this.scrollToBottom(true), 0);
|
|
4577
4642
|
}
|
|
4578
4643
|
break;
|
|
4579
4644
|
}
|