@quidgest/chatbot 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.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;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.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-btn.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-btn.q-chatbot__remove-image:hover,.q-chatbot .q-btn.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:end;max-width:100%}.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{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.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}#comment-dialog .q-dialog__header,.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;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}}
1
+ .q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.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;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.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:end;max-width:100%}.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{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.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}#comment-dialog .q-dialog__header,.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;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}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quidgest/chatbot",
3
3
  "private": false,
4
- "version": "0.2.0",
4
+ "version": "0.3.1",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "main": "dist/index.cjs",
@@ -51,7 +51,7 @@
51
51
  "vue-tsc": "^1.8.27"
52
52
  },
53
53
  "peerDependencies": {
54
- "@quidgest/ui": "^0.14.19",
55
- "vue": "3.5.13"
54
+ "@quidgest/ui": "^0.15.9",
55
+ "vue": "^3.5.13"
56
56
  }
57
57
  }
@@ -74,7 +74,7 @@
74
74
  }
75
75
  }
76
76
 
77
- .q-btn.q-chatbot__remove-image {
77
+ .q-button.q-chatbot__remove-image {
78
78
  position: absolute;
79
79
  top: -5px;
80
80
  right: -5px;
@@ -56,7 +56,6 @@
56
56
  :title="props.texts.goodResponse"
57
57
  borderless
58
58
  :disabled="loading"
59
- b-style="secondary"
60
59
  @click="openFeedbackDialog(1)">
61
60
  <q-icon icon="thumb-up" />
62
61
  </q-button>
@@ -64,7 +63,6 @@
64
63
  :title="props.texts.badResponse"
65
64
  borderless
66
65
  :disabled="loading"
67
- b-style="secondary"
68
66
  @click="openFeedbackDialog(0)">
69
67
  <q-icon icon="thumb-down" />
70
68
  </q-button>
@@ -72,7 +70,6 @@
72
70
  :title="props.texts.copyResponse"
73
71
  borderless
74
72
  :disabled="loading"
75
- b-style="secondary"
76
73
  @click="copyResponse">
77
74
  <q-icon icon="copy-content" />
78
75
  </q-button>
@@ -187,7 +184,7 @@
187
184
  action: submitFeedback,
188
185
  props: {
189
186
  label: props.texts.submitButton,
190
- 'b-style': 'primary',
187
+ 'variant': 'bold',
191
188
  },
192
189
  icon: {
193
190
  icon: 'submit'
@@ -196,8 +193,7 @@
196
193
  {
197
194
  id: 'cancel-btn',
198
195
  props: {
199
- label: props.texts.cancelButton,
200
- 'b-style': 'secondary',
196
+ label: props.texts.cancelButton
201
197
  },
202
198
  icon: {
203
199
  icon: 'cancel'
@@ -5,7 +5,6 @@
5
5
  <div class="q-chatbot__tools">
6
6
  <q-button
7
7
  :title="props.texts.clearChat"
8
- b-style="secondary"
9
8
  :disabled="isChatDisabled"
10
9
  borderless
11
10
  @click="clearChat">
@@ -55,7 +54,6 @@
55
54
  <q-button
56
55
  class="q-chatbot__remove-image"
57
56
  tabindex="0"
58
- b-style="secondary"
59
57
  flat
60
58
  round
61
59
  @click="removeImage">
@@ -77,7 +75,6 @@
77
75
  <!-- Upload button moved to the same container as send, but positioned to the left -->
78
76
  <q-button
79
77
  :title="props.texts.imageUpload"
80
- b-style="secondary"
81
78
  class="q-chatbot__upload"
82
79
  :disabled="isChatDisabled || isLoading || hasSelectedImage"
83
80
  @click="triggerImageUpload">
@@ -95,7 +92,7 @@
95
92
 
96
93
  <q-button
97
94
  :title="props.texts.sendMessage"
98
- b-style="primary"
95
+ variant="bold"
99
96
  class="q-chatbot__send"
100
97
  :disabled="isSendButtonDisabled"
101
98
  :readonly="isSendButtonDisabled"
@@ -194,49 +191,36 @@
194
191
  }
195
192
 
196
193
  async function initChat() {
197
- const response = await axios.post(props.apiEndpoint + '/auth/login', {
198
- username: props.username,
199
- password: 'test'
200
- })
201
-
202
- if(!response.data) {
203
- addChatMessage(props.texts.loginError)
204
- setDisabledState(true)
205
- isLoading.value = false
206
- return
207
- }
194
+ try {
195
+ await axios.post(props.apiEndpoint + '/auth/login', {
196
+ username: props.username,
197
+ password: 'test'
198
+ })
208
199
 
209
- if (response.status !== 200 || !response.data.success) {
200
+ loadChatData()
201
+ } catch (error) {
210
202
  setDisabledState(true)
211
203
  addChatMessage(props.texts.loginError)
212
- console.log(`Unsuccessful login, endpoint gave status ${response.status}`)
213
- return
204
+ console.log('Error logging in: ' + error)
214
205
  }
215
-
216
- loadChatData()
217
206
  };
218
207
 
219
208
  async function loadChatData() {
220
- const response = await axios.post(props.apiEndpoint + '/prompt/load', {
221
- username: props.username,
222
- project: props.projectPath
223
- })
209
+ try {
210
+ const response = await axios.post(props.apiEndpoint + '/prompt/load', {
211
+ username: props.username,
212
+ project: props.projectPath
213
+ });
224
214
 
225
- if(!response.data) {
226
- setDisabledState(true)
227
- addChatMessage(props.texts.loginError)
228
- setDisabledState(true)
229
- isLoading.value = false
230
- return
231
- }
232
-
233
- if (response.status !== 200 || !response.data.success) {
234
- setDisabledState(true)
235
- addChatMessage(props.texts.loginError)
236
- console.log(`Unsuccessful load, endpoint gave status ${response.status}`)
237
- return
215
+ if(!response) return console.error('No response from server');
216
+
217
+ if (response.status !== 200 || !response.data.success) {
218
+ setDisabledState(true)
219
+ addChatMessage(props.texts.botIsSick)
220
+ console.log(`Unsuccessful load, endpoint gave status ${response.status}`)
221
+ return
238
222
  }
239
-
223
+
240
224
  sendInitialMessage()
241
225
  response.data.history.forEach((message: ChatBotMessageContent) => {
242
226
  const imgUrl = message.imageUrl ? props.controllerEndpoint + message.imageUrl : undefined
@@ -244,9 +228,15 @@
244
228
  message.content,
245
229
  message.type === 'ai' ? 'bot' : 'user',
246
230
  imgUrl,
247
- message.sessionID
248
- )
249
- })
231
+ message.sessionID)
232
+ })
233
+
234
+ } catch(error) {
235
+ setDisabledState(true)
236
+ addChatMessage(props.texts.botIsSick)
237
+ console.log('Error loading: ' + error)
238
+ }
239
+
250
240
  }
251
241
 
252
242
  // Modified addChatMessage to add isStreaming flag for empty bot messages
@@ -379,47 +369,50 @@
379
369
 
380
370
  isLoading.value = true
381
371
 
382
- const response = await axios.post(props.apiEndpoint + '/prompt/submit', formData, {
383
- headers: {
384
- 'Content-Type': 'text/event-stream',
385
- 'Accept': 'text/event-stream',
386
- },
387
- responseType: 'stream',
388
- adapter: 'fetch',
389
- })
372
+ try {
373
+ const response = await axios.post(props.apiEndpoint + '/prompt/submit', formData, {
374
+ headers: {
375
+ 'Content-Type': 'text/event-stream',
376
+ 'Accept': 'text/event-stream',
377
+ },
378
+ responseType: 'stream',
379
+ adapter: 'fetch',
380
+ })
390
381
 
391
- if(!response.data) {
392
- addChatMessage(props.texts.botIsSick)
393
- setDisabledState(true)
394
- isLoading.value = false
395
- return
396
- }
382
+ if(!response) return console.error('No response from server')
397
383
 
398
- const reader = response.data.getReader()
399
- const decoder = new TextDecoder("utf-8")
384
+ const reader = response.data.getReader()
385
+ const decoder = new TextDecoder("utf-8")
400
386
 
401
- while(true) {
402
- const { done, value } = await reader.read()
403
- if(done) break
404
-
405
- const chunk = decoder.decode(value, { stream: true })
406
- const eventList = chunk.match(/data:\s*({.*?})/g)
407
- if(!eventList) continue
387
+ while(true) {
388
+ const { done, value } = await reader.read()
389
+ if(done) break
390
+
391
+ const chunk = decoder.decode(value, { stream: true })
392
+ const eventList = chunk.match(/data:\s*({.*?})/g)
393
+ if(!eventList) continue
408
394
 
409
- for(const event of eventList) {
410
- try {
411
- const rawData = event.split('data:')[1].trim()
412
- const data = JSON.parse(rawData)
413
- if(msg) {
414
- msg.message += data.value
395
+ for(const event of eventList) {
396
+ try {
397
+ const rawData = event.split('data:')[1].trim()
398
+ const data = JSON.parse(rawData)
399
+ if(msg) {
400
+ msg.message += data.value
401
+ }
402
+ } catch (error) {
403
+ console.error('Error parsing match:', error)
415
404
  }
416
- } catch (error) {
417
- console.error('Error parsing match:', error)
418
405
  }
406
+ if(autoScrollEnabled.value) scrollToBottom()
419
407
  }
420
- if(autoScrollEnabled.value) scrollToBottom()
408
+
409
+ isLoading.value = false
410
+ } catch (error) {
411
+ setDisabledState(true)
412
+ addChatMessage(props.texts.botIsSick)
413
+ console.log('Error setting chat prompt: ' + error)
414
+ return
421
415
  }
422
- isLoading.value = false
423
416
  }
424
417
 
425
418
  function clearChat() {
@@ -427,21 +420,21 @@
427
420
  username: props.username,
428
421
  project: props.projectPath
429
422
  })
430
- .then((response: AxiosResponse) => {
431
- if (response.status !== 200 || !response.data.success) {
432
- setDisabledState(true)
433
- addChatMessage(props.texts.loginError)
434
- console.log(`Unsuccessful clear, endpoint gave status ${response.status}`)
435
- return
436
- }
437
- resetChat()
438
- sendInitialMessage()
439
- })
440
- .catch((error: Error) => {
423
+ .then((response: AxiosResponse) => {
424
+ if (response.status !== 200 || !response.data.success) {
441
425
  setDisabledState(true)
442
426
  addChatMessage(props.texts.loginError)
443
- console.log('Error clearing chat: ' + error)
444
- })
427
+ console.log(`Unsuccessful clear, endpoint gave status ${response.status}`)
428
+ return
429
+ }
430
+ resetChat()
431
+ sendInitialMessage()
432
+ })
433
+ .catch((error: Error) => {
434
+ setDisabledState(true)
435
+ addChatMessage(props.texts.loginError)
436
+ console.log('Error clearing chat: ' + error)
437
+ })
445
438
  }
446
439
 
447
440
  function getMessageClasses(sender: ChatBotMessageSender) {