@hivegpt/hiveai-angular 0.0.610 → 0.0.612
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 +63 -17
- package/fesm2015/hivegpt-hiveai-angular.mjs +67 -19
- package/fesm2015/hivegpt-hiveai-angular.mjs.map +1 -1
- package/fesm2020/hivegpt-hiveai-angular.mjs +62 -16
- package/fesm2020/hivegpt-hiveai-angular.mjs.map +1 -1
- package/lib/components/chat-drawer/chat-drawer.component.d.ts +6 -1
- package/lib/components/chat-drawer/chat-drawer.component.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1639,6 +1639,11 @@ class ChatDrawerComponent {
|
|
|
1639
1639
|
this.displayAvatarUrl = 'https://www.jotform.com/uploads/mehmetkarakasli/form_files/1564593667676a8e85f23758.86945537_icon.png';
|
|
1640
1640
|
/** When true, chat auto-scrolls to bottom when new content is added. Default: false (no auto scroll). */
|
|
1641
1641
|
this.autoScrollOnNewMessage = false;
|
|
1642
|
+
/** Tracks whether the user has manually scrolled up, suppressing auto-scroll until they scroll back to bottom or send a new message. */
|
|
1643
|
+
this.userHasScrolled = false;
|
|
1644
|
+
/** Guards against our own programmatic scrolls triggering the userHasScrolled detection. */
|
|
1645
|
+
this.isProgrammaticScroll = false;
|
|
1646
|
+
this.scrollListenerTimer = null;
|
|
1642
1647
|
/** Connections list from host (e.g. from store selectConnectionsList). Each item has userId. When set, used for Connect/Request Sent/Disconnect button state. */
|
|
1643
1648
|
this.connectionsList = [];
|
|
1644
1649
|
/** Pending sent request user IDs from host (e.g. from store selectPendingConnectionsSentList). When set, used for Request Sent state. */
|
|
@@ -3336,6 +3341,8 @@ class ChatDrawerComponent {
|
|
|
3336
3341
|
if (!this.input || this.loading) {
|
|
3337
3342
|
return;
|
|
3338
3343
|
}
|
|
3344
|
+
// Reset auto-scroll suppression when user sends a new message
|
|
3345
|
+
this.userHasScrolled = false;
|
|
3339
3346
|
this.chatLog.push({
|
|
3340
3347
|
type: 'user',
|
|
3341
3348
|
message: this.processMessageForDisplay(this.input),
|
|
@@ -3359,6 +3366,8 @@ class ChatDrawerComponent {
|
|
|
3359
3366
|
if (!inputMsg || this.loading) {
|
|
3360
3367
|
return;
|
|
3361
3368
|
}
|
|
3369
|
+
// Reset auto-scroll suppression when user sends a new message
|
|
3370
|
+
this.userHasScrolled = false;
|
|
3362
3371
|
try {
|
|
3363
3372
|
chat.relatedListItems = [];
|
|
3364
3373
|
this.cdr.detectChanges();
|
|
@@ -3417,7 +3426,8 @@ class ChatDrawerComponent {
|
|
|
3417
3426
|
var _a, _b, _c, _d;
|
|
3418
3427
|
const lastItem = this.chatLog[this.chatLog.length - 1];
|
|
3419
3428
|
if (done) {
|
|
3420
|
-
|
|
3429
|
+
// Final pass with the complete raw text (aiResponse) for a clean render
|
|
3430
|
+
lastItem.message = this.processMessageForDisplay(this.aiResponse);
|
|
3421
3431
|
this.chatLog.pop();
|
|
3422
3432
|
this.chatLog.push(lastItem);
|
|
3423
3433
|
if (allSuggestions === null || allSuggestions === void 0 ? void 0 : allSuggestions.length) {
|
|
@@ -3446,7 +3456,7 @@ class ChatDrawerComponent {
|
|
|
3446
3456
|
allSuggestions.push(match === null || match === void 0 ? void 0 : match.replace(/<\/?sug>/g, ''));
|
|
3447
3457
|
});
|
|
3448
3458
|
}
|
|
3449
|
-
lastItem.message = this.aiResponse;
|
|
3459
|
+
lastItem.message = this.processMessageForDisplay(this.aiResponse);
|
|
3450
3460
|
this.cdr.markForCheck();
|
|
3451
3461
|
}
|
|
3452
3462
|
else {
|
|
@@ -3734,32 +3744,43 @@ class ChatDrawerComponent {
|
|
|
3734
3744
|
}
|
|
3735
3745
|
this.cdr.detectChanges();
|
|
3736
3746
|
}
|
|
3737
|
-
scrollToBottom(force = false) {
|
|
3747
|
+
scrollToBottom(force = false, smooth = true) {
|
|
3738
3748
|
var _a;
|
|
3739
3749
|
if (!force && !this.autoScrollOnNewMessage) {
|
|
3740
3750
|
return;
|
|
3741
3751
|
}
|
|
3752
|
+
if (this.userHasScrolled) {
|
|
3753
|
+
return;
|
|
3754
|
+
}
|
|
3742
3755
|
if (!((_a = this.chatMain) === null || _a === void 0 ? void 0 : _a.nativeElement))
|
|
3743
3756
|
return;
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3757
|
+
const el = this.chatMain.nativeElement;
|
|
3758
|
+
this.isProgrammaticScroll = true;
|
|
3759
|
+
el.scrollTo({
|
|
3760
|
+
top: el.scrollHeight,
|
|
3761
|
+
behavior: smooth ? 'smooth' : 'auto',
|
|
3762
|
+
});
|
|
3763
|
+
// Release the guard after the smooth scroll settles
|
|
3764
|
+
setTimeout(() => { this.isProgrammaticScroll = false; }, smooth ? 400 : 50);
|
|
3751
3765
|
}
|
|
3752
3766
|
/** Scrolls the chat container so the top of the AI message with the given id is visible. */
|
|
3753
3767
|
scrollToAiMessage(messageId) {
|
|
3754
3768
|
var _a;
|
|
3769
|
+
if (this.userHasScrolled)
|
|
3770
|
+
return;
|
|
3755
3771
|
if (!((_a = this.chatMain) === null || _a === void 0 ? void 0 : _a.nativeElement))
|
|
3756
3772
|
return;
|
|
3757
3773
|
const container = this.chatMain.nativeElement;
|
|
3758
3774
|
const el = container.querySelector(`[data-msg-id="${messageId}"]`);
|
|
3759
3775
|
if (!el)
|
|
3760
3776
|
return;
|
|
3761
|
-
const
|
|
3762
|
-
|
|
3777
|
+
const targetTop = el.getBoundingClientRect().top - container.getBoundingClientRect().top;
|
|
3778
|
+
this.isProgrammaticScroll = true;
|
|
3779
|
+
container.scrollTo({
|
|
3780
|
+
top: container.scrollTop + targetTop - 8,
|
|
3781
|
+
behavior: 'smooth',
|
|
3782
|
+
});
|
|
3783
|
+
setTimeout(() => { this.isProgrammaticScroll = false; }, 400);
|
|
3763
3784
|
}
|
|
3764
3785
|
focusOnTextarea() {
|
|
3765
3786
|
setTimeout(() => {
|
|
@@ -3775,6 +3796,23 @@ class ChatDrawerComponent {
|
|
|
3775
3796
|
}
|
|
3776
3797
|
}
|
|
3777
3798
|
ngAfterViewInit() {
|
|
3799
|
+
var _a;
|
|
3800
|
+
// Detect user manual scroll to suppress auto-scroll (debounced, ignores programmatic scrolls)
|
|
3801
|
+
if ((_a = this.chatMain) === null || _a === void 0 ? void 0 : _a.nativeElement) {
|
|
3802
|
+
this.chatMain.nativeElement.addEventListener('scroll', () => {
|
|
3803
|
+
if (this.isProgrammaticScroll)
|
|
3804
|
+
return;
|
|
3805
|
+
clearTimeout(this.scrollListenerTimer);
|
|
3806
|
+
this.scrollListenerTimer = setTimeout(() => {
|
|
3807
|
+
var _a;
|
|
3808
|
+
const el = (_a = this.chatMain) === null || _a === void 0 ? void 0 : _a.nativeElement;
|
|
3809
|
+
if (!el)
|
|
3810
|
+
return;
|
|
3811
|
+
const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
|
3812
|
+
this.userHasScrolled = !atBottom;
|
|
3813
|
+
}, 100);
|
|
3814
|
+
});
|
|
3815
|
+
}
|
|
3778
3816
|
// Check if the drawer is initially open and apply overflow hidden to body if so
|
|
3779
3817
|
if (this.drawer.opened) {
|
|
3780
3818
|
this.setBodyOverflow();
|
|
@@ -4613,7 +4651,7 @@ class ChatDrawerComponent {
|
|
|
4613
4651
|
return false;
|
|
4614
4652
|
}
|
|
4615
4653
|
handleAskWebSocketMessage(rawMessage) {
|
|
4616
|
-
var _a, _b, _c, _d, _e;
|
|
4654
|
+
var _a, _b, _c, _d, _e, _f;
|
|
4617
4655
|
if (!rawMessage)
|
|
4618
4656
|
return;
|
|
4619
4657
|
let parsed = null;
|
|
@@ -4635,7 +4673,9 @@ class ChatDrawerComponent {
|
|
|
4635
4673
|
return;
|
|
4636
4674
|
const isNewAiMessage = !this.chatLog.find((p) => p._id == messageId);
|
|
4637
4675
|
const currentChatMessage = this.upsertAiChatMessage(messageId);
|
|
4638
|
-
|
|
4676
|
+
// Accumulate raw text and render markdown in real-time
|
|
4677
|
+
currentChatMessage.rawMessage = `${currentChatMessage.rawMessage || ''}${(payload === null || payload === void 0 ? void 0 : payload.text) || ''}`;
|
|
4678
|
+
currentChatMessage.message = this.processMessageForDisplay(currentChatMessage.rawMessage);
|
|
4639
4679
|
if (isNewAiMessage) {
|
|
4640
4680
|
// First chunk: hide Thinking indicator and scroll to the message start
|
|
4641
4681
|
this.isChatingWithAi = false;
|
|
@@ -4644,7 +4684,7 @@ class ChatDrawerComponent {
|
|
|
4644
4684
|
}
|
|
4645
4685
|
else {
|
|
4646
4686
|
this.cdr.markForCheck();
|
|
4647
|
-
setTimeout(() => this.scrollToBottom(true), 0);
|
|
4687
|
+
setTimeout(() => this.scrollToBottom(true, false), 0);
|
|
4648
4688
|
}
|
|
4649
4689
|
break;
|
|
4650
4690
|
}
|
|
@@ -4655,19 +4695,21 @@ class ChatDrawerComponent {
|
|
|
4655
4695
|
break;
|
|
4656
4696
|
}
|
|
4657
4697
|
const currentChatMessage = this.upsertAiChatMessage(messageId);
|
|
4658
|
-
const finalAnswer = (_c = (_b = payload === null || payload === void 0 ? void 0 : payload.text) !== null && _b !== void 0 ? _b : currentChatMessage.
|
|
4698
|
+
const finalAnswer = (_d = (_c = (_b = payload === null || payload === void 0 ? void 0 : payload.text) !== null && _b !== void 0 ? _b : currentChatMessage.rawMessage) !== null && _c !== void 0 ? _c : currentChatMessage.message) !== null && _d !== void 0 ? _d : '';
|
|
4659
4699
|
const hasCardResponse = this.applyToolResultCardMessage(currentChatMessage, messageId, finalAnswer, payload === null || payload === void 0 ? void 0 : payload.tool_results);
|
|
4660
4700
|
if (!hasCardResponse) {
|
|
4661
4701
|
currentChatMessage.type = 'ai';
|
|
4662
4702
|
currentChatMessage.message = this.processMessageForDisplay(finalAnswer);
|
|
4663
4703
|
}
|
|
4704
|
+
// Clean up raw accumulator
|
|
4705
|
+
delete currentChatMessage.rawMessage;
|
|
4664
4706
|
if (Array.isArray(payload === null || payload === void 0 ? void 0 : payload.suggestions)) {
|
|
4665
4707
|
currentChatMessage.relatedListItems = payload.suggestions;
|
|
4666
4708
|
}
|
|
4667
4709
|
if (Array.isArray(payload === null || payload === void 0 ? void 0 : payload.web_results)) {
|
|
4668
4710
|
currentChatMessage.sourcesList = payload.web_results;
|
|
4669
|
-
currentChatMessage.displayedSources = (
|
|
4670
|
-
currentChatMessage.remainingSources = (
|
|
4711
|
+
currentChatMessage.displayedSources = (_e = payload.web_results) === null || _e === void 0 ? void 0 : _e.slice(0, 3);
|
|
4712
|
+
currentChatMessage.remainingSources = (_f = payload.web_results) === null || _f === void 0 ? void 0 : _f.slice(3);
|
|
4671
4713
|
}
|
|
4672
4714
|
if (payload === null || payload === void 0 ? void 0 : payload.tool_results) {
|
|
4673
4715
|
currentChatMessage.toolResults = payload.tool_results;
|
|
@@ -4675,7 +4717,12 @@ class ChatDrawerComponent {
|
|
|
4675
4717
|
this.showFeedBackIconsIndex = this.chatLog.length - 1;
|
|
4676
4718
|
this.activeAskMessageId = '';
|
|
4677
4719
|
this.isChatingWithAi = false;
|
|
4678
|
-
|
|
4720
|
+
// For card responses (tool results), don't scroll at all —
|
|
4721
|
+
// user is already viewing the AI text from the streaming phase,
|
|
4722
|
+
// cards render below and the user can scroll down to see them.
|
|
4723
|
+
if (!hasCardResponse) {
|
|
4724
|
+
this.scrollToBottom();
|
|
4725
|
+
}
|
|
4679
4726
|
this.focusOnTextarea();
|
|
4680
4727
|
this.cdr.markForCheck();
|
|
4681
4728
|
break;
|
|
@@ -4794,6 +4841,7 @@ class ChatDrawerComponent {
|
|
|
4794
4841
|
return Object.keys(obj).map((key) => ({ key, value: obj[key] }));
|
|
4795
4842
|
}
|
|
4796
4843
|
startNewConversation() {
|
|
4844
|
+
this.userHasScrolled = false;
|
|
4797
4845
|
this.conversationKey = this.conversationService.getKey(this.botId, true, this.eventId);
|
|
4798
4846
|
this.chatLog = [this.chatLog[0]];
|
|
4799
4847
|
this.isChatingWithAi = false;
|