@quidgest/chatbot 0.5.3-dev.0 → 0.5.3

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 (41) hide show
  1. package/dist/components/ChatBot/ChatBot.vue.d.ts +0 -2
  2. package/dist/components/ChatBot/types.d.ts +4 -3
  3. package/dist/components/ChatBotInput/ChatBotInput.vue.d.ts +3 -3
  4. package/dist/components/ChatBotInput/index.d.ts +2 -2
  5. package/dist/components/ChatBotInput/types.d.ts +4 -4
  6. package/dist/components/ChatBotMessage/ChatBotMessage.vue.d.ts +1 -3
  7. package/dist/components/ChatBotMessage/__tests__/ChatBotMessage.spec.d.ts +1 -0
  8. package/dist/components/ChatBotMessage/types.d.ts +3 -2
  9. package/dist/components/FieldPreview/FieldPreview.vue.d.ts +0 -2
  10. package/dist/composables/useChatApi.d.ts +1 -1
  11. package/dist/composables/useChatMessages.d.ts +2 -2
  12. package/dist/composables/useTexts.d.ts +1 -4
  13. package/dist/index.js +25 -25
  14. package/dist/index.mjs +2308 -1661
  15. package/dist/style.css +1 -1
  16. package/package.json +3 -2
  17. package/src/assets/styles/preview-file.scss +70 -0
  18. package/src/assets/styles/styles.scss +9 -33
  19. package/src/components/ChatBot/ChatBot.vue +70 -71
  20. package/src/components/ChatBot/types.ts +4 -3
  21. package/src/components/ChatBotInput/ChatBotInput.vue +81 -74
  22. package/src/components/ChatBotInput/__tests__/ChatBotInput.spec.ts +29 -42
  23. package/src/components/ChatBotInput/__tests__/__snapshots__/ChatBotInput.spec.ts.snap +5 -5
  24. package/src/components/ChatBotInput/index.ts +2 -2
  25. package/src/components/ChatBotInput/types.ts +4 -4
  26. package/src/components/ChatBotMessage/ChatBotMessage.vue +34 -8
  27. package/src/components/ChatBotMessage/__tests__/ChatBotMessage.spec.ts +256 -0
  28. package/src/components/ChatBotMessage/__tests__/ChatBotMessageButtons.spec.ts +4 -4
  29. package/src/components/ChatBotMessage/__tests__/__snapshots__/ChatBotMessage.spec.ts.snap +35 -0
  30. package/src/components/ChatBotMessage/types.ts +4 -3
  31. package/src/components/ChatToolBar/ChatToolBar.vue +1 -2
  32. package/src/components/ChatToolBar/__tests__/ChatToolBar.spec.ts +18 -38
  33. package/src/components/FieldPreview/FieldPreview.vue +9 -31
  34. package/src/components/FieldPreview/__tests__/__snapshots__/FieldPreview.spec.ts.snap +11 -5
  35. package/src/components/FieldPreview/field-preview.scss +0 -4
  36. package/src/components/MarkdownRender/MarkdownRender.vue +0 -1
  37. package/src/composables/__tests__/useChatMessages.spec.ts +1 -14
  38. package/src/composables/useChatApi.ts +53 -57
  39. package/src/composables/useChatMessages.ts +4 -8
  40. package/src/composables/useTexts.ts +2 -5
  41. package/src/test/setup.ts +0 -5
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .markdown-renderer pre,.markdown-renderer code{white-space:pre-wrap;overflow-wrap:anywhere;overflow-x:auto}.markdown-renderer pre{position:relative;background-color:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:.75rem 1rem;font-size:.875rem}.markdown-renderer code{padding:.2rem .4rem;border-radius:4px;font-size:.875rem}.q-field-preview{position:relative;display:flex;flex-direction:column;margin:1rem .25rem}.q-field-preview__toolbar{z-index:1;display:flex;flex-direction:row;align-items:center;justify-content:space-between;padding:.1rem .2rem}.q-field-preview__content{position:relative;background-color:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:.75rem 1rem;font-size:.875rem}.q-field-preview__content.preserve-whitespace{white-space:pre-wrap}.q-field-preview__footer{display:flex;flex-direction:row;margin-top:.25rem}.q-field-preview:first-child{margin:0 1rem .25rem .25rem}.pulsing-dots{display:flex;align-items:center;justify-content:center;flex-direction:row;gap:.25rem}.generating-text{font-size:.9rem;color:var(--q-theme-primary)}.dots-container{display:flex;align-items:center;gap:.1rem}.dot{font-size:16px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}.q-chatbot{width:100%;height:100%;display:flex;flex-direction:column}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__text p{margin:0}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;flex-direction:column;gap:.75rem;overflow:hidden}.q-chatbot__footer-container{padding:.8rem 0 0}.q-chatbot__input-wrapper{display:flex;flex-direction:column;position:relative}.q-chatbot__image-preview{display:inline-flex;align-items:center;position:relative;margin-top:.5rem;width:fit-content}.q-chatbot__image-preview img{width:60px;height:60px;object-fit:cover;border-radius:4px;margin-right:.25rem;border:1px solid #eaebec;overflow:hidden}.q-chatbot__image-preview img:hover+.q-chatbot__remove-image,.q-chatbot__image-preview img:focus+.q-chatbot__remove-image{opacity:1;pointer-events:auto}.q-chatbot__image-preview img:focus{outline:solid rgb(var(--q-theme-info-rgb)/50%)}.q-chatbot .q-button.q-chatbot__remove-image{position:absolute;top:-5px;right:-5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;font-size:12px;border:none;opacity:0;pointer-events:none;transition:opacity .2s ease-in-out}.q-chatbot .q-button.q-chatbot__remove-image:hover,.q-chatbot .q-button.q-chatbot__remove-image:focus{opacity:1;pointer-events:auto}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/25%);cursor:not-allowed}.q-chatbot__footer.drag-over{border:2px dashed rgb(var(--q-theme-primary-rgb)/25%);background-color:#018bd20d}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:space-between;max-width:100%;padding:.25rem .5rem}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{padding:.3rem .5rem;background-color:#eaebec;width:fit-content;min-height:2rem;white-space:normal;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem;white-space:normal}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__dialog-title{margin:.5rem 0}.hidden-input{display:none}
1
+ .markdown-renderer pre,.markdown-renderer code{white-space:pre-wrap;overflow-wrap:anywhere;overflow-x:auto}.markdown-renderer pre{position:relative;background-color:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:.75rem 1rem;font-size:.875rem}.markdown-renderer code{padding:.2rem .4rem;border-radius:4px;font-size:.875rem}.q-field-preview{position:relative;display:flex;flex-direction:column;margin:1rem .25rem}.q-field-preview__toolbar{z-index:1;display:flex;flex-direction:row;align-items:center;justify-content:space-between;padding:.1rem .2rem}.q-field-preview__content{position:relative;background-color:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:.75rem 1rem;font-size:.875rem}.q-field-preview__footer{display:flex;flex-direction:row;margin-top:.25rem}.q-field-preview:first-child{margin:0 1rem .25rem .25rem}.pulsing-dots{display:flex;align-items:center;justify-content:center;flex-direction:row;gap:.25rem}.generating-text{font-size:.9rem;color:var(--q-theme-primary)}.dots-container{display:flex;align-items:center;gap:.1rem}.dot{font-size:16px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}.q-chatbot__file-preview img,.q-chatbot__image-preview img{width:60px;height:60px;object-fit:cover;border-radius:4px;margin-right:.25rem;border:1px solid #eaebec;overflow:hidden}.q-chatbot__file-preview{display:inline-flex;align-items:center;position:relative;margin-top:.5rem;gap:.25rem;width:fit-content}.q-chatbot__file-preview img:focus{outline:solid rgb(var(--q-theme-info-rgb)/50%)}.q-chatbot__file-preview-container{display:flex;border-radius:.5rem;padding:.25rem .5rem;max-width:320px;align-items:center;justify-content:center;border:1px solid var(--q-theme-primary-light)}.q-chatbot__file-icon-container{display:flex;align-items:center;justify-content:center;border-radius:8px;width:36px;height:36px;flex-shrink:0;margin-right:10px;background:var(--q-theme-primary-light)}.q-chatbot__file-icon-container .q-icon{width:20px;height:20px}.q-chatbot__file-info{display:flex;flex-direction:column;overflow:hidden}.q-chatbot__file-name{font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.q-chatbot__file-extension{font-size:10px}.q-chatbot{width:100%;height:100%;display:flex;flex-direction:column}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__remove-file{position:absolute;top:-8px;right:-8px}.q-chatbot__text p{margin:0}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;flex-direction:column;gap:.75rem;overflow:hidden}.q-chatbot__footer-container{padding:.8rem 0 0}.q-chatbot__input-wrapper{display:flex;flex-direction:column;position:relative}.q-chatbot .q-button.q-chatbot__remove-file{position:absolute;top:-5px;right:-5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;font-size:10px;border:none}.q-chatbot .q-button.q-chatbot__remove-file:hover,.q-chatbot .q-button.q-chatbot__remove-file:focus{opacity:1;pointer-events:auto}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/25%);cursor:not-allowed}.q-chatbot__footer.drag-over{border:2px dashed rgb(var(--q-theme-primary-rgb)/25%);background-color:#018bd20d}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:space-between;max-width:100%;padding:.25rem .5rem}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{padding:.3rem .5rem;background-color:#eaebec;width:fit-content;min-height:2rem;white-space:normal;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem;white-space:normal}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__dialog-title{margin:.5rem 0}.hidden-input{display:none}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quidgest/chatbot",
3
3
  "private": false,
4
- "version": "0.5.3-dev.0",
4
+ "version": "0.5.3",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "main": "dist/index.cjs",
@@ -57,6 +57,7 @@
57
57
  "prettier": "^3.3.3",
58
58
  "rimraf": "^5.0.10",
59
59
  "sass": "^1.77.8",
60
+ "semver": "^7.7.2",
60
61
  "stylelint": "^16.23.1",
61
62
  "stylelint-config-standard-scss": "^15.0.1",
62
63
  "typescript": "^5.5.4",
@@ -66,7 +67,7 @@
66
67
  "vue-tsc": "^1.8.27"
67
68
  },
68
69
  "peerDependencies": {
69
- "@quidgest/ui": "0.16.19",
70
+ "@quidgest/ui": "0.16.12",
70
71
  "vue": "3.5.17"
71
72
  },
72
73
  "engines": {
@@ -0,0 +1,70 @@
1
+ .q-chatbot__file-preview img,
2
+ .q-chatbot__image-preview img {
3
+ width: 60px;
4
+ height: 60px;
5
+ object-fit: cover;
6
+ border-radius: 4px;
7
+ margin-right: 0.25rem;
8
+ border: 1px solid #eaebec;
9
+ overflow: hidden;
10
+ }
11
+
12
+ .q-chatbot__file {
13
+ &-preview {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ position: relative;
17
+ margin-top: 0.5rem;
18
+ gap: 0.25rem;
19
+ width: fit-content;
20
+
21
+ img:focus {
22
+ outline: solid rgb(var(--q-theme-info-rgb) / 50%);
23
+ }
24
+
25
+ &-container {
26
+ display: flex;
27
+ border-radius: 0.5rem;
28
+ padding: 0.25rem 0.5rem;
29
+ max-width: 320px;
30
+ align-items: center;
31
+ justify-content: center;
32
+ border: 1px solid var(--q-theme-primary-light);
33
+ }
34
+ }
35
+
36
+ &-icon-container {
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ border-radius: 8px;
41
+ width: 36px;
42
+ height: 36px;
43
+ flex-shrink: 0;
44
+ margin-right: 10px;
45
+ background: var(--q-theme-primary-light);
46
+
47
+ .q-icon {
48
+ width: 20px;
49
+ height: 20px;
50
+ }
51
+ }
52
+
53
+ &-info {
54
+ display: flex;
55
+ flex-direction: column;
56
+ overflow: hidden;
57
+ }
58
+
59
+ &-name {
60
+ font-size: 12px;
61
+ font-weight: 600;
62
+ white-space: nowrap;
63
+ overflow: hidden;
64
+ text-overflow: ellipsis;
65
+ }
66
+
67
+ &-extension {
68
+ font-size: 10px;
69
+ }
70
+ }
@@ -1,6 +1,7 @@
1
1
  @import '../../components/MarkdownRender/markdown-render';
2
2
  @import '../../components/FieldPreview/field-preview';
3
3
  @import '../../components/PulseDots/pulse-dots';
4
+ @import '../styles/preview-file';
4
5
 
5
6
  .q-chatbot {
6
7
  width: 100%;
@@ -17,6 +18,12 @@
17
18
  flex: 1;
18
19
  }
19
20
 
21
+ &__remove-file {
22
+ position: absolute;
23
+ top: -8px;
24
+ right: -8px;
25
+ }
26
+
20
27
  &__text {
21
28
  p {
22
29
  margin: 0;
@@ -44,35 +51,7 @@
44
51
  position: relative;
45
52
  }
46
53
 
47
- &__image-preview {
48
- display: inline-flex;
49
- align-items: center;
50
- position: relative;
51
- margin-top: 0.5rem;
52
- width: fit-content;
53
-
54
- img {
55
- width: 60px;
56
- height: 60px;
57
- object-fit: cover;
58
- border-radius: 4px;
59
- margin-right: 0.25rem;
60
- border: 1px solid #eaebec;
61
- overflow: hidden;
62
- }
63
- }
64
-
65
- &__image-preview img:hover + .q-chatbot__remove-image,
66
- &__image-preview img:focus + .q-chatbot__remove-image {
67
- opacity: 1;
68
- pointer-events: auto;
69
- }
70
-
71
- &__image-preview img:focus {
72
- outline: solid rgb(var(--q-theme-info-rgb) / 50%);
73
- }
74
-
75
- .q-button.q-chatbot__remove-image {
54
+ .q-button.q-chatbot__remove-file {
76
55
  position: absolute;
77
56
  top: -5px;
78
57
  right: -5px;
@@ -80,11 +59,8 @@
80
59
  color: white;
81
60
  border-radius: 50%;
82
61
  padding: 5px;
83
- font-size: 12px;
62
+ font-size: 10px;
84
63
  border: none;
85
- opacity: 0;
86
- pointer-events: none;
87
- transition: opacity 0.2s ease-in-out;
88
64
 
89
65
  &:hover,
90
66
  &:focus {
@@ -22,11 +22,10 @@
22
22
  :user-image="props.userImage"
23
23
  :chatbot-image="props.chatbotImage"
24
24
  :loading="isLoading && !message.message"
25
- :image-preview-url="message.imagePreviewUrl"
25
+ :file="message.file"
26
26
  :api-endpoint="props.apiEndpoint"
27
27
  :session-i-d="message.sessionID"
28
28
  :fields="message.fields"
29
- @regenerate="onFieldRegenerate"
30
29
  @apply-fields="applyFields" />
31
30
  </div>
32
31
  </div>
@@ -48,7 +47,7 @@
48
47
  import { ChatBotInput } from '@/components/ChatBotInput'
49
48
 
50
49
  // Utils
51
- import { onMounted, ref, watch, computed, onBeforeMount } from 'vue'
50
+ import { onMounted, nextTick, ref, watch, computed, onBeforeMount } from 'vue'
52
51
  import { v4 as uuidv4 } from 'uuid'
53
52
 
54
53
  // Types
@@ -59,7 +58,7 @@
59
58
  FieldData,
60
59
  AppliedFieldData
61
60
  } from './types'
62
- import type { ChatBotImage } from '../ChatBotInput'
61
+ import type { ChatBotFile } from '../ChatBotInput'
63
62
 
64
63
  // Assets
65
64
  import ChatBotIcon from '@/assets/chatbot_profile.svg'
@@ -87,7 +86,6 @@
87
86
 
88
87
  const emit = defineEmits<{
89
88
  (e: 'apply-fields', fields: AppliedFieldData[]): void
90
- (e: 'direct-agent-chat', agentId: string, prompt: string): void
91
89
  }>()
92
90
 
93
91
  const isChatDisabled = ref(true)
@@ -99,11 +97,9 @@
99
97
 
100
98
  // Composables
101
99
  const texts = useTexts()
102
- const { isLoading, clearChatData, getChatData, getJobResultData, sendPrompt } = useChatApi(
103
- props.apiEndpoint
104
- )
105
- const { messages, addChatMessage, clearMessages, getLastMessage, deleteMessageById } =
106
- useChatMessages()
100
+ const { isLoading, clearChatData, getChatData, getFieldSuggestionData, sendPrompt } =
101
+ useChatApi(props.apiEndpoint)
102
+ const { messages, addChatMessage, clearMessages, getLastMessage } = useChatMessages()
107
103
 
108
104
  const isDisabled = computed(() => {
109
105
  return isChatDisabled.value || isLoading.value
@@ -150,14 +146,10 @@
150
146
  sendInitialMessage()
151
147
 
152
148
  data.history.forEach(async (message: ChatBotMessageContent) => {
153
- const imgUrl = message.imageUrl
154
- ? props.controllerEndpoint + message.imageUrl
155
- : undefined
156
-
157
149
  addChatMessage(
158
150
  message.content,
159
151
  message.type === 'ai' ? 'bot' : 'user',
160
- imgUrl,
152
+ undefined, // At this point we don't have preview URLs for past messages
161
153
  message.sessionID
162
154
  )
163
155
  })
@@ -165,7 +157,7 @@
165
157
 
166
158
  function sendInitialMessage() {
167
159
  const message = texts.initialMessage
168
- addChatMessage(message, 'bot', null, undefined, true)
160
+ addChatMessage(message, 'bot', undefined, undefined, true)
169
161
  }
170
162
 
171
163
  function resetChat() {
@@ -175,6 +167,14 @@
175
167
  autoScrollEnabled.value = true
176
168
  }
177
169
 
170
+ function scrollToBottom() {
171
+ nextTick(() => {
172
+ if (messagesContainer.value) {
173
+ messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
174
+ }
175
+ })
176
+ }
177
+
178
178
  function handleScroll() {
179
179
  if (messagesContainer.value) {
180
180
  const threshold = 20 // px threshold from the bottom
@@ -183,7 +183,7 @@
183
183
  }
184
184
  }
185
185
 
186
- async function sendMessage(prompt: string, image?: ChatBotImage) {
186
+ async function sendMessage(prompt: string, file?: ChatBotFile) {
187
187
  if (messagesContainer.value) {
188
188
  messagesContainer.value.scrollTo({
189
189
  top: messagesContainer.value.scrollHeight,
@@ -191,8 +191,11 @@
191
191
  })
192
192
  }
193
193
 
194
- addChatMessage(prompt, 'user', image?.previewUrl)
195
- setChatPrompt(prompt, image?.file)
194
+ addChatMessage(prompt, 'user', file)
195
+ nextTick(() => {
196
+ if (autoScrollEnabled.value) scrollToBottom()
197
+ })
198
+ setChatPrompt(prompt, file?.fileData)
196
199
  }
197
200
 
198
201
  async function getAgentJob(jobId: string) {
@@ -205,47 +208,47 @@
205
208
 
206
209
  // Add an empty bot message to trigger bouncing dots animation
207
210
  addChatMessage('', 'bot')
211
+ nextTick(() => {
212
+ if (autoScrollEnabled.value) scrollToBottom()
213
+ })
208
214
 
209
215
  const msg = getLastMessage()
210
216
  if (!msg) return
211
217
 
212
- await getJobResultData(
218
+ await getFieldSuggestionData(
213
219
  jobId,
214
220
  (chunk: string) => {
215
221
  msg.message += chunk
216
222
  if (!msg.fields) msg.fields = []
217
223
 
218
- if (msg.fields.length > 0) {
219
- const lastField = msg.fields[msg.fields.length - 1]
220
- lastField.text = msg.message
221
- }
224
+ const lastField = msg.fields[msg.fields.length - 1]
225
+ lastField.text = msg.message
226
+
227
+ if (autoScrollEnabled.value) scrollToBottom()
222
228
  },
223
229
  (metadata: Record<string, unknown>) => {
224
230
  msg.message = ''
225
231
  const data = metadata as FieldData
226
232
  msg.fields?.push({
227
- id: data.id,
228
233
  type: data.type,
229
234
  name: data.name,
230
235
  text: data.text
231
236
  })
232
- },
233
- (error: Error) => {
234
- setDisabledState(true)
235
- addChatMessage(texts.botIsSick)
236
- console.error('Error getting job result: ' + error)
237
- deleteMessageById(msg.id)
238
237
  }
239
238
  )
240
239
  }
241
240
 
242
- async function setChatPrompt(prompt: string, image?: File) {
241
+ async function setChatPrompt(prompt: string, file?: File) {
243
242
  // Add an empty bot message marked as streaming to trigger bouncing dots animation
244
- const currentSessionID = uuidv4()
243
+ addChatMessage('', 'bot')
244
+ const msg = getLastMessage()
245
+ if (!msg) return
246
+
247
+ const currentSessionID = msg?.sessionID || uuidv4()
245
248
 
246
249
  const formData = new FormData()
247
- if (image) {
248
- formData.append('image', image)
250
+ if (file) {
251
+ formData.append('file', file)
249
252
  }
250
253
 
251
254
  formData.append('message', prompt)
@@ -253,26 +256,19 @@
253
256
  formData.append('user', props.username)
254
257
  formData.append('sessionID', currentSessionID)
255
258
 
256
- if (currentAgentId.value !== '') {
257
- emit('direct-agent-chat', currentAgentId.value, prompt)
258
- } else {
259
- addChatMessage('', 'bot')
260
- const msg = getLastMessage()
261
- if (!msg) return
262
-
263
- await sendPrompt(
264
- formData,
265
- (chunk) => {
266
- if (msg) msg.message += chunk
267
- },
268
- (error) => {
269
- setDisabledState(true)
270
- addChatMessage(texts.botIsSick)
271
- console.error('Error sending message: ' + error)
272
- deleteMessageById(msg.id)
273
- }
274
- )
275
- }
259
+ await sendPrompt(
260
+ formData,
261
+ (chunk) => {
262
+ if (msg) msg.message += chunk
263
+
264
+ if (autoScrollEnabled.value) scrollToBottom()
265
+ },
266
+ (error) => {
267
+ setDisabledState(true)
268
+ addChatMessage(texts.botIsSick)
269
+ console.error('Error sending message: ' + error)
270
+ }
271
+ )
276
272
  }
277
273
 
278
274
  async function clearChat() {
@@ -299,12 +295,11 @@
299
295
  return classes
300
296
  }
301
297
 
302
- async function changeChat(chat: { formId: string; key: string }) {
298
+ function changeChat(chat: { formId: string; key: string }) {
303
299
  currentAgentId.value = chat.key
304
300
  currentFormId.value = chat.formId
305
-
306
301
  resetChat()
307
- await initChat()
302
+ loadChatData()
308
303
  }
309
304
 
310
305
  function applyFields(fields: AppliedFieldData[]) {
@@ -313,11 +308,6 @@
313
308
  emit('apply-fields', fields)
314
309
  }
315
310
 
316
- function onFieldRegenerate(name: string) {
317
- const prompt = texts.regenerateResponsePrompt.replace('{0}', name)
318
- emit('direct-agent-chat', currentAgentId.value, prompt)
319
- }
320
-
321
311
  watch(
322
312
  () => props.availableAgents,
323
313
  (newValue, oldValue) => {
@@ -332,19 +322,28 @@
332
322
 
333
323
  watch(
334
324
  () => props.agentData,
335
- async (newData, oldData) => {
325
+ async (newValue, oldValue) => {
336
326
  if (isDisabled.value) return
337
327
 
338
- const newJobId = newData.jobId
339
- const oldJobId = oldData.jobId
328
+ if (props.agentData?.id !== oldValue?.id) {
329
+ currentAgentId.value = newValue?.id || ''
330
+ currentFormId.value = newValue?.formId || ''
331
+ resetChat()
332
+ await initChat()
333
+ }
340
334
 
341
- const jobChanged = newJobId !== oldJobId
342
- const agentChanged = newData.id !== currentAgentId.value
343
- if (agentChanged) await changeChat({ formId: newData.formId, key: newData.id })
335
+ if (newValue?.id !== '' && newValue && newValue.jobId !== oldValue.jobId)
336
+ await getAgentJob(newValue.jobId)
337
+ }
338
+ )
344
339
 
345
- if (newJobId && jobChanged) await getAgentJob(newJobId)
340
+ watch(
341
+ () => [props.agentData.id, props.agentData.formId],
342
+ ([newId, newFormId]) => {
343
+ currentAgentId.value = newId
344
+ currentFormId.value = newFormId
346
345
  },
347
- { deep: true }
346
+ { immediate: true }
348
347
  )
349
348
 
350
349
  defineOptions({ name: 'ChatBot' })
@@ -1,3 +1,5 @@
1
+ import { ChatBotFile } from '../ChatBotInput'
2
+
1
3
  export type ChatBotProps = {
2
4
  apiEndpoint?: string
3
5
  controllerEndpoint?: string
@@ -23,7 +25,6 @@ export type AgentData = {
23
25
  }
24
26
 
25
27
  export type FieldData = {
26
- id: string
27
28
  name: string
28
29
  type: string
29
30
  text: string
@@ -31,7 +32,7 @@ export type FieldData = {
31
32
  }
32
33
 
33
34
  export type AppliedFieldData = {
34
- id: string
35
+ name: string
35
36
  text: unknown
36
37
  }
37
38
 
@@ -41,7 +42,7 @@ export type ChatMessage = {
41
42
  date: Date
42
43
  sender: ChatBotMessageSender
43
44
  sessionID: string
44
- imagePreviewUrl?: string
45
+ file?: ChatBotFile
45
46
  isWelcomeMessage?: boolean
46
47
  fields?: FieldData[]
47
48
  }