@adminforth/agent 2.0.10 → 2.2.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 (201) hide show
  1. package/README.md +333 -10
  2. package/dist/application/ports.d.ts +66 -0
  3. package/dist/application/runTurnUseCase.d.ts +71 -0
  4. package/dist/application/runTurnUseCase.js +364 -0
  5. package/dist/custom/ChatFooter.vue +58 -30
  6. package/dist/custom/SteerDebugPanel.vue +45 -0
  7. package/dist/custom/SteerQueue.vue +54 -0
  8. package/dist/custom/composables/agentStore/constants.ts +1 -0
  9. package/dist/custom/composables/agentStore/useAgentSessions.ts +35 -16
  10. package/dist/custom/composables/agentStore/useAgentSteerQueue.ts +114 -0
  11. package/dist/custom/composables/useAgentStore.ts +46 -1
  12. package/dist/custom/conversation_area/MessageRenderer.vue +7 -1
  13. package/dist/custom/speech_recognition_frontend/AudioLines.vue +1 -1
  14. package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +3 -3
  15. package/dist/{agentEvents.d.ts → domain/agentEvents.d.ts} +5 -1
  16. package/dist/domain/steerBuffer.d.ts +33 -0
  17. package/dist/domain/steerBuffer.js +51 -0
  18. package/dist/{agent → domain}/systemPrompt.js +1 -1
  19. package/dist/{agent/turn → domain}/turnTypes.d.ts +41 -37
  20. package/dist/{agent/turn/VegaLiteStreamBuffer.d.ts → domain/vegaLiteStreamBuffer.d.ts} +1 -1
  21. package/dist/index.d.ts +4 -2
  22. package/dist/index.js +49 -35
  23. package/dist/{agent/runtime/AgentContext.d.ts → llm/agentContext.d.ts} +3 -3
  24. package/dist/{agent/simpleAgent.d.ts → llm/agentModels.d.ts} +18 -16
  25. package/dist/llm/agentModels.js +65 -0
  26. package/dist/{agent/runtime/AgentRuntime.d.ts → llm/agentRuntime.d.ts} +14 -2
  27. package/dist/{agent/runtime/AgentRuntime.js → llm/agentRuntime.js} +41 -6
  28. package/dist/llm/langGraphLlm.d.ts +25 -0
  29. package/dist/llm/langGraphLlm.js +54 -0
  30. package/dist/{agent/middleware/apiBasedTools.d.ts → llm/middleware/apiToolsMiddleware.d.ts} +1 -1
  31. package/dist/{agent/middleware/apiBasedTools.js → llm/middleware/apiToolsMiddleware.js} +8 -14
  32. package/dist/{agent → llm}/middleware/sequenceDebug.d.ts +1 -1
  33. package/dist/llm/middleware/steerMiddleware.d.ts +21 -0
  34. package/dist/llm/middleware/steerMiddleware.js +50 -0
  35. package/dist/{agent/models/AgentModelFactory.d.ts → llm/modelFactory.d.ts} +1 -1
  36. package/dist/{agent/models/AgentModelFactory.js → llm/modelFactory.js} +1 -1
  37. package/dist/llm/streamAdapter.d.ts +18 -0
  38. package/dist/llm/streamAdapter.js +117 -0
  39. package/dist/{sessionStore.d.ts → persistence/sessionStore.d.ts} +19 -2
  40. package/dist/{sessionStore.js → persistence/sessionStore.js} +53 -0
  41. package/dist/{agent/tools/AgentToolProvider.d.ts → tools/agentToolProvider.d.ts} +1 -1
  42. package/dist/{agent/tools/AgentToolProvider.js → tools/agentToolProvider.js} +1 -1
  43. package/dist/{apiBasedTools.js → tools/apiBasedTools.js} +0 -3
  44. package/dist/{agent/tools → tools}/apiTool.d.ts +1 -1
  45. package/dist/{agent/tools → tools}/fetchSkill.js +1 -1
  46. package/dist/{agent/tools → tools}/fetchToolSchema.d.ts +1 -1
  47. package/dist/{agent/tools → tools}/index.d.ts +1 -1
  48. package/dist/{agent/tools → tools}/navigateUser.d.ts +3 -3
  49. package/dist/{endpoints → transport/http}/context.d.ts +12 -4
  50. package/dist/transport/http/context.js +1 -0
  51. package/dist/{endpoints/core.js → transport/http/coreEndpoints.js} +23 -3
  52. package/dist/{endpoints/sessions.js → transport/http/sessionEndpoints.js} +36 -1
  53. package/dist/transport/sse/sseWriter.d.ts +29 -0
  54. package/dist/{surfaces/web-sse/createSseEventEmitter.js → transport/sse/sseWriter.js} +27 -0
  55. package/dist/{chatSurfaceService.d.ts → transport/surfaces/chatSurfaceService.d.ts} +3 -3
  56. package/dist/{chatSurfaceService.js → transport/surfaces/chatSurfaceService.js} +7 -5
  57. package/dist/{agent/speech/SpeechTurnService.d.ts → transport/surfaces/speechTurnService.d.ts} +1 -1
  58. package/dist/{agent/speech/SpeechTurnService.js → transport/surfaces/speechTurnService.js} +2 -2
  59. package/dist/types.d.ts +10 -4
  60. package/package.json +11 -2
  61. package/.woodpecker/buildRelease.sh +0 -13
  62. package/.woodpecker/buildSlackNotify.sh +0 -46
  63. package/.woodpecker/release.yml +0 -57
  64. package/agent/checkpointer.ts +0 -329
  65. package/agent/languageDetect.ts +0 -92
  66. package/agent/middleware/apiBasedTools.ts +0 -174
  67. package/agent/middleware/openAiResponsesContinuation.ts +0 -92
  68. package/agent/middleware/sequenceDebug.ts +0 -429
  69. package/agent/models/AgentModeResolver.ts +0 -9
  70. package/agent/models/AgentModelFactory.ts +0 -28
  71. package/agent/runtime/AgentContext.ts +0 -30
  72. package/agent/runtime/AgentRuntime.ts +0 -89
  73. package/agent/simpleAgent.ts +0 -199
  74. package/agent/skills/registry.ts +0 -162
  75. package/agent/speech/SpeechTurnService.ts +0 -179
  76. package/agent/systemPrompt.ts +0 -133
  77. package/agent/toolCallEvents.ts +0 -135
  78. package/agent/tools/AgentToolProvider.ts +0 -28
  79. package/agent/tools/apiTool.ts +0 -66
  80. package/agent/tools/fetchSkill.ts +0 -68
  81. package/agent/tools/fetchToolSchema.ts +0 -47
  82. package/agent/tools/getUserLocation.ts +0 -45
  83. package/agent/tools/index.ts +0 -31
  84. package/agent/tools/navigateUser.ts +0 -210
  85. package/agent/turn/TurnContextBuilder.ts +0 -36
  86. package/agent/turn/TurnLifecycleService.ts +0 -47
  87. package/agent/turn/TurnPersistenceService.ts +0 -33
  88. package/agent/turn/TurnPromptBuilder.ts +0 -51
  89. package/agent/turn/TurnStreamConsumer.ts +0 -69
  90. package/agent/turn/VegaLiteStreamBuffer.ts +0 -90
  91. package/agent/turn/turnTypes.ts +0 -100
  92. package/agentEvents.ts +0 -75
  93. package/agentTurnService.ts +0 -314
  94. package/apiBasedTools.ts +0 -712
  95. package/build.log +0 -67
  96. package/chatSurfaceService.ts +0 -319
  97. package/custom/ChatFooter.vue +0 -173
  98. package/custom/ChatHeader.vue +0 -78
  99. package/custom/ChatSurface.vue +0 -160
  100. package/custom/CustomAutoScrollContainer.vue +0 -164
  101. package/custom/SessionsHistory.vue +0 -88
  102. package/custom/chat.ts +0 -82
  103. package/custom/composables/agentAudio/utils.ts +0 -220
  104. package/custom/composables/agentStore/constants.ts +0 -19
  105. package/custom/composables/agentStore/pageContext.ts +0 -8
  106. package/custom/composables/agentStore/useAgentChat.ts +0 -241
  107. package/custom/composables/agentStore/useAgentPlaceholder.ts +0 -142
  108. package/custom/composables/agentStore/useAgentSessions.ts +0 -350
  109. package/custom/composables/useAgentAudio.ts +0 -272
  110. package/custom/composables/useAgentStore.ts +0 -510
  111. package/custom/composables/useAgentTransitions.ts +0 -58
  112. package/custom/conversation_area/ConversationArea.vue +0 -301
  113. package/custom/conversation_area/MessageRenderer.vue +0 -49
  114. package/custom/conversation_area/ProcessingTimeline.vue +0 -286
  115. package/custom/conversation_area/ReasoningRenderer.vue +0 -79
  116. package/custom/conversation_area/SystemMessageRenderer.vue +0 -28
  117. package/custom/conversation_area/TextRenderer.vue +0 -182
  118. package/custom/conversation_area/ThreeDotsAnimation.vue +0 -35
  119. package/custom/conversation_area/ToolApprovalRenderer.vue +0 -98
  120. package/custom/conversation_area/ToolRenderer.vue +0 -178
  121. package/custom/conversation_area/ToolsGroup.vue +0 -59
  122. package/custom/env.d.ts +0 -7
  123. package/custom/incremark_code_renderers/IncremarkShikiCodeBlock.vue +0 -393
  124. package/custom/incremark_code_renderers/incremarkCodeHighlight.ts +0 -285
  125. package/custom/incremark_code_renderers/incremarkRenderer.ts +0 -653
  126. package/custom/incremark_code_renderers/renderIncremarkMarkdown.ts +0 -118
  127. package/custom/package.json +0 -30
  128. package/custom/pnpm-lock.yaml +0 -2394
  129. package/custom/public/agentAudio/agent-processing.mp3 +0 -0
  130. package/custom/skills/analyze_data/SKILL.md +0 -25
  131. package/custom/skills/charts/SKILL.md +0 -193
  132. package/custom/skills/fetch_data/SKILL.md +0 -31
  133. package/custom/skills/mutate_data/SKILL.md +0 -121
  134. package/custom/speech_recognition_frontend/AudioLines.vue +0 -43
  135. package/custom/speech_recognition_frontend/MicrophoneButon.vue +0 -185
  136. package/custom/speech_recognition_frontend/types/voice-activity-detection.d.ts +0 -22
  137. package/custom/speech_recognition_frontend/voiceActivityDetection.ts +0 -62
  138. package/custom/tsconfig.json +0 -15
  139. package/custom/types.ts +0 -108
  140. package/custom/utils.ts +0 -38
  141. package/dist/agent/middleware/openAiResponsesContinuation.d.ts +0 -1
  142. package/dist/agent/middleware/openAiResponsesContinuation.js +0 -66
  143. package/dist/agent/models/AgentModeResolver.d.ts +0 -9
  144. package/dist/agent/models/AgentModeResolver.js +0 -9
  145. package/dist/agent/simpleAgent.js +0 -118
  146. package/dist/agent/turn/TurnContextBuilder.d.ts +0 -14
  147. package/dist/agent/turn/TurnContextBuilder.js +0 -31
  148. package/dist/agent/turn/TurnLifecycleService.d.ts +0 -24
  149. package/dist/agent/turn/TurnLifecycleService.js +0 -47
  150. package/dist/agent/turn/TurnPersistenceService.d.ts +0 -13
  151. package/dist/agent/turn/TurnPersistenceService.js +0 -35
  152. package/dist/agent/turn/TurnPromptBuilder.d.ts +0 -19
  153. package/dist/agent/turn/TurnPromptBuilder.js +0 -43
  154. package/dist/agent/turn/TurnStreamConsumer.d.ts +0 -11
  155. package/dist/agent/turn/TurnStreamConsumer.js +0 -84
  156. package/dist/agentTurnService.d.ts +0 -24
  157. package/dist/agentTurnService.js +0 -269
  158. package/dist/surfaces/web-sse/createSseEventEmitter.d.ts +0 -14
  159. package/endpoints/chatSurfaces.ts +0 -66
  160. package/endpoints/context.ts +0 -52
  161. package/endpoints/core.ts +0 -181
  162. package/endpoints/sessions.ts +0 -183
  163. package/errors.ts +0 -10
  164. package/index.ts +0 -192
  165. package/pnpm-workspace.yaml +0 -4
  166. package/sanitizeSpeechText.ts +0 -32
  167. package/sessionStore.ts +0 -105
  168. package/surfaces/web-sse/createSseEventEmitter.ts +0 -311
  169. package/tsconfig.json +0 -14
  170. package/types.ts +0 -127
  171. /package/dist/{agent/turn/turnTypes.js → application/ports.js} +0 -0
  172. /package/dist/{agentEvents.js → domain/agentEvents.js} +0 -0
  173. /package/dist/{agent → domain}/languageDetect.d.ts +0 -0
  174. /package/dist/{agent → domain}/languageDetect.js +0 -0
  175. /package/dist/{agent → domain}/systemPrompt.d.ts +0 -0
  176. /package/dist/{agent → domain}/toolCallEvents.d.ts +0 -0
  177. /package/dist/{agent → domain}/toolCallEvents.js +0 -0
  178. /package/dist/{endpoints/context.js → domain/turnTypes.js} +0 -0
  179. /package/dist/{agent/turn/VegaLiteStreamBuffer.js → domain/vegaLiteStreamBuffer.js} +0 -0
  180. /package/dist/{agent/runtime/AgentContext.js → llm/agentContext.js} +0 -0
  181. /package/dist/{agent → llm}/middleware/sequenceDebug.js +0 -0
  182. /package/dist/{agent/checkpointer.d.ts → persistence/checkpointStore.d.ts} +0 -0
  183. /package/dist/{agent/checkpointer.js → persistence/checkpointStore.js} +0 -0
  184. /package/dist/{errors.d.ts → shared/errors.d.ts} +0 -0
  185. /package/dist/{errors.js → shared/errors.js} +0 -0
  186. /package/dist/{sanitizeSpeechText.d.ts → shared/sanitizeSpeechText.d.ts} +0 -0
  187. /package/dist/{sanitizeSpeechText.js → shared/sanitizeSpeechText.js} +0 -0
  188. /package/dist/{apiBasedTools.d.ts → tools/apiBasedTools.d.ts} +0 -0
  189. /package/dist/{agent/tools → tools}/apiTool.js +0 -0
  190. /package/dist/{agent/tools → tools}/fetchSkill.d.ts +0 -0
  191. /package/dist/{agent/tools → tools}/fetchToolSchema.js +0 -0
  192. /package/dist/{agent/tools → tools}/getUserLocation.d.ts +0 -0
  193. /package/dist/{agent/tools → tools}/getUserLocation.js +0 -0
  194. /package/dist/{agent/tools → tools}/index.js +0 -0
  195. /package/dist/{agent/tools → tools}/navigateUser.js +0 -0
  196. /package/dist/{agent → tools}/skills/registry.d.ts +0 -0
  197. /package/dist/{agent → tools}/skills/registry.js +0 -0
  198. /package/dist/{endpoints/chatSurfaces.d.ts → transport/http/chatSurfaceEndpoints.d.ts} +0 -0
  199. /package/dist/{endpoints/chatSurfaces.js → transport/http/chatSurfaceEndpoints.js} +0 -0
  200. /package/dist/{endpoints/core.d.ts → transport/http/coreEndpoints.d.ts} +0 -0
  201. /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>