@adminforth/agent 1.25.0 → 1.26.1
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/build.log +2 -2
- package/custom/ChatSurface.vue +4 -2
- package/custom/CustomAutoScrollContainer.vue +1 -1
- package/custom/conversation_area/ConversationArea.vue +154 -13
- package/custom/conversation_area/TextRenderer.vue +1 -1
- package/custom/conversation_area/ToolRenderer.vue +1 -1
- package/custom/types.ts +0 -1
- package/dist/custom/ChatSurface.vue +4 -2
- package/dist/custom/CustomAutoScrollContainer.vue +1 -1
- package/dist/custom/conversation_area/ConversationArea.vue +154 -13
- package/dist/custom/conversation_area/TextRenderer.vue +1 -1
- package/dist/custom/conversation_area/ToolRenderer.vue +1 -1
- package/dist/custom/types.ts +0 -1
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -38,5 +38,5 @@ custom/skills/fetch_data/SKILL.md
|
|
|
38
38
|
custom/skills/mutate_data/
|
|
39
39
|
custom/skills/mutate_data/SKILL.md
|
|
40
40
|
|
|
41
|
-
sent
|
|
42
|
-
total size is
|
|
41
|
+
sent 206,263 bytes received 562 bytes 413,650.00 bytes/sec
|
|
42
|
+
total size is 203,953 speedup is 0.99
|
package/custom/ChatSurface.vue
CHANGED
|
@@ -93,7 +93,8 @@
|
|
|
93
93
|
<div
|
|
94
94
|
class="relative flex-1 min-h-0 flex flex-col overflow-hidden"
|
|
95
95
|
>
|
|
96
|
-
<ConversationArea
|
|
96
|
+
<ConversationArea
|
|
97
|
+
ref="conversationArea"
|
|
97
98
|
v-if="agentStore.isChatOpen"
|
|
98
99
|
:messages="agentStore.chatMessages"
|
|
99
100
|
/>
|
|
@@ -201,6 +202,7 @@ const props = defineProps<{
|
|
|
201
202
|
const chatSurface = useTemplateRef('chatSurface');
|
|
202
203
|
const textInput = useTemplateRef('textInput');
|
|
203
204
|
const modeMenu = useTemplateRef('modeMenu');
|
|
205
|
+
const conversationArea = useTemplateRef('conversationArea');
|
|
204
206
|
const agentStore = useAgentStore();
|
|
205
207
|
const agentTransitions = useAgentTransitions();
|
|
206
208
|
const coreStore = useCoreStore();
|
|
@@ -254,7 +256,6 @@ onMounted(async () => {
|
|
|
254
256
|
agentStore.setIsTeleportedToBody(isTeleportedToBodyFromLocalStorage || props.meta.stickByDefault);
|
|
255
257
|
}
|
|
256
258
|
await agentStore.fetchSessionsList();
|
|
257
|
-
agentStore.setFullScreen(true);
|
|
258
259
|
});
|
|
259
260
|
|
|
260
261
|
function autoResize() {
|
|
@@ -286,6 +287,7 @@ async function sendMessage() {
|
|
|
286
287
|
isModeMenuOpen.value = false;
|
|
287
288
|
await agentStore.sendMessage();
|
|
288
289
|
autoResize();
|
|
290
|
+
conversationArea.value?.handleSendMessage();
|
|
289
291
|
}
|
|
290
292
|
|
|
291
293
|
</script>
|
|
@@ -34,9 +34,10 @@
|
|
|
34
34
|
>
|
|
35
35
|
|
|
36
36
|
<div
|
|
37
|
-
v-for="(message, index) in props.messages" :key="
|
|
37
|
+
v-for="(message, index) in props.messages" :key="index"
|
|
38
38
|
class="flex flex-col w-full mt-2"
|
|
39
39
|
:class="message.role === 'user' ? 'self-end' : 'self-start'"
|
|
40
|
+
ref="messagesRefs"
|
|
40
41
|
>
|
|
41
42
|
<MessageRenderer :message="message" :isLastMessageInChat="index === props.messages.length - 1"/>
|
|
42
43
|
</div>
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
<p>{{ $t('Start the conversation') }}</p>
|
|
51
52
|
<p class="tracking-normal text-base text">{{ $t('Give any input to begin') }}</p>
|
|
52
53
|
</div>
|
|
53
|
-
<div></div>
|
|
54
|
+
<div v-if="showBottomSpacer" class="w-full" :style="{ height: spacerHeight + 'px' }"></div>
|
|
54
55
|
</CustomAutoScrollContainer>
|
|
55
56
|
<button @click="scrollContainer.scrollToBottom();">
|
|
56
57
|
<IconArrowDownOutline
|
|
@@ -64,8 +65,8 @@
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
<script setup lang="ts">
|
|
67
|
-
import type { IMessage
|
|
68
|
-
import { useTemplateRef, ref,
|
|
68
|
+
import type { IMessage } from '../types';
|
|
69
|
+
import { useTemplateRef, ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
|
69
70
|
import { IconArrowDownOutline } from '@iconify-prerendered/vue-flowbite';
|
|
70
71
|
import SessionsHistory from '../SessionsHistory.vue';
|
|
71
72
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
@@ -77,18 +78,140 @@ const props = defineProps<{
|
|
|
77
78
|
messages: IMessage[]
|
|
78
79
|
}>();
|
|
79
80
|
|
|
81
|
+
defineExpose({
|
|
82
|
+
handleSendMessage
|
|
83
|
+
});
|
|
84
|
+
|
|
80
85
|
const scrollContainer = useTemplateRef('scrollContainer');
|
|
81
86
|
const showScrollToBottomButton = ref(false);
|
|
82
|
-
const innerScrollContainerRef = ref(null);
|
|
87
|
+
const innerScrollContainerRef = ref<HTMLElement | null>(null);
|
|
83
88
|
const agentStore = useAgentStore();
|
|
84
89
|
const agentTransitions = useAgentTransitions();
|
|
85
90
|
const showScrollContainer = ref(true);
|
|
86
|
-
const chatContainerRef = ref(null);
|
|
91
|
+
const chatContainerRef = ref<HTMLElement | null>(null);
|
|
87
92
|
|
|
88
|
-
const
|
|
89
|
-
|
|
93
|
+
const messagesRefs = ref<Array<HTMLElement | null>>([]);
|
|
94
|
+
const showBottomSpacer = ref(false);
|
|
95
|
+
const spacerHeight = ref(0);
|
|
96
|
+
const MASK_HEIGHT = 20;
|
|
97
|
+
const EMPTY_MESSAGE_HEIGHT = 18;
|
|
98
|
+
let messageResizeObserver: ResizeObserver | null = null;
|
|
99
|
+
let observedLastUserMessageElement: HTMLElement | null = null;
|
|
100
|
+
let observedLastAgentMessageElement: HTMLElement | null = null;
|
|
101
|
+
|
|
102
|
+
function resetSpacer() {
|
|
103
|
+
showBottomSpacer.value = false;
|
|
104
|
+
spacerHeight.value = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
watch(() => agentStore.activeSessionId, () => {
|
|
108
|
+
resetSpacer();
|
|
90
109
|
});
|
|
91
110
|
|
|
111
|
+
function getLastMessageElement(role: 'user' | 'assistant') {
|
|
112
|
+
const lastMessageIndex = props.messages.findLastIndex((message: IMessage) => message.role === role);
|
|
113
|
+
return messagesRefs.value[lastMessageIndex] ?? null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getHeightOfLastUserMessage() {
|
|
117
|
+
return getLastMessageElement('user')?.clientHeight ?? 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getHeightOfLastAgentMessage() {
|
|
121
|
+
return getLastMessageElement('assistant')?.clientHeight ?? 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getScrollClientHeight() {
|
|
125
|
+
return scrollContainer.value?.container.scrollEl.clientHeight ?? scrollContainer.value?.scrollParams.clientHeight ?? 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function waitForRealHeight(role: 'user' | 'assistant'): Promise<number> {
|
|
129
|
+
return new Promise((resolve) => {
|
|
130
|
+
const interval = setInterval(() => {
|
|
131
|
+
const height = role === 'user' ? getHeightOfLastUserMessage() : getHeightOfLastAgentMessage();
|
|
132
|
+
|
|
133
|
+
if (height > EMPTY_MESSAGE_HEIGHT) {
|
|
134
|
+
clearInterval(interval);
|
|
135
|
+
resolve(height);
|
|
136
|
+
}
|
|
137
|
+
}, 50);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const useWaitingForHeight = ref(false);
|
|
142
|
+
async function updateSpacerHeight() {
|
|
143
|
+
if (!showBottomSpacer.value) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const clientHeight = getScrollClientHeight();
|
|
148
|
+
|
|
149
|
+
if (!clientHeight) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const lastUserMessageHeight = useWaitingForHeight.value ? await waitForRealHeight('user') : getHeightOfLastUserMessage();
|
|
154
|
+
const lastAgentMessageHeight = useWaitingForHeight.value ? await waitForRealHeight('assistant') : getHeightOfLastAgentMessage();
|
|
155
|
+
|
|
156
|
+
spacerHeight.value = Math.max(0, clientHeight - (lastUserMessageHeight + MASK_HEIGHT + lastAgentMessageHeight));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function stopObservingLastMessages() {
|
|
160
|
+
if (!messageResizeObserver) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (observedLastUserMessageElement) {
|
|
165
|
+
messageResizeObserver.unobserve(observedLastUserMessageElement);
|
|
166
|
+
observedLastUserMessageElement = null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (observedLastAgentMessageElement) {
|
|
170
|
+
messageResizeObserver.unobserve(observedLastAgentMessageElement);
|
|
171
|
+
observedLastAgentMessageElement = null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function observeLastMessages() {
|
|
176
|
+
if (!messageResizeObserver) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
stopObservingLastMessages();
|
|
181
|
+
|
|
182
|
+
observedLastUserMessageElement = getLastMessageElement('user');
|
|
183
|
+
observedLastAgentMessageElement = getLastMessageElement('assistant');
|
|
184
|
+
|
|
185
|
+
if (observedLastUserMessageElement) {
|
|
186
|
+
messageResizeObserver.observe(observedLastUserMessageElement);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (observedLastAgentMessageElement) {
|
|
190
|
+
messageResizeObserver.observe(observedLastAgentMessageElement);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function refreshSpacerTracking() {
|
|
195
|
+
await nextTick();
|
|
196
|
+
observeLastMessages();
|
|
197
|
+
await updateSpacerHeight();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function handleSendMessage() {
|
|
201
|
+
const clientHeight = getScrollClientHeight();
|
|
202
|
+
|
|
203
|
+
if (clientHeight) {
|
|
204
|
+
showBottomSpacer.value = true;
|
|
205
|
+
useWaitingForHeight.value = true;
|
|
206
|
+
setTimeout(() => {
|
|
207
|
+
useWaitingForHeight.value = false;
|
|
208
|
+
}, 1000);
|
|
209
|
+
await updateSpacerHeight();
|
|
210
|
+
await nextTick();
|
|
211
|
+
scrollContainer.value?.scrollToBottom();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
92
215
|
function recalculateScroll() {
|
|
93
216
|
if (scrollContainer.value) {
|
|
94
217
|
scrollContainer.value.handleScroll(false);
|
|
@@ -101,26 +224,44 @@ watch(() => agentStore.activeSessionId, async () => {
|
|
|
101
224
|
showScrollContainer.value = false;
|
|
102
225
|
await nextTick();
|
|
103
226
|
showScrollContainer.value = true;
|
|
104
|
-
await
|
|
227
|
+
await refreshSpacerTracking();
|
|
105
228
|
recalculateScroll();
|
|
106
229
|
});
|
|
107
230
|
|
|
231
|
+
watch(() => props.messages.length, async () => {
|
|
232
|
+
await refreshSpacerTracking();
|
|
233
|
+
});
|
|
234
|
+
|
|
108
235
|
onMounted(async () => {
|
|
236
|
+
messageResizeObserver = new ResizeObserver(() => {
|
|
237
|
+
updateSpacerHeight();
|
|
238
|
+
});
|
|
239
|
+
|
|
109
240
|
await import('@incremark/theme/styles.css')
|
|
110
241
|
await agentStore.fetchPlaceholderMessages()
|
|
242
|
+
await refreshSpacerTracking();
|
|
111
243
|
});
|
|
112
244
|
|
|
113
245
|
onUnmounted(() => {
|
|
246
|
+
if (innerScrollContainerRef.value) {
|
|
247
|
+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
stopObservingLastMessages();
|
|
251
|
+
messageResizeObserver?.disconnect();
|
|
114
252
|
agentStore.stopPlaceholderAnimation();
|
|
115
253
|
});
|
|
116
254
|
|
|
117
|
-
watch(scrollContainer, () => {
|
|
255
|
+
watch(scrollContainer, async () => {
|
|
256
|
+
if (innerScrollContainerRef.value) {
|
|
257
|
+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
|
|
258
|
+
}
|
|
259
|
+
|
|
118
260
|
if (scrollContainer.value) {
|
|
119
261
|
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
|
|
120
262
|
|
|
121
|
-
innerScrollContainerRef.value.addEventListener('scroll',
|
|
122
|
-
|
|
123
|
-
});
|
|
263
|
+
innerScrollContainerRef.value.addEventListener('scroll', recalculateScroll);
|
|
264
|
+
await refreshSpacerTracking();
|
|
124
265
|
}
|
|
125
266
|
})
|
|
126
267
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<span v-if="props.data?.toolInfo?.durationMs" class="text-xs">({{ (props.data.toolInfo.durationMs / 1000).toFixed(2) }}s)</span>
|
|
30
30
|
</p> -->
|
|
31
31
|
<p class="break-all font-mono text-sm leading-5 text-nowrap">
|
|
32
|
-
{{ props.data?.toolInfo?.toolInfo }}
|
|
32
|
+
{{ props.data?.toolInfo?.toolInfo ? props.data.toolInfo.toolInfo : props.data?.toolInfo?.toolName}}
|
|
33
33
|
</p>
|
|
34
34
|
</div>
|
|
35
35
|
<IconAngleDownOutline
|
package/custom/types.ts
CHANGED
|
@@ -93,7 +93,8 @@
|
|
|
93
93
|
<div
|
|
94
94
|
class="relative flex-1 min-h-0 flex flex-col overflow-hidden"
|
|
95
95
|
>
|
|
96
|
-
<ConversationArea
|
|
96
|
+
<ConversationArea
|
|
97
|
+
ref="conversationArea"
|
|
97
98
|
v-if="agentStore.isChatOpen"
|
|
98
99
|
:messages="agentStore.chatMessages"
|
|
99
100
|
/>
|
|
@@ -201,6 +202,7 @@ const props = defineProps<{
|
|
|
201
202
|
const chatSurface = useTemplateRef('chatSurface');
|
|
202
203
|
const textInput = useTemplateRef('textInput');
|
|
203
204
|
const modeMenu = useTemplateRef('modeMenu');
|
|
205
|
+
const conversationArea = useTemplateRef('conversationArea');
|
|
204
206
|
const agentStore = useAgentStore();
|
|
205
207
|
const agentTransitions = useAgentTransitions();
|
|
206
208
|
const coreStore = useCoreStore();
|
|
@@ -254,7 +256,6 @@ onMounted(async () => {
|
|
|
254
256
|
agentStore.setIsTeleportedToBody(isTeleportedToBodyFromLocalStorage || props.meta.stickByDefault);
|
|
255
257
|
}
|
|
256
258
|
await agentStore.fetchSessionsList();
|
|
257
|
-
agentStore.setFullScreen(true);
|
|
258
259
|
});
|
|
259
260
|
|
|
260
261
|
function autoResize() {
|
|
@@ -286,6 +287,7 @@ async function sendMessage() {
|
|
|
286
287
|
isModeMenuOpen.value = false;
|
|
287
288
|
await agentStore.sendMessage();
|
|
288
289
|
autoResize();
|
|
290
|
+
conversationArea.value?.handleSendMessage();
|
|
289
291
|
}
|
|
290
292
|
|
|
291
293
|
</script>
|
|
@@ -34,9 +34,10 @@
|
|
|
34
34
|
>
|
|
35
35
|
|
|
36
36
|
<div
|
|
37
|
-
v-for="(message, index) in props.messages" :key="
|
|
37
|
+
v-for="(message, index) in props.messages" :key="index"
|
|
38
38
|
class="flex flex-col w-full mt-2"
|
|
39
39
|
:class="message.role === 'user' ? 'self-end' : 'self-start'"
|
|
40
|
+
ref="messagesRefs"
|
|
40
41
|
>
|
|
41
42
|
<MessageRenderer :message="message" :isLastMessageInChat="index === props.messages.length - 1"/>
|
|
42
43
|
</div>
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
<p>{{ $t('Start the conversation') }}</p>
|
|
51
52
|
<p class="tracking-normal text-base text">{{ $t('Give any input to begin') }}</p>
|
|
52
53
|
</div>
|
|
53
|
-
<div></div>
|
|
54
|
+
<div v-if="showBottomSpacer" class="w-full" :style="{ height: spacerHeight + 'px' }"></div>
|
|
54
55
|
</CustomAutoScrollContainer>
|
|
55
56
|
<button @click="scrollContainer.scrollToBottom();">
|
|
56
57
|
<IconArrowDownOutline
|
|
@@ -64,8 +65,8 @@
|
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
<script setup lang="ts">
|
|
67
|
-
import type { IMessage
|
|
68
|
-
import { useTemplateRef, ref,
|
|
68
|
+
import type { IMessage } from '../types';
|
|
69
|
+
import { useTemplateRef, ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
|
69
70
|
import { IconArrowDownOutline } from '@iconify-prerendered/vue-flowbite';
|
|
70
71
|
import SessionsHistory from '../SessionsHistory.vue';
|
|
71
72
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
@@ -77,18 +78,140 @@ const props = defineProps<{
|
|
|
77
78
|
messages: IMessage[]
|
|
78
79
|
}>();
|
|
79
80
|
|
|
81
|
+
defineExpose({
|
|
82
|
+
handleSendMessage
|
|
83
|
+
});
|
|
84
|
+
|
|
80
85
|
const scrollContainer = useTemplateRef('scrollContainer');
|
|
81
86
|
const showScrollToBottomButton = ref(false);
|
|
82
|
-
const innerScrollContainerRef = ref(null);
|
|
87
|
+
const innerScrollContainerRef = ref<HTMLElement | null>(null);
|
|
83
88
|
const agentStore = useAgentStore();
|
|
84
89
|
const agentTransitions = useAgentTransitions();
|
|
85
90
|
const showScrollContainer = ref(true);
|
|
86
|
-
const chatContainerRef = ref(null);
|
|
91
|
+
const chatContainerRef = ref<HTMLElement | null>(null);
|
|
87
92
|
|
|
88
|
-
const
|
|
89
|
-
|
|
93
|
+
const messagesRefs = ref<Array<HTMLElement | null>>([]);
|
|
94
|
+
const showBottomSpacer = ref(false);
|
|
95
|
+
const spacerHeight = ref(0);
|
|
96
|
+
const MASK_HEIGHT = 20;
|
|
97
|
+
const EMPTY_MESSAGE_HEIGHT = 18;
|
|
98
|
+
let messageResizeObserver: ResizeObserver | null = null;
|
|
99
|
+
let observedLastUserMessageElement: HTMLElement | null = null;
|
|
100
|
+
let observedLastAgentMessageElement: HTMLElement | null = null;
|
|
101
|
+
|
|
102
|
+
function resetSpacer() {
|
|
103
|
+
showBottomSpacer.value = false;
|
|
104
|
+
spacerHeight.value = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
watch(() => agentStore.activeSessionId, () => {
|
|
108
|
+
resetSpacer();
|
|
90
109
|
});
|
|
91
110
|
|
|
111
|
+
function getLastMessageElement(role: 'user' | 'assistant') {
|
|
112
|
+
const lastMessageIndex = props.messages.findLastIndex((message: IMessage) => message.role === role);
|
|
113
|
+
return messagesRefs.value[lastMessageIndex] ?? null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getHeightOfLastUserMessage() {
|
|
117
|
+
return getLastMessageElement('user')?.clientHeight ?? 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getHeightOfLastAgentMessage() {
|
|
121
|
+
return getLastMessageElement('assistant')?.clientHeight ?? 0;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getScrollClientHeight() {
|
|
125
|
+
return scrollContainer.value?.container.scrollEl.clientHeight ?? scrollContainer.value?.scrollParams.clientHeight ?? 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function waitForRealHeight(role: 'user' | 'assistant'): Promise<number> {
|
|
129
|
+
return new Promise((resolve) => {
|
|
130
|
+
const interval = setInterval(() => {
|
|
131
|
+
const height = role === 'user' ? getHeightOfLastUserMessage() : getHeightOfLastAgentMessage();
|
|
132
|
+
|
|
133
|
+
if (height > EMPTY_MESSAGE_HEIGHT) {
|
|
134
|
+
clearInterval(interval);
|
|
135
|
+
resolve(height);
|
|
136
|
+
}
|
|
137
|
+
}, 50);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const useWaitingForHeight = ref(false);
|
|
142
|
+
async function updateSpacerHeight() {
|
|
143
|
+
if (!showBottomSpacer.value) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const clientHeight = getScrollClientHeight();
|
|
148
|
+
|
|
149
|
+
if (!clientHeight) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const lastUserMessageHeight = useWaitingForHeight.value ? await waitForRealHeight('user') : getHeightOfLastUserMessage();
|
|
154
|
+
const lastAgentMessageHeight = useWaitingForHeight.value ? await waitForRealHeight('assistant') : getHeightOfLastAgentMessage();
|
|
155
|
+
|
|
156
|
+
spacerHeight.value = Math.max(0, clientHeight - (lastUserMessageHeight + MASK_HEIGHT + lastAgentMessageHeight));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function stopObservingLastMessages() {
|
|
160
|
+
if (!messageResizeObserver) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (observedLastUserMessageElement) {
|
|
165
|
+
messageResizeObserver.unobserve(observedLastUserMessageElement);
|
|
166
|
+
observedLastUserMessageElement = null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (observedLastAgentMessageElement) {
|
|
170
|
+
messageResizeObserver.unobserve(observedLastAgentMessageElement);
|
|
171
|
+
observedLastAgentMessageElement = null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function observeLastMessages() {
|
|
176
|
+
if (!messageResizeObserver) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
stopObservingLastMessages();
|
|
181
|
+
|
|
182
|
+
observedLastUserMessageElement = getLastMessageElement('user');
|
|
183
|
+
observedLastAgentMessageElement = getLastMessageElement('assistant');
|
|
184
|
+
|
|
185
|
+
if (observedLastUserMessageElement) {
|
|
186
|
+
messageResizeObserver.observe(observedLastUserMessageElement);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (observedLastAgentMessageElement) {
|
|
190
|
+
messageResizeObserver.observe(observedLastAgentMessageElement);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function refreshSpacerTracking() {
|
|
195
|
+
await nextTick();
|
|
196
|
+
observeLastMessages();
|
|
197
|
+
await updateSpacerHeight();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function handleSendMessage() {
|
|
201
|
+
const clientHeight = getScrollClientHeight();
|
|
202
|
+
|
|
203
|
+
if (clientHeight) {
|
|
204
|
+
showBottomSpacer.value = true;
|
|
205
|
+
useWaitingForHeight.value = true;
|
|
206
|
+
setTimeout(() => {
|
|
207
|
+
useWaitingForHeight.value = false;
|
|
208
|
+
}, 1000);
|
|
209
|
+
await updateSpacerHeight();
|
|
210
|
+
await nextTick();
|
|
211
|
+
scrollContainer.value?.scrollToBottom();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
92
215
|
function recalculateScroll() {
|
|
93
216
|
if (scrollContainer.value) {
|
|
94
217
|
scrollContainer.value.handleScroll(false);
|
|
@@ -101,26 +224,44 @@ watch(() => agentStore.activeSessionId, async () => {
|
|
|
101
224
|
showScrollContainer.value = false;
|
|
102
225
|
await nextTick();
|
|
103
226
|
showScrollContainer.value = true;
|
|
104
|
-
await
|
|
227
|
+
await refreshSpacerTracking();
|
|
105
228
|
recalculateScroll();
|
|
106
229
|
});
|
|
107
230
|
|
|
231
|
+
watch(() => props.messages.length, async () => {
|
|
232
|
+
await refreshSpacerTracking();
|
|
233
|
+
});
|
|
234
|
+
|
|
108
235
|
onMounted(async () => {
|
|
236
|
+
messageResizeObserver = new ResizeObserver(() => {
|
|
237
|
+
updateSpacerHeight();
|
|
238
|
+
});
|
|
239
|
+
|
|
109
240
|
await import('@incremark/theme/styles.css')
|
|
110
241
|
await agentStore.fetchPlaceholderMessages()
|
|
242
|
+
await refreshSpacerTracking();
|
|
111
243
|
});
|
|
112
244
|
|
|
113
245
|
onUnmounted(() => {
|
|
246
|
+
if (innerScrollContainerRef.value) {
|
|
247
|
+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
stopObservingLastMessages();
|
|
251
|
+
messageResizeObserver?.disconnect();
|
|
114
252
|
agentStore.stopPlaceholderAnimation();
|
|
115
253
|
});
|
|
116
254
|
|
|
117
|
-
watch(scrollContainer, () => {
|
|
255
|
+
watch(scrollContainer, async () => {
|
|
256
|
+
if (innerScrollContainerRef.value) {
|
|
257
|
+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
|
|
258
|
+
}
|
|
259
|
+
|
|
118
260
|
if (scrollContainer.value) {
|
|
119
261
|
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
|
|
120
262
|
|
|
121
|
-
innerScrollContainerRef.value.addEventListener('scroll',
|
|
122
|
-
|
|
123
|
-
});
|
|
263
|
+
innerScrollContainerRef.value.addEventListener('scroll', recalculateScroll);
|
|
264
|
+
await refreshSpacerTracking();
|
|
124
265
|
}
|
|
125
266
|
})
|
|
126
267
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
<span v-if="props.data?.toolInfo?.durationMs" class="text-xs">({{ (props.data.toolInfo.durationMs / 1000).toFixed(2) }}s)</span>
|
|
30
30
|
</p> -->
|
|
31
31
|
<p class="break-all font-mono text-sm leading-5 text-nowrap">
|
|
32
|
-
{{ props.data?.toolInfo?.toolInfo }}
|
|
32
|
+
{{ props.data?.toolInfo?.toolInfo ? props.data.toolInfo.toolInfo : props.data?.toolInfo?.toolName}}
|
|
33
33
|
</p>
|
|
34
34
|
</div>
|
|
35
35
|
<IconAngleDownOutline
|
package/dist/custom/types.ts
CHANGED