@adminforth/agent 2.0.10 → 2.1.0

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 (187) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +68 -0
  4. package/dist/application/runTurnUseCase.js +358 -0
  5. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +1 -1
  6. package/dist/{agent → domain}/systemPrompt.js +1 -1
  7. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  8. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.js +40 -35
  11. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  12. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  13. package/dist/llm/agentModels.js +65 -0
  14. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +11 -2
  15. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +38 -6
  16. package/dist/llm/langGraphLlm.d.ts +25 -0
  17. package/dist/llm/langGraphLlm.js +54 -0
  18. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  19. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  20. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  21. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  22. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  23. package/dist/llm/streamAdapter.d.ts +18 -0
  24. package/dist/llm/streamAdapter.js +117 -0
  25. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +12 -2
  26. package/dist/{sessionStore.js → persistence/sessionStore.js} +33 -0
  27. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  28. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  29. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
  30. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  31. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  32. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  33. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  34. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  35. package/dist/{endpoints → transport/http}/context.d.ts +2 -2
  36. package/dist/transport/http/context.js +1 -0
  37. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +3 -3
  38. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +7 -1
  39. package/dist/transport/sse/sseWriter.d.ts +29 -0
  40. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +15 -0
  41. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  42. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  43. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  44. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  45. package/dist/types.d.ts +10 -4
  46. package/package.json +11 -2
  47. package/.woodpecker/buildRelease.sh +0 -13
  48. package/.woodpecker/buildSlackNotify.sh +0 -46
  49. package/.woodpecker/release.yml +0 -57
  50. package/agent/checkpointer.ts +0 -329
  51. package/agent/languageDetect.ts +0 -92
  52. package/agent/middleware/apiBasedTools.ts +0 -174
  53. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  54. package/agent/middleware/sequenceDebug.ts +0 -429
  55. package/agent/models/AgentModeResolver.ts +0 -9
  56. package/agent/models/AgentModelFactory.ts +0 -28
  57. package/agent/runtime/AgentContext.ts +0 -30
  58. package/agent/runtime/AgentRuntime.ts +0 -89
  59. package/agent/simpleAgent.ts +0 -199
  60. package/agent/skills/registry.ts +0 -162
  61. package/agent/speech/SpeechTurnService.ts +0 -179
  62. package/agent/systemPrompt.ts +0 -133
  63. package/agent/toolCallEvents.ts +0 -135
  64. package/agent/tools/AgentToolProvider.ts +0 -28
  65. package/agent/tools/apiTool.ts +0 -66
  66. package/agent/tools/fetchSkill.ts +0 -68
  67. package/agent/tools/fetchToolSchema.ts +0 -47
  68. package/agent/tools/getUserLocation.ts +0 -45
  69. package/agent/tools/index.ts +0 -31
  70. package/agent/tools/navigateUser.ts +0 -210
  71. package/agent/turn/TurnContextBuilder.ts +0 -36
  72. package/agent/turn/TurnLifecycleService.ts +0 -47
  73. package/agent/turn/TurnPersistenceService.ts +0 -33
  74. package/agent/turn/TurnPromptBuilder.ts +0 -51
  75. package/agent/turn/TurnStreamConsumer.ts +0 -69
  76. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  77. package/agent/turn/turnTypes.ts +0 -100
  78. package/agentEvents.ts +0 -75
  79. package/agentTurnService.ts +0 -314
  80. package/apiBasedTools.ts +0 -712
  81. package/build.log +0 -67
  82. package/chatSurfaceService.ts +0 -319
  83. package/custom/ChatFooter.vue +0 -173
  84. package/custom/ChatHeader.vue +0 -78
  85. package/custom/ChatSurface.vue +0 -160
  86. package/custom/CustomAutoScrollContainer.vue +0 -164
  87. package/custom/SessionsHistory.vue +0 -88
  88. package/custom/chat.ts +0 -82
  89. package/custom/composables/agentAudio/utils.ts +0 -220
  90. package/custom/composables/agentStore/constants.ts +0 -19
  91. package/custom/composables/agentStore/pageContext.ts +0 -8
  92. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  93. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  94. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  95. package/custom/composables/useAgentAudio.ts +0 -272
  96. package/custom/composables/useAgentStore.ts +0 -510
  97. package/custom/composables/useAgentTransitions.ts +0 -58
  98. package/custom/conversation_area/ConversationArea.vue +0 -301
  99. package/custom/conversation_area/MessageRenderer.vue +0 -49
  100. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  101. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  102. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  103. package/custom/conversation_area/TextRenderer.vue +0 -182
  104. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  105. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  106. package/custom/conversation_area/ToolRenderer.vue +0 -178
  107. package/custom/conversation_area/ToolsGroup.vue +0 -59
  108. package/custom/env.d.ts +0 -7
  109. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  110. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  111. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  112. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  113. package/custom/package.json +0 -30
  114. package/custom/pnpm-lock.yaml +0 -2394
  115. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  116. package/custom/skills/analyze_data/SKILL.md +0 -25
  117. package/custom/skills/charts/SKILL.md +0 -193
  118. package/custom/skills/fetch_data/SKILL.md +0 -31
  119. package/custom/skills/mutate_data/SKILL.md +0 -121
  120. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  121. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  122. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  123. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  124. package/custom/tsconfig.json +0 -15
  125. package/custom/types.ts +0 -108
  126. package/custom/utils.ts +0 -38
  127. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  128. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  129. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  130. package/dist/agent/models/AgentModeResolver.js +0 -9
  131. package/dist/agent/simpleAgent.js +0 -118
  132. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  133. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  134. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  135. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  136. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  137. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  138. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  139. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  140. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  141. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  142. package/dist/agentTurnService.d.ts +0 -24
  143. package/dist/agentTurnService.js +0 -269
  144. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  145. package/endpoints/chatSurfaces.ts +0 -66
  146. package/endpoints/context.ts +0 -52
  147. package/endpoints/core.ts +0 -181
  148. package/endpoints/sessions.ts +0 -183
  149. package/errors.ts +0 -10
  150. package/index.ts +0 -192
  151. package/pnpm-workspace.yaml +0 -4
  152. package/sanitizeSpeechText.ts +0 -32
  153. package/sessionStore.ts +0 -105
  154. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  155. package/tsconfig.json +0 -14
  156. package/types.ts +0 -127
  157. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  158. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  159. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  160. /package/dist/{agent → domain}/languageDetect.js +0 -0
  161. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  162. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  163. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  164. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  165. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  166. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  167. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  168. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  169. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  170. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  171. /package/dist/{errors.js → shared/errors.js} +0 -0
  172. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  173. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  174. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  175. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  176. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  177. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  178. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  179. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  180. /package/dist/{agent/tools → tools}/index.js +0 -0
  181. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  182. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  183. /package/dist/{agent → tools}/skills/registry.js +0 -0
  184. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  185. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  186. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  187. /package/dist/{endpoints/sessions.d.ts → transport/http/sessionEndpoints.d.ts} +0 -0
