|
28 | 28 | uploadConversationFiles, |
29 | 29 | getAddressOptions, |
30 | 30 | pinConversationToDashboard, |
| 31 | + stopStreaming as stopStreamingApi, |
31 | 32 | } from '$lib/services/conversation-service.js'; |
32 | 33 | import { |
33 | 34 | PUBLIC_LIVECHAT_ENTRY_ICON, |
|
200 | 201 | let isListening = $state(false); |
201 | 202 | let isLite = $state(false); |
202 | 203 | let isFrame = $state(false); |
203 | | - let loadTextEditor = $state(false); |
204 | 204 | let autoScrollLog = $state(false); |
205 | 205 | let loadChatUtils = $state(false); |
206 | 206 | let disableSpeech = $state(false); |
|
212 | 212 | let copyClicked = $state(false); |
213 | 213 | let isStreaming = $state(false); |
214 | 214 | let isHandlingQueue = $state(false); |
| 215 | + let isStopStreamClicked = $state(false); |
215 | 216 |
|
216 | | - let loadEditor = $derived(!isSendingMsg && !isThinking && loadTextEditor && messageQueue.length === 0); |
217 | | - let disableAction = $derived(!ADMIN_ROLES.includes(currentUser?.role || '') && currentUser?.id !== conversationUser?.id || !AgentExtensions.chatable(agent)); |
| 217 | + // let loadEditor = $derived(!isSendingMsg && !isThinking && loadTextEditor && messageQueue.length === 0); |
| 218 | + let loadEditor = true; |
| 219 | + let disableAction = $derived(!ADMIN_ROLES.includes(currentUser?.role || '') |
| 220 | + && currentUser?.id !== conversationUser?.id |
| 221 | + || !AgentExtensions.chatable(agent)); |
218 | 222 |
|
219 | 223 | $effect(() => { |
220 | | - loadTextEditor = true; |
221 | 224 | if (loadEditor) { |
222 | 225 | focusChatTextArea(); |
223 | 226 | } |
|
599 | 602 | && lastMsg?.is_dummy |
600 | 603 | ) { |
601 | 604 | setTimeout(() => { |
602 | | - const lastDialog = dialogs[dialogs.length - 1]; |
603 | 605 | const thinkingText = message.meta_data?.thinking_text || ''; |
604 | 606 | if (thinkingText) { |
605 | | - if (!lastDialog.meta_data) { |
606 | | - lastDialog.meta_data = { thinking_text: '' }; |
| 607 | + if (!dialogs[dialogs.length - 1].meta_data) { |
| 608 | + dialogs[dialogs.length - 1].meta_data = { thinking_text: '' }; |
607 | 609 | } |
608 | | - lastDialog.meta_data.thinking_text += thinkingText; |
| 610 | + dialogs[dialogs.length - 1].meta_data.thinking_text += thinkingText; |
609 | 611 | } |
610 | | - lastDialog.text += message.text; |
| 612 | + dialogs[dialogs.length - 1].text += message.text; |
611 | 613 | refreshDialogs(); |
612 | 614 | }, 0); |
613 | 615 | } |
|
636 | 638 | } |
637 | 639 |
|
638 | 640 | try { |
639 | | - const lastDialog = dialogs[dialogs.length - 1]; |
640 | 641 | const thinkingText = item.meta_data?.thinking_text || ''; |
641 | 642 | if (thinkingText) { |
642 | | - if (!lastDialog.meta_data) { |
643 | | - lastDialog.meta_data = { thinking_text: '' }; |
| 643 | + if (!dialogs[dialogs.length - 1].meta_data) { |
| 644 | + dialogs[dialogs.length - 1].meta_data = { thinking_text: '' }; |
644 | 645 | } |
645 | 646 | for (const tt of thinkingText) { |
646 | | - lastDialog.meta_data.thinking_text += tt; |
| 647 | + dialogs[dialogs.length - 1].meta_data.thinking_text += tt; |
647 | 648 | refreshDialogs(); |
648 | 649 | await delay(10); |
649 | 650 | } |
650 | 651 | } |
651 | 652 |
|
652 | 653 | for (const char of item.text) { |
653 | | - lastDialog.text += char; |
| 654 | + dialogs[dialogs.length - 1].text += char; |
654 | 655 | refreshDialogs(); |
655 | 656 | await delay(10); |
656 | 657 | } |
|
667 | 668 | refresh(); |
668 | 669 | } |
669 | 670 |
|
| 671 | + function stopStreaming() { |
| 672 | + isStopStreamClicked = true; |
| 673 | + // @ts-ignore |
| 674 | + stopStreamingApi(page.params.conversationId).then((res) => { |
| 675 | + if (res?.success) { |
| 676 | + isStreaming = false; |
| 677 | + isThinking = false; |
| 678 | + isSendingMsg = false; |
| 679 | + messageQueue = []; |
| 680 | + isHandlingQueue = false; |
| 681 | + refresh(); |
| 682 | + } |
| 683 | + isStopStreamClicked = false; |
| 684 | + }); |
| 685 | + } |
| 686 | +
|
670 | 687 | /** @param {import('$conversationTypes').ChatResponseModel} message */ |
671 | 688 | function onIndicationReceived(message) { |
672 | 689 | isThinking = true; |
|
782 | 799 | ...data, |
783 | 800 | postback: postback, |
784 | 801 | states: [ |
785 | | - ...data?.states || [], |
786 | | - { key: "use_stream_message", value: PUBLIC_LIVECHAT_STREAM_ENABLED } |
| 802 | + ...data?.states || [] |
787 | 803 | ] |
788 | 804 | }; |
789 | 805 |
|
|
826 | 842 | } |
827 | 843 |
|
828 | 844 | // @ts-ignore |
829 | | - await sendMessageToHub(agentId, convId, msgText, messageData); |
| 845 | + await sendMessageToHub(agentId, convId, msgText, messageData, PUBLIC_LIVECHAT_STREAM_ENABLED === "true"); |
830 | 846 | deleteMessageDraft(); |
831 | 847 | isSendingMsg = false; |
832 | 848 | } |
|
1998 | 2014 | {#if message.sender.role == UserRole.Client} |
1999 | 2015 | <img src="images/users/user-dummy.jpg" class="rounded-circle avatar-sm" style="margin-bottom: -15px;" alt="avatar"> |
2000 | 2016 | {:else} |
2001 | | - {@const isShowIcon = (message?.rich_content?.message?.text || message?.text) || message?.uuid !== lastBotMsg?.uuid} |
| 2017 | + {@const isShowIcon = (message?.rich_content?.message?.text || message?.text || message?.meta_data?.thinking_text) || message?.uuid !== lastBotMsg?.uuid} |
2002 | 2018 | <img |
2003 | 2019 | class="rounded-circle avatar-sm" |
2004 | 2020 | style={`display: ${isShowIcon ? 'block' : 'none'}; margin-bottom: -15px;`} |
|
2008 | 2024 | {/if} |
2009 | 2025 | </div> |
2010 | 2026 | <div class="msg-container"> |
2011 | | - <RcMessage containerClasses={'bot-msg'} markdownClasses={'markdown-dark text-dark'} message={message} /> |
| 2027 | + <RcMessage containerClasses={'bot-msg'} markdownClasses={'markdown-dark text-dark'} message={message} isStreaming={isStreaming || isThinking} /> |
2012 | 2028 | {#if message?.message_id === lastBotMsg?.message_id && message?.uuid === lastBotMsg?.uuid} |
2013 | 2029 | {@const isStreamEnd = (message?.rich_content?.message?.text || message?.text) && !isStreaming && !isHandlingQueue && !isThinking} |
2014 | 2030 | <div style={`display: ${isStreamEnd ? 'flex' : 'none'}; gap: 10px; flex-wrap: wrap; margin-top: 5px;`}> |
|
2175 | 2191 | <ChatFileUploader |
2176 | 2192 | accept={'.png,.jpg,.jpeg'} |
2177 | 2193 | containerClasses={'line-align-center text-primary chat-util-item'} |
2178 | | - disabled={disableAction} |
| 2194 | + disabled={isSendingMsg || isThinking || disableAction} |
2179 | 2195 | onfiledroped={() => refresh()} |
2180 | 2196 | > |
2181 | 2197 | <span> |
|
2189 | 2205 | <ChatFileUploader |
2190 | 2206 | accept={'.pdf,.xlsx,.xls,.csv'} |
2191 | 2207 | containerClasses={'line-align-center text-primary chat-util-item'} |
2192 | | - disabled={disableAction} |
| 2208 | + disabled={isSendingMsg || isThinking || disableAction} |
2193 | 2209 | onfiledroped={() => refresh()} |
2194 | 2210 | > |
2195 | 2211 | <span> |
|
2203 | 2219 | <ChatFileUploader |
2204 | 2220 | accept={'.wav,.mp3'} |
2205 | 2221 | containerClasses={'line-align-center text-primary chat-util-item'} |
2206 | | - disabled={disableAction} |
| 2222 | + disabled={isSendingMsg || isThinking || disableAction} |
2207 | 2223 | onfiledroped={() => refresh()} |
2208 | 2224 | > |
2209 | 2225 | <span> |
|
2221 | 2237 | onclick={() => toggleBigMessageModal()} |
2222 | 2238 | /> |
2223 | 2239 | {#if PUBLIC_LIVECHAT_FILES_ENABLED === 'true'} |
2224 | | - <ChatUtil disabled={disableAction} onclick={() => loadChatUtils = true} /> |
| 2240 | + <ChatUtil |
| 2241 | + disabled={isSendingMsg || isThinking || disableAction} |
| 2242 | + onclick={() => loadChatUtils = true} |
| 2243 | + /> |
2225 | 2244 | {/if} |
2226 | 2245 | </div> |
2227 | 2246 | </div> |
2228 | 2247 | </div> |
2229 | 2248 | <div class="col-auto"> |
2230 | | - <button |
2231 | | - type="submit" |
2232 | | - class={`btn btn-rounded chat-send waves-effect waves-light ${mode === TRAINING_MODE ? 'btn-danger' : 'btn-primary'}`} |
2233 | | - disabled={!_.trim(text) || isSendingMsg || isThinking || disableAction} |
2234 | | - onclick={() => sentTextMessage()} |
2235 | | - > |
2236 | | - <span class="d-none d-md-inline-block me-2">Send</span> |
2237 | | - <i class="mdi mdi-send"></i> |
2238 | | - </button> |
| 2249 | + {#if !isStopStreamClicked && isStreaming && PUBLIC_LIVECHAT_STREAM_ENABLED === 'true'} |
| 2250 | + <button |
| 2251 | + type="button" |
| 2252 | + class="btn btn-rounded chat-send waves-effect waves-light btn-danger" |
| 2253 | + aria-label="Stop streaming" |
| 2254 | + onclick={() => stopStreaming()} |
| 2255 | + > |
| 2256 | + <i class="mdi mdi-stop"></i> |
| 2257 | + </button> |
| 2258 | + {:else} |
| 2259 | + <button |
| 2260 | + type="submit" |
| 2261 | + class={`btn btn-rounded chat-send waves-effect waves-light ${mode === TRAINING_MODE ? 'btn-danger' : 'btn-primary'}`} |
| 2262 | + disabled={!_.trim(text) || isSendingMsg || isThinking || disableAction} |
| 2263 | + onclick={() => sentTextMessage()} |
| 2264 | + > |
| 2265 | + <span class="d-none d-md-inline-block me-2">Send</span> |
| 2266 | + <i class="mdi mdi-send"></i> |
| 2267 | + </button> |
| 2268 | + {/if} |
2239 | 2269 | </div> |
2240 | 2270 | </div> |
2241 | 2271 | </div> |
|
0 commit comments