@adminforth/agent 1.24.3 → 1.24.5
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 +2 -3
- package/custom/CustomAutoScrollContainer.vue +48 -22
- package/custom/SessionsHistory.vue +2 -11
- package/custom/conversation_area/ConversationArea.vue +62 -39
- package/custom/conversation_area/MessageRenderer.vue +1 -1
- package/custom/conversation_area/ProcessingTimeline.vue +4 -11
- package/custom/conversation_area/ReasoningRenderer.vue +13 -11
- package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +8 -2
- package/custom/package.json +2 -2
- package/custom/pnpm-lock.yaml +14 -18
- package/custom/types.ts +1 -0
- package/dist/custom/ChatSurface.vue +2 -3
- package/dist/custom/CustomAutoScrollContainer.vue +48 -22
- package/dist/custom/SessionsHistory.vue +2 -11
- package/dist/custom/conversation_area/ConversationArea.vue +62 -39
- package/dist/custom/conversation_area/MessageRenderer.vue +1 -1
- package/dist/custom/conversation_area/ProcessingTimeline.vue +4 -11
- package/dist/custom/conversation_area/ReasoningRenderer.vue +13 -11
- package/dist/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +8 -2
- package/dist/custom/package.json +2 -2
- package/dist/custom/pnpm-lock.yaml +14 -18
- package/dist/custom/types.ts +1 -0
- 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 201,498 bytes received 566 bytes 404,128.00 bytes/sec
|
|
42
|
+
total size is 199,190 speedup is 0.99
|
package/custom/ChatSurface.vue
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
></div>
|
|
33
33
|
|
|
34
34
|
<div
|
|
35
|
-
class="w-full h-full flex flex-col"
|
|
35
|
+
class="w-full min-h-0 max-h-full flex flex-col"
|
|
36
36
|
>
|
|
37
37
|
<div
|
|
38
38
|
class="flex items-center justify-between h-14 border-b border-gray-200 dark:border-gray-700"
|
|
@@ -91,11 +91,10 @@
|
|
|
91
91
|
|
|
92
92
|
</div>
|
|
93
93
|
<div
|
|
94
|
-
class="relative flex-1 flex flex-col overflow-hidden"
|
|
94
|
+
class="relative flex-1 min-h-0 flex flex-col overflow-hidden"
|
|
95
95
|
>
|
|
96
96
|
<ConversationArea
|
|
97
97
|
v-if="agentStore.isChatOpen"
|
|
98
|
-
class="flex-1 overflow-auto"
|
|
99
98
|
:messages="agentStore.chatMessages"
|
|
100
99
|
/>
|
|
101
100
|
|
|
@@ -1,11 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<CustomScrollbar
|
|
3
|
+
ref="containerRef"
|
|
4
|
+
class="auto-scroll-container mask-y"
|
|
5
|
+
:wrapperStyle = "wrapperStyle"
|
|
6
|
+
:contentStyle = "contentStyle"
|
|
7
|
+
>
|
|
8
|
+
<slot />
|
|
9
|
+
</CustomScrollbar>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
1
12
|
<script setup lang="ts">
|
|
2
13
|
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
|
3
|
-
import
|
|
14
|
+
import CustomScrollbar from 'custom-vue-scrollbar';
|
|
15
|
+
import 'custom-vue-scrollbar/dist/style.css';
|
|
16
|
+
import { useScroll } from '@vueuse/core'
|
|
17
|
+
import { useAgentStore } from './composables/useAgentStore';
|
|
18
|
+
|
|
19
|
+
const agentStore = useAgentStore();
|
|
4
20
|
|
|
5
21
|
const props = withDefaults(defineProps<{
|
|
6
22
|
enabled?: boolean
|
|
7
23
|
threshold?: number
|
|
8
24
|
behavior?: ScrollBehavior
|
|
25
|
+
wrapperStyle?: Record<string, string>
|
|
26
|
+
contentStyle?: Record<string, string>
|
|
9
27
|
}>(), {
|
|
10
28
|
enabled: true,
|
|
11
29
|
threshold: 50,
|
|
@@ -14,12 +32,18 @@ const props = withDefaults(defineProps<{
|
|
|
14
32
|
|
|
15
33
|
const containerRef = ref<HTMLDivElement | null>(null)
|
|
16
34
|
const isUserScrolledUp = ref(false)
|
|
35
|
+
const scrollElement = ref<HTMLElement | null>(null)
|
|
36
|
+
const { y } = useScroll(scrollElement)
|
|
37
|
+
|
|
38
|
+
watch(y, () => {
|
|
39
|
+
handleScroll()
|
|
40
|
+
})
|
|
17
41
|
|
|
18
42
|
let lastScrollTop = 0
|
|
19
43
|
let lastScrollHeight = 0
|
|
20
44
|
|
|
21
45
|
function isNearBottom(): boolean {
|
|
22
|
-
const container = containerRef.value
|
|
46
|
+
const container = containerRef.value?.scrollEl
|
|
23
47
|
if (!container) return true
|
|
24
48
|
|
|
25
49
|
const { scrollTop, scrollHeight, clientHeight } = container
|
|
@@ -27,7 +51,7 @@ function isNearBottom(): boolean {
|
|
|
27
51
|
}
|
|
28
52
|
|
|
29
53
|
function scrollToBottom(force = false): void {
|
|
30
|
-
const container = containerRef.value
|
|
54
|
+
const container = containerRef.value?.scrollEl
|
|
31
55
|
if (!container) return
|
|
32
56
|
|
|
33
57
|
if (isUserScrolledUp.value && !force) return
|
|
@@ -40,14 +64,14 @@ function scrollToBottom(force = false): void {
|
|
|
40
64
|
|
|
41
65
|
|
|
42
66
|
function hasScrollbar(): boolean {
|
|
43
|
-
const container = containerRef.value
|
|
67
|
+
const container = containerRef.value?.scrollEl
|
|
44
68
|
if (!container) return false
|
|
45
69
|
return container.scrollHeight > container.clientHeight
|
|
46
70
|
}
|
|
47
71
|
|
|
48
72
|
|
|
49
73
|
function handleScroll(): void {
|
|
50
|
-
const container = containerRef.value
|
|
74
|
+
const container = containerRef.value.scrollEl
|
|
51
75
|
if (!container) return
|
|
52
76
|
|
|
53
77
|
const { scrollTop, scrollHeight, clientHeight } = container
|
|
@@ -58,7 +82,6 @@ function handleScroll(): void {
|
|
|
58
82
|
lastScrollHeight = scrollHeight
|
|
59
83
|
return
|
|
60
84
|
}
|
|
61
|
-
|
|
62
85
|
if (isNearBottom()) {
|
|
63
86
|
isUserScrolledUp.value = false
|
|
64
87
|
} else {
|
|
@@ -69,7 +92,6 @@ function handleScroll(): void {
|
|
|
69
92
|
isUserScrolledUp.value = true
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
|
-
|
|
73
95
|
lastScrollTop = scrollTop
|
|
74
96
|
lastScrollHeight = scrollHeight
|
|
75
97
|
}
|
|
@@ -79,18 +101,19 @@ let observer: MutationObserver | null = null
|
|
|
79
101
|
onMounted(() => {
|
|
80
102
|
if (!containerRef.value) return
|
|
81
103
|
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
scrollElement.value = containerRef.value.scrollEl
|
|
105
|
+
lastScrollTop = containerRef.value.scrollEl.scrollTop
|
|
106
|
+
lastScrollHeight = containerRef.value.scrollEl.scrollHeight
|
|
84
107
|
|
|
85
108
|
observer = new MutationObserver(() => {
|
|
86
109
|
nextTick(() => {
|
|
87
|
-
if (!containerRef.value) return
|
|
110
|
+
if (!containerRef.value?.scrollEl) return
|
|
88
111
|
|
|
89
112
|
if (!hasScrollbar()) {
|
|
90
113
|
isUserScrolledUp.value = false
|
|
91
114
|
}
|
|
92
115
|
|
|
93
|
-
lastScrollHeight = containerRef.value.scrollHeight
|
|
116
|
+
lastScrollHeight = containerRef.value.scrollEl.scrollHeight
|
|
94
117
|
|
|
95
118
|
if (props.enabled && !isUserScrolledUp.value) {
|
|
96
119
|
scrollToBottom()
|
|
@@ -98,7 +121,7 @@ onMounted(() => {
|
|
|
98
121
|
})
|
|
99
122
|
})
|
|
100
123
|
|
|
101
|
-
observer.observe(containerRef.value, {
|
|
124
|
+
observer.observe(containerRef.value?.scrollEl, {
|
|
102
125
|
childList: true,
|
|
103
126
|
subtree: true,
|
|
104
127
|
characterData: true
|
|
@@ -112,16 +135,19 @@ onUnmounted(() => {
|
|
|
112
135
|
defineExpose({
|
|
113
136
|
scrollToBottom: () => scrollToBottom(true),
|
|
114
137
|
isUserScrolledUp: () => isUserScrolledUp.value,
|
|
115
|
-
container: containerRef
|
|
138
|
+
container: containerRef,
|
|
139
|
+
handleScroll
|
|
116
140
|
})
|
|
117
141
|
</script>
|
|
118
142
|
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
<style>
|
|
144
|
+
.mask-y {
|
|
145
|
+
mask-image: linear-gradient(
|
|
146
|
+
to bottom,
|
|
147
|
+
transparent,
|
|
148
|
+
black 20px,
|
|
149
|
+
black calc(100% - 20px),
|
|
150
|
+
transparent
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<h3 :class="h3Style">{{ $t('Chat history') }}</h3>
|
|
9
9
|
<div class="w-full flex items-center justify-center">
|
|
10
10
|
<Button
|
|
11
|
-
@click="agentStore.createPreSession(); agentStore.setSessionHistoryOpen(false); agentStore.focusTextInput();
|
|
11
|
+
@click="agentStore.createPreSession(); agentStore.setSessionHistoryOpen(false); agentStore.focusTextInput();"
|
|
12
12
|
:disabled="agentStore.isResponseInProgress"
|
|
13
13
|
class="w-[90%] my-2 mb-4 rounded-3xl text-gray-800 dark:text-gray-200"
|
|
14
14
|
>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
'bg-lightPrimary/20 hover:bg-lightPrimary/20 dark:bg-darkPrimary/20 dark:hover:bg-darkPrimary/20': agentStore.activeSessionId === session.sessionId,
|
|
35
35
|
'cursor-default opacity-50 pointer-events-none': agentStore.isResponseInProgress,
|
|
36
36
|
}"
|
|
37
|
-
@click="agentStore.setActiveSession(session.sessionId); agentStore.setSessionHistoryOpen(false);
|
|
37
|
+
@click="agentStore.setActiveSession(session.sessionId); agentStore.setSessionHistoryOpen(false);"
|
|
38
38
|
:disabled="agentStore.isResponseInProgress"
|
|
39
39
|
>
|
|
40
40
|
<p class="truncate">{{ session.title || session.sessionId }}</p>
|
|
@@ -99,13 +99,4 @@ const groupedSessions = computed(() => {
|
|
|
99
99
|
return Array.from(groups.values());
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
const emit = defineEmits<{
|
|
103
|
-
(e: 'recalculateScroll'): void
|
|
104
|
-
}>()
|
|
105
|
-
|
|
106
|
-
function recalculateScroll() {
|
|
107
|
-
// Emit an event to notify the parent component to recalculate scroll
|
|
108
|
-
emit('recalculateScroll');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
102
|
</script>
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<button @click="scrollContainer.scrollToBottom(); recalculateScroll();">
|
|
3
|
-
<IconArrowDownOutline
|
|
4
|
-
class="absolute z-10 bottom-32 left-1/2 bg-lightPrimary dark:bg-darkPrimary text-white p-2 w-10 h-10 rounded-full transition-opacity duration-100 ease-in"
|
|
5
|
-
:class="showScrollToBottomButton ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
|
6
|
-
:disabled="!showScrollToBottomButton"
|
|
7
|
-
/>
|
|
8
|
-
</button>
|
|
9
|
-
|
|
10
2
|
<SessionsHistory
|
|
11
3
|
:class="agentStore.isSessionHistoryOpen ? 'translate-x-0' : '-translate-x-full'"
|
|
12
4
|
@recalculateScroll="recalculateScroll"
|
|
@@ -16,38 +8,59 @@
|
|
|
16
8
|
@click="agentStore.setSessionHistoryOpen(false)"
|
|
17
9
|
class="absolute bg-black/10 backdrop-blur-md z-10 h-full w-full"
|
|
18
10
|
>
|
|
19
|
-
|
|
20
11
|
</div>
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
12
|
+
<div class="relative flex-1 min-h-0 overflow-hidden">
|
|
13
|
+
<button @click="scrollContainer.scrollToBottom(); recalculateScroll();">
|
|
14
|
+
<IconArrowDownOutline
|
|
15
|
+
class="absolute z-10 bottom-8 left-1/2 bg-lightPrimary dark:bg-darkPrimary text-white p-2 w-10 h-10 rounded-full transition-opacity duration-100 ease-in"
|
|
16
|
+
:class="showScrollToBottomButton ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
|
17
|
+
:disabled="!showScrollToBottomButton"
|
|
18
|
+
/>
|
|
19
|
+
</button>
|
|
20
|
+
<CustomAutoScrollContainer
|
|
21
|
+
v-if="showScrollContainer"
|
|
22
|
+
:enabled="!showScrollToBottomButton"
|
|
23
|
+
class="relative h-full flex flex-col overflow-y-auto translate-x-[-50%] left-1/2"
|
|
24
|
+
ref="scrollContainer"
|
|
25
|
+
:threshold="10"
|
|
26
|
+
behavior="smooth"
|
|
27
|
+
:wrapperStyle = "{
|
|
28
|
+
height: '100%',
|
|
29
|
+
maxHeight: '100%',
|
|
30
|
+
maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
|
|
31
|
+
width: '100%',
|
|
32
|
+
marginLeft: 'auto',
|
|
33
|
+
marginRight: 'auto',
|
|
34
|
+
}"
|
|
35
|
+
:contentStyle="{
|
|
36
|
+
height: '100%',
|
|
37
|
+
maxHeight: '100%',
|
|
38
|
+
}"
|
|
39
|
+
:style="{
|
|
40
|
+
maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
|
|
41
|
+
transition: `
|
|
42
|
+
max-width ${agentTransitions.TRANSITION_DURATION}ms ease-in-out,
|
|
43
|
+
transform ${agentTransitions.TRANSITION_DURATION}ms ease-in-out
|
|
44
|
+
`
|
|
45
|
+
}"
|
|
46
|
+
>
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
<div
|
|
49
|
+
v-for="(message, index) in props.messages" :key="message.id"
|
|
50
|
+
class="flex flex-col w-full"
|
|
51
|
+
:class="message.role === 'user' ? 'self-end' : 'self-start'"
|
|
52
|
+
>
|
|
53
|
+
<MessageRenderer :message="message" :isLastMessageInChat="index === props.messages.length - 1"/>
|
|
54
|
+
</div>
|
|
55
|
+
<div
|
|
56
|
+
v-if="props.messages.length === 0"
|
|
57
|
+
class="flex-1 flex flex-col items-center justify-center text-gray-400 tracking-widest text-xl font-medium h-full"
|
|
58
|
+
>
|
|
59
|
+
<p>{{ $t('Start the conversation') }}</p>
|
|
60
|
+
<p class="tracking-normal text-base text">{{ $t('Give any input to begin') }}</p>
|
|
61
|
+
</div>
|
|
62
|
+
</CustomAutoScrollContainer>
|
|
63
|
+
</div>
|
|
51
64
|
</template>
|
|
52
65
|
|
|
53
66
|
|
|
@@ -71,14 +84,24 @@ const innerScrollContainerRef = ref(null);
|
|
|
71
84
|
const agentStore = useAgentStore();
|
|
72
85
|
const agentTransitions = useAgentTransitions();
|
|
73
86
|
const clicks = ref(0);
|
|
87
|
+
const showScrollContainer = ref(true);
|
|
74
88
|
|
|
75
89
|
function recalculateScroll() {
|
|
76
90
|
if (scrollContainer.value) {
|
|
91
|
+
scrollContainer.value.handleScroll();
|
|
77
92
|
const isScrolledUp = scrollContainer.value.isUserScrolledUp();
|
|
78
93
|
showScrollToBottomButton.value = !!isScrolledUp;
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
|
|
97
|
+
watch(() => agentStore.activeSessionId, async () => {
|
|
98
|
+
showScrollContainer.value = false;
|
|
99
|
+
await nextTick();
|
|
100
|
+
showScrollContainer.value = true;
|
|
101
|
+
await nextTick();
|
|
102
|
+
recalculateScroll();
|
|
103
|
+
});
|
|
104
|
+
|
|
82
105
|
onMounted(async () => {
|
|
83
106
|
await import('@incremark/theme/styles.css')
|
|
84
107
|
await agentStore.fetchPlaceholderMessages()
|
|
@@ -90,7 +113,7 @@ onUnmounted(() => {
|
|
|
90
113
|
|
|
91
114
|
watch(scrollContainer, () => {
|
|
92
115
|
if (scrollContainer.value) {
|
|
93
|
-
innerScrollContainerRef.value = scrollContainer.value.container;
|
|
116
|
+
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
|
|
94
117
|
|
|
95
118
|
innerScrollContainerRef.value.addEventListener('scroll', () => {
|
|
96
119
|
recalculateScroll();
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
v-if="part.type === 'text'"
|
|
12
12
|
:message="part.text"
|
|
13
13
|
:role="props.message.role"
|
|
14
|
-
:state="part.state
|
|
14
|
+
:state="part.state ?? (props.message.role === 'user' ? 'done' : undefined)"
|
|
15
15
|
/>
|
|
16
16
|
</template>
|
|
17
17
|
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
behavior="smooth"
|
|
19
19
|
v-if="ToolOrReasoningParts.length > 0"
|
|
20
20
|
v-show="isExpanded"
|
|
21
|
-
|
|
21
|
+
:wrapperStyle="{
|
|
22
|
+
marginRight: '8rem',
|
|
23
|
+
}"
|
|
22
24
|
>
|
|
23
25
|
<ol class="ml-8 relative border-l border-l-2 border-black border-default border-listTableHeadingText dark:border-darkListTableHeadingText">
|
|
24
26
|
<li class="mb-6 ms-2 z-50" v-for="(part, index) in ToolOrReasoningParts" :key="index">
|
|
@@ -99,6 +101,7 @@
|
|
|
99
101
|
durationMs: finishedPart?.data?.durationMs,
|
|
100
102
|
input: part.data.input,
|
|
101
103
|
output: finishedPart?.data?.output,
|
|
104
|
+
toolInfo: part.data.toolInfo,
|
|
102
105
|
}
|
|
103
106
|
};
|
|
104
107
|
};
|
|
@@ -176,15 +179,5 @@
|
|
|
176
179
|
opacity: 1;
|
|
177
180
|
max-height: 384px;
|
|
178
181
|
}
|
|
179
|
-
|
|
180
|
-
.mask-y {
|
|
181
|
-
mask-image: linear-gradient(
|
|
182
|
-
to bottom,
|
|
183
|
-
transparent,
|
|
184
|
-
black 20px,
|
|
185
|
-
black calc(100% - 20px),
|
|
186
|
-
transparent
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
182
|
|
|
190
183
|
</style>
|
|
@@ -16,15 +16,17 @@
|
|
|
16
16
|
/>
|
|
17
17
|
</h3>
|
|
18
18
|
<transition name="expand">
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
<CustomAutoScrollContainer
|
|
20
|
+
v-if="isExpanded" v-show="isExpanded" class="mb-4 text-sm max-h-64 pl-4"
|
|
21
|
+
:wrapperStyle="{
|
|
22
|
+
marginRight: '8rem',
|
|
23
|
+
}"
|
|
24
|
+
:enabled="true"
|
|
25
|
+
>
|
|
26
|
+
<IncremarkContent
|
|
27
|
+
:content="reasoningText"
|
|
28
|
+
/>
|
|
29
|
+
</CustomAutoScrollContainer>
|
|
28
30
|
</transition>
|
|
29
31
|
</template>
|
|
30
32
|
|
|
@@ -37,10 +39,10 @@ import { ref, computed, watch, defineAsyncComponent } from 'vue';
|
|
|
37
39
|
import ThreeDotsAnimation from './ThreeDotsAnimation.vue';
|
|
38
40
|
import { extractTitleAndTextFromReasoning } from '../utils';
|
|
39
41
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
40
|
-
|
|
42
|
+
import CustomAutoScrollContainer from '../CustomAutoScrollContainer.vue';
|
|
41
43
|
|
|
42
44
|
const IncremarkContent = defineAsyncComponent(() => import('@incremark/vue').then(module => module.IncremarkContent))
|
|
43
|
-
const AutoScrollContainer = defineAsyncComponent(() => import('@incremark/vue').then(module => module.AutoScrollContainer))
|
|
45
|
+
// const AutoScrollContainer = defineAsyncComponent(() => import('@incremark/vue').then(module => module.AutoScrollContainer))
|
|
44
46
|
|
|
45
47
|
const props = defineProps<{
|
|
46
48
|
state?: IPart['state']
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
<script setup lang="ts">
|
|
38
38
|
import type { Code } from 'mdast';
|
|
39
|
-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
39
|
+
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
40
40
|
import embed from 'vega-embed';
|
|
41
41
|
|
|
42
42
|
import { highlightCodeSnippetHtml, type IncremarkCodeTheme } from './incremarkCodeHighlight';
|
|
@@ -171,7 +171,13 @@ async function renderHighlight() {
|
|
|
171
171
|
if (shouldRenderVega.value) {
|
|
172
172
|
renderedHtml.value = '';
|
|
173
173
|
|
|
174
|
-
if (!sourceCode.value
|
|
174
|
+
if (!sourceCode.value) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await nextTick();
|
|
179
|
+
|
|
180
|
+
if (requestId !== renderRequestId || !shouldRenderVega.value || !vegaContainer.value) {
|
|
175
181
|
return;
|
|
176
182
|
}
|
|
177
183
|
|
package/custom/package.json
CHANGED
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"@shikijs/themes": "^4.0.2",
|
|
19
19
|
"@vueuse/core": "^14.2.1",
|
|
20
20
|
"ai": "^6.0.168",
|
|
21
|
+
"custom-vue-scrollbar": "^0.0.8",
|
|
21
22
|
"dompurify": "^3.3.3",
|
|
22
23
|
"katex": "^0.16.45",
|
|
23
24
|
"marked": "^18.0.0",
|
|
24
|
-
"vega-embed": "^7.1.0"
|
|
25
|
-
"vue-custom-scrollbar": "^2.0.2"
|
|
25
|
+
"vega-embed": "^7.1.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
package/custom/pnpm-lock.yaml
CHANGED
|
@@ -29,6 +29,9 @@ importers:
|
|
|
29
29
|
ai:
|
|
30
30
|
specifier: ^6.0.168
|
|
31
31
|
version: 6.0.168(zod@4.3.6)
|
|
32
|
+
custom-vue-scrollbar:
|
|
33
|
+
specifier: ^0.0.8
|
|
34
|
+
version: 0.0.8(lodash-es@4.18.1)(vue@3.5.32)
|
|
32
35
|
dompurify:
|
|
33
36
|
specifier: ^3.3.3
|
|
34
37
|
version: 3.3.3
|
|
@@ -41,9 +44,6 @@ importers:
|
|
|
41
44
|
vega-embed:
|
|
42
45
|
specifier: ^7.1.0
|
|
43
46
|
version: 7.1.0(vega-lite@6.4.2(vega@6.2.0))(vega@6.2.0)
|
|
44
|
-
vue-custom-scrollbar:
|
|
45
|
-
specifier: ^2.0.2
|
|
46
|
-
version: 2.0.2(vue@3.5.32)
|
|
47
47
|
|
|
48
48
|
packages:
|
|
49
49
|
|
|
@@ -307,6 +307,12 @@ packages:
|
|
|
307
307
|
csstype@3.2.3:
|
|
308
308
|
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
|
309
309
|
|
|
310
|
+
custom-vue-scrollbar@0.0.8:
|
|
311
|
+
resolution: {integrity: sha512-JcO0B+02Kf9wXSL9SaxXVvuToaY+lvJAtmrwNfSLS3x6xx5+mO24r5/dGkNK8av0VlSDzviypYUXTjEZbwgGHA==}
|
|
312
|
+
peerDependencies:
|
|
313
|
+
lodash-es: ^4.17.21
|
|
314
|
+
vue: ^3.2.13
|
|
315
|
+
|
|
310
316
|
d3-array@3.2.4:
|
|
311
317
|
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
|
|
312
318
|
engines: {node: '>=12'}
|
|
@@ -656,9 +662,6 @@ packages:
|
|
|
656
662
|
parse-entities@4.0.2:
|
|
657
663
|
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
|
658
664
|
|
|
659
|
-
perfect-scrollbar@1.5.6:
|
|
660
|
-
resolution: {integrity: sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==}
|
|
661
|
-
|
|
662
665
|
picocolors@1.1.1:
|
|
663
666
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
|
664
667
|
|
|
@@ -879,11 +882,6 @@ packages:
|
|
|
879
882
|
vfile@6.0.3:
|
|
880
883
|
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
|
881
884
|
|
|
882
|
-
vue-custom-scrollbar@2.0.2:
|
|
883
|
-
resolution: {integrity: sha512-eRyxGb7UFLLH8P0B8FDux2uPrzNBH0X6IN+A/RB5sfmLq1ym7shbCPVKua1pC7LPqPB7dc86evFXyWO/svrfKA==}
|
|
884
|
-
peerDependencies:
|
|
885
|
-
vue: ^3.3.0
|
|
886
|
-
|
|
887
885
|
vue@3.5.32:
|
|
888
886
|
resolution: {integrity: sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==}
|
|
889
887
|
peerDependencies:
|
|
@@ -1219,6 +1217,11 @@ snapshots:
|
|
|
1219
1217
|
|
|
1220
1218
|
csstype@3.2.3: {}
|
|
1221
1219
|
|
|
1220
|
+
custom-vue-scrollbar@0.0.8(lodash-es@4.18.1)(vue@3.5.32):
|
|
1221
|
+
dependencies:
|
|
1222
|
+
lodash-es: 4.18.1
|
|
1223
|
+
vue: 3.5.32
|
|
1224
|
+
|
|
1222
1225
|
d3-array@3.2.4:
|
|
1223
1226
|
dependencies:
|
|
1224
1227
|
internmap: 2.0.3
|
|
@@ -1766,8 +1769,6 @@ snapshots:
|
|
|
1766
1769
|
is-decimal: 2.0.1
|
|
1767
1770
|
is-hexadecimal: 2.0.1
|
|
1768
1771
|
|
|
1769
|
-
perfect-scrollbar@1.5.6: {}
|
|
1770
|
-
|
|
1771
1772
|
picocolors@1.1.1: {}
|
|
1772
1773
|
|
|
1773
1774
|
postcss@8.5.10:
|
|
@@ -2142,11 +2143,6 @@ snapshots:
|
|
|
2142
2143
|
'@types/unist': 3.0.3
|
|
2143
2144
|
vfile-message: 4.0.3
|
|
2144
2145
|
|
|
2145
|
-
vue-custom-scrollbar@2.0.2(vue@3.5.32):
|
|
2146
|
-
dependencies:
|
|
2147
|
-
perfect-scrollbar: 1.5.6
|
|
2148
|
-
vue: 3.5.32
|
|
2149
|
-
|
|
2150
2146
|
vue@3.5.32:
|
|
2151
2147
|
dependencies:
|
|
2152
2148
|
'@vue/compiler-dom': 3.5.32
|
package/custom/types.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
></div>
|
|
33
33
|
|
|
34
34
|
<div
|
|
35
|
-
class="w-full h-full flex flex-col"
|
|
35
|
+
class="w-full min-h-0 max-h-full flex flex-col"
|
|
36
36
|
>
|
|
37
37
|
<div
|
|
38
38
|
class="flex items-center justify-between h-14 border-b border-gray-200 dark:border-gray-700"
|
|
@@ -91,11 +91,10 @@
|
|
|
91
91
|
|
|
92
92
|
</div>
|
|
93
93
|
<div
|
|
94
|
-
class="relative flex-1 flex flex-col overflow-hidden"
|
|
94
|
+
class="relative flex-1 min-h-0 flex flex-col overflow-hidden"
|
|
95
95
|
>
|
|
96
96
|
<ConversationArea
|
|
97
97
|
v-if="agentStore.isChatOpen"
|
|
98
|
-
class="flex-1 overflow-auto"
|
|
99
98
|
:messages="agentStore.chatMessages"
|
|
100
99
|
/>
|
|
101
100
|
|
|
@@ -1,11 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<CustomScrollbar
|
|
3
|
+
ref="containerRef"
|
|
4
|
+
class="auto-scroll-container mask-y"
|
|
5
|
+
:wrapperStyle = "wrapperStyle"
|
|
6
|
+
:contentStyle = "contentStyle"
|
|
7
|
+
>
|
|
8
|
+
<slot />
|
|
9
|
+
</CustomScrollbar>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
1
12
|
<script setup lang="ts">
|
|
2
13
|
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
|
3
|
-
import
|
|
14
|
+
import CustomScrollbar from 'custom-vue-scrollbar';
|
|
15
|
+
import 'custom-vue-scrollbar/dist/style.css';
|
|
16
|
+
import { useScroll } from '@vueuse/core'
|
|
17
|
+
import { useAgentStore } from './composables/useAgentStore';
|
|
18
|
+
|
|
19
|
+
const agentStore = useAgentStore();
|
|
4
20
|
|
|
5
21
|
const props = withDefaults(defineProps<{
|
|
6
22
|
enabled?: boolean
|
|
7
23
|
threshold?: number
|
|
8
24
|
behavior?: ScrollBehavior
|
|
25
|
+
wrapperStyle?: Record<string, string>
|
|
26
|
+
contentStyle?: Record<string, string>
|
|
9
27
|
}>(), {
|
|
10
28
|
enabled: true,
|
|
11
29
|
threshold: 50,
|
|
@@ -14,12 +32,18 @@ const props = withDefaults(defineProps<{
|
|
|
14
32
|
|
|
15
33
|
const containerRef = ref<HTMLDivElement | null>(null)
|
|
16
34
|
const isUserScrolledUp = ref(false)
|
|
35
|
+
const scrollElement = ref<HTMLElement | null>(null)
|
|
36
|
+
const { y } = useScroll(scrollElement)
|
|
37
|
+
|
|
38
|
+
watch(y, () => {
|
|
39
|
+
handleScroll()
|
|
40
|
+
})
|
|
17
41
|
|
|
18
42
|
let lastScrollTop = 0
|
|
19
43
|
let lastScrollHeight = 0
|
|
20
44
|
|
|
21
45
|
function isNearBottom(): boolean {
|
|
22
|
-
const container = containerRef.value
|
|
46
|
+
const container = containerRef.value?.scrollEl
|
|
23
47
|
if (!container) return true
|
|
24
48
|
|
|
25
49
|
const { scrollTop, scrollHeight, clientHeight } = container
|
|
@@ -27,7 +51,7 @@ function isNearBottom(): boolean {
|
|
|
27
51
|
}
|
|
28
52
|
|
|
29
53
|
function scrollToBottom(force = false): void {
|
|
30
|
-
const container = containerRef.value
|
|
54
|
+
const container = containerRef.value?.scrollEl
|
|
31
55
|
if (!container) return
|
|
32
56
|
|
|
33
57
|
if (isUserScrolledUp.value && !force) return
|
|
@@ -40,14 +64,14 @@ function scrollToBottom(force = false): void {
|
|
|
40
64
|
|
|
41
65
|
|
|
42
66
|
function hasScrollbar(): boolean {
|
|
43
|
-
const container = containerRef.value
|
|
67
|
+
const container = containerRef.value?.scrollEl
|
|
44
68
|
if (!container) return false
|
|
45
69
|
return container.scrollHeight > container.clientHeight
|
|
46
70
|
}
|
|
47
71
|
|
|
48
72
|
|
|
49
73
|
function handleScroll(): void {
|
|
50
|
-
const container = containerRef.value
|
|
74
|
+
const container = containerRef.value.scrollEl
|
|
51
75
|
if (!container) return
|
|
52
76
|
|
|
53
77
|
const { scrollTop, scrollHeight, clientHeight } = container
|
|
@@ -58,7 +82,6 @@ function handleScroll(): void {
|
|
|
58
82
|
lastScrollHeight = scrollHeight
|
|
59
83
|
return
|
|
60
84
|
}
|
|
61
|
-
|
|
62
85
|
if (isNearBottom()) {
|
|
63
86
|
isUserScrolledUp.value = false
|
|
64
87
|
} else {
|
|
@@ -69,7 +92,6 @@ function handleScroll(): void {
|
|
|
69
92
|
isUserScrolledUp.value = true
|
|
70
93
|
}
|
|
71
94
|
}
|
|
72
|
-
|
|
73
95
|
lastScrollTop = scrollTop
|
|
74
96
|
lastScrollHeight = scrollHeight
|
|
75
97
|
}
|
|
@@ -79,18 +101,19 @@ let observer: MutationObserver | null = null
|
|
|
79
101
|
onMounted(() => {
|
|
80
102
|
if (!containerRef.value) return
|
|
81
103
|
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
scrollElement.value = containerRef.value.scrollEl
|
|
105
|
+
lastScrollTop = containerRef.value.scrollEl.scrollTop
|
|
106
|
+
lastScrollHeight = containerRef.value.scrollEl.scrollHeight
|
|
84
107
|
|
|
85
108
|
observer = new MutationObserver(() => {
|
|
86
109
|
nextTick(() => {
|
|
87
|
-
if (!containerRef.value) return
|
|
110
|
+
if (!containerRef.value?.scrollEl) return
|
|
88
111
|
|
|
89
112
|
if (!hasScrollbar()) {
|
|
90
113
|
isUserScrolledUp.value = false
|
|
91
114
|
}
|
|
92
115
|
|
|
93
|
-
lastScrollHeight = containerRef.value.scrollHeight
|
|
116
|
+
lastScrollHeight = containerRef.value.scrollEl.scrollHeight
|
|
94
117
|
|
|
95
118
|
if (props.enabled && !isUserScrolledUp.value) {
|
|
96
119
|
scrollToBottom()
|
|
@@ -98,7 +121,7 @@ onMounted(() => {
|
|
|
98
121
|
})
|
|
99
122
|
})
|
|
100
123
|
|
|
101
|
-
observer.observe(containerRef.value, {
|
|
124
|
+
observer.observe(containerRef.value?.scrollEl, {
|
|
102
125
|
childList: true,
|
|
103
126
|
subtree: true,
|
|
104
127
|
characterData: true
|
|
@@ -112,16 +135,19 @@ onUnmounted(() => {
|
|
|
112
135
|
defineExpose({
|
|
113
136
|
scrollToBottom: () => scrollToBottom(true),
|
|
114
137
|
isUserScrolledUp: () => isUserScrolledUp.value,
|
|
115
|
-
container: containerRef
|
|
138
|
+
container: containerRef,
|
|
139
|
+
handleScroll
|
|
116
140
|
})
|
|
117
141
|
</script>
|
|
118
142
|
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
143
|
+
<style>
|
|
144
|
+
.mask-y {
|
|
145
|
+
mask-image: linear-gradient(
|
|
146
|
+
to bottom,
|
|
147
|
+
transparent,
|
|
148
|
+
black 20px,
|
|
149
|
+
black calc(100% - 20px),
|
|
150
|
+
transparent
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<h3 :class="h3Style">{{ $t('Chat history') }}</h3>
|
|
9
9
|
<div class="w-full flex items-center justify-center">
|
|
10
10
|
<Button
|
|
11
|
-
@click="agentStore.createPreSession(); agentStore.setSessionHistoryOpen(false); agentStore.focusTextInput();
|
|
11
|
+
@click="agentStore.createPreSession(); agentStore.setSessionHistoryOpen(false); agentStore.focusTextInput();"
|
|
12
12
|
:disabled="agentStore.isResponseInProgress"
|
|
13
13
|
class="w-[90%] my-2 mb-4 rounded-3xl text-gray-800 dark:text-gray-200"
|
|
14
14
|
>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
'bg-lightPrimary/20 hover:bg-lightPrimary/20 dark:bg-darkPrimary/20 dark:hover:bg-darkPrimary/20': agentStore.activeSessionId === session.sessionId,
|
|
35
35
|
'cursor-default opacity-50 pointer-events-none': agentStore.isResponseInProgress,
|
|
36
36
|
}"
|
|
37
|
-
@click="agentStore.setActiveSession(session.sessionId); agentStore.setSessionHistoryOpen(false);
|
|
37
|
+
@click="agentStore.setActiveSession(session.sessionId); agentStore.setSessionHistoryOpen(false);"
|
|
38
38
|
:disabled="agentStore.isResponseInProgress"
|
|
39
39
|
>
|
|
40
40
|
<p class="truncate">{{ session.title || session.sessionId }}</p>
|
|
@@ -99,13 +99,4 @@ const groupedSessions = computed(() => {
|
|
|
99
99
|
return Array.from(groups.values());
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
-
const emit = defineEmits<{
|
|
103
|
-
(e: 'recalculateScroll'): void
|
|
104
|
-
}>()
|
|
105
|
-
|
|
106
|
-
function recalculateScroll() {
|
|
107
|
-
// Emit an event to notify the parent component to recalculate scroll
|
|
108
|
-
emit('recalculateScroll');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
102
|
</script>
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<button @click="scrollContainer.scrollToBottom(); recalculateScroll();">
|
|
3
|
-
<IconArrowDownOutline
|
|
4
|
-
class="absolute z-10 bottom-32 left-1/2 bg-lightPrimary dark:bg-darkPrimary text-white p-2 w-10 h-10 rounded-full transition-opacity duration-100 ease-in"
|
|
5
|
-
:class="showScrollToBottomButton ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
|
6
|
-
:disabled="!showScrollToBottomButton"
|
|
7
|
-
/>
|
|
8
|
-
</button>
|
|
9
|
-
|
|
10
2
|
<SessionsHistory
|
|
11
3
|
:class="agentStore.isSessionHistoryOpen ? 'translate-x-0' : '-translate-x-full'"
|
|
12
4
|
@recalculateScroll="recalculateScroll"
|
|
@@ -16,38 +8,59 @@
|
|
|
16
8
|
@click="agentStore.setSessionHistoryOpen(false)"
|
|
17
9
|
class="absolute bg-black/10 backdrop-blur-md z-10 h-full w-full"
|
|
18
10
|
>
|
|
19
|
-
|
|
20
11
|
</div>
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
12
|
+
<div class="relative flex-1 min-h-0 overflow-hidden">
|
|
13
|
+
<button @click="scrollContainer.scrollToBottom(); recalculateScroll();">
|
|
14
|
+
<IconArrowDownOutline
|
|
15
|
+
class="absolute z-10 bottom-8 left-1/2 bg-lightPrimary dark:bg-darkPrimary text-white p-2 w-10 h-10 rounded-full transition-opacity duration-100 ease-in"
|
|
16
|
+
:class="showScrollToBottomButton ? 'opacity-100' : 'opacity-0 pointer-events-none'"
|
|
17
|
+
:disabled="!showScrollToBottomButton"
|
|
18
|
+
/>
|
|
19
|
+
</button>
|
|
20
|
+
<CustomAutoScrollContainer
|
|
21
|
+
v-if="showScrollContainer"
|
|
22
|
+
:enabled="!showScrollToBottomButton"
|
|
23
|
+
class="relative h-full flex flex-col overflow-y-auto translate-x-[-50%] left-1/2"
|
|
24
|
+
ref="scrollContainer"
|
|
25
|
+
:threshold="10"
|
|
26
|
+
behavior="smooth"
|
|
27
|
+
:wrapperStyle = "{
|
|
28
|
+
height: '100%',
|
|
29
|
+
maxHeight: '100%',
|
|
30
|
+
maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
|
|
31
|
+
width: '100%',
|
|
32
|
+
marginLeft: 'auto',
|
|
33
|
+
marginRight: 'auto',
|
|
34
|
+
}"
|
|
35
|
+
:contentStyle="{
|
|
36
|
+
height: '100%',
|
|
37
|
+
maxHeight: '100%',
|
|
38
|
+
}"
|
|
39
|
+
:style="{
|
|
40
|
+
maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
|
|
41
|
+
transition: `
|
|
42
|
+
max-width ${agentTransitions.TRANSITION_DURATION}ms ease-in-out,
|
|
43
|
+
transform ${agentTransitions.TRANSITION_DURATION}ms ease-in-out
|
|
44
|
+
`
|
|
45
|
+
}"
|
|
46
|
+
>
|
|
35
47
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
<div
|
|
49
|
+
v-for="(message, index) in props.messages" :key="message.id"
|
|
50
|
+
class="flex flex-col w-full"
|
|
51
|
+
:class="message.role === 'user' ? 'self-end' : 'self-start'"
|
|
52
|
+
>
|
|
53
|
+
<MessageRenderer :message="message" :isLastMessageInChat="index === props.messages.length - 1"/>
|
|
54
|
+
</div>
|
|
55
|
+
<div
|
|
56
|
+
v-if="props.messages.length === 0"
|
|
57
|
+
class="flex-1 flex flex-col items-center justify-center text-gray-400 tracking-widest text-xl font-medium h-full"
|
|
58
|
+
>
|
|
59
|
+
<p>{{ $t('Start the conversation') }}</p>
|
|
60
|
+
<p class="tracking-normal text-base text">{{ $t('Give any input to begin') }}</p>
|
|
61
|
+
</div>
|
|
62
|
+
</CustomAutoScrollContainer>
|
|
63
|
+
</div>
|
|
51
64
|
</template>
|
|
52
65
|
|
|
53
66
|
|
|
@@ -71,14 +84,24 @@ const innerScrollContainerRef = ref(null);
|
|
|
71
84
|
const agentStore = useAgentStore();
|
|
72
85
|
const agentTransitions = useAgentTransitions();
|
|
73
86
|
const clicks = ref(0);
|
|
87
|
+
const showScrollContainer = ref(true);
|
|
74
88
|
|
|
75
89
|
function recalculateScroll() {
|
|
76
90
|
if (scrollContainer.value) {
|
|
91
|
+
scrollContainer.value.handleScroll();
|
|
77
92
|
const isScrolledUp = scrollContainer.value.isUserScrolledUp();
|
|
78
93
|
showScrollToBottomButton.value = !!isScrolledUp;
|
|
79
94
|
}
|
|
80
95
|
}
|
|
81
96
|
|
|
97
|
+
watch(() => agentStore.activeSessionId, async () => {
|
|
98
|
+
showScrollContainer.value = false;
|
|
99
|
+
await nextTick();
|
|
100
|
+
showScrollContainer.value = true;
|
|
101
|
+
await nextTick();
|
|
102
|
+
recalculateScroll();
|
|
103
|
+
});
|
|
104
|
+
|
|
82
105
|
onMounted(async () => {
|
|
83
106
|
await import('@incremark/theme/styles.css')
|
|
84
107
|
await agentStore.fetchPlaceholderMessages()
|
|
@@ -90,7 +113,7 @@ onUnmounted(() => {
|
|
|
90
113
|
|
|
91
114
|
watch(scrollContainer, () => {
|
|
92
115
|
if (scrollContainer.value) {
|
|
93
|
-
innerScrollContainerRef.value = scrollContainer.value.container;
|
|
116
|
+
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
|
|
94
117
|
|
|
95
118
|
innerScrollContainerRef.value.addEventListener('scroll', () => {
|
|
96
119
|
recalculateScroll();
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
v-if="part.type === 'text'"
|
|
12
12
|
:message="part.text"
|
|
13
13
|
:role="props.message.role"
|
|
14
|
-
:state="part.state
|
|
14
|
+
:state="part.state ?? (props.message.role === 'user' ? 'done' : undefined)"
|
|
15
15
|
/>
|
|
16
16
|
</template>
|
|
17
17
|
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
behavior="smooth"
|
|
19
19
|
v-if="ToolOrReasoningParts.length > 0"
|
|
20
20
|
v-show="isExpanded"
|
|
21
|
-
|
|
21
|
+
:wrapperStyle="{
|
|
22
|
+
marginRight: '8rem',
|
|
23
|
+
}"
|
|
22
24
|
>
|
|
23
25
|
<ol class="ml-8 relative border-l border-l-2 border-black border-default border-listTableHeadingText dark:border-darkListTableHeadingText">
|
|
24
26
|
<li class="mb-6 ms-2 z-50" v-for="(part, index) in ToolOrReasoningParts" :key="index">
|
|
@@ -99,6 +101,7 @@
|
|
|
99
101
|
durationMs: finishedPart?.data?.durationMs,
|
|
100
102
|
input: part.data.input,
|
|
101
103
|
output: finishedPart?.data?.output,
|
|
104
|
+
toolInfo: part.data.toolInfo,
|
|
102
105
|
}
|
|
103
106
|
};
|
|
104
107
|
};
|
|
@@ -176,15 +179,5 @@
|
|
|
176
179
|
opacity: 1;
|
|
177
180
|
max-height: 384px;
|
|
178
181
|
}
|
|
179
|
-
|
|
180
|
-
.mask-y {
|
|
181
|
-
mask-image: linear-gradient(
|
|
182
|
-
to bottom,
|
|
183
|
-
transparent,
|
|
184
|
-
black 20px,
|
|
185
|
-
black calc(100% - 20px),
|
|
186
|
-
transparent
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
182
|
|
|
190
183
|
</style>
|
|
@@ -16,15 +16,17 @@
|
|
|
16
16
|
/>
|
|
17
17
|
</h3>
|
|
18
18
|
<transition name="expand">
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
<CustomAutoScrollContainer
|
|
20
|
+
v-if="isExpanded" v-show="isExpanded" class="mb-4 text-sm max-h-64 pl-4"
|
|
21
|
+
:wrapperStyle="{
|
|
22
|
+
marginRight: '8rem',
|
|
23
|
+
}"
|
|
24
|
+
:enabled="true"
|
|
25
|
+
>
|
|
26
|
+
<IncremarkContent
|
|
27
|
+
:content="reasoningText"
|
|
28
|
+
/>
|
|
29
|
+
</CustomAutoScrollContainer>
|
|
28
30
|
</transition>
|
|
29
31
|
</template>
|
|
30
32
|
|
|
@@ -37,10 +39,10 @@ import { ref, computed, watch, defineAsyncComponent } from 'vue';
|
|
|
37
39
|
import ThreeDotsAnimation from './ThreeDotsAnimation.vue';
|
|
38
40
|
import { extractTitleAndTextFromReasoning } from '../utils';
|
|
39
41
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
40
|
-
|
|
42
|
+
import CustomAutoScrollContainer from '../CustomAutoScrollContainer.vue';
|
|
41
43
|
|
|
42
44
|
const IncremarkContent = defineAsyncComponent(() => import('@incremark/vue').then(module => module.IncremarkContent))
|
|
43
|
-
const AutoScrollContainer = defineAsyncComponent(() => import('@incremark/vue').then(module => module.AutoScrollContainer))
|
|
45
|
+
// const AutoScrollContainer = defineAsyncComponent(() => import('@incremark/vue').then(module => module.AutoScrollContainer))
|
|
44
46
|
|
|
45
47
|
const props = defineProps<{
|
|
46
48
|
state?: IPart['state']
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
<script setup lang="ts">
|
|
38
38
|
import type { Code } from 'mdast';
|
|
39
|
-
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
39
|
+
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
|
40
40
|
import embed from 'vega-embed';
|
|
41
41
|
|
|
42
42
|
import { highlightCodeSnippetHtml, type IncremarkCodeTheme } from './incremarkCodeHighlight';
|
|
@@ -171,7 +171,13 @@ async function renderHighlight() {
|
|
|
171
171
|
if (shouldRenderVega.value) {
|
|
172
172
|
renderedHtml.value = '';
|
|
173
173
|
|
|
174
|
-
if (!sourceCode.value
|
|
174
|
+
if (!sourceCode.value) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await nextTick();
|
|
179
|
+
|
|
180
|
+
if (requestId !== renderRequestId || !shouldRenderVega.value || !vegaContainer.value) {
|
|
175
181
|
return;
|
|
176
182
|
}
|
|
177
183
|
|
package/dist/custom/package.json
CHANGED
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
"@shikijs/themes": "^4.0.2",
|
|
19
19
|
"@vueuse/core": "^14.2.1",
|
|
20
20
|
"ai": "^6.0.168",
|
|
21
|
+
"custom-vue-scrollbar": "^0.0.8",
|
|
21
22
|
"dompurify": "^3.3.3",
|
|
22
23
|
"katex": "^0.16.45",
|
|
23
24
|
"marked": "^18.0.0",
|
|
24
|
-
"vega-embed": "^7.1.0"
|
|
25
|
-
"vue-custom-scrollbar": "^2.0.2"
|
|
25
|
+
"vega-embed": "^7.1.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -29,6 +29,9 @@ importers:
|
|
|
29
29
|
ai:
|
|
30
30
|
specifier: ^6.0.168
|
|
31
31
|
version: 6.0.168(zod@4.3.6)
|
|
32
|
+
custom-vue-scrollbar:
|
|
33
|
+
specifier: ^0.0.8
|
|
34
|
+
version: 0.0.8(lodash-es@4.18.1)(vue@3.5.32)
|
|
32
35
|
dompurify:
|
|
33
36
|
specifier: ^3.3.3
|
|
34
37
|
version: 3.3.3
|
|
@@ -41,9 +44,6 @@ importers:
|
|
|
41
44
|
vega-embed:
|
|
42
45
|
specifier: ^7.1.0
|
|
43
46
|
version: 7.1.0(vega-lite@6.4.2(vega@6.2.0))(vega@6.2.0)
|
|
44
|
-
vue-custom-scrollbar:
|
|
45
|
-
specifier: ^2.0.2
|
|
46
|
-
version: 2.0.2(vue@3.5.32)
|
|
47
47
|
|
|
48
48
|
packages:
|
|
49
49
|
|
|
@@ -307,6 +307,12 @@ packages:
|
|
|
307
307
|
csstype@3.2.3:
|
|
308
308
|
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
|
309
309
|
|
|
310
|
+
custom-vue-scrollbar@0.0.8:
|
|
311
|
+
resolution: {integrity: sha512-JcO0B+02Kf9wXSL9SaxXVvuToaY+lvJAtmrwNfSLS3x6xx5+mO24r5/dGkNK8av0VlSDzviypYUXTjEZbwgGHA==}
|
|
312
|
+
peerDependencies:
|
|
313
|
+
lodash-es: ^4.17.21
|
|
314
|
+
vue: ^3.2.13
|
|
315
|
+
|
|
310
316
|
d3-array@3.2.4:
|
|
311
317
|
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
|
|
312
318
|
engines: {node: '>=12'}
|
|
@@ -656,9 +662,6 @@ packages:
|
|
|
656
662
|
parse-entities@4.0.2:
|
|
657
663
|
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
|
658
664
|
|
|
659
|
-
perfect-scrollbar@1.5.6:
|
|
660
|
-
resolution: {integrity: sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw==}
|
|
661
|
-
|
|
662
665
|
picocolors@1.1.1:
|
|
663
666
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
|
664
667
|
|
|
@@ -879,11 +882,6 @@ packages:
|
|
|
879
882
|
vfile@6.0.3:
|
|
880
883
|
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
|
|
881
884
|
|
|
882
|
-
vue-custom-scrollbar@2.0.2:
|
|
883
|
-
resolution: {integrity: sha512-eRyxGb7UFLLH8P0B8FDux2uPrzNBH0X6IN+A/RB5sfmLq1ym7shbCPVKua1pC7LPqPB7dc86evFXyWO/svrfKA==}
|
|
884
|
-
peerDependencies:
|
|
885
|
-
vue: ^3.3.0
|
|
886
|
-
|
|
887
885
|
vue@3.5.32:
|
|
888
886
|
resolution: {integrity: sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==}
|
|
889
887
|
peerDependencies:
|
|
@@ -1219,6 +1217,11 @@ snapshots:
|
|
|
1219
1217
|
|
|
1220
1218
|
csstype@3.2.3: {}
|
|
1221
1219
|
|
|
1220
|
+
custom-vue-scrollbar@0.0.8(lodash-es@4.18.1)(vue@3.5.32):
|
|
1221
|
+
dependencies:
|
|
1222
|
+
lodash-es: 4.18.1
|
|
1223
|
+
vue: 3.5.32
|
|
1224
|
+
|
|
1222
1225
|
d3-array@3.2.4:
|
|
1223
1226
|
dependencies:
|
|
1224
1227
|
internmap: 2.0.3
|
|
@@ -1766,8 +1769,6 @@ snapshots:
|
|
|
1766
1769
|
is-decimal: 2.0.1
|
|
1767
1770
|
is-hexadecimal: 2.0.1
|
|
1768
1771
|
|
|
1769
|
-
perfect-scrollbar@1.5.6: {}
|
|
1770
|
-
|
|
1771
1772
|
picocolors@1.1.1: {}
|
|
1772
1773
|
|
|
1773
1774
|
postcss@8.5.10:
|
|
@@ -2142,11 +2143,6 @@ snapshots:
|
|
|
2142
2143
|
'@types/unist': 3.0.3
|
|
2143
2144
|
vfile-message: 4.0.3
|
|
2144
2145
|
|
|
2145
|
-
vue-custom-scrollbar@2.0.2(vue@3.5.32):
|
|
2146
|
-
dependencies:
|
|
2147
|
-
perfect-scrollbar: 1.5.6
|
|
2148
|
-
vue: 3.5.32
|
|
2149
|
-
|
|
2150
2146
|
vue@3.5.32:
|
|
2151
2147
|
dependencies:
|
|
2152
2148
|
'@vue/compiler-dom': 3.5.32
|
package/dist/custom/types.ts
CHANGED