@@ -1,301 +0,0 @@
1
- <template>
2
- <SessionsHistory
3
- :class="agentStore.isSessionHistoryOpen ? 'translate-x-0' : '-translate-x-full'"
4
- />
5
- <div
6
- v-if="agentStore.isSessionHistoryOpen"
7
- @click="agentStore.setSessionHistoryOpen(false)"
8
- class="absolute bg-black/10 backdrop-blur-md z-10 h-full w-full"
9
- >
10
- </div>
11
- <div ref="chatContainerRef" class="relative flex-1 min-h-0 overflow-hidden" @click="recalculateScroll()">
12
- <CustomAutoScrollContainer
13
- v-if="showScrollContainer"
14
- :enabled="!showScrollToBottomButton"
15
- class="relative h-full flex flex-col overflow-y-auto translate-x-[-50%] left-1/2"
16
- ref="scrollContainer"
17
- :threshold="THRESHOLD_TO_SHOW_BUTTON"
18
- behavior="smooth"
19
- :wrapperStyle = "{
20
- height: '100%',
21
- maxHeight: '100%',
22
- maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
23
- width: '100%',
24
- marginLeft: 'auto',
25
- marginRight: 'auto',
26
- }"
27
- :style="{
28
- maxWidth: agentStore.isFullScreen ? agentStore.MAX_WIDTH+'rem' : '100%',
29
- transition: `
30
- max-width ${agentTransitions.TRANSITION_DURATION}ms ease-in-out,
31
- transform ${agentTransitions.TRANSITION_DURATION}ms ease-in-out
32
- `
33
- }"
34
- >
35
-
36
- <div
37
- v-for="(message, index) in props.messages" :key="index"
38
- class="flex flex-col w-full mt-2 pb-2"
39
- :class="message.role === 'user' ? 'self-end' : 'self-start'"
40
- ref="messagesRefs"
41
- >
42
- <MessageRenderer :message="message" :isLastMessageInChat="index === props.messages.length - 1"/>
43
- </div>
44
- <div
45
- v-if="props.messages.length === 0"
46
- class="flex-1 flex flex-col items-center justify-center text-gray-400 tracking-widest text-xl font-medium h-max"
47
- :style="{
48
- height: chatContainerRef ? chatContainerRef.clientHeight + 'px' : '100%',
49
- }"
50
- >
51
- <p>{{ $t('Start the conversation') }}</p>
52
- <p class="tracking-normal text-base text">{{ $t('Give any input to begin') }}</p>
53
- </div>
54
- <div v-if="showBottomSpacer" class="w-full" :style="{ height: spacerHeight + 'px' }"></div>
55
- </CustomAutoScrollContainer>
56
- <button @click="scrollContainer.scrollToBottom();">
57
- <IconArrowDownOutline
58
- class="absolute z-10 bottom-8 left-1/2 -translate-x-1/2 bg-lightPrimary/20 dark:bg-darkPrimary/10
59
- border border-lightPrimary dark:border-darkPrimary text-lightPrimary dark:text-darkPrimary p-2 w-10 h-10
60
- rounded-full transition-opacity duration-100 ease-in backdrop-blur-sm"
61
- :class="showScrollToBottomButton ? 'opacity-100' : 'opacity-0 pointer-events-none'"
62
- :disabled="!showScrollToBottomButton"
63
- />
64
- </button>
65
- </div>
66
- </template>
67
-
68
-
69
- <script setup lang="ts">
70
- import type { IMessage } from '../types';
71
- import { useTemplateRef, ref, onMounted, onUnmounted, watch, nextTick, defineAsyncComponent } from 'vue';
72
- import { IconArrowDownOutline } from '@iconify-prerendered/vue-flowbite';
73
- import SessionsHistory from '../SessionsHistory.vue';
74
- import { useAgentStore } from '../composables/useAgentStore';
75
- import { useAgentTransitions } from '../composables/useAgentTransitions';
76
- import MessageRenderer from './MessageRenderer.vue';
77
-
78
- const CustomAutoScrollContainer = defineAsyncComponent(() => import('../CustomAutoScrollContainer.vue'));
79
-
80
- const props = defineProps<{
81
- messages: IMessage[]
82
- }>();
83
-
84
- defineExpose({
85
- handleSendMessage
86
- });
87
-
88
- const scrollContainer = useTemplateRef('scrollContainer');
89
- const showScrollToBottomButton = ref(false);
90
- const innerScrollContainerRef = ref<HTMLElement | null>(null);
91
- const agentStore = useAgentStore();
92
- const agentTransitions = useAgentTransitions();
93
- const showScrollContainer = ref(true);
94
- const chatContainerRef = ref<HTMLElement | null>(null);
95
- const messagesRefs = ref<Array<HTMLElement | null>>([]);
96
- /*
97
- * Whenever user sends a message, it adds a bottom spacer, that takes the remaining height
98
- * without last user and last agent message.
99
- *
100
- * On send message, happens the following logic:
101
- * 1) showBottomSpacer is set to true
102
- * 2) updateSpacerHeight is called, which calculates the height for spacer based on scroll container height and messages height
103
- * 3) Spacer moves text up
104
- */
105
- const showBottomSpacer = ref(false);
106
- const spacerHeight = ref(0);
107
- const MASK_HEIGHT = 20;
108
- const EMPTY_MESSAGE_HEIGHT = 18;
109
- const THRESHOLD_TO_SHOW_BUTTON = 10;
110
- let messageResizeObserver: ResizeObserver | null = null;
111
- let observedLastUserMessageElement: HTMLElement | null = null;
112
- let observedLastAgentMessageElement: HTMLElement | null = null;
113
- let updateSpacerFrameId: number | null = null;
114
- let pendingSpacerUpdate: Promise<void> | null = null;
115
- let spacerUpdateQueued = false;
116
-
117
- onMounted(async () => {
118
- messageResizeObserver = new ResizeObserver(() => {
119
- scheduleSpacerHeightUpdate();
120
- });
121
-
122
- await import('@incremark/theme/styles.css')
123
- await agentStore.fetchPlaceholderMessages()
124
- await refreshSpacerTracking();
125
- });
126
-
127
- onUnmounted(() => {
128
- if (innerScrollContainerRef.value) {
129
- innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
130
- }
131
-
132
- stopObservingLastMessages();
133
- messageResizeObserver?.disconnect();
134
- if (updateSpacerFrameId !== null) {
135
- cancelAnimationFrame(updateSpacerFrameId);
136
- updateSpacerFrameId = null;
137
- }
138
- agentStore.stopPlaceholderAnimation();
139
- });
140
-
141
- watch(() => agentStore.activeSessionId, () => {
142
- resetSpacer();
143
- });
144
-
145
- watch(() => agentStore.activeSessionId, async () => {
146
- showScrollContainer.value = false;
147
- await nextTick();
148
- showScrollContainer.value = true;
149
- await refreshSpacerTracking();
150
- recalculateScroll();
151
- });
152
-
153
- watch(() => props.messages.length, async () => {
154
- await refreshSpacerTracking();
155
- });
156
-
157
- watch(scrollContainer, async () => {
158
- if (innerScrollContainerRef.value) {
159
- innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
160
- }
161
-
162
- if (scrollContainer.value) {
163
- innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
164
-
165
- innerScrollContainerRef.value.addEventListener('scroll', recalculateScroll);
166
- await refreshSpacerTracking();
167
- }
168
- })
169
-
170
- function resetSpacer() {
171
- showBottomSpacer.value = false;
172
- spacerHeight.value = 0;
173
- }
174
-
175
- function getLastMessageElement(role: 'user' | 'assistant') {
176
- const lastMessageIndex = props.messages.findLastIndex((message: IMessage) => message.role === role);
177
- return messagesRefs.value[lastMessageIndex] ?? null;
178
- }
179
-
180
- function getHeightOfLastUserMessage() {
181
- return getLastMessageElement('user')?.clientHeight ?? 0;
182
- }
183
-
184
- function getHeightOfLastAgentMessage() {
185
- return getLastMessageElement('assistant')?.clientHeight ?? 0;
186
- }
187
-
188
- function getScrollClientHeight() {
189
- return scrollContainer.value?.container.scrollEl.clientHeight ?? scrollContainer.value?.scrollParams.clientHeight ?? 0;
190
- }
191
-
192
- async function updateSpacerHeight() {
193
- if (!showBottomSpacer.value) {
194
- return;
195
- }
196
-
197
- const clientHeight = getScrollClientHeight();
198
-
199
- if (!clientHeight) {
200
- return;
201
- }
202
-
203
- const lastUserMessageHeight = getHeightOfLastUserMessage();
204
- const lastAgentMessageHeight = getHeightOfLastAgentMessage();
205
-
206
- spacerHeight.value = Math.max(0, clientHeight - (lastUserMessageHeight + MASK_HEIGHT + lastAgentMessageHeight));
207
- }
208
-
209
- function scheduleSpacerHeightUpdate() {
210
- spacerUpdateQueued = true;
211
-
212
- if (updateSpacerFrameId !== null) {
213
- return;
214
- }
215
-
216
- updateSpacerFrameId = requestAnimationFrame(() => {
217
- updateSpacerFrameId = null;
218
-
219
- if (pendingSpacerUpdate) {
220
- return;
221
- }
222
-
223
- spacerUpdateQueued = false;
224
- pendingSpacerUpdate = updateSpacerHeight().finally(() => {
225
- pendingSpacerUpdate = null;
226
-
227
- // Auto-scroll to bottom if response generation is in progress
228
- if (agentStore.isResponseInProgress) {
229
- nextTick(() => {
230
- scrollContainer.value?.scrollToBottom();
231
- });
232
- }
233
-
234
- if (spacerUpdateQueued) {
235
- scheduleSpacerHeightUpdate();
236
- }
237
- });
238
- });
239
- }
240
-
241
- function stopObservingLastMessages() {
242
- if (!messageResizeObserver) {
243
- return;
244
- }
245
-
246
- if (observedLastUserMessageElement) {
247
- messageResizeObserver.unobserve(observedLastUserMessageElement);
248
- observedLastUserMessageElement = null;
249
- }
250
-
251
- if (observedLastAgentMessageElement) {
252
- messageResizeObserver.unobserve(observedLastAgentMessageElement);
253
- observedLastAgentMessageElement = null;
254
- }
255
- }
256
-
257
- function observeLastMessages() {
258
- if (!messageResizeObserver) {
259
- return;
260
- }
261
-
262
- stopObservingLastMessages();
263
-
264
- observedLastUserMessageElement = getLastMessageElement('user');
265
- observedLastAgentMessageElement = getLastMessageElement('assistant');
266
-
267
- if (observedLastUserMessageElement) {
268
- messageResizeObserver.observe(observedLastUserMessageElement);
269
- }
270
-
271
- if (observedLastAgentMessageElement) {
272
- messageResizeObserver.observe(observedLastAgentMessageElement);
273
- }
274
- }
275
-
276
- async function refreshSpacerTracking() {
277
- await nextTick();
278
- observeLastMessages();
279
- await updateSpacerHeight();
280
- }
281
-
282
- async function handleSendMessage() {
283
- const clientHeight = getScrollClientHeight();
284
-
285
- if (clientHeight) {
286
- showBottomSpacer.value = true;
287
- await updateSpacerHeight();
288
- await nextTick();
289
- scrollContainer.value?.scrollToBottom();
290
- }
291
- }
292
-
293
- function recalculateScroll() {
294
- if (scrollContainer.value) {
295
- scrollContainer.value.handleScroll(false,spacerHeight.value + THRESHOLD_TO_SHOW_BUTTON);
296
- const isScrolledUp = scrollContainer.value.isUserScrolledUp();
297
- showScrollToBottomButton.value = !!isScrolledUp;
298
- }
299
- }
300
-
301
- </script>
@@ -1,49 +0,0 @@
1
- <template>
2
- <ProcessingTimeline
3
- :message="message"
4
- :isLastMessageInChat="isLastMessageInChat"
5
- />
6
- <template
7
- v-for="(part, index) in getMessageParts(message)"
8
- :key="part.type"
9
- >
10
- <TextRenderer
11
- v-if="part.type === 'text' && !checkIfMessageSystemMessage(part.text ?? '')"
12
- :message="part.text"
13
- :role="props.message.role"
14
- :state="part.state ?? (props.message.role === 'user' ? 'done' : undefined)"
15
- />
16
- <ToolApprovalRenderer
17
- v-else-if="part.type === 'data-tool-approval'"
18
- :data="part.data ?? {}"
19
- />
20
- <SystemMessageRenderer
21
- v-else-if="part.type === 'text'"
22
- :message="part.text"
23
- />
24
- </template>
25
-
26
- </template>
27
-
28
-
29
-
30
-
31
- <script setup lang="ts">
32
- import TextRenderer from './TextRenderer.vue';
33
- import type { IMessage } from '../types';
34
- import { getMessageParts } from '../utils';
35
- import ProcessingTimeline from './ProcessingTimeline.vue';
36
- import SystemMessageRenderer from './SystemMessageRenderer.vue';
37
- import ToolApprovalRenderer from './ToolApprovalRenderer.vue';
38
- import { RESERVED_SYSTEM_MESSAGE_CONTENT } from '../composables/agentStore/constants';
39
-
40
- const props = defineProps<{
41
- message: IMessage
42
- isLastMessageInChat: boolean
43
- }>();
44
-
45
- function checkIfMessageSystemMessage(message: IMessage): boolean {
46
- const isReserved = Object.values(RESERVED_SYSTEM_MESSAGE_CONTENT).includes(message as RESERVED_SYSTEM_MESSAGE_CONTENT);
47
- return isReserved;
48
- }
49
- </script>
@@ -1,286 +0,0 @@
1
- <template>
2
- <template v-if="ToolOrReasoningParts.length > 0 || inProgress">
3
- <div
4
- class="shine-text-container ml-2 px-4 flex items-center gap-1 select-none hover:opacity-80 tracking-wide font-medium text-sm text-listTableHeadingText dark:text-darkListTableHeadingText"
5
- :class="[ToolOrReasoningParts.length > 0 ? 'cursor-pointer' : '']"
6
- @click="isExpanded = !isExpanded"
7
- >
8
- <p
9
- :class="[
10
- inProgress ? `
11
- shine-text text-listTableHeadingText dark:text-darkListTableHeadingText
12
- bg-[linear-gradient(-65deg,currentColor,_rgb(120,120,120)_50%,currentColor)]
13
- dark:bg-[linear-gradient(-65deg,currentColor,_rgb(250,250,250,0.8)_70%,currentColor)]
14
- `
15
- : '']"
16
- >
17
- {{ inProgress ? $t('Thinking') : $t('Thoughts') }}
18
- </p>
19
-
20
- <span v-if="thinkingDuration > 0">({{ (thinkingDuration/1000).toFixed(2) }} s)</span>
21
- <IconAngleDownOutline
22
- v-if="ToolOrReasoningParts.length > 0"
23
- :class="isExpanded ? 'rotate-180' : 'rotate-0'"
24
- class="transition-transform duration-200"
25
- />
26
- </div>
27
- <transition name="expand" class="sm:max-h-96 max-h-48 overflow-y-auto mb-4 pt-1">
28
- <CustomAutoScrollContainer
29
- ref="scrollContainerRef"
30
- :enabled="isResponseInProgress"
31
- behavior="smooth"
32
- v-if="ToolOrReasoningParts.length > 0"
33
- v-show="isExpanded"
34
- :threshold="5"
35
- :wrapperStyle="{
36
- marginRight: '1rem',
37
- }"
38
- :scrollBarAutoHide="false"
39
- >
40
- <ol class="ml-8 my-2 relative border-l border-l-2 border-black border-default border-listTableHeadingText dark:border-darkListTableHeadingText">
41
- <template v-for="(part, index) in ToolOrReasoningParts" :key="index">
42
- <ReasoningRenderer v-if="part.type === 'reasoning'" :state="part.state" :text="part.text" />
43
- <ToolsGroup v-else-if="part.type==='data-tool-call'" :toolGroup="groupToolCallParts(message, part)" :isExpanded="isExpanded" />
44
- <li v-else-if="part.type === 'data-rendering'" class="mb-6 mx-2 mt-2 px-2 z-50 overflow-hidden">
45
- <span class="bg-lightNavbar dark:bg-darkNavbar absolute flex items-center text-listTableHeadingText dark:text-darkListTableHeadingText justify-center w-5 h-5 rounded-full -start-[0.68rem] ring-4 ring-lightNavbar dark:ring-darkNavbar">
46
- <div class="w-2 h-2 rounded-full bg-current animate-pulse"></div>
47
- </span>
48
- <h3 class="flex items-center mb-1 text-sm ml-3 gap-1 text-listTableHeadingText dark:text-darkListTableHeadingText">
49
- <span class="font-semibold">{{ part.data?.label ?? 'Rendering...' }}</span>
50
- <ThreeDotsAnimation />
51
- </h3>
52
- </li>
53
- </template>
54
- </ol>
55
- </CustomAutoScrollContainer>
56
- </transition>
57
- </template>
58
- </template>
59
-
60
-
61
-
62
- <script setup lang="ts">
63
- import type { IFormattedToolCallPart, IMessage, IPart, IToolGroup } from '../types';
64
- import { ref, computed, watch, onUnmounted, onMounted, defineAsyncComponent } from 'vue';
65
- import ReasoningRenderer from './ReasoningRenderer.vue';
66
- import { IconAngleDownOutline } from '@iconify-prerendered/vue-flowbite';
67
- import ThreeDotsAnimation from './ThreeDotsAnimation.vue';
68
- import { useAgentStore } from '../composables/useAgentStore';
69
- import { getMessageParts } from '../utils';
70
- import ToolsGroup from './ToolsGroup.vue';
71
-
72
- const CustomAutoScrollContainer = defineAsyncComponent(() => import('../CustomAutoScrollContainer.vue'));
73
-
74
- const props = defineProps<{
75
- message: IMessage
76
- isLastMessageInChat: boolean
77
- }>()
78
-
79
- const agentStore = useAgentStore();
80
- const thinkingStartTime = ref<number | null>(null);
81
- const thinkingDuration = ref(0);
82
- const scrollContainerRef = ref<InstanceType<typeof CustomAutoScrollContainer> | null>(null);
83
- const innerScrollContainerRef = ref<HTMLElement | null>(null);
84
- const isExpanded = ref(true);
85
- let isUserScrolled = false;
86
- const ToolOrReasoningParts = computed(() => {
87
- return props.message.parts.filter((part: IPart) => {
88
- return part.type === 'data-tool-call'
89
- || part.type === 'reasoning'
90
- || isActiveRenderingPart(part);
91
- });
92
- });
93
- const isResponseInProgress = computed(() =>{
94
- return props.isLastMessageInChat && agentStore.isResponseInProgress;
95
- });
96
-
97
- const showFakeThinkingMessage = computed(() => {
98
- if (props.message.parts.length === 0 && props.isLastMessageInChat) return true;
99
- return false;
100
- })
101
-
102
- const inProgress = computed(() => {
103
- return isResponseInProgress.value || showFakeThinkingMessage.value;
104
- })
105
-
106
- onMounted(() => {
107
- thinkingStartTime.value = Date.now();
108
- if (isResponseInProgress.value) {
109
- isExpanded.value = true;
110
- } else {
111
- isExpanded.value = false;
112
- }
113
- })
114
-
115
- onUnmounted(() => {
116
- scrollContainerRef.value?.container.scrollEl?.removeEventListener('scroll', handleScroll);
117
- scrollContainerRef.value?.container.scrollEl?.removeEventListener('wheel', toggleIsUserScrolled);
118
- scrollContainerRef.value?.container.scrollEl?.removeEventListener('touchmove', toggleIsUserScrolled);
119
- })
120
-
121
- watch(scrollContainerRef, async () => {
122
- if (innerScrollContainerRef.value) {
123
- innerScrollContainerRef.value.removeEventListener('scroll', handleScroll);
124
- innerScrollContainerRef.value.removeEventListener('wheel', toggleIsUserScrolled);
125
- innerScrollContainerRef.value.removeEventListener('touchmove', toggleIsUserScrolled);
126
- }
127
-
128
- if (scrollContainerRef.value) {
129
- innerScrollContainerRef.value = scrollContainerRef.value.container.scrollEl;
130
- innerScrollContainerRef.value.addEventListener('scroll', handleScroll);
131
- innerScrollContainerRef.value.addEventListener('wheel', toggleIsUserScrolled);
132
- innerScrollContainerRef.value.addEventListener('touchmove', toggleIsUserScrolled);
133
-
134
- }
135
- })
136
-
137
- watch(isResponseInProgress, (newValue: boolean) => {
138
- if (!newValue) {
139
- isExpanded.value = false;
140
- thinkingDuration.value = Date.now() - (thinkingStartTime.value ?? Date.now());
141
- }
142
- });
143
-
144
- const formatToolCallPart = (part: IPart, currentMessage: IMessage): IFormattedToolCallPart | null => {
145
- if (part.type !== 'data-tool-call' || part.data?.phase !== 'start') {
146
- return null;
147
- }
148
-
149
- const finishedPart = currentMessage.parts.find(candidate => {
150
- return candidate.type === 'data-tool-call'
151
- && candidate.data?.toolCallId === part.data?.toolCallId
152
- && candidate.data?.phase === 'end';
153
- });
154
-
155
- return {
156
- type: 'data-tool-call',
157
- toolInfo: {
158
- toolCallId: part.data.toolCallId,
159
- toolName: part.data.toolName,
160
- phase: finishedPart ? 'end' : 'start',
161
- durationMs: finishedPart?.data?.durationMs,
162
- input: part.data.input,
163
- output: finishedPart?.data?.output,
164
- toolInfo: part.data.toolInfo,
165
- error: finishedPart?.data?.error,
166
- }
167
- };
168
- };
169
-
170
- const getVisibleTimelineParts = (message: IMessage) => {
171
- return getMessageParts(message).filter(part => {
172
- return part.type === 'reasoning' || (part.type === 'data-tool-call' && part.data?.phase === 'start');
173
- });
174
- };
175
-
176
- function isActiveRenderingPart(part: IPart) {
177
- return part.type === 'data-rendering'
178
- && part.data?.phase === 'start'
179
- && !props.message.parts.some((candidate: IPart) => {
180
- return candidate.type === 'data-rendering' && candidate.data?.phase === 'end';
181
- });
182
- }
183
-
184
- const groupToolCallParts = (message: IMessage, currentPart: IPart): IToolGroup[] => {
185
- if (currentPart.type !== 'data-tool-call') {
186
- return [];
187
- }
188
-
189
- const visibleParts = getVisibleTimelineParts(message);
190
- const currentPartIndex = visibleParts.findIndex(part => part === currentPart);
191
-
192
- if (currentPartIndex === -1) {
193
- return [];
194
- }
195
-
196
- if (currentPartIndex > 0 && visibleParts[currentPartIndex - 1]?.type === 'data-tool-call') {
197
- return [];
198
- }
199
-
200
- const groupedParts: IToolGroup[] = [];
201
-
202
- for (let index = currentPartIndex; index < visibleParts.length; index += 1) {
203
- const part = visibleParts[index];
204
-
205
- if (part.type === 'reasoning') {
206
- break;
207
- }
208
-
209
- const formattedPart = formatToolCallPart(part, message);
210
-
211
- if (!formattedPart) {
212
- continue;
213
- }
214
-
215
- const lastGroup = groupedParts[groupedParts.length - 1];
216
-
217
- if (lastGroup?.title === formattedPart.toolInfo.toolName) {
218
- lastGroup.groupedTools.push(formattedPart);
219
- continue;
220
- }
221
-
222
- groupedParts.push({
223
- title: formattedPart.toolInfo.toolName,
224
- groupedTools: [formattedPart],
225
- });
226
- }
227
-
228
- return groupedParts;
229
- };
230
-
231
- function handleScroll() {
232
- if (isUserScrolled) {
233
- scrollContainerRef.value?.handleScroll();
234
- }
235
- }
236
-
237
- function toggleIsUserScrolled() {
238
- isUserScrolled = true;
239
- setTimeout(() => {
240
- isUserScrolled = false;
241
- }, 100);
242
- }
243
- </script>
244
-
245
- <style scoped>
246
- .expand-enter-active,
247
- .expand-leave-active {
248
- transition: all 0.3s ease;
249
- }
250
-
251
- .expand-enter-from,
252
- .expand-leave-to {
253
- opacity: 0;
254
- max-height: 0;
255
- }
256
-
257
- .expand-enter-to,
258
- .expand-leave-from {
259
- opacity: 1;
260
- max-height: 384px;
261
-
262
- @media (max-width: 640px) {
263
- max-height: 192px;
264
- }
265
- }
266
-
267
-
268
- .shine-text {
269
-
270
- background-clip: text;
271
- -webkit-background-clip: text;
272
- -webkit-text-fill-color: transparent;
273
- background-position: -12rem;
274
- }
275
-
276
- .shine-text {
277
- animation: shineText 6s infinite linear;
278
- }
279
-
280
- @keyframes shineText {
281
- to {
282
- background-position: -100%;
283
- }
284
- }
285
-
286
- </style>